Secure Terraform - Part 1 - tfsec

6 minute read

This blog was posted as part of the Festive Tech Calendar 2022. I really want to thank the organizers for helping set this up!

Look for the hashtag #FestiveTechCalendar2022 on social media! Make sure to check out everyone else’s work when you’re done here

This is part 1 of the Secure Terraform series. You can read the series of articles here:

Introduction

Securing Terraform starts before we even deploy anything. Our tooling is a great place to start! We can leverage one or more static code analyzers to look for misconfigurations, security issues, and other problems. Many of these great tools not only plug into our CI/CD pipeline, they also work within our IDEs. This allows us to catch issues while we work. We can also leverage pre-commit hooks to catch things before we even commit our code. With Cloud infrastructure, its easy to make mistakes, and these tools can help us catch them.

terraform logo

Today we are going to look at a one of these tools, tfsec, and how we can leverage it to secure our Terraform code. I’ll work through the rest of the ones in the list in follow on posts, but there are many more out there. I encourage you to check them out and see which ones work best for you.

tfsec

tfsec logo

Let’s start with tfsec by aquasecurity. Aquasecurity supports multiple amazing tools like trivy and tfsec. Tfsec is an open-source tool available on GitHub at https://github.com/aquasecurity/tfsec. The docs are hosted at: https://aquasecurity.github.io/tfsec/. There are some great guides for installing it and configuring it for GitHub Actions. Tfsec even has an integration with GitHub Advanced security to show the results of the scan in the security tab of the repository.

Installation

We can run tfsec from a docker container or we can install it locally via homebrew, chocolatey, go, or the releases page.

After tfsec is installed (or docker is setup), we can run it against our Terraform code. Running it with defaults is quite easy, just invoking the command tfsec will run it against the current directory. If it finds files it will scan them and output the results. By default it checks all rules and outputs all severities found.

Running tfsec

Let’s take a look at the output of tfsec against a simple Terraform file:

resource "azurerm_storage_account" "sa" {
  name                     = "samplesa${random_uuid.uuid.result}"
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
  account_tier             = "Standard"
  account_replication_type = "LRS"
}

Running tfsec against this file produces the following output:

$ tfsec

Result #1 CRITICAL Storage account uses an insecure TLS version. 
─────────────────────────────────────────────────────────────────────────────────────────
  insecure-terraform/main.tf:8-14
─────────────────────────────────────────────────────────────────────────────────────────
    8    resource "azurerm_storage_account" "sa" {
    9      name                     = "samplesa${random_uuid.uuid.result}"
   10      resource_group_name      = azurerm_resource_group.rg.name
   11      location                 = azurerm_resource_group.rg.location
   12      account_tier             = "Standard"
   13      account_replication_type = "LRS"
   14    }
─────────────────────────────────────────────────────────────────────────────────────────
          ID azure-storage-use-secure-tls-policy
      Impact The TLS version being outdated and has known vulnerabilities
  Resolution Use a more recent TLS/SSL policy for the load balancer

  More Information
  - https://aquasecurity.github.io/tfsec/latest/checks/azure/storage/use-secure-tls-policy/
  - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/storage_account#min_tls_version
─────────────────────────────────────────────────────────────────────────────────────────


  timings
  ──────────────────────────────────────────
  disk i/o             28.432µs
  parsing              509.357µs
  adaptation           93.3µs
  checks               5.59119ms
  total                6.222279ms

  counts
  ──────────────────────────────────────────
  modules downloaded   0
  modules processed    2
  blocks processed     12
  files read           7

  results
  ──────────────────────────────────────────
  passed               7
  ignored              0
  critical             1
  high                 0
  medium               0
  low                  0

  7 passed, 1 potential problem(s) detected.

As you can see, tfsec found a potential problem with the TLS version being used. This could be a critical issue and should be addressed. We can see the ID of the rule, the impact, and the resolution. We can also see a link to the documentation for the rule and the link to the documentation for the resource.

I can also apply a custom configuration to tfsec to fine tune how I want to scan my code. This can be either a file I pass to tfsec or a config.json or config.yml inside a .tfsec directory. We could override the minimum severity to only show critical issues, or we could ignore a specific rule.

If I had misconfigured my storage account to accept traffic on http instead of HTTPS, tfsec would have found that as well. But maybe I don’t agree with the default severity of that rule. I can override the severity of the rule to be critical instead of high.

severity_overrides:
  azure-storage-enforce-https: CRITICAL
minimum_severity: MEDIUM

I’ve got a few simple misconfigurations checked into my sample repository at secure-terraform-on-azure. They aren’t on the main branch, but the demos branch.

VSCode

What about adding tfsec to VSCode? Well, we can install the tfsec extension. This will use the installed version of tfsec to scan our code. It will also show the results so we can see them right in our editor and go to the line where the issue is.

tfsec extension in vscode
tfsec extension in vscode

Great! Now we can see the issues right in our editor. But what if we forget to check the problems? How do we catch the issues and resolve them in our pipeline?

GitHub Actions

Aquasecurity has provided a few GitHub Actions and sample workflows to scan our terraform during every pull request. We can use the tfsec-action to scan our code.

name: tfsec
on:
  push:
    branches:
      - main
  pull_request:
jobs:
  tfsec:
    name: tfsec
    runs-on: ubuntu-latest

    steps:
      - name: Clone repository
        uses: actions/checkout@master
      - name: tfsec
        uses: aquasecurity/tfsec-action@v1.0.0

Now because I’ve got some tf nested, I added the following line:

          additional_args: --force-all-dirs

All of the available options and parameters are documented on the actions page.

This will run tfsec against our repository on every check-in to main and every pull request. If we have insecure code, it will fail the workflow.

Failing build on GitHub
Failing build on GitHub

There is another action, tfsec-pr-commenter-action that is supposed to automatically add comments to the pull request with the results of the scan. I haven’t been able to get it to work because of my file nesting, but I’m sure it will be fixed soon.

Pre-commit Hooks

The last thing I want to talk about is pre-commit hooks. Pre-commit hooks are a way to run a script or command before you commit your code. This is a great way to make sure you don’t commit any code that doesn’t pass your checks.

There is a great framework for running pre-commit hooks called pre-commit. It is a python package that you can install with pip. Once you have it installed, you can add a .pre-commit-config.yaml file to your repository. This file will contain the hooks you want to run.

There is a project for setting up pre-commit hooks to scan terraform. It is called pre-commit-terraform. It will run tfsec against your code and fail the commit if there are any issues.

This runs BEFORE you code gets committed and before it gets pushed to GitHub. Your CI/CD workflow will never run if the pre-commit hook blocks the commit.

Conclusion

Terraform is a great tool for infrastructure as code. Leveraging smart tools like tfsec at various places in the development cycle can help you find and fix those issues before they become a problem. Join me again soon as we look at more tools to help you secure your infrastructure.