github.com/huaweicloud/golangsdk@v0.0.0-20210831081626-d823fe11ceba/openstack/identity/v3/tokens/requests.go (about) 1 package tokens 2 3 import "github.com/huaweicloud/golangsdk" 4 5 // Scope allows a created token to be limited to a specific domain or project. 6 type Scope struct { 7 ProjectID string 8 ProjectName string 9 DomainID string 10 DomainName string 11 } 12 13 // AuthOptionsBuilder provides the ability for extensions to add additional 14 // parameters to AuthOptions. Extensions must satisfy all required methods. 15 type AuthOptionsBuilder interface { 16 // ToTokenV3CreateMap assembles the Create request body, returning an error 17 // if parameters are missing or inconsistent. 18 ToTokenV3CreateMap(map[string]interface{}) (map[string]interface{}, error) 19 ToTokenV3ScopeMap() (map[string]interface{}, error) 20 CanReauth() bool 21 AuthTokenID() string 22 AuthHeaderDomainID() string 23 } 24 25 // AuthOptions represents options for authenticating a user. 26 type AuthOptions struct { 27 // IdentityEndpoint specifies the HTTP endpoint that is required to work with 28 // the Identity API of the appropriate version. While it's ultimately needed 29 // by all of the identity services, it will often be populated by a 30 // provider-level function. 31 IdentityEndpoint string `json:"-"` 32 33 // Username is required if using Identity V2 API. Consult with your provider's 34 // control panel to discover your account's username. In Identity V3, either 35 // UserID or a combination of Username and DomainID or DomainName are needed. 36 Username string `json:"username,omitempty"` 37 UserID string `json:"id,omitempty"` 38 39 Password string `json:"password,omitempty"` 40 41 // At most one of DomainID and DomainName must be provided if using Username 42 // with Identity V3. Otherwise, either are optional. 43 DomainID string `json:"-"` 44 DomainName string `json:"name,omitempty"` 45 46 // AllowReauth should be set to true if you grant permission for Gophercloud 47 // to cache your credentials in memory, and to allow Gophercloud to attempt 48 // to re-authenticate automatically if/when your token expires. If you set 49 // it to false, it will not cache these settings, but re-authentication will 50 // not be possible. This setting defaults to false. 51 AllowReauth bool `json:"-"` 52 53 // TokenID allows users to authenticate (possibly as another user) with an 54 // authentication token ID. 55 TokenID string `json:"-"` 56 57 Scope Scope `json:"-"` 58 } 59 60 // ToTokenV3CreateMap builds a request body from AuthOptions. 61 func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) { 62 golangsdkAuthOpts := golangsdk.AuthOptions{ 63 Username: opts.Username, 64 UserID: opts.UserID, 65 Password: opts.Password, 66 DomainID: opts.DomainID, 67 DomainName: opts.DomainName, 68 AllowReauth: opts.AllowReauth, 69 TokenID: opts.TokenID, 70 } 71 72 return golangsdkAuthOpts.ToTokenV3CreateMap(scope) 73 } 74 75 // ToTokenV3CreateMap builds a scope request body from AuthOptions. 76 func (opts *AuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) { 77 if opts.Scope.ProjectName != "" { 78 // ProjectName provided: either DomainID or DomainName must also be supplied. 79 // ProjectID may not be supplied. 80 if opts.Scope.DomainID == "" && opts.Scope.DomainName == "" { 81 return nil, golangsdk.ErrScopeDomainIDOrDomainName{} 82 } 83 if opts.Scope.ProjectID != "" { 84 return nil, golangsdk.ErrScopeProjectIDOrProjectName{} 85 } 86 87 if opts.Scope.DomainID != "" { 88 // ProjectName + DomainID 89 return map[string]interface{}{ 90 "project": map[string]interface{}{ 91 "name": &opts.Scope.ProjectName, 92 "domain": map[string]interface{}{"id": &opts.Scope.DomainID}, 93 }, 94 }, nil 95 } 96 97 if opts.Scope.DomainName != "" { 98 // ProjectName + DomainName 99 return map[string]interface{}{ 100 "project": map[string]interface{}{ 101 "name": &opts.Scope.ProjectName, 102 "domain": map[string]interface{}{"name": &opts.Scope.DomainName}, 103 }, 104 }, nil 105 } 106 } else if opts.Scope.ProjectID != "" { 107 // ProjectID provided. ProjectName, DomainID, and DomainName may not be provided. 108 if opts.Scope.DomainID != "" { 109 return nil, golangsdk.ErrScopeProjectIDAlone{} 110 } 111 if opts.Scope.DomainName != "" { 112 return nil, golangsdk.ErrScopeProjectIDAlone{} 113 } 114 115 // ProjectID 116 return map[string]interface{}{ 117 "project": map[string]interface{}{ 118 "id": &opts.Scope.ProjectID, 119 }, 120 }, nil 121 } else if opts.Scope.DomainID != "" { 122 // DomainID provided. ProjectID, ProjectName, and DomainName may not be provided. 123 if opts.Scope.DomainName != "" { 124 return nil, golangsdk.ErrScopeDomainIDOrDomainName{} 125 } 126 127 // DomainID 128 return map[string]interface{}{ 129 "domain": map[string]interface{}{ 130 "id": &opts.Scope.DomainID, 131 }, 132 }, nil 133 } else if opts.Scope.DomainName != "" { 134 // DomainName 135 return map[string]interface{}{ 136 "domain": map[string]interface{}{ 137 "name": &opts.Scope.DomainName, 138 }, 139 }, nil 140 } 141 142 return nil, nil 143 } 144 145 func (opts *AuthOptions) CanReauth() bool { 146 return opts.AllowReauth 147 } 148 149 func (opts *AuthOptions) AuthTokenID() string { 150 return "" 151 } 152 153 func (opts *AuthOptions) AuthHeaderDomainID() string { 154 return "" 155 } 156 157 func subjectTokenHeaders(c *golangsdk.ServiceClient, subjectToken string) map[string]string { 158 return map[string]string{ 159 "X-Subject-Token": subjectToken, 160 } 161 } 162 163 // Create authenticates and either generates a new token, or changes the Scope 164 // of an existing token. 165 func Create(c *golangsdk.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) { 166 scope, err := opts.ToTokenV3ScopeMap() 167 if err != nil { 168 r.Err = err 169 return 170 } 171 172 b, err := opts.ToTokenV3CreateMap(scope) 173 if err != nil { 174 r.Err = err 175 return 176 } 177 178 resp, err := c.Post(tokenURL(c), b, &r.Body, &golangsdk.RequestOpts{ 179 MoreHeaders: map[string]string{ 180 "X-Auth-Token": opts.AuthTokenID(), 181 "X-Domain-Id": opts.AuthHeaderDomainID(), 182 }, 183 }) 184 r.Err = err 185 if resp != nil { 186 r.Header = resp.Header 187 } 188 return 189 } 190 191 // Get validates and retrieves information about another token. 192 func Get(c *golangsdk.ServiceClient, token string) (r GetResult) { 193 resp, err := c.Get(tokenURL(c), &r.Body, &golangsdk.RequestOpts{ 194 MoreHeaders: subjectTokenHeaders(c, token), 195 OkCodes: []int{200, 203}, 196 }) 197 if resp != nil { 198 r.Err = err 199 r.Header = resp.Header 200 } 201 return 202 } 203 204 // Validate determines if a specified token is valid or not. 205 func Validate(c *golangsdk.ServiceClient, token string) (bool, error) { 206 resp, err := c.Request("HEAD", tokenURL(c), &golangsdk.RequestOpts{ 207 MoreHeaders: subjectTokenHeaders(c, token), 208 OkCodes: []int{200, 204, 404}, 209 }) 210 if err != nil { 211 return false, err 212 } 213 214 return resp.StatusCode == 200 || resp.StatusCode == 204, nil 215 } 216 217 // Revoke immediately makes specified token invalid. 218 func Revoke(c *golangsdk.ServiceClient, token string) (r RevokeResult) { 219 _, r.Err = c.Delete(tokenURL(c), &golangsdk.RequestOpts{ 220 MoreHeaders: subjectTokenHeaders(c, token), 221 }) 222 return 223 }