Bind OpenBao builds to approved inputs and secure credential delivery
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a0e75a-fc5c-7913-9dba-9846210c766d
This commit is contained in:
parent
ee1dc2b651
commit
2b83324c01
8 changed files with 622 additions and 84 deletions
|
|
@ -95,3 +95,93 @@ section does not exist until phase 4 has run.
|
|||
See `plans/rein-openweights-openrouter-approle.md` once T01 is
|
||||
implemented against this format — the first real plan, not a synthetic
|
||||
one, per `MASON-WP-0001`'s own scoping.
|
||||
|
||||
## Binding OpenBao approval to execution inputs
|
||||
|
||||
The AppRole and Kubernetes-auth builders additionally require two frontmatter
|
||||
fields: `build_spec` and `approved_spec_sha256`. `build_spec` is the complete
|
||||
value-free output of `ops_mason.executor.build_spec_document(spec)`. It includes
|
||||
the engine, exact policy/role/path and identity bindings, token bounds, policy
|
||||
reuse and content pin, delivery destination, audit destination, and executable.
|
||||
`credential_type` must match its `engine`.
|
||||
|
||||
During drafting, render the specification and its digest for review:
|
||||
|
||||
```python
|
||||
from pathlib import Path
|
||||
from ops_mason.executor import AppRoleKVSpec, build_spec_document, build_spec_digest
|
||||
|
||||
spec = AppRoleKVSpec(
|
||||
policy_name="workload-kv-read-example",
|
||||
kv_path="platform/workloads/example/runtime",
|
||||
approle_name="example",
|
||||
token_num_uses=8,
|
||||
delivery_dir=Path("/home/consumer/.local/example/approle"),
|
||||
audit_log_path=Path("/home/builder/ops-mason/audit/build-log.jsonl"),
|
||||
)
|
||||
document = build_spec_document(spec) # put this mapping under build_spec
|
||||
candidate_digest = build_spec_digest(document) # present alongside the review
|
||||
```
|
||||
|
||||
The digest is SHA-256 of UTF-8 JSON with sorted keys, compact separators and
|
||||
no NaN values. Paths render as absolute strings; tuples render as lists. All
|
||||
specification fields, including explicit defaults and null values, participate.
|
||||
After the founder approves that exact specification, record the digest as
|
||||
`approved_spec_sha256` alongside `approved_by`, `approved_at` and
|
||||
`status: approved`. Quote approval dates in YAML. A candidate digest alone
|
||||
is not approval, and the digest is an integrity marker, not a signature.
|
||||
|
||||
Before any OpenBao command, the builder reloads the plan from disk, checks
|
||||
approval and engine, validates the specification, and compares both the
|
||||
frontmatter mapping and approved digest to the actual inputs. Duplicate YAML
|
||||
keys, missing build specifications, changed scope or changed destinations are
|
||||
refused. Editing the mapping without renewing its approval digest cannot reuse
|
||||
the previous approval. The plan file remains the trust boundary: this does not
|
||||
protect against someone authorized to rewrite the approval record itself.
|
||||
|
||||
Historical plans stay historical. They are not automatically given new
|
||||
specifications or approvals. Before re-executing one, draft and review the exact
|
||||
new inputs through the existing four-phase process. No live lane was changed
|
||||
by this format migration.
|
||||
|
||||
### Input and policy constraints
|
||||
|
||||
The existing AppRole engine creates only exact KV-v2 read lanes: one literal
|
||||
entry path, `read` on data and metadata, no wildcard, empty/parent path segment,
|
||||
HCL injection, or write capability. OIDC matrix writers remain a separate,
|
||||
blocked contract under MASON-WP-0005. Role and policy names must be single
|
||||
literal names; Kubernetes service-account names/namespaces must be explicit,
|
||||
nonempty, unique DNS labels. Token use counts must be explicit nonnegative
|
||||
integers (zero is deliberately unlimited when approved); TTLs are positive
|
||||
integer durations in `s`, `m` or `h`, with maximum TTL at least initial TTL.
|
||||
`secret_id_ttl: "0"` remains an explicit reviewable choice.
|
||||
|
||||
For `AppRoleKVSpec(reuse_policy=True)`, also provide
|
||||
`reuse_policy_sha256`. For `KubernetesKVSpec`, provide `policy_sha256`, since
|
||||
that builder always binds an existing policy. During the scoped structure
|
||||
survey, hash the exact UTF-8 output of `bao policy read <name>`, including its
|
||||
trailing newline, and review that policy's full scope. The builder reads only
|
||||
policy text, checks its hash before auth-role writes, and refuses drift. A
|
||||
reused policy may deliberately cover more than the AppRole's nominal KV path;
|
||||
its reviewed contents, not that path field alone, define the grant. Rechecking
|
||||
a pin is not an atomic lock against later administrative policy changes.
|
||||
|
||||
### Credential delivery and failed builds
|
||||
|
||||
AppRole delivery requires an absolute directory. Every directory component is
|
||||
opened without following symlinks; missing directories are created privately.
|
||||
An existing final directory must belong to the executing account with mode
|
||||
0700. Both credential files are reserved exclusively at mode 0600 before any
|
||||
policy/auth write or credential issuance. Existing files, hardlinks and symlink
|
||||
paths are refused rather than overwritten or permission-repaired. Delivery
|
||||
uses the held file descriptors and flushes credentials to disk.
|
||||
|
||||
OpenBao error and timeout output is suppressed so a failed credential command
|
||||
cannot echo sensitive material. Audit output contains object names, the
|
||||
approved specification digest and approval attribution, never credentials.
|
||||
A failed build can leave private empty or partially delivered files, and may
|
||||
have changed policy/auth structure or issued a credential before failing.
|
||||
Do not blindly retry or delete them: inspect structure and audit metadata,
|
||||
resolve/revoke any partial issuance through the scoped custody procedure, and
|
||||
review a fresh delivery destination before retrying. The executor does not
|
||||
claim transactional rollback or automatically widen its revocation authority.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue