Secure, Auditable EC2 Shell Access with AWS Systems Manager Session Manager
Eliminate SSH and bastion hosts by routing shell sessions through Session Manager. This guide walks you through the prerequisites, configuration, validation, and recovery steps for secure, audit‑ready EC2 access.
13 Oct 2025, 11:44 UTC

Desired Outcome
Replace traditional SSH access with a fully managed, IAM‑controlled, audit‑ready shell session that requires no inbound ports, bastion hosts, or SSH keys. The session should be encrypted in transit, logged to CloudWatch Logs or S3, and accessible only to principals with the appropriate IAM permissions.
Prerequisites
- EC2 instance running a supported AMI (Amazon Linux 2, Ubuntu 20.04+, Windows 2019+). The SSM agent is preinstalled on these images.
- Instance profile attached to the EC2 instance with the
AmazonSSMManagedInstanceCoremanaged policy (or an equivalent custom policy grantingssm:DescribeInstanceInformation,ssm:StartSession, andssm:SendCommand). - Outbound HTTPS connectivity to the Systems Manager endpoints. In a private subnet, this can be achieved via a NAT gateway or interface VPC endpoints for
ssmandssmmessages. - IAM user or role that will initiate sessions must have the
ssm:StartSessionpermission for the target instance (or for all instances in the account). A common practice is to grantssm:StartSessiononarn:aws:ssm:*:*:instance/*. - Optional: KMS key for session data encryption and a CloudWatch Logs group or S3 bucket for session recording. If omitted, session data is encrypted in transit only.
Focused Procedure
- Attach the IAM Instance Profile
- In the EC2 console, select the instance, choose Actions > Security > Modify IAM role, and attach the role that contains
AmazonSSMManagedInstanceCore. - Or, via CLI:
aws ec2 associate-iam-instance-profile \ --instance-id i-0123456789abcdef0 \ --iam-instance-profile Name=my-ssm-role
- In the EC2 console, select the instance, choose Actions > Security > Modify IAM role, and attach the role that contains
- Verify SSM Agent Health
- SSH into the instance (if temporary) or use the EC2 serial console to run:
systemctl status amazon-ssm-agent - Ensure the service is active. If not, start it:
sudo systemctl start amazon-ssm-agent
- SSH into the instance (if temporary) or use the EC2 serial console to run:
- Confirm Instance Appears Online
- Run:
aws ssm describe-instance-information --query "InstanceInformationList[?InstanceId=='i-0123456789abcdef0'].PingStatus" --output text - The output should be
Online. IfOffline, check networking and IAM role.
- Run:
- Start a Session
- From the AWS CLI (with appropriate IAM permissions):
aws ssm start-session --target i-0123456789abcdef0 - Alternatively, in the console: select the instance, click Connect and choose Session Manager.
- From the AWS CLI (with appropriate IAM permissions):
- Enable Session Recording (Optional but Recommended)
- In the Session Manager preferences, enable
Send session data to CloudWatch LogsorS3. Provide a KMS key if you want encrypted logs. - Verify that the log group
/aws/ssm/SessionManageror the specified S3 bucket receives entries when you run a command.
- In the Session Manager preferences, enable
- Remove SSH Inbound Rules (Proof of Concept)
- Delete any
22/tcprule from the instance’s security group. - Attempt the
aws ssm start-sessioncommand again to confirm access is still functional.
- Delete any
Expected Checks
- Instance Status:
describe-instance-informationreturnsOnline. - Session Initiation: The CLI returns a JSON object with a
SessionIdand the shell prompt appears without needing port 22. - Audit Trail: CloudWatch Logs contain entries with the session ID, user ARN, and command output. If using S3, the bucket contains a
session-logs/prefix with the session data. - Network Isolation: Security group no longer allows inbound SSH, yet the session remains operational.
Recovery Options
- SSM Agent Unreachable
- Check the agent’s logs (e.g.,
/var/log/amazon/ssm/amazon-ssm-agent.log) for connectivity errors. - If the instance is in a subnet without NAT or VPC endpoints, add an interface endpoint for
ssmandssmmessagesor deploy a NAT gateway. - Restart the agent:
sudo systemctl restart amazon-ssm-agent.
- Check the agent’s logs (e.g.,
- IAM Permission Issues
- Ensure the instance profile contains
AmazonSSMManagedInstanceCoreand the initiating principal hasssm:StartSession. - Detach and reattach the instance profile if changes are made.
- Ensure the instance profile contains
- Instance Offline in Fleet Manager
- Use the EC2 Serial Console (if enabled) to access the instance directly.
- Alternatively, launch a temporary instance in the same subnet, attach the same IAM role, and use
aws ssm start-sessionon the temporary instance to run commands on the offline instance viassm:SendCommand.
Limitations & Practical Checks
- Session Manager requires outbound HTTPS. Verify that the instance’s network ACLs and security groups allow egress to
*.ssm.amazonaws.comon port 443. - Agent version matters: older agents (<1.0.2100) do not support port forwarding or KMS encryption. Run
amazon-ssm-agent -versionto confirm. - Windows instances need the
AmazonSSMManagedInstanceCorerole and the SSM agent must be running as a Windows service. - Audit logs are only as reliable as the CloudWatch Logs or S3 bucket retention settings. Verify retention policies.
- If the instance is in a very small subnet with no NAT or VPC endpoints, consider using the
aws ssm start-session --document-name AWS-StartInteractiveCommandwith--parametersto run commands without full shell access.
Conclusion
By following the steps above, you can securely expose an EC2 shell without opening inbound ports or managing SSH keys. Session Manager provides IAM‑based access control, optional encryption of session data, and built‑in audit logging, making it a robust replacement for traditional bastion‑host setups.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.