Run Terraform with GitHub Actions#

In previous post Run Terraform within GitHub Codespaces the Terraform environment was setup within GitHub Codespaces. The next step is to run Terraform with GitHub Actions via Terraform Cloud as part of a workflow and scan the Terraform code with KICS is the first step to reduce technical debt as described in the post KICS.

Let’s start with the workflow file .github/workflows/terraform.yml to run a KICS scan to verify the Terraform code. The workflow is triggered on push and pull request on the master branch. The Terraform code is checked out and the KICS scan is executed. The KICS scan is configured to run on the Terraform code in the directory terraform and the results are stored in the directory build. The KICS scan is configured to run on the Terraform platform and the output formats are JSON and SARIF so the results can be processed later. The KICS scan is configured to fail on high and medium severity issues. The KICS scan is configured to not add comments to the pull request and to exclude the query with the ID 1e434b25-8763-4b00-a5ca-ca03b7abbb66 during the scan.

.github/workflows/terraform.yml with KICS scan job#
---
name: Terraform

on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master

jobs:
  kics:
    name: KICS scan
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Code
        uses: actions/checkout@v3

      - name: Create directory build
        run: mkdir -p build

      - name: Run KICS Scan with SARIF result
        uses: checkmarx/[email protected]
        with:
          path: 'terraform'
          output_path: 'build'
          platform_type: terraform
          output_formats: 'json,sarif'
          fail_on: high,medium
          enable_comments: false
          exclude_queries: 1e434b25-8763-4b00-a5ca-ca03b7abbb66

In the second step the file .github/workflows/terraform.yml is extended to run Terraform with GitHub Actions. The Terraform version is configured with the environment variable TERRAFORM_VERSION. The Terraform code is checked out and then Terraform code is checked if it is formatted correctly. After this the Terraform code is initialized, validated, and then a dry-run is executed. If the dry-run is successful and the GitHub Action runs as part of a push event on the master branch.

.github/workflows/terraform.yml extended with Terraform job#
env:
  TERRAFORM_VERSION: '1.4.6'

jobs:
  ...

  terraform:
    name: Terraform
    runs-on: ubuntu-latest
    needs: kics

    steps:
      - name: Checkout Code
        uses: actions/checkout@v3

      - name: Set up Terraform
        uses: hashicorp/setup-terraform@v2
        with:
          terraform_version: ${{ env.TERRAFORM_VERSION }}
          cli_config_credentials_token: ${{ secrets.TF_API_TOKEN }}

      - name: Terraform Format
        id: fmt
        run: terraform -chdir=terraform fmt -check
        continue-on-error: true

      - name: Terraform Init
        run: terraform -chdir=terraform init

      - name: Terraform Validate
        id: validate
        run: terraform -chdir=terraform validate -no-color

      - name: Terraform Plan
        id: plan
        if: github.event_name == 'pull_request'
        run: terraform -chdir=terraform plan -no-color -input=false
        continue-on-error: true

      - name: Terraform Plan Status
        if: steps.plan.outcome == 'failure'
        run: exit 1

      - name: Terraform Apply
        if: github.ref == 'refs/heads/master' && github.event_name == 'push'
        run: terraform -chdir=terraform apply -auto-approve -input=false

For the workflow to work correctly the secret variable TF_API_TOKEN needs to be configured in the repository settings. The Terraform Cloud API token is used to authenticate with Terraform Cloud and can be created in the Terraform Cloud user settings. The Terraform Cloud API token is stored as secret variable in the repository settings within GitHub to prevent the token from being exposed in the workflow file.

From this point every pull request on the master branch will be checked with KICS and Terraform Cloud if it could be deployed successfully. If the pull request is merged into the master branch the Terraform code will be deployed automatically without any manual interaction.