AWS Cloud Operations Blog

Automated configuration of Session Manager without an internet gateway

Session Manager is a fully managed AWS Systems Manager capability that you can use to manage your Amazon Elastic Compute Cloud (Amazon EC2) instances, on-premises instances, and virtual machines (VMs) through an interactive one-click browser-based shell or through the AWS CLI. Session Manager also provides secure and auditable instance management without the need to open inbound ports, maintain bastion hosts, or manage SSH keys. This results in cost savings because it reduces management overhead, centralizes access control by using AWS Identity and Access Management (IAM) policies, and enhances operational security by logging and auditing session activity.


This post describes how, with AWS Systems Manager support for AWS PrivateLink, you can further reduce the attack surface by using virtual private cloud (VPC) endpoints instead of an internet gateway, NAT gateway, or proxy server. This is especially useful for public sector customers, customers in highly regulated industries, or customers who might be forbidden from using internet gateways or required to use cloud access point (CAP) connections.

In addition to Knowledge Center resolutions about SSH tunnels and manual configuration of this solution in the AWS Management Console, there is an AWS CloudFormation template available on GitHub that automates its deployment. The architecture of the solution is illustrated in Figure 1.

Architecture diagram for Automated configuration of Session Manager without an internet gateway. An EC2 instance in a VPC with VPC endpoints that route to AWS Systems Manager, Amazon Session Manager Message Gateway Service, and Amazon Message Delivery Service.

Figure 1. Architecture Diagram

Choosing an AMI ID

Session Manager requires use of the SSM Agent. You can either install the SSM Agent on the EC2 instance, or use an Amazon Machine Image (AMI) that already includes the SSM Agent, such as the Amazon Linux 2 AMI. You can query for the latest AMI ID of Amazon Linux 2 using Systems Manager Parameter Store:

Parameters:
  pLatestAmiId:
    Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2

You can use the AMI ID returned from AWS Systems Manager Parameter Store in the ImageId property when you create the EC2 instance. This ensures you’re using the latest version of the AMI, but it doesn’t require you to update the AWS CloudFormation template as new versions of the AMI are released. It also simplifies multi-Region deployments by eliminating the need for mappings between AWS Regions and AMI IDs.

Select an EC2 instance type available in your AWS Region. You don’t need to configure an EC2 key pair to connect to the EC2 instance using Session Manager. See the following code:

  rEc2Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref pLatestAmiId
      InstanceType: !Ref pInstanceType
      SubnetId: !Ref rPrivateSubnet
      IamInstanceProfile: !Ref rEc2InstanceProfile 
      SecurityGroupIds:
        - !Ref rSecurityGroupEc2Instance

IAM instance profile for EC2 instance

In the preceding AWS::EC2::Instance resource, the IamInstanceProfile property is set. To use Session Manager, the EC2 instance you want to connect to must include an IAM instance profile with Session Manager permissions. This instance profile must have a trust relationship to Amazon EC2 and include the permissions granted by the managed AmazonSSMManagedInstanceCore policy.

By using pseudo parameters, you can parameterize the AWS CloudFormation template to work in multiple AWS Regions and partitions. For example, you can run the same AWS CloudFormation template in US East (N. Virginia) and AWS GovCloud (US-West) Regions.

See the following code:

  rEc2InstanceProfile: 
    Type: AWS::IAM::InstanceProfile
    Properties: 
      Path: /
      Roles: 
        - !Ref rEc2InstanceRole
  rEc2InstanceRole: 
    Type: AWS::IAM::Role
    Properties: 
      AssumeRolePolicyDocument: 
        Version: 2012-10-17
        Statement: 
          - 
            Effect: Allow
            Principal: 
              Service: 
                - ec2.amazonaws.com
            Action: 
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        # The managed IAM policy AmazonSSMManagedInstanceCore grants access to Session Manager
        - !Sub arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore

VPC endpoints

