// Policy for the Centralis control-plane container on vps2. // // Centralis is the tool an operator drives a rotation THROUGH, so it needs more than // a host render does: it must enumerate key names across every environment to build // `secrets_inventory`, and write values to perform `secrets_rotate`. // // The split below is the important part. Centralis gets: // * METADATA read/list on every path -> it can build a names-and-versions // inventory across all three environments WITHOUT being able to read a value. // * DATA write on every path -> it can rotate. // * DATA read on NOTHING. // // That is a genuine improvement on the SOPS design, not a port of it. Today // `secrets_inventory` can list key names without a decryption key only because SOPS // happens to leave key names as plaintext in the YAML — a property of the file // format, relied on deliberately (tools/secrets.ts:199 `extractKeyNames`). Under // OpenBao the same "names, never values" guarantee becomes an ENFORCED capability // boundary instead of a fortunate accident. Centralis cannot print a secret it is // not able to fetch. // // The `read` omission is load-bearing: Centralis holds the Docker socket (root // -equivalent on prod) and an SSH private key to beta and dev. Granting it data read // on prod's secrets would make a Centralis compromise equivalent to full estate // credential disclosure. It already effectively is via the Docker socket — but there // is no reason to hand it a second, easier path. // Names and version history across the whole tree — no values. path "thermograph/metadata/*" { capabilities = ["read", "list"] } // Rotation: write a new version. Note "create" + "update" but NOT "read": // OpenBao permits a blind write, which is exactly the shape secrets_rotate wants — // it mints or receives a new value and stores it, and never needs the old one. path "thermograph/data/*" { capabilities = ["create", "update"] } // Its OWN configuration is the one place Centralis may read, because it must render // /etc/centralis.env for itself. This is the direct analogue of centralis.prod.yaml. path "thermograph/data/centralis/prod" { capabilities = ["read", "create", "update"] } // Version rollback, so a bad rotation is recoverable through the control plane // rather than requiring a shell on the box. This is the capability that replaces // "revert the PR" in the SOPS model. path "thermograph/undelete/*" { capabilities = ["update"] } path "thermograph/destroy/*" { capabilities = ["deny"] } path "auth/token/lookup-self" { capabilities = ["read"] } path "auth/token/renew-self" { capabilities = ["update"] } // Read its own AppRole role-id for self-diagnosis, but never the secret-id. path "auth/approle/role/tg-centralis/role-id" { capabilities = ["read"] }