Improve security and simplify remote server access with AWS Session Manager

Using SSH

  1. you open an incoming port (by default 22) which becomes available to attackers and you have to harden it. Typically, we address this with the use of an SSH Bastion instance, a dedicated and hardened instance acting as an intermediary and offering indirect SSH connectivity to servers by using SSH forwarding.
  2. SSH Bastions need hardening and management and could become a single point of failure, if miss-configured.
  3. Regardless of network protection, SSH typically relies on ssh key pairs to protect from brute attacks on authentication credentials. However, rotating and managing this keys as the research I referenced earlier shows is a key risk. This in line with my own experiences. A month into a new job as a startup CTO, I found out that leavers could still access systems because their SSH public keys had not been removed and their home IP addresses were still in EC2 security groups.
  4. On AWS, you can’t rely on Cloud trail to audit or respond to unauthorized intrusions since CloudTrail only monitors AWS API calls.
  • Enable Traceability
  • Implement a strong identity foundation

Using SSM Session Manager

  1. No need to open any incoming ports on your instance
  2. No need for Bastion hosts or any other resources to manage.
  3. Connections are logged in CloudTrail, offering auditability, but also the ability to respond to intrusions via EventBridge events and your own rules.
  4. Sessions can be logged in S3 buckets or CloudWatch logs for troubleshooting purposes.
  5. No need for SSH keys; it uses standard AWS authentication and is subject to IAM policies.
  1. IAM Permissions for the EC2 role.
  2. SSM agent installed on your instance (in most cases already per-installed)

IAM Permissions

"Version": "2012-10-17",
"Statement": [
"Sid": "AllowSessionManagerSupportingPrequisites",
"Effect": "Allow",
"Action": [
"Resource": "*"
"Sid": "AllowSSMSessionManagerSessions",
"Effect": "Allow",
"Action": "ssm:StartSession",
"Resource": "arn:aws:ec2:*:*:instance/*"
"Sid": "AllowCurrentUserToResumeOrTerminateASession",
"Effect": "Allow",
"Action": [
"Resource": "arn:aws:ssm:*:*:session/${aws:username}-*"
"Sid": "SessionManagerPortForward",
"Effect": "Allow",
"Action": "ssm:StartSession",
"Sid": "SSHOverSessionManager",
"Effect": "Allow",
"Action": "ssm:StartSession",
"Resource": [

Instance Setup

  • Amazon Linux
  • Amazon Linux 2 (but not necessarily custom AMIs based on Amazon Linux that may have removed it, so always double check Amazon Linux2 custom AMIs)
  • Amazon Linux 2 ECS-Optimized Base AMIs
  • SUSE Linux Enterprise Server (SLES) 12 and 15
  • Ubuntu Server 16.04, 18.04, and 20.04

Setting up Networking Connectivity for Session Manager

sudo su - ec2-user
sudo su -

Routing SSH and SCP over SSM

# SSH over Session Manager
host i-* mi-*
ProxyCommand sh -c “aws ssm start-session — target %h — document-name AWS-StartSSHSession — parameters ‘portNumber=%p’”

Securing Session Manager implementations

  1. Logging Sessions could leak private data. Update your guidance to your staff to avoid use of Session Managers to display sensitive data. Save any session logs (but also CloudTrail trails) SSE Encrypted with your own Customer-Managed Key and secure Session logs at the same level as you would for sensitive data. Look at the use of the Amazon Comprehend API to search logs for Personal Data. The later is NOT a substitute for defensive security and could entail writing scripts similar to this AWS demo
  2. The ssm-user used by Session Manager for its interactive sessions is by default a privileged user. You can (and should) restrict what that user can do by restricting the commands available in a session and/or switching off its admin permissions depending on your requirements.
  3. Apply Lest Privilege to the IAM Role . The sample policy above gives the role access to create sessions on any instance. You should restrict that to the instances required. Use condition with tags to restrict it to a group of instances rather than individual instance if you want to reuse it rather than copy and paste. You can also further restrict — based on your use cases with conditions such region, caller IP, etc.
  4. Remove port forwarding permissions from the IAM policy if port forwarding is not needed.
  5. Apply the same principle at the network layer. In addition to the EC2 Instance Security Group, secure the VPCE with its own security group restricting incoming traffic and use the VPCE Policy to whitelist only roles that need access to these points. A good approach would be to have a security group for the VPCE with the allowed subnets as incoming and then use this Security Group in the outgoing rule of the EC2 instance Security Group. This way, you avoid duplicating values in two different places and both interfaces are protected.
  6. Take advantage of the Cloud Trail integration and create alarms and events to watch for intrusions.
  7. Automate all of these steps to avoid mis-configurations that could result to denial of service or accidental unauthorized access.




Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Why Golden is the future of knowledge

Bootcamp Mastery: Why Did I Choose Fullstack Academy in NYC?

Functional Data Structures and pattern matching in Scala

Conceal Desktop and Core Release v6.2.0

Linux VM based Setup for Android Automation

Few Spark Concepts :

The Death of the Non-Coding QA Role

The easiest way to load a CSV into Google BigQuery

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
John Sotiropoulos

John Sotiropoulos

More from Medium

Security by design for cloud secrets

Event-Driven serverless architecture to automatically remediate security findings

No BS guide to Enforcing Mandatory Tags for EC2 and EKS

AWS: New Look