EC2 instances in the VPC need a route to Systems Manager, Session Manager Message Gateway Service, and Message Delivery Service. Without an internet gateway, this requires a VPC endpoint for each of the three required services (ssm, ssmmessages, and ec2messages). This solution works only in AWS Regions that offer these three VPC endpoints. Otherwise, you must use an internet gateway or select a different AWS Region. The following code has the resources required to create these VPC endpoints and associate them with the VPC, subnet, and security group:

  rSsmVpcEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ssm
      VpcId: !Ref rVpc
      SubnetIds:
        - !Ref rPrivateSubnet
      SecurityGroupIds:
        - !Ref rSecurityGroupVpcEndpoint
      VpcEndpointType: Interface
      PrivateDnsEnabled: True
  rSsmMessagesVpcEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ssmmessages
      VpcId: !Ref rVpc
      SubnetIds:
        - !Ref rPrivateSubnet
      SecurityGroupIds:
        - !Ref rSecurityGroupVpcEndpoint
      VpcEndpointType: Interface
      PrivateDnsEnabled: True
  rEc2MessagesVpcEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub com.amazonaws.${AWS::Region}.ec2messages
      VpcId: !Ref rVpc
      SubnetIds:
        - !Ref rPrivateSubnet
      SecurityGroupIds:
        - !Ref rSecurityGroupVpcEndpoint
      VpcEndpointType: Interface
      PrivateDnsEnabled: True

Security groups

An inspection of the security groups reveals how Session Manager reduces the attack surface. You might be accustomed to bastion hosts that require TCP port 22 to be opened for SSH access or TCP port 3389 to be opened for RDP access. In the following code, the security group attached to the EC2 instance has no inbound rules, but we can connect to the instance through Session Manager. This is because the connection originates outbound through the SSM Agent as opposed to originating inbound through TCP port 22 or 3389, and security group rules are stateful. This is important because it eliminates a common entry point for bad actors. The outbound connections are routed through the VPC endpoint over TCP port 443. Furthermore, access to the VPC endpoint is limited to the security group associated with the EC2 instance.

  rSecurityGroupEc2Instance:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: SG for EC2 Instance
      VpcId: !Ref rVpc
      # Despite this security group containing no ingress rules, Session 
      # Manager can still provide shell access 
      SecurityGroupEgress:
      # The SSM Agent connects to Session Manager over TCP 443
      - Description: allow outbound HTTPS to the VPC
        CidrIp: !Ref pCidr 
        FromPort: 443
        ToPort: 443
        IpProtocol: tcp
  rSecurityGroupVpcEndpoint:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: SG for VPC Endpoints
      VpcId: !Ref rVpc
      SecurityGroupIngress:
      # The SSM Agent connects to Session Manager over TCP 443
      - Description: allow inbound HTTPS from the EC2 instance
        SourceSecurityGroupId: !Ref rSecurityGroupEc2Instance
        FromPort: 443
        ToPort: 443
        IpProtocol: tcp
      SecurityGroupEgress:
      # The SSM Agent connects to Session Manager over TCP 443
      - Description: allow outbound HTTPS to the VPC
        CidrIp: !Ref pCidr 
        FromPort: 443
        ToPort: 443
        IpProtocol: tcp

Tunneling RDP traffic using Session Manager

If you require UI access to EC2 instances, you can use Session Manager to redirect traffic from any port inside a remote EC2 instance or on-premises instance to a local port on a client machine. This is especially useful for Remote Desktop access to Windows instances and does not require an internet gateway. For more information, see Now forward traffic between a local and remote port using Session Manager.

Integrating AWS Transit Gateway with AWS PrivateLink and Amazon Route 53 Resolver

To reduce the number of VPC endpoints, simplify VPC endpoint deployment, and help cost-optimize when deploying at scale, consider using AWS Transit Gateway with Amazon Route 53 Resolver to share AWS PrivateLink interface endpoints between multiple connected VPCs and on-premises environments. This way, multiple VPCs across multiple accounts can share a secure, scalable, cost-efficient connection that doesn’t traverse the internet. For more information, see Integrating AWS Transit Gateway with AWS PrivateLink and Amazon Route 53 Resolver.

Summary

You can use AWS PrivateLink and Session Manager for shell access and UI access without the use of an internet gateway. Deploy this solution today to improve security posture, provide cost savings, and enable access for users who are restricted from using internet gateways. The code is open source: join us on GitHub to contribute!

About the author

Brian Landry is a Senior Consultant at AWS working out of San Diego, CA. He enjoys traveling, attending sporting events, and visiting breweries.