Blog

AWS CLOUDFORMATION All Together – Part 2

This is a follow up of my earlier blog – AWS CLOUDFORMATION All Together – Part 1. This covers many of AWS Network Components like VPC, NAT Gateway, Private & Public […]

Nikhil Singh | 31 March , 2016 , 3 years ago

AWS CLOUDFORMATION All Together – Part 2

This is a follow up of my earlier blog – AWS CLOUDFORMATION All Together – Part 1. This covers 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"
         }
      }
   }
}

From 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