Skip to content

Scan your terraform infrastructure using tfsec

Published: at 03:02 PM

Recently, I’ve been playing with GitLab, mostly because I’ve never used it so much, and at the same time, I stumbled upon tfsec, which is a really cool Terraform scanner! tfsec uses static analysis to catch any potential misconfigurations. So I thought to myself that it would be nice to combine those two together and include tfsec into my Merge Request pipeline.

About tfsec

tfsec can analyze your terraform configurations and generate reports. It has a lot of cool features:

example report using markdown

Gitlab CI setup

We want to run our tfsec scans only when a Merge Request is opened, scan terraform files located on the feature branch, and put a comment with our scanning results.

Before we start writing our configuration, we need to generate our Access Token and add it as an environment variable in our project configuration on GitLab.

To do it, we need to go into our project and then Settings—>Access Tokens how to get to access token We click Add new token, we select api scope for our token, role for it (I think reporter makes the most sense in our case) and we are ready to go. access token settings Save your token afterwards as you won’t be able to access it again! Now when we have our token, we need to go to our CI/CD configuration. Similar story as with Access Token, we go into our project and then Settings—>CI/CD.

There will be multiple settings for us to choose from, but we are interested in Variables. Expand it, and click Add variable. We paste our token there and we set up key for it. Remember to turn on the flag Mask variable so our token value is not visible in the pipeline. ci/cd variable settings When we are done with that, we are ready to write our tfsec commenter pipeline! :D

Gitlab CI config

In the root directory of our terraform repository we need a .gitlab-ci.yml file which is used for our pipeline configuration.

As we want to run our pipeline only when Merge Request is opened, we begin our configuration with:

workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'

We are going to have 2 stages in our pipeline: scan and comment. So…

stages:
  - scan
  - comment

Our first stage is a scan

tfsec-scan:
  stage: scan
  image:
    name: aquasec/tfsec-ci:latest
  script:
    - tfsec . -f markdown --out results.md || true
  artifacts:
    paths:
      - "results.md"

We are using tfsec-ci image and we output scan results to results.md.

And our commenting stage

comment_on_merge_request:
  stage: comment
  image: alpine:latest
  script: |
    apk add --update curl jq
    results=$(cat results.md)
    json_payload=$(jq -n --arg body "$results" '{body: $body}')
    curl --location --request POST "https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes" --header "PRIVATE-TOKEN: $TFSEC" --header "Content-Type: application/json" --data "$json_payload"
  needs:
    - job: tfsec-scan
      artifacts: true

Let’s see how it works

I’ve made a Merge Request with some dubious configuration of AWS RDS and… scan comment It works! Our pipeline added a scan result to our Merge Request :D