Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 86 additions & 9 deletions auth_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@ type AuthOptions struct {
// TokenID allows users to authenticate (possibly as another user) with an
// authentication token ID.
TokenID string `json:"-"`

// AgencyNmae is the name of agnecy
AgencyName string `json:"xrole_name,omitempty"`

// AgencyDomainName is the domain name who created the agency
AgencyDomainName string `json:"domain_name,omitempty"`

// AgencyProjectName is the project name of agency
AgencyProjectName string
}

// ToTokenV2CreateMap allows AuthOptions to satisfy the AuthOptionsBuilder
Expand Down Expand Up @@ -263,13 +272,7 @@ func (opts *AuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[s
}

func (opts *AuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) {

var scope struct {
ProjectID string
ProjectName string
DomainID string
DomainName string
}
var scope scopeInfo

if opts.TenantID != "" {
scope.ProjectID = opts.TenantID
Expand All @@ -278,9 +281,31 @@ func (opts *AuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) {
scope.ProjectName = opts.TenantName
scope.DomainID = opts.DomainID
scope.DomainName = opts.DomainName
} else {
// support scoping to domain
scope.DomainID = opts.DomainID
scope.DomainName = opts.DomainName
}
}
return scope.BuildTokenV3ScopeMap()
}

func (opts *AuthOptions) CanReauth() bool {
return opts.AllowReauth
}

func (opts *AuthOptions) AuthTokenID() string {
return ""
}

type scopeInfo struct {
ProjectID string
ProjectName string
DomainID string
DomainName string
}

func (scope *scopeInfo) BuildTokenV3ScopeMap() (map[string]interface{}, error) {
if scope.ProjectName != "" {
// ProjectName provided: either DomainID or DomainName must also be supplied.
// ProjectID may not be supplied.
Expand Down Expand Up @@ -349,6 +374,58 @@ func (opts *AuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) {
return nil, nil
}

func (opts AuthOptions) CanReauth() bool {
return opts.AllowReauth
type AgencyAuthOptions struct {
TokenID string
AgencyName string
AgencyDomainName string
AgencyProjectName string
}

func (opts *AgencyAuthOptions) CanReauth() bool {
return false
}

func (opts *AgencyAuthOptions) AuthTokenID() string {
return opts.TokenID
}

func (opts *AgencyAuthOptions) ToTokenV3ScopeMap() (map[string]interface{}, error) {
scope := scopeInfo{
ProjectName: opts.AgencyProjectName,
DomainName: opts.AgencyDomainName,
}

return scope.BuildTokenV3ScopeMap()
}

func (opts *AgencyAuthOptions) ToTokenV3CreateMap(scope map[string]interface{}) (map[string]interface{}, error) {
type assumeRoleReq struct {
DomainName string `json:"domain_name"`
AgencyName string `json:"xrole_name"`
}

type identityReq struct {
Methods []string `json:"methods"`
AssumeRole assumeRoleReq `json:"assume_role"`
}

type authReq struct {
Identity identityReq `json:"identity"`
}

var req authReq
req.Identity.Methods = []string{"assume_role"}
req.Identity.AssumeRole = assumeRoleReq{
DomainName: opts.AgencyDomainName,
AgencyName: opts.AgencyName,
}
r, err := BuildRequestBody(req, "auth")
if err != nil {
return r, err
}

if len(scope) != 0 {
r["auth"].(map[string]interface{})["scope"] = scope
}
return r, nil
}
15 changes: 15 additions & 0 deletions openstack/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,21 @@ func v3auth(client *golangsdk.ProviderClient, endpoint string, opts tokens3.Auth
return err
}

opts1, ok := opts.(*golangsdk.AuthOptions)
if ok && opts1.AgencyDomainName != "" && opts1.AgencyName != "" {
opts2 := golangsdk.AgencyAuthOptions{
TokenID: token.ID,
AgencyName: opts1.AgencyName,
AgencyDomainName: opts1.AgencyDomainName,
AgencyProjectName: opts1.AgencyProjectName,
}
result = tokens3.Create(v3Client, &opts2)
token, err = result.ExtractToken()
if err != nil {
return err
}
}

project, err := result.ExtractProject()
if err != nil {
return err
Expand Down
7 changes: 6 additions & 1 deletion openstack/identity/v3/tokens/requests.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type AuthOptionsBuilder interface {
ToTokenV3CreateMap(map[string]interface{}) (map[string]interface{}, error)
ToTokenV3ScopeMap() (map[string]interface{}, error)
CanReauth() bool
AuthTokenID() string
}

// AuthOptions represents options for authenticating a user.
Expand Down Expand Up @@ -144,6 +145,10 @@ func (opts *AuthOptions) CanReauth() bool {
return opts.AllowReauth
}

func (opts *AuthOptions) AuthTokenID() string {
return ""
}

func subjectTokenHeaders(c *golangsdk.ServiceClient, subjectToken string) map[string]string {
return map[string]string{
"X-Subject-Token": subjectToken,
Expand All @@ -166,7 +171,7 @@ func Create(c *golangsdk.ServiceClient, opts AuthOptionsBuilder) (r CreateResult
}

resp, err := c.Post(tokenURL(c), b, &r.Body, &golangsdk.RequestOpts{
MoreHeaders: map[string]string{"X-Auth-Token": ""},
MoreHeaders: map[string]string{"X-Auth-Token": opts.AuthTokenID()},
})
r.Err = err
if resp != nil {
Expand Down