Using Terrascan for Static Code Analysis of Your Infrastructure Code (part 2)
You followed my advice and configured terrascan as a pre-commit hook to scan your terraform code for security weaknesses on your desktop before being committed into your repository.
The setup allows you to quickly check any security issues before they’re introduced into your AWS environment.
You’ve been using it for a while and you’re pretty happy that it has caught some issues before you accidentally pushed them to your GitHub repository.
Unfortunately, not all of your co-workers have it installed and some nasty bugs have been committed into one of your feature branches.
Luckily, terrascan can be used as a step in your continuous integration (CI) pipeline. This would allow you to test your terraform code before any security weaknesses are merged into your master branch.
How do you do that?
Let’s create an example repo.
$ mkdir terrascan-example && cd terrascan-example
$ git init .
I’ll be using “hub” for this example on my mac. If you don’t have it installed you can follow the instructions for your OS here. Here’s an example using the org “cloud-security-musings” and the repo “terrascan-example”. You’ll need to use your own username/repo combination:
$ hub create -d "terrascan usage example" cloud-security-musings/terrascan-example
You should now have a new repository created in GitHub and configured as a remote named “origin”. Let’s confirm.
$ git remote -v
origin git@github.com:cloud-security-musings/terrascan-example.git (fetch)
origin git@github.com:cloud-security-musings/terrascan-example.git (push)
As in part 1 of this blog series, you need to add a “.pre-commit-config.yaml” file added to the top-level of your repository with the following contents:
repos:
- repo: https://github.com/cesar-rodriguez/terrascan
rev: v0.2.0
hooks:
- id: terrascan
pass_filenames: false
args: [-l=infra] #NOTE: this command should point to the directory containing your .tf files
verbose: true
Let’s also add an example terraform file to “infra/s3.tf” containing a security issue, so we can test.
resource "aws_s3_bucket" "my_s3_bucket" {
bucket = "my-s3-bucket"
acl = "public-read-write"
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
kms_master_key_id = "$"
sse_algorithm = "aws:kms"
}
}
}
logging {
target_bucket = "logging_bucket"
target_prefix = "log/"
}
tags = {
Name = "my-s3-bucket"
Environment = "production"
}
}
Finally, we will follow the instructions here to run pre-commit as part of CI in a GitHub action. To do this you will add the following code to a file named “.github/workflows/precommit.yaml”:
name: pre-commit
on: [push]
jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-python@v1
- name: set PY
run: echo "::set-env name=PY::$(python --version --version | sha256sum | cut -d' ' -f1)"
- uses: actions/cache@v1
with:
path: ~/.cache/pre-commit
key: pre-commit|${ }|${ }
- uses: pre-commit/action@v1.0.0
Now, let’s push our changes and see what happens:
$ git add .
$ git commit -m "testing github actions"
$ git push --set-upstream origin master
Now the action should run to evaluate your s3.tf file since we configured it to run on every push. You can browse to the GitHub actions tab in your repo to see the output of the action. Here’s what I see for my repo at https://github.com/cloud-security-musings/terrascan-examples/actions.
Since we had a security weakness in the s3.tf file, the GitHub action failed. If you click on “pre-commit”, you can see the details of the CI job where the failure is shown:
As the error message indicates. Our aws_s3_bucket resource has a “public-read-write” ACL. Let’s fix the issue by updating infra/s3.tf with the following:
resource "aws_s3_bucket" "my_s3_bucket" {
bucket = "my-s3-bucket"
acl = "private"
server_side_encryption_configuration {
rule {
apply_server_side_encryption_by_default {
kms_master_key_id = "$"
sse_algorithm = "aws:kms"
}
}
}
logging {
target_bucket = "logging_bucket"
target_prefix = "log/"
}
tags = {
Name = "my-s3-bucket"
Environment = "production"
}
}
Then execute the commands below:
$ git add .
$ git commit -m "fixes public bucket"
$ git push
$ hub browse
As expected, you should see the action now succeed indicated by a green checkmark:
What if I don’t use GitHub Actions for CI?
If you don’t use GitHub or GitHub actions for continuous integration, a similar setup can be accomplished with any CI tool. Here’s documentation on how to run pre-commit in other continuous integration tools: https://pre-commit.com/#usage-in-continuous-integration
What other security checks you perform on your CI builds for infrastructure code?