Posts in this Series
- Getting Started
- Static Code Analysis - What your reading now.
- Unit Testing
- Functional Testing
In the previous article Getting Started we setup pre-commit
with some basic checks in our Cloudformation Repo. In this article we will take a look at the Static Code Analysis tools available for Cloudformation.
Static Code Analysis
Static Code Analysis is a method of testing code without actually running it. The most common types of Static Code Analysis is Linters and Static Application Security Testing (SAST). SAST tools share a common goal of making code more secure, while linters come in many varieties. A linter may do all or any of the following: catch syntax errors, find bugs, enforce code styling.
Linting
We will be using cfn-lint to lint our template. The list of checks that will be performed on our template can be found here. If you are following along with the companion repo then you can checkout the static-analysis-start
branch.
With pre-commit
setup in our repo it’s very easy to add new checks. To add cfn-lint
we just need to modify .pre-commit-config.yaml
to look like this:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/aws-cloudformation/cfn-python-lint
rev: v0.48.2 # The version of cfn-lint to use
hooks:
- id: cfn-python-lint
files: templates/.*\.(json|yml|yaml)$
Let give it a test run.
I honestly didn’t expect to find any issues. Let’s commit our changes now that we know cfn-lint
is working and then fix our template.
git add .pre-commit-config.yaml
git commit -m "add cfn-lint to pre-commit"
A quick google search for UpdateReplacePolicy
took me to this page on the AWS docs site. Since the effected resouce was the RetainLogsBucket
and we know we want to retain this bucket at all costs. We just have to add the UpdateReplacePolicy
attribute and set it to Retain
.
Not only will cfn-lint
help you write better templates, but it can also save you loads of time from failed deployments.
SAST
Cloudformation also has cfn-nag that will scan our template for potential security issues. If you don’t have docker on your system, then just skip this step.
Again we start by adding a new check to our pre-commit
config file. Unlike our other checks, I couldn’t find a pre-existing hook for cfn-nag
, so we will roll our own using local.
Modify .pre-commit-config.yaml
.
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/aws-cloudformation/cfn-python-lint
rev: v0.48.2 # The version of cfn-lint to use
hooks:
- id: cfn-python-lint
files: templates/.*\.(json|yml|yaml)$
- repo: local
hooks:
- id: cfn-nag
name: cfn-nag
language: docker_image
entry: alpine/cfn-nag:latest -f --input-path /src
files: templates/
pass_filenames: false
Setting up this local
check wasn’t hard, but it did take a bit of reading through different parts of the pre-commit
documentation and some StackOverflow posts. The only thing you might want to change is the -f
option I’m passing to cfn-nag
. That option tells it to fail on warnings, which is something you might not want.
Let’s try it out.
Now that we know cfn-nag
is working, let’s commit our changes.
git add .pre-commit-config.yaml
git commit -m "add cfn-nag to pre-commit"
The warnings we got from cfn-nag
are all very valid. Because I want to demonstrate how to silence a warning and because it will be lots of effort to fix for our example repo, let’s disable the access logging warning.
cfn-nag
allows us to disable rules from inside our template by adding metadata to a resource using the following format.
Metadata:
cfn_nag:
rules_to_suppress:
- id: W9
reason: "This is a public facing ELB and ingress from the internet should be permitted."
Let’s try again after adding in a rule suppression for W35
.
The access log warning is gone, but we are still unable to commit our changes. We still need to force encryption and add an access policy to remove the other warnings. After consulting the Cloudformation docs and some trial and error, we have a template that passes our pre-commit
checks.
If you have been following along with the companion repo then your branch should look similar to this. We have made lots of changes and I’m not really sure this template functions correctly anymore. In the next section we will add Unit Tests so that we can test the template locally without worrying about AWS credentials.