Deploy Terraform Code using GitHub Actions with OpenID Connect (OIDC) identity providers (AWS Cloud)

Deploy Terraform Code using GitHub Actions with OpenID Connect (OIDC) identity providers (AWS Cloud)


Overview:

OpenID Connect (OIDC) allows your GitHub Actions workflows to access resources in Amazon Web Services (AWS), without needing to store the AWS credentials as long-lived GitHub secrets.

This guide explains how to configure AWS to trust GitHub's OIDC as a federated identity, and includes a workflow example for the aws-actions/configure-aws-credentials that uses tokens to authenticate to AWS and access resources.

Prerequisites:

  • To learn the basic concepts of how GitHub uses OpenID Connect (OIDC), and its architecture and benefits, see "About security hardening with OpenID Connect."
  • Before proceeding, you must plan your security strategy to ensure that access tokens are only allocated in a predictable way. To control how your cloud provider issues access tokens, you must define at least one condition, so that untrusted repositories can’t request access tokens for your cloud resources. For more information, see "About security hardening with OpenID Connect."

Step 1 — Create a repo on Github

aws-oidc-terraform-github (Private)

Step 2 — Create OIDC Provider & Role in AWS Account

Create a file cf-basic.yml (Cloud formation File)

Name of Github user : "aslamchandio"

GitHub Repo name: "aws-oidc-terraform-github"

OIDC Provider: token.actions.githubusercontent.com

Role: github-actions-role

S3 Bucket: aslam-aws-terraform-github (Versioning enable)

DynamoDB Table: aslam-aws-terraform-github

Note: (S3 Bucket & DynamoDB Table for terraform remote state & locking purpose)


Parameters:
  GitHubOrg:
    Description: Name of GitHub organization/user (case sensitive)
    Default: "aslamchandio"
    Type: String
  RepositoryName:
    Description: Name of GitHub repository (case sensitive)
    Default: "aws-oidc-terraform-github"
    Type: String
  OIDCProviderArn:
    Description: Arn for the GitHub OIDC Provider.
    Default: ""
    Type: String
  OIDCAudience:
    Description: Audience supplied to configure-aws-credentials.
    Default: "sts.amazonaws.com"
    Type: String

Conditions:
  CreateOIDCProvider: !Equals [!Ref OIDCProviderArn, ""]
Resources:
  Role:
    Type: AWS::IAM::Role
    Properties:
      RoleName: github-actions-role
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Action: sts:AssumeRoleWithWebIdentity
            Principal:
              Federated: !If
                - CreateOIDCProvider
                - !Ref GithubOidc
                - !Ref OIDCProviderArn
            Condition:
              StringEquals:
                token.actions.githubusercontent.com:aud: !Ref OIDCAudience
              StringLike:
                token.actions.githubusercontent.com:sub: !Sub repo:${GitHubOrg}/${RepositoryName}:*
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AdministratorAccess

  GithubOidc:
    Type: AWS::IAM::OIDCProvider
    Condition: CreateOIDCProvider
    Properties:
      Url: https://token.actions.githubusercontent.com
      ClientIdList:
        - sts.amazonaws.com
      ThumbprintList:
        - 6938fd4d98bab03faadb97b34396831e3780aea1
        #- 1c58a3a8518e8759bf075b76b750d4f2df264fcd

  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: aslam-aws-terraform-github
      VersioningConfiguration:
        Status: Enabled
        
  DynamoDBTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: aslam-aws-terraform-github
      AttributeDefinitions:
        - AttributeName: LockID
          AttributeType: S
      KeySchema:
        - AttributeName: LockID
          KeyType: HASH
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5    

    

Outputs:
  Role:
    Value: !GetAtt Role.Arn
        

aws cloudformation create-stack \
--stack-name cf-basic \
--template-body file://cf-base.yml \
--capabilities "CAPABILITY_IAM" "CAPABILITY_NAMED_IAM"        

Update provider.tf file


Step 3 — Clone repo from Github on your local machine

Step 4 — Create Folders in local Repo in Hierarchical way

1- Under aws-oidc-terraform-github repo create folder .github

2- under .github folder create workflows folder

3- under workflows folder create Github action files.

Step 5 — Github Actions Files

vpc-ci-dev-create.yml (For Creating AWS Resources)

Name: vpc-ci-dev-create

Branch: GitHub Action Trigger always run from Main branch

Paths: only changes done from aws-eks-vpc-production

AWS Account-Number: 123456789123 (Yours Account Number)

Run Env: Latest Ubuntu with terraform install



name: vpc-ci-dev-create
on:
  push:
    branches:
      - main
    paths:
      - "aws-eks-vpc-production/*"
env:
  # TF_LOG: INFO
  AWS_ACCOUNT_NUMBER: 123456789123
defaults:
  run:
    shell: bash
    working-directory: ./aws-eks-vpc-production
permissions:
  contents: read
jobs:
  deploy-dev:
    runs-on: ubuntu-latest
    # These permissions are needed to interact with GitHub's OIDC Token endpoint. New
    permissions:
      id-token: write
      contents: read
    steps:
      - name: "Checkout"
        uses: actions/checkout@v3
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-region: us-east-1
          role-to-assume: arn:aws:iam::${{env.AWS_ACCOUNT_NUMBER}}:role/github-actions-role
          role-session-name: Session-GitHubActions
      - name: Setup Terraform with specified version on the runner
        uses: hashicorp/setup-terraform@v2
        # with:
        #   terraform_version: 1.4.6
      - name: Terraform format
        id: fmt
        run: terraform fmt -check
      - name: Terraform init
        id: init
        run: terraform init
      - name: Terraform validate
        id: validate
        run: terraform validate
      - name: Terraform plan
        id: plan
        run: terraform plan 
        continue-on-error: true
      - name: Terraform Plan Status
        if: steps.plan.outcome == 'failure'
        run: exit 1
      - name: Terraform Apply
        run: terraform apply -auto-approve 
        

vpc-ci-dev-destroy.yml (For Destroying AWS Resources)


name: vpc-ci-dev-destroy
on: workflow_dispatch
env:
  TF_LOG: INFO
  AWS_ACCOUNT_NUMBER: 123456789123
permissions:
  contents: read
jobs:
  destroy:
    runs-on: ubuntu-latest
    defaults:
      run:
        shell: bash
        working-directory: ./aws-eks-vpc-production
    # These permissions are needed to interact with GitHub's OIDC Token endpoint.
    permissions:
      id-token: write
      contents: read
    steps:
      - name: "Checkout"
        uses: actions/checkout@v3
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-region: us-east-1
          role-to-assume: arn:aws:iam::${{env.AWS_ACCOUNT_NUMBER}}:role/github-actions-role
          role-session-name: Session-GitHubActions
      - name: Setup Terraform with specified version on the runner
        uses: hashicorp/setup-terraform@v2
        with:
          terraform_version: 1.6.5
      - name: Terraform init
        id: init
        run: terraform init
      - name: Terraform Destroy
        run: terraform destroy -auto-approve        

Step 6 — Create .gitignore file in terraform main folder

.gitignore (Ignore .terraform & .terraform.local.hcl file if you already run terraform on local machine


.terraform/
.terraform.lock.hcl        

Step 7 — Switched from main to feature branch

We don't want push our terraform code into main branch that's why first push code into feature branch then Merage into main branch

bellow commands used in above images


git checkout -b feature

git add .

git status

git commit -m "Adding Terraform and Github action Files"

git push -u origin feature
        

Step 8 — Check Terraform Code on GitHub

see github main branch is empty

Terraform Code in feature branch

Step 9 — Check Terraform Code on GitHub

copy terraform code from feature to main branch using compare & pull request

All Code copy into main branch

Step 10 — Check Terraform Code deploy on GitHub Actions


Step 10 — Check AWS Resources on Console


Check terraform.tfstate file in s3 bucket

Check DynamoDB Table

Step 11 — Destroy AWS Resource from Github Actions

using here vpc-ci-dev-destroy.yml

Links:

https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services

https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html







Elliott A.

Senior System Reliability Engineer / Platform Engineer

1 年

Found this article at the right time. It's just what the Dr. ordered.

  • 该图片无替代文字

要查看或添加评论,请登录

Aslam Chandio的更多文章

社区洞察

其他会员也浏览了