Posts in this Series
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.
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
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
Not only will
cfn-lint help you write better templates, but it can also save you loads of time from failed deployments.
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.
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
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
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.