Ditch SSH: Secure EC2 Access with AWS Systems Manager Session Manager
Opening port 22 on an EC2 instance is one of the most common attack vectors in cloud environments — bots continuously scan for exposed SSH ports, and a single misconfigured security group can become a critical breach point. AWS Systems Manager Session Manager eliminates this risk entirely by providing browser-based and CLI shell access to EC2 instances with zero open inbound ports, zero SSH keys, and full audit logging.
TL;DR
| Concern | Traditional SSH | SSM Session Manager |
|---|---|---|
| Inbound port required | Port 22 open | No inbound ports needed |
| Authentication | SSH key pairs | IAM identity & policies |
| Key management | Manual (rotate, distribute) | None — IAM handles it |
| Audit trail | None by default | Full session logs via CloudWatch / S3 |
| Access from browser | Not supported natively | Native AWS Console support |
| Bastion host needed | Often yes | No |
How It Works: The Architecture
Session Manager works through the SSM Agent installed on your EC2 instance. The agent initiates an outbound HTTPS connection (port 443) to the AWS Systems Manager service endpoint — meaning your instance calls out, not in. Your browser or CLI connects to SSM, and SSM proxies the session. No inbound firewall rules are required.
- User (Browser/CLI): Initiates a session via the AWS Console or
aws ssm start-sessionCLI command, authenticated via IAM. - AWS Systems Manager: Validates the IAM principal's permissions against the target instance resource.
- SSM Agent (on EC2): The agent, running on the instance, maintains a persistent outbound WebSocket connection over HTTPS (port 443) to the SSM service endpoint. SSM proxies the shell session through this channel.
- No inbound traffic: The EC2 security group requires no inbound rules — not even port 22.
- Session logs: All session activity is optionally streamed to CloudWatch Logs or an S3 bucket for compliance and auditing.
Analogy: Think of Session Manager like a corporate VPN reverse tunnel. Instead of the office (EC2) opening its front door (port 22) to the internet, the employee inside (SSM Agent) calls the corporate switchboard (SSM service) and says "I'm ready." When you need access, the switchboard connects you through that existing internal call — the front door never opens.
Prerequisites
Before you can use Session Manager, three conditions must be met on your EC2 instance:
- SSM Agent installed and running — Pre-installed on Amazon Linux 2, Amazon Linux 2023, and recent Windows Server AMIs. May need manual installation on Ubuntu or custom AMIs.
- IAM Instance Profile with SSM permissions — The EC2 instance must have an attached IAM role with the
AmazonSSMManagedInstanceCoremanaged policy. - Network connectivity to SSM endpoints — Either via a public NAT Gateway/Internet Gateway, or via VPC Interface Endpoints for fully private connectivity.
Step 1: Create the IAM Role for Your EC2 Instance
The instance needs an IAM role that allows it to communicate with the SSM service. The AWS-managed policy AmazonSSMManagedInstanceCore grants the minimum required permissions.
🔽 [Click to expand] — IAM Trust Policy & Role (AWS CLI)
# 1. Create the trust policy document
cat > ec2-trust-policy.json <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
# 2. Create the IAM role
aws iam create-role \
--role-name EC2-SSM-SessionManager-Role \
--assume-role-policy-document file://ec2-trust-policy.json
# 3. Attach the AWS managed policy for SSM core functionality
aws iam attach-role-policy \
--role-name EC2-SSM-SessionManager-Role \
--policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
# 4. Create an instance profile and attach the role
aws iam create-instance-profile \
--instance-profile-name EC2-SSM-InstanceProfile
aws iam add-role-to-instance-profile \
--instance-profile-name EC2-SSM-InstanceProfile \
--role-name EC2-SSM-SessionManager-Role
# 5. Attach the instance profile to your EC2 instance
aws ec2 associate-iam-instance-profile \
--instance-id i-0123456789abcdef0 \
--iam-instance-profile Name=EC2-SSM-InstanceProfile
Step 2: Verify the Security Group (No Port 22 Needed)
Your EC2 security group should have no inbound rules for SSH. The only network requirement is that the instance can reach SSM service endpoints outbound on port 443.
# Confirm no port 22 inbound rule exists — this should return empty
aws ec2 describe-security-groups \
--group-ids sg-0123456789abcdef0 \
--query "SecurityGroups[0].IpPermissions[?FromPort==\`22\`]"
If you are in a private subnet with no internet access, you must create VPC Interface Endpoints for the following services in your VPC:
com.amazonaws.us-east-1.ssmcom.amazonaws.us-east-1.ssmmessagescom.amazonaws.us-east-1.ec2messages
Step 3: Grant IAM Users/Roles Permission to Start Sessions
The operator (the human or role initiating the session) also needs IAM permissions. Apply least privilege by restricting access to specific instance IDs.
🔽 [Click to expand] — Least-Privilege IAM Policy for Session Operator
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowSSMSessionStart",
"Effect": "Allow",
"Action": [
"ssm:StartSession",
"ssm:DescribeSessions",
"ssm:GetConnectionStatus",
"ssm:DescribeInstanceProperties",
"ssm:DescribeInstanceInformation"
],
"Resource": [
"arn:aws:ec2:us-east-1:123456789012:instance/i-0123456789abcdef0",
"arn:aws:ssm:us-east-1:123456789012:session/${aws:username}-*"
]
},
{
"Sid": "AllowSessionTermination",
"Effect": "Allow",
"Action": "ssm:TerminateSession",
"Resource": "arn:aws:ssm:us-east-1:123456789012:session/${aws:username}-*"
}
]
}
Step 4: Connect — Browser & CLI
Option A: AWS Management Console (Browser)
- Navigate to AWS Systems Manager → Session Manager → Start Session.
- Select your target EC2 instance from the list (it will appear only if the SSM Agent is running and the instance profile is attached).
- Click Start Session. A browser-based terminal opens immediately.
Option B: AWS CLI
# Requires the Session Manager plugin for the AWS CLI
# Install: https://docs.aws.amazon.com/systems-manager/latest/userguide/session-manager-working-with-install-plugin.html
aws ssm start-session \
--target i-0123456789abcdef0 \
--region us-east-1
Option C: SSH Tunneling via Session Manager (Port Forwarding)
You can even tunnel SSH or local ports through Session Manager without opening port 22 — useful for tools that require native SSH.
# ~/.ssh/config entry to proxy SSH through SSM
Host i-* mi-*
ProxyCommand sh -c "aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'"
User ec2-user
IdentityFile ~/.ssh/your-key.pem
Note: This SSH-over-SSM approach still requires the key file locally, but the EC2 security group still needs no inbound port 22 — the tunnel is proxied through SSM's outbound channel.
Step 5: Enable Session Logging for Compliance
Session Manager can log all session activity. Configure this in Systems Manager → Session Manager → Preferences.
- Session starts via Console or CLI.
- All keystrokes and output are captured by the SSM service.
- Logs are streamed to CloudWatch Logs for real-time querying, and/or archived to an S3 bucket for long-term retention.
- CloudTrail records the
ssm:StartSessionAPI call, providing a full identity-level audit trail (who started the session, when, from which IP).
🔽 [Click to expand] — S3 Bucket Policy for Session Logs (Least Privilege)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "SSMSessionManagerLogs",
"Effect": "Allow",
"Principal": {
"Service": "ssm.amazonaws.com"
},
"Action": [
"s3:PutObject",
"s3:GetEncryptionConfiguration"
],
"Resource": [
"arn:aws:s3:::your-session-logs-bucket",
"arn:aws:s3:::your-session-logs-bucket/*"
]
}
]
}
Troubleshooting: Instance Not Appearing in Session Manager
| Symptom | Root Cause | Fix |
|---|---|---|
| Instance not listed | SSM Agent not running | Run sudo systemctl status amazon-ssm-agent and start it |
| Instance not listed | No IAM instance profile attached | Attach the role with AmazonSSMManagedInstanceCore |
| Instance not listed | No outbound HTTPS to SSM endpoints | Add NAT Gateway or create VPC Interface Endpoints |
| Session fails to start | Operator lacks IAM permissions | Attach ssm:StartSession policy to the operator's role |
Glossary
| Term | Definition |
|---|---|
| SSM Agent | A lightweight agent pre-installed on many AWS AMIs that communicates with the Systems Manager service over HTTPS. |
| Instance Profile | An IAM container that passes an IAM role's credentials to an EC2 instance at launch. |
| VPC Interface Endpoint | An AWS PrivateLink-powered endpoint that allows private subnet resources to reach AWS services without traversing the public internet. |
| Session Document | An SSM document (e.g., AWS-StartInteractiveCommand) that defines the type of session to initiate on the target instance. |
| AmazonSSMManagedInstanceCore | An AWS-managed IAM policy granting the minimum permissions an EC2 instance needs to be managed by Systems Manager. |
Next Steps
- 📖 Official AWS Session Manager Documentation
- 🔒 Enforce Session Manager as the only access method by using an SCP (Service Control Policy) to deny
ec2:AuthorizeSecurityGroupIngressfor port 22 across your AWS Organization. - 📊 Set up CloudWatch Alarms on Session Manager session start events via CloudTrail → EventBridge for real-time alerting on instance access.
Related Posts
- 📄 EC2 SSH Connection Timeout: The Exact Security Group Rules You Need to Fix It
- 📄 IAM User vs. IAM Role: Why Your EC2 Instance Should Never Use a User
- 📄 How to Attach or Replace an IAM Role on a Running EC2 Instance (No Restart Required)
- 📄 AWS IAM Policy Structure: Decoding Effect, Action, Resource, and Condition
Comments
Post a Comment