github.com/gophercloud/gophercloud@v1.11.0/openstack/identity/v3/tokens/requests.go (about)

     1  package tokens
     2  
     3  import "github.com/gophercloud/gophercloud"
     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  	System      bool
    12  }
    13  
    14  // AuthOptionsBuilder provides the ability for extensions to add additional
    15  // parameters to AuthOptions. Extensions must satisfy all required methods.
    16  type AuthOptionsBuilder interface {
    17  	// ToTokenV3CreateMap assembles the Create request body, returning an error
    18  	// if parameters are missing or inconsistent.
    19  	ToTokenV3CreateMap(map[string]interface{}) (map[string]interface{}, error)
    20  	ToTokenV3HeadersMap(map[string]interface{}) (map[string]string, error)
    21  	ToTokenV3ScopeMap() (map[string]interface{}, error)
    22  	CanReauth() bool
    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  	// Passcode is used in TOTP authentication method
    42  	Passcode string `json:"passcode,omitempty"`
    43  
    44  	// At most one of DomainID and DomainName must be provided if using Username
    45  	// with Identity V3. Otherwise, either are optional.
    46  	DomainID   string `json:"-"`
    47  	DomainName string `json:"name,omitempty"`
    48  
    49  	// AllowReauth should be set to true if you grant permission for Gophercloud
    50  	// to cache your credentials in memory, and to allow Gophercloud to attempt
    51  	// to re-authenticate automatically if/when your token expires.  If you set
    52  	// it to false, it will not cache these settings, but re-authentication will
    53  	// not be possible.  This setting defaults to false.
    54  	AllowReauth bool `json:"-"`
    55  
    56  	// TokenID allows users to authenticate (possibly as another user) with an
    57  	// authentication token ID.
    58  	TokenID string `json:"-"`
    59  
    60  	// Authentication through Application Credentials requires supplying name, project and secret
    61  	// For project we can use TenantID
    62  	ApplicationCredentialID     string `json:"-"`
    63  	ApplicationCredentialName   string `json:"-"`
    64  	ApplicationCredentialSecret string `json:"-"`
    65  
    66  	Scope Scope `json:"-"`
    67  }
    68  
    69  // ToTokenV3CreateMap builds a request body from AuthOptions.
    70  func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) {
    71  	gophercloudAuthOpts := gophercloud.AuthOptions{
    72  		Username:                    opts.Username,
    73  		UserID:                      opts.UserID,
    74  		Password:                    opts.Password,
    75  		Passcode:                    opts.Passcode,
    76  		DomainID:                    opts.DomainID,
    77  		DomainName:                  opts.DomainName,
    78  		AllowReauth:                 opts.AllowReauth,
    79  		TokenID:                     opts.TokenID,
    80  		ApplicationCredentialID:     opts.ApplicationCredentialID,
    81  		ApplicationCredentialName:   opts.ApplicationCredentialName,
    82  		ApplicationCredentialSecret: opts.ApplicationCredentialSecret,
    83  	}
    84  
    85  	return gophercloudAuthOpts.ToTokenV3CreateMap(scope)
    86  }
    87  
    88  // ToTokenV3ScopeMap builds a scope request body from AuthOptions.
    89  func (opts *AuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) {
    90  	scope := gophercloud.AuthScope(opts.Scope)
    91  
    92  	gophercloudAuthOpts := gophercloud.AuthOptions{
    93  		Scope:      &scope,
    94  		DomainID:   opts.DomainID,
    95  		DomainName: opts.DomainName,
    96  	}
    97  
    98  	return gophercloudAuthOpts.ToTokenV3ScopeMap()
    99  }
   100  
   101  func (opts *AuthOptions) CanReauth() bool {
   102  	if opts.Passcode != "" {
   103  		// cannot reauth using TOTP passcode
   104  		return false
   105  	}
   106  
   107  	return opts.AllowReauth
   108  }
   109  
   110  // ToTokenV3HeadersMap allows AuthOptions to satisfy the AuthOptionsBuilder
   111  // interface in the v3 tokens package.
   112  func (opts *AuthOptions) ToTokenV3HeadersMap(map[string]interface{}) (map[string]string, error) {
   113  	return nil, nil
   114  }
   115  
   116  func subjectTokenHeaders(subjectToken string) map[string]string {
   117  	return map[string]string{
   118  		"X-Subject-Token": subjectToken,
   119  	}
   120  }
   121  
   122  // Create authenticates and either generates a new token, or changes the Scope
   123  // of an existing token.
   124  func Create(c *gophercloud.ServiceClient, opts AuthOptionsBuilder) (r CreateResult) {
   125  	scope, err := opts.ToTokenV3ScopeMap()
   126  	if err != nil {
   127  		r.Err = err
   128  		return
   129  	}
   130  
   131  	b, err := opts.ToTokenV3CreateMap(scope)
   132  	if err != nil {
   133  		r.Err = err
   134  		return
   135  	}
   136  
   137  	resp, err := c.Post(tokenURL(c), b, &r.Body, &gophercloud.RequestOpts{
   138  		OmitHeaders: []string{"X-Auth-Token"},
   139  	})
   140  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   141  	return
   142  }
   143  
   144  // Get validates and retrieves information about another token.
   145  func Get(c *gophercloud.ServiceClient, token string) (r GetResult) {
   146  	resp, err := c.Get(tokenURL(c), &r.Body, &gophercloud.RequestOpts{
   147  		MoreHeaders: subjectTokenHeaders(token),
   148  		OkCodes:     []int{200, 203},
   149  	})
   150  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   151  	return
   152  }
   153  
   154  // Validate determines if a specified token is valid or not.
   155  func Validate(c *gophercloud.ServiceClient, token string) (bool, error) {
   156  	resp, err := c.Head(tokenURL(c), &gophercloud.RequestOpts{
   157  		MoreHeaders: subjectTokenHeaders(token),
   158  		OkCodes:     []int{200, 204, 404},
   159  	})
   160  	if err != nil {
   161  		return false, err
   162  	}
   163  
   164  	return resp.StatusCode == 200 || resp.StatusCode == 204, nil
   165  }
   166  
   167  // Revoke immediately makes specified token invalid.
   168  func Revoke(c *gophercloud.ServiceClient, token string) (r RevokeResult) {
   169  	resp, err := c.Delete(tokenURL(c), &gophercloud.RequestOpts{
   170  		MoreHeaders: subjectTokenHeaders(token),
   171  	})
   172  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   173  	return
   174  }