3 releases (breaking)
| 0.3.0 | Feb 11, 2026 |
|---|---|
| 0.2.0 | Jan 22, 2026 |
| 0.1.0 | Jan 22, 2026 |
#7 in #ssm
46 downloads per month
1MB
8K
SLoC
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 116-byte AWS header, SHA-256 digest validation
- Reliable Delivery: Sequence tracking, ACK/retransmission, RTT estimation (Jacobson/Karels)
- Lock-Free Architecture: Dedicated writer task via mpsc channel, no mutex contention
- Dead Connection Detection: Pong-based heartbeat tracking with configurable threshold
- 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.3"
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() -> anyhow::Result<()> {
let config = InteractiveConfig::default();
let mut shell = InteractiveShell::new(config)?;
// Connect and run interactive session
// 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() -> anyhow::Result<()> {
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 aws_ssm_bridge::{SessionManager, PortForwardConfig, PortForwarder};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let manager = SessionManager::new().await?;
let forwarder = PortForwarder::new(&manager, PortForwardConfig {
target: "i-0123456789abcdef0".into(),
local_port: 8080,
remote_port: 80,
..Default::default()
}).await?;
println!("Forwarding localhost:8080 -> remote:80");
forwarder.wait().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")
async for chunk in await session.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
let session = SessionBuilder::new("i-xxx")
.document(PortForwardingSession::builder()
.remote_port(3306)
.local_port(13306)
.build())
.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 # 116-byte header, SHA-256
├── session.rs # Session lifecycle, target validation
├── connection.rs # WebSocket, writer task, retransmit, pong tracking
├── channels.rs # BroadcastStream-backed output multiplexer
├── ack.rs # ACK tracking, RTT (Jacobson/Karels)
├── handshake.rs # 3-phase handshake
├── 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.
Dependencies
~39–60MB
~861K SLoC