From c97aefcaf72c20db377639bbfedc3b45bd874f80 Mon Sep 17 00:00:00 2001 From: Tom Bamford Date: Wed, 29 Nov 2023 21:18:38 +0000 Subject: [PATCH] REBASE: bump go-azure-sdk, see https://github.com/hashicorp/go-azure-sdk/pull/753 --- go.mod | 2 +- go.sum | 4 +- .../sdk/auth/azure_cli_authorizer.go | 41 ++--- .../sdk/internal/azurecli/azcli.go | 145 +++++++++++------- .../sdk/internal/azurecli/cache.go | 24 +++ .../sdk/internal/azurecli/versions.go | 9 +- vendor/modules.txt | 2 +- 7 files changed, 138 insertions(+), 89 deletions(-) create mode 100644 vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/cache.go diff --git a/go.mod b/go.mod index f02c3c013952d..12f534bd42624 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,7 @@ require ( github.com/google/go-cmp v0.5.9 github.com/google/uuid v1.3.1 github.com/hashicorp/go-azure-helpers v0.64.0 - github.com/hashicorp/go-azure-sdk v0.20231129.1103252 + github.com/hashicorp/go-azure-sdk v0.20231129.1170310-0.20231129211023-ba3d6f4db55b github.com/hashicorp/go-hclog v1.5.0 github.com/hashicorp/go-multierror v1.1.1 github.com/hashicorp/go-uuid v1.0.3 diff --git a/go.sum b/go.sum index cc28bb6a85fe2..577fcdb974aae 100644 --- a/go.sum +++ b/go.sum @@ -113,8 +113,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.64.0 h1:JNTt0F7tbApmpmF9hzNq2TN1lduOiXJFkMFoAPVctK8= github.com/hashicorp/go-azure-helpers v0.64.0/go.mod h1:ELmZ65vzHJNTk6ml4jsPD+xq2gZb7t78D35s+XN02Kk= -github.com/hashicorp/go-azure-sdk v0.20231129.1103252 h1:H5SzxFYj++yIwN4o3WeEz0qMDFDOGeQt+H/j0yyhhz8= -github.com/hashicorp/go-azure-sdk v0.20231129.1103252/go.mod h1:MfF4SCtGLaSP7OeJk+Y3xd4MQL5tFbz31c+ERP1S9D0= +github.com/hashicorp/go-azure-sdk v0.20231129.1170310-0.20231129211023-ba3d6f4db55b h1:WXjbGiJ2JgE6i0niH94gxo85TahrIIGaotl5Du9y3zY= +github.com/hashicorp/go-azure-sdk v0.20231129.1170310-0.20231129211023-ba3d6f4db55b/go.mod h1:b5nMCVXXrqnjFGBmtpJZ0lFvghDm+FiuWmjjAMFu6Ug= 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/azure_cli_authorizer.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/auth/azure_cli_authorizer.go index 21de3aaa457a4..e82b8040d41fa 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 @@ -5,7 +5,6 @@ package auth import ( "context" - "errors" "fmt" "net/http" "os" @@ -58,13 +57,10 @@ func (a *AzureCliAuthorizer) Token(_ context.Context, _ *http.Request) (*oauth2. return nil, fmt.Errorf("could not request token: conf is nil") } + var err error + azArgs := []string{"account", "get-access-token"} - // verify that the Azure CLI supports MSAL - ADAL is no longer supported - err := azurecli.CheckAzVersion(azurecli.MsalVersion, nil) - if err != nil { - return nil, fmt.Errorf("checking the version of the Azure CLI: %+v", err) - } scope, err := environments.Scope(a.conf.Api) if err != nil { return nil, fmt.Errorf("determining scope for %q: %+v", a.conf.Api.Name(), err) @@ -78,7 +74,7 @@ func (a *AzureCliAuthorizer) Token(_ context.Context, _ *http.Request) (*oauth2. } var token azureCliToken - if err := azurecli.JSONUnmarshalAzCmd(&token, azArgs...); err != nil { + if err = azurecli.JSONUnmarshalAzCmd(false, &token, azArgs...); err != nil { return nil, err } @@ -113,12 +109,8 @@ func (a *AzureCliAuthorizer) AuxiliaryTokens(_ context.Context, _ *http.Request) } azArgs := []string{"account", "get-access-token"} + var err error - // verify that the Azure CLI supports MSAL - ADAL is no longer supported - err := azurecli.CheckAzVersion(AzureCliMsalVersion, nil) - if err != nil { - return nil, fmt.Errorf("checking the version of the Azure CLI: %+v", err) - } scope, err := environments.Scope(a.conf.Api) if err != nil { return nil, fmt.Errorf("determining scope for %q: %+v", a.conf.Api.Name(), err) @@ -130,7 +122,7 @@ func (a *AzureCliAuthorizer) AuxiliaryTokens(_ context.Context, _ *http.Request) argsWithTenant := append(azArgs, "--tenant", tenantId) var token azureCliToken - if err := azurecli.JSONUnmarshalAzCmd(&token, argsWithTenant...); err != nil { + if err = azurecli.JSONUnmarshalAzCmd(false, &token, argsWithTenant...); err != nil { return nil, err } @@ -145,7 +137,6 @@ func (a *AzureCliAuthorizer) AuxiliaryTokens(_ context.Context, _ *http.Request) const ( AzureCliMinimumVersion = "2.0.81" - AzureCliMsalVersion = "2.30.0" AzureCliNextMajorVersion = "3.0.0" ) @@ -161,31 +152,33 @@ type azureCliConfig struct { // DefaultSubscriptionID is the optional default subscription ID DefaultSubscriptionID string + + // CacheEnabled specifies whether to use module-level caching to speed up idempotent az-cli operations. + CacheEnabled bool } // newAzureCliConfig validates the supplied tenant ID and returns a new azureCliConfig. func newAzureCliConfig(api environments.Api, tenantId string, auxiliaryTenantIds []string) (*azureCliConfig, error) { var err error - // check az-cli version - nextMajor := azurecli.NextMajorVersion - if err = azurecli.CheckAzVersion(azurecli.MinimumVersion, &nextMajor); err != nil { + // check az-cli version, ensure that MSAL is supported + if err = azurecli.CheckAzVersion(); err != nil { return nil, err } // check tenant ID - tenantId, err = azurecli.CheckTenantID(tenantId) - if err != nil { + if defaultTenantId, err := azurecli.CheckTenantID(tenantId); err != nil { return nil, err - } - if tenantId == "" { - return nil, errors.New("invalid tenantId or unable to determine tenantId") + } else if defaultTenantId != nil { + tenantId = *defaultTenantId } // get the default subscription ID - subscriptionId, err := azurecli.GetDefaultSubscriptionID() - if err != nil { + var subscriptionId string + if defaultSubscriptionId, err := azurecli.GetDefaultSubscriptionID(); err != nil { return nil, err + } else if defaultSubscriptionId != nil { + subscriptionId = *defaultSubscriptionId } return &azureCliConfig{ 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 09896637dc314..e5e59cb85724f 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 @@ -7,6 +7,7 @@ import ( "bytes" "encoding/json" "fmt" + "log" "os/exec" "regexp" "strings" @@ -15,41 +16,29 @@ import ( ) // CheckAzVersion tries to determine the version of Azure CLI in the path and checks for a compatible version -func CheckAzVersion(minVersion string, nextMajorVersion *string) error { - var cliVersion *struct { - AzureCli *string `json:"azure-cli,omitempty"` - AzureCliCore *string `json:"azure-cli-core,omitempty"` - AzureCliTelemetry *string `json:"azure-cli-telemetry,omitempty"` - Extensions *interface{} `json:"extensions,omitempty"` - } - err := JSONUnmarshalAzCmd(&cliVersion, "version") +func CheckAzVersion() error { + currentVersion, err := getAzVersion() if err != nil { - return fmt.Errorf("could not parse Azure CLI version: %v", err) - } - - if cliVersion.AzureCli == nil { - return fmt.Errorf("could not detect Azure CLI version. Please ensure you have installed Azure CLI version %s or newer", minVersion) + return err } - actual, err := version.NewVersion(*cliVersion.AzureCli) + actual, err := version.NewVersion(*currentVersion) if err != nil { - return fmt.Errorf("could not parse detected Azure CLI version %q: %+v", *cliVersion.AzureCli, err) + return fmt.Errorf("could not parse detected Azure CLI version %q: %+v", *currentVersion, err) } - supported, err := version.NewVersion(minVersion) + supported, err := version.NewVersion(MinimumVersion) if err != nil { return fmt.Errorf("could not parse supported Azure CLI version: %+v", err) } - if nextMajorVersion != nil { - nextMajor, err := version.NewVersion(*nextMajorVersion) - if err != nil { - return fmt.Errorf("could not parse next major Azure CLI version: %+v", err) - } + nextMajor, err := version.NewVersion(NextMajorVersion) + if err != nil { + return fmt.Errorf("could not parse next major Azure CLI version: %+v", err) + } - if nextMajor.LessThanOrEqual(actual) { - return fmt.Errorf("unsupported Azure CLI version %q detected, please install a version newer than %s but older than %s", actual, supported, nextMajor) - } + if nextMajor.LessThanOrEqual(actual) { + return fmt.Errorf("unsupported Azure CLI version %q detected, please install a version newer than %s but older than %s", actual, supported, nextMajor) } if actual.LessThan(supported) { @@ -59,24 +48,11 @@ 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) { +func CheckTenantID(tenantId string) (*string, error) { validTenantId, err := regexp.MatchString("^[a-zA-Z0-9._-]+$", tenantId) if err != nil { - return "", fmt.Errorf("could not parse tenant ID %q: %s", tenantId, err) + return nil, fmt.Errorf("could not parse tenant ID %q: %s", tenantId, err) } if !validTenantId { @@ -84,45 +60,96 @@ func CheckTenantID(tenantId string) (string, error) { ID string `json:"id"` TenantID string `json:"tenantId"` } - err := JSONUnmarshalAzCmd(&account, "account", "show") - if err != nil { - return "", fmt.Errorf("obtaining tenant ID: %s", err) + if err = JSONUnmarshalAzCmd(true, &account, "account", "show"); err != nil { + return nil, fmt.Errorf("obtaining tenant ID: %s", err) } tenantId = account.TenantID } - return tenantId, nil + return &tenantId, nil +} + +// GetDefaultSubscriptionID tries to determine the default subscription +func GetDefaultSubscriptionID() (*string, error) { + var account struct { + SubscriptionID string `json:"id"` + } + err := JSONUnmarshalAzCmd(true, &account, "account", "show") + if err != nil { + return nil, fmt.Errorf("obtaining subscription ID: %s", err) + } + + return &account.SubscriptionID, nil +} + +// getAzVersion tries to determine the version of Azure CLI in the path. +func getAzVersion() (*string, error) { + var cliVersion *struct { + AzureCli *string `json:"azure-cli,omitempty"` + AzureCliCore *string `json:"azure-cli-core,omitempty"` + AzureCliTelemetry *string `json:"azure-cli-telemetry,omitempty"` + Extensions *interface{} `json:"extensions,omitempty"` + } + err := JSONUnmarshalAzCmd(true, &cliVersion, "version") + if err != nil { + return nil, fmt.Errorf("could not parse Azure CLI version: %v", err) + } + + if cliVersion.AzureCli == nil { + return nil, fmt.Errorf("could not detect Azure CLI version") + } + + return cliVersion.AzureCli, nil } // JSONUnmarshalAzCmd executes an Azure CLI command and unmarshalls the JSON output. -func JSONUnmarshalAzCmd(i interface{}, arg ...string) error { +func JSONUnmarshalAzCmd(cacheable bool, i interface{}, arg ...string) error { var stderr bytes.Buffer var stdout bytes.Buffer arg = append(arg, "-o=json") - cmd := exec.Command("az", arg...) - cmd.Stderr = &stderr - cmd.Stdout = &stdout - - if err := cmd.Start(); err != nil { - err := fmt.Errorf("launching Azure CLI: %+v", err) - if stdErrStr := stderr.String(); stdErrStr != "" { - err = fmt.Errorf("%s: %s", err, strings.TrimSpace(stdErrStr)) + argstring := strings.Join(arg, " ") + + var result []byte + if cacheable { + if cachedResult, ok := cache.Get(argstring); ok { + result = cachedResult } - return err } - if err := cmd.Wait(); err != nil { - err := fmt.Errorf("running Azure CLI: %+v", err) - if stdErrStr := stderr.String(); stdErrStr != "" { - err = fmt.Errorf("%s: %s", err, strings.TrimSpace(stdErrStr)) + if result == nil { + log.Printf("[DEBUG] az-cli invocation: az %s", argstring) + + cmd := exec.Command("az", arg...) + cmd.Stderr = &stderr + cmd.Stdout = &stdout + + if err := cmd.Start(); err != nil { + err := fmt.Errorf("launching Azure CLI: %+v", err) + if stdErrStr := stderr.String(); stdErrStr != "" { + err = fmt.Errorf("%s: %s", err, strings.TrimSpace(stdErrStr)) + } + return err } - return err + + if err := cmd.Wait(); err != nil { + err := fmt.Errorf("running Azure CLI: %+v", err) + if stdErrStr := stderr.String(); stdErrStr != "" { + err = fmt.Errorf("%s: %s", err, strings.TrimSpace(stdErrStr)) + } + return err + } + + result = stdout.Bytes() } - if err := json.Unmarshal(stdout.Bytes(), &i); err != nil { + if err := json.Unmarshal(result, &i); err != nil { return fmt.Errorf("unmarshaling the output of Azure CLI: %v", err) } + if cacheable { + cache.Set(argstring, result) + } + return nil } diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/cache.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/cache.go new file mode 100644 index 0000000000000..93e645d460b79 --- /dev/null +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/cache.go @@ -0,0 +1,24 @@ +package azurecli + +var cache *cachedCliData + +type cachedCliData struct { + data map[string][]byte +} + +func (c *cachedCliData) Set(index string, data []byte) { + c.data[index] = data +} + +func (c *cachedCliData) Get(index string) ([]byte, bool) { + if data, ok := c.data[index]; ok { + return data, true + } + return nil, false +} + +func init() { + cache = &cachedCliData{ + data: make(map[string][]byte), + } +} diff --git a/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/versions.go b/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/versions.go index 6fb0fac8bc895..ccbe084a8ffb5 100644 --- a/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/versions.go +++ b/vendor/github.com/hashicorp/go-azure-sdk/sdk/internal/azurecli/versions.go @@ -4,7 +4,12 @@ package azurecli const ( - MinimumVersion = "2.0.81" - MsalVersion = "2.30.0" + // MsalVersion is the first known version of Azure CLI to support MSAL / v2 tokens + MsalVersion = "2.30.0" + + // MinimumVersion is the oldest supported version of Azure CLI by this package + MinimumVersion = "2.0.81" + + // NextMajorVersion is the next (possibly upcoming) major version that is not yet supported by this package NextMajorVersion = "3.0.0" ) diff --git a/vendor/modules.txt b/vendor/modules.txt index 68967fbdd4a4d..5b37623c33c00 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -158,7 +158,7 @@ github.com/hashicorp/go-azure-helpers/resourcemanager/tags github.com/hashicorp/go-azure-helpers/resourcemanager/zones github.com/hashicorp/go-azure-helpers/sender github.com/hashicorp/go-azure-helpers/storage -# github.com/hashicorp/go-azure-sdk v0.20231129.1103252 +# github.com/hashicorp/go-azure-sdk v0.20231129.1170310-0.20231129211023-ba3d6f4db55b ## explicit; go 1.21 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