Infrastructure as Code (IaC) has revolutionized how we provision and manage cloud resources. Tools like Terraform, Pulumi, and OpenTofu allow us to define infrastructure using code, making it versionable, repeatable, and scalable. However, with great power comes great responsibility. Misconfigurations in IaC can lead to massive security breaches, such as publicly exposed data storage or overly permissive access roles.
This is where Static Application Security Testing (SAST) comes in. SAST tools analyze your source code to find security vulnerabilities before the code is deployed. In this article, we'll explore how to apply SAST to a Terraform project using Checkov, a popular open-source static analysis tool for IaC, and how to automate this process using GitHub Actions.
(Note: We are intentionally avoiding tfsec for this demonstration to explore other powerful alternatives).
Why Checkov?
Checkov, created by Bridgecrew (now part of Prisma Cloud), is a static code analysis tool for IaC. It scans cloud infrastructure provisioned using Terraform, Terraform plan, Cloudformation, Kubernetes, Dockerfile, Serverless, or ARM Templates and detects security and compliance misconfigurations. It includes hundreds of built-in policies covering security and compliance best practices for AWS, Azure, and Google Cloud.
The Demo Scenario: A Vulnerable S3 Bucket
Let's start by creating a simple Terraform configuration for an AWS S3 bucket. We will intentionally introduce a security misconfiguration: making the bucket public without encryption.
Create a file named main.tf:
# main.tf
provider "aws" {
region = "us-east-1"
}
resource "aws_s3_bucket" "my_vulnerable_bucket" {
bucket = "my-company-public-data-bucket-12345"
}
# Misconfiguration 1: Public Read Access
resource "aws_s3_bucket_acl" "example" {
bucket = aws_s3_bucket.my_vulnerable_bucket.id
acl = "public-read"
}
If we were to deploy this, anyone on the internet could read the contents of this bucket. Let's see how Checkov can catch this before it reaches production.
Running Checkov Locally
You can easily install Checkov using Python's package manager, pip:
pip install checkov
Once installed, navigate to the directory containing your main.tf and run:
checkov -d .
The Output
Checkov will scan the directory and output a detailed report. You will see something like this:
_ _
___| |__ ___ ___| | _______ __
/ __| '_ \ / _ \/ __| |/ / _ \ \ / /
| (__| | | | __/ (__| < (_) \ V /
\___|_| |_|\___|\___|_|\_\___/ \_/
By Prisma Cloud | version: 3.1.0
terraform scan results:
Passed checks: 0, Failed checks: 3, Skipped checks: 0
Failed checks:
1. Check: CKV_AWS_20: "S3 Bucket has an ACL defined which allows public READ access."
FAILED for resource: aws_s3_bucket_acl.example
File: /main.tf:10-13
Guide: https://docs.prismacloud.io/en/enterprise-edition/policy-reference/aws-policies/s3-policies/s3-1-acl-read-access
2. Check: CKV_AWS_19: "Ensure all data stored in the S3 bucket is securely encrypted at rest"
FAILED for resource: aws_s3_bucket.my_vulnerable_bucket
File: /main.tf:6-8
3. Check: CKV_AWS_21: "Ensure all data stored in the S3 bucket have versioning enabled"
FAILED for resource: aws_s3_bucket.my_vulnerable_bucket
File: /main.tf:6-8
Checkov successfully identified our public ACL misconfiguration (CKV_AWS_20) and also pointed out that we are missing encryption at rest and versioning!
Automating SAST with GitHub Actions
Running SAST tools locally is great, but to truly secure your pipeline, you must automate it. We can use GitHub Actions to run Checkov on every Pull Request. This ensures no vulnerable code can be merged into the main branch.
Create a .github/workflows/checkov.yml file in your repository:
name: Checkov IaC Scan
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
scan:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Run Checkov action
uses: bridgecrewio/checkov-action@master
with:
directory: .
framework: terraform
output_format: cli
soft_fail: false # Set to true if you don't want the build to fail on violations
How it works:
-
Trigger: The workflow runs on any push or pull request to the
mainbranch. - Checkout: It checks out your repository code.
-
Checkov Action: It uses the official
bridgecrewio/checkov-actionto scan the current directory (.) specifically looking for Terraform files. -
Soft Fail: By setting
soft_fail: false, the GitHub Action will fail if any vulnerabilities are found, blocking the Pull Request from being merged.
Fixing the Code
To fix our pipeline, we need to address the vulnerabilities in main.tf. Here is the secure version:
# main.tf
provider "aws" {
region = "us-east-1"
}
resource "aws_s3_bucket" "my_secure_bucket" {
bucket = "my-company-secure-data-bucket-12345"
}
# Fix 1: Private ACL
resource "aws_s3_bucket_acl" "example" {
bucket = aws_s3_bucket.my_secure_bucket.id
acl = "private"
}
# Fix 2: Enable Versioning
resource "aws_s3_bucket_versioning" "versioning_example" {
bucket = aws_s3_bucket.my_secure_bucket.id
versioning_configuration {
status = "Enabled"
}
}
# Fix 3: Enable Server-Side Encryption
resource "aws_s3_bucket_server_side_encryption_configuration" "example" {
bucket = aws_s3_bucket.my_secure_bucket.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
Now, if you commit these changes, the GitHub Action will run Checkov again, and it will pass successfully!
Conclusion
Securing Infrastructure as Code is not optional; it is a critical part of modern cloud architecture. By integrating a SAST tool like Checkov into your GitHub Actions pipeline, you establish a strong first line of defense against misconfigurations. It shifts security "left," empowering developers to fix issues before they ever see the light of a production environment.
Demo Repository: You can find the complete code for this demo in my GitHub Repository: https://github.com/Cristhian465/Research-Team-Work-N-02-Sast-tools-for-infraestructure
If you found this article helpful, please leave a like or comment below! Have you used Checkov or other SAST tools? Share your experience!
Top comments (0)