Skip to content

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:

  1. Automated (recommended) — credctl setup aws deploys everything via CloudFormation
  2. 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)

A single command deploys all required infrastructure:

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.

What it creates

The CloudFormation stack deploys:

ResourcePurpose
S3 bucketHosts .well-known/openid-configuration and keys.json (JWKS)
CloudFront distributionServes OIDC documents over HTTPS — acts as the issuer URL
IAM OIDC providerTells AWS to trust JWTs signed by keys published at the issuer URL
IAM roleThe 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

FlagDefaultDescription
--policy-arnIAM managed policy ARN to attach. Required.
--stack-namecredctl-infraCloudFormation stack name
--role-namecredctl-device-roleIAM role name
--regionus-east-1AWS 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/config

Manual setup

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

1. Generate OIDC documents

Terminal window
credctl oidc generate --issuer-url https://your-cloudfront-distribution.cloudfront.net

2. 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

Terminal window
credctl oidc publish --bucket your-oidc-bucket --region us-east-1

4. 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:

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"
}

Set up the credential helper

Add a credential_process entry to ~/.aws/config for transparent integration:

[profile credctl]
credential_process = credctl auth

Test it:

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.

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:

Terminal window
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:

Terminal window
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.