QueryProxy

What is database access control?

Updated:

Database access control is how an organisation decides three things: who may reach a database, what they may do once they are there, and what they are allowed to see in the result. Most teams have an answer to the first, a partial answer to the second, and no answer at all to the third.

The three layers

Who may connect

This is the layer everyone builds first: network rules, a bastion host or VPN, SSH keys, and credentials held in a password manager. It answers a real question and answers it well. Its limit is that its job ends the moment the connection is established.

What they may do

The database’s own permission system lives here — GRANT, roles, row-level security where the engine supports it. It is genuinely powerful and genuinely coarse. A read-only role permits SELECT across every column of every row. A role permitting UPDATE cannot tell a careful one-row change from a statement with no WHERE clause that rewrites the whole table.

What they may see

The layer most teams skip. Even a correctly scoped read returns real email addresses, real phone numbers and real card numbers — onto a laptop, into a terminal’s scrollback, sometimes into a spreadsheet that outlives the incident it was pulled for.

Why the layers do not add up

The gap is structural rather than a failure of configuration. Network controls cannot read SQL. Database grants cannot judge intent. Neither can mask a result.

So the common arrangement — a bastion plus a read-only role plus a credential in a vault — leaves a real hole: an authenticated engineer with a legitimate reason runs a legitimate-looking query and receives unmasked production data, and the only record is that a connection happened.

Practices that close it

Least privilege, actually applied. Read-only where reads suffice; one schema rather than the whole instance; no standing production access for anyone who does not need it daily.

No shared credentials. A password two people know is a password with no owner. Every action should trace to a person. The post on production access without shared passwords shows the alternative.

Review the statement, not just the identity. Parsing the SQL before it runs catches the UPDATE with no WHERE and the unbounded SELECT that authentication never could.

Approval by a second person. The same logic as code review: cheap, and it catches what the author could not see about their own work.

Mask on the way out. If PII is masked as results stream to storage, an unmasked copy never exists to leak.

Log immutably. Who asked, who approved, what ran, how long it took, what it touched — in a store that permits inserts and reads but not edits.

By database engine

The idea is the same on every engine, but what the engine itself offers, and what a guard has to block, differs. Engine-specific pages cover PostgreSQL, MySQL and MariaDB and SQL Server. SQLite targets are supported too: the SQL guards reference lists that the guard blocks ATTACH, DETACH, VACUUM ... INTO and load_extension(, and a setting can limit which files a connection may open. To see how QueryProxy compares with other ways of reaching a database, read the comparisons.

Compliance

Auditors ask the same question of database access: who could reach the data, who approved a change, and can you show it. QueryProxy helps produce that evidence; it does not make anyone pass an audit. Each page below lists the controls it relates to, and what stays with your organization:

Where QueryProxy fits

QueryProxy implements the second and third layers, and assumes you already have the first. Developers never hold production credentials; they submit SQL against connections a DBA granted them. Statements are parsed before they run. A DBA approves from the web queue or from a Slack card, and no DBA may approve their own request — only an administrator can override that, and the override is flagged in the audit log. Results come back limited, masked by your rules before they touch disk, and recorded in an append-only audit log that the application never edits or deletes from.

It is not a replacement for your network controls or your database’s own grants. It is the layer that sits between them and asks the question neither one can: should this particular statement run, and who else agrees?

Read the introduction for how a request travels end to end, or compare QueryProxy with a bastion host for what changes against the usual setup.

Frequently asked

What is database access control?
Database access control is the set of rules and mechanisms that decide who may connect to a database, which operations they may perform, and what data they are allowed to see in the result. It spans the database's own GRANT system, the network path, and any approval or masking layer in front of it.
Is database access control the same as authentication?
No. Authentication establishes who someone is. Access control decides what that identity may then do. A system can authenticate perfectly and still let every engineer run DELETE against production, because those are separate questions.
What is the principle of least privilege?
Granting each identity the narrowest set of permissions that still lets it do its job, rather than a broad role that happens to include what it needs. In database terms it means read-only where reads suffice, one schema rather than the whole instance, and no standing production access for anyone who does not need it daily.
Why is role-based access control not enough on its own?
Roles are coarse. A read-only role still permits SELECT over every column of every row, including personal data, and a role that permits UPDATE cannot distinguish a careful one-row update from a WHERE-less statement that rewrites the table. Roles say who may act; they cannot review the specific statement.

Arrow keys to move, Enter to open.