Skip to content

AWS setup guide

credctl authenticates to AWS using OIDC federation. It signs a JWT with a hardware-bound Secure Enclave key and exchanges it for short-lived STS credentials via AssumeRoleWithWebIdentity.

This guide covers two approaches:

  1. Automated (recommended) — credctl setup aws does everything in one command
  2. Manual — deploy the infrastructure yourself using Terraform or the AWS Console
sequenceDiagram
participant SE as Secure Enclave
participant CLI as credctl CLI
participant S3 as S3 (OIDC)
participant STS as AWS STS
Note over SE,CLI: One-time setup
CLI->>SE: Generate ECDSA P-256 key pair
SE-->>CLI: Public key
CLI->>S3: Publish OIDC discovery + JWKS
Note over SE,STS: Each authentication
CLI->>SE: Sign JWT
SE-->>CLI: Signed JWT
CLI->>STS: AssumeRoleWithWebIdentity(JWT)
STS->>S3: Fetch JWKS (validate signature)
S3-->>STS: JWKS
STS-->>CLI: Temporary credentials (1h)

credctl publishes your device’s public key as a JWKS (JSON Web Key Set) document, served over HTTPS. AWS IAM trusts this endpoint as an OIDC provider. When you run credctl auth, credctl signs a JWT with the Secure Enclave key. AWS STS validates the JWT against the published JWKS and issues short-lived credentials.

A single command sets up everything — OIDC hosting on S3, the IAM OIDC provider, the IAM role, and the AWS CLI profile:

Terminal window
credctl setup aws --policy-arn arn:aws:iam::123456789012:policy/MyDevPolicy

Replace the policy ARN with the IAM managed policy you want attached to the role. This policy controls what AWS resources you can access with credctl credentials.

  1. Creates an S3 bucket and uploads OIDC discovery documents (.well-known/openid-configuration and keys.json)
  2. Creates an IAM OIDC provider that trusts the S3-hosted issuer URL
  3. Creates an IAM role with a trust policy referencing the OIDC provider
  4. Attaches the specified IAM policy to the role
  5. Configures the credctl AWS CLI profile in ~/.aws/config
  6. Writes configuration to ~/.credctl/config.json

If you already have an OIDC issuer configured (e.g., from credctl setup gcp), the command reuses it automatically and skips S3 bucket creation.

FlagDefaultDescription
--policy-arnIAM managed policy ARN to attach. Required.
--role-namecredctl-device-roleIAM role name
--regionus-east-1AWS region
--profilecredctlAWS CLI profile name to create
--cloudfrontfalseDeploy via CloudFormation with S3 + CloudFront (CDN caching, DDoS protection)
--issuer-urlUse an existing OIDC issuer URL instead of creating one
Creating S3 bucket 'credctl-oidc-123456789012'...
Uploading OIDC documents...
Creating IAM OIDC provider...
Creating IAM role 'credctl-device-role'...
Attaching policy...
Configuring AWS CLI profile 'credctl'...
AWS setup complete.
Issuer URL: https://credctl-oidc-123456789012.s3.us-east-1.amazonaws.com
Role ARN: arn:aws:iam::123456789012:role/credctl-device-role
Profile: credctl
Test it:
AWS_PROFILE=credctl aws sts get-caller-identity

For CDN caching and DDoS protection on the OIDC endpoint, use the --cloudfront flag:

Terminal window
credctl setup aws --policy-arn arn:aws:iam::123456789012:policy/MyDevPolicy --cloudfront

This deploys a CloudFormation stack with S3, CloudFront, IAM OIDC provider, and IAM role. The CloudFront distribution URL becomes the issuer URL. This requires additional IAM permissions for CloudFormation and CloudFront.

If you prefer full control over the infrastructure, follow these steps:

Create a bucket and configure it for public read access on the OIDC paths only.

credctl generates OIDC documents as part of setup aws. For manual setups, you can upload them yourself — the files are stored in ~/.credctl/oidc/ after running any setup command.

In the AWS Console or via CLI, create an IAM OIDC provider with:

  • Provider URL: your S3 bucket URL or CloudFront distribution URL
  • Audience: sts.amazonaws.com

Create an IAM role with a trust policy that references the OIDC provider:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/credctl-oidc-123456789012.s3.us-east-1.amazonaws.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"credctl-oidc-123456789012.s3.us-east-1.amazonaws.com:aud": "sts.amazonaws.com"
}
}
}
]
}

Attach your desired IAM policy to the role.

Add the AWS configuration to ~/.credctl/config.json:

{
"aws": {
"role_arn": "arn:aws:iam::123456789012:role/credctl-device-role",
"issuer_url": "https://credctl-oidc-123456789012.s3.us-east-1.amazonaws.com",
"region": "us-east-1",
"s3_bucket": "credctl-oidc-123456789012"
}
}

Verify authentication works:

Terminal window
credctl auth

Then confirm the assumed role:

Terminal window
eval $(credctl auth --format env)
aws sts get-caller-identity

Expected output:

{
"UserId": "AROAI...:credctl-aBcDeFg1",
"Account": "123456789012",
"Arn": "arn:aws:sts::123456789012:assumed-role/credctl-device-role/credctl-aBcDeFg1"
}

Or use the AWS profile:

Terminal window
AWS_PROFILE=credctl aws s3 ls

This works with any tool that supports AWS profiles — Terraform, the AWS CDK, Pulumi, and all AWS SDKs.

Check that you have IAM permissions to create S3 buckets, IAM OIDC providers, and IAM roles. If using --cloudfront, you also need permissions for CloudFormation stacks and CloudFront distributions.

Verify the issuer URL is accessible:

Terminal window
curl https://credctl-oidc-123456789012.s3.us-east-1.amazonaws.com/.well-known/openid-configuration

If using --cloudfront, CloudFront distributions take a few minutes to propagate. Wait 2-3 minutes and retry.

”Access denied on AssumeRoleWithWebIdentity”

Section titled “”Access denied on AssumeRoleWithWebIdentity””

The IAM role trust policy does not reference the OIDC provider, or the OIDC documents are not published. Verify with credctl status that the issuer_url and role_arn are set, then check the role trust policy in the IAM Console.

S3 bucket names are globally unique. Use a custom bucket name or role name to avoid conflicts.

Run credctl init before credctl setup aws.

See the full troubleshooting guide for more errors and solutions.