From 9d32bab8e1c79a20b55b39024d03617ec0112d43 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Fri, 17 Feb 2023 15:29:49 +0200 Subject: [PATCH 1/2] Update to latest go-azure-sdk --- go.mod | 2 +- go.sum | 4 +-- .../go-azure-sdk/sdk/auth/autorest/auth.go | 21 ++++++++------- .../sdk/auth/azure_cli_authorizer.go | 26 ++++++++++++++----- .../sdk/auth/managed_identity_authorizer.go | 16 +++++++++--- .../sdk/internal/azurecli/azcli.go | 13 ++++++++++ vendor/modules.txt | 2 +- 7 files changed, 60 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index b0b5895bb71b..64bd7b1dc714 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/google/go-cmp v0.5.9 github.com/google/uuid v1.1.2 github.com/hashicorp/go-azure-helpers v0.51.0 - github.com/hashicorp/go-azure-sdk v0.20230217.1092053 + github.com/hashicorp/go-azure-sdk v0.20230217.1131029 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/go-version v1.6.0 diff --git a/go.sum b/go.sum index a2318986eef7..1c8fc0d75dab 100644 --- a/go.sum +++ b/go.sum @@ -207,8 +207,8 @@ github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brv github.com/hashicorp/go-azure-helpers v0.12.0/go.mod h1:Zc3v4DNeX6PDdy7NljlYpnrdac1++qNW0I4U+ofGwpg= github.com/hashicorp/go-azure-helpers v0.51.0 h1:8KSDGkGnWH6zOT60R3KUqsi0fk1vA7AMunaOUJZMM6k= github.com/hashicorp/go-azure-helpers v0.51.0/go.mod h1:lsykLR4KjTUO7MiRmNWiTiX8QQtw3ILjyOvT0f5h3rw= -github.com/hashicorp/go-azure-sdk v0.20230217.1092053 h1:044WTlqd5eoUYgL9ij7oe5H1kLTCs0D9L3rGWCMsZRY= -github.com/hashicorp/go-azure-sdk v0.20230217.1092053/go.mod h1:aHinadEuBi04I1i+yvpPMZUxvxRxl5JgBOwlzIIxozU= +github.com/hashicorp/go-azure-sdk v0.20230217.1131029 h1:QbSLBbv7xpterl93SM4oZX3ptN18DLNfDrPjRIMxMqc= +github.com/hashicorp/go-azure-sdk v0.20230217.1131029/go.mod h1:aHinadEuBi04I1i+yvpPMZUxvxRxl5JgBOwlzIIxozU= github.com/hashicorp/go-checkpoint v0.5.0 h1:MFYpPZCnQqQTE18jFwSII6eUQrD/oxMFp3mlgcqk5mU= github.com/hashicorp/go-checkpoint v0.5.0/go.mod h1:7nfLNL10NsxqO4iWuW6tWW0HjZuDrwkBuEQsVcpCOgg= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/autorest/auth.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/autorest/auth.go index 10bca1d322a0..6b20258ca8de 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/autorest/auth.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/autorest/auth.go @@ -34,23 +34,24 @@ func (c *Authorizer) WithAuthorization() autorest.PrepareDecorator { req, err = autorest.Prepare(req, autorest.WithHeader("Authorization", fmt.Sprintf("Bearer %s", token.AccessToken))) if err != nil { - return req, err + return nil, fmt.Errorf("preparing request: %+v", err) } auxTokens, err := c.AuxiliaryTokens(ctx, req) if err != nil { - return req, err + return nil, fmt.Errorf("preparing auxiliary tokens for request: %+v", err) } - - auxTokenList := make([]string, 0) - for _, a := range auxTokens { - if a != nil && a.AccessToken != "" { - auxTokenList = append(auxTokenList, fmt.Sprintf("%s %s", a.TokenType, a.AccessToken)) + if len(auxTokens) > 0 { + auxTokenList := make([]string, 0) + for _, a := range auxTokens { + if a != nil && a.AccessToken != "" { + auxTokenList = append(auxTokenList, fmt.Sprintf("%s %s", a.TokenType, a.AccessToken)) + } } - } - if len(auxTokenList) > 0 { - return autorest.Prepare(req, autorest.WithHeader("x-ms-authorization-auxiliary", strings.Join(auxTokenList, ", "))) + if len(auxTokenList) > 0 { + return autorest.Prepare(req, autorest.WithHeader("x-ms-authorization-auxiliary", strings.Join(auxTokenList, ", "))) + } } return req, nil diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/azure_cli_authorizer.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/azure_cli_authorizer.go index 4488a67d2872..5a6d87bd6684 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/azure_cli_authorizer.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/azure_cli_authorizer.go @@ -45,6 +45,9 @@ type AzureCliAuthorizer struct { // TenantID is the specified tenant ID, or the auto-detected tenant ID if none was specified TenantID string + // DefaultSubscriptionID is the default subscription, when detected + DefaultSubscriptionID string + conf *azureCliConfig } @@ -141,6 +144,9 @@ type azureCliConfig struct { // AuxiliaryTenantIDs is an optional list of tenant IDs for which to obtain additional tokens AuxiliaryTenantIDs []string + + // DefaultSubscriptionID is the optional default subscription ID + DefaultSubscriptionID string } // newAzureCliConfig validates the supplied tenant ID and returns a new azureCliConfig. @@ -153,7 +159,7 @@ func newAzureCliConfig(api environments.Api, tenantId string, auxiliaryTenantIds return nil, err } - // check tenant id + // check tenant ID tenantId, err = azurecli.CheckTenantID(tenantId) if err != nil { return nil, err @@ -162,10 +168,17 @@ func newAzureCliConfig(api environments.Api, tenantId string, auxiliaryTenantIds return nil, errors.New("invalid tenantId or unable to determine tenantId") } + // get the default subscription ID + subscriptionId, err := azurecli.GetDefaultSubscriptionID() + if err != nil { + return nil, err + } + return &azureCliConfig{ - Api: api, - TenantID: tenantId, - AuxiliaryTenantIDs: auxiliaryTenantIds, + Api: api, + TenantID: tenantId, + AuxiliaryTenantIDs: auxiliaryTenantIds, + DefaultSubscriptionID: subscriptionId, }, nil } @@ -173,8 +186,9 @@ func newAzureCliConfig(api environments.Api, tenantId string, auxiliaryTenantIds func (c *azureCliConfig) TokenSource(ctx context.Context) (Authorizer, error) { // Cache access tokens internally to avoid unnecessary `az` invocations return NewCachedAuthorizer(&AzureCliAuthorizer{ - TenantID: c.TenantID, - conf: c, + TenantID: c.TenantID, + DefaultSubscriptionID: c.DefaultSubscriptionID, + conf: c, }) } diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/managed_identity_authorizer.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/managed_identity_authorizer.go index 023f8572ccd7..e3a69b446dd7 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/managed_identity_authorizer.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/managed_identity_authorizer.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "io" + "log" "net/http" "net/url" "strconv" @@ -114,7 +115,8 @@ func (a *ManagedIdentityAuthorizer) Token(ctx context.Context, _ *http.Request) // AuxiliaryTokens returns additional tokens for auxiliary tenant IDs, for use in multi-tenant scenarios func (a *ManagedIdentityAuthorizer) AuxiliaryTokens(_ context.Context, _ *http.Request) ([]*oauth2.Token, error) { - return nil, fmt.Errorf("auxiliary tokens are not supported with MSI authentication") + // auxiliary tokens are not supported with MSI authentication, so just return an empty slice + return []*oauth2.Token{}, nil } // managedIdentityConfig configures an ManagedIdentityAuthorizer. @@ -149,15 +151,18 @@ func newManagedIdentityConfig(resource, clientId, customManagedIdentityEndpoint } // TokenSource provides a source for obtaining access tokens using ManagedIdentityAuthorizer. -func (c *managedIdentityConfig) TokenSource(ctx context.Context) (Authorizer, error) { +func (c *managedIdentityConfig) TokenSource(_ context.Context) (Authorizer, error) { return NewCachedAuthorizer(&ManagedIdentityAuthorizer{ conf: c, }) } func azureMetadata(ctx context.Context, url string) (body []byte, err error) { + ctx2, cancel := context.WithDeadline(ctx, time.Now().Add(time.Second*30)) + defer cancel() + var req *http.Request - req, err = http.NewRequestWithContext(ctx, http.MethodGet, url, http.NoBody) + req, err = http.NewRequestWithContext(ctx2, http.MethodGet, url, http.NoBody) if err != nil { return } @@ -165,13 +170,16 @@ func azureMetadata(ctx context.Context, url string) (body []byte, err error) { "Metadata": []string{"true"}, } client := &http.Client{ - Timeout: msiDefaultTimeout, + Transport: http.DefaultTransport, + Timeout: msiDefaultTimeout, } var resp *http.Response + log.Printf("[DEBUG] Performing %s Request to %q", req.Method, url) resp, err = client.Do(req) if err != nil { return } + log.Printf("[DEBUG] Reading Body from %s %q", req.Method, url) body, err = io.ReadAll(resp.Body) if err != nil { return diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/azcli.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/azcli.go index 48c42e1e8cb7..f879e3f02fd6 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/azcli.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/azcli.go @@ -59,6 +59,19 @@ func CheckAzVersion(minVersion string, nextMajorVersion *string) error { return nil } +// GetDefaultSubscriptionID tries to determine the default subscription +func GetDefaultSubscriptionID() (string, error) { + var account struct { + SubscriptionID string `json:"id"` + } + err := JSONUnmarshalAzCmd(&account, "account", "show") + if err != nil { + return "", fmt.Errorf("obtaining subscription ID: %s", err) + } + + return account.SubscriptionID, nil +} + // CheckTenantID validates the supplied tenant ID, and tries to determine the default tenant if a valid one is not supplied. func CheckTenantID(tenantId string) (string, error) { validTenantId, err := regexp.MatchString("^[a-zA-Z0-9._-]+$", tenantId) diff --git a/vendor/modules.txt b/vendor/modules.txt index 2685c65ca697..eb58e67d7cca 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -159,7 +159,7 @@ github.com/hashicorp/go-azure-helpers/resourcemanager/zones github.com/hashicorp/go-azure-helpers/resourceproviders github.com/hashicorp/go-azure-helpers/sender github.com/hashicorp/go-azure-helpers/storage -# github.com/hashicorp/go-azure-sdk v0.20230217.1092053 +# github.com/hashicorp/go-azure-sdk v0.20230217.1131029 ## explicit; go 1.19 github.com/hashicorp/go-azure-sdk/resource-manager/aad/2021-05-01/domainservices github.com/hashicorp/go-azure-sdk/resource-manager/aadb2c/2021-04-01-preview From b0a580956573c6328626ce15d630fa2eb38de11d Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Fri, 17 Feb 2023 14:22:57 +0200 Subject: [PATCH 2/2] Bugfix: source the tenant ID, subscription ID and client ID from Azure CLI as needed --- internal/clients/auth.go | 39 +++++++++++++++++++++++++++++++++++++ internal/clients/builder.go | 4 ++-- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/internal/clients/auth.go b/internal/clients/auth.go index 6424637ec62d..d643cfad3303 100644 --- a/internal/clients/auth.go +++ b/internal/clients/auth.go @@ -84,6 +84,45 @@ func NewResourceManagerAccount(ctx context.Context, config auth.Credentials, sub tenantId = config.TenantID } + // Finally, defer to Azure CLI to obtain tenant ID, subscription ID and client ID when not specified and missing from claims + realAuthorizer := authorizer + if cache, ok := authorizer.(*auth.CachedAuthorizer); ok { + realAuthorizer = cache.Source + } + if cli, ok := realAuthorizer.(*auth.AzureCliAuthorizer); ok { + // Use the tenant ID from Azure CLI when otherwise unknown + if tenantId == "" { + if cli.TenantID == "" { + return nil, fmt.Errorf("azure-cli could not determine tenant ID to use") + } + tenantId = cli.TenantID + log.Printf("[DEBUG] Using tenant ID from Azure CLI: %q", tenantId) + } + + // Use the subscription ID from Azure CLI when otherwise unknown + if subscriptionId == "" { + if cli.DefaultSubscriptionID == "" { + return nil, fmt.Errorf("azure-cli could not determine subscription ID to use and no subscription was specified") + } + + subscriptionId = cli.DefaultSubscriptionID + log.Printf("[DEBUG] Using default subscription ID from Azure CLI: %q", subscriptionId) + } + + // Use the Azure CLI client ID + if id, ok := config.Environment.MicrosoftAzureCli.AppId(); ok { + clientId = *id + log.Printf("[DEBUG] Using client ID from Azure CLI: %q", clientId) + } + } + + if tenantId == "" { + return nil, fmt.Errorf("unable to configure ResourceManagerAccount: tenant ID could not be determined and was not specified") + } + if subscriptionId == "" { + return nil, fmt.Errorf("unable to configure ResourceManagerAccount: subscription ID could not be determined and was not specified") + } + account := ResourceManagerAccount{ Environment: config.Environment, diff --git a/internal/clients/builder.go b/internal/clients/builder.go index 5fd36290e8b5..b8b02e95c498 100644 --- a/internal/clients/builder.go +++ b/internal/clients/builder.go @@ -130,8 +130,8 @@ func Build(ctx context.Context, builder ClientBuilder) (*Client, error) { Environment: builder.AuthConfig.Environment, Features: builder.Features, - SubscriptionId: builder.SubscriptionID, - TenantId: builder.AuthConfig.TenantID, + SubscriptionId: account.SubscriptionId, + TenantId: account.TenantId, PartnerId: builder.PartnerID, TerraformVersion: builder.TerraformVersion,