AWS Session Manager: Securing Access to Cloud Resources

Syed Hasan
7 min readJun 21, 2022

Managing resources on the cloud — with both security and scalability at mind— can quickly get out of hands. Luckily, AWS released the Systems Manager which is a collection of tools or functions which can help us manage assets in the cloud while minimizing the time and efforts required to resolve operational problems within them. A tool within this suite is the Session Manager.

Session Manager allows secure access to instances in the AWS cloud or on-premise infrastructure (via AWS PrivateLink) without leaving the browser (or your CLI). Using the service, we can easily launch a one-click in-browser shell and run (virtually) a large subset of commands in the bash shell. Neither do you have to allow inbound ports to your infrastructure, nor do keys need to be managed — it’s all handled by the Session Manager.

Limited security exposure, session auditing and logging, and ease of node management — sign me up!

Getting Started with Session Manager

Session Manager or any other tool from the Systems Manager suite isn’t readily able to access any instance. An agent needs to be installed on the endpoints, permissions need to be assigned to roles, instance profiles need to be created, and only then can you go ahead and start sessions on your instances.

Creating an IAM Role

Systems Manager doesn’t have permissions, by default, to perform actions on instances. AWS requires explicit assignment of permissions to the instance which needs to be managed by the Systems Manager. As such, you can either create an entirely new role or add permissions for access to the Systems Manager to an existing role (and later assign it to your EC2 instance via an Instance Profile).

Here, I’ll create a new role with necessary permissions for Session Manager and Amazon S3 (I’ll cover the ‘why’ later):

