Code Monkey home page Code Monkey logo

cfn-lint's Introduction

AWS CloudFormation Linter

[cfn-lint logo]

Testing PyPI version PyPI downloads PyPI downloads codecov Discord Shield

Validate AWS CloudFormation yaml/json templates against the AWS CloudFormation resource provider schemas and additional checks. Includes checking valid values for resource properties and best practices.

Warning

This is an attempt to provide validation for AWS CloudFormation templates properties and their values. For values things can get pretty complicated (mappings, joins, splits, conditions, and nesting those functions inside each other) so it's a best effort to validate those values but the promise is to not fail if we can't understand or translate all the things that could be going on.

Contribute

We encourage you to contribute to cfn-lint! Please check out the Contributing Guidelines for more information on how to proceed.

Community

Join us on Discord! Connect & interact with CloudFormation developers & experts, find channels to discuss and get help for cfn-lint, CloudFormation registry, StackSets, Guard and more:

Join our Discord

Serverless Application Model

The Serverless Application Model (SAM) is supported by the linter. The template is transformed using AWS SAM before the linter processes the template.

To get information about the SAM Transformation, run the linter with --info

Install

Python 3.8+ is supported.

Pip

pip install cfn-lint. If pip is not available, run python setup.py clean --all then python setup.py install.

Optional dependencies

cfn-lint has optional dependencies based on certain features you may need.

  • pip install cfn-lint[full] for installing all the optional dependencies. This will install all the dependencies for graph, junit, and sarif.
  • pip install cfn-lint[graph] for installing pydot to draw and output template graphs
  • pip install cfn-lint[junit] for installing the packages to output the junit format
  • pip install cfn-lint[sarif] for installing the packages to output the sarif format

Homebrew (macOS)

brew install cfn-lint

Docker

In cfn-lint source tree:

docker build --tag cfn-lint:latest .

In repository to be linted:

docker run --rm -v `pwd`:/data cfn-lint:latest /data/template.yaml

Editor Plugins

There are IDE plugins available to get direct linter feedback from you favorite editor:

Basic Usage

  • cfn-lint template.yaml
  • cfn-lint -t template.yaml

Multiple files can be linted by either specifying multiple specific files:

  • cfn-lint template1.yaml template2.yaml
  • cfn-lint -t template1.yaml template2.yaml

or by using wildcards (globbing):

Lint all yaml files in path:

  • cfn-lint path/*.yaml

Lint all yaml files in path and all subdirectories (recursive):

  • cfn-lint path/**/*.yaml

Note: If using sh/bash/zsh, you must enable globbing. (shopt -s globstar for sh/bash, setopt extended_glob for zsh).

Exit Codes

cfn-lint will return a non zero exit if there are any issues with your template. The value is dependent on the severity of the issues found. For each level of discovered error cfn-lint will use bitwise OR to determine the final exit code. This will result in these possibilities.

  • 0 is no issue was found
  • 2 is an error
  • 4 is a warning
  • 6 is an error and a warning
  • 8 is an informational
  • 10 is an error and informational
  • 12 is an warning and informational
  • 14 is an error and a warning and an informational
Configuring Exit Codes

cfn-lint allows you to configure exit codes. You can provide the parameter --non-zero-exit-code with a value of informational, warning, error, or none. cfn-lint will determine the exit code based on the match severity being the value of the parameter --non-zero-exit-code and higher. The exit codes will remain the same as above.

The order of severity is as follows:

  1. informational default
  2. warning
  3. error
  4. none Exit code will always be 0 unless there is a syntax error
Specifying the template as an input stream

The template to be linted can also be passed using standard input:

  • cat path/template.yaml | cfn-lint -
Specifying the template with other parameters
  • cfn-lint -r us-east-1 ap-south-1 -- template.yaml
  • cfn-lint -r us-east-1 ap-south-1 -t template.yaml

Configuration

Command Line

From a command prompt run cfn-lint <path to template> to run standard linting of the template.

Config File

It will look for a configuration file in the following locations (by order of preference):

  • .cfnlintrc, .cfnlintrc.yaml or .cfnlintrc.yml in the current working directory
  • ~/.cfnlintrc for the home directory

In that file you can specify settings from the parameter section below.

Example:

templates:
  - test/fixtures/templates/good/**/*.yaml
ignore_templates:
  - codebuild.yaml
include_checks:
  - I
custom_rules: custom_rules.txt

Parameters

Optional parameters:

Command Line Metadata Options Description
-h, --help Get description of cfn-lint
-z, --custom-rules filename Text file containing user-defined custom rules. See here for more information
-t, --template filename Alternative way to specify Template file path to the file that needs to be tested by cfn-lint
-f, --format format quiet, parseable, json, junit, pretty, sarif Output format
-l, --list-rules List all the rules
-r, --regions regions [REGIONS [REGIONS ...]], ALL_REGIONS Test the template against many regions. Supported regions
-b, --ignore-bad-template ignore_bad_template Ignores bad template errors
--ignore-templates IGNORE_TEMPLATES [IGNORE_TEMPLATES ...] Ignore templates from being scanned
-a, --append-rules append_rules [RULESPATH [RULESPATH ...]] Specify one or more rules paths using one or more --append-rules arguments. Each path can be either a directory containing python files, or an import path to a module.
-i, --ignore-checks ignore_checks [IGNORE_CHECKS [IGNORE_CHECKS ...]] Only check rules whose ID do not match or prefix these values. Examples:
- A value of W will disable all warnings
- W2 disables all Warnings for Parameter rules.
- W2001 will disable rule W2001
-e, --include-experimental include_experimental Whether rules that still in an experimental state should be included in the checks
-c, --include-checks INCLUDE_CHECKS [INCLUDE_CHECKS ...] Include rules whose id match these values
-m, --mandatory-checks Rules to check regardless of ignore configuration
--non-zero-exit-code informational (default), warning, error, none] Exit code will be non zero from the specified rule class and higher
-x, --configure-rule CONFIGURE_RULES [CONFIGURE_RULES ...] Provide configuration for a rule. Format RuleId:key=value. Example: E3012:strict=true
-D, --debug Specify to enable debug logging. Debug logging outputs detailed information about rules processing, useful for debugging rules.
-I, --info Specify to enable logging. Outputs additional information about the template processing.
-u, --update-specs Update the CloudFormation resource provider schemas. You may need sudo to run this. You will need internet access when running this command
-o, --override-spec filename Spec-style file containing custom definitions. Can be used to override CloudFormation specifications. More info here
-g, --build-graph Creates a file in the same directory as the template that models the template's resources in DOT format
-s, --registry-schemas one or more directories of CloudFormation Registry Resource Schemas
-v, --version Version of cfn-lint

