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.
⚠️ 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)]zeroizescrubs 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
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
acfc2ec81b48c6dec2eeb4ada15c02760228dbf4506c565496d9023d0902e837
|
|
| MD5 |
0d64b55b8d6db7e23d10468ea8645836
|
|
| BLAKE2b-256 |
562d6ac60fc8bc5c2a51ce74ae3b41f29daaf681925692184b66bd3043011315
|
Provenance
The following attestation bundles were made for aws_ssm_bridge-0.4.0.tar.gz:
Publisher:
release.yml on hupe1980/aws-ssm-bridge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aws_ssm_bridge-0.4.0.tar.gz -
Subject digest:
acfc2ec81b48c6dec2eeb4ada15c02760228dbf4506c565496d9023d0902e837 - Sigstore transparency entry: 1704845119
- Sigstore integration time:
-
Permalink:
hupe1980/aws-ssm-bridge@b885409d0bc25432d62003313c96a6fef7212eeb -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/hupe1980
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b885409d0bc25432d62003313c96a6fef7212eeb -
Trigger Event:
push
-
Statement type:
File details
Details for the file aws_ssm_bridge-0.4.0-cp38-abi3-win_amd64.whl.
File metadata
- Download URL: aws_ssm_bridge-0.4.0-cp38-abi3-win_amd64.whl
- Upload date:
- Size: 5.8 MB
- Tags: CPython 3.8+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
382b83aec5caa2322079582432237caadad92ce84f0edb834d1a49f1ea985453
|
|
| MD5 |
25d1eec897938f46d1c288b5149e2ba0
|
|
| BLAKE2b-256 |
5a46fb9bff983a777439b9806a23312121b4170355d4a9c117a4227f5aecdf8e
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aws_ssm_bridge-0.4.0-cp38-abi3-win_amd64.whl -
Subject digest:
382b83aec5caa2322079582432237caadad92ce84f0edb834d1a49f1ea985453 - Sigstore transparency entry: 1704845150
- Sigstore integration time:
-
Permalink:
hupe1980/aws-ssm-bridge@b885409d0bc25432d62003313c96a6fef7212eeb -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/hupe1980
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b885409d0bc25432d62003313c96a6fef7212eeb -
Trigger Event:
push
-
Statement type:
File details
Details for the file aws_ssm_bridge-0.4.0-cp38-abi3-manylinux_2_39_x86_64.whl.
File metadata
- Download URL: aws_ssm_bridge-0.4.0-cp38-abi3-manylinux_2_39_x86_64.whl
- Upload date:
- Size: 8.5 MB
- Tags: CPython 3.8+, manylinux: glibc 2.39+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ca3e5637f7c6ec9dce9a5557c18acc252ee932d38ffe38c879094c10340a9a61
|
|
| MD5 |
9fa86348eef8331d6a97f2c47244c78c
|
|
| BLAKE2b-256 |
62f4aed76b40d0f9a04d3ca23e5473ba9d75dba045ba4d5f502d63402ee6bebe
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aws_ssm_bridge-0.4.0-cp38-abi3-manylinux_2_39_x86_64.whl -
Subject digest:
ca3e5637f7c6ec9dce9a5557c18acc252ee932d38ffe38c879094c10340a9a61 - Sigstore transparency entry: 1704845176
- Sigstore integration time:
-
Permalink:
hupe1980/aws-ssm-bridge@b885409d0bc25432d62003313c96a6fef7212eeb -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/hupe1980
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b885409d0bc25432d62003313c96a6fef7212eeb -
Trigger Event:
push
-
Statement type:
File details
Details for the file aws_ssm_bridge-0.4.0-cp38-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: aws_ssm_bridge-0.4.0-cp38-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 5.7 MB
- Tags: CPython 3.8+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
209897cd480219eb2deffb447cfc0abc6c650b906fdbe8b26bd3fa18c3f501c0
|
|
| MD5 |
73ee5a3c045658c2a9ffd96e12afcfaa
|
|
| BLAKE2b-256 |
1e8df9cd26a5e6cee8ded6e9b3af0df05e242a8197e3a9ec3992d193bda6428d
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
aws_ssm_bridge-0.4.0-cp38-abi3-macosx_11_0_arm64.whl -
Subject digest:
209897cd480219eb2deffb447cfc0abc6c650b906fdbe8b26bd3fa18c3f501c0 - Sigstore transparency entry: 1704845202
- Sigstore integration time:
-
Permalink:
hupe1980/aws-ssm-bridge@b885409d0bc25432d62003313c96a6fef7212eeb -
Branch / Tag:
refs/tags/v0.4.0 - Owner: https://github.com/hupe1980
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@b885409d0bc25432d62003313c96a6fef7212eeb -
Trigger Event:
push
-
Statement type: