Using OIDC access with HCP Terraform

We all know (and it’s also a good industry practice🙂) that the use of static (long-lived) access keys to manage AWS resources should be avoided, because it increases risk of compromise if the keys are leaked. In this blog post I’ll look at how to use short-lived AWS keys to run Terraform. There are few approaches, but today we’ll be looking at a preferred solution using OpenID Connect (OIDC) federation with AWS Identity and Access Management (IAM), which allows external identities like HCP Terraform or GitHub (also others) to assume an IAM role, ensuring secure and temporary access to AWS resources.

What is OIDC?

OpenID Connect (OIDC) is an identity layer built on top of the OAuth 2.0 framework. It allows third-party applications to verify the identity of the end-user and to obtain basic user profile information. For example if using HCP Terraform, it integrates with AWS using dynamic provider credentials, leveraging OIDC federation to assume an AWS IAM role at runtime. This integration allows HCP Terraform to generate temporary security credentials, which are valid for a limited duration (most commonly an hour), minimising the risk if these credentials are ever compromised.

Overview of the Setup Process

The process involves setting up an OIDC provider in AWS IAM which establishes a trust relationship between HCP Terraform and your AWS account. This relationship enables HCP Terraform to assume a predefined IAM role and obtain temporary credentials for performing actions like terraform plan or terraform apply. In our example here we’ll assume you already have a method to authenticate to your AWS account beforehand.

Step 1: Setting Up the OIDC Provider

To start, configure HCP Terraform to act as an OIDC provider using the following example configuration:

data "tls_certificate" "provider" {
  url = "https://app.terraform.io"
}

resource "aws_iam_openid_connect_provider" "hcp_terraform" {
  url             = "https://app.terraform.io"
  client_id_list  = ["aws.workload.identity"] # Default AWS audience in HCP Terraform
  thumbprint_list = [data.tls_certificate.provider.certificates[0].sha1_fingerprint]
}

This configuration establishes HCP Terraform as a trusted identity provider within your AWS account.

Step 2: Creating an IAM Role

After setting up the OIDC provider, create an IAM role that HCP Terraform will assume. The role’s trust policy specifies that it permits federated access via the OIDC provider:

data "aws_iam_policy_document" "example_oidc_assume_role_policy" {
  statement {
	effect = "Allow"
	actions = ["sts:AssumeRoleWithWebIdentity"]
	principals {
  	    type        = "Federated"
  	    identifiers = [aws_iam_openid_connect_provider.hcp_terraform.arn]
	}
	condition {
  	    test     = "StringEquals"
  	    variable = "app.terraform.io:aud"
  	    values   = ["aws.workload.identity"]
	}
	condition {
      	test     = "StringLike"
  	    variable = "app.terraform.io:sub"
      	values   = ["organization:${var.org_name}:project:${var.project_name}:workspace:${var.workspace_name}:run_phase:*"]
	}
  }
}

resource "aws_iam_role" "example_tf_role" {
  name           	 = "example-tf-exec"
  assume_role_policy = data.aws_iam_policy_document.example_oidc_assume_role_policy.json
}

This setup defines the conditions under which HCP Terraform can assume the role, such as specific organisation, project, and workspace contexts.

Customising Permissions

To allow HCP Terraform to manage resources, you’ll need to attach policies to this IAM role. For example, to grant full S3 access:

data "aws_iam_policy" "s3_full_access" {
  arn = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}

resource "aws_iam_role_policy_attachment" "example_s3_full_access" {
  policy_arn = data.aws_iam_policy.s3_full_access.arn
  role   	 = aws_iam_role.example_tf_role.name
}

Using OIDC Federation in HCP Terraform

Once the OIDC federation is set up, you don’t need to provide explicit AWS credentials within the Terraform provider block, just the AWS region. Instead, you can configure your HCP Terraform workspace environment variables using TFE provider to automate the process:

resource "tfe_variable" "tfc_aws_provider_auth" {
  key      	   = "TFC_AWS_PROVIDER_AUTH"
  value    	   = "true"
  category 	   = "env"
  workspace_id = tfe_workspace.example.id
}

resource "tfe_variable" "tfc_example_role_arn" {
  sensitive	= true
  key      	   = "TFC_AWS_RUN_ROLE_ARN"
  value    	   = aws_iam_role.example_tf_role.arn
  category 	   = "env"
  workspace_id = tfe_workspace.example.id
}

By setting these environment variables, HCP Terraform automatically assumes the IAM role and injects temporary credentials during the execution of Terraform runs.

Implementing Access Management for Your AWS Organization

To ensure scalability and security, consider setting up a pattern where one or more HCP Terraform workspaces manage the IAM role and OIDC provider ARNs centrally. These ARNs can then be shared with other workspaces using HCP Terraform variable sets. This approach allows a cloud or platform team to pre-configure AWS authentication for other teams’ workspaces, promoting autonomous yet secure infrastructure management.

Example of Creating a Variable Set:

First, define a variable set:

resource "tfe_variable_set" "example" {
  name     	   = aws_iam_role.example.name
  description  = "OIDC federation configuration for ${aws_iam_role.example.arn}"
  organization = var.org_name
}

Next, set up the required environment variables:

resource "tfe_variable" "tfc_aws_provider_auth" {
  key         	  = "TFC_AWS_PROVIDER_AUTH"
  value       	  = "true"
  category    	  = "env"
  variable_set_id = tfe_variable_set.example.id
}

resource "tfe_variable" "tfc_example_role_arn" {
  sensitive   	  = true
  key         	  = "TFC_AWS_RUN_ROLE_ARN"
  value       	  = aws_iam_role.example_tf_role.arn
  category    	  = "env"
  variable_set_id = tfe_variable_set.example.id
}

Finally, link the variable set to another workspace:

resource "tfe_workspace_variable_set" "example" {
  variable_set_id = tfe_variable_set.example.id
  workspace_id	  = var.workspace_id
}

Creating Infrastructure Using OIDC Federation

Once the setup is complete, HCP Terraform can create AWS resources using the IAM role without requiring direct AWS credentials in the provider configuration. For example, to create an S3 bucket:

provider "aws" {
  region = "eu-west-1"
}

resource "aws_s3_bucket" "example" {
  bucket = "example-bucket"
}

Conclusion

By using OIDC federation with AWS, HCP Terraform (or GitHub if you run Terraform there) achieves a more secure, scalable, and flexible method for managing infrastructure. It eliminates the need for long-lived access keys, thereby reducing security risks and ensuring that only temporary credentials are used for each run. This setup is aligned with modern security practices, offering a streamlined yet robust way to integrate Terraform workflows when connecting to AWS. For further details you can refer to the AWS Provider and OIDC federation documentation and check out how to set up Dynamic Credentials with the AWS Provider. There is also an IAM Terraform module available to set up an OIDC role as well.


Keeping on top of all the latest features can feel like an impossible task. Is practical infrastructure-modernisation an area you are interested in hearing more about? Book a free chat with us to discuss this further.


This blog is written exclusively by The Scale Factory team. We do not accept external contributions.

Free Healthcheck

Get an expert review of your AWS platform, focused on your business priorities.

Book Now

Discover how we can help you.


Consulting packages

Advice, engineering, and training, solving common SaaS problems at a fixed price.

Learn more >

Growth solutions

Complete AWS solutions, tailored to the unique needs of your SaaS business.

Learn more >

Support services

An ongoing relationship, providing access to our AWS expertise at any time.

Learn more >