Open-source SSH proxy with identity-aware shell (Rust)
Find a file
Claude Code 999c78ef4c feat(m1): bascule-shell composes a real SAT anchored on session_leaf
Replaces the opaque BASCULE_ATTESTATION_HASH (a SHA over a
"pcrN:val;ima:hash;" evidence string) with a real proto-canonical
SatBundle composed from the operator's identity + local platform
attestation, anchored on the L4 SessionClaim.

bascule-core::sat (NEW): pure composer module.
- build_session_claim(SessionInputs) -> SessionClaim builds the
  L4 leaf from {principal, auth_method, actor_type,
  identity_verified, platform_attested, software_verified,
  nonce_seed}, computes posture per SAT-SPEC-0002 §7, and
  populates the L1/L2/L3 binding fields with zero-padded
  placeholders until upstream producers exist.
- compose_local(SessionClaim) -> ComposedSat assembles the proto
  SatBundle via SatBundleBuilder. Hot path stays local per ADR D9
  (zero network); QM's gRPC ComposeSat is the warm-path surface.
- 7 unit tests cover layer/actor wiring, posture math at each
  evidence level, deterministic nonce, sat_hash uniqueness across
  principal changes.

bascule-shell: composes the SAT in main() right before execvp
of the inner shell — that's the OSS equivalent of an "Authenticated
-> ShellActive" transition (the OSS Bascule has no russh state
machine; it's a CLI wrapper). Exports the new env var surface:

  BASCULE_SAT_HASH            hex of proto sat_hash (canonical)
  BASCULE_SESSION_CLAIM_HASH  hex of L4 leaf hash
  BASCULE_SESSION_ID          UUID from SessionClaim
  BASCULE_POSTURE_LEVEL       SAT-SPEC-0002 §7 posture

  BASCULE_ATTESTATION_HASH    retained as compat alias (gsh /
                              dashboard consumers); now points at
                              the proto sat_hash, not the old
                              evidence-string SHA.

Cross-workspace path dep: substrate-proto via
../substrate-project/substrate/crates/substrate-proto. CI mounts
~/projects as one volume so the path resolves. Switching to a git
dep is post-MVP.

Note: russh-keys pulls `home` which requires Rust 1.88; CI bumps
the docker image accordingly. No code change.

Tested:
  cargo build -p bascule-core -p bascule-shell             clean
  cargo test  -p bascule-core --lib sat                    7/7

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Signed-off-by: Claude Code <claude@guildhouse.dev>
2026-04-07 14:38:20 -04:00
.github/workflows docs: DCO, NOTICE, and governance framework 2026-04-05 11:13:20 -04:00
charts/bascule docs: comprehensive documentation + developer experience polish 2026-04-05 10:53:08 -04:00
config docs: update all documentation for management API + dashboard 2026-04-05 17:17:18 -04:00
crates feat(m1): bascule-shell composes a real SAT anchored on session_leaf 2026-04-07 14:38:20 -04:00
docs docs: update all documentation for management API + dashboard 2026-04-05 17:17:18 -04:00
images feat: structured logging, tracing spans, comprehensive documentation 2026-04-04 23:45:03 -04:00
.editorconfig docs: comprehensive documentation + developer experience polish 2026-04-05 10:53:08 -04:00
.gitignore feat: Bascule — identity-aware SSH proxy 2026-04-04 22:25:33 -04:00
Cargo.lock feat(m1): bascule-shell composes a real SAT anchored on session_leaf 2026-04-07 14:38:20 -04:00
Cargo.toml feat(m1): bascule-shell composes a real SAT anchored on session_leaf 2026-04-07 14:38:20 -04:00
CLAUDE.md docs: update all documentation for management API + dashboard 2026-04-05 17:17:18 -04:00
CONTRIBUTING.md docs: update all documentation for management API + dashboard 2026-04-05 17:17:18 -04:00
DCO docs: DCO, NOTICE, and governance framework 2026-04-05 11:13:20 -04:00
docker-compose.yml feat: bascule-shell — identity-aware shell with TPM attestation 2026-04-05 09:47:46 -04:00
Dockerfile feat: bascule-shell — identity-aware shell with TPM attestation 2026-04-05 09:47:46 -04:00
GOVERNANCE.md docs: DCO, NOTICE, and governance framework 2026-04-05 11:13:20 -04:00
LICENSE feat: bascule-shell — identity-aware shell with TPM attestation 2026-04-05 09:47:46 -04:00
Makefile docs: comprehensive documentation + developer experience polish 2026-04-05 10:53:08 -04:00
NOTICE docs: DCO, NOTICE, and governance framework 2026-04-05 11:13:20 -04:00
README.md docs: update all documentation for management API + dashboard 2026-04-05 17:17:18 -04:00
rustfmt.toml docs: comprehensive documentation + developer experience polish 2026-04-05 10:53:08 -04:00

Bascule

Identity-aware SSH proxy for modern infrastructure.

Bascule authenticates operators via SSH keys or AI agent tokens, then connects them to a local shell, remote host, or ephemeral container. No agents to install. No control plane. One binary.

Quick Start

cargo build --release -p bascule-server
./target/release/bascule --config config/bascule.example.toml
# In another terminal:
ssh -p 2222 localhost

See docs/quickstart.md for Docker, Helm, and container mode.

Features

Session Backends

Mode Config Description
Local PTY (default) Spawn a local shell process
Remote Proxy [proxy] Forward to a remote SSH host
Container [container] Ephemeral container per session (Docker/Podman/nerdctl)
Kubernetes [k8s] Shared jumphost with shell sidecar (config ready, runtime coming)

Authentication

  • SSH Keys — standard OpenSSH authorized_keys files
  • Accept All — development only, accepts any key
  • Entra Agent ID — Microsoft AI agent identity (--features agent-id)
  • SPIFFE/SPIRE — workload identity (config ready, runtime coming)

Security

  • Session limiting (semaphore-based max_sessions)
  • Container hardening (--cap-drop ALL, --security-opt no-new-privileges)
  • Container config validation (injection prevention)
  • Read-only rootfs option
  • NetworkPolicy for Kubernetes deployments

Management API + Dashboard

Built-in HTTP management API (port 9090, --features dashboard):

  • GET /api/sessions — active sessions with auth/backend/TPM status
  • GET /api/stats — aggregate analytics (auth breakdown, peak concurrent, TPM %)
  • GET /api/health — server health and version
  • WASM dashboard at /dashboard/ (coming soon)

Observability

  • Structured JSON logging (BASCULE_LOG_FORMAT=json)
  • Tracing spans on auth, session lifecycle, exec requests
  • Management API for real-time session monitoring

Client: bascule-shell

Identity-aware login shell with TPM attestation:

./target/release/bascule-shell --info
╔═══════════════════════════════════════════════════════╗
║  Bascule Shell v0.1.0                                 ║
║  Principal:  tking                                     ║
║  Method:     ssh-key                                   ║
║  TPM:        available (6 PCRs verified)               ║
║  Platform:   sha256:e9b95f002f54222d...                ║
╚═══════════════════════════════════════════════════════╝

See docs/bascule-shell.md.

Comparison

Bascule Teleport Boundary
License Apache 2.0 AGPL / Commercial MPL / Commercial
Agents required No Yes Yes
Control plane No Required Required
Container sessions Yes No No
AI Agent Identity Yes (Entra Agent ID) No No
Binary size ~7MB ~150MB ~100MB
Built-in dashboard Yes (port 9090) Yes No

See docs/comparison.md.

Deployment

  • Standalone: cargo build --release -p bascule-server
  • Docker: docker build -t bascule .
  • Kubernetes: helm install bascule charts/bascule/ — see docs/kubernetes.md

Extending Bascule

Implement SessionHandler to add custom policy:

use bascule_core::hooks::{SessionHandler, SessionInfo};

struct AuditHandler;

#[async_trait]
impl SessionHandler for AuditHandler {
    async fn on_session_start(&self, s: &SessionInfo) -> anyhow::Result<()> {
        println!("{} connected from {}", s.principal, s.source_ip);
        Ok(())
    }
}

See docs/architecture.md.

Governance

Bascule is maintained by Guildhouse LLC. Contributions are accepted under the DCO — you retain copyright to your contributions.

The SessionHandler and AuthProvider traits are public APIs. Implementations are the intellectual property of their authors. See GOVERNANCE.md.

Roadmap

Not yet implemented:

  • OIDC authentication (Keycloak, Entra, Okta)
  • K8s API exec backend runtime
  • SPIFFE/SPIRE auth runtime
  • OpenTelemetry OTLP exporter
  • Prometheus metrics endpoint
  • Session recording
  • Per-session Pod isolation

Documentation

License

Apache 2.0