AWS CLOUDFORMATION All Together – Part 2

AWS Cloudformation

This is a follow up of my earlier blog where I coverd many of AWS Network Components like VPC, NAT Gateway, Private & Public Subnet etc. So here I am hope from my last blog AWS CLOUDFORMATION All Together – Part 1 you would have got basic idea of how to work with Cloud Formation. In this let create template for creating

  1. VPC
  2. NAT Gateway
  3. 2 Public Subnet
  4. 2 Private Subnet
  5. Other dependent Resources for VPC

NAT Gateway is new AWS Managed Service which replaces  NAT instances which had to be configured by ourself.

  1. Parameters

The Parameters to be passed are Tag VPC CIDR Range Public Subnet-1 CIDR Range Public Subnet-1 Availability Zone Public Subnet-2 CIDR Range Public Subnet-2 Availability Zone Private Subnet-1 CIDR Range Private Subnet-1 Availability Zone Private Subnet-2 CIDR Range Private Subnet-2 Availability Zone

Tip: Use of “AllowedValues” helps in selecting the value from a drop down list as in below screen-shot. "TagValue2" : { "Description" : "The Name of Environment", "Type" : "String", "AllowedValues" : ["Development","Staging","Production"]

Environment-tag

  1. Resources

In Resources section we will have the following components VPC Subnets Internet Gateway NAT Gateway EIP for NAT Gateway Route Table Route Table Association Network Acl Subnet Network Acl Association Private Subnets

Few important points worth considering. Please note that you will likely have a Network ACL Association per subnet subnet 1 to acl1 subnet 2 to acl2


"PrivateSubnetNetworkAclAssociation1":{  
   "Type":"AWS::EC2::SubnetNetworkAclAssociation",
   "Properties":{  
      "SubnetId":{  
         "Ref":"PrivateSubnet1"
      },
      "NetworkAclId":{  
         "Ref":"PrivateNetworkAcl"
      }
   }
},
"PrivateSubnetNetworkAclAssociation2":{  
   "Type":"AWS::EC2::SubnetNetworkAclAssociation",
   "Properties":{  
      "SubnetId":{  
         "Ref":"PrivateSubnet2"
      },
      "NetworkAclId":{  
         "Ref":"PrivateNetworkAcl"
      }
   }
},
Here we can not add both subnet in single block like 
"PrivateSubnetNetworkAclAssociation1":{  
   "Type":"AWS::EC2::SubnetNetworkAclAssociation",
   "Properties":{  
      "SubnetId":[  
         {  
            "Ref":"PrivateSubnet1"
         },
         {  
            "Ref":"PrivateSubnet2"
         }
      ]      "NetworkAclId":{  
         "Ref":"PrivateNetworkAcl"
      }
   }
},
Finally here is my template which will create VPC,
2Public Subnet,
2Private Subnet and NAT Gateway.{  
   "AWSTemplateFormatVersion":"2016-03-31",
   "Description":"This Template will create VPC, Subnet and resources needed for VPC  ",
   "Parameters":{  
      "TagValue1":{  
         "Description":"The Project Name",
         "Type":"String"
      },
      "TagValue2":{  
         "Description":"The Name of Environment",
         "Type":"String",
         "AllowedValues":[  
            "Development",
            "Staging",
            "Production"
         ]
      },
      "CIDR":{  
         "Description":"The IP address range that you'll use for your VPC",
         "Type":"String"
      }      "PublicCidrBlock1":{  
         "Description":"The IP address range for Public Subnet 1",
         "Type":"String"
      },
      "PublicSubnet1AZ":{  
         "Description":"The AZ for Public Subnet 1",
         "Type":"AWS::EC2::AvailabilityZone::Name"
      },
      "PublicCidrBlock2":{  
         "Description":"The IP address range for Public Subnet 2",
         "Type":"String"
      },
      "PublicSubnet2AZ":{  
         "Description":"The AZ for Public Subnet 2",
         "Type":"AWS::EC2::AvailabilityZone::Name"
      },
      "PrivateCidrBlock1":{  
         "Description":"The IP address range for Private Subnet 1",
         "Type":"String"
      },
      "PrivateSubnet1AZ":{  
         "Description":"The AZ for Private Subnet 1",
         "Type":"AWS::EC2::AvailabilityZone::Name"
      },
      "PrivateCidrBlock2":{  
         "Description":"The IP address range for Private Subnet 2",
         "Type":"String"
      },
      "PrivateSubnet2AZ":{  
         "Description":"The AZ Private Subnet 2",
         "Type":"AWS::EC2::AvailabilityZone::Name"
      }
   },
   "Resources":{  
      "VPC":{  
         "Type":"AWS::EC2::VPC",
         "Properties":{  
            "CidrBlock":{  
               "Ref":"CIDR"
            },
            "EnableDnsSupport":"true",
            "EnableDnsHostnames":"true",
            "InstanceTenancy":"default",
            "Tags":[  
               {  
                  "Key":"Project",
                  "Value":{  
                     "Ref":"TagValue1"
                  }
               },
               {  
                  "Key":"Environment",
                  "Value":{  
                     "Ref":"TagValue2"
                  }
               }
            ]
         }
      },
      "PublicSubnet1":{  
         "Type":"AWS::EC2::Subnet",
         "Properties":{  
            "VpcId":{  
               "Ref":"VPC"
            },
            "CidrBlock":{  
               "Ref":"PublicCidrBlock1"
            },
            "MapPublicIpOnLaunch":"true",
            "AvailabilityZone":{  
               "Ref":"PublicSubnet1AZ"
            },
            "Tags":[  
               {  
                  "Key":"Project",
                  "Value":{  
                     "Ref":"TagValue1"
                  }
               },
               {  
                  "Key":"Environment",
                  "Value":{  
                     "Ref":"TagValue2"
                  }
               }
            ]
         }
      },
      "PublicSubnet2":{  
         "Type":"AWS::EC2::Subnet",
         "Properties":{  
            "VpcId":{  
               "Ref":"VPC"
            },
            "CidrBlock":{  
               "Ref":"PublicCidrBlock2"
            },
            "MapPublicIpOnLaunch":"true",
            "AvailabilityZone":{  
               "Ref":"PublicSubnet2AZ"
            },
            "Tags":[  
               {  
                  "Key":"Project",
                  "Value":{  
                     "Ref":"TagValue1"
                  }
               },
               {  
                  "Key":"Environment",
                  "Value":{  
                     "Ref":"TagValue2"
                  }
               }
            ]
         }
      },
      "InternetGateway":{  
         "Type":"AWS::EC2::InternetGateway",
         "Properties":{  
            "Tags":[  
               {  
                  "Key":"Project",
                  "Value":{  
                     "Ref":"TagValue1"
                  }
               },
               {  
                  "Key":"Environment",
                  "Value":{  
                     "Ref":"TagValue2"
                  }
               }
            ]
         }
      },
      "AttachGateway":{  
         "Type":"AWS::EC2::VPCGatewayAttachment",
         "Properties":{  
            "VpcId":{  
               "Ref":"VPC"
            },
            "InternetGatewayId":{  
               "Ref":"InternetGateway"
            }
         }
      },
      "NAT":{  
         "DependsOn":"AttachGateway",
         "Type":"AWS::EC2::NatGateway",
         "Properties":{  
            "AllocationId":{  
               "Fn::GetAtt":[  
                  "EIP",
                  "AllocationId"
               ]
            },
            "SubnetId":{  
               "Ref":"PublicSubnet1"
            }
         }
      },
      "EIP":{  
         "Type":"AWS::EC2::EIP",
         "Properties":{  
            "Domain":"vpc"
         }
      },
      "PublicRouteTable":{  
         "Type":"AWS::EC2::RouteTable",
         "Properties":{  
            "VpcId":{  
               "Ref":"VPC"
            },
            "Tags":[  
               {  
                  "Key":"Project",
                  "Value":{  
                     "Ref":"TagValue1"
                  }
               },
               {  
                  "Key":"Environment",
                  "Value":{  
                     "Ref":"TagValue2"
                  }
               },
               {  
                  "Key":"Network",
                  "Value":"Public"
               }
            ]
         }
      },
      "PublicRoute":{  
         "Type":"AWS::EC2::Route",
         "DependsOn":"AttachGateway",
         "Properties":{  
            "RouteTableId":{  
               "Ref":"PublicRouteTable"
            },
            "DestinationCidrBlock":"0.0.0.0/0",
            "GatewayId":{  
               "Ref":"InternetGateway"
            }
         }
      },
      "PublicSubnetRouteTableAssociation1":{  
         "Type":"AWS::EC2::SubnetRouteTableAssociation",
         "Properties":{  
            "SubnetId":{  
               "Ref":"PublicSubnet1"
            },
            "RouteTableId":{  
               "Ref":"PublicRouteTable"
            }
         }
      },
      "PublicSubnetRouteTableAssociation2":{  
         "Type":"AWS::EC2::SubnetRouteTableAssociation",
         "Properties":{  
            "SubnetId":{  
               "Ref":"PublicSubnet2"
            },
            "RouteTableId":{  
               "Ref":"PublicRouteTable"
            }
         }
      },
      "PublicNetworkAcl":{  
         "Type":"AWS::EC2::NetworkAcl",
         "Properties":{  
            "VpcId":{  
               "Ref":"VPC"
            },
            "Tags":[  
               {  
                  "Key":"Project",
                  "Value":{  
                     "Ref":"TagValue1"
                  }
               },
               {  
                  "Key":"Environment",
                  "Value":{  
                     "Ref":"TagValue2"
                  }
               },
               {  
                  "Key":"Network",
                  "Value":"Public"
               }
            ]
         }
      },
      "PublicSubnetNetworkAclAssociation1":{  
         "Type":"AWS::EC2::SubnetNetworkAclAssociation",
         "Properties":{  
            "SubnetId":{  
               "Ref":"PublicSubnet1"
            },
            "NetworkAclId":{  
               "Ref":"PublicNetworkAcl"
            }
         }
      },
      "PublicSubnetNetworkAclAssociation2":{  
         "Type":"AWS::EC2::SubnetNetworkAclAssociation",
         "Properties":{  
            "SubnetId":{  
               "Ref":"PublicSubnet2"
            },
            "NetworkAclId":{  
               "Ref":"PublicNetworkAcl"
            }
         }
      },
      "PrivateSubnet1":{  
         "Type":"AWS::EC2::Subnet",
         "Properties":{  
            "VpcId":{  
               "Ref":"VPC"
            },
            "CidrBlock":{  
               "Ref":"PrivateCidrBlock1"
            },
            "AvailabilityZone":{  
               "Ref":"PrivateSubnet1AZ"
            },
            "Tags":[  
               {  
                  "Key":"Project",
                  "Value":{  
                     "Ref":"TagValue1"
                  }
               },
               {  
                  "Key":"Environment",
                  "Value":{  
                     "Ref":"TagValue2"
                  }
               }
            ]
         }
      },
      "PrivateSubnet2":{  
         "Type":"AWS::EC2::Subnet",
         "Properties":{  
            "VpcId":{  
               "Ref":"VPC"
            },
            "CidrBlock":{  
               "Ref":"PrivateCidrBlock2"
            },
            "AvailabilityZone":{  
               "Ref":"PrivateSubnet2AZ"
            },
            "Tags":[  
               {  
                  "Key":"Project",
                  "Value":{  
                     "Ref":"TagValue1"
                  }
               },
               {  
                  "Key":"Environment",
                  "Value":{  
                     "Ref":"TagValue2"
                  }
               }
            ]
         }
      },
      "PrivateRouteTable":{  
         "Type":"AWS::EC2::RouteTable",
         "Properties":{  
            "VpcId":{  
               "Ref":"VPC"
            },
            "Tags":[  
               {  
                  "Key":"Project",
                  "Value":{  
                     "Ref":"TagValue1"
                  }
               },
               {  
                  "Key":"Environment",
                  "Value":{  
                     "Ref":"TagValue2"
                  }
               },
               {  
                  "Key":"Network",
                  "Value":"Private"
               }
            ]
         }
      },
      "PrivateSubnetRouteTableAssociation1":{  
         "Type":"AWS::EC2::SubnetRouteTableAssociation",
         "Properties":{  
            "SubnetId":{  
               "Ref":"PrivateSubnet1"
            },
            "RouteTableId":{  
               "Ref":"PrivateRouteTable"
            }
         }
      },
      "PrivateSubnetRouteTableAssociation2":{  
         "Type":"AWS::EC2::SubnetRouteTableAssociation",
         "Properties":{  
            "SubnetId":{  
               "Ref":"PrivateSubnet2"
            },
            "RouteTableId":{  
               "Ref":"PrivateRouteTable"
            }
         }
      },
      "PrivateNATRouteTableAssociation":{  
         "Type":"AWS::EC2::Route",
         "Properties":{  
            "RouteTableId":{  
               "Ref":"PrivateRouteTable"
            },
            "DestinationCidrBlock":"0.0.0.0/0",
            "NatGatewayId":{  
               "Ref":"NAT"
            }
         }
      },
      "PrivateNetworkAcl":{  
         "Type":"AWS::EC2::NetworkAcl",
         "Properties":{  
            "VpcId":{  
               "Ref":"VPC"
            },
            "Tags":[  
               {  
                  "Key":"Project",
                  "Value":{  
                     "Ref":"TagValue1"
                  }
               },
               {  
                  "Key":"Environment",
                  "Value":{  
                     "Ref":"TagValue2"
                  }
               },
               {  
                  "Key":"Network",
                  "Value":"Private"
               }
            ]
         }
      },
      "PrivateSubnetNetworkAclAssociation1":{  
         "Type":"AWS::EC2::SubnetNetworkAclAssociation",
         "Properties":{  
            "SubnetId":{  
               "Ref":"PrivateSubnet1"
            },
            "NetworkAclId":{  
               "Ref":"PrivateNetworkAcl"
            }
         }
      },
      "PrivateSubnetNetworkAclAssociation2":{  
         "Type":"AWS::EC2::SubnetNetworkAclAssociation",
         "Properties":{  
            "SubnetId":{  
               "Ref":"PrivateSubnet2"
            },
            "NetworkAclId":{  
               "Ref":"PrivateNetworkAcl"
            }
         }
      },
      "NetworkAclEntry1":{  
         "Type":"AWS::EC2::NetworkAclEntry",
         "Properties":{  
            "CidrBlock":"0.0.0.0/0",
            "Egress":"true",
            "Protocol":"-1",
            "RuleAction":"allow",
            "RuleNumber":"100",
            "NetworkAclId":{  
               "Ref":"PublicNetworkAcl"
            }
         }
      },
      "NetworkAclEntry2":{  
         "Type":"AWS::EC2::NetworkAclEntry",
         "Properties":{  
            "CidrBlock":"0.0.0.0/0",
            "Protocol":"-1",
            "RuleAction":"allow",
            "RuleNumber":"100",
            "NetworkAclId":{  
               "Ref":"PublicNetworkAcl"
            }
         }
      },
      "NetworkAclEntry3":{  
         "Type":"AWS::EC2::NetworkAclEntry",
         "Properties":{  
            "CidrBlock":"0.0.0.0/0",
            "Egress":"true",
            "Protocol":"-1",
            "RuleAction":"allow",
            "RuleNumber":"100",
            "NetworkAclId":{  
               "Ref":"PrivateNetworkAcl"
            }
         }
      },
      "NetworkAclEntry4":{  
         "Type":"AWS::EC2::NetworkAclEntry",
         "Properties":{  
            "CidrBlock":"0.0.0.0/0",
            "Protocol":"-1",
            "RuleAction":"allow",
            "RuleNumber":"100",
            "NetworkAclId":{  
               "Ref":"PrivateNetworkAcl"
            }
         }
      }
   },
   "Outputs":{  
      "VPCId":{  
         "Description":"VPCId of the newly created VPC",
         "Value":          {  
            "Ref":"VPC"
         }
      },
      "PublicSubnet1Id":{  
         "Description":"SubnetId of the public subnet",
         "Value":          {  
            "Ref":"PublicSubnet1"
         }
      },
      "PublicSubnet2Id":{  
         "Description":"SubnetId of the public subnet",
         "Value":          {  
            "Ref":"PublicSubnet2"
         }
      },
      "PrivateSubnet1Id":{  
         "Description":"SubnetId of the public subnet",
         "Value":          {  
            "Ref":"PrivateSubnet1"
         }
      },
      "PrivateSubnet2Id":{  
         "Description":"SubnetId of the public subnet",
         "Value":          {  
            "Ref":"PrivateSubnet2"
         }
      }
   }
}

Using CLI:


aws cloudformation create-stack –stack-name MY-FIRST-VPC –template-body file:///file-path.json –parameters ParameterKey=CIDR,ParameterValue=10.0.0.0/16 ParameterKey=PrivateCidrBlock1,ParameterValue=10.0.1.0/24 ParameterKey=PrivateCidrBlock2,ParameterValue=10.0.2.0/24 ParameterKey=PrivateSubnet1AZ,ParameterValue=us-east-1b ParameterKey=PrivateSubnet2AZ,ParameterValue=us-east-1c ParameterKey=PublicCidrBlock1,ParameterValue=10.0.3.0/24 ParameterKey=PublicCidrBlock2,ParameterValue=10.0.4.0/24 ParameterKey=PublicSubnet1AZ,ParameterValue=us-east-1b ParameterKey=PublicSubnet2AZ,ParameterValue=us-east-1c ParameterKey=TagValue1,ParameterValue=MyProject ParameterKey=TagValue2,ParameterValue=Development

Conclusion

AWS CLOUDFORMATION helps you implement Infra as a Code. This is the part 2 of the blog that we published earlier.

Related Blogs