diff --git a/00-META/process/06-writing-a-module.md b/00-META/process/06-writing-a-module.md index e0064ee..9edadce 100644 --- a/00-META/process/06-writing-a-module.md +++ b/00-META/process/06-writing-a-module.md @@ -38,10 +38,35 @@ Three questions, answered from the machine: it and removed after them. 4. **Put every secret in a file, never in `env`.** A declaration travels over the broker in plain - text: a password in `env` is a password the broker sees. Use `env-file` for containers, or - `${secret:name}` inside a config file the module supplies. **The mesh delivers parts; a module + text: a password in `env` is a password the broker sees. **The mesh delivers parts; a module that needs them combined combines them.** + **A sealed file holds the password and nothing else** — no key, no `=`, no newline that means + anything. So `env-file` must never point at one. It points at a file the module *declares*, + whose content leaves a hole: + + ``` + own-secrets superuser → /var/lib/postgres/superuser.secret the password, alone + a file /var/lib/postgres/superuser.env, mode 0600, + content: POSTGRES_PASSWORD=${secret:superuser} + the container env-file: [/var/lib/postgres/superuser.env] + ``` + + The host fills the hole on the machine, which is the only place both halves exist — the mesh + discarded the value + ([credentials and their rotation](../../03-DESIGN/01-to-be/13-credentials-and-their-rotation.md)). + A **provisioner** is the exception: it reads a password file, so it mounts the `.secret` + directly. + + Every example module in `mesh-control` had this wrong and shipped: `own-secrets` pointing at a + path *named* `.env`, mounted as `env-file`, holding a bare password. Docker reads that as a + malformed line and the container starts **with no password set at all** — not a failure to + start, a service running on the wrong credential. They parsed and they resolved. Two tests in + `examples/modules` now refuse both halves of it. + + Add `restart-on` naming the env file, or the container keeps the credential it started with + through every rotation. + 5. **Pin every image by digest.** A tag moves. The manifest in a repository names artifacts; the manifest the mesh holds names digests, and they are not the same document.