3 Tools to Validate CloudFormation

Hello!

This article is about functional testing in CloudFormation, if you’re looking for security testing, check out this.

I run three tools before applying CF templates. Here they are!

#1 AWS CLI’s validator

This is the native tool. It’s ok. It’s really only a syntax checker, there are plenty of errors you won’t see until you apply a template to a stack. Still, it’s fast and catches some things.

aws cloudformation validate-template --template-body file://./my_template.yaml

Notes:

  • The CLI has to be configured with access keys or it won’t run the validator.
  • If the template is JSON, this will ignore some requirements (e.g. it’ll allow trailing commas). However, the CF service ignores the same things.

#2 cfn-nag cfn-lint

cfn-lint is, like you’d expect, a linter for CloudFormation. I only started using it recently, but so far it’s pretty helpful.

cfn-lint my_template.yaml

Notes:

  • Before cfn-lint came out, I was using cfn-nag. I switched for two reasons:
    • Cfn-nag is a security testing tool, not a validator in general. Check out my article on using it to help write limited-privilege IAM policies.
    • It was a Ruby gem so you needed a whole extra dependency chain (and ideally a tool like RVM) to install it). Cfn-lint is a Python app available on PyPI, like the AWS CLI and its validator. Less tooling to maintain.

#3 Python’s JSON library

In general you should only write CloudFormation templates in YAML, but, sometimes I’m stuck with legacy JSON ones that need to be maintained.

Because the AWS CLI validator ignores some JSON requirements, I like to pass JSON templates through Python’s parser to make sure they’re valid. In the past, I’ve had to do things like load and search templates for unused parameters, etc. That’s not ideal but it’s happened a couple times while doing cleanup and refactoring of legacy code. It’s easier if the JSON is valid JSON.

It’s fiddly to run this in a shell script. I do it with a heredoc so I don’t have to write multiple scripts to the filesystem:

python - <<END
import json
with open('my_template.json') as f:
    json.load(f)
END

Notes:

  • I use Python for this because it’s a dependency of the AWS CLI so I know it’s already installed. You could use jq or another tool, though.
  • I don’t do the YAML equivalent of this because it errors on CF-specific syntax like !Ref.

Happy automating!

Adam

If this was helpful and you want to save time by getting “copy and paste” patterns for Cloud DevOps in your inbox, subscribe here. If you don’t want to wait for the next one, check out these: