template-validator

SKILL.md

Template Validator

Quick Start

Validate CloudFormation templates for syntax errors, security issues, and adherence to best practices before deployment.

Instructions

Step 1: Validate template syntax

# Basic validation
aws cloudformation validate-template \
  --template-body file://template.yaml

# Validation with parameters
aws cloudformation validate-template \
  --template-body file://template.yaml \
  --parameters ParameterKey=Param1,ParameterValue=Value1

Check for:

  • Valid YAML/JSON syntax
  • Required template sections
  • Valid resource types
  • Correct intrinsic function usage
  • Parameter references

Step 2: Use cfn-lint for comprehensive checks

# Install cfn-lint
pip install cfn-lint

# Validate template
cfn-lint template.yaml

# Validate with specific rules
cfn-lint template.yaml --ignore-checks W

# Output as JSON
cfn-lint template.yaml --format json

cfn-lint checks:

  • Template structure
  • Resource properties
  • Best practices
  • Security issues
  • Regional availability

Step 3: Security validation

Check IAM policies:

# Review for overly permissive policies
Resources:
  Role:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: ec2.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: AppPolicy
          PolicyDocument:
            Statement:
              # Avoid wildcards
              - Effect: Allow
                Action: s3:*  # Too permissive!
                Resource: '*'  # Too broad!

Better approach:

Policies:
  - PolicyName: AppPolicy
    PolicyDocument:
      Statement:
        - Effect: Allow
          Action:
            - s3:GetObject
            - s3:PutObject
          Resource: !Sub '${MyBucket.Arn}/*'

Check security groups:

# Avoid open access
Resources:
  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      SecurityGroupIngress:
        # Don't allow 0.0.0.0/0 for SSH
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 0.0.0.0/0  # Security risk!

Better approach:

SecurityGroupIngress:
  - IpProtocol: tcp
    FromPort: 22
    ToPort: 22
    CidrIp: 10.0.0.0/8  # Restrict to internal network

Step 4: Check resource dependencies

Verify DependsOn usage:

Resources:
  # Explicit dependency needed
  Instance:
    Type: AWS::EC2::Instance
    DependsOn: InternetGatewayAttachment
    Properties:
      # ...
  
  # Implicit dependency via Ref
  SecurityGroupIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref SecurityGroup  # Implicit dependency

Check for circular dependencies:

  • Review all DependsOn relationships
  • Check Ref and GetAtt usage
  • Verify no circular references

Step 5: Validate best practices

Use specific resource names:

# Good
Resources:
  WebServerSecurityGroup:
    Type: AWS::EC2::SecurityGroup

# Avoid generic names
Resources:
  SecurityGroup1:
    Type: AWS::EC2::SecurityGroup

Add descriptions:

AWSTemplateFormatVersion: '2010-09-09'
Description: Web application infrastructure with ALB and Auto Scaling

Parameters:
  InstanceType:
    Type: String
    Description: EC2 instance type for web servers

Use tags:

Resources:
  Instance:
    Type: AWS::EC2::Instance
    Properties:
      Tags:
        - Key: Name
          Value: !Sub '${AWS::StackName}-WebServer'
        - Key: Environment
          Value: !Ref Environment
        - Key: ManagedBy
          Value: CloudFormation

Common Validation Checks

Syntax Validation

Valid YAML structure:

AWSTemplateFormatVersion: '2010-09-09'
Description: Template description

Parameters:
  # Parameters section

Resources:
  # Resources section (required)

Outputs:
  # Outputs section

Intrinsic functions:

# Correct
Value: !Ref MyResource
Value: !GetAtt MyResource.Attribute
Value: !Sub '${MyResource}'

# Incorrect
Value: Ref: MyResource  # Wrong syntax
Value: !GetAtt MyResource  # Missing attribute

Security Validation

IAM policies:

  • No wildcards in actions unless necessary
  • Specific resources instead of '*'
  • Least privilege principle
  • No hardcoded credentials

Security groups:

  • No 0.0.0.0/0 for sensitive ports (22, 3389, 3306, 5432)
  • Specific port ranges
  • Documented ingress rules

Encryption:

  • Enable encryption for S3 buckets
  • Enable encryption for EBS volumes
  • Enable encryption for RDS instances
  • Use KMS keys for sensitive data

Resource Validation

Required properties:

Resources:
  Bucket:
    Type: AWS::S3::Bucket
    Properties:
      # BucketName is optional but recommended
      BucketName: !Sub '${AWS::StackName}-bucket'

Valid property values:

Resources:
  Instance:
    Type: AWS::EC2::Instance
    Properties:
      InstanceType: t3.micro  # Must be valid instance type
      ImageId: ami-12345678  # Must be valid AMI ID

Validation Tools

AWS CLI

# Validate template
aws cloudformation validate-template \
  --template-body file://template.yaml

# Create change set (validates before applying)
aws cloudformation create-change-set \
  --stack-name my-stack \
  --change-set-name my-changes \
  --template-body file://template.yaml

# Describe change set
aws cloudformation describe-change-set \
  --stack-name my-stack \
  --change-set-name my-changes

cfn-lint

# Basic validation
cfn-lint template.yaml

# Ignore warnings
cfn-lint template.yaml --ignore-checks W

# Specific regions
cfn-lint template.yaml --regions us-east-1 us-west-2

# Custom rules
cfn-lint template.yaml --append-rules custom-rules/

cfn-nag

# Install cfn-nag
gem install cfn-nag

# Scan template
cfn_nag_scan --input-path template.yaml

# Scan with rules
cfn_nag_scan --input-path template.yaml --deny-list-path rules.txt

TaskCat

# Install taskcat
pip install taskcat

# Test template
taskcat test run

# Configuration in .taskcat.yml
project:
  name: my-project
  regions:
    - us-east-1
    - us-west-2
tests:
  default:
    template: template.yaml
    parameters:
      InstanceType: t3.micro

Validation Checklist

Template structure:

  • Valid YAML/JSON syntax
  • AWSTemplateFormatVersion present
  • Description provided
  • Resources section present

Parameters:

  • Descriptive names
  • Descriptions provided
  • Validation constraints (AllowedValues, AllowedPattern)
  • Appropriate defaults
  • NoEcho for sensitive values

Resources:

  • Descriptive logical IDs
  • Required properties present
  • Valid property values
  • Appropriate DependsOn usage
  • Tags applied

Security:

  • IAM policies follow least privilege
  • No hardcoded credentials
  • Security groups restrict access
  • Encryption enabled where appropriate
  • No overly permissive policies

Outputs:

  • Descriptive names
  • Descriptions provided
  • Appropriate exports
  • Conditional outputs where needed

Best practices:

  • Consistent naming convention
  • Appropriate use of parameters
  • Cross-stack references via exports
  • Proper error handling
  • Documentation in descriptions

Advanced

For detailed information, see:

Weekly Installs
5
GitHub Stars
26
First Seen
Feb 4, 2026
Installed on
claude-code5
opencode4
gemini-cli4
github-copilot4
codex4
replit3