{"record":{"id":"ea90b0c6b6bbc831","repo":"hashicorp/terraform","slug":"retrieving-key-for-storage-account-q-s","errorCode":null,"errorMessage":"retrieving key for Storage Account %q: %s","messagePattern":"retrieving key for Storage Account %q: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/azure/api_client.go","lineNumber":184,"sourceCode":"\t\tlog.Printf(\"[DEBUG] Building the Blob Client from an Access Key\")\n\t\tauthorizer, err := auth.NewSharedKeyAuthorizer(c.storageAccountName, c.accessKey, auth.SharedKey)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"new shared key authorizer: %v\", err)\n\t\t}\n\t\tc.configureClient(blobsClient.Client, authorizer)\n\t\treturn blobsClient, nil\n\n\tcase c.azureAdStorageAuth != nil:\n\t\tlog.Printf(\"[DEBUG] Building the Blob Client from AAD auth\")\n\t\tc.configureClient(blobsClient.Client, c.azureAdStorageAuth)\n\t\treturn blobsClient, nil\n\n\tdefault:\n\t\t// Neither shared access key, sas token, or AAD Auth were specified so we have to call the management plane API to get the key.\n\t\tlog.Printf(\"[DEBUG] Building the Blob Client from an Access Key (key is listed using client credentials)\")\n\t\tkey, err := c.accountDetail.AccountKey(ctx, c.storageAccountsClient)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"retrieving key for Storage Account %q: %s\", c.storageAccountName, err)\n\t\t}\n\t\tauthorizer, err := auth.NewSharedKeyAuthorizer(c.storageAccountName, *key, auth.SharedKey)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"new shared key authorizer: %v\", err)\n\t\t}\n\t\tc.configureClient(blobsClient.Client, authorizer)\n\t\treturn blobsClient, nil\n\t}\n}\n\nfunc (c *Client) getContainersClient(ctx context.Context) (cc *containers.Client, err error) {\n\tif c.containersClient != nil {\n\t\treturn c.containersClient, nil\n\t}\n\n\tdefer func() {\n\t\tif err == nil {\n\t\t\tc.containersClient = cc","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/backend/remote-state/azure/api_client.go#L166-L202","documentation":"Thrown by getBlobClient in the default branch (no access_key, no sas, no aad) when c.accountDetail.AccountKey(ctx, storageAccountsClient) fails. AccountKey calls the ARM storageAccounts.ListKeys API and extracts a Full-permission key; failure means the ARM call failed (permissions, network, throttling) or no Full-permission key was returned.","triggerScenarios":"Default auth path (CLI/principal with no explicit data-plane creds). (a) The identity lacks Microsoft.Storage/storageAccounts/listKeys/action. (b) ListKeys returned keys but none has KeyPermission == Full. (c) ARM throttled or network failed.","commonSituations":"Service principal or managed identity with only Reader / Contributor-via-other-scope role; cross-tenant access where the principal cannot list keys; subscription throttling on busy accounts; key regeneration left the account in a transitional state.","solutions":["Grant the principal Storage Account Contributor (or the narrower Storage Account Key Operator Service role) on the account.","Switch to use_azuread_auth = true (recommended modern path) to avoid the key-list entirely.","Provide access_key directly.","Retry for transient ARM throttling; check Azure status for region incidents."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Pre-flight: verify the principal can list storage keys before configuring the backend.\n// (Requires az login or an authenticated SDK client.)\nfunc canListKeys(ctx context.Context, sub, rg, acct string) error {\n    // use az CLI as the simplest check\n    cmd := exec.CommandContext(ctx, \"az\", \"storage\", \"account\", \"keys\", \"list\", \"-g\", rg, \"-n\", acct, \"--query\", \"[0].value\", \"-o\", \"tsv\")\n    out, err := cmd.Output()\n    if err != nil { return fmt.Errorf(\"cannot list keys: %w (stderr: %s)\", err, out) }\n    if len(strings.TrimSpace(string(out))) == 0 { return fmt.Errorf(\"listed key was empty\") }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// If you must call getBlobClient directly, retry once on the list-keys failure (transient throttling).\nvar blob *blobs.Client\nerr := backoff.Retry(func() error {\n    b, err := apiClient.GetBlobClient(ctx)\n    if err != nil && strings.Contains(err.Error(), \"retrieving key for Storage Account\") {\n        return err // retryable\n    }\n    if err != nil { return backoff.Permanent(err) }\n    blob = b\n    return nil\n}, backoff.WithMaxRetries(backoff.NewExponentialBackOff(), 3))","preventionTips":["Grant the principal Storage Account Key Operator Service (least privilege) or Storage Account Contributor.","Use use_azuread_auth = true to sidestep the listKeys path.","In CI, run a `az role assignment list` smoke test before terraform init."],"tags":["azure","arm","rbac","storage-account","authentication","permissions"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}