Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
832 lines (831 sloc) 20.7 KB
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Create a VPC with public/private subnets in two AZs using NAT gateways in each public zone for private instance outbound Internet connectivity.",
"Metadata": {
"AWS::CloudFormation::Interface": {
"ParameterGroups": [
{
"Label": { "default": "VPC Configuration" },
"Parameters": [
"Environment",
"RemoteCIDR",
"ConfigS3Endpoint",
"S3Bucket",
"TemplatePath",
"VpcCIDR",
"AvZone1",
"AvZone2",
"PublicSubnetAZ1",
"PublicSubnetAZ2",
"PrivateSubnetAZ1",
"PrivateSubnetAZ2"
]
}
],
"ParameterLabels": {
"Environment": { "default": "Which environment will use this VPC? (used in various tags and resource names)" },
"VpcCIDR": { "default": "What is the CIDR block for this VPC?" }
}
}
},
"Parameters": {
"Environment": {
"Type": "String",
"Description": "Used for miscellaneous object names and tags",
"AllowedValues": [ "dev", "staging", "prod" ],
"Default": "dev"
},
"ConfigS3Endpoint": {
"Type": "String",
"Description": "Select yes to create a VPC endpoint to privatize access to S3 resources. Be sure to review implications first.",
"AllowedValues": [ "no", "yes" ],
"Default": "no"
},
"VpcCIDR": {
"Type": "String",
"Description": "IP Address range for the VPC",
"MinLength": "9",
"MaxLength": "18",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "Valid IP CIDR range as x.x.x.x/x.",
"Default": "10.0.0.0/16"
},
"PublicSubnetAZ1": {
"Type": "String",
"Description": "IP Address range for AZ1 public subnet",
"MinLength": "9",
"MaxLength": "18",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "Valid IP CIDR block range - x.x.x.x/x.",
"Default": "10.0.0.0/24"
},
"PublicSubnetAZ2": {
"Type": "String",
"Description": "IP Address range for AZ2 public subnet",
"MinLength": "9",
"MaxLength": "18",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "Valid IP CIDR block range - x.x.x.x/x.",
"Default": "10.0.2.0/24"
},
"PrivateSubnetAZ1": {
"Type": "String",
"Description": "IP Address range for AZ1 private subnet",
"MinLength": "9",
"MaxLength": "18",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "Valid IP CIDR block range - x.x.x.x/x.",
"Default": "10.0.1.0/24"
},
"PrivateSubnetAZ2": {
"Type": "String",
"Description": "IP Address range for AZ2 private subnet",
"MinLength": "9",
"MaxLength": "18",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "Valid IP CIDR block range - x.x.x.x/x.",
"Default": "10.0.3.0/24"
},
"AvZone1": {
"Type": "String",
"Description": "First AZ to use for subnets, etc.",
"ConstraintDescription": "Must be a valid AZ - # aws ec2 describe-availability-zones",
"Default": "us-east-1a"
},
"AvZone2": {
"Type": "String",
"Description": "Second AZ to use for subnets, etc.",
"ConstraintDescription": "Must be a valid AZ - # aws ec2 describe-availability-zones",
"Default": "us-east-1c"
},
"RemoteCIDR": {
"Type": "String",
"Description": "CIDR IP range allowed to login remotely to the VPC, ideally your VPN/ISP netblock",
"MinLength": "9",
"MaxLength": "18",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"ConstraintDescription": "must be a valid CIDR range of the form x.x.x.x/x."
},
"S3Bucket": {
"Type": "String",
"Description": "S3Bucket containing CloudFormation templates, also used for S3 VPC Endpoint policy",
"Default": "myS3bucket"
},
"TemplatePath": {
"Type": "String",
"Description": "Path to CloudFormation templates (relative to top level of S3Bucket parameter)",
"Default": "/cloudformation_templates/"
}
},
"Mappings": {
"PrefixListId": {
"us-east-1": {
"s3": "pl-63a5400a"
},
"us-east-2": {
"s3": "pl-7ba54012"
},
"us-west-1": {
"s3": "pl-6ba54002"
},
"us-west-2": {
"s3": "pl-68a54001"
},
"eu-west-1": {
"s3": "pl-6da54004"
},
"eu-central-1": {
"s3": "pl-6ea54007"
},
"ap-northeast-1": {
"s3": "pl-61a54008"
},
"ap-northeast-2": {
"s3": "pl-78a54011"
},
"ap-southeast-1": {
"s3": "pl-6fa54006"
},
"ap-southeast-2": {
"s3": "pl-6ca54005"
},
"ap-south-1": {
"s3": "pl-78a54011"
},
"sa-east-1": {
"s3": "pl-6aa54003"
}
}
},
"Conditions": {
"ConfigureS3Endpoint": {
"Fn::Equals": [
{
"Ref": "ConfigS3Endpoint"
},
"yes"
]
}
},
"Resources": {
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"EnableDnsSupport": "True",
"EnableDnsHostnames": "True",
"CidrBlock": {
"Ref": "VpcCIDR"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"vpc_",
{
"Ref": "Environment"
}
]
]
}
},
{
"Key": "Environment",
"Value": {
"Ref": "Environment"
}
}
]
}
},
"InetGw": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"igw_",
{
"Ref": "Environment"
}
]
]
}
},
{
"Key": "Environment",
"Value": {
"Ref": "Environment"
}
}
]
}
},
"IgwAttachment": {
"DependsOn": [ "InetGw" ],
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"InternetGatewayId": {
"Ref": "InetGw"
}
}
},
"PubSubnetAZ1": {
"DependsOn": [ "VPC" ],
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"AvailabilityZone": {
"Ref": "AvZone1"
},
"CidrBlock": {
"Ref": "PublicSubnetAZ1"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"subnet_",
{
"Ref": "Environment"
},
"_public_az1"
]
]
}
},
{
"Key": "Environment",
"Value": {
"Ref": "Environment"
}
}
]
}
},
"PubSubnetAZ2": {
"DependsOn": [ "VPC" ],
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"AvailabilityZone": {
"Ref": "AvZone2"
},
"CidrBlock": {
"Ref": "PublicSubnetAZ2"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"subnet_",
{
"Ref": "Environment"
},
"_public_az2"
]
]
}
},
{
"Key": "Environment",
"Value": {
"Ref": "Environment"
}
}
]
}
},
"PublicRoute": {
"DependsOn": [ "PublicRouteTable", "VPC" ],
"Type": "AWS::EC2::Route",
"DependsOn": [ "InetGw","PublicRouteTable" ],
"Properties": {
"RouteTableId": {
"Ref": "PublicRouteTable"
},
"DestinationCidrBlock": "0.0.0.0/0",
"GatewayId": {
"Ref": "InetGw"
}
}
},
"PublicRouteTable": {
"DependsOn": [ "VPC" ],
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"rtb_",
{
"Ref": "Environment"
},
"_public"
]
]
}
},
{
"Key": "SubnetType",
"Value": "public"
},
{
"Key": "Environment",
"Value": {
"Ref": "Environment"
}
}
]
}
},
"PubRouteTableAssocAZ1": {
"DependsOn": [ "PubSubnetAZ1", "PublicRouteTable" ],
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PubSubnetAZ1"
},
"RouteTableId": {
"Ref": "PublicRouteTable"
}
}
},
"PubRouteTableAssocAZ2": {
"DependsOn": [ "PubSubnetAZ2", "PublicRouteTable" ],
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PubSubnetAZ2"
},
"RouteTableId": {
"Ref": "PublicRouteTable"
}
}
},
"PrivSubnetAZ1": {
"DependsOn": [ "VPC" ],
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"AvailabilityZone": {
"Ref": "AvZone1"
},
"CidrBlock": {
"Ref": "PrivateSubnetAZ1"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"subnet_",
{
"Ref": "Environment"
},
"_private_az1"
]
]
}
},
{
"Key": "Environment",
"Value": {
"Ref": "Environment"
}
}
]
}
},
"PrivSubnetAZ2": {
"DependsOn": [ "VPC" ],
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"AvailabilityZone": {
"Ref": "AvZone2"
},
"CidrBlock": {
"Ref": "PrivateSubnetAZ2"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"subnet_",
{
"Ref": "Environment"
},
"_private_az2"
]
]
}
},
{
"Key": "Environment",
"Value": {
"Ref": "Environment"
}
}
]
}
},
"PrivateRouteAZ1": {
"DependsOn": [ "PrivateRouteTableAZ1", "NatGatewayAZ1" ],
"Type": "AWS::EC2::Route",
"Properties": {
"RouteTableId": {
"Ref": "PrivateRouteTableAZ1"
},
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": {
"Ref": "NatGatewayAZ1"
}
}
},
"PrivateRouteAZ2": {
"DependsOn": [ "PrivateRouteTableAZ2", "NatGatewayAZ2" ],
"Type": "AWS::EC2::Route",
"Properties": {
"RouteTableId": {
"Ref": "PrivateRouteTableAZ2"
},
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": {
"Ref": "NatGatewayAZ2"
}
}
},
"PrivateRouteTableAZ1": {
"DependsOn": [ "VPC" ],
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"rtb_",
{
"Ref": "Environment"
},
"_private_az1"
]
]
}
},
{
"Key": "SubnetType",
"Value": "private"
},
{
"Key": "Environment",
"Value": {
"Ref": "Environment"
}
}
]
}
},
"PrivateRouteTableAZ2": {
"DependsOn": [ "VPC" ],
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {
"Ref": "VPC"
},
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"rtb_",
{
"Ref": "Environment"
},
"_private_az2"
]
]
}
},
{
"Key": "SubnetType",
"Value": "private"
},
{
"Key": "Environment",
"Value": {
"Ref": "Environment"
}
}
]
}
},
"PrivRouteTableAssocAZ1": {
"DependsOn": [ "PrivSubnetAZ1", "PrivateRouteTableAZ1" ],
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivSubnetAZ1"
},
"RouteTableId": {
"Ref": "PrivateRouteTableAZ1"
}
}
},
"PrivRouteTableAssocAZ2": {
"DependsOn": [ "PrivSubnetAZ2", "PrivateRouteTableAZ2" ],
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {
"Ref": "PrivSubnetAZ2"
},
"RouteTableId": {
"Ref": "PrivateRouteTableAZ2"
}
}
},
"NetworkAclStack": {
"DependsOn": [ "PrivSubnetAZ1", "PrivSubnetAZ2", "PubSubnetAZ1", "PubSubnetAZ2" ],
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": {
"Fn::Join": [
"",
[
"https://s3.amazonaws.com/",
{
"Ref": "S3Bucket"
},
{
"Ref": "TemplatePath"
},
"aws-vpc-network-acls.json"
]
]
},
"Parameters": {
"AvZone1": { "Ref": "AvZone1" },
"AvZone2": { "Ref": "AvZone2" },
"Environment": { "Ref": "Environment" },
"PrivSubnetAZ1": { "Ref": "PrivSubnetAZ1" },
"PrivSubnetAZ2": { "Ref": "PrivSubnetAZ2" },
"PrivateSubnetAZ1": { "Ref": "PrivateSubnetAZ1" },
"PrivateSubnetAZ2": { "Ref": "PrivateSubnetAZ2" },
"PubSubnetAZ1": { "Ref": "PubSubnetAZ1" },
"PubSubnetAZ2": { "Ref": "PubSubnetAZ2" },
"RemoteCIDR": { "Ref": "RemoteCIDR" },
"VPC": { "Ref": "VPC" },
"VpcCIDR": { "Ref": "VpcCIDR" }
},
"TimeoutInMinutes": "15"
}
},
"S3EndpointStack": {
"DependsOn": [ "PrivateRouteTableAZ1", "PrivateRouteTableAZ2", "PublicRouteTable" ],
"Condition" : "ConfigureS3Endpoint",
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": {
"Fn::Join": [
"",
[
"https://s3.amazonaws.com/",
{
"Ref": "S3Bucket"
},
{
"Ref": "TemplatePath"
},
"aws-vpc-s3endpoint.json"
]
]
},
"Parameters": {
"PrivateRouteTableAZ1": { "Ref": "PrivateRouteTableAZ1" },
"PrivateRouteTableAZ2": { "Ref": "PrivateRouteTableAZ2" },
"PublicRouteTable": { "Ref": "PublicRouteTable" },
"S3Bucket": { "Ref": "S3Bucket" },
"VPC": { "Ref": "VPC" }
},
"TimeoutInMinutes": "15"
}
},
"InstanceSecurityGroupStack": {
"DependsOn": [ "PrivSubnetAZ1", "PrivSubnetAZ2", "PubSubnetAZ1", "PubSubnetAZ2" ],
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": {
"Fn::Join": [
"",
[
"https://s3.amazonaws.com/",
{
"Ref": "S3Bucket"
},
{
"Ref": "TemplatePath"
},
"aws-vpc-instance-securitygroups.json"
]
]
},
"Parameters": {
"Environment": { "Ref": "Environment" },
"RemoteCIDR": { "Ref": "RemoteCIDR" },
"VpcCIDR": { "Ref": "VpcCIDR" },
"VPC": { "Ref": "VPC" }
},
"TimeoutInMinutes": "15"
}
},
"NatGatewayEipAZ1": {
"DependsOn": [ "IgwAttachment" ],
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc"
}
},
"NatGatewayEipAZ2": {
"DependsOn": [ "IgwAttachment" ],
"Type": "AWS::EC2::EIP",
"Properties": {
"Domain": "vpc"
}
},
"NatGatewayAZ1": {
"DependsOn": [ "NatGatewayEipAZ1", "PubSubnetAZ1", "IgwAttachment" ],
"Type": "AWS::EC2::NatGateway",
"Properties": {
"AllocationId": {
"Fn::GetAtt": [ "NatGatewayEipAZ1", "AllocationId" ]
},
"SubnetId": {
"Ref": "PubSubnetAZ1"
}
}
},
"NatGatewayAZ2": {
"DependsOn": [ "NatGatewayEipAZ2", "PubSubnetAZ2", "IgwAttachment" ],
"Type": "AWS::EC2::NatGateway",
"Properties": {
"AllocationId": {
"Fn::GetAtt": [ "NatGatewayEipAZ2", "AllocationId" ]
},
"SubnetId": {
"Ref": "PubSubnetAZ2"
}
}
},
"RdsPrivateSubnetGroup": {
"DependsOn": [ "PrivSubnetAZ1", "PrivSubnetAZ2" ],
"Type": "AWS::RDS::DBSubnetGroup",
"Properties": {
"DBSubnetGroupDescription": "Allows RDS communication between private subnets",
"SubnetIds": [
{
"Ref": "PrivSubnetAZ1"
},
{
"Ref": "PrivSubnetAZ2"
}
],
"Tags": [
{
"Key": "Name",
"Value": {
"Fn::Join": [
"",
[
"dbsubnetgroup_",
{
"Ref": "Environment"
},
"_private"
]
]
}
},
{
"Key": "Network",
"Value": "private"
},
{
"Key": "Environment",
"Value": {
"Ref": "Environment"
}
}
]
}
}
},
"Outputs": {
"VPC": {
"Description": "VPC ID of the new VPC",
"Value": {
"Ref": "VPC"
}
},
"InetGw": {
"Description": "IGW ID for VPC",
"Value": {
"Ref": "InetGw"
}
},
"PrivateSubnetAZ1": {
"Description": "Private subnet ID in AZ1",
"Value": {
"Ref": "PrivSubnetAZ1"
}
},
"PrivateSubnetAZ2": {
"Description": "Private subnet ID in AZ2",
"Value": {
"Ref": "PrivSubnetAZ2"
}
},
"PublicSubnetAZ1": {
"Description": "Public subnet ID in AZ1",
"Value": {
"Ref": "PubSubnetAZ1"
}
},
"PublicSubnetAZ2": {
"Description": "Public subnet ID in AZ2",
"Value": {
"Ref": "PubSubnetAZ2"
}
},
"RdsPrivateSubnetGroup": {
"Description": "Private access to DB subnets",
"Value": "RdsPrivateSubnetGroup"
},
"NatGatewayAZ1": {
"Description": "NAT gateway in AZ1",
"Value": {
"Ref": "NatGatewayAZ1"
}
},
"NatGatewayEipAZ1": {
"Description": "EIP of NAT gateway in AZ1",
"Value": {
"Ref": "NatGatewayEipAZ1"
}
},
"NatGatewayAZ2": {
"Description": "NAT gateway in AZ2",
"Value": {
"Ref": "NatGatewayAZ2"
}
},
"NatGatewayEipAZ2": {
"Description": "EIP of NAT gateway in AZ2",
"Value": {
"Ref": "NatGatewayEipAZ2"
}
}
}
}