Skip to main content

Python bindings for AWS Systems Manager Session Manager protocol

Project description

aws-ssm-bridge

A Rust library implementing the AWS Systems Manager (SSM) Session Manager protocol with Python bindings.

License Rust Python unsafe


⚠️ Disclaimer

This project is not affiliated with, endorsed by, or sponsored by Amazon Web Services, Inc. or any of its affiliates.

This is an independent implementation of the SSM Session Manager protocol.


Overview

Unlike the official AWS Session Manager Plugin (a CLI binary written in Go), aws-ssm-bridge is a library designed for embedding in your applications.

Features

  • Binary Protocol: Full 120-byte AWS header, SHA-256 digest checking (advisory — mismatches warn but do not fail the session, to handle known SSM agent quirks)
  • Reliable Delivery: Sequence tracking, ACK/retransmission, RTT estimation (Jacobson/Karels)
  • Bounded Writer Channel: Dedicated writer task with backpressure — no mutex contention, no OOM under slow remotes
  • Dead Connection Detection: Pong-based heartbeat with auto-shutdown on missed responses
  • Interactive Shell: Raw terminal mode, resize handling (SIGWINCH)
  • Port Forwarding: TCP tunneling via PortForwarder
  • Python Bindings: Async support via PyO3, type stubs included
  • Security: #![forbid(unsafe_code)], zeroize token scrubbing, rate limiting, SSRF protection, target validation

Installation

Rust

[dependencies]
aws-ssm-bridge = "0.4"
tokio = { version = "1", features = ["full"] }

Python

pip install aws-ssm-bridge

Quick Start

Interactive Shell

use aws_ssm_bridge::interactive::{InteractiveShell, InteractiveConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = InteractiveConfig::default();
    let mut shell = InteractiveShell::new(config)?;

    // Handles raw mode, resize (SIGWINCH), signals (Ctrl+C/D/Z)
    shell.connect("i-0123456789abcdef0").await?;
    shell.run().await?;
    Ok(())
}

Programmatic Session

use aws_ssm_bridge::{SessionManager, SessionConfig};
use futures::StreamExt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let manager = SessionManager::new().await?;

    let mut session = manager.start_session(SessionConfig {
        target: "i-0123456789abcdef0".into(),
        ..Default::default()
    }).await?;

    let mut output = session.output();
    tokio::spawn(async move {
        while let Some(data) = output.next().await {
            print!("{}", String::from_utf8_lossy(&data));
        }
    });

    session.send(b"hostname\n").await?;
    tokio::time::sleep(std::time::Duration::from_secs(2)).await;
    session.terminate().await?;
    Ok(())
}

Port Forwarding

use std::net::SocketAddr;
use std::sync::Arc;
use aws_ssm_bridge::{SessionBuilder, PortForwardConfig, PortForwarder,
                     ShutdownSignal, install_signal_handlers};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let shutdown = ShutdownSignal::new();
    install_signal_handlers(shutdown.clone());

    // Remote port belongs in the session document, not PortForwardConfig.
    let session = Arc::new(
        SessionBuilder::new("i-0123456789abcdef0")
            .port_forward(80)
            .build()
            .await?
    );

    // bind() binds the local TCP port immediately; local_addr() returns the
    // actual address (useful when port 0 was requested for an OS-assigned port).
    let forwarder = PortForwarder::bind(PortForwardConfig {
        local_addr: "127.0.0.1:8080".parse::<SocketAddr>()?,
        ..Default::default()
    }).await?;
    println!("Forwarding {} -> remote:80", forwarder.local_addr());
    forwarder.forward(session, shutdown).await?;
    Ok(())
}

Python

import asyncio
from aws_ssm_bridge import SessionManager

async def main():
    manager = await SessionManager.new()

    async with await manager.start_session(target="i-0123456789abcdef0") as session:
        await session.send(b"hostname\n")
        output = session.output()
        async for chunk in output:
            print(chunk.decode(), end="")

asyncio.run(main())

Type-Safe Documents

Use type-safe document wrappers instead of magic strings:

use aws_ssm_bridge::{SessionBuilder, documents::*};

// Port forwarding to instance (remote port 3306)
let session = SessionBuilder::new("i-xxx")
    .document(PortForwardingSession::new(3306))
    .build().await?;

// Port forwarding through bastion to RDS
let session = SessionBuilder::new("i-bastion")
    .document(PortForwardingToRemoteHost::new("mydb.rds.amazonaws.com", 3306))
    .build().await?;

// SSH over Session Manager
let session = SessionBuilder::new("i-xxx")
    .document(SshSession::new())
    .build().await?;

// Interactive command execution
let session = SessionBuilder::new("i-xxx")
    .document(InteractiveCommand::new("top"))
    .build().await?;

Documentation


Examples

Rust Examples (examples/)

Example Description
interactive_shell.rs Full interactive shell with raw mode, resize, signals
shell_session.rs Programmatic shell session (send commands, read output)
port_forwarding.rs TCP port forwarding through SSM
session_pool.rs Managing multiple concurrent sessions
reconnecting.rs Auto-reconnection with exponential backoff
metrics_session.rs Session with observability hooks

