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>
|
||
|---|---|---|
| .github/workflows | ||
| charts/bascule | ||
| config | ||
| crates | ||
| docs | ||
| images | ||
| .editorconfig | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CLAUDE.md | ||
| CONTRIBUTING.md | ||
| DCO | ||
| docker-compose.yml | ||
| Dockerfile | ||
| GOVERNANCE.md | ||
| LICENSE | ||
| Makefile | ||
| NOTICE | ||
| README.md | ||
| rustfmt.toml | ||
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 statusGET /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... ║
╚═══════════════════════════════════════════════════════╝
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
- Quick Start
- Configuration
- Authentication
- Architecture
- Observability
- Kubernetes
- bascule-shell
- Comparison
- Container Images
- Contributing
License
Apache 2.0