New files: CONTRIBUTING.md — dev setup, code style, PR process CLAUDE.md — workspace context for Claude Code Makefile — build, test, lint, fmt, docker, helm-lint, dev, ci .editorconfig — consistent formatting rustfmt.toml — Rust formatting config docs/kubernetes.md — Helm install, values, architecture docs/bascule-shell.md — client shell install, config, TPM charts/bascule/README.md — Helm quick start Updated: README.md — accurate feature matrix, clear shipped vs planned config/bascule.example.toml — full reference (72 lines, all fields) All 15 README links verified valid. Helm lint clean. Build passes. 0 substrate deps. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
135 lines
4.1 KiB
Markdown
135 lines
4.1 KiB
Markdown
# 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
|