Skip to main content

anycloud credentials

Manage named provider credentials. Alias: anycloud creds.

anycloud credentials new [name] [provider options]
anycloud credentials list [--json]
anycloud credentials edit <name> [provider options]
anycloud credentials delete [name] [--force]
OptionApplies toDescription
--provider aws|azure|gcp|lambda|cloudflarenewSelect the provider without the interactive picker
--profile NAMEnewAWS profile to import, or authenticated operator profile with --generate
--account-id IDnewRequired target AWS account with --generate, or the Cloudflare account ID
--generatenewExplicitly create AWS, Azure, or GCP credentials using an authenticated provider CLI
--gcloud-account EMAILnewSelect the cached gcloud operator account for GCP generation
--overwritenewReplace an existing credential with the same name
--access-key-id, --secret-access-keynew,editSet AWS fields
--application-id, --secretnew,editSet Azure application fields
--subscription-id, --directory-idnew,editSet Azure account fields
--project-id, --client-emailnew,editSet GCP service-account fields
--private-keynew,editSet the GCP service-account private key
--key-file PATHeditRead replacement GCP service-account fields from a JSON key file
--api-keynew,editSet a Lambda Labs key
--api-token, --jurisdictionnew,editSet the Cloudflare API token and R2 jurisdiction (default, eu or fedramp)
--jsonlist[{name, cloudProvider, health, invalidSince?}]; never includes secret values
-f, --forcedeleteDelete even when a non-terminal workload references the credential

With missing provider arguments in a terminal, new opens a wizard. Provider flows can import local credentials, accept pasted values, or generate AWS, Azure, and GCP credentials.

Wizard imports ask you to choose a source whenever local or environment credentials are available, even if only one source was detected. Complete environment credentials are highlighted first. Manual entry asks for fresh values; GCP asks for a service-account JSON file.

Before saving, the wizard shows the source and available account identifiers, then asks Save these <provider> credentials as "<name>"?. The default is Yes. Declining or pressing Ctrl-C at that prompt saves nothing. Secrets stay hidden. AWS authenticates the account and identity through STS. GCP and Azure reviews show identifiers supplied in the credentials. Lambda reviews show the provider, source, and credential name.

Explicit complete credential flags, AWS --profile, and non-interactive imports do not add a source picker or save confirmation. Existing AWS and Azure partial-field completion still uses flags and environment fallbacks, then asks for confirmation when interactive.

Choosing generation in the wizard previews the target and grants, then asks for confirmation. Passing --generate authorizes creation without another confirmation prompt, even in a terminal.

Generation uses an authenticated provider CLI. Reuse a working login or sign in first. --generate cannot be combined with credential-material flags or --overwrite. Anycloud never installs provider CLIs. When one is missing, the wizard prints a per-user install command that needs no sudo and still offers the other choices.

The AWS, Azure, and GCP pickers end with an option for people who have neither credentials nor permission to create them, such as I don't have AWS access keys. It prints a request to forward to your cloud administrator and saves nothing; see Ask an administrator.

Secret provider fields accept their documented environment fallbacks; an explicit CLI flag wins when creating credentials. edit uses explicit flags only.

edit requires an existing name and updates only the provider fields supplied as flags; it does not open a wizard or change the provider. The API merges those fields into the stored credential, so saved secrets never leave it. A flag for another provider's field fails and leaves the credential unchanged. delete without a name opens a picker in a terminal. Deletion is blocked while a non-terminal workload references the credential unless --force is supplied.

Non-interactive provider fields​

AWS​

# Enter existing keys
anycloud credentials new production-aws \
--provider aws \
--access-key-id AKIA... \
--secret-access-key ...

# Import durable keys from a named AWS profile
anycloud credentials new production-aws \
--provider aws \
--profile production

# Generate a new IAM user/key through an authenticated AWS operator
anycloud credentials new production-aws \
--provider aws --generate \
--profile operator --account-id 123456789012

Importable profiles must contain a durable access-key ID and secret in the shared credentials or config file. When credentials are detected, the wizard asks you to choose a source, even when only one profile is available. It offers durable profiles, complete durable environment keys, and manual entry. Environment keys are highlighted first; otherwise the current or default profile is highlighted. AWS_PROFILE sets a default selection without authorizing an import. Manual entry from this picker asks for fresh keys instead of reusing environment values. SSO, role, web-identity, credential-process, and session-token profiles cannot be imported because their credentials rotate or expire; the API also refuses to save an AWS credential with a session token.

