One of the first components I created on the AWS cloud was an Amazon Elastic Compute Cloud (Amazon EC2) instance by watching hands-on tutorials. Little did I know about the infrastructure bits that went behind that. In this note, I list the AWS infrastructure and the configurations I created to host an Amazon EC2 instance using Terraform. To make this use case interesting, I added the capability to access the internet from the Amazon EC2 instance. While trying to learn the underlying concepts, I came across numerous videos that demoed how to host an Amazon EC2 in AWS using the console. However, I was unsure how many of these approaches were secure or, said differently, had security as a top consideration. An Amazon EC2 instance is a virtual machine you host in a private cloud. I required a few infrastructure components before creating an Amazon EC2 instance in my AWS account. These were:

1. An Amazon Virtual Private Cloud (Amazon VPC). 2. A subnet in the VPC. 3. A route table in the VPC associated with the subnet. 4. An internet gateway in the VPC. 5. A route in the route table to allow network traffic from the Amazon EC2 instance to the internet. 6. A security group.

I stored the Terraform code associated with this project at GitHub: kunduso/ec2-userdata-terraform. As I listed above, I created a few infrastructure components before launching an Amazon EC2 instance in my AWS account. I’ll briefly mention these components and how and why they are necessary. Note: The best resource to study for AWS networking is the provision-an-amazon-ec2-instance-with-session-manager-access-using-terraform. That is my go-to resource for any clarifications. It could be exhausting to go through it, but it is worth it.

Pre-requisite: Please create a new Amazon EC2 key pair with pem format. You can find details at -create-key-pair. After creating the key, download the key to your local laptop. When you try to RDP into the Amazon EC2 instance, you will require this to generate the password. Also, please note that you will require the key-pair name in the Amazon EC2 resource block. In my GitHub repository, it is referred to as skundu-sandbox. Your key-pair name can be different.

Amazon VPC: This is the platform on which I hosted the entire infrastructure. This AWS resource requires the CIDR block (list of permissible IP addresses) to allocate to network interface resources. There is generally a tendency to allocate a large block(/16 or even /20), which is fine, but I prefer keeping it realistic, and hence I have it at “/25” which is 128 IP addresses, more than my current requirement. 53-image-1 Subnet: This is a section of the VPC CIDR block. A VPC CIDR block can be divided into subnets associated with CIDR blocks (IP addresses) that do not overlap. I created only one subnet (public) with 64 IP addresses and allocated a smaller CIDR block. The idea behind segregating IP addresses into separate subnets is to enable and disable communication. For, IP addresses in the “public subnet” could be accessible from the Internet (using the internet-gateway route rules in the associated route table), while the IP addresses in the “private subnet” would not be accessible from the Internet but from within the VPC or a VPN. The private subnet must be associated with a separate route table (than the public subnet). 53-image-2 Route table: This table with routes determines where network traffic flows from and within the VPC. 53-image-3 Route table association: Per AWS-Docs (and that’s because I couldn’t have explained better), “Your VPC has an implicit router, and you use route tables to control where network traffic is directed. Each subnet in your VPC must be associated with a route table, which controls the routing for the subnet (subnet route table). You can explicitly associate a subnet with a particular route table. Otherwise, the subnet is implicitly associated with the main route table. A subnet can only be associated with one route table at a time, but you can associate multiple subnets with the same subnet route table.” Since I am interested in provisioning EC2 in the public subnet, I associated that with the route table. 53.Image-5 Internet gateway: This Amazon VPC component allows communication between the VPC and the internet. It is a crucial piece of infrastructure when you want your Amazon EC2 instance to send and receive traffic from the internet. Additionally, the internet gateway is required if you want to connect or log in to the EC2 instance directly—for example, using RDP or SSH from your local machine. 53-image-5 If your goal is to connect securely to the instance without exposing it to the public internet, a more secure approach involves using AWS Systems Manager Session Manager. I’ve covered that method in detail in provision-an-amazon-ec2-instance-with-session-manager-access-using-terraform.

Route in the route table: This is an entry (row) in a route table with a destination IP address/CIDR and what target to use. In my terraform configuration, I added the below aws_route resource type to enable access to the internet (0.0.0.0/0) using the internet gateway I created earlier. 53.Image-7 Security Group: This is a virtual firewall for the Amazon EC2 to control inbound (ingress) and outbound (egress) traffic. I enabled RDP access (port# 3389) into the Amazon EC2 instance from my IP address in the code below. I also have the “egress” block, which is currently open to all, which implies that all kinds of outbound IPv4 traffic from the instance can flow. Please note that you must update the code below with your IP address range. I explain how to get that information in the GitHub repository. 53-image-7 And that brings us to the end of all the underlying infrastructure required to host the Amazon EC2. Regarding provisioning the Amazon EC2, two configuration blocks are necessary: (a) the data block to query an appropriate AMI and (b) a resource block to create the Amazon EC2. I added the code below to create an Amazon EC2 instance in the same subnet and associated the same key pair I created before starting work on this repository. Also, note that associate_public_ip_address = true is necessary if you intend to access the EC2 instance from your laptop. 53-image-8 Note: I faced an interesting challenge while trying to uniquely identify an AMI name and have a separate note at: create-ec2-instance-from-an-aws-ami-using-terraform.

After running terraform apply, I could log in to these Amazon EC2 instances and access the internet from there, which was my primary use case. If you are interested, you should be able to take this code and run it after making a few modifications.

Thank you for reading my note. If you believe I have misstated some things, please let me know via the comments. Also, please reach out if you have questions or suggestions.