Securely Access Your EC2 Instances with AWS Systems Manager SSM and VPC Endpoints (2023)

Sunny Nazar for AWS Community Builders

Posted on • Updated on

Securely Access Your EC2 Instances with AWS Systems Manager SSM and VPC Endpoints (3) Securely Access Your EC2 Instances with AWS Systems Manager SSM and VPC Endpoints (4) Securely Access Your EC2 Instances with AWS Systems Manager SSM and VPC Endpoints (5) Securely Access Your EC2 Instances with AWS Systems Manager SSM and VPC Endpoints (6) Securely Access Your EC2 Instances with AWS Systems Manager SSM and VPC Endpoints (7)

#aws #ec2 #terraform #awscommunitybuilders

  • Overview
  • Background Knowledge
    • What is SSH-Less Login?
    • What is AWS Systems Manager (SSM)?
    • How to Use SSM for SSH-Less Login?
  • Terraform code
  • Documentation Links
  • Conclusion

Overview

As more and more organizations adopt cloud computing, managing resources on cloud platforms like Amazon Web Services (AWS) becomes increasingly important. The need to manage multiple instances of Amazon Elastic Compute Cloud (EC2) instances effectively has led to the development of various tools to simplify the process. One such tool is the AWS Systems Manager (SSM), which enables users to manage EC2 instances, as well as other AWS resources, using a single interface. One of the most powerful features of SSM is the ability to perform SSH-less login to EC2 machines, which we will explore in this blog.

Background Knowledge

What is SSH-Less Login?

Traditionally, logging into an EC2 instance involves connecting via SSH with a username and password or a key pair. However, managing SSH keys can be challenging, particularly when dealing with multiple EC2 instances. SSH-Less login, on the other hand, is a secure and more efficient method of accessing EC2 instances without requiring SSH keys.

What is AWS Systems Manager (SSM)?

AWS Systems Manager (SSM) is a management service that enables users to automate the management of their EC2 instances and other AWS resources. SSM enables users to perform various tasks, including software installation, patching, and maintenance across a fleet of EC2 instances. It also provides a single interface to manage EC2 instances running in different regions and accounts.

How to Use SSM for SSH-Less Login?

To use SSM for SSH-less login, follow the steps below:

Security Group for EC2 Instance: The minimum traffic you need to allow for SSM access to work is to add an Outbound HTTPS (port 443) in the security group for EC2 instance.

Create an IAM Role: To use SSM to log in to EC2 instances, you must first create an IAM role with the required permissions. The role must have the AmazonEC2RoleforSSM policy attached to it, which allows SSM to access the EC2 instances.

Install SSM Agent: After creating the IAM role, you need to install the SSM agent on each EC2 instance you want to access using SSM. The SSM agent is pre-installed on Amazon Linux 2 and Amazon Linux AMIs, but you must install it manually on other instances.

Configure EC2 Instances: Once the SSM agent is installed, you need to configure your EC2 instances to allow SSM access. You can do this by creating a VPC endpoint for SSM. VPC endpoints which are required when using Private Subnets are below:

  1. com.amazonaws.region.ec2messages
  2. com.amazonaws.region.ssmmessages
  3. com.amazonaws.region.ssm
  4. com.amazonaws.region.kms (This is needed if you want to use AWS KMS encryption for Session Manager.)

Note:The security group for VPC Endpoints must allow inbound HTTPS (port 443) traffic from the resources in your VPC that communicate with the service.

Terraform code

  • Let's first start with creating VPC, Public Subnet, Private Subnet, Internet Gateway, Nat Gateway and Route tables.

Prerequisite - Create provider configuration.

terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 4.60.0" } }}provider "aws" { region = var.region}

  • Variable definition can be done like this:
# Please set variable region as per your needs.variable "region" { type = string description = "Region for the resource deployment" default = "eu-central-1"}

# Create a VPCresource "aws_vpc" "vpc" { cidr_block = "10.0.0.0/16" tags = { Name = "vpc-${var.region}" }}# Create an internet gatewayresource "aws_internet_gateway" "gw" { vpc_id = aws_vpc.vpc.id tags = { Name = "igw-${var.region}" }}# Create a public subnetresource "aws_subnet" "public_subnet" { vpc_id = aws_vpc.vpc.id cidr_block = "10.0.1.0/24" availability_zone = "${var.region}a" tags = { Name = "Public Subnet" }}# Create a private subnetresource "aws_subnet" "private_subnet" { vpc_id = aws_vpc.vpc.id cidr_block = "10.0.2.0/24" availability_zone = "${var.region}a" tags = { Name = "Private Subnet" }}# Create a NAT gatewayresource "aws_nat_gateway" "nat_gateway" { allocation_id = aws_eip.nat_eip.id subnet_id = aws_subnet.public_subnet.id tags = { Name = "ngw-${var.region}" }}# Create an EIP for the NAT gatewayresource "aws_eip" "nat_eip" { vpc = true}# Create a public route table and associate it with the public subnetresource "aws_route_table" "public_route_table" { vpc_id = aws_vpc.vpc.id route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.gw.id } tags = { Name = "Public route table" }}resource "aws_route_table_association" "public_route_table_association" { subnet_id = aws_subnet.public_subnet.id route_table_id = aws_route_table.public_route_table.id}# Create a private route table and associate it with the private subnetresource "aws_route_table" "private_route_table" { vpc_id = aws_vpc.vpc.id route { cidr_block = "0.0.0.0/0" nat_gateway_id = aws_nat_gateway.nat_gateway.id } tags = { Name = "Private route table" }}resource "aws_route_table_association" "private_route_table_association" { subnet_id = aws_subnet.private_subnet.id route_table_id = aws_route_table.private_route_table.id}

  • Let's now create EC2 and Endpoint Security Group
# Create a security group for the EC2 instanceresource "aws_security_group" "instance_security_group" { name_prefix = "instance-sg" vpc_id = aws_vpc.vpc.id description = "security group for the EC2 instance" # Allow outbound HTTPS traffic egress { from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] description = "Allow HTTPS outbound traffic" } tags = { Name = "EC2 Instance security group" }}# Security group for VPC Endpointsresource "aws_security_group" "vpc_endpoint_security_group" { name_prefix = "vpc-endpoint-sg" vpc_id = aws_vpc.vpc.id description = "security group for VPC Endpoints" # Allow inbound HTTPS traffic ingress { from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = [aws_vpc.vpc.cidr_block] description = "Allow HTTPS traffic from VPC" } tags = { Name = "VPC Endpoint security group" }}

  • Now we can create VPC Endpoints
locals { endpoints = { "endpoint-ssm" = { name = "ssm" }, "endpoint-ssmm-essages" = { name = "ssmmessages" }, "endpoint-ec2-messages" = { name = "ec2messages" } }}resource "aws_vpc_endpoint" "endpoints" { vpc_id = aws_vpc.vpc.id for_each = local.endpoints vpc_endpoint_type = "Interface" service_name = "com.amazonaws.${var.region}.${each.value.name}" # Add a security group to the VPC endpoint security_group_ids = [aws_security_group.vpc_endpoint_security_group.id]}

  • After creating endpoints, the final components are Instance profile and EC2 instance.
# Create IAM role for EC2 instanceresource "aws_iam_role" "ec2_role" { name = "EC2_SSM_Role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Principal = { Service = "ec2.amazonaws.com" } Action = "sts:AssumeRole" } ] })}# Attach AmazonSSMManagedInstanceCore policy to the IAM roleresource "aws_iam_role_policy_attachment" "ec2_role_policy" { policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" role = aws_iam_role.ec2_role.name}# Create an instance profile for the EC2 instance and associate the IAM roleresource "aws_iam_instance_profile" "ec2_instance_profile" { name = "EC2_SSM_Instance_Profile" roles = [aws_iam_role.ec2_role.name]}data "aws_ami" "amazon_linux_2_ssm" { most_recent = true filter { name = "owner-alias" values = ["amazon"] } filter { name = "name" values = ["amzn2-ami-hvm-*-x86_64-ebs"] }}# Create EC2 instanceresource "aws_instance" "ec2_instance" { ami = data.aws_ami.amazon_linux_2_ssm.id instance_type = "t2.micro" subnet_id = aws_subnet.private_subnet.id vpc_security_group_ids = [ aws_security_group.instance_security_group.id, ] iam_instance_profile = aws_iam_instance_profile.ec2_instance_profile.name}

Access EC2 Instance using SSM: After completing the above steps, you can access your EC2 instances using SSM without requiring an SSH key. To do this, navigate to the EC2 console and select the instance you want to access. Then, click on the "Connect" button and select "Session Manager" from the dropdown menu. This will open a web-based shell that allows you to interact with the instances.

Documentation Links

Conclusion

Using SSM for SSH-less login provides a secure and efficient way to manage multiple EC2 instances without the need for managing SSH keys. SSM makes it easy to perform tasks like software installation, patching, and maintenance across a fleet of EC2 instances using a single interface. With the steps outlined above, you can easily set up SSH-less login for your EC2 instances and enjoy the benefits of streamlined instance management.

Top Articles
Latest Posts
Article information

Author: Prof. An Powlowski

Last Updated: 10/12/2023

Views: 5738

Rating: 4.3 / 5 (64 voted)

Reviews: 87% of readers found this page helpful

Author information

Name: Prof. An Powlowski

Birthday: 1992-09-29

Address: Apt. 994 8891 Orval Hill, Brittnyburgh, AZ 41023-0398

Phone: +26417467956738

Job: District Marketing Strategist

Hobby: Embroidery, Bodybuilding, Motor sports, Amateur radio, Wood carving, Whittling, Air sports

Introduction: My name is Prof. An Powlowski, I am a charming, helpful, attractive, good, graceful, thoughtful, vast person who loves writing and wants to share my knowledge and understanding with you.