Run with: cargo run --example interactive_shell -- i-0123456789abcdef0

Python Examples (python_examples/)

Example Description
interactive_shell.py Full interactive shell with raw terminal mode
shell_session.py Basic shell session with context manager
port_forwarding.py TCP port forwarding
multiple_sessions.py Concurrent sessions to multiple instances

Run with: python python_examples/interactive_shell.py i-0123456789abcdef0


Architecture

src/
├── lib.rs              # Public API
├── binary_protocol.rs  # 120-byte header, SHA-256
├── session.rs          # Session lifecycle, target validation
├── connection.rs       # WebSocket, bounded writer task, retransmit, heartbeat
├── channels.rs         # BroadcastStream-backed output multiplexer
├── ack.rs              # ACK tracking, RTT (Jacobson/Karels)
├── handshake.rs        # 3-phase handshake
├── mux.rs              # smux v1 multiplexer (port forwarding)
├── port_forward.rs     # TCP tunneling
├── rate_limit.rs       # Token bucket
└── python/             # PyO3 bindings

Security

  • #![forbid(unsafe_code)]
  • zeroize scrubs session tokens from memory on drop
  • Target format validation (EC2 instance, managed instance, ARN)
  • SSRF protection (AWS endpoint validation)
  • Rate limiting (configurable token bucket)
  • TLS required (WSS only)
  • Dead connection detection via pong tracking
  • AWS transport encryption (all SSM traffic is encrypted)

See Security Documentation for threat model and details.


License

MIT License. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

aws_ssm_bridge-0.4.0.tar.gz (856.3 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

aws_ssm_bridge-0.4.0-cp38-abi3-win_amd64.whl (5.8 MB view details)

Uploaded CPython 3.8+Windows x86-64

aws_ssm_bridge-0.4.0-cp38-abi3-manylinux_2_39_x86_64.whl (8.5 MB view details)

Uploaded CPython 3.8+manylinux: glibc 2.39+ x86-64

aws_ssm_bridge-0.4.0-cp38-abi3-macosx_11_0_arm64.whl (5.7 MB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

File details

Details for the file aws_ssm_bridge-0.4.0.tar.gz.

File metadata

  • Download URL: aws_ssm_bridge-0.4.0.tar.gz
  • Upload date:
  • Size: 856.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for aws_ssm_bridge-0.4.0.tar.gz
Algorithm Hash digest
SHA256 acfc2ec81b48c6dec2eeb4ada15c02760228dbf4506c565496d9023d0902e837
MD5 0d64b55b8d6db7e23d10468ea8645836
BLAKE2b-256 562d6ac60fc8bc5c2a51ce74ae3b41f29daaf681925692184b66bd3043011315

See more details on using hashes here.

Provenance

The following attestation bundles were made for aws_ssm_bridge-0.4.0.tar.gz:

Publisher: release.yml on hupe1980/aws-ssm-bridge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file aws_ssm_bridge-0.4.0-cp38-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for aws_ssm_bridge-0.4.0-cp38-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 382b83aec5caa2322079582432237caadad92ce84f0edb834d1a49f1ea985453
MD5 25d1eec897938f46d1c288b5149e2ba0
BLAKE2b-256 5a46fb9bff983a777439b9806a23312121b4170355d4a9c117a4227f5aecdf8e

See more details on using hashes here.

Provenance

The following attestation bundles were made for aws_ssm_bridge-0.4.0-cp38-abi3-win_amd64.whl:

Publisher: release.yml on hupe1980/aws-ssm-bridge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file aws_ssm_bridge-0.4.0-cp38-abi3-manylinux_2_39_x86_64.whl.

File metadata

File hashes

Hashes for aws_ssm_bridge-0.4.0-cp38-abi3-manylinux_2_39_x86_64.whl
Algorithm Hash digest
SHA256 ca3e5637f7c6ec9dce9a5557c18acc252ee932d38ffe38c879094c10340a9a61
MD5 9fa86348eef8331d6a97f2c47244c78c
BLAKE2b-256 62f4aed76b40d0f9a04d3ca23e5473ba9d75dba045ba4d5f502d63402ee6bebe

See more details on using hashes here.

Provenance

The following attestation bundles were made for aws_ssm_bridge-0.4.0-cp38-abi3-manylinux_2_39_x86_64.whl:

Publisher: release.yml on hupe1980/aws-ssm-bridge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file aws_ssm_bridge-0.4.0-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for aws_ssm_bridge-0.4.0-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 209897cd480219eb2deffb447cfc0abc6c650b906fdbe8b26bd3fa18c3f501c0
MD5 73ee5a3c045658c2a9ffd96e12afcfaa
BLAKE2b-256 1e8df9cd26a5e6cee8ded6e9b3af0df05e242a8197e3a9ec3992d193bda6428d

See more details on using hashes here.

Provenance

The following attestation bundles were made for aws_ssm_bridge-0.4.0-cp38-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on hupe1980/aws-ssm-bridge

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page