Before saving imported, pasted, or environment-provided AWS keys, Anycloud calls STS with those exact keys. This proves their identity, not broad EC2, S3, IAM, quota, or organization-policy access.

Anycloud attaches no IAM role to the VMs it launches. Everything an imported key needs is in the AnycloudAccess policy. A key that may use EC2 in only some regions runs Jobs in those regions (see Cloud Credentials).

Wizard imports show the source, authenticated account ID, and identity ARN, then ask for confirmation before saving. The default is Yes; declining or pressing Ctrl-C saves nothing. Partial key flags also receive this confirmation after their missing fields are completed. Explicit --profile, both access-key flags together, and non-interactive commands authorize the import without a confirmation prompt.

Generation uses the selected operator profile and requires both --profile and --account-id; an account mismatch fails before creation. A working profile needs no new sign-in. To authenticate through the browser, run aws login --profile operator with AWS CLI 2.32.0 or newer. Static keys in that profile can shadow the login session. Anycloud does not launch AWS sign-in for you.

When the AWS CLI is installed, the source picker also offers Create an IAM user with AWS CLI, including when existing credentials are available. Without it, the wizard prints the official per-user installer, even when profiles or environment keys are available: curl -fsSL https://awscli.amazonaws.com/v2/install.sh | bash, or irm https://awscli.amazonaws.com/v2/install.ps1 | iex on Windows. The picker still offers detected credentials, manual entry, and the administrator request. Failed imports never trigger generation automatically. Choosing generation lists every profile in ~/.aws/config and ~/.aws/credentials, including SSO profiles, as the operator; the current profile is highlighted.

The new IAM user, anycloud-<credential-name>, receives one inline policy, AnycloudAccess, and nothing else. The operator needs the operator permissions listed below.

For a comparison of the AWS paths, see Ways to add AWS credentials.

Generation names use 1–55 letters, digits, or _+=,.@- characters. Generation cannot overwrite an existing credential or IAM user.

Azure​

# Azure service principal
anycloud credentials new production-azure \
--provider azure \
--application-id ... \
--secret ... \
--subscription-id ... \
--directory-id ...

# Create an Azure service principal through an authenticated Azure CLI
anycloud credentials new production-azure \
--provider azure \
--generate

Azure CLI user sessions cannot reveal an existing service-principal secret. The wizard offers complete environment credentials, Enter existing service principal credentials, and Create a service principal with Azure CLI. Environment values never bypass this choice. Before saving an import, review the tenant, subscription, and application ID. Without the Azure CLI, choosing creation prints an install hint: brew install azure-cli on macOS, winget install --exact --id Microsoft.AzureCLI on Windows, and Microsoft's Linux install page, whose packages need administrator rights. For explicit generation, authenticate with az login if needed; use --subscription-id to select a subscription or reuse the Azure CLI's current subscription.

The preview identifies the tenant, subscription, scope, and grants. Generation creates an application, service principal, client secret, and one subscription-scoped Contributor assignment. Azure VMs get no managed identity, so generation assigns no role-administration role. Controller Blob operations use a current account key fetched through listKeys; the controller does not receive a subscription-wide Blob data role. An imported service principal needs only the Anycloud role on its subscription.

GCP​

# GCP service account
anycloud credentials new production-gcp \
--provider gcp \
--project-id my-project \
--client-email service-account@my-project.iam.gserviceaccount.com \
--private-key "..."

# Generate a service account/key through an authenticated gcloud operator
anycloud credentials new production-gcp \
--provider gcp --generate \
--gcloud-account operator@example.com --project-id my-project

Import accepts service-account fields or a key JSON file discovered through GOOGLE_APPLICATION_CREDENTIALS, the conventional Application Default Credentials (ADC) path, or ~/.anycloud. A gcloud user login or user ADC cannot be imported and never triggers generation automatically.

The wizard also offers complete GCP_PROJECT_ID, GCP_CLIENT_EMAIL, and GCP_PRIVATE_KEY environment credentials. File selection and generation stay available alongside detected credentials. Review the project and service-account email before approving an import. An uploaded key is copied to the Anycloud directory only after approval, using the same contents that were reviewed.

