docs: comprehensive documentation + developer experience polish
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>
This commit is contained in:
parent
9dc5cb9eee
commit
2fa92f8635
10 changed files with 487 additions and 74 deletions
21
.editorconfig
Normal file
21
.editorconfig
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.toml]
|
||||
indent_size = 2
|
||||
|
||||
[Makefile]
|
||||
indent_style = tab
|
||||
39
CLAUDE.md
Normal file
39
CLAUDE.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# CLAUDE.md — Context for Claude Code
|
||||
|
||||
## What is this?
|
||||
|
||||
Bascule is an identity-aware SSH proxy. It authenticates operators via SSH keys or AI agent tokens, then connects them to a shell, remote host, or ephemeral container.
|
||||
|
||||
## Workspace
|
||||
|
||||
- `crates/bascule-core/` — Library: SSH server, auth, session backends, hooks
|
||||
- `crates/bascule-server/` — Binary: CLI wrapper, config loading, telemetry setup
|
||||
- `crates/bascule-auth-agent-id/` — Optional: Entra Agent ID auth provider
|
||||
- `crates/bascule-shell/` — Binary: Identity-aware login shell with TPM attestation
|
||||
- `charts/bascule/` — Helm chart for K8s deployment
|
||||
- `images/` — Curated container images for operator environments
|
||||
|
||||
## Key traits
|
||||
|
||||
- `AuthProvider` (auth.rs) — implement to add auth methods
|
||||
- `SessionHandler` (hooks.rs) — implement to add session policy
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
cargo build --all # Build everything
|
||||
cargo test --all # Run tests
|
||||
cargo clippy --all-targets # Lint
|
||||
make ci # Full CI check
|
||||
make dev # Run locally in dev mode
|
||||
```
|
||||
|
||||
## Feature flags (bascule-server)
|
||||
|
||||
- `agent-id` — Entra Agent ID auth
|
||||
|
||||
## Rules
|
||||
|
||||
- Zero substrate/chronicle/gsap dependencies
|
||||
- No unwrap() in production code
|
||||
- cargo fmt + cargo clippy must pass
|
||||
50
CONTRIBUTING.md
Normal file
50
CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# Contributing to Bascule
|
||||
|
||||
## Development Setup
|
||||
|
||||
```bash
|
||||
git clone https://github.com/your-org/bascule.git
|
||||
cd bascule
|
||||
cargo build --all
|
||||
cargo test --all
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
Bascule is a Rust workspace:
|
||||
|
||||
| Crate | Purpose |
|
||||
|-------|---------|
|
||||
| `bascule-core` | Library — SSH server, auth, PTY, proxy, container, hooks |
|
||||
| `bascule-server` | Binary — CLI, config, telemetry |
|
||||
| `bascule-auth-agent-id` | Optional — Entra Agent ID auth |
|
||||
| `bascule-shell` | Binary — Identity-aware login shell |
|
||||
|
||||
## Testing
|
||||
|
||||
```bash
|
||||
cargo test --all
|
||||
```
|
||||
|
||||
## Code Style
|
||||
|
||||
- `cargo fmt` before committing
|
||||
- `cargo clippy` must pass
|
||||
- No `unwrap()` in production code
|
||||
- All public items need doc comments
|
||||
|
||||
## Pull Request Process
|
||||
|
||||
1. Create a feature branch
|
||||
2. Ensure `make ci` passes
|
||||
3. Update docs if adding features
|
||||
4. Submit PR against `main`
|
||||
|
||||
## Commit Messages
|
||||
|
||||
Format: `type: description`
|
||||
Types: feat, fix, docs, chore, refactor, test
|
||||
|
||||
## License
|
||||
|
||||
By contributing, you agree your contributions are licensed under Apache 2.0.
|
||||
40
Makefile
Normal file
40
Makefile
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
.PHONY: build build-full test lint fmt fmt-check clean docker docker-images helm-lint dev ci
|
||||
|
||||
build:
|
||||
cargo build --release --all
|
||||
|
||||
build-full:
|
||||
cargo build --release -p bascule-server --features agent-id
|
||||
|
||||
test:
|
||||
cargo test --all
|
||||
|
||||
lint:
|
||||
cargo clippy --all-targets -- -D warnings
|
||||
|
||||
fmt:
|
||||
cargo fmt --all
|
||||
|
||||
fmt-check:
|
||||
cargo fmt --all --check
|
||||
|
||||
clean:
|
||||
cargo clean
|
||||
|
||||
docker:
|
||||
docker build -t bascule:latest .
|
||||
|
||||
docker-images:
|
||||
docker build -t bascule-shell:minimal images/minimal/
|
||||
docker build -t bascule-shell:k8s-ops images/k8s-ops/
|
||||
docker build -t bascule-shell:net-ops images/net-ops/
|
||||
docker build -t bascule-shell:dev images/dev/
|
||||
|
||||
helm-lint:
|
||||
helm lint charts/bascule/
|
||||
|
||||
dev:
|
||||
RUST_LOG=debug cargo run -p bascule-server -- --config config/bascule.example.toml
|
||||
|
||||
ci: fmt-check lint build test helm-lint
|
||||
@echo "All checks passed"
|
||||
141
README.md
141
README.md
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Identity-aware SSH proxy for modern infrastructure.
|
||||
|
||||
**Bascule** is a lightweight SSH proxy that authenticates users via SSH keys or AI agent tokens, then connects them to a local shell, remote host, or ephemeral container. No agents. No control plane. One binary.
|
||||
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
|
||||
|
||||
|
|
@ -13,78 +13,109 @@ cargo build --release -p bascule-server
|
|||
ssh -p 2222 localhost
|
||||
```
|
||||
|
||||
See [docs/quickstart.md](docs/quickstart.md) for Docker and container mode.
|
||||
|
||||
## Session Modes
|
||||
|
||||
| Mode | Config | Use case |
|
||||
|------|--------|----------|
|
||||
| **Local PTY** | (default) | Spawn a local shell |
|
||||
| **Remote proxy** | `[proxy]` | Forward to a remote SSH host |
|
||||
| **Container** | `[container]` | Ephemeral container per session |
|
||||
|
||||
### Container mode
|
||||
|
||||
Each SSH session spawns a fresh container. The image defines the toolset — if it's not in the image, the operator can't use it.
|
||||
|
||||
```toml
|
||||
[container]
|
||||
image = "bascule-shell:k8s-ops"
|
||||
ephemeral = true
|
||||
hardened = true
|
||||
memory_limit = "512m"
|
||||
```
|
||||
See [docs/quickstart.md](docs/quickstart.md) for Docker, Helm, and container mode.
|
||||
|
||||
## Features
|
||||
|
||||
- **Three backends** — local PTY, remote SSH proxy, ephemeral containers
|
||||
- **Identity-aware sessions** — every connection authenticated and attributed
|
||||
- **SSH key authentication** — standard authorized_keys file
|
||||
- **AI agent authentication** — Microsoft Entra Agent ID support (optional feature)
|
||||
- **Session limiting** — configurable max concurrent sessions
|
||||
- **Right-sized images** — curated container images (minimal, k8s-ops, net-ops, dev)
|
||||
- **SessionHandler trait** — extend with custom policy, audit, or recording
|
||||
- **Structured logging** — JSON format for production observability
|
||||
- **Small footprint** — single binary, ~7MB, <64MB memory
|
||||
### 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 |
|
||||
|---|---|---|---|
|
||||
| Agents | None | Required | Required |
|
||||
| Control plane | None | Required | Required |
|
||||
| License | Apache 2.0 | AGPL | MPL |
|
||||
| Container sessions | Native | No | No |
|
||||
| AI Agent Identity | Native | No | No |
|
||||
| Auth | SSH keys, Entra Agent ID | OIDC, SAML, GitHub | OIDC, LDAP |
|
||||
| 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) for the full comparison.
|
||||
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 the `SessionHandler` trait to add custom behavior:
|
||||
Implement `SessionHandler` to add custom policy:
|
||||
|
||||
```rust
|
||||
use bascule_core::hooks::{SessionHandler, SessionInfo};
|
||||
|
||||
struct MyAuditHandler;
|
||||
struct AuditHandler;
|
||||
|
||||
#[async_trait]
|
||||
impl SessionHandler for MyAuditHandler {
|
||||
async fn on_session_start(&self, session: &SessionInfo) -> anyhow::Result<()> {
|
||||
log::info!("{} connected from {}", session.principal, session.source_ip);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn on_exec(&self, session: &SessionInfo, command: &str) -> anyhow::Result<()> {
|
||||
log::info!("{} executed: {}", session.principal, command);
|
||||
impl SessionHandler for AuditHandler {
|
||||
async fn on_session_start(&self, s: &SessionInfo) -> anyhow::Result<()> {
|
||||
println!("{} connected from {}", s.principal, s.source_ip);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Projects like [Guildhouse](https://guildhouse.dev) use the SessionHandler trait to add custom authorization, audit logging, and session governance.
|
||||
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
|
||||
|
||||
|
|
@ -93,17 +124,11 @@ Projects like [Guildhouse](https://guildhouse.dev) use the SessionHandler trait
|
|||
- [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)
|
||||
|
||||
## Roadmap
|
||||
|
||||
- [ ] OIDC authentication (Keycloak, Entra, Okta, Google)
|
||||
- [ ] Certificate-based authentication
|
||||
- [ ] OpenTelemetry OTLP trace export
|
||||
- [ ] Prometheus metrics endpoint
|
||||
- [ ] Session recording
|
||||
- [ ] Web UI for session management
|
||||
- [Contributing](CONTRIBUTING.md)
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
|||
37
charts/bascule/README.md
Normal file
37
charts/bascule/README.md
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
# Bascule Helm Chart
|
||||
|
||||
Deploy Bascule SSH proxy on Kubernetes.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
helm install bascule charts/bascule/
|
||||
```
|
||||
|
||||
## Connect
|
||||
|
||||
```bash
|
||||
ssh -p 2222 $(kubectl get svc bascule -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
||||
```
|
||||
|
||||
## Common Configurations
|
||||
|
||||
```bash
|
||||
# NodePort
|
||||
helm install bascule charts/bascule/ --set service.type=NodePort
|
||||
|
||||
# SSH keys from Secret
|
||||
kubectl create secret generic bascule-keys --from-file=authorized_keys=$HOME/.ssh/authorized_keys
|
||||
helm install bascule charts/bascule/ --set auth.authorizedKeysSecret=bascule-keys
|
||||
|
||||
# Custom shell image
|
||||
helm install bascule charts/bascule/ --set shell.image.tag=net-ops
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
Pod with two containers:
|
||||
- `bascule` — SSH proxy (port 2222)
|
||||
- `shell` — operator environment (exec'd into on connect)
|
||||
|
||||
See [values.yaml](values.yaml) for all options.
|
||||
|
|
@ -1,23 +1,90 @@
|
|||
# Bascule SSH Proxy — Example Configuration
|
||||
# ╔══════════════════════════════════════════════════════╗
|
||||
# ║ Bascule SSH Proxy — Configuration Reference ║
|
||||
# ╚══════════════════════════════════════════════════════╝
|
||||
|
||||
# Listen address
|
||||
# ─── Server ──────────────────────────────────────────────
|
||||
|
||||
# Listen address (default: 0.0.0.0:2222)
|
||||
listen_addr = "0.0.0.0:2222"
|
||||
|
||||
# Host key (auto-generated if not present)
|
||||
# host_key_path = "/etc/bascule/host_key"
|
||||
# Path to host key. Auto-generated Ed25519 if not present.
|
||||
# host_key_path = "/var/lib/bascule/host_key"
|
||||
|
||||
# Shell command to spawn for each session
|
||||
# Default: /bin/bash
|
||||
# shell_command = "/bin/bash"
|
||||
# shell_command = "/usr/local/bin/custom-shell"
|
||||
# Maximum concurrent sessions (default: 0 → 10000 internal cap)
|
||||
# max_sessions = 100
|
||||
|
||||
# Authentication
|
||||
[auth]
|
||||
mode = "accept-all" # "accept-all" (dev only), "authorized-keys"
|
||||
# authorized_keys_path = "/etc/bascule/authorized_keys"
|
||||
|
||||
# Session banner (optional)
|
||||
# Banner shown after authentication
|
||||
# banner = "Welcome to Bascule."
|
||||
|
||||
# Max concurrent sessions (0 = unlimited)
|
||||
# max_sessions = 100
|
||||
# ─── Shell (Local PTY mode — default backend) ────────────
|
||||
|
||||
# Shell command to spawn (default: /bin/bash)
|
||||
# shell_command = "/bin/bash"
|
||||
# shell_args = ["--login"]
|
||||
|
||||
# ─── Authentication ──────────────────────────────────────
|
||||
|
||||
[auth]
|
||||
# Auth mode: "accept-all" (DEV ONLY), "authorized-keys"
|
||||
mode = "accept-all"
|
||||
|
||||
# For authorized-keys mode:
|
||||
# authorized_keys_path = "/etc/bascule/keys"
|
||||
|
||||
# ─── Entra Agent ID (optional, --features agent-id) ─────
|
||||
# [auth.agent_id]
|
||||
# tenant_id = "your-entra-tenant-id"
|
||||
# audiences = ["api://bascule-proxy"]
|
||||
# multi_tenant = false
|
||||
|
||||
# ─── SPIFFE/SPIRE (config ready, runtime planned) ───────
|
||||
# [auth.spiffe]
|
||||
# trust_domain = "example.com"
|
||||
# trust_bundle_path = "/run/spire/bundle/bundle.pem"
|
||||
# workload_api_socket = "/run/spire/agent/sockets/agent.sock"
|
||||
|
||||
# ─── Remote Proxy Mode ──────────────────────────────────
|
||||
# Uncomment to forward sessions to a remote SSH host.
|
||||
# [proxy]
|
||||
# target_host = "192.168.1.100"
|
||||
# target_port = 22
|
||||
# target_user = "deploy"
|
||||
# target_key_path = "/path/to/key"
|
||||
# accept_target_host_key = false
|
||||
|
||||
# ─── Container Mode ─────────────────────────────────────
|
||||
# Uncomment to spawn ephemeral containers per session.
|
||||
# [container]
|
||||
# runtime = "auto" # auto | docker | podman | nerdctl
|
||||
# image = "bascule-shell:k8s-ops"
|
||||
# pull_policy = "if-not-present" # always | if-not-present | never
|
||||
# ephemeral = true # destroy container on disconnect
|
||||
# hardened = true # cap-drop ALL, no-new-privileges
|
||||
# read_only_rootfs = false
|
||||
# memory_limit = "512m"
|
||||
# cpu_limit = "1.0"
|
||||
# shell = "/bin/bash"
|
||||
# user = "operator"
|
||||
# network = "bridge" # bridge | none | host
|
||||
#
|
||||
# [[container.mounts]]
|
||||
# source = "/home/user/.kube"
|
||||
# target = "/home/operator/.kube"
|
||||
# readonly = true
|
||||
|
||||
# ─── Kubernetes Mode (config ready, runtime planned) ────
|
||||
# Auto-detected in-cluster via downward API.
|
||||
# [k8s]
|
||||
# enabled = true
|
||||
# shell_container = "shell"
|
||||
# shell = "/bin/bash"
|
||||
|
||||
# ─── Telemetry ──────────────────────────────────────────
|
||||
# [telemetry]
|
||||
# otlp_endpoint = "http://localhost:4317"
|
||||
# service_name = "bascule"
|
||||
|
||||
# ─── Metrics (planned) ──────────────────────────────────
|
||||
# [metrics]
|
||||
# enabled = true
|
||||
# port = 9090
|
||||
|
|
|
|||
82
docs/bascule-shell.md
Normal file
82
docs/bascule-shell.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# bascule-shell
|
||||
|
||||
Identity-aware login shell with TPM attestation.
|
||||
|
||||
## What it does
|
||||
|
||||
`bascule-shell` wraps your preferred shell (bash/zsh/fish) and:
|
||||
|
||||
1. Detects your identity (Entra, Kerberos, SSH key)
|
||||
2. Reads TPM PCR values and IMA measurements
|
||||
3. Displays a banner with identity + attestation summary
|
||||
4. Sets `BASCULE_*` environment variables
|
||||
5. Execs into the inner shell
|
||||
|
||||
Every SSH connection from inside the shell carries your identity and platform attestation.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
cargo install --path crates/bascule-shell
|
||||
# or
|
||||
cargo build --release -p bascule-shell
|
||||
cp target/release/bascule-shell /usr/local/bin/
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# Start the shell
|
||||
bascule-shell
|
||||
|
||||
# Show identity + attestation (dry run)
|
||||
bascule-shell --info
|
||||
|
||||
# JSON output
|
||||
bascule-shell --info --json
|
||||
|
||||
# Run a single command
|
||||
bascule-shell --exec "env | grep BASCULE_"
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
`~/.config/bascule/shell.toml`:
|
||||
|
||||
```toml
|
||||
inner_shell = "/bin/bash"
|
||||
show_banner = true
|
||||
pcr_indices = [0, 1, 2, 7, 10, 14]
|
||||
|
||||
# Auto-configure SSH for Bascule servers
|
||||
# [[servers]]
|
||||
# alias = "jumphost"
|
||||
# hostname = "bascule.example.com"
|
||||
# port = 2222
|
||||
```
|
||||
|
||||
## Identity Detection
|
||||
|
||||
Priority order:
|
||||
|
||||
| Method | Source | When detected |
|
||||
|--------|--------|---------------|
|
||||
| Entra (WSL2) | `cmd.exe` interop | WSL2 with Entra-joined Windows |
|
||||
| Azure CLI | `az account show` | `az` installed and logged in |
|
||||
| Kerberos | `klist -s` | Valid TGT present |
|
||||
| Cached OIDC | `~/.config/bascule/token.json` | Token file exists and not expired |
|
||||
| System user | `$USER` | Always (fallback) |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
After startup, the inner shell has:
|
||||
|
||||
| Variable | Example |
|
||||
|----------|---------|
|
||||
| `BASCULE_PRINCIPAL` | `tking` |
|
||||
| `BASCULE_AUTH_METHOD` | `ssh-key` |
|
||||
| `BASCULE_ATTESTATION_HASH` | `sha256:e9b95f...` |
|
||||
| `BASCULE_TPM_AVAILABLE` | `true` |
|
||||
| `BASCULE_PCR_COUNT` | `6` |
|
||||
| `BASCULE_IMA_COUNT` | `1247` |
|
||||
| `BASCULE_PLATFORM_SUMMARY` | `tpm:6pcr,ima:1247` |
|
||||
49
docs/kubernetes.md
Normal file
49
docs/kubernetes.md
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Kubernetes Deployment
|
||||
|
||||
## Helm Install
|
||||
|
||||
```bash
|
||||
helm install bascule charts/bascule/
|
||||
```
|
||||
|
||||
### Common Options
|
||||
|
||||
```bash
|
||||
# NodePort access
|
||||
helm install bascule charts/bascule/ --set service.type=NodePort
|
||||
|
||||
# Authorized keys from a Secret
|
||||
kubectl create secret generic bascule-keys --from-file=authorized_keys=$HOME/.ssh/authorized_keys
|
||||
helm install bascule charts/bascule/ --set auth.authorizedKeysSecret=bascule-keys
|
||||
|
||||
# Custom shell image
|
||||
helm install bascule charts/bascule/ --set shell.image.tag=net-ops
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
The chart deploys a Pod with two containers:
|
||||
|
||||
- **bascule** — the SSH proxy (port 2222)
|
||||
- **shell** — the operator environment (configured image, sleeps until exec'd)
|
||||
|
||||
Operators SSH to Bascule. Bascule exec's into the shell container for each session. Multiple operators share the Pod with separate exec sessions.
|
||||
|
||||
## Security Defaults
|
||||
|
||||
- **NetworkPolicy**: egress restricted to DNS + K8s API
|
||||
- **RBAC**: minimal Role (pods/exec in own namespace only)
|
||||
- **SecurityContext**: no privilege escalation, cap-drop ALL on shell container
|
||||
- **Host key**: persisted via volume (stable across restarts)
|
||||
|
||||
## Values Reference
|
||||
|
||||
See [values.yaml](../charts/bascule/values.yaml) for all options.
|
||||
|
||||
| Key | Default | Description |
|
||||
|-----|---------|-------------|
|
||||
| `shell.image.tag` | `k8s-ops` | Shell image variant |
|
||||
| `auth.mode` | `authorized-keys` | Auth mode |
|
||||
| `service.type` | `LoadBalancer` | Service type |
|
||||
| `maxSessions` | `100` | Max concurrent SSH sessions |
|
||||
| `networkPolicy.enabled` | `true` | Enable network restrictions |
|
||||
3
rustfmt.toml
Normal file
3
rustfmt.toml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
edition = "2021"
|
||||
max_width = 100
|
||||
use_small_heuristics = "Default"
|
||||
Loading…
Reference in a new issue