Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@cb372
Last active June 10, 2020 15:04
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save cb372/fc36a0d1db54f495988a507d5ec8a51c to your computer and use it in GitHub Desktop.
Save cb372/fc36a0d1db54f495988a507d5ec8a51c to your computer and use it in GitHub Desktop.
CloudFormation for setting up a VPC
AWSTemplateFormatVersion: 2010-09-09
Description: >
Creates a cross-account role that your AWS account can assume
in order to accept a VPC peering connection in the other account.
This is pretty confusing, so to clarify,
1. Run this CloudFormation in the OTHER account to create the cross-account role.
2. Your account requests a peering connection with the other account.
3. Your account assumes the role in order to access the other account
and accept the peering connection.
Parameters:
PeerRequesterAccountId:
Type: String
Resources:
AcceptVpcPeeringRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Principal:
AWS: !Ref PeerRequesterAccountId
Action:
- 'sts:AssumeRole'
Effect: Allow
Path: /
Policies:
- PolicyName: root
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: 'ec2:AcceptVpcPeeringConnection'
Resource: '*'
---
AWSTemplateFormatVersion: 2010-09-09
Description: |
VPC with 3 public and 3 private subnets,
and a VPN connection to a corporate network,
and a peering to a VPC in another account.
Parameters:
PeeredVpcId:
Type: String
Description: The VPC ID of the VPC in another AWS account that you want to peer with
PeeredVpcAccountId:
Type: String
Description: The AWS account ID of the account containing the VPC you want to peer with
PeeredVpcCrossAccountRoleName:
Type: String
Description: The name of the cross-account role in the other AWS account that CloudFormation will assume in order to accept the peering connection
Mappings:
CidrBlocks:
MyAccount:
# TODO: Tweak these IP ranges as necessary
VPC: 10.128.0.0/19
PublicSubnet1: 10.128.0.0/22
PublicSubnet2: 10.128.4.0/22
PublicSubnet3: 10.128.8.0/22
PrivateSubnet1: 10.128.12.0/22
PrivateSubnet2: 10.128.16.0/22
PrivateSubnet3: 10.131.20.0/22
CorporateNetwork: 10.0.0.0/9
IPAddresses:
CorporateNetwork:
# TODO: your networks team will be able to tell you this
CustomerGateway: 1.2.3.4
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
EnableDnsSupport: true
EnableDnsHostnames: true
CidrBlock: !FindInMap [ CidrBlocks, MyAccount, VPC ]
Tags:
- Key: Name
Value: My VPC
InternetGateway:
Type: AWS::EC2::InternetGateway
AttachInternetGatewayToVPC:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref InternetGateway
#
# Public subnets
#
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !FindInMap [ CidrBlocks, MyAccount, PublicSubnet1 ]
MapPublicIpOnLaunch: true
AvailabilityZone: !Sub "${AWS::Region}a"
Tags:
- Key: Name
Value: Public1
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !FindInMap [ CidrBlocks, MyAccount, PublicSubnet2 ]
MapPublicIpOnLaunch: true
AvailabilityZone: !Sub "${AWS::Region}b"
Tags:
- Key: Name
Value: Public2
PublicSubnet3:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !FindInMap [ CidrBlocks, MyAccount, PublicSubnet3 ]
MapPublicIpOnLaunch: true
AvailabilityZone: !Sub "${AWS::Region}c"
Tags:
- Key: Name
Value: Public3
#
# Routing for public subnets
#
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: PublicRouteTable
PublicInternetRoute:
Type: AWS::EC2::Route
DependsOn: AttachInternetGatewayToVPC
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet1
RouteTableId: !Ref PublicRouteTable
PublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet2
RouteTableId: !Ref PublicRouteTable
PublicSubnet3RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet3
RouteTableId: !Ref PublicRouteTable
#
# Network ACL for public subnets
#
PublicNetworkAcl:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: PublicNetworkAcl
# Allow requests from the outside world to HTTPS services inside the VPC
InboundHTTPSPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: 100
Protocol: 6
RuleAction: allow
Egress: false
CidrBlock: 0.0.0.0/0
PortRange:
From: 443
To: 443
# Allow TCP responses from the outside world on ephemeral ports
InboundEphemeralTcpPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: 101
Protocol: 6
RuleAction: allow
Egress: false
CidrBlock: 0.0.0.0/0
PortRange:
From: 1024
To: 65535
# Allow services inside the VPC to make TCP requests to the outside world
# and make TCP responses on ephemeral ports
OutboundTcpPublicNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PublicNetworkAcl
RuleNumber: 100
Protocol: 6
RuleAction: allow
Egress: true
CidrBlock: 0.0.0.0/0
PortRange:
From: 0
To: 65535
PublicSubnet1NetworkAclAssociation:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PublicSubnet1
NetworkAclId: !Ref PublicNetworkAcl
PublicSubnet2NetworkAclAssociation:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PublicSubnet2
NetworkAclId: !Ref PublicNetworkAcl
PublicSubnet3NetworkAclAssociation:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PublicSubnet3
NetworkAclId: !Ref PublicNetworkAcl
#
# NAT gateway
#
NatGatewayElasticIP:
Type: AWS::EC2::EIP
DependsOn: AttachInternetGatewayToVPC
Properties:
Domain: vpc
# We have to put the NAT gateway in one of the AZs.
# We arbitrarily choose 'b'.
NatGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt NatGatewayElasticIP.AllocationId
SubnetId: !Ref PublicSubnet2
Tags:
- Key: Name
Value: NatGateway
#
# Private subnets
#
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !FindInMap [ CidrBlocks, MyAccount, PrivateSubnet1 ]
AvailabilityZone: !Sub "${AWS::Region}a"
Tags:
- Key: Name
Value: Private1
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !FindInMap [ CidrBlocks, MyAccount, PrivateSubnet2 ]
AvailabilityZone: !Sub "${AWS::Region}b"
Tags:
- Key: Name
Value: Private2
PrivateSubnet3:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: !FindInMap [ CidrBlocks, MyAccount, PrivateSubnet3 ]
AvailabilityZone: !Sub "${AWS::Region}c"
Tags:
- Key: Name
Value: Private3
#
# Routing for private subnets
#
PrivateRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: PrivateRouteTable
PrivateInternetRoute:
Type: AWS::EC2::Route
DependsOn: NatGateway
Properties:
RouteTableId: !Ref PrivateRouteTable
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NatGateway
PrivateSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
RouteTableId: !Ref PrivateRouteTable
PrivateSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet2
RouteTableId: !Ref PrivateRouteTable
PrivateSubnet3RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet3
RouteTableId: !Ref PrivateRouteTable
#
# Network ACL for private subnets
#
PrivateNetworkAcl:
Type: AWS::EC2::NetworkAcl
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: PrivateNetworkAcl
# Allow incoming traffic from anywhere in the VPC
InboundAllLocalTrafficPrivateNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PrivateNetworkAcl
RuleNumber: 100
Protocol: -1
RuleAction: allow
Egress: false
CidrBlock: !FindInMap [ CidrBlocks, MyAccount, VPC ]
# Allow incoming TCP responses from anywhere
InboundEphemeralTcpPrivateNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PrivateNetworkAcl
RuleNumber: 101
Protocol: 6
RuleAction: allow
Egress: false
CidrBlock: 0.0.0.0/0
PortRange:
From: 1024
To: 65535
# Allow incoming SSH requests from corporate network
InboundEphemeralTcpPrivateNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PrivateNetworkAcl
RuleNumber: 102
Protocol: 6
RuleAction: allow
Egress: false
CidrBlock: !FindInMap [ CidrBlocks, MyAccount, CorporateNetwork ]
PortRange:
From: 22
To: 22
# Allow outgoing TCP requests to anywhere
OutboundTcpPrivateNetworkAclEntry:
Type: AWS::EC2::NetworkAclEntry
Properties:
NetworkAclId: !Ref PrivateNetworkAcl
RuleNumber: 100
Protocol: 6
RuleAction: allow
Egress: true
CidrBlock: 0.0.0.0/0
PortRange:
From: 0
To: 65535
PrivateSubnet1NetworkAclAssociation:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
NetworkAclId: !Ref PrivateNetworkAcl
PrivateSubnet2NetworkAclAssociation:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PrivateSubnet2
NetworkAclId: !Ref PrivateNetworkAcl
PrivateSubnet3NetworkAclAssociation:
Type: AWS::EC2::SubnetNetworkAclAssociation
Properties:
SubnetId: !Ref PrivateSubnet3
NetworkAclId: !Ref PrivateNetworkAcl
# The customer gateway is the endpoint on the corporate-network side of the VPN tunnel
CustomerGateway:
Type: AWS::EC2::CustomerGateway
Properties:
Type: ipsec.1
BgpAsn: 65000
IpAddress: !FindInMap [ IPAddresses, CorporateNetwork, CustomerGateway ]
Tags:
- Key: Name
Value: corporate network
# The virtual private gateway is the endpoint on the AWS side
VirtualPrivateGateway:
Type: AWS::EC2::VPNGateway
Properties:
Type: ipsec.1
Tags:
- Key: Name
Value: corporate network
AttachVPNGatewayToVPC:
Type: AWS::EC2::VPCGatewayAttachment
DependsOn: VirtualPrivateGateway
Properties:
VpcId: !Ref VPC
VpnGatewayId: !Ref VirtualPrivateGateway
VPNGatewayRoutePropagation:
Type: AWS::EC2::VPNGatewayRoutePropagation
DependsOn: AttachVPNGatewayToVPC
Properties:
RouteTableIds:
- !Ref PrivateRouteTable
VpnGatewayId: !Ref VirtualPrivateGateway
VPNConnection:
Type: AWS::EC2::VPNConnection
Properties:
Type: ipsec.1
CustomerGatewayId: !Ref CustomerGateway
VpnGatewayId: !Ref VirtualPrivateGateway
StaticRoutesOnly: true
Tags:
- Key: Name
Value: corporate network
VPNConnectionRoute:
Type: AWS::EC2::VPNConnectionRoute
Properties:
DestinationCidrBlock: !FindInMap [ CidrBlocks, MyAccount, CorporateNetwork ]
VpnConnectionId: !Ref VPNConnection
# Peer with a VPC in another AWS account
PeeringConnection:
Type: AWS::EC2::VPCPeeringConnection
Properties:
VpcId: !Ref VPC
PeerVpcId: !Ref PeeredVpcId
PeerOwnerId: !Ref PeeredVpcAccountId
PeerRoleArn: !Sub "arn:aws:iam::${PeeredVpcAccountId}:role/${PeeredVpcCrossAccountRoleName}"
Tags:
- Key: Name
Value: VPC in another AWS account
Outputs:
VPCCidrBlock:
Value: !GetAtt VPC.CidrBlock
Export:
Name: VPC-CIDR
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment