DEV Community

Alexandre Rabello
Alexandre Rabello

Posted on • Edited on

Github Actions — Terraform — CI/CD Multiple Accounts AWS

Terraform - Multiple AWS Accounts

This repository contains a GitHub Actions workflow for managing Terraform deployments across multiple AWS accounts. The workflow allows for planning, manual approval, and applying or destroying Terraform configurations.

Workflow: Terraform Plan, Approval, and Deploy

Workflow Dispatch Inputs

  • action: Specifies the action to perform (apply or destroy). Default is apply.
  • aws_account: Specifies the AWS account to deploy to (shared, network, production, stage, develop).
  • terraform_version: Specifies the version of Terraform to use. Default is 1.8.0.

Workflow Jobs

1. Plan

  • Runs on: ubuntu-latest
  • Permissions:
    • actions: read
    • issues: write
    • id-token: write
    • contents: write
  • Timeout: 5 minutes
  • Steps:
    • Checkout the code.
    • Configure AWS credentials based on the selected AWS account.
    • Install and run tflint for linting Terraform files.
    • Setup Terraform with the specified version.
    • Initialize Terraform.
    • Plan Terraform changes and save the plan.
    • Cache Terraform files.
    • Upload the Terraform plan as an artifact.

2. Approval

  • Needs: plan
  • Runs on: ubuntu-latest
  • Permissions:
    • actions: read
    • issues: write
    • id-token: write
    • contents: write
  • Steps:
    • Request manual approval from the specified approvers.

3. Deploy

  • Needs: approval
  • Runs on: ubuntu-latest
  • Permissions:
    • id-token: write
    • contents: write
  • Timeout: 20 minutes
  • Steps:
    • Checkout the code.
    • Configure AWS credentials based on the selected AWS account.
    • Setup Terraform with the specified version.
    • Download the Terraform plan artifact.
    • Move the Terraform plan.
    • Initialize Terraform.
    • Apply or destroy the Terraform plan based on the specified action.

Usage

To trigger the workflow, go to the Actions tab in your GitHub repository, select the Terraform - Multiple AWS Accounts workflow, and click on Run workflow. Fill in the required inputs and run the workflow.

Secrets

The following secrets need to be configured in your GitHub repository:

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_ROLE_ARN_NETWORK
  • AWS_ROLE_ARN_PROD
  • AWS_ROLE_ARN_DEVELOP
  • AWS_ROLE_ARN_STAGE
  • GITHUB_TOKEN (automatically provided by GitHub)

Notes

  • Ensure the roles specified in the AWS credentials have the necessary permissions to perform the Terraform actions.
  • Modify the role ARNs and other configurations as per your AWS setup.

For more information on GitHub Actions and Terraform, refer to the GitHub Actions documentation and Terraform documentation.


Code : deploy-to-terraform.yml


name: Terraform - Multiple AWS Accounts

on:
  workflow_dispatch:
    inputs:
      action:
        description: 'Action to perform (apply or destroy)'
        required: true
        default: 'apply'
      aws_account:
        description: 'AWS Account to deploy to (shared, network, production, stage, develop)'
        required: true
      terraform_version:
        description: 'Version of Terraform to use'
        required: true
        default: '1.8.0'

jobs:
  plan:
    runs-on: ubuntu-latest
    permissions:
      actions: read
      issues: write
      id-token: write # This is required for requesting the JWT
      contents: write  # This is required for actions/checkout
    timeout-minutes: 5
    steps:
      - name: Checkout Code
        uses: actions/checkout@v2

      - name: Configure AWS Credentials
        if: ${{ github.event.inputs.aws_account == 'network' }}
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN_NETWORK }}
          aws-region: us-east-1

      - name: Configure AWS Credentials
        if: ${{ github.event.inputs.aws_account == 'prod' }}
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN_PROD }}
          aws-region: us-east-1

      - name: Configure AWS Credentials
        if: ${{ github.event.inputs.aws_account == 'stage' }}
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN_STAGE }}
          aws-region: us-east-1

      - name: Configure AWS Credentials
        if: ${{ github.event.inputs.aws_account == 'develop' }}
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN_DEVELOP }}
          aws-region: us-east-1

      - name: Install TFLint
        run: |
          curl -L https://github.com/terraform-linters/tflint/releases/latest/download/tflint_linux_amd64.zip -o tflint.zip
          unzip tflint.zip
          sudo mv tflint /usr/local/bin/
          rm tflint.zip

      - name: Lint Terraform files
        run: tflint

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: ${{ github.event.inputs.terraform_version }}
        env:
          AWS_DEFAULT_REGION: us-east-1

      - name: Initialize Terraform
        run: terraform init -reconfigure

      - name: Plan Terraform changes
        run: terraform plan -out=tfplan

      - name: Cache Terraform files
        uses: actions/cache@v2
        with:
          path: |
            .terraform
            .terraform.lock.hcl
          key: ${{ runner.os }}-terraform-${{ hashFiles('**/*.tf') }}

      - name: Upload Terraform plan
        uses: actions/upload-artifact@v2
        with:
            name: tfplan
            path: tfplan

  approval:
    needs: plan
    runs-on: ubuntu-latest
    permissions:
      actions: read
      issues: write
      id-token: write # This is required for requesting the JWT
      contents: write  # This is required for actions/checkout
    steps:
      - name: Request Manual Approval
        uses: trstringer/manual-approval@v1
        with:
          secret: ${{ secrets.GITHUB_TOKEN }}
          approvers: alerabello
          minimum-approvals: 1
          additional-approved-words: 'Approve, Approved, approve, approved'
        timeout-minutes: 10

  deploy:
    needs: approval
    runs-on: ubuntu-latest
    permissions:
      id-token: write # This is required for requesting the JWT
      contents: write  # This is required for actions/checkout
    timeout-minutes: 20
    steps:
      - name: Checkout Code
        uses: actions/checkout@v2

      - name: Configure AWS Credentials
        if: ${{ github.event.inputs.aws_account == 'network' }}
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN_NETWORK }}
          aws-region: us-east-1

      - name: Configure AWS Credentials
        if: ${{ github.event.inputs.aws_account == 'prod' }}
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN_PROD }}
          aws-region: us-east-1

      - name: Configure AWS Credentials
        if: ${{ github.event.inputs.aws_account == 'stage' }}
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN_STAGE }}
          aws-region: us-east-1

      - name: Configure AWS Credentials
        if: ${{ github.event.inputs.aws_account == 'develop' }}
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN_DEVELOP }}
          aws-region: us-east-1

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v3
        with:
          terraform_version: ${{ github.event.inputs.terraform_version }}

      - name: Download repository artifact
        uses: actions/download-artifact@v2
        with:
          name: tfplan
          path: ./tfplan

      - name: Move Terraform plan
        run: mv ./tfplan/tfplan ./tfplan.tfplan

      - name: Initialize Terraform
        run: terraform init -reconfigure

      - name: Apply or Destroy Terraform
        run: |
          if [ "${{ github.event.inputs.action }}" == "apply" ]; then
            terraform apply -auto-approve ./tfplan.tfplan
          elif [ "${{ github.event.inputs.action }}" == "destroy" ]; then
            terraform destroy -auto-approve
          else
            echo "Invalid action specified: ${{ github.event.inputs.action }}"
            exit 1
          fi
Enter fullscreen mode Exit fullscreen mode

Top comments (1)

Collapse
 
der_gopher profile image
Alex Pliutau

Great write-up! We also have a bunch of articles on Github Actions in our Newsletter, check it out - packagemain.tech/p/github-actions-...