Walk-through - OIDC to AWS
Feel free to comment. Just to note: We moved on to Vault.
OIDC Provider Configuration
Let’s create an OIDC provider configuration.
The URL is always https://oidc.circleci.com/org/<organization-id>
, where <organization-id>
is the CircleCI Org UUID that represents your organization.
ClientIDList
is the audience defined by CircleCI, which is the organization ID as well.
To get the thumbprint follow this guide.
create-open-id-connect-provider.json
{
"Url": "oidc.circleci.com/org/${CIRCLECI_ORG_UUID}",
"ClientIDList": [
"${CIRCLECI_ORG_UUID}"
],
"ThumbprintList": [
"9e99a48a9960b14926bb7f3b02e22da2b0ab7280"
],
"Tags": [
{
"Key": "Name",
"Value": "circleci-oidc"
}
]
}
aws iam create-open-id-connect-provider \
--cli-input-json file://create-open-id-connect-provider.json
OIDC IAM Assume Role
This IAM role will be assumed by the web identity authenticated via the OIDC provider.
We will use the OIDC provider ARN and add a condition, who is allowed to assume this role.
Following CircleCIs token format we are going to allow all workflows from our org-id/project-id by wildcarding the user.
create-iam-role.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/oidc.circleci.com/org/${CIRCLECI_ORG_UUID}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringLike": {
"oidc.circleci.com/org/${CIRCLECI_ORG_UUID}:sub": "org/${CIRCLECI_ORG_UUID}/project/${CIRCLECI_PROJECT_UUID}/user/*"
}
}
}
]
}
aws iam create-role \
--role-name circleci-oidc \
--assume-role-policy-document file://create-iam-role.json
IAM assume role (AWS Sub-Account)
create-iam-policy.json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"eks:DescribeCluster",
"eks:ListClusters"
],
"Resource": "*"
}
]
}
aws iam create-policy \
--policy-name circleci-oidc \
--policy-document file://create-iam-policy.json
aws iam attach-role-policy \
--role-name circle-oidc \
--policy-arn "arn:aws:iam::${AWS_ACCOUNT_ID}:policy/circle-oidc"
CI Implementation
Here is what it does:
- create aws config directory
- write aws profile config
- call
sts:assume-role-with-web-identity
using the${CIRCLE_OIDC_TOKEN}
- parsing response for credentials
- write to aws credential file
- run:
name: AWS OIDC auth
command: |
mkdir ~/.aws
cat > ~/.aws/config \<<- EOF
[default]
region = eu-central-1
output = json
[profile playground]
source_profile = default
role_arn = "arn:aws:iam::${AWS_ACCOUNT_ID}:role/circleci-oidc"
EOF
AWS_OIDC_ROLE_ARN="arn:aws:iam::${AWS_ACCOUNT_ID}:role/circleci-oidc"
AWS_SESSION_NAME="circleci-oidc"
AWS_STS_CREDENTIALS=$(aws sts assume-role-with-web-identity \
--duration-seconds 900 \
--output "json" \
--query "Credentials" \
--role-arn "${AWS_OIDC_ROLE_ARN}" \
--role-session-name "${AWS_SESSION_NAME}" \
--web-identity-token "${CIRCLE_OIDC_TOKEN}"
)
cat > ~/.aws/credentials \<<- EOF
[default]
aws_access_key_id=$(echo $AWS_STS_CREDENTIALS | jq -r '.AccessKeyId')
aws_secret_access_key=$(echo $AWS_STS_CREDENTIALS | jq -r '.SecretAccessKey')
aws_session_token=$(echo $AWS_STS_CREDENTIALS | jq -r '.SessionToken')
EOF