cfn-lint

Catching Errors Early with cfn-lint

This draft of a reviews table has four mistakes that would otherwise surface minutes into a deployment, or on LocalStack 63,725 , which skips most validation (Validating Templates), not at all:

~/v5-ch7/scratch/reviews.yaml: a draft with four mistakesYAML
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  Stage: {Type: String, AllowedValues: [dev, prod]}
  Owner: {Type: String}
Resources:
  ReviewsTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: !Sub booknest-${Stage}-reviews
      BilingMode: PAY_PER_REQUEST
      AttributeDefinitions: [{AttributeName: bookId, AttributeType: N}]
      KeySchema: [{AttributeName: bookId, KeyType: RANGE}]
  CoversBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub booknest-${Stag}-covers
Linting the draft in the one-line parseable formatShell
cd ~/v5-ch7/scratch
cfn-lint --format parseable reviews.yaml | cut -d: -f2,6- | fold -s -w 90
echo "exit code: ${PIPESTATUS[0]}"
Output
4:W2001:Parameter Owner not used.
8:E3639:'ProvisionedThroughput' is a required property
10:E3002:Additional properties are not allowed ('BilingMode' was unexpected. Did you mean
'BillingMode'?)
12:E3002:'HASH' was expected
12:E3012:[{'AttributeName': 'bookId', 'KeyType': 'RANGE'}] is not of type 'object',
'string'
12:E3018:[{'AttributeName': 'bookId', 'KeyType': 'RANGE'}] is not valid under any of the
given schemas
16:E1019:'Stag' is not one of ['Stage', 'Owner', 'ReviewsTable', 'CoversBucket',
'AWS::AccountId', 'AWS::NoValue', 'AWS::NotificationARNs', 'AWS::Partition',
'AWS::Region', 'AWS::StackId', 'AWS::StackName', 'AWS::URLSuffix']
exit code: 6

The misspelled BilingMode produced two findings: E3002 suggests the right name, and E3639 follows because without a billing mode DynamoDB 24 defaults to provisioned capacity. The RANGE key breaks three schema checks, since a table's first key must be HASH; E1019 catches ${Stag}; W2001 flags the unused Owner. Fix the first finding on a line and re-run, since follow-on findings go with it. Exit code 6 is errors plus warnings.

cfn-lint 2,641 --list-rules prints every rule. Silence one for a single resource with Metadata: {cfn-lint: {config: {ignore_checks: [W3011]}}}, next to its reason, rather than globally; --format sarif feeds GitHub 29 code scanning (GitHub), and --append-rules loads rules you write in Python.