Skip to content

Instantly share code, notes, and snippets.

@andrew-templeton
Created April 1, 2016 02:20
Show Gist options
  • Save andrew-templeton/a6711a1fe982fceadee1558b65714cf2 to your computer and use it in GitHub Desktop.
Save andrew-templeton/a6711a1fe982fceadee1558b65714cf2 to your computer and use it in GitHub Desktop.
CloudFormation template packaging a serverless VPC for fixed/static IPs on Lambdas
{
"Description": "Host VPC for Lambda Static IPs",
"Parameters": {
"VPCClassBOctet": {
"Type": "Number",
"Description": "The Class B block to use for the VPC (0-255).",
"MaxValue": 255,
"MinValue": 0,
"Default": 0
},
"EIPAllocationIdAlpha": {
"Type": "String",
"Description": "The EIP AllocationId for a static address to bind some of the Lambdas to.",
"AllowedPattern": "^eipalloc-[a-f0-9]{8}$",
"ConstraintDescription": "IDs must be valid AllocationId"
},
"EIPAllocationIdBeta": {
"Type": "String",
"Description": "The EIP AllocationId for a static address to bind some of the Lambdas to.",
"AllowedPattern": "^(eipalloc-[a-f0-9]{8})|()$",
"ConstraintDescription": "IDs must be valid AllocationId",
"Default": ""
}
},
"Conditions": {
"ShouldPartitionTraffic": {
"Fn::Not": [
{
"Fn::Equals": [
{
"Ref": "EIPAllocationIdBeta"
},
""
]
}
]
},
"ShouldNotPartitionTraffic": {
"Fn::Equals": [
{
"Ref": "EIPAllocationIdBeta"
},
""
]
}
},
"Resources": {
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": { "Fn::Join": [ "", [
"10.",
{ "Ref": "VPCClassBOctet" },
".0.0/16"
]]}
}
},
"PublicSubnetAlpha": {
"DependsOn": [
"VPC"
],
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": {
"Fn::Select": [
0,
{
"Fn::GetAZs": {
"Ref": "AWS::Region"
}
}
]
},
"CidrBlock": { "Fn::Join": [ "", [
"10.",
{ "Ref": "VPCClassBOctet" },
".0.0/18"
]]},
"MapPublicIpOnLaunch" : true,
"VpcId": { "Ref": "VPC" }
}
},
"PublicSubnetBeta": {
"DependsOn": [
"VPC"
],
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": {
"Fn::Select": [
1,
{
"Fn::GetAZs": {
"Ref": "AWS::Region"
}
}
]
},
"CidrBlock": { "Fn::Join": [ "", [
"10.",
{ "Ref": "VPCClassBOctet" },
".64.0/18"
]]},
"MapPublicIpOnLaunch" : true,
"VpcId": { "Ref": "VPC" }
}
},
"PrivateSubnetAlpha": {
"DependsOn": [
"VPC"
],
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": {
"Fn::Select": [
0,
{
"Fn::GetAZs": {
"Ref": "AWS::Region"
}
}
]
},
"CidrBlock": { "Fn::Join": [ "", [
"10.",
{ "Ref": "VPCClassBOctet" },
".128.0/18"
]]},
"VpcId": { "Ref": "VPC" }
}
},
"PrivateSubnetBeta": {
"DependsOn": [
"VPC"
],
"Type": "AWS::EC2::Subnet",
"Properties": {
"AvailabilityZone": {
"Fn::Select": [
0,
{
"Fn::GetAZs": {
"Ref": "AWS::Region"
}
}
]
},
"CidrBlock": { "Fn::Join": [ "", [
"10.",
{ "Ref": "VPCClassBOctet" },
".192.0/18"
]]},
"VpcId": { "Ref": "VPC" }
}
},
"GatewayToInternet": {
"Type": "AWS::EC2::InternetGateway"
},
"NATGatewayAlpha": {
"DependsOn": [
"GatewayAttachmentToVPC",
"PublicSubnetAlpha",
"VPC"
],
"Type": "AWS::EC2::NatGateway",
"Properties": {
"AllocationId": {
"Ref": "EIPAllocationIdAlpha"
},
"SubnetId": {
"Ref": "PublicSubnetAlpha"
}
}
},
"NATGatewayBeta": {
"Condition": "ShouldPartitionTraffic",
"DependsOn": [
"GatewayAttachmentToVPC",
"PublicSubnetAlpha",
"VPC"
],
"Type": "AWS::EC2::NatGateway",
"Properties": {
"AllocationId": {
"Ref": "EIPAllocationIdBeta"
},
"SubnetId": {
"Ref": "PublicSubnetBeta"
}
}
},
"RoutesForPublicSubnets": {
"DependsOn": [
"VPC"
],
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": { "Ref": "VPC" }
}
},
"RoutesForPrivateSubnetAlpha": {
"DependsOn": [
"VPC"
],
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": { "Ref": "VPC" }
}
},
"RoutesForPrivateSubnetBeta": {
"DependsOn": [
"VPC"
],
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": { "Ref": "VPC" }
}
},
"GenericNACL": {
"DependsOn": [
"VPC"
],
"Type": "AWS::EC2::NetworkAcl",
"Properties": {
"VpcId": { "Ref": "VPC" }
}
},
"LambdaPoolSecurityGroup": {
"DependsOn": [
"VPC"
],
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"GroupDescription": "Security group allowing only outbound traffic",
"SecurityGroupEgress": [
{
"CidrIp" : "0.0.0.0/0",
"FromPort" : "-1",
"IpProtocol" : "-1",
"ToPort" : "-1"
}
],
"VpcId": {
"Ref": "VPC"
}
}
},
"GatewayAttachmentToVPC": {
"DependsOn": [
"GatewayToInternet",
"VPC"
],
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"InternetGatewayId": { "Ref": "GatewayToInternet" },
"VpcId": { "Ref": "VPC" }
}
},
"RouteToGateway": {
"DependsOn": [
"GatewayToInternet",
"GatewayAttachmentToVPC",
"RoutesForPublicSubnets"
],
"Type": "AWS::EC2::Route",
"Properties": {
"DestinationCidrBlock": "0.0.0.0/0",
"GatewayId": { "Ref": "GatewayToInternet" },
"RouteTableId": { "Ref": "RoutesForPublicSubnets" }
}
},
"RouteToNatForAlpha": {
"DependsOn": [
"NATGatewayAlpha",
"RoutesForPrivateSubnetAlpha"
],
"Type": "AWS::EC2::Route",
"Properties": {
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": { "Ref": "NATGatewayAlpha" },
"RouteTableId": { "Ref": "RoutesForPrivateSubnetAlpha" }
}
},
"RouteToNatForBetaUsingPartition": {
"Condition": "ShouldPartitionTraffic",
"DependsOn": [
"NATGatewayBeta",
"RoutesForPrivateSubnetBeta"
],
"Type": "AWS::EC2::Route",
"Properties": {
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": { "Ref": "NATGatewayBeta" },
"RouteTableId": { "Ref": "RoutesForPrivateSubnetBeta" }
}
},
"RouteToNatForBetaWithoutPartition": {
"Condition": "ShouldNotPartitionTraffic",
"DependsOn": [
"NATGatewayAlpha",
"RoutesForPrivateSubnetBeta"
],
"Type": "AWS::EC2::Route",
"Properties": {
"DestinationCidrBlock": "0.0.0.0/0",
"NatGatewayId": { "Ref": "NATGatewayAlpha" },
"RouteTableId": { "Ref": "RoutesForPrivateSubnetBeta" }
}
},
"NACLInboundEntry": {
"DependsOn": [
"GenericNACL"
],
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"CidrBlock": "0.0.0.0/0",
"Egress": false,
"NetworkAclId": { "Ref": "GenericNACL" },
"PortRange": {
"From": "0",
"To": "65535"
},
"Protocol": "6",
"RuleAction": "allow",
"RuleNumber": 100
}
},
"NACLOutboundEntry": {
"DependsOn": [
"GenericNACL"
],
"Type": "AWS::EC2::NetworkAclEntry",
"Properties": {
"CidrBlock": "0.0.0.0/0",
"Egress": true,
"NetworkAclId": { "Ref": "GenericNACL" },
"PortRange": {
"From": "0",
"To": "65535"
},
"Protocol": "6",
"RuleAction": "allow",
"RuleNumber": 100
}
},
"NACLBindingForPublicSubnet": {
"DependsOn": [
"PublicSubnetAlpha",
"GenericNACL"
],
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": { "Ref": "PublicSubnetAlpha" },
"NetworkAclId": { "Ref": "GenericNACL" }
}
},
"NACLBindingForPrivateSubnet": {
"DependsOn": [
"PrivateSubnetAlpha",
"GenericNACL"
],
"Type": "AWS::EC2::SubnetNetworkAclAssociation",
"Properties": {
"SubnetId": { "Ref": "PrivateSubnetAlpha" },
"NetworkAclId": { "Ref": "GenericNACL" }
}
},
"RoutesBindingForPublicSubnetAlpha": {
"DependsOn": [
"RoutesForPublicSubnets",
"PublicSubnetAlpha"
],
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": { "Ref": "RoutesForPublicSubnets" },
"SubnetId": { "Ref": "PublicSubnetAlpha" }
}
},
"RoutesBindingForPublicSubnetBeta": {
"DependsOn": [
"RoutesForPublicSubnets",
"PublicSubnetBeta"
],
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": { "Ref": "RoutesForPublicSubnets" },
"SubnetId": { "Ref": "PublicSubnetBeta" }
}
},
"RoutesBindingForPrivateSubnetAlpha": {
"DependsOn": [
"RoutesForPrivateSubnetAlpha",
"PrivateSubnetAlpha"
],
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": { "Ref": "RoutesForPrivateSubnetAlpha" },
"SubnetId": { "Ref": "PrivateSubnetAlpha" }
}
},
"RoutesBindingForPrivateSubnetBeta": {
"DependsOn": [
"RoutesForPrivateSubnetBeta",
"PrivateSubnetBeta"
],
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"RouteTableId": { "Ref": "RoutesForPrivateSubnetBeta" },
"SubnetId": { "Ref": "PrivateSubnetBeta" }
}
}
},
"Outputs": {
"SubnetAlpha": {
"Description": "The first subnet that the Lambdas will execute from.",
"Value": {
"Ref": "PrivateSubnetAlpha"
}
},
"SubnetBeta": {
"Description": "The second subnet that the Lambdas will execute from.",
"Value": {
"Ref": "PrivateSubnetBeta"
}
},
"LambdaPoolSecurityGroup": {
"Description": "The Security Group to assign to any Lambdas executing in the private subnet pool.",
"Value": {
"Ref": "LambdaPoolSecurityGroup"
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment