Skip to main content
INS // Insights

AWS Session Manager vs Bastion Hosts: The Real Tradeoff

Updated August 2026 · 7 min read

A bastion host solves a real problem — you need a controlled entry point into a private subnet — by creating a new one: a single, always-on, internet-facing (or at minimum, always-reachable) server that itself becomes the highest-value target in the environment, guarded by SSH keys that need distribution, rotation, and revocation management of their own.

AWS Systems Manager Session Manager solves the same access problem without standing infrastructure, without SSH keys, and with logging that's substantially harder to bypass than bastion-host shell history.

What Actually Changes With Session Manager

# terraform: EC2 instance profile with SSM access, no bastion, no open SSH port
resource "aws_iam_role" "ssm_managed" {
  name = "ec2-ssm-managed-instance"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "ec2.amazonaws.com" }
      Action    = "sts:AssumeRole"
    }]
  })
}

resource "aws_iam_role_policy_attachment" "ssm_core" {
  role       = aws_iam_role.ssm_managed.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
}

resource "aws_security_group" "app_instance" {
  name   = "app-instance-no-ssh-ingress"
  vpc_id = aws_vpc.main.id

  # No inbound rule for port 22 at all — Session Manager needs no open ingress port,
  # since the connection is initiated outbound from the instance to the SSM service
  egress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

The security group has no port 22 ingress rule at all — not "restricted to a bastion's IP," genuinely absent, because Session Manager's agent on the instance initiates an outbound HTTPS connection to the SSM service rather than accepting an inbound connection. This removes an entire class of finding from any external attack-surface scan: there is no SSH listener to discover, brute-force, or misconfigure.

# Connecting to an instance — no key, no bastion hop
aws ssm start-session --target i-0abc123def456789

No .pem file, no ssh -J bastion-host target-host jump chain, no key distribution problem for a team of engineers who need occasional access. Access is governed entirely by IAM policy — who can call ssm:StartSession against which instance, which is the same permission model already used for everything else in AWS, rather than a parallel SSH-key-based system that needs its own lifecycle management.

Logging Is Where Session Manager Wins Decisively

Bastion host shell history is trivially tamperable by anyone with access to the bastion itself — history -c, a different shell, or simply not caring, and there's no independent record of what happened during a session. Session Manager can be configured to log every session's full input and output to CloudWatch Logs or S3, independent of anything the connecting user controls.

resource "aws_ssm_document" "session_logging" {
  name          = "SSM-SessionManagerRunShell"
  document_type = "Session"

  content = jsonencode({
    schemaVersion = "1.0"
    description   = "Session Manager logging configuration"
    sessionType   = "Standard_Stream"
    inputs = {
      cloudWatchLogGroupName      = "/ssm/session-logs"
      cloudWatchEncryptionEnabled = true
      s3BucketName                = "session-logs-archive"
      s3EncryptionEnabled         = true
    }
  })
}

This produces the evidence a SOC 2 or ISO 27001 privileged access control actually wants: an independent, tamper-resistant record of every command executed during every privileged session, tied to the IAM identity that initiated it — not a shell history file the person being audited could have edited before the review.

Where Bastion Hosts Still Have a Legitimate Place

Session Manager requires the SSM agent running on the target instance and outbound connectivity to the SSM service endpoints (directly or via VPC endpoint). Environments with instances that can't run the agent — some appliance-model systems, air-gapped or highly restricted network segments where even the SSM outbound path isn't acceptable, or non-EC2 targets like on-prem servers accessed through a hybrid setup — may still need a traditional bastion, ideally hardened with short-lived certificate-based SSH (via an internal CA) rather than static key pairs, as a fallback rather than the default.

Frequently Asked Questions

Does Session Manager work for RDP access to Windows instances, not just SSH?

Yes — Session Manager supports port forwarding, which extends to RDP sessions on Windows instances without exposing RDP (port 3389) to any network path, using the same IAM-governed, outbound-initiated connection model as SSH sessions on Linux.

What happens if an instance loses connectivity to the SSM service?

Session Manager access to that instance stops working until connectivity is restored — this is a real operational consideration for instances in highly restricted network segments, which is part of why some environments retain a bastion as a fallback path rather than removing it entirely on day one.

Is Session Manager access logged even for encrypted session content?

Session content logging captures the actual commands and output, separate from any TLS-layer encryption of the transport itself — the CloudWatch/S3 log destination receives the decrypted session content for audit purposes, which needs its own access controls and encryption at rest, since it's now a sensitive log store in its own right.

Can we require MFA for Session Manager access?

Yes, indirectly — since access is governed by IAM policy, requiring MFA on the underlying IAM identity (via a condition key like aws:MultiFactorAuthPresent in the IAM policy attached to whoever calls ssm:StartSession) enforces MFA for privileged session access without any Session Manager-specific configuration.

Is removing bastion hosts entirely always the right move?

For most standard EC2-based application environments, yes — Session Manager covers the access pattern with a stronger security posture and no standing infrastructure to patch or monitor. The exception is environments with genuine technical constraints (agent incompatibility, network isolation requirements) where a hardened, certificate-based bastion remains the pragmatic fallback.


Rutagon migrates environments off SSH-key-based bastion access onto IAM-governed Session Manager access, with full session logging built in from day one.

Discuss your project → rutagon.com/contact | 907-841-8407 | contact@rutagon.com

Related reading: Eliminating Standing Service Account Passwords · Privileged Access Review Automation for AWS Admin Paths · AWS Cloud Infrastructure Capability

External reference: AWS Systems Manager Session Manager User Guide