Generation uses the selected cached gcloud account. Without gcloud, generation prints Google's per-user installer, curl https://sdk.cloud.google.com | bash, or its Windows installer page. Run gcloud auth login if needed, then choose Create a service account with gcloud in the wizard or pass --generate with both --gcloud-account and --project-id.

Enable the IAM, Cloud Resource Manager, Compute Engine, Cloud Storage, and Security Token Service APIs beforehand. The operator needs permission to inspect the project and service accounts, create service accounts and keys, update the project IAM policy, and delete the created resources for cleanup.

The new service account, anycloud-<credential-name>, receives project roles roles/compute.instanceAdmin.v1, roles/compute.securityAdmin, and roles/storage.admin. Anycloud attaches no service account to its VMs, so it needs no grant on the default Compute service account. An administrator can grant the narrower Anycloud role instead.

Generation names use 1–21 lowercase letters, digits, or hyphens, ending in a letter or digit. Generation cannot overwrite an existing credential or service account.

Lambda​

When LAMBDA_API_KEY is set, choose whether to use it or enter a fresh key. Without an environment key, the wizard prompts directly for masked entry. Both paths ask for confirmation before saving.

anycloud credentials new production-lambda \
--provider lambda \
--api-key ...

Cloudflare​

Cloudflare credentials hold R2 storage only: bucket commands use them, and every compute command refuses them. They are never picked automatically. Pass --provider cloudflare; the token is not detected from CLOUDFLARE_API_TOKEN alone. The token needs account-level R2 read and write. Before saving, new checks with Cloudflare that the token is active.

anycloud credentials new r2 \
--provider cloudflare \
--account-id ... \
--api-token ...

With --provider cloudflare, missing flags fall back to CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_API_TOKEN.

Ask an administrator​

Anycloud needs a dedicated identity in your cloud account. If you can't create one, ask whoever administers the account for either of these:

ProviderCredentials to send youOr permission to create them
AWSAccess keys for a dedicated Anycloud IAM user with AnycloudAccessCreate IAM users, add inline policies, and create access keys (operator permissions)
AzureThe application ID, secret, subscription ID, and tenant ID for a service principal with Contributor or the Anycloud roleCreate Entra applications and assign roles on the subscription
GCPA JSON key for a dedicated Anycloud service account with the Anycloud roleCreate service accounts and keys, and grant project IAM roles

The identity needs the grants listed for generation under its provider above. With credentials, rerun anycloud credentials new and enter them. With permission, rerun it and choose the create option.

When generation fails because the operator lacks permission, the error ends with the same request, naming the operator identity when Anycloud knows it.

When a saved credential is valid but the cloud refuses it an action, the Job ends invalid with a "Permission denied" message, or the submission is rejected with it. The message names the cloud, the denied action and where it was denied, such as ec2:RunInstances in us-east-1. On AWS it also points to the AnycloudAccess policy. Send it to your administrator. On AWS, when the denial is limited to a region (an EC2 action), a Job without --region first tries the other regions that offer its VM type, and ends invalid only when every region refuses it.

AWS permissions​

AnycloudAccess is everything Anycloud does with an AWS key: launch, recover and terminate VMs, create and delete Buckets, mint the short-lived token each VM syncs a Bucket with, and read regions, quotas and costs. It grants no IAM action except creating the Spot service-linked role: AWS creates AWSServiceRoleForEC2Spot automatically only for a console request, and asks API callers to make sure it exists (AWS documentation). The condition limits that statement to that one role. --generate adds this policy inline; an administrator can do the same with aws iam put-user-policy --user-name anycloud-<name> --policy-name AnycloudAccess --policy-document file://aws-anycloud-access.json.

