Configure Terraform Cloud to Assume an AWS IAM Role via OIDC
Published June 11, 2025

Here is how to configure Terraform Cloud to assume an AWS IAM role via OIDC (OpenID Connect) using only environment variables—no static AWS keys are required.
Modern security best practices dictate minimising long-lived credentials in CI/CD pipelines, and when it comes to AWS, Terraform Cloud has your back.
Terraform Cloud’s is comfortable with AWS via OIDC, letting you run Terraform without ever storing an AWS access key in your workspace. This guide walks through setting it up. And yes, the official documentation from AWS and Terraform Cloud does cover this however, I didn’t find it fully joined all the dots.
In case you are wondering, does this solution work with both remote execution and remote state only, yes, it does.
So here is how I managed to get Terraform Cloud to assume a tight-scope AWS role and orchestrate AWS.
1. AWS Console: Set Up OIDC & Role
1.1 Create OIDC Identity Provider
- Navigate to IAM → Identity providers → Add provider.
- Choose Provider type: OIDC.
- Provider URL:
https://app.terraform.io
- Audience:
aws.workload.identity
- Click Add provider.
1.2 Create the IAM Role
- Go to IAM → Roles → Create role → Web identity.
- Select your new
app.terraform.io
provider and audienceaws.workload.identity
. - Add a Condition to restrict to your workspace’s
app.terraform.io:sub
claim, e.g.:organization:[Your Terraform Org Name]:project:[Leave black]:workspace:[Your workspace name]:run_phase:*
- Click Next: Permissions.
1.3 Attach the Inline Permissions Policy
Your policy will be based on your needs, mine at the time of writing this was to orchestrate AWS SES.
- Under Permissions, choose Create inline policy.
- Switch to JSON and add your policy:
// Example policy, but will work with AWS SES.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SesAndIamPermissions",
"Effect": "Allow",
"Action": [
"ses:VerifyDomainIdentity",
"ses:VerifyDomainDkim",
"ses:GetIdentityVerificationAttributes",
"ses:GetIdentityDkimAttributes",
"iam:CreateUser",
"iam:GetUser",
"iam:CreatePolicy",
"iam:GetPolicy",
"iam:ListPolicies",
"iam:AttachUserPolicy",
"iam:CreateAccessKey",
"iam:ListAccessKeys",
"iam:DeleteAccessKey",
"iam:TagPolicy",
"iam:UntagPolicy",
"iam:ListPolicyVersions",
"iam:GetPolicyVersion",
"iam:DeletePolicy",
"iam:DeletePolicyVersion",
"iam:DetachUserPolicy",
"iam:ListAttachedUserPolicies",
"iam:TagUser",
"iam:UntagUser"
],
"Resource": "*"
}
]
}
Click Review policy, name it something sensible, then Create policy.
1.4 Configure the Trust Relationship
On your role’s Trust relationships tab, click Edit trust policy.
Replace with:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sts:AssumeRoleWithWebIdentity",
"Principal": {
"Federated": "arn:aws:iam::************:oidc-provider/app.terraform.io"
},
"Condition": {
"StringEquals": {
"app.terraform.io:aud": "aws.workload.identity"
},
"StringLike": {
"app.terraform.io:sub": "organization:[your org name]:project::workspace:[your workspace name]:run_phase:*"
}
}
}
]
}
Save and copy the Role ARN, e.g.: arn:aws:iam::************:role/my-thing-tf-staging-etc
2. Terraform Cloud: Environment-Variable Configuration
Instead of storing AWS keys, configure these Environment variables in your workspace:
Key | Value | Notes |
---|---|---|
TFC_AWS_PROVIDER_AUTH | true | Enables dynamic credential injection |
TFC_AWS_RUN_ROLE_ARN | arn:aws:iam::************:role/my-thing-tf-staging-etc | The Role ARN you created above |
- Go to Workspace → Settings → Variables.
- Add each as an Environment variable (not Terraform).
- Mark Sensitive as needed (so they won’t echo in logs).
3. Update Your AWS Provider Block
Remove any access_key/secret_key
or assume_role
blocks - you don’t need them. Use a minimal provider like:
provider "aws" {
region = var.aws_region
default_tags {
tags = {
Environment = var.environment
ManagedBy = "Terraform"
Client = "..."
}
}
}
Terraform Cloud will now handle the OIDC handshake and assume the role under the hood. And it works with both remote execution and remote state only, so, for example, you can run a development workspace locally, from your own laptop with need any AWS keys.
Why OIDC & Dynamic Credentials?
- No static AWS keys in your Terraform Cloud workspace.
- Least-privilege: your Terraform workspace can only assume a single, scoped IAM role.
- Automatic rotation: AWS issues short-lived tokens per run.
- Auditable: every assume-role call is recorded in CloudTrail (if you have CloudTrail set up).
Hope this helps.