Repository navigation
fix(vault-human-auth-iac): let tenants browse to their folder in the UI - #1655
Conversation
A tenant user signing in to the Vault UI saw an empty secret/ engine: human-tenant-<t> granted list only under secret/metadata/teams/<t>/*, so the UI could not walk down to the tenant folder, and the user had to know to type teams/<t>/ into "View secret". Grant list, and nothing else, on exactly secret/metadata/ and secret/metadata/teams/, with no glob. Those two listings reveal the top-level key names and the tenant folder names, which are public in platform-gitops/tenants/. Another tenant's folder and everything under platform/ stay 403; proven on a local Vault 1.17.2 both ways (without the rules the listing is 403, with a glob another tenant's folder is listable).
|
Claude finished @mashkovd's task in 2m 16s —— View job Review complete ✅
Verdict: APPROVE (0 P1, 0 P2, 1 P3) What changed: adds two static, non-glob ACL rules to every Checked:
1 P3 nit posted inline: the two browse rules are identical literals duplicated into every tenant's policy via |
Antigravity (agy) review — informationalModel: gemini-3.8-flash-medium · commit FindingsFinding 1 (P3)
|
|
|
||
| path "secret/metadata/teams/" { | ||
| capabilities = ["list"] | ||
| } |
There was a problem hiding this comment.
P3: The two browse rules (secret/metadata/ and secret/metadata/teams/, list-only) are identical literal strings duplicated into every tenant's human-tenant-<tenant> policy via this for_each. Functionally fine (exact-match paths, well tested per the PR description), but since the rule doesn't depend on each.key, it could instead live on a single shared policy attached to every tenant group, avoiding N duplicate copies and keeping terraform plan diffs smaller when this rule ever changes. Not blocking.
There was a problem hiding this comment.
Deferred (P3). Keeping the rules inside each tenant's own policy is deliberate: a tenant token carries exactly one human-tenant policy, so its access can be read off that policy alone, and a shared policy would be one more attachment to keep in sync per group. The duplication is two short exact-path rules per tenant.
There was a problem hiding this comment.
No P1/P2 findings (1 P3). Vault ACL semantics check out: the two new rules are exact (non-glob) paths granting list-only on secret/metadata/ and secret/metadata/teams/, so they don't widen read/write/delete/destroy anywhere, and don't let a tenant list another tenant's folder (secret/metadata/teams// remains unmatched by any rule). Matches the PR's documented proof. Good to merge.
|
agy P3 (no CI policy assertions): deferred. The rendered policy was proven both ways against Vault 1.17.2 (see the PR body and runbook); a CI harness that boots Vault and asserts tenant policies is a separate piece of work. Copilot did not review (quota). |
Problem
In a live end-to-end test, a tenant user signed in to the Vault UI through
mctl, opened thesecret/engine and saw an empty list.human-tenant-<t>grantslistonly undersecret/metadata/teams/<t>/*, so the UI could not walk down to the tenant folder. The user had to know to typeteams/<t>/into "View secret" by hand.Change
Every generated
human-tenant-<t>policy gets two exact, list-only rules:The UI can then walk
secret/->teams/-><tenant>/. The database deny rules and every other rule are unchanged. The runbook (docs/runbooks/vault-human-auth.md) documents the browse path and the proof.Why this does not open other tenants (Vault semantics)
*or+is an exact match, solistonsecret/metadata/teams/covers only the LIST request on that one path.secret/metadata/teams/<other>/is a different path, matched by no rule, so it is denied. This holds at every depth.listgives noread. Reading the metadata ofsecret/metadata/teamsitself is still 403.metadata/only. Nothing underdata/,delete/,undelete/ordestroy/is widened.Disclosure trade-off
A tenant user can now see two listings, and nothing else:
secret/. Today these areplatform/andteams/, both already named throughout this repository's docs.secret/teams/. These are the tenant names, already public inplatform-gitops/tenants/, plus any platform-owned folder kept underteams/.Neither listing reveals a secret, a key inside another folder, or any metadata. The alternative was keeping the UI empty and having tenants type paths by hand, which is what triggered this.
If a folder name directly under
teams/ever has to stay private from tenants, it does not belong there. Move it underplatform/.Proof (local Vault 1.17.2, both ways)
The test used a token holding only the rendered
human-tenant-erpactpolicy. A second tenantotherand aplatform/tree were seeded. A check passes only on success or an explicitpermission denied; any other error fails it.secret/metadata/,.../teams/and.../teams/erpact/allowed. Listteams/other/,teams/other/<svc>/andplatform/denied. Readingteamsmetadata and anything underother/denied. Writes atteams/xor a top-level key denied. Deletingsecret/metadata/teamsdenied. Own read/write allowed.databasewrite, soft delete,destroyand own metadata delete denied.secret/metadata/teams/*instead of the exact pathteams/other/andteams/other/<svc>/become listable.This module has no test harness; a CI policy matrix is tracked in #1624. Its matrix should include these rows.
Rollout
Merging changes the
vault_policy.tenant[*]resources in place (update, whichallowedActionsalready allows). The next PostSync Job, or the hourly run, applies it, and the run after that reports no changes.🤖 Generated with Claude Code
https://claude.ai/code/session_01D1kGUJMWeA8hyhQuxKuHd2