I love CloudFormation, and I love Terraform. I use both tools often in blog posts, in courses, and at clients. I often get the question to choose between CloudFormation and Terraform. In this blog post, I want to share a couple of CloudFormation features to help you make a choice. Features that are easy to use and are important considerations when selecting the right tool when running production workloads.
When a template is deployed in CloudFormation, the state is managed in the CloudFormation service. You don’t have to create, maintain and secure the state storage, it’s all built in for free. The state cannot be exported, so things like secrets and passwords in the state are never exposed.
The service CloudTrail keeps an audit log of all API actions in your AWS account. It also means all your CloudFormation deployment actions, and the resources it changed, is all recorded in CloudTrail. When you have thousands of stacks, and/or operate in a highly regulated environment, audit trails are a very important topic. It’s covered out of the box.
To make sure the audit trail does not contain an untraceable user like “deploy”, consider the following role assume command which you should implement in your deployment pipeline.
REPO="appx" COMMIT="41a5f427" USER="donkey12" $ aws sts assume-role \ --external-id "AnotherSecret" \ --role-arn arn:aws:iam::123456789012:role/cfn-deploy \ --role-session-name $REPO-$COMMIT-$USER
There are a couple of AWS services to store secrets, like the SSM Parameter Store. CloudFormation has native support to retrieve a secret from the SSM Parameter Store, and without exposing it somewhere, it’s passed to the end service. For example an API key for a third party service.
This is not really a feature, but still a very good reason to consider CloudFormation. There are really thousands of CloudFormation templates available online. Don’t start from scratch creating a template, spend a few minutes to take advantage of all these examples.
Not that you ever need support for CloudFormation, but it’s good to make sure “support” is covered. I do have some experiences where companies needed support because their Terraform state file was corrupt. I also have experiences where Terraform had such a big role, they asked Hashicorp for a support contract and it was quite expensive just to check the box. So it’s good to know CloudFormation support is part of the AWS support contract, and you might never need support either.
CloudFormation supports more than 400 resource types. Sometimes a new service is not supported, or you want to include a third party service in your CloudFormation. It’s good to know it’s really easy to extend CloudFormation with custom resources. Custom resources are just lambda functions, so you could write in any language you want. Check out our binx.io/blog for lots of examples.
When you’re a developer, you’re probably familiar with the term “linting”. For CloudFormation there are two recommended tools: cfn-lint and cfn-nag, and probably more. Linters work as command line tool, locally and as part of your deployment pipeline. They are also part of your favorite IDE. Linters help to validate templates and to check if they comply with best practices and security principles. For example: while creating the templates, you immediately get feedback wether a property is missing or wrong configured. Like an S3 bucket with public access, or a security group with port 22 open to the world.
A new feature which is supporting more and more services over time, is “drift detection”. When you initiate a check for drift detection, CloudFormation compares the current stack configuration to the one specified in the template that was used to create or update the stack and reports on any differences, providing you with detailed information on each one. Terraform also supports drift detection, so it’s not a differentiator, but in CloudFormation it’s easy to automate the check. For example: alerting in Slack or E-mail that the stack is drifted and you need to take action.
When you have multiple CloudFormation templates, and stacks, it becomes quite hard to manage it. Also to automate the deployment using the CLI, becomes a huge bash script or custom tool. One of these tools I recommend using is Sceptre. Do not build your own tool, and do not start creating templates to generate CloudFormation templates.
Even I made some mistakes in my life by using Jinja and other tools, but at that time Cloud Development Kit (CDK) was not announced yet. CDK is really promising for many reasons, but two of them I think are most important:
CDK is currently in public beta, but I personally think it will be supported natively by CloudFormation in the future. Because it’s backwards compatible with CloudFormation, it’s easy to migrate.
Some companies started with AWS manually. Currently it’s not possible to add existing resources in a CloudFormation stack. For example; you have an RDS instance created manually, and would like to maintain the configuration together with other resources in a CloudFormation stack, it’s not possible. You have to rebuild the stack and migrate the data or state.
There is a tool to create templates based on existing resources. It’s called cloudformer, but it’s in beta for years now and does not support many resource types. I still hope it’s going to be a new AWS feature, or that an open source initiative comes up. I would definitely contribute! Actually, I might want to kick start this idea.
For production usage I recommend to use CloudFormation. If you are already using Terraform, it will take a few hours or days to migrate to CloudFormation, but it will give you the listed benefits. To get al these benefits listed in Terraform, it will probably cost you a lot more.
PS. I’ve time boxed this blog post to an hour. Of course I failed, but still did it much faster compared to all other blog posts. I’m open for discussion to improve the blog post. Maybe you have something to add, or a suggestion to improve, please let me know!