From ecb9c69240ec0956230f7770ab84ce82ac8a579f Mon Sep 17 00:00:00 2001 From: Thomas Kappler Date: Thu, 6 Oct 2022 19:58:41 -0700 Subject: [PATCH] Use correct audience for MSAL Key Vault token #1566 --- provider/pkg/provider/auth.go | 33 +++++++------------ provider/pkg/provider/provider.go | 40 ++++++++++++++++++++--- provider/pkg/resources/customresources.go | 13 +++++--- 3 files changed, 57 insertions(+), 29 deletions(-) diff --git a/provider/pkg/provider/auth.go b/provider/pkg/provider/auth.go index 0187210c07e4..21135892e0d8 100644 --- a/provider/pkg/provider/auth.go +++ b/provider/pkg/provider/auth.go @@ -11,7 +11,6 @@ import ( "strings" "github.com/Azure/go-autorest/autorest" - "github.com/Azure/go-autorest/autorest/azure" "github.com/hashicorp/go-azure-helpers/authentication" "github.com/hashicorp/go-azure-helpers/sender" "github.com/manicminer/hamilton/environments" @@ -139,8 +138,11 @@ func runAzCmd(target interface{}, arg ...string) error { return nil } -func (k *azureNativeProvider) getAuthorizers(ctx context.Context, authConfig *authentication.Config) (tokenAuth autorest.Authorizer, - bearerAuth autorest.Authorizer, err error) { +type AuthorizerFactory func(api environments.Api) (autorest.Authorizer, error) + +func (k *azureNativeProvider) makeAuthorizerFactories(ctx context.Context, + authConfig *authentication.Config) (AuthorizerFactory, AuthorizerFactory, error) { + buildSender := sender.BuildSender("AzureNative") oauthConfig, err := k.buildOAuthConfig(authConfig) @@ -148,17 +150,17 @@ func (k *azureNativeProvider) getAuthorizers(ctx context.Context, authConfig *au return nil, nil, err } - api := k.autorestEnvToHamiltonEnv().ResourceManager - endpoint := k.environment.TokenAudience - tokenAuth, err = authConfig.GetMSALToken(ctx, api, buildSender, oauthConfig, endpoint) - if err != nil { - return nil, nil, err + tokenFactory := func(api environments.Api) (autorest.Authorizer, error) { + return authConfig.GetMSALToken(ctx, api, buildSender, oauthConfig, endpoint) } - bearerAuth = authConfig.MSALBearerAuthorizerCallback(ctx, api, buildSender, oauthConfig, endpoint) - return tokenAuth, bearerAuth, nil + bearerAuthFactory := func(api environments.Api) (autorest.Authorizer, error) { + return authConfig.MSALBearerAuthorizerCallback(ctx, api, buildSender, oauthConfig, endpoint), nil + } + + return tokenFactory, bearerAuthFactory, nil } func (k *azureNativeProvider) getOAuthToken(ctx context.Context, auth *authentication.Config, endpoint string) (string, error) { @@ -208,14 +210,3 @@ func (k *azureNativeProvider) buildOAuthConfig(authConfig *authentication.Config } return oauthConfig, nil } - -func (k *azureNativeProvider) autorestEnvToHamiltonEnv() environments.Environment { - switch k.environment.Name { - case azure.USGovernmentCloud.Name: - return environments.USGovernmentL4 - case azure.ChinaCloud.Name: - return environments.China - default: - return environments.Global - } -} diff --git a/provider/pkg/provider/provider.go b/provider/pkg/provider/provider.go index 8fac2e27e8bb..00be8b708fef 100644 --- a/provider/pkg/provider/provider.go +++ b/provider/pkg/provider/provider.go @@ -17,6 +17,7 @@ import ( "strings" "time" + "github.com/manicminer/hamilton/environments" "github.com/segmentio/encoding/json" structpb "github.com/golang/protobuf/ptypes/struct" @@ -176,19 +177,39 @@ func (k *azureNativeProvider) Configure(ctx context.Context, } k.environment = env + hamiltonEnv := k.autorestEnvToHamiltonEnv() + // The ctx Context given by gRPC is request-scoped and will be canceled after this request. We // need the authorizers to function across requests. authCtx := context.Background() - tokenAuth, bearerAuth, err := k.getAuthorizers(authCtx, authConfig) + + tokenAuth, bearerAuth, err := k.makeAuthorizerFactories(authCtx, authConfig) + if err != nil { + return nil, fmt.Errorf("auth setup: %w", err) + } + + resourceManagerAuth, err := tokenAuth(hamiltonEnv.ResourceManager) + if err != nil { + return nil, fmt.Errorf("building authorizer for %s: %w", hamiltonEnv.ResourceManager.Endpoint, err) + } + + resourceManagerBearerAuth, err := bearerAuth(hamiltonEnv.ResourceManager) if err != nil { - return nil, errors.Wrap(err, "building authorizer") + return nil, fmt.Errorf("building bearer authorizer for %s: %w", hamiltonEnv.ResourceManager.Endpoint, err) + } + + keyVaultBearerAuth, err := tokenAuth(hamiltonEnv.KeyVault) + if err != nil { + return nil, fmt.Errorf("building authorizer for %s: %w", hamiltonEnv.KeyVault.Endpoint, err) } k.subscriptionID = authConfig.SubscriptionID - k.client.Authorizer = tokenAuth + k.client.Authorizer = resourceManagerAuth k.client.UserAgent = k.getUserAgent() - k.customResources = resources.BuildCustomResources(&env, k.subscriptionID, bearerAuth, tokenAuth, k.client.UserAgent) + k.customResources = resources.BuildCustomResources(&env, k.subscriptionID, + resourceManagerBearerAuth, resourceManagerAuth, keyVaultBearerAuth, + k.client.UserAgent) return &rpc.ConfigureResponse{ SupportsPreview: true, @@ -1812,3 +1833,14 @@ func parseCheckpointObject(obj resource.PropertyMap) resource.PropertyMap { return nil } + +func (k *azureNativeProvider) autorestEnvToHamiltonEnv() environments.Environment { + switch k.environment.Name { + case azure.USGovernmentCloud.Name: + return environments.USGovernmentL4 + case azure.ChinaCloud.Name: + return environments.China + default: + return environments.Global + } +} diff --git a/provider/pkg/resources/customresources.go b/provider/pkg/resources/customresources.go index c21c7dea2a30..8868b0bc32c3 100644 --- a/provider/pkg/resources/customresources.go +++ b/provider/pkg/resources/customresources.go @@ -4,6 +4,7 @@ package resources import ( "context" + "github.com/Azure/azure-sdk-for-go/services/keyvault/2016-10-01/keyvault" "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-04-01/storage" "github.com/Azure/go-autorest/autorest" @@ -36,11 +37,15 @@ type CustomResource struct { } // BuildCustomResources creates a map of custom resources for given environment parameters. -func BuildCustomResources(env *azure.Environment, subscriptionID string, bearerAuth autorest.Authorizer, - tokenAuth autorest.Authorizer, userAgent string) map[string]*CustomResource { +func BuildCustomResources(env *azure.Environment, + subscriptionID string, + bearerAuth autorest.Authorizer, + tokenAuth autorest.Authorizer, + kvBearerAuth autorest.Authorizer, + userAgent string) map[string]*CustomResource { kvClient := keyvault.New() - kvClient.Authorizer = bearerAuth + kvClient.Authorizer = kvBearerAuth kvClient.UserAgent = userAgent storageAccountsClient := storage.NewAccountsClientWithBaseURI(env.ResourceManagerEndpoint, subscriptionID) @@ -64,7 +69,7 @@ func BuildCustomResources(env *azure.Environment, subscriptionID string, bearerA } // featureLookup is a map of custom resource to lookup their capabilities. -var featureLookup = BuildCustomResources(&azure.Environment{}, "", nil, nil, "") +var featureLookup = BuildCustomResources(&azure.Environment{}, "", nil, nil, nil, "") // HasCustomDelete returns true if a custom DELETE operation is defined for a given API path. func HasCustomDelete(path string) bool {