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]
| Option | Applies to | Description |
|---|---|---|
--provider aws|azure|gcp|lambda|cloudflare | new | Select the provider without the interactive picker |
--profile NAME | new | AWS profile to import, or authenticated operator profile with --generate |
--account-id ID | new | Required target AWS account with --generate, or the Cloudflare account ID |
--generate | new | Explicitly create AWS, Azure, or GCP credentials using an authenticated provider CLI |
--gcloud-account EMAIL | new | Select the cached gcloud operator account for GCP generation |
--overwrite | new | Replace an existing credential with the same name |
--access-key-id, --secret-access-key | new,edit | Set AWS fields |
--application-id, --secret | new,edit | Set Azure application fields |
--subscription-id, --directory-id | new,edit | Set Azure account fields |
--project-id, --client-email | new,edit | Set GCP service-account fields |
--private-key | new,edit | Set the GCP service-account private key |
--key-file PATH | edit | Read replacement GCP service-account fields from a JSON key file |
--api-key | new,edit | Set a Lambda Labs key |
--api-token, --jurisdiction | new,edit | Set the Cloudflare API token and R2 jurisdiction (default, eu or fedramp) |
--json | list | [{name, cloudProvider, health, invalidSince?}]; never includes secret values |
-f, --force | delete | Delete 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 exactly two
subscription-scoped controller assignments: Contributor and User Access
Administrator. Controller Blob operations use a current account key fetched
through listKeys; the controller does not receive a subscription-wide Blob
data role.
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, and Cloud Storage APIs beforehand; the project's default Compute service account must already exist. The operator needs permission to inspect the project and service accounts, create service accounts and keys, update project and default Compute service-account IAM policies, 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, plus roles/iam.serviceAccountUser on the default
Compute service account. These controller grants do not give the VM service
account access to workload buckets.
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:
| Provider | Credentials to send you | Or permission to create them |
|---|---|---|
| AWS | Access keys for a dedicated Anycloud IAM user with AnycloudAccess | Create IAM users, add inline policies, and create access keys (operator permissions) |
| Azure | A service principal's application ID, secret, subscription ID, and tenant ID | Create Entra applications and assign roles on the subscription |
| GCP | A JSON key for a dedicated Anycloud service account | Create 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.
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.
{
"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:ListAllMyBucketsto its own statement on*, and replace theBucketsstatement'sResourcewith the Buckets Anycloud may use, for examplearn:aws:s3:::team-ml-*andarn: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
Computestatement in two. Keep theec2:Describe*actions unconditioned, because Anycloud reads every enabled region, for example to find a cluster's VMs when restoring it. Put theaws:RequestedRegioncondition only on the actions that change resources. Jobs without--regionthen 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.
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. Each read allows up to three attempts within 60 seconds,
including command execution and backoff. Authentication, permission, and
ownership failures stop immediately. IAM writes are sent once, including
cleanup writes. 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, storage, and controller-managed role-assignment
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.