Github Actions — Terraform — CI/CD Multiple Accounts AWS

RMAG news

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: arn:aws:iam::000000000:role/TESTE-GITHUB-ACTIONS
aws-region: us-east-1
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

– 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_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
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: arn:aws:iam::000000000:role/TESTE-GITHUB-ACTIONS
aws-region: us-east-1
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

– 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