Introduction
As organizations increasingly adopt secure and scalable CI/CD pipelines, managing long-lived AWS credentials becomes a growing security concern. A powerful alternative is using temporary credentials via IAM Roles Anywhere, a service that allows external workloads to assume AWS IAM roles securely using X.509 certificates.
Why Use Temporary Credentials for CI/CD?
Traditionally, CI/CD tools like Gitlab, Bitbucket pipelines, or Azure DevOps used long-lived IAM user access keys to authenticate with AWS. But this method has security risks:
- Access keys don’t auto-expire
- Key rotation is manual
- Higher risk of credentials leaks
IAM Roles Anywhere solves this by issuing temporary credentials to external environments, based on trusted X.509 certificates. It combines the security of AWS IAM roles with the flexibility to authenticate outside AWS, like in on-premises CI/CD systems or self-hosted runners.
What is IAM Roles Anywhere?
IAM Roles Anywhere allows workloads outside AWS to assume IAM roles by presenting signed X.509 certificates from a trusted Certificate Authority (CA).
Key components:
- Trust Anchor: Represents your CA (e.g., ACM PCA or a self-managed CA)
- Profile: Specifies which IAM roles can be assumed and what actions are allowed
- Session: Temporary credentials (via AWS Security Token Service - STS)
Setting up CI/CD Deployment using IAM Roles Anywhere
Let’s walk through setting up a pipeline to deploy to AWS using temporary credentials.
Prerequisites
- IAM Roles Anywhere is enabled in your AWS account
- A trusted root CA or use AWS ACM PCA
- Signed certificate + private key
- CI/CD runner or server (Linux VM or Docker)
1.
Generate and Sign Certificate
# generate key for CA certificate
openssl genrsa -out ca.key 2048
# generate CA certificate
openssl req -new -x509 -days 1826 -key ca.key -subj /CN=ca.example.com \
-addext 'keyUsage=critical,keyCertSign,cRLSign,digitalSignature' \
-addext 'basicConstraints=critical,CA:TRUE' -out ca.crt
#generate key for leaf certificate
openssl genrsa -out private.key 2048
#request leaf certificate
cat > extensions.cnf <<EOF
[v3_ca]
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
EOF
openssl req -new -key private.key -subj /CN=cicd-agent.example.com -out iamra-cert.csr
#sign leaf certificate with CA
openssl x509 -req -days 3650 -in iamra-cert.csr -CA ca.crt -CAkey ca.key -set_serial 01 -extfile extensions.cnf -extensions v3_ca -out certificate.crt ```
2.
Setup IAM Roles Anywhere in AWS
# ----------------------------------------
# AWS Provider for Stage Account
# ----------------------------------------
provider "aws" {
region = var.REGION
alias = "deployment-eu"
}
# -----------------------------
# 1. Create a Trust Anchor
# -----------------------------
resource "aws_rolesanywhere_trust_anchor" "external_pipeline_trust" {
name = "external-pipeline-trust"
source {
source_type = "CERTIFICATE_BUNDLE"
source_data {
x509_certificate_data = file("ca.crt") # Your trusted CA bundle (PEM)
}
}
enabled = true
provider = aws.deployment-eu
}
# ----------------------------------------
# 2. Create an IAM Role for External CICD
# ----------------------------------------
resource "aws_iam_role" "pipeline_deployer" {
name = "external-pipeline-deployer-${var.REGION}"
assume_role_policy = jsonencode({
Version = "2012-10-17",
Statement = [{
Effect = "Allow",
Principal = {
Service = "rolesanywhere.amazonaws.com"
},
Action = [
"sts:AssumeRole",
"sts:TagSession",
"sts:SetSourceIdentity"
],
Condition = {
StringEquals = {
"aws:PrincipalTag/x509Subject/CN" = "example-internal-ca"
},
ArnEquals = {
"aws:SourceArn" = aws_rolesanywhere_trust_anchor.external_pipeline_trust.arn
}
}
}]
})
provider = aws.deployment-eu
}
# ----------------------------------------
# 3. Attach Deployment Permissions (Broad Example)
# ----------------------------------------
resource "aws_iam_role_policy" "pipeline_access_policy" {
name = "deployment-access"
role = aws_iam_role.pipeline_deployer.id
policy = jsonencode({
Version = "2012-10-17",
Statement = [
{
Effect = "Allow",
Action = ["*"],
Resource = ["*"]
}
]
})
provider = aws.deployment-eu
}
# ----------------------------------------
# 4. Create a RolesAnywhere Profile
# ----------------------------------------
resource "aws_rolesanywhere_profile" "pipeline_profile" {
name = "pipeline-profile"
role_arns = [aws_iam_role.pipeline_deployer.arn]
require_instance_properties = false
enabled = true
duration_seconds = 3600
provider = aws.deployment-eu
}
3.
Upload Certificate and Private Key to Azure DevOps Secure Files
To ensure your private key and certificate are kept safe and not exposed in your code repository, upload them to Azure DevOps Secure Files.
4.
Use in CI/CD Pipeline File
jobs:
- deployment: Deploy
strategy:
runOnce:
deploy:
steps:
- task: DownloadSecureFile@1
name: Certificate
displayName: 'Download certificate'
inputs:
secureFile: 'certificate.crt'
- task: DownloadSecureFile@1
name: Privatekey
displayName: 'Download private key'
inputs:
secureFile: 'private.key'
- bash: |
wget https://rolesanywhere.amazonaws.com/releases/1.0.3/X86_64/Linux/aws_signing_helper
chmod +x aws_signing_helper
displayName: Install AWS Signer
- bash: |
aws configure set credential_process "$(pwd)/aws_signing_helper credential-process --certificate $(Certificate.secureFilePath) --private-key $(Privatekey.secureFilePath) --trust-anchor-arn $TRUST_ANCHOR_ARN --profile-arn $PROFILE_ARN --role-arn $ROLE_ARN" --profile "$PROFILE_ENV"
echo "##vso[task.setvariable variable=AWS_SDK_LOAD_CONFIG]1"
displayName: Obtain AWS Credentials
- script: |
source .env
aws s3 sync rewired_build s3://$REACT_APP_SELLER_S3_BUCKET --acl public-read --profile "$PROFILE_ENV"
aws cloudfront create-invalidation --distribution-id $REACT_APP_SELLER_DISTRIBUTION_ID --paths "/*" --profile "$PROFILE_ENV"
displayName: 'Deployment'
Conclusion
IAM Roles Anywhere makes it possible to run secure, temporary AWS deployments from any CI/CD pipeline without the need for long-lived credentials. It bridges the gap between external workloads and AWS IAM, enabling safer automation.
By following the approach outlined above, we can modernize your CI/CD security while maintaining flexibility and speed.
