Using Checkov for Infrastructure as Code Security Audits

Security is a major component of all cloud architecture frameworks, such as Google Cloud’s Architecture Framework or the Amazon Web Services (AWS) Well-Architected Framework. These frameworks are superb teaching tools and should remain top-of-mind while crafting designs. However, frameworks are useless in practicality; one must assume that the engineer (a fallible human) has read, understood, and applied the knowledge correctly.

Searching the high seas for automated security.

The ideal solution is to create a system that uses well crafted frameworks, agreed upon security policies, and community guidelines to audit raw infrastructure as code configurations. This actively prevents security misconfigurations prior to deployment or when crafting and sharing public modules. My solution of choice today is Checkov, an open source infrastructure as code static analysis tool published by Bridgecrew. More on that later.

In this post, I’ll start by explaining the need for infrastructure as code security auditing by looking at the State of Open Source Terraform Security report from Bridgecrew. From there, I’ll share how Checkov audits my Terraform code by way of GitLab’s continuous integration (CI) workflows.

State of Open Source Terraform Security

I’ll start by sharing Bridgecrew’s recently published State of Open Source Terraform Security report. It’s crammed full of interesting data points, including the massive growth in Terraform Registry contributions that began surging earlier in 2020. According to the report, “Nearly 1 in 2 modules within the Terraform Registry is misconfigured” when audited against security policies as defined by the Center of Internet Security (CIS) and others. The top security config offenders center around encryption, logging, and backup and recovery.

Monthly Terraform Registry growth is surging.

Much more code is available to consume but nearly half of it has security vulnerabilities baked in – not awesome! I believe that this underlines the need to add proactive security auditing to a continuous integration (CI) pipeline. This does not let folks using private modules off the hook; it makes sense to audit internally written code, too.

Checkov provides the data used in this report by scanning over 2600 Terraform Registry modules across AWS, Azure, and Google Cloud. I’ve been using this tool for several months to great success – time to dig in!

Checkov and Continuous Integration

All of my cloud environments are constructed and maintained by infrastructure as code tools, such as Terraform, using GitLab as the CI engine. I suggest checking out Continuous Integration Fundamentals if you’re new to the concept.

Note: CI is not required to use Checkov; I can simply grab the tool and run it against locally sourced configurations, too.

My engineering peers trigger a suite of security and linting tests as part of the “validate” stage when a new feature branch is pushed, including one that runs Checkov in Bridgecrew’s published container on the Docker Hub. A snipet of the GitLab CI YAML configuration is shown below:

The Checkov job to audit security settings.

Here’s a breakdown of this job’s lifecycle:

  1. When GitLab triggers the checkov job, a Kubernetes pod is deployed using the bridgecrew/checkov:latest container image based on the “slim” Docker Python image. A nice change from Alpine! :-)
    • This image contains the latest release of Checkov.
  2. GitLab clones the project’s files over via git.
  3. The checkov -d . command executes Checkov and recursively looks for any Terraform files in the root directory.

Terraform Scan Results

When invoked, Checkov provides a pleasant ASCII splash art along with scan results. The first time I ran Checkov I thought it was broken because the test ran instantly without any failed results. I needed to introduce some security vulnerabilities!

$ checkov -d .
       _               _              
   ___| |__   ___  ___| | _______   __
  / __| '_ \ / _ \/ __| |/ / _ \ \ / /
 | (__| | | |  __/ (__|   < (_) \ V / 
  \___|_| |_|\___|\___|_|\_\___/ \_/  
by | version: 1.0.484 
terraform scan results:
Passed checks: 5, Failed checks: 0, Skipped checks: 0

I snagged a Terraform configuration for an internal eCommerce application and disabled Amazon EBS volume encryption. Checkov reported the vulnerability, with a file location and guide URL, as shown below:

A failed Checkov check.

At this point I can read Bridgecrew’s documentation to see why check CKV_AWS_3 failed. In this scenario, the policy states that data stored in Amazon EBS must be securely encrypted. The contributing engineer has all they need to fix the issue, push a new commit, and try again.

Continuous Integration Perspective

GitLab CI visualizes the pipeline and reports a failure with the checkov job. This is handy for understanding the logical stages of the workflow and dependencies, if they exist. In this case, I allowed the violation for a lab deployment and then later destroyed the resources using the destroy job.

Validate, Plan, Apply, oh my!

While no single tool is foolproof, CI makes it trivial to add as many tests, checks, audits, and linting tasks as are desired without adding operational toil.

Next Steps

Please accept a crisp high five for reaching this point in the post!

If you’d like to learn more about Infrastructure as Code, or other modern technology approaches, head over to the Guided Learning page.