aws-anycloud-access.json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Compute",
"Effect": "Allow",
"Action": [
"ec2:DescribeImages",
"ec2:DescribeInstances",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSpotInstanceRequests",
"ec2:DescribeVolumes",
"ec2:DescribeVpcs",
"ec2:RunInstances",
"ec2:StartInstances",
"ec2:TerminateInstances",
"ec2:CreateTags",
"ec2:CancelSpotInstanceRequests",
"ec2:CreateSecurityGroup",
"ec2:AuthorizeSecurityGroupIngress",
"ec2:RevokeSecurityGroupIngress",
"ec2:DeleteSecurityGroup",
"ec2:DeleteNetworkInterface",
"ec2:DeleteVolume"
],
"Resource": "*"
},
{
"Sid": "Buckets",
"Effect": "Allow",
"Action": [
"s3:ListAllMyBuckets",
"s3:CreateBucket",
"s3:DeleteBucket",
"s3:ListBucket",
"s3:ListBucketVersions",
"s3:GetBucketLocation",
"s3:GetBucketTagging",
"s3:PutBucketTagging",
"s3:GetBucketVersioning",
"s3:PutBucketVersioning",
"s3:PutBucketPublicAccessBlock",
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject",
"s3:DeleteObjectVersion",
"s3:AbortMultipartUpload"
],
"Resource": "*"
},
{
"Sid": "BucketTokens",
"Effect": "Allow",
"Action": "sts:GetFederationToken",
"Resource": "*"
},
{
"Sid": "RegionsQuotasCosts",
"Effect": "Allow",
"Action": [
"account:ListRegions",
"servicequotas:GetServiceQuota",
"servicequotas:ListRequestedServiceQuotaChangeHistory",
"ce:GetCostAndUsage"
],
"Resource": "*"
},
{
"Sid": "SpotServiceLinkedRole",
"Effect": "Allow",
"Action": "iam:CreateServiceLinkedRole",
"Resource": "arn:aws:iam::*:role/aws-service-role/spot.amazonaws.com/AWSServiceRoleForEC2Spot",
"Condition": {
"StringEquals": {
"iam:AWSServiceName": "spot.amazonaws.com"
}
}
}
]
}

An administrator can narrow it further:

  • Buckets: move s3:ListAllMyBuckets to its own statement on *, and replace the Buckets statement's Resource with the Buckets Anycloud may use, for example arn:aws:s3:::team-ml-* and arn:aws:s3:::team-ml-*/*. Buckets Anycloud names for you, such as a spot Job's checkpoint Bucket, fall outside such a prefix, so name every Bucket explicitly.

  • Regions: split the Compute statement in two. Keep the ec2:Describe* actions unconditioned, because Anycloud reads every enabled region, for example to find a cluster's VMs when restoring it. Put the aws:RequestedRegion condition only on the actions that change resources. Jobs without --region then run only in those regions; see Cloud Credentials.

    {
    "Sid": "ComputeReads",
    "Effect": "Allow",
    "Action": [
    "ec2:DescribeImages",
    "ec2:DescribeInstances",
    "ec2:DescribeNetworkInterfaces",
    "ec2:DescribeSecurityGroups",
    "ec2:DescribeSpotInstanceRequests",
    "ec2:DescribeVolumes",
    "ec2:DescribeVpcs"
    ],
    "Resource": "*"
    },
    {
    "Sid": "ComputeChanges",
    "Effect": "Allow",
    "Action": [
    "ec2:RunInstances",
    "ec2:StartInstances",
    "ec2:TerminateInstances",
    "ec2:CreateTags",
    "ec2:CancelSpotInstanceRequests",
    "ec2:CreateSecurityGroup",
    "ec2:AuthorizeSecurityGroupIngress",
    "ec2:RevokeSecurityGroupIngress",
    "ec2:DeleteSecurityGroup",
    "ec2:DeleteNetworkInterface",
    "ec2:DeleteVolume"
    ],
    "Resource": "*",
    "Condition": {
    "StringEquals": { "aws:RequestedRegion": ["us-east-1", "us-west-2"] }
    }
    }

If your account encrypts EBS volumes by default with a customer-managed KMS key, that key's policy must also let this user and AWSServiceRoleForEC2Spot use it. The AWS-managed aws/ebs key needs nothing.

AWS operator permissions​

To let someone run --generate instead of handing them keys, grant their profile these actions. Anycloud creates users only under anycloud-:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:CreateUser",
"iam:TagUser",
"iam:GetUser",
"iam:ListUserTags",
"iam:PutUserPolicy",
"iam:CreateAccessKey",
"iam:DeleteAccessKey",
"iam:DeleteUserPolicy",
"iam:DeleteUser"
],
"Resource": "arn:aws:iam::*:user/anycloud-*"
}
]
}

