73 lines
2.8 KiB
HCL
73 lines
2.8 KiB
HCL
|
|
// Policy for the DEV host's render identity (vps1).
|
||
|
|
//
|
||
|
|
// THIS FILE IS THE POINT OF THE MIGRATION.
|
||
|
|
//
|
||
|
|
// infra/CLAUDE.md states the rule: "vps1 must never hold prod credentials. It's the
|
||
|
|
// box that runs Forgejo, its CI runner, and dev's unreviewed branch — the opposite of
|
||
|
|
// an isolation boundary."
|
||
|
|
//
|
||
|
|
// Today that rule is enforced by a SHELL FLAG (THERMOGRAPH_SECRETS_SKIP_COMMON=1) set
|
||
|
|
// by the *caller*, at three separate call sites: env-topology.sh:196 -> deploy.sh:67,
|
||
|
|
// deploy-dev.sh:86, and infra-sync.yml:93-95. The renderer itself does not know that
|
||
|
|
// env=dev means never-common. A fourth call site, or one by-hand
|
||
|
|
// `render_thermograph_secrets /opt/thermograph-dev/infra dev`, writes both S3
|
||
|
|
// keypairs (one read-write on the bucket holding prod's database backups), the VAPID
|
||
|
|
// private key that signs Web Push to real subscribers, REGISTRY_TOKEN, and the
|
||
|
|
// IndexNow and metrics tokens onto the Forgejo CI-runner box — and exits 0.
|
||
|
|
//
|
||
|
|
// Under this policy that is no longer possible to get wrong. dev's identity cannot
|
||
|
|
// read the common path. A misconfigured caller gets a 403 from OpenBao, not a silent
|
||
|
|
// success with production credentials on disk. The failure class is gone, not guarded.
|
||
|
|
|
||
|
|
// dev's own values. This is the ONLY secret path dev can read.
|
||
|
|
path "thermograph/data/env/dev" {
|
||
|
|
capabilities = ["read"]
|
||
|
|
}
|
||
|
|
|
||
|
|
path "thermograph/metadata/env/dev" {
|
||
|
|
capabilities = ["read", "list"]
|
||
|
|
}
|
||
|
|
|
||
|
|
// EXPLICIT DENY on the shared production credential set.
|
||
|
|
//
|
||
|
|
// A deny rule is redundant with OpenBao's default-deny — anything not granted is
|
||
|
|
// already refused. It is here anyway, and must stay, for two reasons:
|
||
|
|
// 1. It is documentation that survives refactoring. Someone widening dev's grants
|
||
|
|
// has to delete an explicit deny to break the rule, which is a much louder edit
|
||
|
|
// than adding a path to an allow list.
|
||
|
|
// 2. In OpenBao, a deny on a path beats any grant at that path regardless of rule
|
||
|
|
// order or specificity. So if dev's identity is ever accidentally given a
|
||
|
|
// broader policy alongside this one, this still wins.
|
||
|
|
path "thermograph/data/common" {
|
||
|
|
capabilities = ["deny"]
|
||
|
|
}
|
||
|
|
|
||
|
|
path "thermograph/metadata/common" {
|
||
|
|
capabilities = ["deny"]
|
||
|
|
}
|
||
|
|
|
||
|
|
// Deny the other environments outright. Same argument: dev has no business reading
|
||
|
|
// beta or prod, and being explicit means a widened grant elsewhere cannot silently
|
||
|
|
// re-open it.
|
||
|
|
path "thermograph/data/env/prod" {
|
||
|
|
capabilities = ["deny"]
|
||
|
|
}
|
||
|
|
|
||
|
|
path "thermograph/data/env/beta" {
|
||
|
|
capabilities = ["deny"]
|
||
|
|
}
|
||
|
|
|
||
|
|
path "thermograph/data/centralis/*" {
|
||
|
|
capabilities = ["deny"]
|
||
|
|
}
|
||
|
|
|
||
|
|
// Token self-management, so the render can look up and renew its own lease without
|
||
|
|
// needing a broader grant.
|
||
|
|
path "auth/token/lookup-self" {
|
||
|
|
capabilities = ["read"]
|
||
|
|
}
|
||
|
|
|
||
|
|
path "auth/token/renew-self" {
|
||
|
|
capabilities = ["update"]
|
||
|
|
}
|