If you've used CloudFormation before you'll already know about the validate-template
command on AWS CLI. If you've used this command before, you might also know that this validator only checks the syntax of your template. I can think of countless cases where my deployments failed due to a simple mistake that wasn't caught by this validator. This post will use a simple CloudFormation template to explain how cfn-lint
can help you identify various errors in your stack before deploying it.
Sections
Example Template Setup
AWSTemplateFormatVersion: "2010-09-09"
Description: Example template
Parameters:
Environment:
Type: String
Default: 'dev'
Conditions:
IsDev: !Equals [ !Ref Environment, 'dev' ]
Resources:
Function:
Type: AWS::Lambda::Function
Condition: IsDev
Properties:
Role: !Ref FunctionRole # Role property requires an ARN, not the resource ID
Handler: index.handler
Code:
S3Bucket: my-bucket
S3Key: function.zip
MemorySize: 3000 # Invalid memory size
Runtime: nodejs12.x
Timeout: 5
TracingConfig:
Mode: !If [IsTracingActive, 'true', 'false'] # Undefined condition IsTracingActive
FunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
Policies:
- PolicyName: all
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: '*'
Resource: '*'
Outputs:
FunctionArn: # Export without matching condition to resource
Description: Lambda ARN
Value: !GetAtt Function.Arn
Export:
Name: !Sub ${Environment}-lambda-arn
This is the template that we'll use to test cfn-lint
. It sets up a simple Lambda function with an IAM role and the lambda ARN is exported as an output. Before we start, let's highlight some of the issues with this template:
Role
property on the lambda is not an ARN. Running aRef
on an IAM role will return the logical ID of the role.MemorySize
of 3000 is invalid. Lambda memory size can range from 128 MB to 3008 MB in 64 MB increments.Condition
IsTracingActive
is undefined.LambdaFunction
is only deployed when the conditionIsDev
is true, but it's export does not have the condition defined.
Here's the output of the built-in validate-template
command for this stack:
{
"CapabilitiesReason": "The following resource(s) require capabilities: [AWS::IAM::Role]",
"Description": "Example template",
"Parameters": [
{
"DefaultValue": "dev",
"NoEcho": false,
"ParameterKey": "Environment"
}
],
"Capabilities": [
"CAPABILITY_IAM"
]
}
As you can see, the validator does not identify any issues with this stack. Deploying this stack however will result in a failure. Let's see what cfn-lint
can do for us in the next section.
cfn-lint Usage
cfn-lint
is a command line tool which examines your CloudFormation template and returns various suggestions. Let's run this tool and see what it has to say about our example stack.
> cfn-lint template.yml
E3008 Property "Role" has no valid Refs to Resources at Resources/Function/Properties/Role/Ref
template.yml:14:7
E2530 You must specify a value that is greater than or equal to 128, and it must be a multiple of 64. You cannot specify a size larger than 3008. Error at Resources/Function/Properties/MemorySize
template.yml:19:7
E8002 Condition IsTracingActive is not defined.
template.yml:23:9
W1001 GetAtt to resource "Function" that may not be available when condition "IsDev" is False at Outputs/FunctionArn/Value/Fn::GetAtt
template.yml:47:5
As you can see, cfn-lint
output covers all 4 issues that we previously highlighted in the form of warnings and errors. Errors indicate issues that will prevent your CloudFormation stack from deploying, and warnings indicate potential issues in your stack that you might want to think about.
It's worth noting that not all warnings are necessarily highlighting an issue that you must fix. Everything depends on the context. If you wish to ignore warnings from the output, you can use the ignore_checks argument:
> cfn-lint template.yml -i W
cfn-lint
also comes with extensive configuration support which allows you to customise your linting rules.
For a complete set of commands and installation guides, please refer to the github repository.
Conclusion
We looked at how cfn-lint
can be used as an additional validator for our CloudFormation templates. It provides a way to check the semantics of our templates and helps us catch mistakes before making a deployment. Some of the CI pipelines that I work on uses cfn-lint
to decide whether the deployment step should execute. I hope this tool can help you iterate quicker and make your CloudFormation development experience a bit more enjoyable.
Top comments (1)
Way to raise our automation potential. Sometimes editing CloudFormation is icky. The slightest CloudFormation mistep can stop a deployment. It's silly.
cfn-lint
looks like the next best thing to a deployment simulator.