Info Rules

To maintain backwards compatibility info rules are not included by default. To include these rules you will need to include -c I or --include-checks I

Metadata

Template Based Metadata

Inside the root level Metadata key you can configure cfn-lint using the supported parameters.

Metadata:
  cfn-lint:
    config:
      regions:
        - us-east-1
        - us-east-2
      ignore_checks:
        - E2530

Resource Based Metadata

Inside a resources Metadata key you can configure cfn-lint to ignore checks. This will filter out failures for the resource in which the Metadata belongs. Keep in mind that AWS::Serverless resources may lose metadata during the Serverless transform

Resources:
  myInstance:
    Type: AWS::EC2::Instance
    Metadata:
      cfn-lint:
        config:
          ignore_checks:
            - E3030
    Properties:
      InstanceType: nt.x4superlarge
      ImageId: ami-abc1234

Precedence

cfn-lint applies configurations from several sources. The rules at lower levels are overridden by those at higher levels.

  1. cfnlintrc configurations
  2. Template Metadata configurations
  3. CLI parameters

Configure Rules

Certain rules support configuration properties. You can configure these rules by using configure_rules parameter.

From the command line the format is RuleId:key=value, for example: E3012:strict=true. From the cfnlintrc or Metadata section the format is

Metadata:
  cfn-lint:
    config:
      configure_rules:
        RuleId:
          key: value

The configurable rules have a non-empty Config entry in the table here.

Getting Started Guides

There are getting started guides available in the documentation section to help with integrating cfn-lint or creating rules.

Rules

This linter checks the AWS CloudFormation template by processing a collection of Rules, where every rule handles a specific function check or validation of the template.

This collection of rules can be extended with custom rules using the --append-rules argument.

More information describing how rules are set up and an overview of all the Rules that are applied by this linter are documented here.

Custom Rules

The linter supports the creation of custom one-line rules which compare any resource with a property using pre-defined operators. These custom rules take the following format:

<Resource Type> <Property[*]> <Operator> <Value> [Error Level] [Custom Error Message]

Example

A separate custom rule text file must be created.

The example below validates example_template.yml does not use any EC2 instances of size m4.16xlarge

custom_rule.txt

AWS::EC2::Instance InstanceType NOT_EQUALS "m4.16xlarge" WARN "This is an expensive instance type, don't use it"

example_template.yml

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  myInstance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: m4.16xlarge
      ImageId: ami-asdfef

The custom rule can be added to the configuration file or ran as a command line argument

The linter will produce the following output, running cfn-lint example_template.yml -z custom_rules.txt:

W9001  This is an expensive instance type, don't use it
mqtemplate.yml:6:17

More information describing how custom rules are setup and an overview of all operators available is documented here.

Customize specifications

The linter follows the AWS CloudFormation resource provider schemas by default. However, for your use case specific requirements might exist. For example, within your organisation it might be mandatory to use Tagging.

The linter provides the possibility to implement these customized specifications using the --override-spec argument.

More information about how this feature works is documented here

pre-commit

If you'd like cfn-lint to be run automatically when making changes to files in your Git repository, you can install pre-commit and add the following text to your repositories' .pre-commit-config.yaml:

repos:
  - repo: https://github.com/aws-cloudformation/cfn-lint
    rev: v1.9.6 # The version of cfn-lint to use
    hooks:
      - id: cfn-lint
        files: path/to/cfn/dir/.*\.(json|yml|yaml)$

If you are using a .cfnlintrc and specifying the templates or ignore_templates we would recommend using the .cfnlintrc exlusively to determine which files should be scanned and then using:

repos:
  - repo: https://github.com/aws-cloudformation/cfn-lint
    rev: v1.9.6 # The version of cfn-lint to use
    hooks:
      - id: cfn-lint-rc

Note: When mixing .cfnlintrc ignore_templates and files option in your .pre-commit-config.yaml cfn-lint may return a file not found error

  • If you exclude the files: line above, every json/yml/yaml file will be checked.
  • You can see available cfn-lint versions on the releases page.

cfn-lint's People

Contributors

adamchainz avatar alexjurkiewicz avatar andrew-glenn avatar benbridts avatar cmmeyer avatar coyoteecd avatar dependabot[bot] avatar dunedan avatar fatbasstard avatar github-actions[bot] avatar gliptak avatar jaymccon avatar jonathanmorley avatar jpeddicord avatar kddejong avatar kftsehk avatar lejiati avatar malikatalla-aws avatar michael-k avatar miparnisari avatar muneebar avatar mvanholsteijn avatar orez- avatar patmyron avatar rjlohan avatar sambattalio avatar scottbrenner avatar seporaitis avatar tazatwell avatar tro95 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cfn-lint's Issues

Missing filename in error output

Using cfn-lint 0.3.0 I was trying to fix up linting on vim.

At some point while testing the linting I deleted a three W3010 warnings from this file (explicit mentions of Properties/AvailabilityZones under an RDSCluster node) and this caused cfn-lint to output the follow from the lint invocation: :159:25:159:26:E0000:Null value at line 158 column 24. As you can see, the filename is missing.

So it boils down to:

RDSCluster:
  Type: "AWS::RDS::DBCluster"
  Properties:
    AvailabilityZones:
    BackupRetentionPeriod: 35

So in essence if a sequence of scalars is empty it will return this linting line, which misses the filename.

Also tested this with a Resources/AutoScalingGroup/Properties/VPCZoneIdentifier by removing all its scalars.

Detect missing Conditions

When a resource specifies a Condition: โ€ฆ and the named condition does not exist, cfn-lint does not detect a problem.

  ListenerHttps:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Condition: ListenForHttps
    โ€ฆ

CloudFormation server-side validation says:

An error occurred (ValidationError) when calling the CreateStack operation: Template format error: Condition ListenForHttps is not defined.


