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  }