MASON-WP-0015-T03: deny comma-string token_policies in ops-mason-construct
Live probe showed token_policies=workload-kv-read-x,default passes the workload-kv-read-* glob as one string. Login denies held; this closes the role-policy limit. Reinstall required. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Assistant: claude-code Assistant-Model: opus Assistant-Process: 278674@bnt-lap001 Assistant-Session: 64827407-e196-4ce3-b70c-76e7b537493f
This commit is contained in:
parent
ea847816ad
commit
482a08b40e
4 changed files with 122 additions and 35 deletions
|
|
@ -2,19 +2,18 @@
|
|||
# Custodian Brief — ops-mason
|
||||
|
||||
**Domain:** infotech
|
||||
**Last synced:** 2026-10-18 09:49 UTC
|
||||
**Last synced:** 2026-10-18 09:50 UTC
|
||||
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
|
||||
|
||||
## Active Workstreams
|
||||
|
||||
### Restore ops-mason as the OpenBao builder: the ops-mason-construct grant
|
||||
Progress: 1/6 done | workplan_id: `384b3efc-f9a5-5ea9-b224-0ce900e79804`
|
||||
Progress: 2/6 done | workplan_id: `384b3efc-f9a5-5ea9-b224-0ce900e79804`
|
||||
|
||||
**Open tasks:**
|
||||
- ! Live negative and positive tests `8b512822`
|
||||
- · Install the policy (founder act) `1c8893bd`
|
||||
- · Executor and post-build check `7b7a436f`
|
||||
- · Align ops-warden and railiance-platform references `8fbac212`
|
||||
- · Close the Kubernetes variant `feb17422`
|
||||
|
||||
### Describe every stored credential so the store is navigable
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@
|
|||
| task | MASON-WP-0015-T02 | todo | — | workplans/MASON-WP-0015-construct-grant.md |
|
||||
| task | MASON-WP-0015-T03 | wait | — | workplans/MASON-WP-0015-construct-grant.md |
|
||||
| task | MASON-WP-0015-T04 | todo | — | workplans/MASON-WP-0015-construct-grant.md |
|
||||
| task | MASON-WP-0015-T05 | todo | — | workplans/MASON-WP-0015-construct-grant.md |
|
||||
| task | MASON-WP-0015-T05 | done | — | workplans/MASON-WP-0015-construct-grant.md |
|
||||
| task | MASON-WP-0015-T06 | todo | — | workplans/MASON-WP-0015-construct-grant.md |
|
||||
| intake | MASON-IN-0001 | closed | green | intakes/intakes.md |
|
||||
| intake | MASON-IN-0002 | closed | — | intakes/intakes.md |
|
||||
|
|
|
|||
|
|
@ -23,22 +23,59 @@
|
|||
# specific path wins, and a `+` segment loses to a literal one. The denies below
|
||||
# are literal or more specific than the grants they bound.
|
||||
#
|
||||
# allowed_parameters: OpenBao glob support on list-valued parameters must be
|
||||
# confirmed by the negative tests in MASON-WP-0015-T03 before this is relied on.
|
||||
# allowed_parameters: OpenBao matches a comma string ("workload-kv-read-x,default")
|
||||
# against the glob as one value before splitting it (MASON-WP-0015-T03 probe,
|
||||
# 2026-10-18), so token_policies containing a comma is denied outright. A JSON
|
||||
# list is checked element by element; pass several policies that way.
|
||||
|
||||
# --- everything the survey grant can read -----------------------------------
|
||||
path "sys/mounts" { capabilities = ["read", "list"] }
|
||||
path "sys/auth" { capabilities = ["read", "list"] }
|
||||
path "sys/policies/acl" { capabilities = ["list"] }
|
||||
path "auth/approle/role" { capabilities = ["list"] }
|
||||
path "auth/netkingdom/role/*" { capabilities = ["read", "list"] }
|
||||
path "auth/jwt/role/*" { capabilities = ["read", "list"] }
|
||||
path "auth/keycape-services/role/*" { capabilities = ["read", "list"] }
|
||||
path "operators/metadata/*" { capabilities = ["read", "list"] }
|
||||
path "sys/capabilities" { capabilities = ["update"] }
|
||||
path "sys/capabilities-self" { capabilities = ["update"] }
|
||||
path "auth/token/lookup-self" { capabilities = ["read"] }
|
||||
path "auth/token/revoke-self" { capabilities = ["update"] }
|
||||
path "sys/mounts" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
|
||||
path "sys/auth" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
|
||||
path "sys/policies/acl" {
|
||||
capabilities = ["list"]
|
||||
}
|
||||
|
||||
path "auth/approle/role" {
|
||||
capabilities = ["list"]
|
||||
}
|
||||
|
||||
path "auth/netkingdom/role/*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
|
||||
path "auth/jwt/role/*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
|
||||
path "auth/keycape-services/role/*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
|
||||
path "operators/metadata/*" {
|
||||
capabilities = ["read", "list"]
|
||||
}
|
||||
|
||||
path "sys/capabilities" {
|
||||
capabilities = ["update"]
|
||||
}
|
||||
|
||||
path "sys/capabilities-self" {
|
||||
capabilities = ["update"]
|
||||
}
|
||||
|
||||
path "auth/token/lookup-self" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
|
||||
path "auth/token/revoke-self" {
|
||||
capabilities = ["update"]
|
||||
}
|
||||
|
||||
# Every policy stays readable for the survey and for verification.
|
||||
path "sys/policies/acl/*" {
|
||||
|
|
@ -56,12 +93,15 @@ path "sys/policies/acl/workload-kv-read-*" {
|
|||
# Role may carry only workload-kv-read-* policies; legacy `policies` refused.
|
||||
path "auth/kubernetes/role/external-secrets-*" {
|
||||
capabilities = ["create", "read", "update", "delete", "list"]
|
||||
|
||||
allowed_parameters = {
|
||||
"token_policies" = ["workload-kv-read-*"]
|
||||
"*" = []
|
||||
}
|
||||
|
||||
denied_parameters = {
|
||||
"policies" = []
|
||||
"policies" = []
|
||||
"token_policies" = ["*,*"]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -74,12 +114,15 @@ path "auth/kubernetes/role/*" {
|
|||
# lane's credential delivery stays a founder act.
|
||||
path "auth/approle/role/+" {
|
||||
capabilities = ["create", "read", "update", "delete"]
|
||||
|
||||
allowed_parameters = {
|
||||
"token_policies" = ["workload-kv-read-*"]
|
||||
"*" = []
|
||||
}
|
||||
|
||||
denied_parameters = {
|
||||
"policies" = []
|
||||
"policies" = []
|
||||
"token_policies" = ["*,*"]
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -108,26 +151,69 @@ path "platform/metadata/*" {
|
|||
}
|
||||
|
||||
# --- the grant cannot widen itself or every token ---------------------------
|
||||
path "sys/policies/acl/ops-mason-construct" { capabilities = ["deny"] }
|
||||
path "sys/policies/acl/ops-mason-survey" { capabilities = ["deny"] }
|
||||
path "sys/policies/acl/default" { capabilities = ["deny"] }
|
||||
path "sys/policies/acl/root" { capabilities = ["deny"] }
|
||||
path "sys/policies/acl/ops-mason-construct" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
path "sys/policies/acl/ops-mason-survey" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
path "sys/policies/acl/default" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
path "sys/policies/acl/root" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
# --- never become what it builds ---------------------------------------------
|
||||
path "auth/approle/role/+/role-id" { capabilities = ["deny"] }
|
||||
path "auth/approle/role/+/secret-id" { capabilities = ["deny"] }
|
||||
path "auth/approle/role/+/secret-id/*" { capabilities = ["deny"] }
|
||||
path "auth/approle/role/+/secret-id-accessor/*" { capabilities = ["deny"] }
|
||||
path "auth/approle/role/+/custom-secret-id" { capabilities = ["deny"] }
|
||||
path "auth/token/create" { capabilities = ["deny"] }
|
||||
path "auth/token/create/*" { capabilities = ["deny"] }
|
||||
path "auth/token/create-orphan" { capabilities = ["deny"] }
|
||||
path "auth/approle/role/+/role-id" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
path "auth/approle/role/+/secret-id" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
path "auth/approle/role/+/secret-id/*" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
path "auth/approle/role/+/secret-id-accessor/*" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
path "auth/approle/role/+/custom-secret-id" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
path "auth/token/create" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
path "auth/token/create/*" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
path "auth/token/create-orphan" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
# --- never read a value --------------------------------------------------------
|
||||
path "platform/data/*" { capabilities = ["deny"] }
|
||||
path "operators/data/*" { capabilities = ["deny"] }
|
||||
path "secret/data/*" { capabilities = ["deny"] }
|
||||
path "platform/data/*" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
path "operators/data/*" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
path "secret/data/*" {
|
||||
capabilities = ["deny"]
|
||||
}
|
||||
|
||||
# Not granted, on purpose: sys/mounts/* and sys/auth/* (no new mounts or auth
|
||||
# methods), auth/token/revoke (other tokens), operators/ and secret/ writes,
|
||||
# any policy outside workload-kv-read-*, any role outside the two shapes above.
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ def test_role_writes_restrict_token_policies():
|
|||
if path.startswith("auth/") and "/role/" in path and _caps(body) & {"create", "update"}:
|
||||
assert '"token_policies" = ["workload-kv-read-*"]' in body, path
|
||||
assert re.search(r'denied_parameters\s*=\s*\{\s*"policies"\s*=\s*\[\]', body), path
|
||||
# Comma strings bypass the glob (MASON-WP-0015-T03).
|
||||
assert re.search(r'"token_policies"\s*=\s*\["\*,\*"\]', body), path
|
||||
|
||||
|
||||
def test_no_mount_or_auth_method_writes():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue