AWS setup guide
Overview
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:
- Automated (recommended) —
credctl setup awsdeploys everything via CloudFormation - Manual — deploy the infrastructure yourself using Terraform or the AWS Console
How OIDC federation works
credctl publishes your device’s public key as a JWKS (JSON Web Key Set) document, served over HTTPS via CloudFront. 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.
sequenceDiagram participant SE as Secure Enclave participant CLI as credctl CLI participant S3 as S3 + CloudFront 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)Automated setup (recommended)
A single command deploys all required infrastructure:
credctl setup aws --policy-arn arn:aws:iam::123456789012:policy/MyDevPolicyReplace 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.
What it creates
The CloudFormation stack deploys:
| Resource | Purpose |
|---|---|
| S3 bucket | Hosts .well-known/openid-configuration and keys.json (JWKS) |
| CloudFront distribution | Serves OIDC documents over HTTPS — acts as the issuer URL |
| IAM OIDC provider | Tells AWS to trust JWTs signed by keys published at the issuer URL |
| IAM role | The role credctl assumes; trust policy references the OIDC provider |
The command also generates and publishes OIDC documents automatically, and writes the configuration to ~/.credctl/config.json.
Available flags
| Flag | Default | Description |
|---|---|---|
--policy-arn | — | IAM managed policy ARN to attach. Required. |
--stack-name | credctl-infra | CloudFormation stack name |
--role-name | credctl-device-role | IAM role name |
--region | us-east-1 | AWS region |
Expected output
Deploying CloudFormation stack 'credctl-infra' in us-east-1...Waiting for stack to complete...
Stack outputs: Issuer URL: https://d1234567890.cloudfront.net Role ARN: arn:aws:iam::123456789012:role/credctl-device-role S3 Bucket: credctl-oidc-123456789012
Generating OIDC documents...Publishing OIDC documents...AWS setup complete. Configure your AWS CLI: echo '[profile credctl]\ncredential_process = credctl auth' >> ~/.aws/configManual setup
If you prefer full control over the infrastructure, follow these steps:
1. Generate OIDC documents
credctl oidc generate --issuer-url https://your-cloudfront-distribution.cloudfront.net2. Create the S3 bucket and CloudFront distribution
Create an S3 bucket to host the OIDC documents and a CloudFront distribution to serve them over HTTPS. The CloudFront distribution URL becomes your OIDC issuer URL.
3. Publish OIDC documents
credctl oidc publish --bucket your-oidc-bucket --region us-east-14. Create the IAM OIDC provider
In the AWS Console or via CLI, create an IAM OIDC provider with:
- Provider URL: your CloudFront distribution URL
- Audience:
sts.amazonaws.com
5. Create the IAM role
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/d1234567890.cloudfront.net" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "d1234567890.cloudfront.net:aud": "sts.amazonaws.com" } } } ]}Attach your desired IAM policy to the role.
6. Update configuration
Add the AWS configuration to ~/.credctl/config.json:
{ "aws": { "role_arn": "arn:aws:iam::123456789012:role/credctl-device-role", "issuer_url": "https://d1234567890.cloudfront.net", "region": "us-east-1", "s3_bucket": "your-oidc-bucket" }}Test the configuration
Verify authentication works:
credctl authThen confirm the assumed role:
eval $(credctl auth --format env)aws sts get-caller-identityExpected output:
{ "UserId": "AROAI...:credctl-aBcDeFg1", "Account": "123456789012", "Arn": "arn:aws:sts::123456789012:assumed-role/credctl-device-role/credctl-aBcDeFg1"}Set up the credential helper
Add a credential_process entry to ~/.aws/config for transparent integration:
[profile credctl]credential_process = credctl authTest it:
AWS_PROFILE=credctl aws s3 lsThis works with any tool that supports AWS profiles — Terraform, the AWS CDK, Pulumi, and all AWS SDKs.
Troubleshooting
”CloudFormation deploy failed”
Check that you have IAM permissions to create CloudFormation stacks, S3 buckets, CloudFront distributions, IAM OIDC providers, and IAM roles. View the CloudFormation events in the AWS Console for the specific error.
”OIDC provider validation failed”
CloudFront distributions take a few minutes to propagate. Wait 2–3 minutes and retry. Verify the issuer URL is accessible:
curl https://d1234567890.cloudfront.net/.well-known/openid-configuration“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 already exists”
S3 bucket names are globally unique. Use a custom stack name to generate a different bucket name:
credctl setup aws --policy-arn arn:aws:iam::123456789012:policy/MyDevPolicy --stack-name credctl-myname“device not initialised”
Run credctl init before credctl setup aws.
See the full troubleshooting guide for more errors and solutions.
Related
- Quickstart — if you haven’t set up credctl yet
credctl setup aws— command referencecredctl auth— command reference- Configuration reference —
~/.credctl/config.jsonschema