The delete actions are used only to clean up after a failed generation.

Azure permissions​

The Anycloud role is everything Anycloud does with an Azure service principal: launch, recover and delete VMs and their networks, create the storage account and its Buckets, read the account key that signs each VM's Bucket token, and read regions, quotas and costs. Azure VMs get no managed identity, so the role grants no role-assignment or identity action. Contributor also covers it.

To create it, replace <subscription-id> in AssignableScopes, then run az role definition create --role-definition azure-anycloud-role.json and az role assignment create --assignee <application-id> --role Anycloud --scope /subscriptions/<subscription-id>.

azure-anycloud-role.json
{
"Name": "Anycloud",
"IsCustom": true,
"Description": "What Anycloud needs to run Jobs, Services and VMs and to manage their Buckets in one subscription. See https://anycloud.sh/reference/cli/credentials",
"Actions": [
"Microsoft.Compute/disks/delete",
"Microsoft.Compute/disks/read",
"Microsoft.Compute/disks/write",
"Microsoft.Compute/locations/communityGalleries/images/versions/read",
"Microsoft.Compute/locations/publishers/artifacttypes/offers/skus/versions/read",
"Microsoft.Compute/locations/usages/read",
"Microsoft.Compute/register/action",
"Microsoft.Compute/skus/read",
"Microsoft.Compute/virtualMachines/delete",
"Microsoft.Compute/virtualMachines/read",
"Microsoft.Compute/virtualMachines/start/action",
"Microsoft.Compute/virtualMachines/write",
"Microsoft.CostManagement/query/action",
"Microsoft.CostManagement/query/read",
"Microsoft.Network/networkInterfaces/delete",
"Microsoft.Network/networkInterfaces/join/action",
"Microsoft.Network/networkInterfaces/read",
"Microsoft.Network/networkInterfaces/write",
"Microsoft.Network/networkSecurityGroups/delete",
"Microsoft.Network/networkSecurityGroups/join/action",
"Microsoft.Network/networkSecurityGroups/read",
"Microsoft.Network/networkSecurityGroups/write",
"Microsoft.Network/publicIPAddresses/delete",
"Microsoft.Network/publicIPAddresses/join/action",
"Microsoft.Network/publicIPAddresses/read",
"Microsoft.Network/publicIPAddresses/write",
"Microsoft.Network/register/action",
"Microsoft.Network/virtualNetworks/delete",
"Microsoft.Network/virtualNetworks/read",
"Microsoft.Network/virtualNetworks/subnets/join/action",
"Microsoft.Network/virtualNetworks/subnets/read",
"Microsoft.Network/virtualNetworks/write",
"Microsoft.Quota/quotaRequests/read",
"Microsoft.Quota/quotas/read",
"Microsoft.Quota/usages/read",
"Microsoft.Resources/subscriptions/providers/read",
"Microsoft.Resources/subscriptions/resourceGroups/read",
"Microsoft.Resources/subscriptions/resourceGroups/write",
"Microsoft.Storage/register/action",
"Microsoft.Storage/storageAccounts/blobServices/read",
"Microsoft.Storage/storageAccounts/blobServices/write",
"Microsoft.Storage/storageAccounts/listkeys/action",
"Microsoft.Storage/storageAccounts/read",
"Microsoft.Storage/storageAccounts/write",
"Microsoft.Support/supportTickets/read"
],
"NotActions": [],
"DataActions": [],
"NotDataActions": [],
"AssignableScopes": [
"/subscriptions/<subscription-id>"
]
}

GCP permissions​

The Anycloud custom role is everything Anycloud does with a GCP service-account key: launch, recover and delete VMs and their firewall rules, create and delete Buckets, and read costs from a Cloud Billing BigQuery export. Anycloud attaches no service account to its VMs, so the role grants no iam.serviceAccounts.actAs. Each VM syncs a Bucket with an access token downscoped from the key to that one Bucket. That needs no further permission, but the project must have the Security Token Service API (sts.googleapis.com) enabled.

An administrator creates the role and grants it to the service account:

