Terraform
Configure dynamic credentials for AWS in module testing
You can use HCP Terraform's native OpenID Connect integration with AWS to get dynamic, short-lived credentials for module test runs. This approach eliminates the need to store static AWS credentials and improves security by using temporary credentials that automatically expire.
Before you begin, decide whether to use separate IAM roles for module tests or reuse workspace roles. Separate roles provide better isolation and allow you to grant different permissions for testing versus production workloads.
Requirements
You need the following to configure dynamic credentials for AWS in module testing:
- An AWS account with permissions to create and configure IAM roles and OIDC providers
- An HCP Terraform organization with module testing enabled
- A private registry module with testing configured
- Permissions in HCP Terraform to modify registry module test settings
Configure AWS
Complete the following steps in AWS, then configure HCP Terraform.
Create an IAM OIDC provider
You only need to create one OIDC provider per AWS account and reuse it with all HCP Terraform workspaces and module tests. If you haven't already configured an OIDC identity provider for HCP Terraform in your AWS account, complete the following steps to create one:
- Sign in to the AWS Management Console and navigate to IAM > Identity providers
- Click Add provider
- Select OpenID Connect as the provider type
- Enter the provider URL:
- For HCP Terraform:
https://app.terraform.io - For Terraform Enterprise:
https://<your-terraform-enterprise-hostname>.
- For HCP Terraform:
- Click Get thumbprint to automatically retrieve the thumbprint
- For Audience, enter:
aws.workload.identity - Click Add provider
Create an IAM role for module tests
Create a dedicated IAM role that module tests assume during test runs:
- In the AWS Management Console, navigate to IAM > Roles.
- Click Create role.
- Select Web identity as the trusted entity type.
- Choose the OIDC provider you created in the previous step.
- For Audience, select
aws.workload.identity. - Click Next.
- Attach permissions policies required for your module tests. Refer to permissions recommendations for more information.
- Specify a name for the role, for example
terraform-module-test-role. - Click Create role.
Configure the trust policy
After creating the role, configure its trust policy to accept tokens from your module tests. The trust policy controls which HCP Terraform organizations and modules can assume the role.
- Open the IAM role you created
- Navigate to the Trust relationships tab
- Click Edit trust policy
- Update the trust policy to include module test-specific conditions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/app.terraform.io"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"app.terraform.io:aud": "aws.workload.identity"
},
"StringLike": {
"app.terraform.io:sub": "organization:my-org:module:*:operation:test_run"
}
}
}
]
}
Replace the following values:
123456789012: Your AWS account IDapp.terraform.io: Your HCP Terraform or Terraform Enterprise hostnamemy-org: Your organization's name. You can get the name from your organization settings page.
This trust policy allows any module in your organization to assume the role, but only during test runs (identified by the :operation:test_run suffix in the subject claim).
Configure HCP Terraform
After configuring AWS, configure your registry module's test configuration to use dynamic credentials.
Configure through the UI
- Navigate to your private registry module in HCP Terraform
- Click Tests in the module navigation
- Click Configuration or Settings
- In the Dynamic Credentials section, toggle Enable dynamic credentials
- Select AWS as the provider
- Enter the IAM role ARN, for example,
arn:aws:iam::123456789012:role/terraform-module-test-role - (Optional) Set a custom audience if you configured a different audience in your OIDC provider
- Click Save configuration
Configure through the API
You can also configure dynamic credentials using the Test Configuration API:
curl \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/vnd.api+json" \
--request PATCH \
--data @payload.json \
https://app.terraform.io/api/v2/registry-modules/:registry_name/:namespace/:name/:provider/test-configuration
With the following payload.json:
{
"data": {
"type": "test-configurations",
"attributes": {
"oidc-enabled": true,
"oidc-provider": "aws",
"oidc-configuration": {
"role-arn": "arn:aws:iam::123456789012:role/terraform-module-test-role",
"audience": "aws.workload.identity"
}
}
}
}
Environment variables
When you configure dynamic credentials for AWS, HCP Terraform automatically sets the following environment variables in your module test runs:
| Variable | Description | Example Value |
|---|---|---|
TFC_AWS_PROVIDER_AUTH | Signals the AWS provider to use OIDC authentication | true |
TFC_AWS_RUN_ROLE_ARN | The IAM role ARN to assume | arn:aws:iam::123456789012:role/terraform-module-test-role |
TFC_AWS_WORKLOAD_IDENTITY_AUDIENCE | The audience claim for OIDC tokens | aws.workload.identity |
TFC_OIDC_ISSUER_URL | The OIDC issuer URL | https://app.terraform.io |
TFC_OIDC_AUDIENCE | The OIDC audience | aws.workload.identity |
The AWS Terraform provider version 4.67.0 and later automatically uses these environment variables to authenticate with AWS. You don't need to configure the provider block explicitly.
Trust policy examples
The following examples show common trust policy configurations.
Basic trust policy for all module tests
Allow all module tests in your organization to assume the role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/app.terraform.io"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"app.terraform.io:aud": "aws.workload.identity"
},
"StringLike": {
"app.terraform.io:sub": "organization:my-org:module:*:operation:test_run"
}
}
}
]
}
Trust policy for specific module
Allow only a specific module to assume the role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/app.terraform.io"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"app.terraform.io:aud": "aws.workload.identity",
"app.terraform.io:sub": "organization:my-org:module:terraform-aws-vpc:operation:test_run"
}
}
}
]
}
Trust policy with organization name claim
Add the organization name claim for additional verification:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/app.terraform.io"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"app.terraform.io:aud": "aws.workload.identity",
"app.terraform.io:terraform_organization_name": "my-org"
},
"StringLike": {
"app.terraform.io:sub": "organization:my-org:module:*:operation:test_run"
}
}
}
]
}
Trust policy with module name pattern
Allow all AWS modules to assume the role by matching the module name in the subject claim:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/app.terraform.io"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"app.terraform.io:aud": "aws.workload.identity"
},
"StringLike": {
"app.terraform.io:sub": "organization:my-org:module:terraform-aws-*:operation:test_run"
}
}
}
]
}
Permissions recommendations
The permissions you attach to your IAM role depend on what your module tests need to do. Follow the principle of least privilege by granting only the minimum permissions required.
Read-only testing
For modules that only need to validate configurations without creating resources:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:Describe*",
"s3:List*",
"s3:Get*",
"iam:Get*",
"iam:List*"
],
"Resource": "*"
}
]
}
Resource creation for testing
For modules that create test resources, limit permissions to specific resource types and use resource tags:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:RunInstances",
"ec2:TerminateInstances",
"ec2:CreateTags",
"ec2:Describe*"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:RequestedRegion": "us-east-1",
"ec2:CreateAction": "RunInstances"
}
}
},
{
"Effect": "Allow",
"Action": [
"ec2:TerminateInstances"
],
"Resource": "arn:aws:ec2:us-east-1:123456789012:instance/*",
"Condition": {
"StringEquals": {
"ec2:ResourceTag/Testing": "true"
}
}
}
]
}
Tip: Use resource tags like Testing: true or ManagedBy: terraform-test to identify and scope permissions for test resources.
Verify the configuration
After configuring both AWS and HCP Terraform, verify the setup by running a test:
- Navigate to your module in HCP Terraform
- Go to the Tests tab
- Click Start Test Run or trigger a test through your VCS
- Monitor the test run logs for successful authentication
If authentication succeeds, you'll see log output indicating the AWS provider authenticated using the OIDC token. If it fails, check the troubleshooting section.
Troubleshooting
Error: "No valid credential sources found"
This error indicates the AWS provider cannot find credentials. Check:
- The AWS provider version is 4.67.0 or later
- Dynamic credentials are enabled in the test configuration
- The role ARN is correct in the test configuration
- The
TFC_AWS_PROVIDER_AUTHenvironment variable is set totrue
Error: "Not authorized to perform sts:AssumeRoleWithWebIdentity"
This error means the IAM role's trust policy rejected the OIDC token. Verify:
- The OIDC provider exists in your AWS account
- The trust policy includes the correct issuer URL (app.terraform.io or your TFE hostname)
- The subject claim pattern matches your organization name and module, ending with
:operation:test_run - The audience in the trust policy matches the configured audience
Error: "Token has expired"
OIDC tokens expire after the configured TTL (default: 10 minutes). If your tests run longer:
- Increase the organization's
module_test_token_ttlusing the Organizations API - Optimize your tests to complete faster
- Ensure your test infrastructure setup is efficient
Error: "Access denied" or "UnauthorizedOperation"
The IAM role lacks necessary permissions. Check:
- The IAM role has appropriate permissions policies attached
- Resource policies or SCPs aren't blocking the assumed role
- Condition statements in permissions policies match your test runs
- The role isn't restricted by permission boundaries
Debugging trust policy conditions
To debug trust policy issues, enable AWS CloudTrail and examine AssumeRoleWithWebIdentity events. The events show which claims were present in the token and why the trust policy allowed or denied access.
You can also test the trust policy using the AWS CLI:
aws sts assume-role-with-web-identity \
--role-arn arn:aws:iam::123456789012:role/terraform-module-test-role \
--role-session-name test-session \
--web-identity-token "$(cat token.jwt)"
This command shows the exact error message if the trust policy rejects the token.
Next steps
- Learn about dynamic credentials for module testing
- Configure dynamic credentials for other providers:
- Review workload identity token specifications
- Set up policy enforcement to require OIDC for tests