# 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 ```bash 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](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 ### Observability - Structured JSON logging (`BASCULE_LOG_FORMAT=json`) - Tracing spans on auth, session lifecycle, exec requests ## Client: bascule-shell Identity-aware login shell with TPM attestation: ```bash ./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](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 | See [docs/comparison.md](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](docs/kubernetes.md) ## Extending Bascule Implement `SessionHandler` to add custom policy: ```rust 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](docs/architecture.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 - [Quick Start](docs/quickstart.md) - [Configuration](docs/configuration.md) - [Authentication](docs/authentication.md) - [Architecture](docs/architecture.md) - [Observability](docs/observability.md) - [Kubernetes](docs/kubernetes.md) - [bascule-shell](docs/bascule-shell.md) - [Comparison](docs/comparison.md) - [Container Images](images/README.md) - [Contributing](CONTRIBUTING.md) ## License Apache 2.0