AWS Integration¶
Set up AWS IAM to trust the Auths OIDC Bridge for workload identity federation.
Overview¶
AWS IAM can federate identity from any OIDC provider. By registering the Auths OIDC Bridge as an IAM OIDC provider, your CI pipelines and services can assume IAM roles using their KERI identity -- no long-lived access keys needed.
Step 1: Create OIDC Identity Provider¶
# Get the TLS certificate thumbprint
THUMBPRINT=$(openssl s_client -connect your-bridge.example.com:443 < /dev/null 2>/dev/null \
| openssl x509 -fingerprint -noout -sha1 \
| sed 's/.*=//' | tr -d ':' | tr 'A-F' 'a-f')
# Create the provider
aws iam create-open-id-connect-provider \
--url https://your-bridge.example.com \
--client-id-list sts.amazonaws.com \
--thumbprint-list "$THUMBPRINT"
Step 2: Create IAM Role with Trust Policy¶
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/your-bridge.example.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"your-bridge.example.com:aud": "sts.amazonaws.com",
"your-bridge.example.com:sub": "did:keri:EXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
}
}
}
]
}
Recommended conditions:
- Always set
audcondition to prevent confused deputy - Set
subcondition to restrict to specific KERI identities - Use
StringLikewith wildcards cautiously (e.g.,did:keri:E*allows any KERI identity)
Step 3: Assume Role from CI¶
# Exchange attestation chain for JWT
JWT=$(curl -s -X POST https://your-bridge.example.com/token \
-H "Content-Type: application/json" \
-d '{"attestation_chain": [...], "root_public_key": "..."}' \
| jq -r '.access_token')
# Assume AWS role
CREDS=$(aws sts assume-role-with-web-identity \
--role-arn arn:aws:iam::ACCOUNT:role/auths-ci \
--role-session-name "build-$BUILD_ID" \
--web-identity-token "$JWT" \
--output json)
# Export credentials
export AWS_ACCESS_KEY_ID=$(echo $CREDS | jq -r '.Credentials.AccessKeyId')
export AWS_SECRET_ACCESS_KEY=$(echo $CREDS | jq -r '.Credentials.SecretAccessKey')
export AWS_SESSION_TOKEN=$(echo $CREDS | jq -r '.Credentials.SessionToken')
Infrastructure-as-Code¶
Terraform¶
resource "aws_iam_openid_connect_provider" "auths_bridge" {
url = "https://your-bridge.example.com"
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = [var.bridge_tls_thumbprint]
tags = {
Name = "auths-oidc-bridge"
}
}
resource "aws_iam_role" "auths_ci" {
name = "auths-ci-role"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Federated = aws_iam_openid_connect_provider.auths_bridge.arn
}
Action = "sts:AssumeRoleWithWebIdentity"
Condition = {
StringEquals = {
"${aws_iam_openid_connect_provider.auths_bridge.url}:aud" = "sts.amazonaws.com"
"${aws_iam_openid_connect_provider.auths_bridge.url}:sub" = var.allowed_keri_did
}
}
}
]
})
}
variable "bridge_tls_thumbprint" {
description = "SHA-1 thumbprint of the bridge TLS certificate"
type = string
}
variable "allowed_keri_did" {
description = "KERI DID allowed to assume this role (e.g., did:keri:Eabc...)"
type = string
}
CloudFormation¶
AWSTemplateFormatVersion: "2010-09-09"
Description: Auths OIDC Bridge IAM resources
Parameters:
BridgeUrl:
Type: String
Description: HTTPS URL of the auths-oidc-bridge
Default: https://your-bridge.example.com
BridgeTlsThumbprint:
Type: String
Description: SHA-1 thumbprint of the bridge TLS certificate
AllowedKeriDid:
Type: String
Description: KERI DID allowed to assume the role
Resources:
AuthsOidcProvider:
Type: AWS::IAM::OIDCProvider
Properties:
Url: !Ref BridgeUrl
ClientIdList:
- sts.amazonaws.com
ThumbprintList:
- !Ref BridgeTlsThumbprint
AuthsCiRole:
Type: AWS::IAM::Role
Properties:
RoleName: auths-ci-role
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Federated: !GetAtt AuthsOidcProvider.Arn
Action: sts:AssumeRoleWithWebIdentity
Condition:
StringEquals:
!Sub "${BridgeUrl}:aud": sts.amazonaws.com
!Sub "${BridgeUrl}:sub": !Ref AllowedKeriDid
Outputs:
OidcProviderArn:
Value: !GetAtt AuthsOidcProvider.Arn
RoleArn:
Value: !GetAtt AuthsCiRole.Arn
Common Mistakes¶
- Missing
audcondition -- allows any OIDC provider with the same issuer URL - Overly broad
sub--StringLike: "did:keri:*"allows any KERI identity - Setting
azpclaim -- AWS usesazpas audience when present, ignoringaud - Ephemeral bridge keys -- bridge restart invalidates all in-flight tokens