(Apologies for Issue rather than Pull Request, if I have time I'll come back with code)

Incorrect parameter type message for Number parameters

Receiving the error:

E2530 Type for Parameter should be Integer, MinValue should be at least 128, and MaxValue equal or less than 1536 at Parameters/MemorySize/Type
cloudformation/ec2/management/templates/instance-scheduler.yaml:20:5

The block of cloudformation it is complaining about it:

MemorySize:
    Type: Number
    AllowedValues:
      - 128
      - 384
      - 512
      - 640
      - 768
      - 896
      - 1024
      - 1152
      - 1280
      - 1408
      - 1536
    Default: 128
    Description: Size of the Lambda function running the scheduler, increase size when
      processing large numbers of instances

There is no parameter type of Integer so I don't where this error is coming from?

unhashable type: 'dict_node'

I'm getting this:

2018-04-22 00:46:35,869 - cfnlint - DEBUG - Get resources from template...
Traceback (most recent call last):
  File "/usr/local/bin/cfn-lint", line 11, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.6/dist-packages/cfnlint/__main__.py", line 157, in main
    matches.extend(runner.run())
  File "/usr/local/lib/python3.6/dist-packages/cfnlint/__init__.py", line 560, in run
    self.filename, self.cfn, self.ignore_checks))
  File "/usr/local/lib/python3.6/dist-packages/cfnlint/__init__.py", line 107, in run
    matches.extend(rule.matchall(filename, cfn))
  File "/usr/local/lib/python3.6/dist-packages/cfnlint/__init__.py", line 55, in matchall
    results = self.match(cfn)  # pylint: disable=E1102
  File "/usr/local/lib/python3.6/dist-packages/cfnlint/rules/resources/properties/Properties.py", line 195, in match
    resourcetype, resourcename, path, True))
  File "/usr/local/lib/python3.6/dist-packages/cfnlint/rules/resources/properties/Properties.py", line 131, in propertycheck
    parenttype, resourcename, arrproppath, False))
  File "/usr/local/lib/python3.6/dist-packages/cfnlint/rules/resources/properties/Properties.py", line 172, in propertycheck
    resourcename, proppath, False))
  File "/usr/local/lib/python3.6/dist-packages/cfnlint/rules/resources/properties/Properties.py", line 111, in propertycheck
    if prop not in resourcespec:
TypeError: unhashable type: 'dict_node'

The template deploys just fine.

Exceptions handling

Based on the documentation in the Readme, and the https://github.com/awslabs/cfn-python-lint/blob/master/test/templates/good/core/config_parameters.yaml file.

I setup this list

~/git/cfn-test$ yq r my-test-stack.yaml Metadata.cfn-lint
config:
  ignore_checks:
  - E2504
  - E2507
  - E2520
  - E2523

where yq is mikefarah's yq, similar to jq, but still I got all the errors marked bellow.

~/git/cfn-test$ cfn-lint --template my-test-stack.yaml | grep ^E
E2507 IAM Policy statement key Fn::If isn't valid
E2507 IAM Policy statement missing Effect
E2507 IAM Policy statement missing Action or NotAction
E2507 IAM Policy statement missing Resource or NotResource
E2523 Only one of [VirtualName, Ebs] should be specified for Resources/FileServer/Properties/BlockDeviceMappings/1
E2504 Iops shouldn't be defined for type gp2 for Resources/FileServer/Properties/BlockDeviceMappings/0/Ebs/Iops
E2520 Parameter MasterUsername should NOT exist with SourceDBInstanceIdentifier for Resources/DB/Properties
E2520 Parameter MasterUserPassword should NOT exist with SourceDBInstanceIdentifier for Resources/DB/Properties
E2520 Parameter MasterUsername should NOT exist with DBSnapshotIdentifier for Resources/DB/Properties
E2520 Parameter MasterUserPassword should NOT exist with DBSnapshotIdentifier for Resources/DB/Properties

and

~/git/cfn-test$ cfn-lint --version
cfn-lint 0.2.1

This whole list is needed only just to go around this for now #112

JSON templates that use Tabs will fail

JSON templates that are using Tabs and not spaces will fail on Python YAML parsing.

found character '\t' that cannot start any token
  in "<string>", line 2, column 1:
    	"AWSTemplateFormatVersion": "20 ...

!If seems to break rule E3002 for lists

!If seems to break the type checker for lists. It seems to work with other types like boolean, strings, and !Ref 'AWS::NoValue'.

I get the following findings using v0.3.0:

E3002 Property AttributeDefinitions should be of type List for resource Table

E3002 Property KeySchema should be of type List for resource Table

For this template:

Conditions:
  HasSortKey: !Not [!Equals [!Ref SortKeyName, '']]
  HasTableName: !Not [!Equals [!Ref TableName, '']]
  HasAwsManagedEncryption: !Equals [!Ref Encryption, aws]
Resources:
  Table:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      TableName: !If [HasTableName, !Ref TableName, !Ref 'AWS::NoValue']
      AttributeDefinitions: !If
      - HasSortKey
      - - AttributeName: !Ref PartitionKeyName
          AttributeType: !Ref PartitionKeyType
        - AttributeName: !Ref SortKeyName
          AttributeType: !Ref SortKeyType
      - - AttributeName: !Ref PartitionKeyName
          AttributeType: !Ref PartitionKeyType
      KeySchema: !If
      - HasSortKey
      - - AttributeName: !Ref PartitionKeyName
          KeyType: HASH
        - AttributeName: !Ref SortKeyName
          KeyType: RANGE
      - - AttributeName: !Ref PartitionKeyName
          KeyType: HASH
      ProvisionedThroughput:
        ReadCapacityUnits: !Ref MinReadCapacityUnits
        WriteCapacityUnits: !Ref MinWriteCapacityUnits
      SSESpecification:
        SSEEnabled: !If [HasAwsManagedEncryption, true, false]

AWS::NoValue without quotes causes error: "Template is malformed: found unexpected ':'"

I'm getting an error with this template, but CFN builds it fine, and the js cfn-linter claims it has no errors or warnings.

Debug Logs:

$ cfn-lint --template templates/rds.yaml --log-level debug
2018-05-24 10:54:46,166 - cfnlint - ERROR - Template templates/rds.yaml is malformed: found unexpected ':'
2018-05-24 10:54:46,166 - cfnlint - ERROR - Tried to parse templates/rds.yaml as JSON but got error: Expecting value: line 1 column 1 (char 0)