gcloud iam roles create anycloud --project=PROJECT_ID --file=gcp-anycloud-role.json
gcloud projects add-iam-policy-binding PROJECT_ID \
--member=serviceAccount:SERVICE_ACCOUNT_EMAIL \
--role=projects/PROJECT_ID/roles/anycloud
gcp-anycloud-role.json
{
"title": "Anycloud",
"description": "Everything Anycloud does with a service-account key: launch and manage VMs, and the Cloud Storage buckets its Jobs and Services use.",
"stage": "GA",
"includedPermissions": [
"bigquery.jobs.create",
"bigquery.tables.getData",
"compute.disks.create",
"compute.disks.delete",
"compute.disks.list",
"compute.disks.setLabels",
"compute.firewalls.create",
"compute.firewalls.delete",
"compute.firewalls.list",
"compute.globalOperations.get",
"compute.images.getFromFamily",
"compute.instances.create",
"compute.instances.delete",
"compute.instances.get",
"compute.instances.list",
"compute.instances.setLabels",
"compute.instances.setMetadata",
"compute.instances.setScheduling",
"compute.instances.setTags",
"compute.instances.start",
"compute.machineTypes.get",
"compute.networks.updatePolicy",
"compute.subnetworks.use",
"compute.subnetworks.useExternalIp",
"compute.zoneOperations.get",
"resourcemanager.projects.get",
"storage.buckets.create",
"storage.buckets.delete",
"storage.buckets.get",
"storage.buckets.list",
"storage.buckets.update",
"storage.objects.create",
"storage.objects.delete",
"storage.objects.get",
"storage.objects.list"
]
}

resourcemanager.projects.get reads the project's number, which a spot node pool's Job checks before it reuses a checkpoint bucket that already has its name.

The two bigquery permissions are needed only for per-VM costs from a billing export; remove them if you don't configure one. Anycloud runs the cost query in the key's project, which needs bigquery.jobs.create, and reads the export table, which needs bigquery.tables.getData where the billing dataset lives. When that dataset is in another project, also grant the service account roles/bigquery.dataViewer on the dataset.

Saving and cleanup​

Generated credentials use the normal encrypted API save flow; provider CLI logins stay local. AWS generation leaves the operator profile unchanged. GCP keeps the new private key in memory until saving and creates no local key file. Saving generated AWS or Azure credentials does not perform a separate readiness wait or probe.

Interrupted generation or uncertain responses can leave identities, keys, or grants requiring manual reconciliation. AWS diagnostics identify the known account and user; GCP diagnostics identify the project, service-account ID, and invocation. Uncertain saves retain the identity. Automatic cleanup only removes resources verified as belonging to that invocation.

AWS generation and cleanup retry transient connection failures, throttling, and temporary service errors in GetCallerIdentity, GetUser, and ListUserTags, and in the cleanup deletes of the access key, inline policy, and user. Each call allows up to three attempts within 60 seconds, including command execution and backoff. A cleanup delete that finds its resource already gone counts as done. Authentication, permission, and ownership failures stop immediately. Other IAM writes are sent once. Failures report the operation, safe error category, attempt count, and elapsed time without exposing credentials or raw CLI output.

Deleting a saved Anycloud credential does not delete its cloud identity, keys, or grants. Existing credentials and provider resources created by older releases remain available.

First-use recovery​

GCP bucket listing, existence checks, creation and deletion, and object upload, download and deletion, retry only the structured OAuth invalid_grant failure with Invalid JWT Signature. or Invalid grant: account not found, at most six attempts with 23 seconds of backoff. A key Google still refuses after that answers the retryable BUCKET_CREDENTIAL_NOT_READY error. Unrelated permission denials remain terminal. Generation also bounds retries for a newly created identity that IAM cannot yet read or definitively rejects in a grant update. Service-account creation, key issuance, and uncertain writes are never automatically repeated.

Azure authorization can still be propagating when a credential is first used. At compute validation and storage operations, the API retries only the specific ARM AuthorizationFailed and Entra AADSTS7000215 shapes. Recovery is capped at nine attempts over 39.5 seconds and refreshes authentication between attempts. It does not depend on credential age, a readiness probe, or a previous success.

An unrelated 403, an expired secret (AADSTS7000222), or a generic invalid_client failure receives no special propagation retry. A persistently broken secret exhausts at most the bounded recovery window and then fails normally.

For selection precedence and storage identities, see Cloud Credentials and Configuration.