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
30 changes: 30 additions & 0 deletions auth_aksk_options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package golangsdk

// AKSKAuthOptions presents the required information for AK/SK auth
type AKSKAuthOptions struct {
// IdentityEndpoint specifies the HTTP endpoint that is required to work with
// the Identity API of the appropriate version. While it's ultimately needed by
// all of the identity services, it will often be populated by a provider-level
// function.
//
// The IdentityEndpoint is typically referred to as the "auth_url" or
// "OS_AUTH_URL" in the information provided by the cloud operator.
IdentityEndpoint string `json:"-"`

// user project id
ProjectId string

// region
Region string

// cloud service domain, example: myhwclouds.com
Domain string

AccessKey string //Access Key
SecretKey string //Secret key
}

// Implements the method of AuthOptionsProvider
func (opts AKSKAuthOptions) GetIdentityEndpoint() string {
return opts.IdentityEndpoint
}
6 changes: 6 additions & 0 deletions auth_option_provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package golangsdk

// AuthOptionsProvider presents the base of an auth options implementation
type AuthOptionsProvider interface {
GetIdentityEndpoint() string
}
5 changes: 5 additions & 0 deletions auth_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,11 @@ func (opts *AuthOptions) AuthTokenID() string {
return ""
}

// Implements the method of AuthOptionsProvider
func (opts AuthOptions) GetIdentityEndpoint() string {
return opts.IdentityEndpoint
}

type scopeInfo struct {
ProjectID string
ProjectName string
Expand Down
114 changes: 105 additions & 9 deletions openstack/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ import (

"github.com/huaweicloud/golangsdk"
tokens2 "github.com/huaweicloud/golangsdk/openstack/identity/v2/tokens"
"github.com/huaweicloud/golangsdk/openstack/identity/v3/endpoints"
"github.com/huaweicloud/golangsdk/openstack/identity/v3/services"
tokens3 "github.com/huaweicloud/golangsdk/openstack/identity/v3/tokens"
"github.com/huaweicloud/golangsdk/openstack/utils"
"github.com/huaweicloud/golangsdk/pagination"
)

const (
Expand Down Expand Up @@ -99,7 +102,7 @@ func AuthenticatedClient(options golangsdk.AuthOptions) (*golangsdk.ProviderClie

// Authenticate or re-authenticate against the most recent identity service
// supported at the provided endpoint.
func Authenticate(client *golangsdk.ProviderClient, options golangsdk.AuthOptions) error {
func Authenticate(client *golangsdk.ProviderClient, options golangsdk.AuthOptionsProvider) error {
versions := []*utils.Version{
{ID: v2, Priority: 20, Suffix: "/v2.0/"},
{ID: v3, Priority: 30, Suffix: "/v3/"},
Expand All @@ -110,15 +113,28 @@ func Authenticate(client *golangsdk.ProviderClient, options golangsdk.AuthOption
return err
}

switch chosen.ID {
case v2:
return v2auth(client, endpoint, options, golangsdk.EndpointOpts{})
case v3:
return v3auth(client, endpoint, &options, golangsdk.EndpointOpts{})
default:
// The switch statement must be out of date from the versions list.
return fmt.Errorf("Unrecognized identity version: %s", chosen.ID)
authOptions, isTokenAuthOptions := options.(golangsdk.AuthOptions)

if isTokenAuthOptions {
switch chosen.ID {
case v2:
return v2auth(client, endpoint, authOptions, golangsdk.EndpointOpts{})
case v3:
return v3auth(client, endpoint, &authOptions, golangsdk.EndpointOpts{})
default:
// The switch statement must be out of date from the versions list.
return fmt.Errorf("Unrecognized identity version: %s", chosen.ID)
}
} else {
akskAuthOptions, isAkSkOptions := options.(golangsdk.AKSKAuthOptions)

if isAkSkOptions {
return v3AKSKAuth(client, endpoint, akskAuthOptions, golangsdk.EndpointOpts{})
} else {
return fmt.Errorf("Unrecognized auth options provider: %s", reflect.TypeOf(options))
}
}

}

// AuthenticateV2 explicitly authenticates against the identity v2 endpoint.
Expand Down Expand Up @@ -239,6 +255,86 @@ func v3auth(client *golangsdk.ProviderClient, endpoint string, opts tokens3.Auth
return nil
}

func getEntryByServiceId(entries []tokens3.CatalogEntry, serviceId string) *tokens3.CatalogEntry {
if entries == nil {
return nil
}

for idx, _ := range entries {
if entries[idx].ID == serviceId {
return &entries[idx]
}
}

return nil
}

func v3AKSKAuth(client *golangsdk.ProviderClient, endpoint string, options golangsdk.AKSKAuthOptions, eo golangsdk.EndpointOpts) error {
v3Client, err := NewIdentityV3(client, eo)
if err != nil {
return err
}

if endpoint != "" {
v3Client.Endpoint = endpoint
}

v3Client.AKSKAuthOptions = options
v3Client.ProjectID = options.ProjectId

var entries = make([]tokens3.CatalogEntry, 0, 1)
services.List(v3Client, services.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
serviceLst, err := services.ExtractServices(page)
if err != nil {
return false, err
}

for _, svc := range serviceLst {
entry := tokens3.CatalogEntry{
Type: svc.Type,
//Name: svc.Name,
ID: svc.ID,
}
entries = append(entries, entry)
}

return true, nil
})

endpoints.List(v3Client, endpoints.ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
endpoints, err := endpoints.ExtractEndpoints(page)
if err != nil {
return false, err
}

for _, endpoint := range endpoints {
entry := getEntryByServiceId(entries, endpoint.ServiceID)

if entry != nil {
entry.Endpoints = append(entry.Endpoints, tokens3.Endpoint{
URL: strings.Replace(endpoint.URL, "$(tenant_id)s", options.ProjectId, -1),
Region: endpoint.Region,
Interface: string(endpoint.Availability),
ID: endpoint.ID,
})
}
}

client.EndpointLocator = func(opts golangsdk.EndpointOpts) (string, error) {
if opts.Region == "" {
opts.Region = options.Region
}
return V3EndpointURL(&tokens3.ServiceCatalog{
Entries: entries,
}, opts)
}

return true, nil
})

return nil
}

// NewIdentityV2 creates a ServiceClient that may be used to interact with the
// v2 identity service.
func NewIdentityV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) {
Expand Down
11 changes: 11 additions & 0 deletions provider_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ type ProviderClient struct {
// authentication functions for different Identity service versions.
ReauthFunc func() error

// AKSKAuthOptions provides the value for AK/SK authentication, it should be nil if you use token authentication,
// Otherwise, it must have a value
AKSKAuthOptions AKSKAuthOptions

mut *sync.RWMutex

reauthmut *reauthlock
Expand Down Expand Up @@ -217,6 +221,13 @@ func (client *ProviderClient) Request(method, url string, options *RequestOpts)

prereqtok := req.Header.Get("X-Auth-Token")

if client.AKSKAuthOptions.AccessKey != "" {
Sign(req, SignOptions{
AccessKey: client.AKSKAuthOptions.AccessKey,
SecretKey: client.AKSKAuthOptions.SecretKey,
})
}

// Issue the request.
resp, err := client.HTTPClient.Do(req)
if err != nil {
Expand Down
Loading