If I comment out the MonitoringInterval and MonitoringRoleArn in the rDBServerInstance resource, the error seems to go away. So it seems related to my !If statements.

These lines appear to be the issue:

MonitoringInterval: !If [ EnhancedMonitoring, !Ref pProdMonitoringInterval, !Ref pDevMonitoringInterval ]
MonitoringRoleArn: !If [ EnhancedMonitoring, !GetAtt [ rDBMonitoringRole, Arn ], !Ref AWS::NoValue ]

In fact, if I comment out just MonitoringRoleArn I get an entirely different failure.

Debug Logs:

cfn-lint --template templates/rds.yaml --log-level debug
2018-05-24 11:02:20,595 - cfnlint - DEBUG - Transform templates if needed
2018-05-24 11:02:20,596 - cfnlint - DEBUG - Run scan of template...
...
2018-05-24 11:02:20,606 - cfnlint - DEBUG - Starting match function for rule E3002 at 2018-05-24 11:02:20.606796
2018-05-24 11:02:20,606 - cfnlint - DEBUG - Get names of all parameters from template...
2018-05-24 11:02:20,607 - cfnlint - DEBUG - Get resources from template...
2018-05-24 11:02:20,607 - cfnlint - DEBUG - Get condition values...
2018-05-24 11:02:20,607 - cfnlint - DEBUG - Get condition values...
2018-05-24 11:02:20,607 - cfnlint - DEBUG - Complete match function for rule E3002 at 2018-05-24 11:02:20.607507.  Ran in 0:00:00.000713
2018-05-24 11:02:20,607 - cfnlint - DEBUG - Results from rule E3002 are [<cfnlint.RuleMatch object at 0x10907c240>, <cfnlint.RuleMatch object at 0x108fa1f28>]:
2018-05-24 11:02:20,607 - cfnlint - DEBUG - Get location of path ['Resources', 'rDBServerInstance', 'Properties', 'MonitoringInterval', 1, 'Ref']
2018-05-24 11:02:20,607 - cfnlint - DEBUG - Get location of path ['rDBServerInstance', 'Properties', 'MonitoringInterval', 1, 'Ref']
2018-05-24 11:02:20,607 - cfnlint - DEBUG - Get location of path ['Properties', 'MonitoringInterval', 1, 'Ref']
2018-05-24 11:02:20,607 - cfnlint - DEBUG - Get location of path ['MonitoringInterval', 1, 'Ref']
2018-05-24 11:02:20,608 - cfnlint - DEBUG - Get location of path [1, 'Ref']
2018-05-24 11:02:20,608 - cfnlint - ERROR - Tried to process rules on file templates/rds.yaml but got an error: 1

js cfn-lint:

$ /usr/local/bin/cfn-lint validate templates/rds.yaml
0 infos
0 warn
0 crit
Template valid!

Template:

---
AWSTemplateFormatVersion: '2010-09-09'

Description: MyApp RDS instances

Parameters:
    pApplicationName:
        Type: String
        Description: Application name (typically MyApp).
        Default: MyApp
    pMultiAZ:
        Type: String
        Description: Set to true to create instances in both AZs, false for one.
        AllowedValues:
            - true
            - false
    pEnhancedMonitoring:
        Type: String
        Description: Set to true to enable RDS enhanced monitoring, false to disable.
        AllowedValues:
            - true
            - false
    pDBAllocatedStorage:
        Type: String
        Description: The amount of disk storage allocated to the database server.
    pDBParameterGroupFamily:
        Type: String
        Description: The RDS parameter group family.
    pDBInstanceClass:
        Type: String
        Description: The RDS instance class.
    pDBEngine:
        Type: String
        Description: The RDS Engine.
    pDBEngineVersion:
        Type: String
        Description: The RDS Engine version.
    pDBMasterUsername:
        Type: String
        Description: The DB Master Username.
    pDBServerPort:
        Type: Number
        Description: The DB engine port. Valid values are 1150-65535 except for 1434, 3389, 47001, 49152, and 49152 through 49156.
        Default: 1433
    pProdMonitoringInterval:
        Type: Number
        Description: The interval, in seconds, between points when Enhanced Monitoring metrics are collected for the DB instance when running in the Prod stage.
        Default: 60
    pDevMonitoringInterval:
        Type: Number
        Description: The interval, in seconds, between points when Enhanced Monitoring metrics are collected for the DB instance when running in the Dev stage.
        Default: 0

