Hypermodern Cloudformation Part 2

Static Code Analysis

Posted by Levi on Monday, April 12, 2021
Last Modified on Friday, May 7, 2021
Cloudformation Logo

Posts in this Series

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.