Skip to content

AWS CloudFormation

Infrastructure as Code (IaC) service for AWS that allows you to define and provision AWS resources using templates.

CloudFormation Template Basics

Template Formats

CloudFormation supports two template formats:

  • YAML: More readable, supports comments
  • JSON: Validated by schema, less readable

Basic Template Structure (YAML)

yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Sample CloudFormation template

Parameters:
  # Input parameters for your template

Resources:
  # AWS resources to create

Outputs:
  # Values to return after stack creation

Stack Management Commands

Create Stack

COMMANDDESCRIPTION
aws cloudformation create-stack --stack-name my-stack --template-body file://template.yamlCreate stack from template file
aws cloudformation create-stack --stack-name my-stack --template-url https://s3.amazonaws.com/...Create stack from S3 URL
aws cloudformation create-stack --stack-name my-stack --parameters ParameterKey=Param1,ParameterValue=Value1Create with parameters
aws cloudformation create-stack --stack-name my-stack --capabilities CAPABILITY_IAMCreate with IAM capabilities
aws cloudformation create-stack --stack-name my-stack --on-failure ROLLBACKSet failure behavior (ROLLBACK/DELETE/DO_NOTHING)

Update Stack

COMMANDDESCRIPTION
aws cloudformation update-stack --stack-name my-stack --template-body file://template.yamlUpdate stack with new template
aws cloudformation update-stack --stack-name my-stack --parameters ParameterKey=Param1,ParameterValue=NewValueUpdate stack parameters
aws cloudformation update-stack --stack-name my-stack --use-previous-templateRe-use existing template
aws cloudformation update-stack --stack-name my-stack --capabilities CAPABILITY_IAMUpdate with IAM capabilities

Delete Stack

COMMANDDESCRIPTION
aws cloudformation delete-stack --stack-name my-stackDelete stack
aws cloudformation delete-stack --stack-name my-stack --retain-resources Resource1,Resource2Delete but retain specific resources

Stack Monitoring

COMMANDDESCRIPTION
aws cloudformation describe-stacks --stack-name my-stackDescribe stack details
aws cloudformation list-stacksList all stacks
aws cloudformation list-stacks --stack-status-filter CREATE_COMPLETE UPDATE_COMPLETEFilter by status
aws cloudformation get-template --stack-name my-stackGet stack template
aws cloudformation describe-stack-events --stack-name my-stackView stack events
aws cloudformation describe-stack-resources --stack-name my-stackList stack resources
aws cloudformation describe-stack-resource --stack-name my-stack --logical-resource-id MyResourceGet specific resource details
aws cloudformation list-stack-resources --stack-name my-stackList all resources in stack

Change Sets

COMMANDDESCRIPTION
aws cloudformation create-change-set --stack-name my-stack --change-set-name my-changes --template-body file://template.yamlCreate change set
aws cloudformation describe-change-set --change-set-name my-changes --stack-name my-stackDescribe change set
aws cloudformation list-change-sets --stack-name my-stackList all change sets
aws cloudformation execute-change-set --change-set-name my-changes --stack-name my-stackExecute change set
aws cloudformation delete-change-set --change-set-name my-changes --stack-name my-stackDelete change set

Stack Drift Detection

COMMANDDESCRIPTION
aws cloudformation detect-stack-drift --stack-name my-stackDetect stack drift
aws cloudformation describe-stack-drift-detection-status --stack-drift-detection-id <id>Check drift detection status
aws cloudformation describe-stack-resource-drifts --stack-name my-stackList drifted resources
aws cloudformation detect-stack-resource-drift --stack-name my-stack --logical-resource-id MyResourceDetect drift for single resource

Common Resource Examples

S3 Bucket

yaml
Resources:
  MyBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: my-unique-bucket-name
      VersioningConfiguration:
        Status: Enabled
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256

EC2 Instance

yaml
Resources:
  MyInstance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: ami-0c55b159cbfafe1f0
      InstanceType: t2.micro
      KeyName: my-key-pair
      SecurityGroupIds:
        - sg-12345678
      UserData: !Base64 |
        #!/bin/bash
        echo "Hello World" > /tmp/hello.txt

VPC

yaml
Resources:
  MyVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: MyVPC

  PublicSubnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MyVPC
      CidrBlock: 10.0.1.0/24
      AvailabilityZone: us-east-1a
      MapPublicIpOnLaunch: true

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: MyIGW

  VPCGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref MyVPC
      InternetGatewayId: !Ref InternetGateway

Lambda Function

yaml
Resources:
  MyLambdaFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: MyLambda
      Runtime: python3.9
      Handler: index.handler
      Code:
        ZipFile: |
          def handler(event, context):
              return {'statusCode': 200, 'body': 'Hello World'}
      Role: !GetAtt LambdaRole.Arn

  LambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

Security Group

