Skip to content
This repository was archived by the owner on Aug 1, 2023. It is now read-only.

Commit f28452d

Browse files
authored
Merge pull request #528 from orivej/openstack-identity-v3-pass-tokenid
Fix keystone v3 token auth
2 parents caaa536 + 3d6ab64 commit f28452d

File tree

4 files changed

+77
-20
lines changed

4 files changed

+77
-20
lines changed

openstack/auth_env.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,15 @@ var nilOptions = gophercloud.AuthOptions{}
1313
// environment variables, respectively, remain undefined. See the AuthOptions() function for more details.
1414
var (
1515
ErrNoAuthURL = fmt.Errorf("Environment variable OS_AUTH_URL needs to be set.")
16-
ErrNoUsername = fmt.Errorf("Environment variable OS_USERNAME needs to be set.")
17-
ErrNoPassword = fmt.Errorf("Environment variable OS_PASSWORD needs to be set.")
16+
ErrNoUsername = fmt.Errorf("Environment variable OS_USERNAME, OS_USERID, or OS_TOKEN needs to be set.")
17+
ErrNoPassword = fmt.Errorf("Environment variable OS_PASSWORD or OS_TOKEN needs to be set.")
1818
)
1919

20-
// AuthOptions fills out an identity.AuthOptions structure with the settings found on the various OpenStack
21-
// OS_* environment variables. The following variables provide sources of truth: OS_AUTH_URL, OS_USERNAME,
22-
// OS_PASSWORD, OS_TENANT_ID, and OS_TENANT_NAME. Of these, OS_USERNAME, OS_PASSWORD, and OS_AUTH_URL must
23-
// have settings, or an error will result. OS_TENANT_ID and OS_TENANT_NAME are optional.
20+
// AuthOptionsFromEnv fills out an AuthOptions structure from the environment
21+
// variables: OS_AUTH_URL, OS_USERNAME, OS_USERID, OS_PASSWORD, OS_TENANT_ID,
22+
// OS_TENANT_NAME, OS_DOMAIN_ID, OS_DOMAIN_NAME, OS_TOKEN. It checks that
23+
// (1) OS_AUTH_URL is set, (2) OS_USERNAME, OS_USERID, or OS_TOKEN is set,
24+
// (3) OS_PASSWORD or OS_TOKEN is set.
2425
func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) {
2526
authURL := os.Getenv("OS_AUTH_URL")
2627
username := os.Getenv("OS_USERNAME")
@@ -30,16 +31,17 @@ func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) {
3031
tenantName := os.Getenv("OS_TENANT_NAME")
3132
domainID := os.Getenv("OS_DOMAIN_ID")
3233
domainName := os.Getenv("OS_DOMAIN_NAME")
34+
tokenID := os.Getenv("OS_TOKEN")
3335

3436
if authURL == "" {
3537
return nilOptions, ErrNoAuthURL
3638
}
3739

38-
if username == "" && userID == "" {
40+
if username == "" && userID == "" && tokenID == "" {
3941
return nilOptions, ErrNoUsername
4042
}
4143

42-
if password == "" {
44+
if password == "" && tokenID == "" {
4345
return nilOptions, ErrNoPassword
4446
}
4547

@@ -52,6 +54,7 @@ func AuthOptionsFromEnv() (gophercloud.AuthOptions, error) {
5254
TenantName: tenantName,
5355
DomainID: domainID,
5456
DomainName: domainName,
57+
TokenID: tokenID,
5558
}
5659

5760
return ao, nil

openstack/identity/v3/tokens/errors.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ var (
5252
// It may also indicate that both a DomainID and a DomainName were provided at once.
5353
ErrDomainIDOrDomainName = errors.New("You must provide exactly one of DomainID or DomainName to authenticate by Username")
5454

55-
// ErrMissingPassword indicates that no password was provided and no token is available.
56-
ErrMissingPassword = errors.New("You must provide a password to authenticate")
55+
// ErrMissingPassword indicates that no password and no token were provided and no token is available.
56+
ErrMissingPassword = errors.New("You must provide a password or a token to authenticate")
5757

5858
// ErrScopeDomainIDOrDomainName indicates that a domain ID or Name was required in a Scope, but not present.
5959
ErrScopeDomainIDOrDomainName = errors.New("You must provide exactly one of DomainID or DomainName in a Scope with ProjectName")

openstack/identity/v3/tokens/requests.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ func Create(c *gophercloud.ServiceClient, options gophercloud.AuthOptions, scope
8484
}
8585

8686
if options.Password == "" {
87+
if options.TokenID != "" {
88+
c.TokenID = options.TokenID
89+
}
8790
if c.TokenID != "" {
8891
// Because we aren't using password authentication, it's an error to also provide any of the user-based authentication
8992
// parameters.
@@ -93,12 +96,6 @@ func Create(c *gophercloud.ServiceClient, options gophercloud.AuthOptions, scope
9396
if options.UserID != "" {
9497
return createErr(ErrUserIDWithToken)
9598
}
96-
if options.DomainID != "" {
97-
return createErr(ErrDomainIDWithToken)
98-
}
99-
if options.DomainName != "" {
100-
return createErr(ErrDomainNameWithToken)
101-
}
10299

103100
// Configure the request for Token authentication.
104101
req.Auth.Identity.Methods = []string{"token"}

openstack/identity/v3/tokens/requests_test.go

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,21 @@ func TestCreateTokenID(t *testing.T) {
135135
`)
136136
}
137137

138+
func TestCreateNewTokenID(t *testing.T) {
139+
authTokenPost(t, gophercloud.AuthOptions{TokenID: "asdf"}, nil, `
140+
{
141+
"auth": {
142+
"identity": {
143+
"methods": ["token"],
144+
"token": {
145+
"id": "asdf"
146+
}
147+
}
148+
}
149+
}
150+
`)
151+
}
152+
138153
func TestCreateProjectIDScope(t *testing.T) {
139154
options := gophercloud.AuthOptions{UserID: "fenris", Password: "g0t0h311"}
140155
scope := &Scope{ProjectID: "123456"}
@@ -296,12 +311,54 @@ func TestCreateFailureTokenIDUserID(t *testing.T) {
296311
authTokenPostErr(t, gophercloud.AuthOptions{UserID: "something"}, nil, true, ErrUserIDWithToken)
297312
}
298313

299-
func TestCreateFailureTokenIDDomainID(t *testing.T) {
300-
authTokenPostErr(t, gophercloud.AuthOptions{DomainID: "something"}, nil, true, ErrDomainIDWithToken)
314+
func TestCreateTokenIDDomainID(t *testing.T) {
315+
scope := &Scope{ProjectName: "world-domination", DomainID: "1000"}
316+
authTokenPost(t, gophercloud.AuthOptions{DomainID: "something"}, scope, `
317+
{
318+
"auth": {
319+
"identity": {
320+
"methods": [
321+
"token"
322+
],
323+
"token": {
324+
"id": "12345abcdef"
325+
}
326+
},
327+
"scope": {
328+
"project": {
329+
"domain": {
330+
"id": "1000"
331+
},
332+
"name": "world-domination"
333+
}
334+
}
335+
}
336+
}`)
301337
}
302338

303-
func TestCreateFailureTokenIDDomainName(t *testing.T) {
304-
authTokenPostErr(t, gophercloud.AuthOptions{DomainName: "something"}, nil, true, ErrDomainNameWithToken)
339+
func TestCreateTokenIDDomainName(t *testing.T) {
340+
scope := &Scope{ProjectName: "world-domination", DomainName: "evil-plans"}
341+
authTokenPost(t, gophercloud.AuthOptions{DomainName: "something"}, scope, `
342+
{
343+
"auth": {
344+
"identity": {
345+
"methods": [
346+
"token"
347+
],
348+
"token": {
349+
"id": "12345abcdef"
350+
}
351+
},
352+
"scope": {
353+
"project": {
354+
"domain": {
355+
"name": "evil-plans"
356+
},
357+
"name": "world-domination"
358+
}
359+
}
360+
}
361+
}`)
305362
}
306363

307364
func TestCreateFailureMissingUser(t *testing.T) {

0 commit comments

Comments
 (0)