Resources:

    rParameterGroup:
        Type: AWS::RDS::DBParameterGroup
        Properties:
            Description: !Join [' ', [!Ref pApplicationName, 'RDS Parameter Group.']]
            Family: !Ref pDBParameterGroupFamily
            Tags:
                - Key: app
                  Value: !Ref pApplicationName
                - Key: env
                  Value:
                      Fn::ImportValue: !Sub "${pApplicationName}:config:env"

    rDBSubnetGroup:
        Type: AWS::RDS::DBSubnetGroup
        Properties:
            DBSubnetGroupDescription: !Join [' ', [!Ref pApplicationName, 'RDS Subnet Group.']]
            SubnetIds:
                - Fn::ImportValue: !Sub "${pApplicationName}:subnet:data:1"
                - Fn::ImportValue: !Sub "${pApplicationName}:subnet:data:2"
            Tags:
                - Key: app
                  Value: !Ref pApplicationName
                - Key: env
                  Value:
                      Fn::ImportValue: !Sub "${pApplicationName}:config:env"

    rDBPassword:
        Type: Custom::Secret
        Properties:
            Name: !Sub "/passwords/rds/${AWS::StackName}"
            KeyAlias: alias/aws/ssm
            Alphabet: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
            Length: 30
            ReturnSecret: true
            ServiceToken:
                Fn::Join: [ ":", [ "arn:aws:lambda", !Ref "AWS::Region", ! "Ref": "AWS::AccountId", "function:binxio-cfn-secret-provider" ] ]

    rDBMonitoringRole:
        Type: AWS::IAM::Role
        Condition: EnhancedMonitoring
        Properties:
            AssumeRolePolicyDocument:
                Statement:
                    - Effect: Allow
                      Principal:
                          Service: monitoring.rds.amazonaws.com
                      Action: sts:AssumeRole
            Policies:
                - PolicyName: "MyAppRDSEnhancedMonitoring"
                  PolicyDocument:
                    Version: '2012-10-17'
                    Statement:
                        - Effect: Allow
                          Action:
                              - logs:CreateLogGroup
                              - logs:PutRetentionPolicy
                          Resource:
                              - arn:aws:logs:*:*:log-group:RDS*
                        - Effect: Allow
                          Action:
                              - logs:CreateLogStream
                              - logs:PutLogEvents
                              - logs:DescribeLogStreams
                              - logs:GetLogEvents
                          Resource:
                              - arn:aws:logs:*:*:log-group:RDS*:log-stream:*

    rDBServerInstance:
        Type: AWS::RDS::DBInstance
        Properties:
            AllocatedStorage: !Ref pDBAllocatedStorage
            AllowMajorVersionUpgrade: False
            AutoMinorVersionUpgrade: True
            BackupRetentionPeriod: 35
            CopyTagsToSnapshot: True
            DBInstanceClass: !Ref pDBInstanceClass
            DBParameterGroupName: !Ref rParameterGroup
            DBSubnetGroupName: !Ref rDBSubnetGroup
            Engine: !Ref pDBEngine
            EngineVersion: !Ref pDBEngineVersion
            LicenseModel: license-included
            MasterUserPassword: !GetAtt [ rDBPassword, "Secret" ]
            MasterUsername: !Ref pDBMasterUsername
            MonitoringInterval: !If [ EnhancedMonitoring, !Ref pProdMonitoringInterval, !Ref pDevMonitoringInterval ]
            MonitoringRoleArn: !If [ EnhancedMonitoring, !GetAtt [ rDBMonitoringRole, Arn ], !Ref AWS::NoValue ]
            MultiAZ: !If [ MultiAZ, true, false ]
            Port: !Ref pDBServerPort
            PubliclyAccessible: False
            StorageEncrypted: True
            StorageType: gp2
            Tags:
                - Key: app
                  Value: !Ref pApplicationName
                - Key: env
                  Value:
                      Fn::ImportValue: !Sub "${pApplicationName}:config:env"
            VPCSecurityGroups:
                - Fn::ImportValue: !Sub "${pApplicationName}:sg:data"

Conditions:
    MultiAZ: !Equals [ !Ref pMultiAZ, true ]
    EnhancedMonitoring: !Equals [ !Ref pEnhancedMonitoring, true ]

Incorrectly reporting issue with DynamoDB table Read and Write Capacity units

E3002 Property Resources/ConfigTable/Properties/ProvisionedThroughput/ReadCapacityUnits should be of type Integer
cloudformation/ec2/management/templates/instance-scheduler.yaml:945:9

E3002 Property Resources/ConfigTable/Properties/ProvisionedThroughput/WriteCapacityUnits should be of type Integer
cloudformation/ec2/management/templates/instance-scheduler.yaml:946:9

Resource is:

ConfigTable:
    Type: 'AWS::DynamoDB::Table'
    Properties:
      AttributeDefinitions:
        - AttributeName: type
          AttributeType: S
        - AttributeName: name
          AttributeType: S
      KeySchema:
        - AttributeName: type
          KeyType: HASH
        - AttributeName: name
          KeyType: RANGE
      ProvisionedThroughput:
        ReadCapacityUnits: 2
        WriteCapacityUnits: 2

New release incoming?

With a bunch of fixes, additional rules and features in place (or in a PR), when is a new release planned?

Crash on empty file

$ touch foo
$ cfn-lint --template foo
Traceback (most recent call last):
  File "/usr/local/bin/cfn-lint", line 11, in <module>
    sys.exit(main())
  File "/usr/local/lib/python2.7/site-packages/cfnlint/__main__.py", line 27, in main
    (args, template, rules, fmt, formatter) = cfnlint.core.get_template_args_rules(sys.argv[1:])
  File "/usr/local/lib/python2.7/site-packages/cfnlint/core.py", line 207, in get_template_args_rules
    defaults = get_default_args(template)
  File "/usr/local/lib/python2.7/site-packages/cfnlint/core.py", line 279, in get_default_args
    if isinstance(configs, dict):
UnboundLocalError: local variable 'configs' referenced before assignment

Catch duplicate resources

Dictionaries in Python don't support duplicate keys. If a YAML/JSON contains duplicate keys, the last occurrence is "used".

If somebody is copy/pasting a bit too enthusiastic in a big template, weird result will happen.... Change a resource, deploy it, nothing changes. Spand hours on debugging only to find out the Resource occorred 2 times in the template... Yes, experienced this.... Pretty annoying.

Example:

AWSTemplateFormatVersion: "2010-09-09"
Resources:
  mySnsTopic:
    Type: AWS::SNS::Topic
    Parameters:
      TopicName: "unused-topic-name"
  myS3Bucket:
    Type: AWS::S3::Bucket
  mySnsTopic:
    Type: AWS::SNS::Topic
    Parameters:
      TopicName: "used-topic-name"

There will be 1 SNS topic deployed, the one with used-topic-name. In this case pretty clear, but in bigger templates this is not desirable.

Ref and GetAtt Specificiations

I've been writing some individual checks that would check the Ref or GeAtt of resource properties.

For example we would check the that a Ref for VpcId goes to a resource of AWS::EC2::VPC. If it was to a parameter we would check the parameter is of appropriate type (String, AWS::EC2::VPC::Id)

Type: "AWS::EC2::Subnet"
Properties:
  CidrBlock: String
  VpcId: String

After writing a few of these I'm starting to see a lot of repeat and I'm wondering if this would be better defined in a JSON/YAML document. We can then write a singular rule to check these items limiting repeated code.
An example of that document is as follows.

{
  "RelationshipTypes": {
    "String": {
      "Ref": {
        "Parameters": [
          "String"
        ]
      }
    },
    "VpcId": {
      "Ref": {
        "Resources": [
          "AWS::EC2::VPC"
        ],
        "Parameters": [
          "String",
          "AWS::EC2::VPC::Id"
        ]
      },
      "GetAtt": {
        "AWS::EC2::SecurityGroup": "VpcId"
      }
    }
  },
  "ResourceTypes": {
    "AWS::EC2::Subnet": {
      "Properties": {
        "VpcId": {
          "RelationshipType": "VpcId"
        },
        "MapPublicIpOnLaunch": {
          "RelationshipType": "String"
        }
      }
    }
  }
}

Single or double quotes?

I see a mixup of single and double quotes in the codebase Example: (From Properties.py):

            elif primtype == "Boolean":
                if value not in ['true', 'false', 'True', 'False']:
                    message = "Property %s should be of type Boolean" % ('/'.join(map(str, proppath)))
                    matches.append(RuleMatch(proppath, message))
            elif primtype != "String":
                message = "Property %s should be of type String" % ('/'.join(map(str, proppath)))
                matches.append(RuleMatch(proppath, message))
        elif isinstance(value, bool):
            if primtype != "Boolean" and primtype != "String":
                message = "Property %s should be of type %s" % ('/'.join(map(str, proppath)), primtype)
                matches.append(RuleMatch(proppath, message))
        elif isinstance(value, int):
            if primtype in ["String", "Double"]:

For consistency reasons would be nice if there's some guidelines in this (and linted on PR's)

Better error messaging for invalid type or property errors

Currently you can have an invalid type or invalid property based on it actually being invalid, not supported in the region being tested, or by the override-spec parameter.

Ideally the error message would more appropriately relate to the error. Example: This resource type is invalid based on the override spec or this resource type isn't supported in this region.

The goal would be to make sure its understood what the CloudFormation Spec failed and what was a failure of that particular run (with parameter or regions) so we don't confuse the users.

Test command line argument processing

Just had an issue reported that would have hopefully been caught with testing of the parameters and how they are processed.

Add testing so we can make sure we are honoring the parameters correctly.

Best Practices

A question was asked if we should be including template issues and best practices with the same repository of rules.

Example would be for an image ID property.

  1. Refs a Parameter of Type Number would not work at all and should show a failure.
  2. Refs a Parameter of type String shows a failure today because its not AWS::EC2::Image::Id. In this case both would work but AWS::EC2::Image::Id is more right.

Another example would be if you are specifying a password for a RDS database we make sure the REF to a parameter has the property NoEcho True set. Again a best practice but not a requirement for the template to work.

This is a great question and deserves some conversation. I see two options.

  1. Separate out best practice rules into another repo that people can download and use as they want.
  2. Keep Issues in this repo but allow people to turn off or enable best practices as needed.
    a. Tag Rules as Best Practice vs. Issue (wording to be worked on) and allow people to enable best practices as they need (disabled by default).
    b. A variance on the last one would be making best practices Warnings and allowing people to disable Warnings via parameter. Exit code would be determined on Errors and not on Warnings.

Right now I'm leaning towards a model in which we keep the rules in this repo but allow people to disable best practices.

AllowedValues

Question:

There are a lot of Properties that have a specific list of allowed values, some example:

These valid values are not in the CloudFormation Specs. Is there a chance that this data is going to be added somewhere in a near future? @cmmeyer perhaps you know more about this?

It's in there! A todo list to keep an overview:

Source: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-template-resource-type-ref.html

  • Alexa
  • Amazon MQ
  • API Gateway
  • Application Auto Scaling
  • AppMesh
  • AppStream 2.0
  • AppSync
  • Athena
  • Auto Scaling
  • AWS Batch
  • Budgets
  • Certificate Manager
  • AWS Cloud9
  • CloudFormation
  • CloudFront
  • AWS Cloud Map
  • CloudTrail
  • CloudWatch
  • CodeBuild
  • CodeCommit
  • CodeDeploy
  • CodePipeline
  • Amazon Cognito
  • AWS Config
  • Data Pipeline
  • DAX
  • Directory Service
  • Data Lifecycle Manager
  • DMS
  • DocumentDB
  • DynamoDB
  • EC2
  • ECR
  • ECS
  • EFS
  • EKS
  • ElastiCache
  • Elasticsearch
  • Elastic Beanstalk
  • Elastic Load Balancing
  • Elastic Load Balancing V2
  • EMR
  • FSx
  • Amazon GameLift
  • Glue
  • GuardDuty
  • IAM
  • Amazon Inspector
  • AWS IoT
  • AWS IoT 1-Click
  • AWS IoT Analytics
  • Kinesis
  • KMS
  • Lambda
  • Neptune
  • OpsWorks
  • OpsWorks-CM
  • RDS
  • Amazon Redshift
  • Route 53
  • S3
  • SageMaker
  • Secrets Manager
  • Service Catalog
  • SES
  • SimpleDB
  • SNS
  • SQS
  • Step Functions
  • Systems Manager
  • WAF
  • WAF Regional
  • WorkSpaces

New Rule Function for Resource Property Checks

Right now all new rules need to have matchall and the function takes the entire Template object. As a result a lot of rules have repetitive code to do in depth analysis of resource properties and their sub properties.

I'm debating moving that logic into the Runner and creating a new function match_resource_properties and new array attribute inside CloudFormationLintRule that tells us what properties the rules want to scan. The combination of matching the ResourceType or PropertyType from the spec for the thing being scanned and the rule having the function (match_resource_properties) defined will result in it being called with the properties being analyzed.

This would reduce the amount of rules doing this full scan of resource properties and sub properties could be reduced and allow rule writers to focus on whats important.

This would help support a lot of rules that I would like to get written:

  • At least one property. With AWS::IAM::Policy you must specify at least one of Users, Roles, Groups.
  • Only one of. Block Device Mappings need only one of VirtualName or Ebs but not both.
  • Rewrite the already written inclusive and exclusive rules.

Any rule doing in depth checks of resource properties could also use this as needed instead of doing all that work of digging into the CloudFormation template in a safe methodology. Example. When specifying AWS::EC2::Volume if you put a VolumeType of io1 you need to include the Iops property.

Unsupported AllowedValues in parameter Cidr linter

The Paramter Cidr linter checks for an AllowedPattern, but it's also possible that a Cidr parameter is controlled with AllowedValues. This makes the check on the AllowedPattern obsolete:

https://github.com/awslabs/cfn-python-lint/blob/master/src/cfnlint/rules/parameters/Cidr.py#L65

Besides that the allowed values itself are not checked.

Example:

  EgressOracle:
    Type: "String"
    AllowedValues:
      - "XXX.XXX.XXX.XXX/28" # Testing
      - "YYY.YYY.YYY.YYY/28" # Production
    Description: "Egress (Outbound) CIDR for Oracle connectivity (port 1521)"

This raises the

AllowedPattern for Parameter should be specified at Parameters/EgressOracle. Example "^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$"

While there are AllowedValues that specify it. But those aren't checked, so this would be "OK" according to the current code:

  EgressOracle:
    Type: "String"
    AllowedValues:
      - "XXX.XXX.XXX.XXX" # Testing
      - "YYY.YYY.YYY.YYY" # Production
    Description: "Egress (Outbound) CIDR for Oracle connectivity (port 1521)"

There should be support for AllowedValues:

  • Don't raise the AllowedPattern Warning if there are AllowedValues
  • If there are AllowedValues, check those values for valid Cidr's

FindInMap in Conditions

Conditions:
  cCreate:
    Fn::Equals:
    - !FindInMap [myMap, !Ref myInstance1, instance ]
    - true
Resources:
  myInstance1:
    Condition: cCreate
    Type: AWS::EC2::Instance
    Properties:
      ImageId: abc-1234567

should result in Template validation error: Template format error: Unresolved dependencies [myInstance1]. Cannot reference resources in the Conditions block of the template

New rule has alerts on any Ref in the Conditions block thats go to a Resource.

Remove try... convert of integers (E3002)

In the property Type check, when the property value should be an integer (but it's not), there is an attempt to convert it:

https://github.com/awslabs/cfn-python-lint/blob/master/src/cfnlint/rules/resources/properties/Properties.py#L56

Since both YAML and JSON just handle these types out the box, the try..except can in theory be removed (since the type's don't match, a string is not an integer).

Personally I like the check to be more "strict', who do other think?

Example (JSON):
https://github.com/awslabs/cfn-python-lint/blob/master/test/templates/quickstart/vpc-management.json#L816

Example (YAML):
https://github.com/awslabs/cfn-python-lint/blob/master/test/templates/good/resource_properties.yaml#L464

These values can easily be written as actual integers

      - CidrIp:
          Ref: SSHLocation
        FromPort: 22 
        IpProtocol: tcp
        ToPort: 22

Disable rules with inline comments

Hi all,

As a linter used in IDEs, the possibility to add inline comments to ignore a line would be useful.
I think this could inpire us.

What do you think?

Support for Serverless Application Model Cloudformation Templates

Running the tool now will give back errors relating to standard syntax use in SAM based Cloudformation templates such as:

E1001 Top level item Globals isn't valid
E1012 Ref ServerlessRestApi not found as a resource or parameter
E1019 String parameter ServerlessRestApi not found in string for Outputs/ApiURL/Value/Fn::Sub

In this case, It becomes a little tricky as resources like ServerlessRestApi might not be statically defined in the template but rather dynamically built to support a certain functions event properties.

Move logic away friom __main__.py to improve usability

Currently there is a lot of logic implemented in __main__.py which is nice for CLI usage, but is not as handy when used in code.

It would improve the usability of this linter and makes it easier to integrate with other tooling if logic from this class is moved away. Focus should be on parsing the arguments, run the Rules and parse the output.

ATM the logic has to be copied into other tooling that implements this

Add Rules for Route53 records

There are a bunch of rules on recordsets, for instance the TXT records:

https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/ResourceRecordTypes.html#TXTFormat
https://tools.ietf.org/html/rfc1464

These are not checked "yet". Example we hit a couple of days ago was the fact that the TXT records have to be in quotes (So in YAML this ends up as quoted string in quotes.)

Example:

        - Name: !Sub "_amazonses.example.com."
          Type: "TXT"
          TTL: 900
          ResourceRecords:
            - "generatedrandomstring"

Breaks the CloudFormation deployment with the following error:

Invalid Resource Record: FATAL problem: InvalidCharacterString (Value should be enclosed in quotation marks) encountered with 'generatedrandomstring'

Should have been:

        - Name: !Sub "_amazonses.example.com."
          Type: "TXT"
          TTL: 900
          ResourceRecords:
            - "\"generatedrandomstring\""

Documentation: https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/ResourceRecordTypes.html
Record Types:

  • A Record Type
  • AAAA Record Type
  • CAA Record Type
  • CNAME Record Type
  • MX Record Type
  • NAPTR Record Type
  • NS Record Type
  • PTR Record Type
  • SOA Record Type
  • SPF Record Type
  • SRV Record Type
  • TXT Record Type

There are more rules like this (See documentation: https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/ResourceRecordTypes.html) that could/should be implemented.

More documenation urls:

Complex Condition breaks Properties check (E3002)

Properties check breaks on complex Conditions that return multiple sub-properties. Example:

AWSTemplateFormatVersion: "2010-09-09"
Description: A sample template
Parameters:
  EnableGeoBlocking:
    Type: String
Conditions:
  EnableGeoBlocking: !Equals [ !Ref EnableGeoBlocking, "true" ]
Resources:
  CloudFrontDistribution:
    Type: "AWS::CloudFront::Distribution"
    Properties:
      DistributionConfig:
        Enabled: true
        Restrictions:
          GeoRestriction:
            !If
              - EnableGeoBlocking
              -
                RestrictionType: whitelist
                Locations:
                  - BE
                  - LU
                  - NL
              - RestrictionType: none

This returns an error on the !If:

E3002 Expecting an object at Resources/CloudFrontDistribution/Properties/DistributionConfig/Restrictions/GeoRestriction/Fn::If/2
template.yaml:15:11

False errors given with property relationships when conditions are used

Right now we check for attributes that should or shouldn't be defined together. These scenarios can get tricky with conditions and AWS::NoValue.

  • Short term hotfix to not give errors when complex situations are found
  • Ability to analyze if a related resource is available when conditions are used
  • Pull out values of properties in an object when values include conditions
  • Related objects and their values when each object has a condition applied

Related issues:

YAML file IAM policies erroneously trigger "E2507 IAM Policy Documents needs to be JSON"

A resource like this:

Resources:
  MyUser:
    Type: AWS::IAM::User
    Properties:
      Policies:
        - PolicyName: !Sub ${AWS::StackName}-policy
          PolicyDocument:
            - Version: '2012-10-17'
              Statement:
                Action:
                  - s3:GetObject
                Effect: Allow
                Resource:
                  - arn:aws:s3:::*

Will be created just fine by the Amazon API, but cfn-lint reports:

E2507 IAM Policy Documents needs to be JSON
test.yaml:7:11

E3002 Property should be of type Json not List at Resources/MyUser/Properties/Policies/0/PolicyDocument
test.yaml:7:11

Check templates for Null values

Null values should result in a basic parsing error. Not catching them in the parsing can result in a lot of rule errors later on. They also fail with this error when trying to deploy

AWSTemplateFormatVersion: "2010-09-09"
Resources:

or JSON

{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Resources": null
}

Detect unused Mappings

Show a warning if a Mapping is defined that is not used anywhere within the template (similar to Conditions behavior)

[feature request] version with callable API

As linting should be a part of a CI/CD process, it would be very cool to have an API to use the linter directly from other python based app/scripts.

As a user of the linter, I don't want to call shell commands from my python scripts to call another python based application (the linter).

Nesting FindInMap not supported

Don't ask why, but we have the following CloudFormation:

CidrBlock: !FindInMap [!FindInMap ["Environment", !Ref "Environment", "Subnets"], "eu-west-1a", "Management"]

Which causes an error:

E1011 Map Name should be a string for Resources/XXX/Properties/CidrBlock/Fn::FindInMap
../xxx.yaml:

The FindInMap rule does not support recursive FindInMaps.

Unused Mapping Warning does not work with nested FindInMap

Related to issue #57

When a nested FindInMap is used, it raises a warning on the mapping not used.

Example:

Resource part:

CidrBlock: !FindInMap [!FindInMap ["Environment", !Ref "Environment", "Subnets"], "eu-west-1a", "Management"]

Mapping:

Mappings:
  Environment:
    acceptance:
      Subnets: "AcceptanceSubnets"
    testing:
      Subnets: "TestingSubnets"
    production:
      Subnets: "ProductionSubnets"
  AcceptanceSubnets:
    eu-west-1a:
      Management: "XXX.XXX.XXX.XXX/XX"
...

This raises the warning: W7001 - Mapping AcceptanceSubnets not used (line: 90)

Best way to handle parameters from nested stacks?

This project is awesome and super useful!

I can imagine the complexity of linting nested stacks is super high and wouldn't expect that, but how are folks handling situations where Outputs from nested stacks are being used?

For example, given this code:

            /etc/aws-signing-proxy.yml:
              content: !Sub |
                listen-address: 127.0.0.1
                port: 9200
                target: https://${ElasticsearchStack.Outputs.DomainEndpoint}
                region: ${AWS::Region}

always throws:

E1019 String parameter ElasticsearchStack.Outputs.DomainEndpoint not found in string for Resources/ServerLaunchConfig/Metadata/AWS::CloudFormation::Init/es_proxy_setup/files//etc/aws-signing-proxy.yml/content/Fn::Sub

I don't want to disable all E1019 checks because they're useful. Would it maybe be right, for now, to exclude all parameters that have /.Outputs./ in their name?

Rule ID convention

What's the convention behind the rule ID's? If I want to add a rule, how is the rule ID set up?

Add Rule for CloudFront Aliases

If Aliases are used on CloudFront distributions, and you specify an invalid alias, the deployment fails.

In our case it broke on a "copy/paste error":

  myCloudFrontDistribution:
    Type: "AWS::CloudFront::Distribution"
    Properties:
      DistributionConfig:
        Aliases:
          - "www.example.com"
          - "www.example1.com "

Since the Aliases is a list of CNAMEs (alternate domain names), if any, for the distribution. (
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-cloudfront-distribution-distributionconfig.html#cfn-cloudfront-distribution-distributionconfig-aliases), this can be checked pretty simple.

RDS DB Cluster DBSnapshotIdentifier

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-dbsnapshotidentifier

Going to need a special check to validate the empty string value of this. A little hard to do with a Ref but we have to remove it from Exclusive https://github.com/awslabs/cfn-python-lint/blob/master/src/cfnlint/data/AdditionalSpecs/Exclusive.json#L56-L61

By specifying this property, you can create a DB instance from the specified DB snapshot. If the DBSnapshotIdentifier property is an empty string or the AWS::RDS::DBInstance declaration has no DBSnapshotIdentifier property, AWS CloudFormation creates a new database. If the property contains a value (other than an empty string), AWS CloudFormation creates a database from the specified snapshot. If a snapshot with the specified name doesn't exist, AWS CloudFormation can't create the database and it rolls back the stack.

aws-cloudformation/cfn-lint-atom#8

Proposal for CodePipeline rules

Hi,

As per contribution suggestions opening up issue first.

Today trying to update CloudFormation stack with CodePipeline I ran into two rollbacks:

  1. Pipeline should start with a stage that only contains source actions.
  2. Pipeline action declares 0 input artifacts.

Validate template didn't caught those and after quick search I found this project, which made it really easy to write additional rules to validate those two cases:

The first rule just goes through first stage in the pipeline and:

  1. If there are no Source actions - pass.
  2. If there are only Source actions - pass.
  3. If there are Source and other actions - fail.

The second rule goes through stages, starting from the second one, and:

  1. If the action category is Build and there are no InputArtifacts key or it's empty - fail.
  2. Otherwise - pass.

I would gladly contribute these rules back to the project - wondering if you think they'd provide value? Are there any nuances that above rules miss?

As a side question, and I am not sure if you can answer it, but why cloudformation:ValidateTemplate API call would not run this more comprehensive linter on the templates?

Add rules to check the template against CloudFormation limits

Validate that the template does not exceed any of the CloudFormation hard limits:

  • Mappings -- 100 mappings
  • Mappings middle layer
  • Mapping attributes -- 64 attributes
  • Maximum size of each mapping name -- 255 characters
  • Outputs -- 60 outputs
  • Output name -- 255 characters
  • Parameters -- 60 parameters
  • Parameter name -- 255 characters
  • Parameter value -- 4,096 bytes
  • Resources -- 200 resources
  • Resource name -- 255 characters
  • Template body size in an Amazon S3 object -- 460,800 bytes
  • Template description -- 1,024 bytes
  • Dynamic references - 60
  • ~400KB per resource bug
  • #1092

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.