DEV Community

Alexandre Rabello Santana
Alexandre Rabello Santana

Posted on • Edited on

2

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

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly — using the tools and languages you already love!

Learn More

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-...

AWS Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

👋 Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay