Skip to content

Commit

Permalink
[v1] identity: use AuthOptionsBuilder for v2 auth
Browse files Browse the repository at this point in the history
Rather than creating a tokens2.AuthOptions inside the authentication
flow for identity v2, allow any structure that implements the
tokens2.AuthBuilderOptions interface to be used. The interface is
modified to add a CanReauth function like the v3 version has but
provides a default implementation. The gophercloud.AuthOptions already
implements this interface so there is no change to its API. This will
allow an out of tree identity v2 auth mechanism to be implemented,
just like the v3. fixes gophercloud#2651. ref gophercloud#1330.
  • Loading branch information
cardoe committed Apr 14, 2024
1 parent fab2a6e commit 96c9474
Showing 1 changed file with 24 additions and 16 deletions.
40 changes: 24 additions & 16 deletions openstack/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func Authenticate(client *gophercloud.ProviderClient, options gophercloud.AuthOp

switch chosen.ID {
case v2:
return v2auth(client, endpoint, options, gophercloud.EndpointOpts{})
return v2auth(client, endpoint, &options, gophercloud.EndpointOpts{})
case v3:
return v3auth(client, endpoint, &options, gophercloud.EndpointOpts{})
default:
Expand All @@ -116,7 +116,11 @@ func AuthenticateV2(client *gophercloud.ProviderClient, options gophercloud.Auth
return v2auth(client, "", options, eo)
}

func v2auth(client *gophercloud.ProviderClient, endpoint string, options gophercloud.AuthOptions, eo gophercloud.EndpointOpts) error {
func AuthenticateV2Ext(client *gophercloud.ProviderClient, options tokens2.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error {
return v2auth(client, "", options, eo)
}

func v2auth(client *gophercloud.ProviderClient, endpoint string, options tokens2.AuthOptionsBuilder, eo gophercloud.EndpointOpts) error {
v2Client, err := NewIdentityV2(client, eo)
if err != nil {
return err
Expand All @@ -126,17 +130,7 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
v2Client.Endpoint = endpoint
}

v2Opts := tokens2.AuthOptions{
IdentityEndpoint: options.IdentityEndpoint,
Username: options.Username,
Password: options.Password,
TenantID: options.TenantID,
TenantName: options.TenantName,
AllowReauth: options.AllowReauth,
TokenID: options.TokenID,
}

result := tokens2.Create(v2Client, v2Opts)
result := tokens2.Create(v2Client, options)

err = client.SetTokenAndAuthResult(result)
if err != nil {
Expand All @@ -148,16 +142,30 @@ func v2auth(client *gophercloud.ProviderClient, endpoint string, options gopherc
return err
}

if options.AllowReauth {
// use if the client's ReauthFunc is set to avoid needing to copy the AuthOptions and mutating the AllowReauth value
// when creating the reauthentication function below. this allows breaking of the loop without v2auth having to have
// knowledge of the supplied struct, allowing for out of tree extensions
if client.ReauthFunc != nil {
// here we're creating a throw-away client (tac). it's a copy of the user's provider client, but
// with the token and reauth func zeroed out. combined with setting `AllowReauth` to `false`,
// this should retry authentication only once
tac := *client
tac.SetThrowaway(true)
tac.ReauthFunc = nil
tac.SetTokenAndAuthResult(nil)
tao := options
tao.AllowReauth = false
var tao tokens2.AuthOptionsBuilder
switch ot := options.(type) {
case *gophercloud.AuthOptions:
o := *ot
o.AllowReauth = false
tao = &o
case *tokens2.AuthOptions:
o := *ot
o.AllowReauth = false
tao = &o
default:
tao = options
}
client.ReauthFunc = func() error {
err := v2auth(&tac, endpoint, tao, eo)
if err != nil {
Expand Down

0 comments on commit 96c9474

Please sign in to comment.