Note: You need to create a new customer-managed key via KMS and update the key-name value (in the kms:Decrypt permission) to the ARN of the CMK. You also need to create a new bucket in S3 and update the Resource value of the S3 permissions to include the ARN of the bucket. Here’s how my resource fields look:

  • arn:aws:s3:::myssmauditingbucket/prod-account/*
  • arn:aws:kms:us-east-1:{ID}:key/6ad11c3c-ec08–403c-82d5–97c1d8b8a764

The role needs to be created for the EC2 service (select AWS Service under Trusted Entity and EC2 under use-cases) for it to be used as an Instance Profile.

Role Creation via IAM

What’s significant about these permissions? There’s three sets of permissions here:

  • ssmmessages refers to the Session Manager Message Gateway Service which is primarily tasked with the creation and management of data/control channels which connect an instance to the Systems Manager service
  • kms is used for encryption of session data (which is optional but recommended)
  • s3 is used for logging session data from a session to the specific S3 bucket (more on this soon)

Here’s a guide from AWS on creation of an IAM service role for on-premise or hybrid environments.

Creating or Assigning an Instance Profile

Instance profiles are practically just roles which are applicable to EC2 instances to assign them permissions to access other services in the AWS cloud. Let’s assign our newly created role to an instance.

If you’re creating a new instance, you’ll find the setting under the Advanced Details tab. If it’s already launched, you can Modify the IAM Role by selecting your instance, going to Actions, and changing the settings under the Security tab.

Assignment of Instance Profile

Starting Sessions

All done? Let’s spin up a few sessions. You can do so in several ways (documented here). I’ll simply head over to my EC2 console, press Connect, and select Session Manager. Press Connect and that should be it!

Starting Sessions via the Session Manager

Here’s how my in-browser shell looks like:

A Sample Session from the Session Manager

Similarly, I can start a session using the AWS CLI. Create a user with programmatic access, configure the profile, and then issue the following command:

aws ssm start-session --target {InstanceID} --profile {default}

Session Started via the AWS CLI

Configuring Session Manager

Well, that’s all out-of-the-box work with little to no extra configuration. If you’ve worked with SSM before, exposing it to anyone can also pose a security risk in itself. It’s why you need to configure and restrict access to the service. These could include modifying permissions or settings like:

  • Session timeouts and maximum duration
  • Encrypting sessions
  • Denying permission to certain users

Here’s where System Manager Documents come into play. These documents hold region-specific preferences for an AWS account. However, explicit permissions must be assigned to update these documents. Just as we explored the Gateway Services’ permissions before, the following permissions are assigned to users for managing SSM documents:

  • CreateDocument
  • GetDocument
  • UpdateDocument
  • DeleteDocument

By default, a document is created in the region from which the service is accessed. It’s a boilerplate document with the same configurations as set in the Preferences of the Systems Manager. Here’s an example with Cloudwatch configured for streaming:

SSM-SessionManagerRunShell Default SSM Document

Again, you might want to restrict a particular user to be able to update a particular resource (or SSM document in this case). You can restrict these permissions in your IAM policy to the SSM document resource (e.g. SSM-SessionManagerRunShell). Here’s an example from AWS:

{ “Action”: [ “ssm:CreateDocument”, “ssm:GetDocument”, “ssm:UpdateDocument”, “ssm:DeleteDocument” ], “Effect”: “Allow”, “Resource”: [ “arn:aws:ssm:us-east-2:123456789012:document/SSM-SessionManagerRunShell” ] }

The SSM Document captures all these configurations via a simple JSON file. Here’s how a sample document looks:

You can even specify the usage of these documents as part of your IAM policies. Here’s an example of me explicitly requesting the usage of the my-sesh-doc document as part of all session creations on the specified instance (from the user to which this policy will be assigned):

IAM Policy to Restrict SSM Usage

To configure Session Timeouts or Maximum Durations from the console — you can head over to Systems Manager, open up Preferences for Session Manager and edit out the fields. Similarly, encryption of session data can be enabled by selecting a symmetric encryption key from KMS.

Configuring the SSM Service

Restricting Commands

Custom session documents can be used to permit a set of commands as part of an interactive session as well. Using the InteractiveCommands session type document, we can restrict a session to a particular set of commands (ping here).

InteractiveCommands Session Type Document

Here’s how enforcement looks when it’s run via the CLI (paired with the IAM policy shared above):

Launching an Interactive Session with Custom Documents

Auditing and Logging Sessions

Session activity can be audited using CloudTrail. This includes calls like a connection or session start, document delete and all other calls made to/from an instance and the Systems Manager service. Depending on your use-case, there’s a lot of potential on automating anomalies and monitoring of suspicious API calls.

Session History is also maintained under Session History in the Session Manager console (under Systems Manager service. Session termination is also possible from the Sessions tab — depending on your permissions.

Sessions and Session History

Logging Sessions

Sessions can also be logged or streamed to Amazon S3 or CloudWatch Logs.

Logging vs. streaming — which one should you prefer?

  • Streaming allows you to continuously receive commands from all active sessions in a JSON format — for forwarding to EventBridge, monitoring, or generating alarms based on custom needs. It is currently only possible via CloudWatch
  • Session data can only be logged or uploaded at the very end of the session. There’s no continuous stream of messages. This is better suited for archiving. It is possible via both CloudWatch and S3.

For this blog, I chose S3 to log all my session data (as I previously discussed — permissions for S3 are required to log data to the specified bucket). To enable either of the two settings:

  1. Open up Systems Manager
  2. Head to Session Manager
  3. Open up Preferences
  4. Select either of the two — CloudWatch logging or S3 logging
  5. Enable S3 logging and configure the bucket name and prefix (optional)
Configuring S3 logging for SSM

Let’s connect to the instance via SSM again and see if the session data is logged to S3. After launching and terminating an instance, here’s a file in our S3 bucket:

S3 Bucket with Session Log file

Open it up and voila — all our session data was logged:

Contents of the Session Log file

Mind you — session data includes both the input and output. Sensitive data, if input with these configurations, will be logged in the session data!

What’s Next?

Session Manager can save countless hours of security teams trying to limit exposure from sensitive ports for login. Review your environment — is Session Manager the need of the hour? Will it serve any purpose? Can auditing and logging be enabled (if already using it) without risks? Get to work! 🚀



Syed Hasan

Hi, I’m Syed. Explore my articles as I embark on this journey of learning more about Forensics and Cloud! 🚀