Skip to content

Repository files navigation

mediatore

mediatore (Italian: broker, go-between; IPA /me.dja.ˈto.re/, "meh-dyah-TOH-reh")

A trusted go-between for banlieue sandbox VMs. mediatore takes a person's login at the front, an attested virtual machine at the back, and makes sure the two are bound to each other before anything inside the VM can act on that person's behalf.

Build E2E Documentation License Rust

banlieue schedules VMs and hands them out through VirtualMachineClaims, but deliberately carries no credential: a claim records who a sandbox is for, and stops there. mediatore is the component that finishes the story.

  • Front door. Accepts an Entra ID token (or a Dex-bridged GitHub login in a homelab), validates it, and creates the VirtualMachineClaim with the subject taken from the token.
  • Binding. When the claim binds to a pool member that has already attested its vTPM to SPIRE, mediatore registers a SPIFFE identity for that claim, scoped to that VM and to the per-subject Linux user the in-guest agent creates.
  • Delegation. The jailed workload presents its SVID and asks for a token for one downstream audience. mediatore answers with a short-lived, audience-scoped token, minted via Entra On-Behalf-Of or by its own STS. The user's original token never enters the VM.
  • Cut-off. When the claim expires or is deleted, mediatore removes the SPIFFE entry and stops issuing.

How a user, a delegating agent (On-Behalf-Of) or an app-only service actually gets code running in a sandbox: docs/guides/running-workloads.md. Phase status: ROADMAPS.md.

Repository layout

crates/
├── mediatore-proto/    shared wire types (nodes, me, token); server and guest both depend on it
├── mediatore-api/      axum routers: user-facing (bearer) and sandbox-facing (SPIFFE mTLS)
├── mediatore-entra/    upstream token validation (Entra, Dex), Entra On-Behalf-Of
├── mediatore-sts/      self-issued ES256 tokens with an RFC 8693 `act` claim
├── mediatore-spire/    SPIRE server API boundary (registration entries)
├── mediatore-claims/   kube-rs watcher: Bound → entry, Releasing → cut-off
├── mediatore-store/    ClaimStore trait + in-memory impl (sqlx next)
├── mediatore/          server binary
├── mediatore-guest/    in-guest agent (static musl)
└── sandbox-token/      workload-side CLI (static musl)
deploy/                 raw manifests (kustomize), Traefik IngressRoute
image/                  systemd units + cloud-config fragments baked into the VM image
docs/adr/               architecture decision records
docs/architecture/      FINOS CALM model + rendered Mermaid diagrams
docs/guides/            operational guides (enterprise SPIRE topology, ...)
docs/security/          threat model (living document, stamped per ADR range)

Methodology

mediatore follows the same Architecture Driven Development cycle as banlieue — ADR → CALM → TDD → implement → docs → threat model — with the rules in .claude/rules/. The architecture is modeled in CALM (make calm-validate, make calm-diagrams; CI fails on diagram drift), and every implemented ADR ends with a full pass over the threat model. CI is Makefile-driven: each workflow job calls a make target that runs identically locally.

Status

The dev-mode loop is implemented and tested front to back: fake IdP login → claim → bind → /v1/me → /v1/token → STS JWT verified against mediatore's own JWKS → release → cut-off. The remaining edges fail closed (501 not_implemented):

Piece State
Wire types, username derivation, STS minting (JWKS derived from the key), in-memory store implemented, unit-tested
HTTP routing, auth extractors, audience checks, token issuance (sts) implemented, e2e-tested
JWKS validation of upstream tokens (discovery, cache, kid rotation, group gate) implemented, tested against a fake IdP
Claim lifecycle in dev_mode (create, dev bind either order, mirror, release) implemented, e2e-tested
Guest: node registration, subject fetch, user + jail supervision implemented; jail path needs a Linux host
Entra OBO exchange request shape done, untested
SPIRE entry management over spire-api-sdk trait + Noop
VirtualMachineClaim watch (needs banlieue-api pin) client wiring only
SPIFFE mTLS on the sandbox listener stub (dev header)
sqlx store (PostgreSQL / SQLite) not started

Development

# quality gate
cargo fmt --all && cargo clippy --all-targets --all-features -- -D warnings && cargo test --all
cargo deny check

# front-to-back dev-mode demo: fake IdP + server + guest agent + sandbox-token
./dev/demo.sh

# run the server in dev mode (header-based peer identity, in-memory store)
openssl ecparam -name prime256v1 -genkey -noout | openssl pkcs8 -topk8 -nocrypt -out dev/sts.pem
cargo run -p mediatore -- serve --config dev/mediatore.yaml

# static guest binaries
cargo xguest

See docs/adr for decisions and the runbook for the end-to-end setup.

License

Apache License 2.0. See LICENSE.

About

Identity broker for banlieue sandbox VMs. Authenticates a user, claims a VM on their behalf, binds a SPIFFE identity to the attested VM, and hands the sandbox short-lived, audience-scoped tokens instead of the user's credentials. Entra ID or Dex + GitHub; vSphere, Cloud Hypervisor or libvirt.

Resources

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages