Zin Moe / Projects← All projects
AWS · Terraform · Secure access

Private EC2 access with AWS Systems Manager

A hands-on infrastructure lab for reaching EC2 instances in private subnets through Session Manager and VPC interface endpoints, without public instance IPs, a bastion host, or a NAT Gateway.

3EC2 instances
3Private subnets
3Interface endpoints
443Outbound HTTPS port

Architecture

The Terraform code builds a VPC in ap-southeast-1, with three private route tables and an EC2 instance in each subnet. The instances have no public IP addresses. IAM instance profiles grant Systems Manager permissions, while private DNS resolves SSM service names to VPC endpoints.

Repository architecture diagram showing IAM, private EC2 instances, SSM agents, VPC endpoints, and a Session Manager client
Architecture diagram from the GitLab repository. Select to open at full size.

How the lab is built

  1. Define the VPC and subnets

    Create a 10.0.0.0/16 VPC with DNS support, three subnets in separate availability zones, and route tables without an internet route.

  2. Launch private instances

    Use an Ubuntu 24.04 AMI, explicitly disable public IP assignment for each EC2 instance, and attach a dedicated security group.

  3. Assign IAM permissions

    Attach the AWS managed AmazonSSMManagedInstanceCore policy to an EC2 role through an instance profile.

  4. Create interface endpoints

    Provision ssm, ssmmessages, and ec2messages endpoints in all three subnets, with private DNS enabled.

  5. Limit network access

    Permit outbound HTTPS from instances to the endpoint security group; the endpoint group accepts TCP 443 from the VPC CIDR. No inbound SSH rule is defined for instances.

  6. Connect and verify

    Start a Session Manager session by instance ID, then inspect the agent process and established HTTPS connections.

Connection and evidence

The repository includes terminal captures showing a Session Manager session on an instance and the AWS CLI process on the operator's host.

aws ssm start-session --target <instance-id> --profile ssm_access
Terminal capture of an SSM session with the agent process and established HTTPS connections
Inside the instance: session worker and HTTPS connections.
Operator terminal showing the AWS CLI Session Manager process and HTTPS connections
Operator host: AWS CLI session and network connections.

Repository notes

The Terraform files define three instances and subnets, though the README overview says two. The subnet resources also set map_public_ip_on_launch = true; each defined EC2 instance separately sets associate_public_ip_address = false. Align those settings before reusing this as a general private subnet template.

Based on the aws_ssm folder in the GitLab repository. Configuration and evidence describe this lab, not a continuously running environment.