A self-hosted, open-source database access-control proxy for MySQL and PostgreSQL. Clients connect with their normal tools over the native wire protocol; proxy-monster enforces column-level access control per role — deterministic, lineage-aware masking and deny — and records every decision to a tamper-evident audit trail.
- Transparent proxy. Speaks the native MySQL and PostgreSQL wire protocols,
so
psql,mysql, JDBC, and application drivers connect unchanged. It authenticates the client to a principal, authorizes each statement, applies masking, and brokers to the backend with a per-datasource service account — users never hold database credentials. - Column-level access control. Deterministic, role-based masking and deny, driven by Cedar policy over per-column tags.
- Lineage-aware. It parses each query and follows sensitive values through
expressions, functions, subqueries, joins, and
SELECT *, so a masked column stays masked wherever it flows. Anything it cannot prove safe is denied by default through Cedar (fail-closed) — a policy decision, not a hardcoded error. - Just-in-time elevation. Time-boxed, revocable role grants through an approval workflow, so access widens only along an audited path.
- Tamper-evident audit. Every decision is written to a hash-chained log on
the decision path, so a statement cannot run unlogged. Verifying that chain,
anchoring it off-box, detecting anomalies, and exporting to a SIEM are the job
of
auditmon, a separate process you deploy and point at the store — it is not started by the default local stack.
A split control plane (Kotlin/JVM) and data plane (Go), talking over gRPC:
goproxy(Go) — the data-plane wire proxy: protocol codecs, token auth, a per-statementDecidecall to the control plane, inline result masking, and the backend broker.control-plane(Kotlin) — identity and roles (OIDC), Cedar policy, the catalog, the per-statement decision, and the admin/console API.analyzer(Go, reached from the JVM through a Foreign Function & Memory binding) — the sqlglot-go lineage probe that emits each statement's required grants.auditmon(Go) — the independent audit-trail monitor.
Two different things are called an engine here, and they are independent:
- Target databases — what proxy-monster protects. MySQL and PostgreSQL. MySQL is the primary, fully-enforced target; PostgreSQL is experimental.
- The control-plane store — what proxy-monster runs on. PostgreSQL only.
There is no MySQL-store option, and
PM_DB_URLmust be a PostgreSQL JDBC URL.
See ARCHITECTURE.md for the components, topology, and ports.
You need Docker, plus the toolchain pinned in mise.toml — JDK, Gradle, Go,
Node, and pnpm. Install it once, then one task brings up the whole local stack —
the PostgreSQL control-plane store, the control plane, a sample MySQL and
PostgreSQL target database with a wire proxy in front of each, and the web
console:
mise trust # a freshly cloned mise.toml is untrusted, and every mise command refuses it
mise install
mise run devRunning through mise matters: it pins the JDK for you. The build needs JDK 24,
because build.gradle.kts pins the Java compiler to --release 24, so an older
ambient JDK fails to compile.
The console is at http://localhost:41300. The full walkthrough — component by component, local and AWS — is in INSTALL.md.
- ARCHITECTURE.md — the components, topology, trust boundaries, and ports.
- INSTALL.md — install, run locally, and deploy (local + AWS ECS).
- DESIGN.md — the design decisions and the decision-to-enforcement flow.
- docs/ — the design-doc index, plus a summary of what's built.
- KNOWN_LIMITATIONS.md — accepted caveats and gaps.
- AGENTS.md — project entry point: intent, layout, conventions, and the control-plane HTTP route map.
- CONTRIBUTING.md — how to build, test, and contribute.
- SECURITY.md — how to report a vulnerability.
- CODE_OF_CONDUCT.md — the standards we hold each other to, and how to report a problem.
Licensed under the Apache License 2.0. Attribution that redistributors must carry forward is in NOTICE.