Create an Amazon EC2 instance using Terraform with Session Manager access using VPC Endpoint

As a reader of this note, I believe you are familiar with Session Manager. Per AWS-Docs, Session Manager is a fully managed AWS Systems Manager capability that lets you manage your Amazon EC2 instances through an interactive one-click browser-based shell or through the AWS CLI.
For Session Manager to function, the Amazon VPC requires access to the internet using an attached internet gateway. The process has two steps: (i) create an Internet gateway and attach it to the VPC, and (ii) add a route to a route table in the VPC to 0.0.0.0/0 using the Internet gateway.

But how would an Amazon EC2 instance in a VPC connect with Session Manager if it does not have access to the internet due to security requirements? That is where VPC endpoints come in handy.

Note: There is a step-by-step guide on how to do this from the AWS console at ec2-systems-manager-vpc-endpoints.
Per AWS-Docs, a VPC endpoint enables customers to privately connect to supported AWS services and VPC endpoint services powered by AWS PrivateLink. Amazon VPC instances do not require public IP addresses to communicate with resources of the service. Traffic between an Amazon VPC and a service does not leave the Amazon network.
In this note, I list the steps to create an Amazon EC2 instance with Session Manager access that does not have access to the internet using Terraform. Previously, I worked on a similar use case where an internet gateway was available. Since I covered the IAM role and policy requirements applicable to this use case in that note, please read that to understand the required AWS-managed policy. You can read at  – provision-an-amazon-ec2-instance-with-session-manager-access-using-terraform.
If you are interested and want to follow along, I have the code in my GitHub repository: ec2-userdata-terraform. Please ensure you are on the right git branch  – `add-vpc-endpoint`.
Continuing from that note, there are five steps to the process:

Step 1: Enable DNS in the VPC
There are two DNS properties to enable inside the VPC code.
88-image-1
Step 2: Remove Internet gateway and route to the internet
Since I was building off a previous code base, I removed the code to create an Internet gateway and the route to the internet. You can ignore this step.
Effectively, I deleted the below commented-out code block.
88-image-2
Step 3: Create a Security group for the VPC endpoint
88-image-3
Using the code above, Terraform created a security group for the VPC endpoints with an ingress rule on port# 443 from the VPC’s CIDR block.
Step 4: Create VPC endpoints
Finally, I created three endpoints: one for ssm, ec2messages, and ssmmessages, each, and attached them to the correct security group and subnet.
88-image-4
Please note that I referred to the AWS subnet as private since there’s no route to the internet.
Step 5: Update the Amazon EC2 instance’s security group and instance property
88-image-5
Like the VPC endpoint security group’s ingress rule, the Amazon EC2 instance’s egress rule has the same properties.
The Amazon EC2 instance previously had the value associate_public_ip_address = true, which I set to associate_public_ip_address = false.
After updating the code, I ran terraform apply and provisioned all the resources appropriately. I reviewed the VPC on the AWS console and found no internet gateway. The route table associated with the subnet where the Amazon EC2 was hosted also did not have any route to the internet. I also reviewed the three VPC endpoints that were correctly provisioned.
88-image-6
And finally, I could connect to the Amazon EC2 instance using the AWS console.
88-image-7
If you have any questions or suggestions, please do not hesitate to use the comments section below.

Leave a comment