Record the passing hub-writer receipts.

Member and non-member verification both passed. The verifier accepts s. tokens and calls sys/capabilities with a token that is allowed to.

Assistant: grok
Assistant-Session: 01a13b2d-5f6d-7a32-b2c9-384625c55ca6
This commit is contained in:
tegwick 2026-10-14 22:14:32 +02:00
parent 05882b189f
commit 97d1fed949
7 changed files with 116 additions and 45 deletions

View file

@ -2,17 +2,15 @@
# Custodian Brief — ops-mason
**Domain:** infotech
**Last synced:** 2026-10-14 17:37 UTC
**Last synced:** 2026-10-14 17:49 UTC
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
## Active Workstreams
### Name a dedicated caller for the reuse-surface hub writer token
Progress: 2/4 done | workplan_id: `08e52353-b6e5-5742-b7b4-080d51a0cf57`
Progress: 3/4 done | workplan_id: `08e52353-b6e5-5742-b7b4-080d51a0cf57`
**Open tasks:**
- ! Apply the role without a KV write `7c32e273`
*(wait: After T02. Founder applies proposed CCR-2026-0044 through the delegated applier. No bao kv put. Do not attach the policy to the admin entity.)*
- ! Record the sanitized receipt `9e12db29`
*(wait: After T03. Founder runs scripts/verify-reuse-surface-hub-writer.py member and non-member. A live receipt does not exist yet.)*

View file

@ -0,0 +1,16 @@
mode=member
at=2026-10-14T20:05:45Z
addr=http://127.0.0.1:18200
role=reuse-surface-hub-writer-workload-kv-read
policy=workload-kv-read-reuse-surface-runtime
login=ok
entity_id=c204099b-cb94-363f-e207-5ff4d4aa6e94
policies=workload-kv-read-reuse-surface-runtime
identity_policies=
platform/data/workloads/reuse/reuse-surface/runtime-secrets: read
platform/metadata/workloads/reuse/reuse-surface/runtime-secrets: read
platform/data/workloads/reuse/reuse-surface: deny
platform/metadata/workloads/reuse/reuse-surface: deny
platform/data/workloads/issue-core/issue-core/issue-core-runtime: deny
revoked=yes
result=pass

View file

@ -0,0 +1,16 @@
mode=non-member
at=2026-10-14T20:10:49Z
addr=http://127.0.0.1:18200
role=reuse-surface-hub-writer-workload-kv-read
policy=workload-kv-read-reuse-surface-runtime
login=refused
entity_id=
policies=
identity_policies=
platform/data/workloads/reuse/reuse-surface/runtime-secrets: not-run
platform/metadata/workloads/reuse/reuse-surface/runtime-secrets: not-run
platform/data/workloads/reuse/reuse-surface: not-run
platform/metadata/workloads/reuse/reuse-surface: not-run
platform/data/workloads/issue-core/issue-core/issue-core-runtime: not-run
revoked=n/a
result=pass

View file

@ -2,7 +2,7 @@
Plan: `plans/reuse-surface-hub-writer.md`. Filed request:
`railiance-platform/credential-change-requests/CCR-2026-0044-reuse-surface-hub-writer-caller.yaml`
(proposed). Source copy:
(applied 2026-10-14). Source copy:
`builds/reuse-surface-hub-writer/credential-change-requests/CCR-DRAFT-REUSE-SURFACE-HUB-WRITER.yaml`.
Run this only after CCR-2026-0044 is approved and applied. LLDAP group
@ -15,9 +15,11 @@ shape go through
identity-provisioner `POST /v1/groups/ensure`; see
`docs/directory-group-binding.md`.
The script leaves `~/.vault-token` in place and uses it only to call
`sys/capabilities`. The lane token is not printed and is revoked before the
script exits. A passing receipt is the sanitized verification record.
The script leaves `~/.vault-token` in place. It calls `sys/capabilities` with
the first local token that is allowed to: `BAO_TOKEN` or `VAULT_TOKEN`, then
`~/.local/openbao/platform-admin.token`, then `~/.vault-token`. The lane token
is not printed and is revoked before the script exits. A passing receipt is
the sanitized verification record.
```bash
export BAO_ADDR=http://127.0.0.1:18200

View file

@ -140,7 +140,9 @@ key-cape confirms the group:
1. Copy the policy file over
`railiance-platform/openbao/policies/workload-kv-read-reuse-surface-runtime.hcl`
and apply the CCR with the delegated applier. Do not run `bao kv put`.
2. Keep an operator token in `~/.vault-token` for the capability query.
2. The capability query uses the first local token allowed to call
`sys/capabilities`: `BAO_TOKEN` or `VAULT_TOKEN`, then
`~/.local/openbao/platform-admin.token`, then `~/.vault-token`.
In a private window, as the group member:
```bash
@ -165,7 +167,11 @@ Do not export the field. Revoke the lane token when the command returns.
## 6. Result
Applied 2026-10-14T17:47:43Z. No live member receipt yet.
Applied 2026-10-14T17:47:43Z. Both attended receipts passed on 2026-10-14.
Member at 20:05:45Z is entity `c204099b-cb94-363f-e207-5ff4d4aa6e94` with
only `workload-kv-read-reuse-surface-runtime`. Non-member at 20:10:49Z was
refused. Copies are in `docs/evidence/2026-10-14-reuse-surface-hub-writer-member.txt`
and `docs/evidence/2026-10-14-reuse-surface-hub-writer-non-member.txt`.
2026-10-14: railiance-platform filed this bundle as proposed CCR-2026-0044
(`88b4aed`, message `14e23602`). The live policy file stays as it was until

View file

@ -6,11 +6,12 @@
Logs in on auth/netkingdom role reuse-surface-hub-writer-workload-kv-read with
``bao login -token-only``, so the operator's token helper is left alone. The
lane token stays in memory. Capability queries run as the operator token
already present in the environment or token helper, because the workload
policy has no sys/capabilities-self grant. The receipt records policies,
entity id, path capabilities, and pass/fail. It does not record the token or
any KV value.
lane token stays in memory. Capability queries use the first local token that
may call ``sys/capabilities`` (``BAO_TOKEN`` or ``VAULT_TOKEN``, then
``~/.local/openbao/platform-admin.token``, then ``~/.vault-token``), because
the workload policy has no sys/capabilities-self grant. The receipt records
policies, entity id, path capabilities, and pass/fail. It does not record the
token or any KV value.
Sign in with a private browser window. A reused platform-admin session is the
wrong principal for ``member``.
@ -43,7 +44,8 @@ from ops_mason.reuse_surface_hub_writer import (
)
BAO_ADDR = os.environ.get("BAO_ADDR", "http://127.0.0.1:18200")
TOKEN_RE = re.compile(r"\b(?:hvs|hvb|hvr)\.[A-Za-z0-9_-]{8,}\b")
# This OpenBao issues s. service tokens. hvs/hvb/hvr are the newer Vault shapes.
TOKEN_RE = re.compile(r"\b(?:hvs|hvb|hvr|s)\.[A-Za-z0-9_-]{8,}\b")
PATHS = [DATA, METADATA, PARENT_DATA, PARENT_METADATA, SIBLING]
@ -58,14 +60,45 @@ def receipts_dir() -> Path:
return path
def operator_token() -> str:
def token_candidates() -> list[tuple[str, str]]:
found: list[tuple[str, str]] = []
for name in ("BAO_TOKEN", "VAULT_TOKEN"):
value = os.environ.get(name, "").strip()
if value:
return value
helper = Path(os.environ.get("HOME", str(Path.home()))) / ".vault-token"
if helper.is_file():
return helper.read_text(encoding="utf-8").strip()
found.append((name, value))
home = Path(os.environ.get("HOME", str(Path.home())))
for label, path in (
("~/.local/openbao/platform-admin.token", home / ".local/openbao/platform-admin.token"),
("~/.vault-token", home / ".vault-token"),
):
if path.is_file():
value = path.read_text(encoding="utf-8").strip()
if value:
found.append((label, value))
return found
def write_capabilities(caller: str, subject: str, paths: list[str]) -> subprocess.CompletedProcess[str]:
body = json.dumps({"token": subject, "paths": paths})
tmp = tempfile.NamedTemporaryFile("w", prefix="rs-caps-", delete=False)
try:
os.fchmod(tmp.fileno(), stat.S_IRUSR | stat.S_IWUSR)
tmp.write(body)
tmp.close()
return run_bao(["write", "-format=json", "sys/capabilities", f"@{tmp.name}"], caller)
finally:
try:
os.remove(tmp.name)
except OSError:
pass
def operator_token() -> str:
"""Return a token allowed to call sys/capabilities, or an empty string."""
for _label, token in token_candidates():
probe = write_capabilities(token, token, ["auth/token/lookup-self"])
if probe.returncode == 0:
return token
return ""
@ -90,8 +123,8 @@ def login() -> str:
token="",
)
token = (proc.stdout or "").strip()
if proc.returncode != 0 or not token or TOKEN_RE.fullmatch(token) is None:
sys.stderr.write(redact(proc.stderr or "login refused\n"))
if proc.returncode != 0 or TOKEN_RE.fullmatch(token) is None:
sys.stderr.write(redact(proc.stderr or "login output was not a token\n"))
return ""
return token
@ -107,21 +140,10 @@ def lookup(token: str) -> dict:
def capabilities(operator: str, lane: str) -> dict[str, list[str]]:
if not operator:
raise RuntimeError(
"no operator token for sys/capabilities "
"(BAO_TOKEN, VAULT_TOKEN, or ~/.vault-token)"
"no token can call sys/capabilities "
"(BAO_TOKEN, VAULT_TOKEN, ~/.local/openbao/platform-admin.token, or ~/.vault-token)"
)
body = json.dumps({"token": lane, "paths": PATHS})
tmp = tempfile.NamedTemporaryFile("w", prefix="rs-caps-", delete=False)
try:
os.fchmod(tmp.fileno(), stat.S_IRUSR | stat.S_IWUSR)
tmp.write(body)
tmp.close()
proc = run_bao(["write", "-format=json", "sys/capabilities", f"@{tmp.name}"], operator)
finally:
try:
os.remove(tmp.name)
except OSError:
pass
proc = write_capabilities(operator, lane, PATHS)
if proc.returncode != 0:
raise RuntimeError(redact(proc.stderr or "sys/capabilities failed"))
payload = json.loads(proc.stdout)
@ -151,11 +173,17 @@ def main(argv: list[str]) -> int:
if mode not in {"member", "non-member"}:
sys.stderr.write("usage: verify-reuse-surface-hub-writer.py member|non-member\n")
return 2
operator = operator_token()
if not operator:
sys.stderr.write(
"no token can call sys/capabilities. Checked BAO_TOKEN, VAULT_TOKEN, "
"~/.local/openbao/platform-admin.token, and ~/.vault-token.\n"
)
return 1
sys.stderr.write(
f"Sign in as the {mode} identity in a private browser window.\n"
"A platform-admin session is the wrong principal for member.\n"
)
operator = operator_token()
now = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
lane = login()
report: dict = {

View file

@ -4,7 +4,7 @@ type: workplan
title: "Name a dedicated caller for the reuse-surface hub writer token"
domain: infotech
repo: ops-mason
status: active
status: finished
flavor: planning
owner: codex
topic_slug: custodian
@ -117,15 +117,20 @@ Done 2026-10-14.
```task
id: MASON-WP-0011-T04
status: wait
status: done
depends_on: [MASON-WP-0011-T03]
blocked_on: human
blocking_reason: "After T03. Founder runs scripts/verify-reuse-surface-hub-writer.py member and non-member. A live receipt does not exist yet."
priority: high
state_hub_task_id: "9e12db29-532d-5d90-8519-227799018ab0"
```
Both modes must pass. Copy the mode-0600 receipts into `docs/evidence/`
with no token and no field value, reply to message `08b254af`, and tell
ops-warden the role name for `auth_method`. Hub registration itself stays
Both modes passed on 2026-10-14. Member receipt at 20:05:45Z: login ok,
entity `c204099b-cb94-363f-e207-5ff4d4aa6e94`, policy
`workload-kv-read-reuse-surface-runtime` only, exact paths read, parent and
sibling paths deny, token revoked. Non-member receipt at 20:10:49Z:
login refused. Copies with no token are
`docs/evidence/2026-10-14-reuse-surface-hub-writer-member.txt` and
`docs/evidence/2026-10-14-reuse-surface-hub-writer-non-member.txt`.
Replied to message `08b254af`. ops-warden can name role
`reuse-surface-hub-writer-workload-kv-read` on
`auth_method` for `reuse-surface-hub-write-token`. Hub registration stays
with the-custodian.