DEV Community

John Ajera
John Ajera

Posted on

GitHub Actions to AWS OIDC Integration SetuP

GitHub Actions to AWS OIDC Integration Setup

Securely deploy to AWS from GitHub Actions using OpenID Connect (OIDC), eliminating the need for long-lived AWS credentials.


✅ Step 1: Create IAM Role for GitHub (via AWS CLI)

Run the following AWS CLI commands to manually bootstrap the IAM role and OIDC provider:

aws iam create-open-id-connect-provider \ --url https://token.actions.githubusercontent.com \ --client-id-list sts.amazonaws.com \ --thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1 aws iam create-role \ --role-name github-oidc-role \ --assume-role-policy-document file://trust-policy.json aws iam attach-role-policy \ --role-name github-oidc-role \ --policy-arn arn:aws:iam::aws:policy/AdministratorAccess 
Enter fullscreen mode Exit fullscreen mode

Note: Replace AdministratorAccess with a least-privilege policy if possible.


✅ Step 2: Folder Structure (Bootstrap Setup)

Minimal layout for bootstrapping (no remote backend):

my-terraform-project/ ├── .github/ │ └── workflows/ │ └── deploy.yml ├── main.tf ├── .gitignore └── README.md 
Enter fullscreen mode Exit fullscreen mode

Example .gitignore:

.terraform/ 

Note: This is a bootstrap setup and does not use a remote backend. For production, it's recommended to configure a remote backend such as an S3 bucket.


✅ Step 3: Minimal Terraform Configuration (main.tf)

This main.tf contains only a minimal resource for testing. Terraform is not responsible for creating the IAM role in this bootstrap scenario.

provider "aws" { region = var.aws_region } variable "aws_region" { description = "AWS region" default = "ap-southeast-2" } variable "aws_account_id" { description = "AWS Account ID" } variable "github_owner" { description = "GitHub organization or username" } variable "repo_name" { description = "GitHub repository name" } # Minimal test resource data "aws_caller_identity" "current" {} resource "aws_s3_bucket" "test_bucket" { bucket = "test-bucket-${data.aws_caller_identity.current.account_id}" acl = "private" tags = { Name = "Test Bucket" Env = "Bootstrap" } } 
Enter fullscreen mode Exit fullscreen mode

✅ Step 4: Configure GitHub Secrets and Variables

Go to Repo → Settings → Secrets and variables → Actions, and set:

  • Secrets:
  • AWS_ACCOUNT_ID: Your 12-digit AWS account ID (e.g. 123456789012)

Variables:

  • AWS_REGION: AWS region to deploy resources (e.g. ap-southeast-2)
  • TERRAFORM_VERSION: Terraform version to use (e.g. 1.12.1)
  • OIDC_ROLE_NAME: IAM role name that GitHub Actions will assume (must match the name in main.tf, e.g. github-oidc-role)

✅ Step 5: GitHub Actions Workflows

🔹 plan.yml – for Terraform Plan (on PR)

name: Terraform Plan permissions: id-token: write contents: read concurrency: group: terraform-plan-${{ github.head_ref || github.ref }} cancel-in-progress: true on: pull_request: branches: [main] env: AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} AWS_REGION: ${{ vars.AWS_REGION }} TERRAFORM_VERSION: ${{ vars.TERRAFORM_VERSION }} OIDC_ROLE_NAME: ${{ vars.OIDC_ROLE_NAME }} jobs: terraform: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Configure AWS credentials via OIDC uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/${{ env.OIDC_ROLE_NAME }} aws-region: ${{ env.AWS_REGION }} - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: ${{ env.TERRAFORM_VERSION }} - name: Terraform Init run: terraform init - name: Terraform Format run: terraform fmt -check continue-on-error: true - name: Terraform Validate run: terraform validate - name: Terraform Plan run: terraform plan 
Enter fullscreen mode Exit fullscreen mode

🔹 deploy.yml – for Terraform Apply

name: Terraform Apply permissions: id-token: write contents: write concurrency: group: terraform-apply-${{ github.head_ref || github.ref }} cancel-in-progress: true on: push: branches: [main] env: AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }} AWS_REGION: ${{ vars.AWS_REGION }} TERRAFORM_VERSION: ${{ vars.TERRAFORM_VERSION }} OIDC_ROLE_NAME: ${{ vars.OIDC_ROLE_NAME }} jobs: terraform: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Configure AWS credentials via OIDC uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: arn:aws:iam::${{ env.AWS_ACCOUNT_ID }}:role/${{ env.OIDC_ROLE_NAME }} aws-region: ${{ env.AWS_REGION }} - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: ${{ env.TERRAFORM_VERSION }} - name: Terraform Init run: terraform init - name: Terraform Format run: terraform fmt -check continue-on-error: true - name: Terraform Validate run: terraform validate - name: Terraform Plan run: terraform plan - name: Terraform Apply id: apply run: terraform apply -auto-approve continue-on-error: true - name: Commit and force push if changed if: always() run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" if ! git diff --quiet || ! git diff --staged --quiet; then git add . git commit -m "Update terraform state and lock file" git push --force fi - name: Fail if Terraform Apply errored if: steps.apply.outcome == 'failure' run: exit 1 
Enter fullscreen mode Exit fullscreen mode

✅ Summary

Component Status Notes
OIDC Provider One-time setup per AWS account
IAM Role Defined inline in main.tf
Policy Permissions Start with AdministratorAccess, scope down later
GitHub Workflow Uses configure-aws-credentials for OIDC login
No Secrets Required Secure, short-lived tokens – no static credentials

You’re now ready to securely run terraform apply from GitHub Actions using short-lived OIDC credentials with a minimal bootstrap setup.

Top comments (0)