├── .gitignore ├── LICENSE ├── README.md ├── m3 └── m3.sh ├── m4 └── m4.sh ├── m5 ├── flow-log-policy.txt ├── flow-log-role.txt ├── m5.sh └── webserver.txt ├── m6 ├── m6.sh ├── three-vpcs.template └── vpn-vpc.template └── setup ├── basic-network.template └── stack-setup.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.pem -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Ned Bellavance 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Advanced Networking on AWS 2 | 3 | Welcome to Advanced Networking on AWS. These exercise files are meant to accompany my course on Pluralsight. 4 | 5 | ## Using the files 6 | 7 | Each folder follows the progression of modules through the course. The setup folder contains a CloudFormation template, which will deploy a simple VPC. It assumes that the region you choose has at least three Availability Zones. I used `us-east-1` for all of my examples, but choose the region that works best for you. 8 | 9 | The rest of the modules (except module 6) build off the initial VPC, creating additional subnets, CIDR ranges, routes, and security groups. In the script for module 4, there is a process that spins up three Server 2016 boxes. Two are meant to function as domain controllers, and the third is a jump box in a public subnet. The actual configuration of the domain controllers is left as an exercise to you. There's nothing special about the domain, you can simply choose a name and configure custom DNS in the DHCP options set. 10 | 11 | Module 6 has two CloudFormation templates that are used to demonstrate VPC peering and site-to-site VPNs. They are meant to be used separately from the simple VPC you deployed earlier. You may hit the limit of 5 VPCs per region if you have everything deployed at the same time. You can simply log a support request for the limit to be bumped up to 10, and AWS should resolve it quickly. 12 | 13 | ## Course prerequisites 14 | 15 | There are a few pieces of prerequisite software you should have available 16 | 17 | * **Code Editor** - Have a code editor of some kind. My preference is VS Code, but you do you. 18 | * **AWS CLI** - The exercise files all assume you have the AWS CLI installed. You won't get very far without it. 19 | * **jq** - In most cases I tried to use the built-in `query` function of the AWS CLI, but sometimes it just didn't work out. 20 | 21 | You might be able to run these exercises in a PowerShell terminal, but it won't be easy. I recommend installing Windows Subsystem for Linux if you are on a Windows box. Linux and Mac users should have no problems. 22 | 23 | ## MONEY!!! 24 | 25 | A gentle reminder about cost. The course will have you creating resources in AWS. Some of the resources are not going to be 100% free. I have tried to use free resources when possible, but EC2 instances, elastic IPs, and NAT gateways all cost money. We're probably talking a few dollars for the duration of the exercises, but it won't be zero. 26 | 27 | ## Conclusion 28 | 29 | I hope you enjoy taking this course as much as I did creating it. I'd love to hear feedback and suggestions for revisions. Log an issue on this repo or hit me up on Twitter. 30 | 31 | Thanks and happy automating! 32 | 33 | Ned -------------------------------------------------------------------------------- /m3/m3.sh: -------------------------------------------------------------------------------- 1 | # You should have already deployed the basic VPC from the setup folder 2 | # and configured your AWS CLI 3 | 4 | # Let's first get the VPC ID 5 | 6 | vpc_id=$(aws ec2 describe-vpcs --filters Name="tag:Name",Values="globo-primary" \ 7 | --query 'Vpcs[0].VpcId' --output text) 8 | 9 | # Now we're going to add another CIDR block to the VPC 10 | 11 | aws ec2 associate-vpc-cidr-block --cidr-block "10.1.0.0/24" --vpc-id $vpc_id 12 | 13 | # Now we'll create subnet-6 using the new CIDR block 14 | 15 | # Get the AZ of subnet-3 16 | 17 | az=$(aws ec2 describe-subnets --filter Name="tag:Name",Values="subnet-3" \ 18 | --query 'Subnets[0].AvailabilityZoneId' --output text) 19 | 20 | # Create subnet-6 in same AZ and add the tags 21 | 22 | subnet_6=$(aws ec2 create-subnet --availability-zone-id $az \ 23 | --cidr-block "10.1.0.0/24" --vpc-id $vpc_id) 24 | 25 | subnet_6_id=$(echo $subnet_6 | jq .Subnet.SubnetId -r) 26 | 27 | aws ec2 create-tags --resources $subnet_6_id \ 28 | --tags Key=Name,Value=subnet-6 Key=Company,Value=Globomantics Key=Network,Value=Private 29 | 30 | # Add IPv6 to the VPC 31 | 32 | aws ec2 associate-vpc-cidr-block --vpc-id $vpc_id --amazon-provided-ipv6-cidr-block 33 | 34 | # Get the AWS assigned IPv6 block 35 | 36 | ipv6_range=$(aws ec2 describe-vpcs --vpc-ids $vpc_id \ 37 | --query 'Vpcs[0].Ipv6CidrBlockAssociationSet[0].Ipv6CidrBlock' --output text) 38 | 39 | # Create a /64 from the block 40 | 41 | subnet_ipv6_range=$(sed 's|/56|/64|g' <<< $ipv6_range) 42 | 43 | # Associate new block with subnet-6 44 | 45 | aws ec2 associate-subnet-cidr-block --ipv6-cidr-block $subnet_ipv6_range \ 46 | --subnet-id $subnet_6_id 47 | 48 | # Get subnets for new instance 49 | subnet_1_id=$(aws ec2 describe-subnets --filter Name="tag:Name",Values="subnet-1" \ 50 | --query 'Subnets[0].SubnetId' --output text) 51 | 52 | subnet_4_id=$(aws ec2 describe-subnets --filter Name="tag:Name",Values="subnet-4" \ 53 | --query 'Subnets[0].SubnetId' --output text) 54 | 55 | # Create a key-pair for your instances 56 | 57 | aws ec2 create-key-pair --key-name AdvNet --query 'KeyMaterial' --output text > AdvNet.pem 58 | 59 | # Create a security group for your instances 60 | 61 | aws ec2 create-security-group --description "default-sg-for-AdvNet" \ 62 | --group-name "AdvNet" --vpc-id $vpc_id 63 | 64 | sg_id=$(aws ec2 describe-security-groups --filter Name="group-name",Values="AdvNet" \ 65 | --query 'SecurityGroups[0].GroupId' --output text) 66 | 67 | # Get the latest Amazon Linux 2 AMI 68 | # **NOTE** change the region to the one you are using 69 | 70 | ami_id=$(aws ssm get-parameters --names /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 \ 71 | --region us-east-1 | jq .Parameters[].Value -r) 72 | 73 | # Spin up the web-1 instance 74 | 75 | aws ec2 run-instances --image-id $ami_id --count 1 \ 76 | --instance-type t2.micro --key-name AdvNet \ 77 | --security-group-ids $sg_id --subnet-id $subnet_1_id \ 78 | --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=web-1},{Key=Company,Value=Globomantics}]' \ 79 | 'ResourceType=volume,Tags=[{Key=Name,Value=web-1},{Key=Company,Value=Globomantics}]' 80 | 81 | # Get the instance id and the eni id 82 | 83 | web_1_json=$(aws ec2 describe-instances \ 84 | --filter Name="tag:Name",Values="web-1" Name="vpc-id",Values=$vpc_id) 85 | 86 | web_1_id=$(echo $web_1_json | jq .Reservations[0].Instances[0].InstanceId -r) 87 | 88 | web_1_eni_1=$(echo $web_1_json | jq .Reservations[0].Instances[0].NetworkInterfaces[0].NetworkInterfaceId -r) 89 | 90 | # Add another private IP address to web-1 on the primary ENI 91 | 92 | aws ec2 assign-private-ip-addresses --network-interface-id $web_1_eni_1 \ 93 | --private-ip-addresses 10.0.1.10 94 | 95 | # Create a new ENI in subnet-4 96 | 97 | eni_2=$(aws ec2 create-network-interface --description "web ENI" --subnet-id $subnet_4_id) 98 | 99 | eni_2_id=$(echo $eni_2 | jq .NetworkInterface.NetworkInterfaceId -r) 100 | 101 | # Attach new ENI to web-1 102 | 103 | $attach_id=$(aws ec2 attach-network-interface --device-index 1 --instance-id $web_1_id \ 104 | --network-interface-id $eni_2_id) 105 | 106 | # Create web-2 instance 107 | 108 | aws ec2 run-instances --image-id $ami_id --count 1 \ 109 | --instance-type t2.micro --key-name AdvNet \ 110 | --security-group-ids $sg_id --subnet-id $subnet_1_id \ 111 | --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=web-2},{Key=Company,Value=Globomantics}]' \ 112 | 'ResourceType=volume,Tags=[{Key=Name,Value=web-2},{Key=Company,Value=Globomantics}]' 113 | 114 | # Get the instance id and the eni id 115 | 116 | web_2_json=$(aws ec2 describe-instances \ 117 | --filter Name="tag:Name",Values="web-2" Name="vpc-id",Values=$vpc_id) 118 | 119 | web_2_id=$(echo $web_2_json | jq .Reservations[0].Instances[0].InstanceId -r) 120 | 121 | # Detach the ENI from web-1 122 | 123 | aws ec2 detach-network-interface --attachment-id $(echo $attach_id | jq .AttachmentId -r) 124 | 125 | # Attach the ENI to web-2 126 | 127 | aws ec2 attach-network-interface --device-index 1 --instance-id $web_2_id \ 128 | --network-interface-id $eni_2_id -------------------------------------------------------------------------------- /m4/m4.sh: -------------------------------------------------------------------------------- 1 | # Let's first get the VPC ID 2 | 3 | vpc_id=$(aws ec2 describe-vpcs --filters Name="tag:Name",Values="globo-primary" \ 4 | --query 'Vpcs[0].VpcId' --output text) 5 | 6 | # Get the main route table for the VPC 7 | 8 | aws ec2 describe-route-tables --filters Name="vpc-id",Values=$vpc_id Name="association.main",Values="true" \ 9 | --query 'RouteTables[0].Routes' 10 | 11 | # Get the custom route table 12 | 13 | aws ec2 describe-route-tables --filters Name="vpc-id",Values=$vpc_id Name="association.main",Values="false" \ 14 | --query 'RouteTables[0].Routes' 15 | 16 | # Get subnets associated with custom route table 17 | 18 | subnets=$(aws ec2 describe-route-tables --filters Name="vpc-id",Values=$vpc_id Name="association.main",Values="false" \ 19 | --query 'RouteTables[0].Associations[].SubnetId' --output text) 20 | 21 | aws ec2 describe-subnets --subnet-ids $subnets --query 'Subnets[].Tags[?Key==`Name`].Value[]' 22 | 23 | # Let's create NAT gateways for the private subnets 24 | 25 | # Allocate an EIP 26 | 27 | eip=$(aws ec2 allocate-address --domain vpc) 28 | 29 | eip_alloc=$(echo $eip | jq .AllocationId -r) 30 | 31 | # Get the subnet ID for the subnet-1 32 | 33 | subnet_1_id=$(aws ec2 describe-subnets --filter Name="tag:Name",Values="subnet-1" \ 34 | --query 'Subnets[0].SubnetId' --output text) 35 | 36 | # Create a NAT gateway in subnet-1 37 | 38 | nat_gw=$(aws ec2 create-nat-gateway --allocation-id $eip_alloc --subnet-id $subnet_1_id) 39 | 40 | nat_gw_id=$(echo $nat_gw | jq .NatGateway.NatGatewayId -r) 41 | 42 | # Create a route table for subnet-4 43 | 44 | rt1=$(aws ec2 create-route-table --vpc-id $vpc_id) 45 | 46 | rt1_id=$(echo $rt1 | jq .RouteTable.RouteTableId -r) 47 | 48 | # Add entries to the route table 49 | 50 | aws ec2 create-route --destination-cidr-block "0.0.0.0/0" --nat-gateway-id $nat_gw_id --route-table-id $rt1_id 51 | 52 | # Get the subnet ID for the subnet-4 53 | 54 | subnet_4_id=$(aws ec2 describe-subnets --filter Name="tag:Name",Values="subnet-4" \ 55 | --query 'Subnets[0].SubnetId' --output text) 56 | 57 | # Associate route table with each subnet-4 58 | 59 | aws ec2 associate-route-table --route-table-id $rt1_id --subnet-id $subnet_4_id 60 | 61 | # Rinse and repeat for each AZ 62 | 63 | # Allocate an EIP 64 | 65 | eip2=$(aws ec2 allocate-address --domain vpc) 66 | 67 | eip_alloc_2=$(echo $eip2 | jq .AllocationId -r) 68 | 69 | # Get the subnet ID for the subnet-2 70 | 71 | subnet_2_id=$(aws ec2 describe-subnets --filter Name="tag:Name",Values="subnet-2" \ 72 | --query 'Subnets[0].SubnetId' --output text) 73 | 74 | # Create a NAT gateway in subnet-2 75 | 76 | nat_gw_2=$(aws ec2 create-nat-gateway --allocation-id $eip_alloc_2 --subnet-id $subnet_2_id) 77 | 78 | nat_gw_id_2=$(echo $nat_gw_2 | jq .NatGateway.NatGatewayId -r) 79 | 80 | # Create a route table for subnet-5 81 | 82 | rt2=$(aws ec2 create-route-table --vpc-id $vpc_id) 83 | 84 | rt2_id=$(echo $rt2 | jq .RouteTable.RouteTableId -r) 85 | 86 | # Add entries to the route table 87 | 88 | aws ec2 create-route --destination-cidr-block "0.0.0.0/0" --nat-gateway-id $nat_gw_id_2 --route-table-id $rt2_id 89 | 90 | # Get the subnet ID for the subnet-5 91 | 92 | subnet_5_id=$(aws ec2 describe-subnets --filter Name="tag:Name",Values="subnet-5" \ 93 | --query 'Subnets[0].SubnetId' --output text) 94 | 95 | # Associate route table with each subnet-5 96 | 97 | aws ec2 associate-route-table --route-table-id $rt2_id --subnet-id $subnet_5_id 98 | 99 | # Get Windows AMI for Server 2016 100 | 101 | ami_id=$(aws ssm get-parameters --names /aws/service/ami-windows-latest/Windows_Server-2016-English-Full-Base \ 102 | | jq .Parameters[].Value -r) 103 | 104 | # Create a key-pair for your instances 105 | 106 | aws ec2 create-key-pair --key-name GloboKey --query 'KeyMaterial' --output text > GloboKey.pem 107 | 108 | # Create a security group for your jump box 109 | 110 | aws ec2 create-security-group --description "allow-rdp-remote" \ 111 | --group-name "RDPRemote" --vpc-id $vpc_id 112 | 113 | sg_id=$(aws ec2 describe-security-groups --filter Name="group-name",Values="RDPRemote" \ 114 | --query 'SecurityGroups[0].GroupId' --output text) 115 | 116 | my_ip=$(curl ifconfig.me) 117 | 118 | # Add allow RDP from your IP address 119 | 120 | aws ec2 authorize-security-group-ingress \ 121 | --group-id $sg_id \ 122 | --protocol tcp \ 123 | --port 3389 \ 124 | --cidr $my_ip/32 125 | 126 | # Create the jump box 127 | 128 | aws ec2 run-instances --image-id $ami_id --count 1 \ 129 | --instance-type t2.large --key-name GloboKey \ 130 | --security-group-ids $sg_id --subnet-id $subnet_1_id \ 131 | --associate-public-ip-address \ 132 | --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=jump},{Key=Company,Value=Globomantics}]' \ 133 | 'ResourceType=volume,Tags=[{Key=Name,Value=web-1},{Key=Company,Value=Globomantics}]' 134 | 135 | # Create an Elastic IP 136 | 137 | # Create a security group for your private instances 138 | 139 | aws ec2 create-security-group --description "allow-rdp-internal" \ 140 | --group-name "RDPInternal" --vpc-id $vpc_id 141 | 142 | sg_id=$(aws ec2 describe-security-groups --filter Name="group-name",Values="RDPInternal" \ 143 | --query 'SecurityGroups[0].GroupId' --output text) 144 | 145 | # Allow RDP from the VPC 146 | 147 | aws ec2 authorize-security-group-ingress \ 148 | --group-id $sg_id \ 149 | --protocol tcp \ 150 | --port 3389 \ 151 | --cidr "10.0.0.0/16" 152 | 153 | # Spin up two domain controller instances 154 | 155 | aws ec2 run-instances --image-id $ami_id --count 1 \ 156 | --instance-type t2.large --key-name GloboKey \ 157 | --security-group-ids $sg_id --subnet-id $subnet_4_id \ 158 | --private-ip-address "10.0.4.10" \ 159 | --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=dc-1},{Key=Company,Value=Globomantics}]' \ 160 | 'ResourceType=volume,Tags=[{Key=Name,Value=web-1},{Key=Company,Value=Globomantics}]' 161 | 162 | aws ec2 run-instances --image-id $ami_id --count 1 \ 163 | --instance-type t2.large --key-name GloboKey \ 164 | --security-group-ids $sg_id --subnet-id $subnet_5_id \ 165 | --private-ip-address "10.0.5.10" \ 166 | --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=dc-2},{Key=Company,Value=Globomantics}]' \ 167 | 'ResourceType=volume,Tags=[{Key=Name,Value=web-1},{Key=Company,Value=Globomantics}]' 168 | 169 | # Create Domain Controller SG 170 | 171 | aws ec2 create-security-group --description "Domain Controllers" \ 172 | --group-name "DomainControllerSG" --vpc-id $vpc_id 173 | 174 | dc_sg_id=$(aws ec2 describe-security-groups --filter Name="group-name",Values="DomainControllerSG" \ 175 | --query 'SecurityGroups[0].GroupId' --output text) 176 | 177 | # Create Domain Members SG 178 | 179 | aws ec2 create-security-group --description "Domain Members" \ 180 | --group-name "DomainMembersG" --vpc-id $vpc_id 181 | 182 | dm_sg_id=$(aws ec2 describe-security-groups --filter Name="group-name",Values="DomainMembersSG" \ 183 | --query 'SecurityGroups[0].GroupId' --output text) 184 | 185 | # Populate the DC and DM SGs with a LOT of SG rules, like so so so many 186 | 187 | aws ec2 authorize-security-group-ingress \ 188 | --group-id $dc_sg_id \ 189 | --protocol tcp \ 190 | --port 53 \ 191 | --cidr "10.0.0.0/16" 192 | 193 | aws ec2 authorize-security-group-ingress \ 194 | --group-id $dc_sg_id \ 195 | --protocol udp \ 196 | --port 53 \ 197 | --cidr "10.0.0.0/16" 198 | 199 | aws ec2 authorize-security-group-ingress \ 200 | --group-id $dc_sg_id \ 201 | --protocol tcp \ 202 | --port 80 \ 203 | --cidr "10.0.0.0/16" 204 | 205 | aws ec2 authorize-security-group-ingress \ 206 | --group-id $dc_sg_id \ 207 | --protocol tcp \ 208 | --port 5985 \ 209 | --cidr "10.0.0.0/16" 210 | 211 | aws ec2 authorize-security-group-ingress \ 212 | --group-id $dc_sg_id \ 213 | --protocol all \ 214 | --source-group $dc_sg_id 215 | 216 | aws ec2 authorize-security-group-ingress \ 217 | --group-id $dc_sg_id \ 218 | --protocol udp \ 219 | --port 67 \ 220 | --source-group $dm_sg_id 221 | 222 | aws ec2 authorize-security-group-ingress \ 223 | --group-id $dc_sg_id \ 224 | --protocol udp \ 225 | --port 88 \ 226 | --source-group $dm_sg_id 227 | 228 | aws ec2 authorize-security-group-ingress \ 229 | --group-id $dc_sg_id \ 230 | --protocol udp \ 231 | --port 123 \ 232 | --source-group $dm_sg_id 233 | 234 | aws ec2 authorize-security-group-ingress \ 235 | --group-id $dc_sg_id \ 236 | --protocol udp \ 237 | --port 138 \ 238 | --source-group $dm_sg_id 239 | 240 | aws ec2 authorize-security-group-ingress \ 241 | --group-id $dc_sg_id \ 242 | --protocol udp \ 243 | --port 137 \ 244 | --source-group $dm_sg_id 245 | 246 | aws ec2 authorize-security-group-ingress \ 247 | --group-id $dc_sg_id \ 248 | --protocol udp \ 249 | --port 389 \ 250 | --source-group $dm_sg_id 251 | 252 | aws ec2 authorize-security-group-ingress \ 253 | --group-id $dc_sg_id \ 254 | --protocol udp \ 255 | --port 445 \ 256 | --source-group $dm_sg_id 257 | 258 | aws ec2 authorize-security-group-ingress \ 259 | --group-id $dc_sg_id \ 260 | --protocol udp \ 261 | --port 464 \ 262 | --source-group $dm_sg_id 263 | 264 | aws ec2 authorize-security-group-ingress \ 265 | --group-id $dc_sg_id \ 266 | --protocol udp \ 267 | --port 2535 \ 268 | --source-group $dm_sg_id 269 | 270 | aws ec2 authorize-security-group-ingress \ 271 | --group-id $dc_sg_id \ 272 | --protocol udp \ 273 | --port 5355 \ 274 | --source-group $dm_sg_id 275 | 276 | aws ec2 authorize-security-group-ingress \ 277 | --group-id $dc_sg_id \ 278 | --protocol udp \ 279 | --port 49152-65535 \ 280 | --source-group $dm_sg_id 281 | 282 | aws ec2 authorize-security-group-ingress \ 283 | --group-id $dc_sg_id \ 284 | --protocol icmp \ 285 | --port -1 \ 286 | --source-group $dm_sg_id 287 | 288 | aws ec2 authorize-security-group-ingress \ 289 | --group-id $dc_sg_id \ 290 | --protocol tcp \ 291 | --port 88 \ 292 | --source-group $dm_sg_id 293 | 294 | aws ec2 authorize-security-group-ingress \ 295 | --group-id $dc_sg_id \ 296 | --protocol tcp \ 297 | --port 135 \ 298 | --source-group $dm_sg_id 299 | 300 | aws ec2 authorize-security-group-ingress \ 301 | --group-id $dc_sg_id \ 302 | --protocol tcp \ 303 | --port 139 \ 304 | --source-group $dm_sg_id 305 | 306 | aws ec2 authorize-security-group-ingress \ 307 | --group-id $dc_sg_id \ 308 | --protocol tcp \ 309 | --port 389 \ 310 | --source-group $dm_sg_id 311 | 312 | aws ec2 authorize-security-group-ingress \ 313 | --group-id $dc_sg_id \ 314 | --protocol tcp \ 315 | --port 445 \ 316 | --source-group $dm_sg_id 317 | 318 | aws ec2 authorize-security-group-ingress \ 319 | --group-id $dc_sg_id \ 320 | --protocol tcp \ 321 | --port 464 \ 322 | --source-group $dm_sg_id 323 | 324 | aws ec2 authorize-security-group-ingress \ 325 | --group-id $dc_sg_id \ 326 | --protocol tcp \ 327 | --port 636 \ 328 | --source-group $dm_sg_id 329 | 330 | aws ec2 authorize-security-group-ingress \ 331 | --group-id $dc_sg_id \ 332 | --protocol tcp \ 333 | --port 3268-3269 \ 334 | --source-group $dm_sg_id 335 | 336 | aws ec2 authorize-security-group-ingress \ 337 | --group-id $dc_sg_id \ 338 | --protocol tcp \ 339 | --port 5722 \ 340 | --source-group $dm_sg_id 341 | 342 | aws ec2 authorize-security-group-ingress \ 343 | --group-id $dc_sg_id \ 344 | --protocol tcp \ 345 | --port 9389 \ 346 | --source-group $dm_sg_id 347 | 348 | aws ec2 authorize-security-group-ingress \ 349 | --group-id $dc_sg_id \ 350 | --protocol tcp \ 351 | --port 49152-65535 \ 352 | --source-group $dm_sg_id 353 | 354 | aws ec2 authorize-security-group-ingress \ 355 | --group-id $dm_sg_id \ 356 | --protocol udp \ 357 | --port 88 \ 358 | --source-group $dc_sg_id 359 | 360 | aws ec2 authorize-security-group-ingress \ 361 | --group-id $dm_sg_id \ 362 | --protocol udp \ 363 | --port 389 \ 364 | --source-group $dc_sg_id 365 | 366 | aws ec2 authorize-security-group-ingress \ 367 | --group-id $dm_sg_id \ 368 | --protocol udp \ 369 | --port 445 \ 370 | --source-group $dc_sg_id 371 | 372 | aws ec2 authorize-security-group-ingress \ 373 | --group-id $dm_sg_id \ 374 | --protocol udp \ 375 | --port 49152-65535 \ 376 | --source-group $dc_sg_id 377 | 378 | aws ec2 authorize-security-group-ingress \ 379 | --group-id $dm_sg_id \ 380 | --protocol tcp \ 381 | --port 88 \ 382 | --source-group $dc_sg_id 383 | 384 | aws ec2 authorize-security-group-ingress \ 385 | --group-id $dm_sg_id \ 386 | --protocol tcp \ 387 | --port 389 \ 388 | --source-group $dc_sg_id 389 | 390 | aws ec2 authorize-security-group-ingress \ 391 | --group-id $dm_sg_id \ 392 | --protocol tcp \ 393 | --port 445 \ 394 | --source-group $dc_sg_id 395 | 396 | aws ec2 authorize-security-group-ingress \ 397 | --group-id $dm_sg_id \ 398 | --protocol tcp \ 399 | --port 636 \ 400 | --source-group $dc_sg_id 401 | 402 | aws ec2 authorize-security-group-ingress \ 403 | --group-id $dm_sg_id \ 404 | --protocol tcp \ 405 | --port 49152-65535 \ 406 | --source-group $dc_sg_id -------------------------------------------------------------------------------- /m5/flow-log-policy.txt: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Action": [ 6 | "logs:CreateLogGroup", 7 | "logs:CreateLogStream", 8 | "logs:PutLogEvents", 9 | "logs:DescribeLogGroups", 10 | "logs:DescribeLogStreams" 11 | ], 12 | "Effect": "Allow", 13 | "Resource": "*" 14 | } 15 | ] 16 | } -------------------------------------------------------------------------------- /m5/flow-log-role.txt: -------------------------------------------------------------------------------- 1 | { 2 | "Version": "2012-10-17", 3 | "Statement": [ 4 | { 5 | "Sid": "", 6 | "Effect": "Allow", 7 | "Principal": { 8 | "Service": "vpc-flow-logs.amazonaws.com" 9 | }, 10 | "Action": "sts:AssumeRole" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /m5/m5.sh: -------------------------------------------------------------------------------- 1 | # Let's first get the VPC ID 2 | 3 | vpc_id=$(aws ec2 describe-vpcs --filters Name="tag:Name",Values="globo-primary" \ 4 | --query 'Vpcs[0].VpcId' --output text) 5 | 6 | # Create remote access security group 7 | 8 | sg=$(aws ec2 create-security-group --description "allow-globo-remote" \ 9 | --group-name "globo-remote" --vpc-id $vpc_id) 10 | 11 | sg_id=$(echo $sg | jq .GroupId -r) 12 | 13 | my_ip=$(curl ifconfig.me) 14 | 15 | # Add allow RDP from your IP address 16 | 17 | aws ec2 authorize-security-group-ingress \ 18 | --group-id $sg_id \ 19 | --protocol tcp \ 20 | --port 3389 \ 21 | --cidr $my_ip/32 22 | 23 | # Add allow SSH from your IP address 24 | 25 | aws ec2 authorize-security-group-ingress \ 26 | --group-id $sg_id \ 27 | --protocol tcp \ 28 | --port 22 \ 29 | --cidr $my_ip/32 30 | 31 | # Create a web instance 32 | 33 | aws ec2 create-key-pair --key-name GloboKey --query 'KeyMaterial' --output text > GloboKey.pem 34 | 35 | subnet_1_id=$(aws ec2 describe-subnets --filter Name="tag:Name",Values="subnet-1" \ 36 | --query 'Subnets[0].SubnetId' --output text) 37 | 38 | ami_id=$(aws ssm get-parameters --names /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 \ 39 | --region us-east-1 | jq .Parameters[].Value -r) 40 | 41 | # Spin up the web-1 instance 42 | 43 | web_1=$(aws ec2 run-instances --image-id $ami_id --count 1 \ 44 | --instance-type t2.micro --key-name GloboKey \ 45 | --security-group-ids $sg_id --subnet-id $subnet_1_id \ 46 | --user-data file://webserver.txt \ 47 | --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=web-1},{Key=Company,Value=Globomantics}]' \ 48 | 'ResourceType=volume,Tags=[{Key=Name,Value=web-1},{Key=Company,Value=Globomantics}]') 49 | 50 | # Create security group for ALB 51 | 52 | sg=$(aws ec2 create-security-group --description "allow-http-anywhere" \ 53 | --group-name "allow-http-anywhere" --vpc-id $vpc_id) 54 | 55 | sg_id=$(echo $sg | jq .GroupId -r) 56 | 57 | aws ec2 authorize-security-group-ingress \ 58 | --group-id $sg_id \ 59 | --protocol tcp \ 60 | --port 80 \ 61 | --cidr "0.0.0.0/0" 62 | 63 | # Create an ALB and target group 64 | 65 | # Create an ALB for the public subnets 66 | 67 | public_subnets=$(aws ec2 describe-subnets --filter Name="tag:Network",Values="Public" \ 68 | --query 'Subnets[].SubnetId' --output text) 69 | 70 | alb=$(aws elbv2 create-load-balancer --name globo-web \ 71 | --subnets $public_subnets \ 72 | --security-groups $sg_id \ 73 | --scheme internet-facing \ 74 | --type application \ 75 | --ip-address-type ipv4) 76 | 77 | # Create a target group for the web instances 78 | 79 | target_group=$(aws elbv2 create-target-group --name globo-web \ 80 | --protocol HTTP \ 81 | --port 80 \ 82 | --vpc-id $vpc_id \ 83 | --target-type instance) 84 | 85 | aws elbv2 register-targets \ 86 | --target-group-arn $(echo $target_group | jq .TargetGroups[].TargetGroupArn -r) \ 87 | --targets Id=$(echo $web_1 | jq .Instances[].InstanceId -r) 88 | 89 | # Create security group for web instances and allow from ALB SG 90 | 91 | sg=$(aws ec2 create-security-group --description "allow-http-internal" \ 92 | --group-name "allow-http-internal" --vpc-id $vpc_id) 93 | 94 | sg_id=$(echo $sg | jq .GroupId -r) 95 | 96 | aws ec2 authorize-security-group-ingress \ 97 | --group-id $sg_id \ 98 | --protocol tcp \ 99 | --port 80 \ 100 | --source-group $(echo $alb | jq .LoadBalancers[0].SecurityGroups[0] -r) 101 | 102 | # Associate web instance with security group 103 | 104 | aws ec2 modify-instance-attribute \ 105 | --instance-id $(echo $web_1 | jq .Instances[].InstanceId -r) \ 106 | --groups $(echo $web_1 | jq .Instances[].NetworkInterfaces[0].Groups[].GroupId -r) $sg_id 107 | 108 | # Create the listener for globo-web 109 | 110 | aws elbv2 create-listener \ 111 | --load-balancer-arn $(echo $alb | jq .LoadBalancers[].LoadBalancerArn -r) \ 112 | --protocol HTTP \ 113 | --port 80 \ 114 | --default-actions Type=forward,TargetGroupArn=$(echo $target_group | jq .TargetGroups[].TargetGroupArn -r) 115 | 116 | ################# 117 | # NACLs 118 | ################# 119 | 120 | # Create a NACL for web subnets 121 | 122 | web_nacl=$(aws ec2 create-network-acl --vpc-id $vpc_id) 123 | 124 | aws ec2 create-tags --resources $(echo $web_nacl | jq .NetworkAcl.NetworkAclId -r) \ 125 | --tags Key=Name,Value=web-acl Key=Company,Value=Globomantics 126 | 127 | # Add rules to NACL 128 | 129 | aws ec2 create-network-acl-entry \ 130 | --network-acl-id $(echo $web_nacl | jq .NetworkAcl.NetworkAclId -r) \ 131 | --ingress \ 132 | --protocol tcp \ 133 | --port-range From=80,To=80 \ 134 | --cidr-block 0.0.0.0/0 \ 135 | --rule-number 100 \ 136 | --rule-action allow 137 | 138 | aws ec2 create-network-acl-entry \ 139 | --network-acl-id $(echo $web_nacl | jq .NetworkAcl.NetworkAclId -r) \ 140 | --egress \ 141 | --protocol -1 \ 142 | --cidr-block 0.0.0.0/0 \ 143 | --rule-number 100 \ 144 | --rule-action allow 145 | 146 | # Associate NACL with subnet-1 147 | 148 | sub_1_assoc=$(aws ec2 describe-network-acls --filters Name=association.subnet-id,Values=$subnet_1_id \ 149 | --query "NetworkAcls[0].Associations[?SubnetId=='$subnet_1_id'].NetworkAclAssociationId" --output text) 150 | 151 | aws ec2 replace-network-acl-association --association-id $sub_1_assoc \ 152 | --network-acl-id $(echo $web_nacl | jq .NetworkAcl.NetworkAclId -r) 153 | 154 | # Create a NACL for app subnets 155 | 156 | app_nacl=$(aws ec2 create-network-acl --vpc-id $vpc_id) 157 | 158 | aws ec2 create-tags --resources $(echo $app_nacl | jq .NetworkAcl.NetworkAclId -r) \ 159 | --tags Key=Name,Value=app-acl Key=Company,Value=Globomantics 160 | 161 | # Add rules to NACL 162 | 163 | aws ec2 create-network-acl-entry \ 164 | --network-acl-id $(echo $app_nacl | jq .NetworkAcl.NetworkAclId -r) \ 165 | --ingress \ 166 | --protocol tcp \ 167 | --port-range From=80,To=80 \ 168 | --cidr-block 10.0.0.0/16 \ 169 | --rule-number 100 \ 170 | --rule-action allow 171 | 172 | aws ec2 create-network-acl-entry \ 173 | --network-acl-id $(echo $app_nacl | jq .NetworkAcl.NetworkAclId -r) \ 174 | --ingress \ 175 | --protocol tcp \ 176 | --port-range From=443,To=443 \ 177 | --cidr-block 10.0.0.0/16 \ 178 | --rule-number 150 \ 179 | --rule-action allow 180 | 181 | aws ec2 create-network-acl-entry \ 182 | --network-acl-id $(echo $app_nacl | jq .NetworkAcl.NetworkAclId -r) \ 183 | --egress \ 184 | --protocol -1 \ 185 | --cidr-block 0.0.0.0/0 \ 186 | --rule-number 100 \ 187 | --rule-action allow 188 | 189 | # Associate NACL with subnet-4 190 | 191 | subnet_4_id=$(aws ec2 describe-subnets --filter Name="tag:Name",Values="subnet-4" \ 192 | --query 'Subnets[0].SubnetId' --output text) 193 | 194 | sub_4_assoc=$(aws ec2 describe-network-acls --filters Name=association.subnet-id,Values=$subnet_4_id \ 195 | --query "NetworkAcls[0].Associations[?SubnetId=='$subnet_4_id'].NetworkAclAssociationId" --output text) 196 | 197 | aws ec2 replace-network-acl-association --association-id $sub_4_assoc \ 198 | --network-acl-id $(echo $app_nacl | jq .NetworkAcl.NetworkAclId -r) 199 | 200 | ################### 201 | # Service Endpoints 202 | ################### 203 | 204 | # Gateway endpoint 205 | 206 | service_name=$(aws ec2 describe-vpc-endpoint-services --query 'ServiceNames[?ends_with(@,`s3`)]' --output text) 207 | 208 | route_table_ids=$(aws ec2 describe-route-tables \ 209 | --filter Name=association.subnet-id,Values=$subnet_4_id \ 210 | --query 'RouteTables[0].RouteTableId' --output text) 211 | 212 | aws ec2 create-vpc-endpoint --vpc-id $vpc_id \ 213 | --vpc-endpoint-type Gateway \ 214 | --service-name $service_name \ 215 | --route-table-ids $route_table_ids 216 | 217 | # Interface endpoint 218 | 219 | service_name=$(aws ec2 describe-vpc-endpoint-services --query 'ServiceNames[?ends_with(@,`logs`)]' --output text) 220 | 221 | aws ec2 create-vpc-endpoint --vpc-id $vpc_id \ 222 | --vpc-endpoint-type Interface \ 223 | --service-name $service_name \ 224 | --subnet-ids $subnet_1_id \ 225 | --private-dns-enabled 226 | 227 | ############## 228 | # Flow Logs 229 | ############## 230 | 231 | # Create an S3 bucket 232 | 233 | bucket_name=$(echo globo-logs-$RANDOM) 234 | 235 | bucket=$(aws s3api create-bucket --bucket $bucket_name) 236 | 237 | # Create a flow log for the VPC to CloudWatch 238 | 239 | # Create a role and policy to allow VPC to write to CloudWatch 240 | 241 | role=$(aws iam create-role --role-name flow-log-role \ 242 | --assume-role-policy-document file://flow-log-role.txt) 243 | 244 | policy=$(aws iam create-policy --policy-name flow-log-policy \ 245 | --policy-document file://flow-log-policy.txt) 246 | 247 | aws iam attach-role-policy --role-name flow-log-role \ 248 | --policy-arn $(echo $policy | jq .Policy.Arn -r) 249 | 250 | # Create flow log for vpc going to CloudWatch 251 | 252 | aws ec2 create-flow-logs \ 253 | --deliver-logs-permission-arn $(echo $role | jq .Role.Arn -r) \ 254 | --log-group-name globo-vpc-logs \ 255 | --resource-ids $vpc_id \ 256 | --resource-type VPC \ 257 | --traffic-type ALL 258 | 259 | # Create a flow log for public subnets to S3 with custom log format 260 | 261 | aws ec2 create-flow-logs \ 262 | --resource-type Subnet \ 263 | --resource-ids $public_subnets \ 264 | --traffic-type REJECT \ 265 | --log-destination-type s3 \ 266 | --log-destination "arn:aws:s3:::$bucket_name/flow_logs/" \ 267 | --log-format '${version} ${vpc-id} ${subnet-id} ${instance-id} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${tcp-flags} ${type} ${pkt-srcaddr} ${pkt-dstaddr}' -------------------------------------------------------------------------------- /m5/webserver.txt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | yum update -y 4 | yum install -y httpd 5 | systemctl start httpd 6 | systemctl enable httpd -------------------------------------------------------------------------------- /m6/m6.sh: -------------------------------------------------------------------------------- 1 | ################### 2 | # Setup 3 | ################### 4 | 5 | # Create the VPCs using CloudFormation 6 | aws cloudformation create-stack --stack-name Peering-Example --template-body file://three-vpcs.template 7 | 8 | ################### 9 | # VPC Peering 10 | ################### 11 | 12 | # Get the VPC IDs for each VPC 13 | vpc1_id=$(aws ec2 describe-vpcs --filters Name="tag:Name",Values="globo-vpc1" \ 14 | --query 'Vpcs[0].VpcId' --output text) 15 | 16 | vpc2_id=$(aws ec2 describe-vpcs --filters Name="tag:Name",Values="globo-vpc2" \ 17 | --query 'Vpcs[0].VpcId' --output text) 18 | 19 | vpc3_id=$(aws ec2 describe-vpcs --filters Name="tag:Name",Values="globo-vpc3" \ 20 | --query 'Vpcs[0].VpcId' --output text) 21 | 22 | # Create the peering request 23 | peer_req=$(aws ec2 create-vpc-peering-connection --vpc-id $vpc1_id \ 24 | --peer-vpc-id $vpc3_id) 25 | 26 | aws ec2 create-tags \ 27 | --resources $(echo $peer_req | jq .VpcPeeringConnection.VpcPeeringConnectionId -r) \ 28 | --tags Key=Name,Value=vpc1-vpc3 Key=Company,Value=Globomantics 29 | 30 | # Accept the peering request 31 | aws ec2 accept-vpc-peering-connection \ 32 | --vpc-peering-connection-id $(echo $peer_req | jq .VpcPeeringConnection.VpcPeeringConnectionId -r) 33 | 34 | # Get route tables for vpc1 35 | 36 | vpc1_rt_ids=$(aws ec2 describe-route-tables \ 37 | --filter Name=vpc-id,Values=$vpc1_id \ 38 | --query 'RouteTables[].RouteTableId' --output json) 39 | 40 | # Get route tables for vpc3 41 | 42 | vpc3_rt_ids=$(aws ec2 describe-route-tables \ 43 | --filter Name=vpc-id,Values=$vpc3_id \ 44 | --query 'RouteTables[].RouteTableId' --output json) 45 | 46 | # Add route to vpc1 for vpc3 destinations 47 | 48 | for OUTPUT in $(echo $vpc1_rt_ids | jq .[] -r) 49 | do 50 | aws ec2 create-route --route-table-id $OUTPUT \ 51 | --destination-cidr-block "10.2.0.0/16" \ 52 | --vpc-peering-connection-id $(echo $peer_req | jq .VpcPeeringConnection.VpcPeeringConnectionId -r) 53 | done 54 | 55 | # Add route to vpc3 for vpc1 destinations 56 | 57 | for OUTPUT in $(echo $vpc3_rt_ids | jq .[] -r) 58 | do 59 | aws ec2 create-route --route-table-id $OUTPUT \ 60 | --destination-cidr-block "10.0.0.0/16" \ 61 | --vpc-peering-connection-id $(echo $peer_req | jq .VpcPeeringConnection.VpcPeeringConnectionId -r) 62 | done 63 | 64 | ################ 65 | # VPC VPN 66 | ################ 67 | 68 | # Create the Destination VPC using CloudFormation 69 | aws cloudformation create-stack --stack-name VPN-Example --template-body file://vpn-vpc.template 70 | 71 | # Get the two VPC IDs 72 | 73 | dc_id=$(aws ec2 describe-vpcs --filters Name="tag:Name",Values="globo-dc" \ 74 | --query 'Vpcs[0].VpcId' --output text) 75 | 76 | vpc_id=$(aws ec2 describe-vpcs --filters Name="tag:Name",Values="globo-vpc1" \ 77 | --query 'Vpcs[0].VpcId' --output text) 78 | 79 | # Create a VGW 80 | 81 | vgw=$(aws ec2 create-vpn-gateway --type ipsec.1) 82 | 83 | # Attach the VGW to the VPC 84 | 85 | aws ec2 attach-vpn-gateway --vpc-id $vpc_id \ 86 | --vpn-gateway-id $(echo $vgw | jq .VpnGateway.VpnGatewayId -r) 87 | 88 | # Spin up a Server 2012 instance for VPN connection 89 | 90 | # Get the subnet for the server deployment 91 | 92 | vpn_subnet_id=$(aws ec2 describe-subnets --filter Name="tag:Name",Values="subnet-1" \ 93 | Name=vpc-id,Values=$dc_id \ 94 | --query 'Subnets[0].SubnetId' --output text) 95 | 96 | # Create remote access security group 97 | 98 | sg=$(aws ec2 create-security-group --description "vpn-server-sg" \ 99 | --group-name "vpn-server-sg" --vpc-id $dc_id) 100 | 101 | sg_id=$(echo $sg | jq .GroupId -r) 102 | 103 | my_ip=$(curl ifconfig.me) 104 | 105 | # Add allow RDP from your IP address 106 | 107 | aws ec2 authorize-security-group-ingress \ 108 | --group-id $sg_id \ 109 | --protocol tcp \ 110 | --port 3389 \ 111 | --cidr $my_ip/32 112 | 113 | # Allow UDP 4500 from anywhere for VPN 114 | 115 | aws ec2 authorize-security-group-ingress \ 116 | --group-id $sg_id \ 117 | --protocol udp \ 118 | --port 4500 \ 119 | --cidr 0.0.0.0/0 120 | 121 | aws ec2 create-key-pair --key-name VPNKey --query 'KeyMaterial' --output text > VPNKey.pem 122 | 123 | ami_id=$(aws ssm get-parameters --names /aws/service/ami-windows-latest/Windows_Server-2012-R2_RTM-English-64Bit-Base \ 124 | --region us-east-1 | jq .Parameters[].Value -r) 125 | 126 | inst=$(aws ec2 run-instances --image-id $ami_id --count 1 \ 127 | --instance-type t2.large --key-name VPNKey \ 128 | --security-group-ids $sg_id --subnet-id $vpn_subnet_id \ 129 | --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=vpn},{Key=Company,Value=Globomantics}]' \ 130 | 'ResourceType=volume,Tags=[{Key=Name,Value=vpn},{Key=Company,Value=Globomantics}]') 131 | 132 | # Allocate an EIP 133 | 134 | eip=$(aws ec2 allocate-address --domain vpc) 135 | 136 | aws ec2 associate-address \ 137 | --instance-id $(echo $inst | jq .Instances[0].InstanceId -r) \ 138 | --allocation-id $(echo $eip | jq .AllocationId -r) 139 | 140 | # Edit the source/dest check on the ENI 141 | 142 | aws ec2 modify-network-interface-attribute \ 143 | --network-interface-id $(echo $inst | jq .Instances[0].NetworkInterfaces[0].NetworkInterfaceId -r) \ 144 | --no-source-dest-check 145 | 146 | # Create a customer gateway 147 | 148 | cgw=$(aws ec2 create-customer-gateway \ 149 | --public-ip $(echo $eip | jq .PublicIp -r) \ 150 | --type ipsec.1 \ 151 | --device-name globo-dc-cgw \ 152 | --bgp-asn 65000) 153 | 154 | vpn_conn=$(aws ec2 create-vpn-connection \ 155 | --customer-gateway-id $(echo $cgw | jq .CustomerGateway.CustomerGatewayId -r) \ 156 | --vpn-gateway-id $(echo $vgw | jq .VpnGateway.VpnGatewayId -r) \ 157 | --type ipsec.1 \ 158 | --options "{\"StaticRoutesOnly\":true}") 159 | 160 | echo $vpn_conn | jq .VpnConnection.CustomerGatewayConfiguration -r > vpn_config.xml 161 | 162 | aws ec2 create-vpn-connection-route \ 163 | --vpn-connection-id $(echo $vpn_conn | jq .VpnConnection.VpnConnectionId -r) \ 164 | --destination-cidr-block 192.168.0.0/16 165 | 166 | # Create a route for the globo DC for each route table 167 | 168 | vpc_rt_ids=$(aws ec2 describe-route-tables \ 169 | --filter Name=vpc-id,Values=$vpc_id \ 170 | --query 'RouteTables[].RouteTableId' --output json) 171 | 172 | for OUTPUT in $(echo $vpc_rt_ids | jq .[] -r) 173 | do 174 | aws ec2 create-route --route-table-id $OUTPUT \ 175 | --destination-cidr-block "192.168.0.0/16" \ 176 | --gateway-id $(echo $vgw | jq .VpnGateway.VpnGatewayId -r) 177 | done 178 | 179 | # Create an EC2 instance in vpc1 to ping 180 | 181 | ping_sg=$(aws ec2 create-security-group --description "vpn-client-sg" \ 182 | --group-name "vpn-client-sg" --vpc-id $vpc_id) 183 | 184 | ping_sg_id=$(echo $sg | jq .GroupId -r) 185 | 186 | # Allow any traffic from Globo DC 187 | 188 | aws ec2 authorize-security-group-ingress \ 189 | --group-id $ping_sg_id \ 190 | --protocol all \ 191 | --cidr 192.168.0.0/16 192 | 193 | # Get the subnet from Globo VPC 194 | 195 | ping_subnet_id=$(aws ec2 describe-subnets --filter Name="tag:Name",Values="subnet-1" \ 196 | Name=vpc-id,Values=$vpc_id \ 197 | --query 'Subnets[0].SubnetId' --output text) 198 | 199 | ping_inst=$(aws ec2 run-instances --image-id $ami_id --count 1 \ 200 | --instance-type t2.medium --key-name VPNKey \ 201 | --security-group-ids $ping_sg_id --subnet-id $ping_subnet_id \ 202 | --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=vpn-client},{Key=Company,Value=Globomantics}]' \ 203 | 'ResourceType=volume,Tags=[{Key=Name,Value=vpn-client},{Key=Company,Value=Globomantics}]') 204 | 205 | echo $ping_inst | jq .Instances[].PrivateIpAddress -r -------------------------------------------------------------------------------- /m6/three-vpcs.template: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "Basic VPC deployment with two public subnets in two different Availability Zones", 4 | "Parameters": {}, 5 | "Resources": { 6 | "VPC1": { 7 | "Type": "AWS::EC2::VPC", 8 | "Properties": { 9 | "EnableDnsSupport": "true", 10 | "EnableDnsHostnames": "true", 11 | "CidrBlock": "10.0.0.0/16", 12 | "Tags": [ 13 | { 14 | "Key": "Company", 15 | "Value": "Globomantics" 16 | }, 17 | { 18 | "Key": "Name", 19 | "Value": "globo-vpc1" 20 | } 21 | ] 22 | } 23 | }, 24 | "V1Pub1": { 25 | "Type": "AWS::EC2::Subnet", 26 | "Properties": { 27 | "VpcId": { 28 | "Ref": "VPC1" 29 | }, 30 | "CidrBlock": "10.0.1.0/24", 31 | "Tags": [ 32 | { 33 | "Key": "Company", 34 | "Value": "Globomantics" 35 | }, 36 | { 37 | "Key": "Network", 38 | "Value": "Public" 39 | }, 40 | { 41 | "Key": "Name", 42 | "Value": "pub-1" 43 | } 44 | ], 45 | "AvailabilityZone": { 46 | "Fn::Select": [ 47 | "0", 48 | { 49 | "Fn::GetAZs": "" 50 | } 51 | ] 52 | } 53 | } 54 | }, 55 | "V1Pub2": { 56 | "Type": "AWS::EC2::Subnet", 57 | "Properties": { 58 | "VpcId": { 59 | "Ref": "VPC1" 60 | }, 61 | "CidrBlock": "10.0.2.0/24", 62 | "Tags": [ 63 | { 64 | "Key": "Company", 65 | "Value": "Globomantics" 66 | }, 67 | { 68 | "Key": "Network", 69 | "Value": "Public" 70 | }, 71 | { 72 | "Key": "Name", 73 | "Value": "pub-2" 74 | } 75 | ], 76 | "AvailabilityZone": { 77 | "Fn::Select": [ 78 | "1", 79 | { 80 | "Fn::GetAZs": "" 81 | } 82 | ] 83 | } 84 | } 85 | }, 86 | "V1Priv1": { 87 | "Type": "AWS::EC2::Subnet", 88 | "Properties": { 89 | "VpcId": { 90 | "Ref": "VPC1" 91 | }, 92 | "CidrBlock": "10.0.3.0/24", 93 | "Tags": [ 94 | { 95 | "Key": "Company", 96 | "Value": "Globomantics" 97 | }, 98 | { 99 | "Key": "Network", 100 | "Value": "Private" 101 | }, 102 | { 103 | "Key": "Name", 104 | "Value": "priv-1" 105 | } 106 | ], 107 | "AvailabilityZone": { 108 | "Fn::Select": [ 109 | "0", 110 | { 111 | "Fn::GetAZs": "" 112 | } 113 | ] 114 | } 115 | } 116 | }, 117 | "V1Priv2": { 118 | "Type": "AWS::EC2::Subnet", 119 | "Properties": { 120 | "VpcId": { 121 | "Ref": "VPC1" 122 | }, 123 | "CidrBlock": "10.0.4.0/24", 124 | "Tags": [ 125 | { 126 | "Key": "Company", 127 | "Value": "Globomantics" 128 | }, 129 | { 130 | "Key": "Network", 131 | "Value": "Private" 132 | }, 133 | { 134 | "Key": "Name", 135 | "Value": "priv-2" 136 | } 137 | ], 138 | "AvailabilityZone": { 139 | "Fn::Select": [ 140 | "1", 141 | { 142 | "Fn::GetAZs": "" 143 | } 144 | ] 145 | } 146 | } 147 | }, 148 | "V1IGW": { 149 | "Type": "AWS::EC2::InternetGateway", 150 | "Properties": { 151 | "Tags": [ 152 | { 153 | "Key": "Company", 154 | "Value": "Globomantics" 155 | } 156 | ] 157 | } 158 | }, 159 | "V1IGWA": { 160 | "Type": "AWS::EC2::VPCGatewayAttachment", 161 | "Properties": { 162 | "VpcId": { 163 | "Ref": "VPC1" 164 | }, 165 | "InternetGatewayId": { 166 | "Ref": "V1IGW" 167 | } 168 | } 169 | }, 170 | "V1PubRouteTable": { 171 | "Type": "AWS::EC2::RouteTable", 172 | "Properties": { 173 | "VpcId": { 174 | "Ref": "VPC1" 175 | }, 176 | "Tags": [ 177 | { 178 | "Key": "Company", 179 | "Value": "Globomantics" 180 | } 181 | ] 182 | } 183 | }, 184 | "V1PubRoute": { 185 | "Type": "AWS::EC2::Route", 186 | "DependsOn": "V1PubRouteTable", 187 | "Properties": { 188 | "RouteTableId": { 189 | "Ref": "V1PubRouteTable" 190 | }, 191 | "DestinationCidrBlock": "0.0.0.0/0", 192 | "GatewayId": { 193 | "Ref": "V1IGW" 194 | } 195 | } 196 | }, 197 | "V1Pub1RouteTableAssoc": { 198 | "Type": "AWS::EC2::SubnetRouteTableAssociation", 199 | "Properties": { 200 | "SubnetId": { 201 | "Ref": "V1Pub1" 202 | }, 203 | "RouteTableId": { 204 | "Ref": "V1PubRouteTable" 205 | } 206 | } 207 | }, 208 | "V1Pub2RouteTableAssoc": { 209 | "Type": "AWS::EC2::SubnetRouteTableAssociation", 210 | "Properties": { 211 | "SubnetId": { 212 | "Ref": "V1Pub2" 213 | }, 214 | "RouteTableId": { 215 | "Ref": "V1PubRouteTable" 216 | } 217 | } 218 | }, 219 | "V1PubNACL": { 220 | "Type": "AWS::EC2::NetworkAcl", 221 | "Properties": { 222 | "VpcId": { 223 | "Ref": "VPC1" 224 | }, 225 | "Tags": [ 226 | { 227 | "Key": "Company", 228 | "Value": "Globomantics" 229 | } 230 | ] 231 | } 232 | }, 233 | "V1PubNACLEgress": { 234 | "Type": "AWS::EC2::NetworkAclEntry", 235 | "Properties": { 236 | "NetworkAclId": { 237 | "Ref": "V1PubNACL" 238 | }, 239 | "RuleNumber": "100", 240 | "Protocol": "-1", 241 | "RuleAction": "allow", 242 | "Egress": "true", 243 | "CidrBlock": "0.0.0.0/0" 244 | } 245 | }, 246 | "V1PubNACLIngress": { 247 | "Type": "AWS::EC2::NetworkAclEntry", 248 | "Properties": { 249 | "NetworkAclId": { 250 | "Ref": "V1PubNACL" 251 | }, 252 | "RuleNumber": "100", 253 | "Protocol": "-1", 254 | "RuleAction": "allow", 255 | "Egress": "false", 256 | "CidrBlock": "0.0.0.0/0" 257 | } 258 | }, 259 | "V1Pub1NACLAssoc": { 260 | "Type": "AWS::EC2::SubnetNetworkAclAssociation", 261 | "Properties": { 262 | "SubnetId": { 263 | "Ref": "V1Pub1" 264 | }, 265 | "NetworkAclId": { 266 | "Ref": "V1PubNACL" 267 | } 268 | } 269 | }, 270 | "V1Pub2NACLAssoc": { 271 | "Type": "AWS::EC2::SubnetNetworkAclAssociation", 272 | "Properties": { 273 | "SubnetId": { 274 | "Ref": "V1Pub2" 275 | }, 276 | "NetworkAclId": { 277 | "Ref": "V1PubNACL" 278 | } 279 | } 280 | }, 281 | "VPC2": { 282 | "Type": "AWS::EC2::VPC", 283 | "Properties": { 284 | "EnableDnsSupport": "true", 285 | "EnableDnsHostnames": "true", 286 | "CidrBlock": "10.1.0.0/16", 287 | "Tags": [ 288 | { 289 | "Key": "Company", 290 | "Value": "Globomantics" 291 | }, 292 | { 293 | "Key": "Name", 294 | "Value": "globo-vpc2" 295 | } 296 | ] 297 | } 298 | }, 299 | "V2Pub1": { 300 | "Type": "AWS::EC2::Subnet", 301 | "Properties": { 302 | "VpcId": { 303 | "Ref": "VPC2" 304 | }, 305 | "CidrBlock": "10.1.1.0/24", 306 | "Tags": [ 307 | { 308 | "Key": "Company", 309 | "Value": "Globomantics" 310 | }, 311 | { 312 | "Key": "Network", 313 | "Value": "Public" 314 | }, 315 | { 316 | "Key": "Name", 317 | "Value": "pub-1" 318 | } 319 | ], 320 | "AvailabilityZone": { 321 | "Fn::Select": [ 322 | "0", 323 | { 324 | "Fn::GetAZs": "" 325 | } 326 | ] 327 | } 328 | } 329 | }, 330 | "V2Pub2": { 331 | "Type": "AWS::EC2::Subnet", 332 | "Properties": { 333 | "VpcId": { 334 | "Ref": "VPC2" 335 | }, 336 | "CidrBlock": "10.1.2.0/24", 337 | "Tags": [ 338 | { 339 | "Key": "Company", 340 | "Value": "Globomantics" 341 | }, 342 | { 343 | "Key": "Network", 344 | "Value": "Public" 345 | }, 346 | { 347 | "Key": "Name", 348 | "Value": "pub-2" 349 | } 350 | ], 351 | "AvailabilityZone": { 352 | "Fn::Select": [ 353 | "1", 354 | { 355 | "Fn::GetAZs": "" 356 | } 357 | ] 358 | } 359 | } 360 | }, 361 | "V2Priv1": { 362 | "Type": "AWS::EC2::Subnet", 363 | "Properties": { 364 | "VpcId": { 365 | "Ref": "VPC2" 366 | }, 367 | "CidrBlock": "10.1.3.0/24", 368 | "Tags": [ 369 | { 370 | "Key": "Company", 371 | "Value": "Globomantics" 372 | }, 373 | { 374 | "Key": "Network", 375 | "Value": "Private" 376 | }, 377 | { 378 | "Key": "Name", 379 | "Value": "priv-1" 380 | } 381 | ], 382 | "AvailabilityZone": { 383 | "Fn::Select": [ 384 | "0", 385 | { 386 | "Fn::GetAZs": "" 387 | } 388 | ] 389 | } 390 | } 391 | }, 392 | "V2Priv2": { 393 | "Type": "AWS::EC2::Subnet", 394 | "Properties": { 395 | "VpcId": { 396 | "Ref": "VPC2" 397 | }, 398 | "CidrBlock": "10.1.4.0/24", 399 | "Tags": [ 400 | { 401 | "Key": "Company", 402 | "Value": "Globomantics" 403 | }, 404 | { 405 | "Key": "Network", 406 | "Value": "Private" 407 | }, 408 | { 409 | "Key": "Name", 410 | "Value": "priv-2" 411 | } 412 | ], 413 | "AvailabilityZone": { 414 | "Fn::Select": [ 415 | "1", 416 | { 417 | "Fn::GetAZs": "" 418 | } 419 | ] 420 | } 421 | } 422 | }, 423 | "V2IGW": { 424 | "Type": "AWS::EC2::InternetGateway", 425 | "Properties": { 426 | "Tags": [ 427 | { 428 | "Key": "Company", 429 | "Value": "Globomantics" 430 | } 431 | ] 432 | } 433 | }, 434 | "V2IGWA": { 435 | "Type": "AWS::EC2::VPCGatewayAttachment", 436 | "Properties": { 437 | "VpcId": { 438 | "Ref": "VPC2" 439 | }, 440 | "InternetGatewayId": { 441 | "Ref": "V2IGW" 442 | } 443 | } 444 | }, 445 | "V2PubRouteTable": { 446 | "Type": "AWS::EC2::RouteTable", 447 | "Properties": { 448 | "VpcId": { 449 | "Ref": "VPC2" 450 | }, 451 | "Tags": [ 452 | { 453 | "Key": "Company", 454 | "Value": "Globomantics" 455 | } 456 | ] 457 | } 458 | }, 459 | "V2PubRoute": { 460 | "Type": "AWS::EC2::Route", 461 | "DependsOn": "V2PubRouteTable", 462 | "Properties": { 463 | "RouteTableId": { 464 | "Ref": "V2PubRouteTable" 465 | }, 466 | "DestinationCidrBlock": "0.0.0.0/0", 467 | "GatewayId": { 468 | "Ref": "V2IGW" 469 | } 470 | } 471 | }, 472 | "V2Pub1RouteTableAssoc": { 473 | "Type": "AWS::EC2::SubnetRouteTableAssociation", 474 | "Properties": { 475 | "SubnetId": { 476 | "Ref": "V2Pub1" 477 | }, 478 | "RouteTableId": { 479 | "Ref": "V2PubRouteTable" 480 | } 481 | } 482 | }, 483 | "V2Pub2RouteTableAssoc": { 484 | "Type": "AWS::EC2::SubnetRouteTableAssociation", 485 | "Properties": { 486 | "SubnetId": { 487 | "Ref": "V2Pub2" 488 | }, 489 | "RouteTableId": { 490 | "Ref": "V2PubRouteTable" 491 | } 492 | } 493 | }, 494 | "V2PubNACL": { 495 | "Type": "AWS::EC2::NetworkAcl", 496 | "Properties": { 497 | "VpcId": { 498 | "Ref": "VPC2" 499 | }, 500 | "Tags": [ 501 | { 502 | "Key": "Company", 503 | "Value": "Globomantics" 504 | } 505 | ] 506 | } 507 | }, 508 | "V2PubNACLEgress": { 509 | "Type": "AWS::EC2::NetworkAclEntry", 510 | "Properties": { 511 | "NetworkAclId": { 512 | "Ref": "V2PubNACL" 513 | }, 514 | "RuleNumber": "100", 515 | "Protocol": "-1", 516 | "RuleAction": "allow", 517 | "Egress": "true", 518 | "CidrBlock": "0.0.0.0/0" 519 | } 520 | }, 521 | "V2PubNACLIngress": { 522 | "Type": "AWS::EC2::NetworkAclEntry", 523 | "Properties": { 524 | "NetworkAclId": { 525 | "Ref": "V2PubNACL" 526 | }, 527 | "RuleNumber": "100", 528 | "Protocol": "-1", 529 | "RuleAction": "allow", 530 | "Egress": "false", 531 | "CidrBlock": "0.0.0.0/0" 532 | } 533 | }, 534 | "V2Pub1NACLAssoc": { 535 | "Type": "AWS::EC2::SubnetNetworkAclAssociation", 536 | "Properties": { 537 | "SubnetId": { 538 | "Ref": "V2Pub1" 539 | }, 540 | "NetworkAclId": { 541 | "Ref": "V2PubNACL" 542 | } 543 | } 544 | }, 545 | "V2Pub2NACLAssoc": { 546 | "Type": "AWS::EC2::SubnetNetworkAclAssociation", 547 | "Properties": { 548 | "SubnetId": { 549 | "Ref": "V2Pub2" 550 | }, 551 | "NetworkAclId": { 552 | "Ref": "V2PubNACL" 553 | } 554 | } 555 | }, 556 | "VPC3": { 557 | "Type": "AWS::EC2::VPC", 558 | "Properties": { 559 | "EnableDnsSupport": "true", 560 | "EnableDnsHostnames": "true", 561 | "CidrBlock": "10.2.0.0/16", 562 | "Tags": [ 563 | { 564 | "Key": "Company", 565 | "Value": "Globomantics" 566 | }, 567 | { 568 | "Key": "Name", 569 | "Value": "globo-vpc3" 570 | } 571 | ] 572 | } 573 | }, 574 | "V3Pub1": { 575 | "Type": "AWS::EC2::Subnet", 576 | "Properties": { 577 | "VpcId": { 578 | "Ref": "VPC3" 579 | }, 580 | "CidrBlock": "10.2.1.0/24", 581 | "Tags": [ 582 | { 583 | "Key": "Company", 584 | "Value": "Globomantics" 585 | }, 586 | { 587 | "Key": "Network", 588 | "Value": "Public" 589 | }, 590 | { 591 | "Key": "Name", 592 | "Value": "pub-1" 593 | } 594 | ], 595 | "AvailabilityZone": { 596 | "Fn::Select": [ 597 | "0", 598 | { 599 | "Fn::GetAZs": "" 600 | } 601 | ] 602 | } 603 | } 604 | }, 605 | "V3Pub2": { 606 | "Type": "AWS::EC2::Subnet", 607 | "Properties": { 608 | "VpcId": { 609 | "Ref": "VPC3" 610 | }, 611 | "CidrBlock": "10.2.2.0/24", 612 | "Tags": [ 613 | { 614 | "Key": "Company", 615 | "Value": "Globomantics" 616 | }, 617 | { 618 | "Key": "Network", 619 | "Value": "Public" 620 | }, 621 | { 622 | "Key": "Name", 623 | "Value": "pub-2" 624 | } 625 | ], 626 | "AvailabilityZone": { 627 | "Fn::Select": [ 628 | "1", 629 | { 630 | "Fn::GetAZs": "" 631 | } 632 | ] 633 | } 634 | } 635 | }, 636 | "V3Priv1": { 637 | "Type": "AWS::EC2::Subnet", 638 | "Properties": { 639 | "VpcId": { 640 | "Ref": "VPC3" 641 | }, 642 | "CidrBlock": "10.2.3.0/24", 643 | "Tags": [ 644 | { 645 | "Key": "Company", 646 | "Value": "Globomantics" 647 | }, 648 | { 649 | "Key": "Network", 650 | "Value": "Private" 651 | }, 652 | { 653 | "Key": "Name", 654 | "Value": "priv-1" 655 | } 656 | ], 657 | "AvailabilityZone": { 658 | "Fn::Select": [ 659 | "0", 660 | { 661 | "Fn::GetAZs": "" 662 | } 663 | ] 664 | } 665 | } 666 | }, 667 | "V3Priv2": { 668 | "Type": "AWS::EC2::Subnet", 669 | "Properties": { 670 | "VpcId": { 671 | "Ref": "VPC3" 672 | }, 673 | "CidrBlock": "10.2.4.0/24", 674 | "Tags": [ 675 | { 676 | "Key": "Company", 677 | "Value": "Globomantics" 678 | }, 679 | { 680 | "Key": "Network", 681 | "Value": "Private" 682 | }, 683 | { 684 | "Key": "Name", 685 | "Value": "priv-2" 686 | } 687 | ], 688 | "AvailabilityZone": { 689 | "Fn::Select": [ 690 | "1", 691 | { 692 | "Fn::GetAZs": "" 693 | } 694 | ] 695 | } 696 | } 697 | }, 698 | "V3IGW": { 699 | "Type": "AWS::EC2::InternetGateway", 700 | "Properties": { 701 | "Tags": [ 702 | { 703 | "Key": "Company", 704 | "Value": "Globomantics" 705 | } 706 | ] 707 | } 708 | }, 709 | "V3IGWA": { 710 | "Type": "AWS::EC2::VPCGatewayAttachment", 711 | "Properties": { 712 | "VpcId": { 713 | "Ref": "VPC3" 714 | }, 715 | "InternetGatewayId": { 716 | "Ref": "V3IGW" 717 | } 718 | } 719 | }, 720 | "V3PubRouteTable": { 721 | "Type": "AWS::EC2::RouteTable", 722 | "Properties": { 723 | "VpcId": { 724 | "Ref": "VPC3" 725 | }, 726 | "Tags": [ 727 | { 728 | "Key": "Company", 729 | "Value": "Globomantics" 730 | } 731 | ] 732 | } 733 | }, 734 | "V3PubRoute": { 735 | "Type": "AWS::EC2::Route", 736 | "DependsOn": "V3PubRouteTable", 737 | "Properties": { 738 | "RouteTableId": { 739 | "Ref": "V3PubRouteTable" 740 | }, 741 | "DestinationCidrBlock": "0.0.0.0/0", 742 | "GatewayId": { 743 | "Ref": "V3IGW" 744 | } 745 | } 746 | }, 747 | "V3Pub1RouteTableAssoc": { 748 | "Type": "AWS::EC2::SubnetRouteTableAssociation", 749 | "Properties": { 750 | "SubnetId": { 751 | "Ref": "V3Pub1" 752 | }, 753 | "RouteTableId": { 754 | "Ref": "V3PubRouteTable" 755 | } 756 | } 757 | }, 758 | "V3Pub2RouteTableAssoc": { 759 | "Type": "AWS::EC2::SubnetRouteTableAssociation", 760 | "Properties": { 761 | "SubnetId": { 762 | "Ref": "V3Pub2" 763 | }, 764 | "RouteTableId": { 765 | "Ref": "V3PubRouteTable" 766 | } 767 | } 768 | }, 769 | "V3PubNACL": { 770 | "Type": "AWS::EC2::NetworkAcl", 771 | "Properties": { 772 | "VpcId": { 773 | "Ref": "VPC3" 774 | }, 775 | "Tags": [ 776 | { 777 | "Key": "Company", 778 | "Value": "Globomantics" 779 | } 780 | ] 781 | } 782 | }, 783 | "V3PubNACLEgress": { 784 | "Type": "AWS::EC2::NetworkAclEntry", 785 | "Properties": { 786 | "NetworkAclId": { 787 | "Ref": "V3PubNACL" 788 | }, 789 | "RuleNumber": "100", 790 | "Protocol": "-1", 791 | "RuleAction": "allow", 792 | "Egress": "true", 793 | "CidrBlock": "0.0.0.0/0" 794 | } 795 | }, 796 | "V3PubNACLIngress": { 797 | "Type": "AWS::EC2::NetworkAclEntry", 798 | "Properties": { 799 | "NetworkAclId": { 800 | "Ref": "V3PubNACL" 801 | }, 802 | "RuleNumber": "100", 803 | "Protocol": "-1", 804 | "RuleAction": "allow", 805 | "Egress": "false", 806 | "CidrBlock": "0.0.0.0/0" 807 | } 808 | }, 809 | "V3Pub1NACLAssoc": { 810 | "Type": "AWS::EC2::SubnetNetworkAclAssociation", 811 | "Properties": { 812 | "SubnetId": { 813 | "Ref": "V3Pub1" 814 | }, 815 | "NetworkAclId": { 816 | "Ref": "V3PubNACL" 817 | } 818 | } 819 | }, 820 | "V3Pub2NACLAssoc": { 821 | "Type": "AWS::EC2::SubnetNetworkAclAssociation", 822 | "Properties": { 823 | "SubnetId": { 824 | "Ref": "V3Pub2" 825 | }, 826 | "NetworkAclId": { 827 | "Ref": "V3PubNACL" 828 | } 829 | } 830 | } 831 | }, 832 | "Outputs": { 833 | "VPCId": { 834 | "Description": "VPCId of the newly created VPC", 835 | "Value": { 836 | "Ref": "VPC1" 837 | } 838 | } 839 | } 840 | } -------------------------------------------------------------------------------- /m6/vpn-vpc.template: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "Basic VPC deployment with two public subnets in two different Availability Zones", 4 | "Parameters": {}, 5 | "Resources": { 6 | "VPC": { 7 | "Type": "AWS::EC2::VPC", 8 | "Properties": { 9 | "EnableDnsSupport": "true", 10 | "EnableDnsHostnames": "true", 11 | "CidrBlock": "192.168.0.0/16", 12 | "Tags": [ 13 | { 14 | "Key": "Company", 15 | "Value": "Globomantics" 16 | }, 17 | { 18 | "Key": "Name", 19 | "Value": "globo-dc" 20 | } 21 | ] 22 | } 23 | }, 24 | "PublicSubnet1": { 25 | "Type": "AWS::EC2::Subnet", 26 | "Properties": { 27 | "VpcId": { 28 | "Ref": "VPC" 29 | }, 30 | "MapPublicIpOnLaunch": true, 31 | "CidrBlock": "192.168.1.0/24", 32 | "Tags": [ 33 | { 34 | "Key": "Company", 35 | "Value": "Globomantics" 36 | }, 37 | { 38 | "Key": "Network", 39 | "Value": "Public" 40 | }, 41 | { 42 | "Key": "Name", 43 | "Value": "subnet-1" 44 | } 45 | ], 46 | "AvailabilityZone": { 47 | "Fn::Select": [ 48 | "0", 49 | { 50 | "Fn::GetAZs": "" 51 | } 52 | ] 53 | } 54 | } 55 | }, 56 | "InternetGateway": { 57 | "Type": "AWS::EC2::InternetGateway", 58 | "Properties": { 59 | "Tags": [ 60 | { 61 | "Key": "Company", 62 | "Value": "Globomantics" 63 | } 64 | ] 65 | } 66 | }, 67 | "GatewayToInternet": { 68 | "Type": "AWS::EC2::VPCGatewayAttachment", 69 | "Properties": { 70 | "VpcId": { 71 | "Ref": "VPC" 72 | }, 73 | "InternetGatewayId": { 74 | "Ref": "InternetGateway" 75 | } 76 | } 77 | }, 78 | "PublicRouteTable": { 79 | "Type": "AWS::EC2::RouteTable", 80 | "Properties": { 81 | "VpcId": { 82 | "Ref": "VPC" 83 | }, 84 | "Tags": [ 85 | { 86 | "Key": "Company", 87 | "Value": "Globomantics" 88 | } 89 | ] 90 | } 91 | }, 92 | "PublicRoute": { 93 | "Type": "AWS::EC2::Route", 94 | "DependsOn": "GatewayToInternet", 95 | "Properties": { 96 | "RouteTableId": { 97 | "Ref": "PublicRouteTable" 98 | }, 99 | "DestinationCidrBlock": "0.0.0.0/0", 100 | "GatewayId": { 101 | "Ref": "InternetGateway" 102 | } 103 | } 104 | }, 105 | "PublicSubnetRouteTableAssociation1": { 106 | "Type": "AWS::EC2::SubnetRouteTableAssociation", 107 | "Properties": { 108 | "SubnetId": { 109 | "Ref": "PublicSubnet1" 110 | }, 111 | "RouteTableId": { 112 | "Ref": "PublicRouteTable" 113 | } 114 | } 115 | }, 116 | "PublicNetworkAcl": { 117 | "Type": "AWS::EC2::NetworkAcl", 118 | "Properties": { 119 | "VpcId": { 120 | "Ref": "VPC" 121 | }, 122 | "Tags": [ 123 | { 124 | "Key": "Company", 125 | "Value": "Globomantics" 126 | } 127 | ] 128 | } 129 | }, 130 | "OutboundPublicNetworkAclEntry": { 131 | "Type": "AWS::EC2::NetworkAclEntry", 132 | "Properties": { 133 | "NetworkAclId": { 134 | "Ref": "PublicNetworkAcl" 135 | }, 136 | "RuleNumber": "100", 137 | "Protocol": "-1", 138 | "RuleAction": "allow", 139 | "Egress": "true", 140 | "CidrBlock": "0.0.0.0/0" 141 | } 142 | }, 143 | "InboundPublicNetworkAclEntry": { 144 | "Type": "AWS::EC2::NetworkAclEntry", 145 | "Properties": { 146 | "NetworkAclId": { 147 | "Ref": "PublicNetworkAcl" 148 | }, 149 | "RuleNumber": "100", 150 | "Protocol": "-1", 151 | "RuleAction": "allow", 152 | "Egress": "false", 153 | "CidrBlock": "0.0.0.0/0" 154 | } 155 | }, 156 | "PublicSubnetNetworkAclAssociation1": { 157 | "Type": "AWS::EC2::SubnetNetworkAclAssociation", 158 | "Properties": { 159 | "SubnetId": { 160 | "Ref": "PublicSubnet1" 161 | }, 162 | "NetworkAclId": { 163 | "Ref": "PublicNetworkAcl" 164 | } 165 | } 166 | }, 167 | "VPC2": { 168 | "Type": "AWS::EC2::VPC", 169 | "Properties": { 170 | "EnableDnsSupport": "true", 171 | "EnableDnsHostnames": "true", 172 | "CidrBlock": "10.0.0.0/16", 173 | "Tags": [ 174 | { 175 | "Key": "Company", 176 | "Value": "Globomantics" 177 | }, 178 | { 179 | "Key": "Name", 180 | "Value": "globo-s2s" 181 | } 182 | ] 183 | } 184 | }, 185 | "V2PublicSubnet1": { 186 | "Type": "AWS::EC2::Subnet", 187 | "Properties": { 188 | "VpcId": { 189 | "Ref": "VPC2" 190 | }, 191 | "MapPublicIpOnLaunch": true, 192 | "CidrBlock": "10.0.1.0/24", 193 | "Tags": [ 194 | { 195 | "Key": "Company", 196 | "Value": "Globomantics" 197 | }, 198 | { 199 | "Key": "Network", 200 | "Value": "Public" 201 | }, 202 | { 203 | "Key": "Name", 204 | "Value": "subnet-1" 205 | } 206 | ], 207 | "AvailabilityZone": { 208 | "Fn::Select": [ 209 | "0", 210 | { 211 | "Fn::GetAZs": "" 212 | } 213 | ] 214 | } 215 | } 216 | }, 217 | "V2InternetGateway": { 218 | "Type": "AWS::EC2::InternetGateway", 219 | "Properties": { 220 | "Tags": [ 221 | { 222 | "Key": "Company", 223 | "Value": "Globomantics" 224 | } 225 | ] 226 | } 227 | }, 228 | "V2GatewayToInternet": { 229 | "Type": "AWS::EC2::VPCGatewayAttachment", 230 | "Properties": { 231 | "VpcId": { 232 | "Ref": "VPC2" 233 | }, 234 | "InternetGatewayId": { 235 | "Ref": "V2InternetGateway" 236 | } 237 | } 238 | }, 239 | "V2PublicRouteTable": { 240 | "Type": "AWS::EC2::RouteTable", 241 | "Properties": { 242 | "VpcId": { 243 | "Ref": "VPC2" 244 | }, 245 | "Tags": [ 246 | { 247 | "Key": "Company", 248 | "Value": "Globomantics" 249 | } 250 | ] 251 | } 252 | }, 253 | "V2PublicRoute": { 254 | "Type": "AWS::EC2::Route", 255 | "DependsOn": "V2GatewayToInternet", 256 | "Properties": { 257 | "RouteTableId": { 258 | "Ref": "V2PublicRouteTable" 259 | }, 260 | "DestinationCidrBlock": "0.0.0.0/0", 261 | "GatewayId": { 262 | "Ref": "V2InternetGateway" 263 | } 264 | } 265 | }, 266 | "V2PublicSubnetRouteTableAssociation1": { 267 | "Type": "AWS::EC2::SubnetRouteTableAssociation", 268 | "Properties": { 269 | "SubnetId": { 270 | "Ref": "V2PublicSubnet1" 271 | }, 272 | "RouteTableId": { 273 | "Ref": "V2PublicRouteTable" 274 | } 275 | } 276 | }, 277 | "V2PublicNetworkAcl": { 278 | "Type": "AWS::EC2::NetworkAcl", 279 | "Properties": { 280 | "VpcId": { 281 | "Ref": "VPC2" 282 | }, 283 | "Tags": [ 284 | { 285 | "Key": "Company", 286 | "Value": "Globomantics" 287 | } 288 | ] 289 | } 290 | }, 291 | "V2OutboundPublicNetworkAclEntry": { 292 | "Type": "AWS::EC2::NetworkAclEntry", 293 | "Properties": { 294 | "NetworkAclId": { 295 | "Ref": "V2PublicNetworkAcl" 296 | }, 297 | "RuleNumber": "100", 298 | "Protocol": "-1", 299 | "RuleAction": "allow", 300 | "Egress": "true", 301 | "CidrBlock": "0.0.0.0/0" 302 | } 303 | }, 304 | "V2InboundPublicNetworkAclEntry": { 305 | "Type": "AWS::EC2::NetworkAclEntry", 306 | "Properties": { 307 | "NetworkAclId": { 308 | "Ref": "V2PublicNetworkAcl" 309 | }, 310 | "RuleNumber": "100", 311 | "Protocol": "-1", 312 | "RuleAction": "allow", 313 | "Egress": "false", 314 | "CidrBlock": "0.0.0.0/0" 315 | } 316 | }, 317 | "V2PublicSubnetNetworkAclAssociation1": { 318 | "Type": "AWS::EC2::SubnetNetworkAclAssociation", 319 | "Properties": { 320 | "SubnetId": { 321 | "Ref": "V2PublicSubnet1" 322 | }, 323 | "NetworkAclId": { 324 | "Ref": "V2PublicNetworkAcl" 325 | } 326 | } 327 | } 328 | }, 329 | "Outputs": { 330 | "VPCId": { 331 | "Description": "VPCId of the newly created VPC", 332 | "Value": { 333 | "Ref": "VPC" 334 | } 335 | } 336 | } 337 | } -------------------------------------------------------------------------------- /setup/basic-network.template: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "Basic VPC deployment with two public subnets in two different Availability Zones", 4 | "Parameters": {}, 5 | "Resources": { 6 | "VPC": { 7 | "Type": "AWS::EC2::VPC", 8 | "Properties": { 9 | "EnableDnsSupport": "true", 10 | "EnableDnsHostnames": "true", 11 | "CidrBlock": "10.0.0.0/16", 12 | "Tags": [ 13 | { 14 | "Key": "Company", 15 | "Value": "Globomantics" 16 | }, 17 | { 18 | "Key": "Name", 19 | "Value": "globo-primary" 20 | } 21 | ] 22 | } 23 | }, 24 | "PublicSubnet1": { 25 | "Type": "AWS::EC2::Subnet", 26 | "Properties": { 27 | "VpcId": { 28 | "Ref": "VPC" 29 | }, 30 | "CidrBlock": "10.0.1.0/24", 31 | "Tags": [ 32 | { 33 | "Key": "Company", 34 | "Value": "Globomantics" 35 | }, 36 | { 37 | "Key": "Network", 38 | "Value": "Public" 39 | }, 40 | { 41 | "Key": "Name", 42 | "Value": "subnet-1" 43 | } 44 | ], 45 | "AvailabilityZone": { 46 | "Fn::Select": [ 47 | "0", 48 | { 49 | "Fn::GetAZs": "" 50 | } 51 | ] 52 | } 53 | } 54 | }, 55 | "PublicSubnet2": { 56 | "Type": "AWS::EC2::Subnet", 57 | "Properties": { 58 | "VpcId": { 59 | "Ref": "VPC" 60 | }, 61 | "CidrBlock": "10.0.2.0/24", 62 | "Tags": [ 63 | { 64 | "Key": "Company", 65 | "Value": "Globomantics" 66 | }, 67 | { 68 | "Key": "Network", 69 | "Value": "Public" 70 | }, 71 | { 72 | "Key": "Name", 73 | "Value": "subnet-2" 74 | } 75 | ], 76 | "AvailabilityZone": { 77 | "Fn::Select": [ 78 | "1", 79 | { 80 | "Fn::GetAZs": "" 81 | } 82 | ] 83 | } 84 | } 85 | }, 86 | "PublicSubnet3": { 87 | "Type": "AWS::EC2::Subnet", 88 | "Properties": { 89 | "VpcId": { 90 | "Ref": "VPC" 91 | }, 92 | "CidrBlock": "10.0.3.0/24", 93 | "Tags": [ 94 | { 95 | "Key": "Company", 96 | "Value": "Globomantics" 97 | }, 98 | { 99 | "Key": "Network", 100 | "Value": "Private" 101 | }, 102 | { 103 | "Key": "Name", 104 | "Value": "subnet-3" 105 | } 106 | ], 107 | "AvailabilityZone": { 108 | "Fn::Select": [ 109 | "2", 110 | { 111 | "Fn::GetAZs": "" 112 | } 113 | ] 114 | } 115 | } 116 | }, 117 | "PrivateSubnet1": { 118 | "Type": "AWS::EC2::Subnet", 119 | "Properties": { 120 | "VpcId": { 121 | "Ref": "VPC" 122 | }, 123 | "CidrBlock": "10.0.4.0/24", 124 | "Tags": [ 125 | { 126 | "Key": "Company", 127 | "Value": "Globomantics" 128 | }, 129 | { 130 | "Key": "Network", 131 | "Value": "Private" 132 | }, 133 | { 134 | "Key": "Name", 135 | "Value": "subnet-4" 136 | } 137 | ], 138 | "AvailabilityZone": { 139 | "Fn::Select": [ 140 | "0", 141 | { 142 | "Fn::GetAZs": "" 143 | } 144 | ] 145 | } 146 | } 147 | }, 148 | "PrivateSubnet2": { 149 | "Type": "AWS::EC2::Subnet", 150 | "Properties": { 151 | "VpcId": { 152 | "Ref": "VPC" 153 | }, 154 | "CidrBlock": "10.0.5.0/24", 155 | "Tags": [ 156 | { 157 | "Key": "Company", 158 | "Value": "Globomantics" 159 | }, 160 | { 161 | "Key": "Network", 162 | "Value": "Private" 163 | }, 164 | { 165 | "Key": "Name", 166 | "Value": "subnet-5" 167 | } 168 | ], 169 | "AvailabilityZone": { 170 | "Fn::Select": [ 171 | "1", 172 | { 173 | "Fn::GetAZs": "" 174 | } 175 | ] 176 | } 177 | } 178 | }, 179 | "InternetGateway": { 180 | "Type": "AWS::EC2::InternetGateway", 181 | "Properties": { 182 | "Tags": [ 183 | { 184 | "Key": "Company", 185 | "Value": "Globomantics" 186 | } 187 | ] 188 | } 189 | }, 190 | "GatewayToInternet": { 191 | "Type": "AWS::EC2::VPCGatewayAttachment", 192 | "Properties": { 193 | "VpcId": { 194 | "Ref": "VPC" 195 | }, 196 | "InternetGatewayId": { 197 | "Ref": "InternetGateway" 198 | } 199 | } 200 | }, 201 | "PublicRouteTable": { 202 | "Type": "AWS::EC2::RouteTable", 203 | "Properties": { 204 | "VpcId": { 205 | "Ref": "VPC" 206 | }, 207 | "Tags": [ 208 | { 209 | "Key": "Company", 210 | "Value": "Globomantics" 211 | } 212 | ] 213 | } 214 | }, 215 | "PublicRoute": { 216 | "Type": "AWS::EC2::Route", 217 | "DependsOn": "GatewayToInternet", 218 | "Properties": { 219 | "RouteTableId": { 220 | "Ref": "PublicRouteTable" 221 | }, 222 | "DestinationCidrBlock": "0.0.0.0/0", 223 | "GatewayId": { 224 | "Ref": "InternetGateway" 225 | } 226 | } 227 | }, 228 | "PublicSubnetRouteTableAssociation1": { 229 | "Type": "AWS::EC2::SubnetRouteTableAssociation", 230 | "Properties": { 231 | "SubnetId": { 232 | "Ref": "PublicSubnet1" 233 | }, 234 | "RouteTableId": { 235 | "Ref": "PublicRouteTable" 236 | } 237 | } 238 | }, 239 | "PublicSubnetRouteTableAssociation2": { 240 | "Type": "AWS::EC2::SubnetRouteTableAssociation", 241 | "Properties": { 242 | "SubnetId": { 243 | "Ref": "PublicSubnet2" 244 | }, 245 | "RouteTableId": { 246 | "Ref": "PublicRouteTable" 247 | } 248 | } 249 | }, 250 | "PublicSubnetRouteTableAssociation3": { 251 | "Type": "AWS::EC2::SubnetRouteTableAssociation", 252 | "Properties": { 253 | "SubnetId": { 254 | "Ref": "PublicSubnet3" 255 | }, 256 | "RouteTableId": { 257 | "Ref": "PublicRouteTable" 258 | } 259 | } 260 | }, 261 | "PublicNetworkAcl": { 262 | "Type": "AWS::EC2::NetworkAcl", 263 | "Properties": { 264 | "VpcId": { 265 | "Ref": "VPC" 266 | }, 267 | "Tags": [ 268 | { 269 | "Key": "Company", 270 | "Value": "Globomantics" 271 | } 272 | ] 273 | } 274 | }, 275 | "OutboundPublicNetworkAclEntry": { 276 | "Type": "AWS::EC2::NetworkAclEntry", 277 | "Properties": { 278 | "NetworkAclId": { 279 | "Ref": "PublicNetworkAcl" 280 | }, 281 | "RuleNumber": "100", 282 | "Protocol": "-1", 283 | "RuleAction": "allow", 284 | "Egress": "true", 285 | "CidrBlock": "0.0.0.0/0" 286 | } 287 | }, 288 | "InboundPublicNetworkAclEntry": { 289 | "Type": "AWS::EC2::NetworkAclEntry", 290 | "Properties": { 291 | "NetworkAclId": { 292 | "Ref": "PublicNetworkAcl" 293 | }, 294 | "RuleNumber": "100", 295 | "Protocol": "-1", 296 | "RuleAction": "allow", 297 | "Egress": "false", 298 | "CidrBlock": "0.0.0.0/0" 299 | } 300 | }, 301 | "PublicSubnetNetworkAclAssociation1": { 302 | "Type": "AWS::EC2::SubnetNetworkAclAssociation", 303 | "Properties": { 304 | "SubnetId": { 305 | "Ref": "PublicSubnet1" 306 | }, 307 | "NetworkAclId": { 308 | "Ref": "PublicNetworkAcl" 309 | } 310 | } 311 | }, 312 | "PublicSubnetNetworkAclAssociation2": { 313 | "Type": "AWS::EC2::SubnetNetworkAclAssociation", 314 | "Properties": { 315 | "SubnetId": { 316 | "Ref": "PublicSubnet2" 317 | }, 318 | "NetworkAclId": { 319 | "Ref": "PublicNetworkAcl" 320 | } 321 | } 322 | }, 323 | "PublicSubnetNetworkAclAssociation3": { 324 | "Type": "AWS::EC2::SubnetNetworkAclAssociation", 325 | "Properties": { 326 | "SubnetId": { 327 | "Ref": "PublicSubnet3" 328 | }, 329 | "NetworkAclId": { 330 | "Ref": "PublicNetworkAcl" 331 | } 332 | } 333 | } 334 | }, 335 | "Outputs": { 336 | "VPCId": { 337 | "Description": "VPCId of the newly created VPC", 338 | "Value": { 339 | "Ref": "VPC" 340 | } 341 | } 342 | } 343 | } -------------------------------------------------------------------------------- /setup/stack-setup.sh: -------------------------------------------------------------------------------- 1 | # Have AWS CLI already install 2 | # Have Access Key and Secret Key ready 3 | # Recommend using us-east-1 by default 4 | aws configure 5 | 6 | # Create the CloudFormation stack for the basic VPC 7 | aws cloudformation create-stack --stack-name Globomantics --template-body file://basic-network.template --------------------------------------------------------------------------------