Secure Terraform Deployments on AWS with GitHub Actions and OIDC

In the world of DevOps, automating infrastructure deployment securely is crucial. This blog post will guide you through setting up GitHub Actions to automatically deploy your Terraform configurations to AWS using OpenID Connect (OIDC) for enhanced security.

Prerequisites

  • A GitHub repository with your Terraform configuration
  • An AWS account
  • Basic knowledge of Terraform and GitHub Actions

Understanding OIDC in GitHub Actions and AWS

Before we dive into the setup, let's understand how OIDC works in this context:

  1. OpenID Connect (OIDC) is an authentication protocol that allows GitHub Actions to obtain temporary AWS credentials without storing long-term access keys.
  2. AWS is configured to trust GitHub as an identity provider.
  3. When a GitHub Action runs, it requests a short-lived OIDC token from GitHub, which includes claims about the workflow's identity.
  4. This token is sent to AWS's Security Token Service (STS), which verifies the token and issues temporary AWS credentials.
  5. The GitHub Action then uses these temporary credentials to perform AWS operations.

This process enhances security by eliminating the need for long-term credential storage and providing a dynamic, identity-based access model.

Step 1: Set Up AWS IAM OIDC Provider and Role

First, we need to configure AWS to trust GitHub's OIDC provider and create an IAM role:

  1. Create an IAM OIDC Provider
    1. Sign in to the AWS Management Console and navigate to the IAM dashboard.
    2. In the left navigation pane, click on "Identity providers" under "Access management".
    3. Click the "Add provider" button.
    4. For the provider type, select "OpenID Connect".
    5. For the provider URL, enter: https://token.actions.githubusercontent.com
      1. AWS will fetch the OpenID Connect discovery document from this URL to obtain the public keys and verify the OIDC token from GitHub Actions.
    6. For the "Audience", enter: sts.amazonaws.com
      1. This is the intended audience of the OIDC token, which for GitHub Actions is the AWS Security Token Service.
    7. Click "Get thumbprint" to fetch the server certificate thumbprint.
    8. Verify the thumbprint and click "Add provider"
  2. Create an IAM role with the necessary permissions for your Terraform operations.
  3. Configure the role's trust relationship:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::YOUR_ACCOUNT_ID:oidc-provider/token.actions.githubusercontent.com"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringLike": {
          "token.actions.githubusercontent.com:sub": "repo:YOUR_GITHUB_ORG/YOUR_REPO:*"
        }
      }
    }
  ]
}

Replace YOUR_ACCOUNT_ID, YOUR_GITHUB_ORG, and YOUR_REPO with your specific values.

Step 2: Create the GitHub Actions Workflow

Create a new file in your repository at .github/workflows/terraform-deploy.yml:

name: 'Terraform Deploy'

on:
  push:
    branches:
      - main

permissions:
  id-token: write
  contents: read

jobs:
  terraform:
    name: 'Terraform'
    runs-on: ubuntu-latest
    
    steps:
    - name: Checkout
      uses: actions/checkout@v2

    - name: Configure AWS Credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        role-to-assume: arn:aws:iam::YOUR_ACCOUNT_ID:role/YOUR_ROLE_NAME
        aws-region: YOUR_AWS_REGION

    - name: Setup Terraform
      uses: hashicorp/setup-terraform@v1

    - name: Terraform Init
      run: terraform init

    - name: Terraform Plan
      run: terraform plan

    - name: Terraform Apply
      run: terraform apply -auto-approve

Replace YOUR_ACCOUNT_ID, YOUR_ROLE_NAME, and YOUR_AWS_REGION with your specific values.

How It Works

  1. When the workflow runs, GitHub generates an OIDC token containing claims about the workflow's identity.
  2. The aws-actions/configure-aws-credentials action exchanges this OIDC token for temporary AWS credentials:
    • It sends the token to AWS STS.
    • AWS verifies the token's signature using GitHub's public keys.
    • If valid and meeting the role's trust conditions, AWS issues temporary credentials.
  3. These temporary credentials are then used for subsequent AWS operations in the workflow.
  4. Terraform commands use these credentials to authenticate with AWS and perform the necessary operations.

Security Benefits of OIDC

  1. No long-term AWS access keys stored in GitHub secrets.
  2. Temporary credentials reduce risk if exposed.
  3. Easy to audit and rotate permissions by modifying the IAM role.
  4. Follows the principle of least privilege.
  5. Trust is based on the GitHub workflow's identity, not a shared secret.

Best Practices

  1. Use workspaces to manage multiple environments.
  2. Consider adding a manual approval step before applying changes.
  3. Implement state locking to prevent concurrent modifications.
  4. Use Terraform modules to organize and reuse your code.
  5. Regularly review and update the IAM role's permissions.
  6. Use condition keys in the trust policy to restrict access to specific repositories or branches.

Conclusion

Implementing this GitHub Actions workflow with OIDC has automated your Terraform deployments to AWS with significantly enhanced security. This setup improves consistency, reduces human error, speeds up your infrastructure deployment process, and adheres to AWS security best practices.

Always review the planned changes before they are applied to your production environment. Happy secure automating!