Files
mesh-lab/provisioners/README.md
T
jschoubben e89379fef8 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.
2026-08-30 01:29:46 +02:00

2.2 KiB

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:

{
  "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.