Skip to content

Aegis-KMS

An open-source, agent-aware key management service.

Identity, audit, and real-time control for an era when LLM agents call your sign / encrypt APIs and the role-centric audit log can't tell you which agent did what.

Get started in 2 minutes Read the architecture


Why Aegis exists

AI agents — Claude, GPT, custom agents, RAG workloads — now sign payloads, decrypt secrets, and call tools that hold real credentials. None of the existing key managers were built for this.

When something goes wrong, the audit log says "role billing-signer made 80 sign calls" and can't tell you which agent did it, on whose behalf, or whether the burst is anomalous. The problem is structural: every existing KMS — AWS KMS, GCP KMS, Azure Key Vault, HashiCorp Vault, OpenBao — is built around a role-centric model that pre-dates LLM agents in production.

Aegis is the agent-native control plane that sits in front of an existing KMS (AWS KMS today; GCP / Azure / Vault adapters in v0.3.0) and adds the four things role-centric KMSes don't:

  • Per-agent identity


    Every request resolves to a Principal.Agent with a back-pointer to the human who issued it, an explicit scope, and a TTL — not a shared service-account credential.

  • Behavioural baselines


    Five detectors flag scope violations, rate spikes, off-hours access, new source IPs, and operations the actor has never performed.

  • Structured audit


    Every decision, score, and detection lands in an immutable journal with full agent + parent attribution and full request context.

  • Real-time response


    Risk scorer (risk.score + risk.factors on every audit row), decision adapter (Allow / StepUp / Deny), and auto-responder (default High → Revoke) — all wired end-to-end on main. Try it in the wedge demo.

How a request flows through Aegis

Every operation — whether it arrives over REST, the CLI, or (eventually) MCP — passes through the same set of decorators around the KeyService algebra. Each layer does one thing and one thing only:

flowchart LR
    classDef plane   fill:#1d3557,stroke:#1d3557,color:#fff
    classDef ops     fill:#2a9d8f,stroke:#2a9d8f,color:#fff
    classDef gate    fill:#f4a261,stroke:#f4a261,color:#000
    classDef core    fill:#457b9d,stroke:#457b9d,color:#fff
    classDef sink    fill:#e76f51,stroke:#e76f51,color:#fff

    rest["REST · CLI · SDK"]:::plane --> audit["AuditingKeyService<br/><i>records every call</i>"]:::sink
    audit --> traced["TracingKeyService<br/><i>OTel span per op</i>"]:::ops
    traced --> metered["MeteredKeyService<br/><i>Prometheus counter + timer</i>"]:::ops
    metered --> authz["AuthorizingKeyService<br/><i>policy gate</i>"]:::gate
    authz --> actor["KeyOpsActor<br/><i>single-thread state owner</i>"]:::core
    actor --> rot[("Root of Trust<br/>AWS KMS · GCP 🚧 · Azure 🚧")]:::sink
    actor --> journal[(Postgres event journal)]:::sink
  • Audit is outermost so denied calls + errors still produce a row.
  • Auth is innermost of the decorators so a deny short-circuits before any real work.
  • Tracing + metrics sit between them so dashboards see the work that actually happened, while the audit row reflects the post-trace outcome.

Quickstart in 30 seconds

bash git clone https://github.com/sharma-bhaskar/aegis-kms.git cd aegis-kms export POSTGRES_PASSWORD="$(openssl rand -base64 24)" docker compose -f deploy/docker/docker-compose.yml up

Server is now at http://localhost:8080. Swagger UI lives at http://localhost:8080/docs/. Full walkthrough → Getting Started → Quickstart.

What ships today

This table reflects what's on main right now. v0.2.0 is the last released artifact; the rows marked "v0.3.0" / "v0.4.0" are designed and roadmapped, not yet shipped.

Surface Status
REST /v1/keys/* (create, get, activate, destroy, sign, verify, encrypt, decrypt, wrap, unwrap, rotate, compromise) Shipped
aegis admin CLI for the same surface Shipped
JWT bearer auth (HS256) + dev X-Aegis-User header Shipped
Postgres event journal (in-memory option for dev) Shipped
AWS KMS RootOfTrust adapter Shipped
5-detector anomaly engine (scope, rate, op-histogram, time-of-day, source-IP) Shipped
Prometheus /metrics + JVM standard collectors Shipped
OpenTelemetry tracing (auto-configured SDK) Shipped
OpenAPI 3.1 spec + Swagger UI on /docs/ Shipped
Resource[IO, Unit] boot scope for graceful shutdown Shipped
Risk scorer (RiskScorer SPI; baseline + contextual factors stamped on every audit row) Shipped (v0.2.0)
Decision adapter (Allow / StepUp / Deny; HTTP 401 / 403 with reason) Shipped (v0.2.0)
Auto-responder (default High → Revoke, Medium → Alert; configurable rules + 60 s cooldown) Shipped (v0.2.0)
Agent-token issuance endpoint (POST /v1/agents/issue) + OIDC / JWKS verifier (RS256/ES256) Shipped (v0.2.0)
Redis-backed JWT revocation list + role-based policy engine Shipped (v0.2.0)
Honey keys (canary) registry + auto-revoke detector Shipped (v0.2.0)
Postgres audit table + GET /v1/audit read API Shipped (v0.2.0)
SIEM webhook / Kafka / NATS JetStream audit fan-out Shipped (v0.2.0)
MySQL + SQLite event journals Shipped (v0.2.0)
Source IP populated on audit records by the HTTP layer Shipped (v0.2.0)
GCP / Azure / Vault RootOfTrust adapters, Helm chart v0.3.0
KMIP wire plane v0.4.0
MCP-native server v0.4.0

Full per-release breakdown → Roadmap. What changed when → Changelog.

Where to go next


License

Apache-2.0. See LICENSE.

Status

v0.2.0 — pre-alpha. Not production-ready; looking for design partners through v1.0. The full status disclosure is on the Status page.