Prove a mesh credential becomes a login, against a real database
The mesh generates a password, seals it to the machine that must accept it, and discards the plaintext — so it cannot tell PostgreSQL to start accepting it. Something on that machine reads what the host wrote and makes it true. Everything up to that step is proven elsewhere; this is where a password either becomes a login or does not. A scenario with one machine and a database, and six assertions: the password works, running again reaches the same state and says nothing, rotation makes the new one work and the old one stop, a departed consumer loses its login, a role nobody here made is left alone, and a manifest naming a credential that was never written is refused rather than creating a login with no password. Each was confirmed to fail — and only it to fail — with the behaviour removed from the provisioner: only-creates breaks rotation, no-revoke breaks revocation, revoking everything breaks the bystander role, and ignoring a missing credential breaks the refusal. Two faults in the test itself, both worth recording: - it checked logins from inside the database's own container over 127.0.0.1, which PostgreSQL's default pg_hba trusts. No password was ever verified. Demonstrated directly: over loopback a deliberately wrong password still returns a row. Only the rotation assertion noticed, because it is the one that requires a password to STOP working — which is an argument for writing that assertion every time. - the fix then read .NetworkSettings.IPAddress, which docker 29 no longer populates. It templates to empty, psql falls back to a unix socket that is not there, and every login looks impossible rather than misconfigured.
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
# Provisioners
|
||||
|
||||
The half that makes a credential real.
|
||||
|
||||
The mesh generates a password, seals it to the machine that must accept it, and never holds the
|
||||
value — so it cannot tell PostgreSQL, or MinIO, or a broker, to start accepting it. Something on
|
||||
that machine reads what arrived and makes it true. That something is a provisioner, and it belongs
|
||||
to the module that ships the software, not to the mesh.
|
||||
|
||||
**What the mesh owns is the contract.** A provider module declares:
|
||||
|
||||
```json
|
||||
{
|
||||
"provides": [{"name": "database", "scope": "mesh"}],
|
||||
"receives": {"database": "/var/lib/postgres/grants/mesh.json"},
|
||||
"grants": {"database": "/var/lib/postgres/grants"}
|
||||
}
|
||||
```
|
||||
|
||||
and is then given, by the host, from an ordinary declaration:
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| `mesh.json` | every consumer, what it asked for, and where its credential is |
|
||||
| `<node>.secret` | one consumer's password, alone in the file, sealed in transit and written in plain by the host |
|
||||
|
||||
Two files rather than one because the mesh discarded the plaintext and cannot compose a document
|
||||
containing it. The consequence is a good one: the readable half stays readable, and the secret
|
||||
half changes only when the secret does.
|
||||
|
||||
**A provisioner reconciles; it is not told what changed.** It runs after every declaration and
|
||||
must reach the same state from wherever it starts. That means, in order:
|
||||
|
||||
1. every consumer in the manifest has what it asked for, with the password it was given — set
|
||||
every time, not only on creation, or a rotation reports success and changes nothing
|
||||
2. **everything this provisioner made that is no longer asked for is removed.** A consumer that
|
||||
goes away otherwise leaves a working login behind for ever, and nothing says so
|
||||
|
||||
Step 2 is the half usually missing, and it is the same rule the host follows about removing what
|
||||
it declared and no longer declares.
|
||||
|
||||
The reference implementation lives in `mesh-control/examples/postgres-provisioner`, because that
|
||||
is where the contract is defined and where the language is already set up to read it. The lab's
|
||||
job is the other half: raising a real PostgreSQL and proving that what the mesh delivered becomes
|
||||
a login that works, a rotation that takes effect, and a revocation that bites.
|
||||
|
||||
Set `MESH_LAB_PROVISIONER` to a built one to run those.
|
||||
Reference in New Issue
Block a user