Validating CloudFormation Templates With cfn-lint

Watching the clouds form

I’ve been working with CloudFormation in some form for about five years now. Two years ago at Time Out, I helped write an in-house tool that performed some basic template linting. One year ago at Genus AI, I started using the AWS Labs tool cfn-lint to validate my templates before deployment. It’s really neat, covers a lot more than our in-house tool did, and has saved me from a number of mistakes.

Here's my review!

More Like SlowFormation

Editing and testing a CloudFormation template can come with a slow feedback cycle. Creating and deleting resources can take anywhere from a few seconds (such as SNS topics) to a soul-sucking 30 minutes (CloudFront, I’m looking at you!). There’s a limit to how many tea breaks you can take! Anything you can do to pre-validate your templates is totally worth it.

One tool that CloudFormation provides for this is the ValidateTemplate API. Unfortunately it’s not particularly strict.

Many CloudFormation resources act like thin wrappers around the underlying service APIs. ValidateTemplate seems to only check the template generally, maybe against the resource specification. This means it often misses extra constraints that exist only in the service APIs, such as which instance types RDS allows for a given database engine.

Thus only a subset of “validated” templates are actually valid.

Enough Fluff, Show Me the Lint

cfn-lint to the rescue! Besides checking against the resource specification, it also implements many per-resource rules. These try to cover the most common of the underlying service constraints, but also help encode some best practices.

For example, some rules that cover underlying service constraints:

And some rules that cover best practices:

You can read the full list of rules here.

Some Usage Tips

First, I’d like to draw attention to the ability to ignore certain rules. Like most linters, cfn-lint flags the occasional false positive. The first time I had one, I panicked a bit. I started diving through the source code to eventually discover the ignore_checks metadata key was what I wanted. But then I found it’s right there in the README.

Second, keep it up to date. cfn-lint bundles its own copy of the resource specification, so if you’re not on the latest version, it won’t recognize legitimate new resources or properties. They’re also frequently adding new rules which will help you improve your templates.

I normally suggest to my clients they they update all their Python dependencies every two weeks, at least where feasible. cfn-lint is definitely one to have a plan for keeping updated.

Third, engage with the developers. I’ve often found one or two rough edges when upgrading. I think all of the issues I’ve opened got a response or a fix within a day or two. This turned into a virtuous cycle and I ended up able to fix some issues myself. So far I’ve made 25 issues/pull requests. A well run open source project! 🌟

Fourth, look into custom rules. You can use these to check something specific to your organization, for example ensuring every taggable resource has a tag called “Environment”. There isn’t much documentation on this apart from the description of the --append-rules flag, but there are some examples here.

Conclusion

As I’m sure you’ve gathered, I like cfn-lint. I recommend it to anyone using CloudFormation. I’ve had a very positive experience with it, and I haven’t seen any rules, just the occasional bug.

The biggest frustration for me is that it exists as a separate tool, rather than ongoing enhancements to ValidateTemplate (or similar). Many CloudFormation users are unlikely to use it, simply due to the effort of discovering and installing it.

Also if you use a template generator, such as Troposphere or AWS’s own CDK, you will probably get more false positives. I haven’t used either much, but from my limited experience, they don’t always output cfn-lint compatible templates.

Fin

Thanks for reading - I hope this review was useful for you,

—Adam


Newly updated: my book Boost Your Django DX now covers Django 5.0 and Python 3.12.


Subscribe via RSS, Twitter, Mastodon, or email:

One summary email a week, no spam, I pinky promise.

Related posts:

Tags: , ,