yaml
Resources:
  MySecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTP/SSH
      GroupName: MySecurityGroup
      VpcId: !Ref MyVPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          CidrIp: 0.0.0.0/0
        - IpProtocol: tcp
          FromPort: 22
          ToPort: 22
          CidrIp: 10.0.0.0/16

Parameters

Parameter Types

TypeDescriptionExample
StringAlphanumeric string!Sub ${AWS::StackName}
NumberInteger or float1, 2.5
List<Number>Array of numbers[1, 2, 3]
CommaDelimitedListComma-separated values"a,b,c"
AWS::EC2::KeyPair::KeyNameEC2 key pair namemy-key-pair
AWS::EC2::SecurityGroup::GroupNameSecurity group namemy-sg
AWS::EC2::Subnet::IdSubnet IDsubnet-12345
AWS::EC2::VPC::IdVPC IDvpc-12345
AWS::SSM::Parameter::NameSSM parameter name/my/parameter

Parameter Example

yaml
Parameters:
  Environment:
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - staging
      - prod
    Description: Deployment environment

  InstanceType:
    Type: String
    Default: t2.micro
    AllowedValues:
      - t2.micro
      - t2.small
      - t2.medium
    Description: EC2 instance type

  KeyName:
    Type: AWS::EC2::KeyPair::KeyName
    Description: EC2 key pair name

Pseudo Parameters

ParameterDescriptionExample Value
AWS::AccountIdAccount ID123456789012
AWS::NotificationARNsNotification ARNs[]
AWS::NoValueRemoves propertyUsed with conditional
AWS::PartitionPartition nameaws
AWS::RegionRegion nameus-east-1
AWS::StackIdStack IDarn:aws:cloudformation:...
AWS::StackNameStack namemy-stack
AWS::URLSuffixURL suffixamazonaws.com

Intrinsic Functions

FunctionDescriptionExample
!RefReturn value of parameter or resource!Ref InstanceType
!GetAttGet attribute from resource!GetAtt MyInstance.PublicIp
!SubSubstitute variables in string!Sub ${AWS::StackName}-bucket
!JoinJoin values with delimiter!Join ['-', [a, b, c]]
!SelectSelect from list!Select [0, !Ref MyList]
!GetAZsGet availability zones!GetAZs ''
!ImportValueImport export from another stack!ImportValue VPC-ID
!IfConditional logic!If [Condition, TrueValue, FalseValue]
!AndLogical AND!And [!Equals [a, b], !Equals [c, d]]
!OrLogical OR!Or [!Equals [a, b], !Equals [c, d]]
!NotLogical NOT!Not [!Equals [a, b]]
!EqualsString equality!Equals [!Ref Env, 'prod']

Condition Example

yaml
Parameters:
  Environment:
    Type: String
    Default: dev
    AllowedValues:
      - dev
      - prod

Conditions:
  IsProd: !Equals [!Ref Environment, prod]

Resources:
  MyBucket:
    Type: AWS::S3::Bucket
    Properties:
      VersioningConfiguration:
        Status: !If [IsProd, Enabled, Suspended]

Outputs

Output Example

yaml
Outputs:
  VPCId:
    Description: VPC ID
    Value: !Ref MyVPC
    Export:
      Name: !Sub ${AWS::StackName}-VPC-ID

  InstancePublicIP:
    Description: EC2 instance public IP
    Value: !GetAtt MyInstance.PublicIp

  BucketARN:
    Description: S3 bucket ARN
    Value: !GetAtt MyBucket.Arn

Useful Tips

Validation

COMMANDDESCRIPTION
aws cloudformation validate-template --template-body file://template.yamlValidate template syntax
aws cloudformation validate-template --template-url https://s3.amazonaws.com/...Validate remote template

Stack Policies

yaml
{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "Update:Modify",
      "Principal": "*",
      "Resource": "*"
    },
    {
      "Effect": "Deny",
      "Action": "Update:Replace",
      "Principal": "*",
      "Resource": "LogicalResourceId/MyDatabase"
    }
  ]
}

Common Stack Errors

ErrorSolution
CAPABILITY_IAM requiredAdd --capabilities CAPABILITY_IAM to command
CAPABILITY_NAMED_IAM requiredAdd --capabilities CAPABILITY_NAMED_IAM to command
Parameter validation failedCheck parameter values match allowed values
Resource creation failedCheck CloudFormation logs for specific error
Stack already existsUse update-stack instead of create-stack

Best Practices

  1. Use Parameters for values that change between environments
  2. Use Mappings for region-specific values
  3. Use Conditions for environment-specific resources
  4. Use Outputs to share values between stacks
  5. Use Stack Policies to protect critical resources
  6. Use Change Sets for production updates
  7. Enable Termination Protection for production stacks
  8. Use IAM least privilege for CloudFormation roles
  9. Test templates in dev environment first
  10. Version control your templates

Released under MIT License.