feat: adopt security zones and explicit workload refs
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a0291a-1e87-7151-9934-fcbfe3f65eb1
This commit is contained in:
parent
12c637cbf2
commit
7ce58ae638
52 changed files with 1547 additions and 658 deletions
|
|
@ -1,347 +1,196 @@
|
|||
# Policy-Gated SSH Signing
|
||||
# Zone-aware policy-gated signing
|
||||
|
||||
Date: 2026-06-23
|
||||
Status: **implemented (opt-in)** — WARDEN-WP-0007; policy package confirmed FLEX-WP-0006
|
||||
Ops-warden asks flex-auth for a decision before SSH certificate issuance. The
|
||||
gate is resource-scoped through security-zone membership; there is no repo-wide
|
||||
enable switch.
|
||||
|
||||
By default `warden sign` authorizes via **inventory allow-list** and TTL policy
|
||||
only. When `policy.enabled: true` in `warden.yaml`, ops-warden calls flex-auth
|
||||
before signing and records the decision id in `signatures.log`.
|
||||
Authority stays split:
|
||||
|
||||
---
|
||||
- flex-auth owns the versioned pre-sign stance (`enforced`, `advisory`, or
|
||||
`exempt`) and returns the decision;
|
||||
- ops-warden owns what the PEP does when flex-auth is unavailable or invalid;
|
||||
- the workload owner declares identity and zone membership;
|
||||
- zone-engine owns `security-zones_v0.1` admission and resolution semantics.
|
||||
|
||||
## Flow
|
||||
Binding decisions: `ADR-0009` (current) and `ADR-0006` (superseded rationale).
|
||||
|
||||
## Request path
|
||||
|
||||
```text
|
||||
warden sign <actor> --pubkey <path>
|
||||
|
|
||||
v
|
||||
Load actor from inventory (type, principals, ttl)
|
||||
|
|
||||
v
|
||||
policy.enabled?
|
||||
no -> skip
|
||||
yes -> flex-auth POST /v1/check
|
||||
|
|
||||
+-- DENY / unreachable (fail_closed) -> CAError
|
||||
|
|
||||
v ALLOW
|
||||
CABackend.sign() (local or OpenBao SSH engine)
|
||||
|
|
||||
v
|
||||
Append signatures.log (+ policy_decision_id when set)
|
||||
warden sign <actor>
|
||||
-> inventory, principal, actor-type, and TTL checks
|
||||
-> resource id ssh-cert:actor/<actor>
|
||||
-> read compiled security_zone for that resource
|
||||
-> POST flex-auth /v1/check with authenticated caller identity
|
||||
allow -> sign; record decision and zone evidence
|
||||
audit_only -> sign; record advisory decision and zone evidence
|
||||
deny -> refuse before the CA backend
|
||||
unavailable/invalid
|
||||
-> apply that zone's PEP failure mode
|
||||
-> record fail_open when issuance proceeds
|
||||
```
|
||||
|
||||
The same gate runs for `warden issue` (local backend only).
|
||||
The request contains actor id/type, requested principals, TTL, and a SHA-256
|
||||
fingerprint of the public key. It never contains a private key or secret value.
|
||||
|
||||
---
|
||||
## Compiled membership
|
||||
|
||||
## flex-auth request shape
|
||||
|
||||
| Field | Source |
|
||||
| --- | --- |
|
||||
| `subject.id` | `WARDEN_POLICY_SUBJECT` env var, or actor name |
|
||||
| `subject.type` | Actor type (`adm` / `agt` / `atm`) |
|
||||
| `tenant` | `policy.tenant` (default `tenant:platform`) |
|
||||
| `resource.id` | `ssh-cert:actor/<actor-name>` |
|
||||
| `resource.type` | `ssh-certificate` |
|
||||
| `action` | `sign` |
|
||||
| `context.principals` | From inventory |
|
||||
| `context.actor_type` | adm \| agt \| atm |
|
||||
| `context.pubkey_fingerprint` | SHA256 of pubkey text |
|
||||
| `context.ttl_hours` | Requested TTL |
|
||||
|
||||
flex-auth must return `effect: allow` and an `id` (or `request_id`) on allow.
|
||||
Deny responses include a `reason` surfaced in the CLI error.
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
`scripts/build_flex_auth_registry.py` compiles inventory actor resources. Each
|
||||
actor carries an explicit `zone_subject`:
|
||||
|
||||
```yaml
|
||||
# warden.yaml — policy gate (opt-in, default off)
|
||||
policy:
|
||||
enabled: false
|
||||
flex_auth_url: http://127.0.0.1:8080
|
||||
fail_closed: true
|
||||
tenant: tenant:platform
|
||||
subject_env: WARDEN_POLICY_SUBJECT
|
||||
system: ops-warden
|
||||
caller_auth: # how ops-warden identifies itself — see "Caller identity"
|
||||
mode: none
|
||||
actors:
|
||||
agt-state-hub-bridge:
|
||||
type: agt
|
||||
principals: [agt-task-bridge]
|
||||
ttl_hours: 24
|
||||
zone_subject:
|
||||
applicability: applicable
|
||||
workload_id: ops-bridge-tunnel
|
||||
```
|
||||
|
||||
| Key | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `enabled` | `false` | When `true`, call flex-auth before every sign/issue |
|
||||
| `flex_auth_url` | `http://127.0.0.1:8080` | flex-auth base URL |
|
||||
| `fail_closed` | `true` | Deny sign when flex-auth is unreachable or returns HTTP error |
|
||||
| `tenant` | `tenant:platform` | Tenant sent in subject and resource |
|
||||
| `subject_env` | `WARDEN_POLICY_SUBJECT` | Env var for IAM subject id override |
|
||||
| `system` | `ops-warden` | Resource system identifier |
|
||||
| `caller_auth.mode` | `none` | `none` \| `file` \| `env` \| `command` — source of the `Authorization` bearer token flex-auth TokenReviews ([Caller identity](#caller-identity-warden-wp-0031)) |
|
||||
The compiler consumes zone-engine's resolved view when available and emits
|
||||
resource attributes:
|
||||
|
||||
Set `WARDEN_POLICY_SUBJECT` to the caller's IAM profile `sub` when available.
|
||||
If unset, the actor name is used as subject id.
|
||||
|
||||
---
|
||||
|
||||
## Versioning
|
||||
|
||||
| Version | Gate | Status |
|
||||
| --- | --- | --- |
|
||||
| **v1** | Inventory + TTL max | Shipped |
|
||||
| **v2** | flex-auth opt-in via `policy.enabled` | Shipped (WP-0007) |
|
||||
| **v2.1** | Identity claims required for `adm` signs | Planned |
|
||||
| **v3** | Tenant-scoped policies per `tenant:*` | Planned |
|
||||
|
||||
---
|
||||
|
||||
## What stays in inventory
|
||||
|
||||
- Actor registration (name, type, default principals, default TTL)
|
||||
- Host reference documentation
|
||||
- Scorecard local checks
|
||||
|
||||
flex-auth decides **whether this sign request is allowed now**; inventory
|
||||
defines **what the actor is allowed to request**.
|
||||
|
||||
---
|
||||
|
||||
## flex-auth policy package (FLEX-WP-0006)
|
||||
|
||||
flex-auth owns the `ssh-certificate` / `sign` policy package. ops-warden consumes
|
||||
it via `POST /v1/check` when `policy.enabled: true`.
|
||||
|
||||
**Handoff (canonical):** `~/flex-auth/docs/ops-warden-policy-gate-handoff.md`
|
||||
|
||||
| Asset | flex-auth path |
|
||||
| --- | --- |
|
||||
| Policy package | `examples/ops-warden/policy_package.md` |
|
||||
| Allow/deny fixtures | `examples/ops-warden/policy_fixtures.yaml` |
|
||||
| Registry snapshot | `examples/ops-warden/registry_snapshot.json` |
|
||||
| Subject manifest | `examples/ops-warden/subject_manifest.yaml` |
|
||||
| Resource manifest | `examples/ops-warden/resource_manifest.yaml` |
|
||||
|
||||
### Tenant and subject bindings
|
||||
|
||||
| Field | Value |
|
||||
| --- | --- |
|
||||
| Tenant | `tenant:platform` (`policy.tenant`) |
|
||||
| Resource system | `ops-warden` (`policy.system`) |
|
||||
| Resource type | `ssh-certificate` |
|
||||
| Action | `sign` |
|
||||
| Resource id | `ssh-cert:actor/<actor-name>` |
|
||||
|
||||
| Actor type | Example flex-auth subject | ops-warden inventory name pattern |
|
||||
| --- | --- | --- |
|
||||
| `adm` | `platform-steward` | `adm-*` |
|
||||
| `agt` | `ci-deploy-agent` | `agt-*` |
|
||||
| `atm` | `backup-automation` | `atm-*` |
|
||||
|
||||
**Subject id sent to flex-auth:** `WARDEN_POLICY_SUBJECT` when set, otherwise the
|
||||
inventory actor name. flex-auth may also allow `iam:<actor-name>` when listed in
|
||||
`allowed_subjects` on the resource.
|
||||
|
||||
**Principals and TTL:** Taken from the sign request (inventory defaults). flex-auth
|
||||
denies when principals are empty/disallowed or TTL exceeds `max_ttl_hours` on the
|
||||
registered resource.
|
||||
|
||||
### Fixture coverage (flex-auth)
|
||||
|
||||
Allow: `fixture:ops-warden-adm-sign-allow`, `fixture:ops-warden-agt-sign-allow`,
|
||||
`fixture:ops-warden-atm-sign-allow`.
|
||||
|
||||
Deny: `fixture:ops-warden-unknown-subject-deny`,
|
||||
`fixture:ops-warden-actor-type-mismatch-deny`, `fixture:ops-warden-ttl-above-max-deny`,
|
||||
`fixture:ops-warden-disallowed-principal-deny`,
|
||||
`fixture:ops-warden-missing-fingerprint-deny`.
|
||||
|
||||
### Local smoke
|
||||
|
||||
```bash
|
||||
# flex-auth (from ~/flex-auth)
|
||||
flex-auth serve --addr 127.0.0.1:8080 \
|
||||
--registry examples/ops-warden/registry_snapshot.json \
|
||||
--policy examples/ops-warden/policy_package.md \
|
||||
--log /tmp/flex-auth-ops-warden-decisions.jsonl
|
||||
|
||||
# warden.yaml — policy.enabled: true, flex_auth_url pointing at flex-auth
|
||||
# Use an actor registered in the flex-auth registry (example fixtures use
|
||||
# template names; production needs a registry slice for real inventory actors).
|
||||
```json
|
||||
{
|
||||
"workload_id": "ops-bridge-tunnel",
|
||||
"security_zone": "z2-continuity",
|
||||
"security_zone_admission": "satisfied",
|
||||
"security_zone_revision": "sha256:..."
|
||||
}
|
||||
```
|
||||
|
||||
Local end-to-end evidence: `history/2026-06-23-flex-auth-policy-gate-local-smoke.md`.
|
||||
If the workload reference or resolved membership is absent, the resource says
|
||||
`security_zone: unknown` with a reason. A native non-workload actor/action says
|
||||
`security_zone_admission: not-applicable`. The compiler never parses a path or
|
||||
repository name to repair missing identity.
|
||||
|
||||
### Production registry from inventory
|
||||
`trust_zone: platform` was a dormant, unrelated field and is retired. It must
|
||||
not coexist with `security_zone` as a competing membership source.
|
||||
|
||||
Build a flex-auth registry snapshot that mirrors `inventory.yaml` actors:
|
||||
Build the snapshot:
|
||||
|
||||
```bash
|
||||
python scripts/build_flex_auth_registry.py ~/.config/warden/inventory.yaml \
|
||||
python3 scripts/build_flex_auth_registry.py \
|
||||
~/.config/warden/inventory.yaml \
|
||||
--zone-resolutions /path/to/zone-resolved-view.json \
|
||||
-o registry/flex-auth/production_registry_snapshot.json
|
||||
flex-auth load-registry --file registry/flex-auth/production_registry_snapshot.json
|
||||
```
|
||||
|
||||
Re-run after adding or changing actors. Deploy the snapshot to the production
|
||||
flex-auth runtime together with `~/flex-auth/examples/ops-warden/policy_package.md`.
|
||||
Omitting `--zone-resolutions` is safe: applicable actors resolve `unknown`, not
|
||||
to a guessed zone.
|
||||
|
||||
Smoke (non-secret):
|
||||
## PEP failure modes
|
||||
|
||||
```bash
|
||||
./scripts/policy_gate_production_smoke.sh
|
||||
# OpenBao-backed — preferred: credential broker (no manual VAULT_TOKEN):
|
||||
cd ~/railiance-platform && make credential-exec-ops-warden-smoke
|
||||
# Manual fallback when broker unavailable:
|
||||
SMOKE_VAULT=1 ./scripts/policy_gate_production_smoke.sh
|
||||
```
|
||||
The initial build profile accepted by ops-warden is:
|
||||
|
||||
Evidence: `history/2026-06-23-flex-auth-policy-gate-production-smoke.md`.
|
||||
| Zone/result | Dependency failure |
|
||||
| --- | --- |
|
||||
| `z0-experimental` | `fail_open` |
|
||||
| `z1-operational` | `fail_open` |
|
||||
| `z2-protected` | `fail_open` |
|
||||
| `z2-continuity` | `fail_open` |
|
||||
| `z3-critical` | `fail_closed` |
|
||||
| `unknown` | `fail_open` under the versioned build profile |
|
||||
| `not-applicable` | `fail_closed` for this pre-sign PEP |
|
||||
|
||||
---
|
||||
These are dependency failure modes, not policy stance. A rendered deny always
|
||||
blocks. The `unknown` row does not grant membership or an exception; it is the
|
||||
explicit build-stage treatment until authoritative declarations land.
|
||||
|
||||
## Caller identity (WARDEN-WP-0031)
|
||||
|
||||
flex-auth authenticates the **caller** before it evaluates the request. The
|
||||
in-cluster pin `flex-auth-ops-warden` (FLEX-WP-0016) passes the bearer token to a
|
||||
Kubernetes TokenReview and requires the principal
|
||||
`system:serviceaccount:ops-warden:ops-warden` for any request carrying
|
||||
`resource.system: ops-warden`.
|
||||
|
||||
Until ops-warden sends that header the pin logs
|
||||
|
||||
```
|
||||
caller authentication warning: caller is not authenticated
|
||||
```
|
||||
|
||||
and can only run `callerAuth.mode: warn`. Per ADHOC-2026-08-17-T01,
|
||||
`policy.enabled` must not flip while `/v1/check` still answers unauthenticated
|
||||
callers — so **the missing header is what blocks the flip**, and it is
|
||||
ops-warden's to fix, not flex-auth's.
|
||||
|
||||
### Configure a token source
|
||||
Configuration:
|
||||
|
||||
```yaml
|
||||
policy:
|
||||
flex_auth_url: http://127.0.0.1:19090
|
||||
zone_registry_path: registry/flex-auth/production_registry_snapshot.json
|
||||
failure_modes:
|
||||
z0-experimental: fail_open
|
||||
z1-operational: fail_open
|
||||
z2-protected: fail_open
|
||||
z2-continuity: fail_open
|
||||
z3-critical: fail_closed
|
||||
unknown: fail_open
|
||||
not-applicable: fail_closed
|
||||
caller_auth:
|
||||
mode: none # none | file | env | command
|
||||
token_path: /var/run/secrets/flex-auth/token # mode: file
|
||||
token_env: WARDEN_POLICY_CALLER_TOKEN # mode: env
|
||||
command: kubectl create token ops-warden -n ops-warden --audience flex-auth --duration 10m
|
||||
audience: flex-auth
|
||||
mode: command
|
||||
command:
|
||||
- kubectl
|
||||
- create
|
||||
- token
|
||||
- ops-warden
|
||||
- -n
|
||||
- ops-warden
|
||||
- --audience
|
||||
- flex-auth
|
||||
- --duration
|
||||
- 10m
|
||||
```
|
||||
|
||||
| Mode | Use it when |
|
||||
| --- | --- |
|
||||
| `none` | Default. No header — pre-FLEX-WP-0016 behaviour, only viable while the pin is in `warn` |
|
||||
| `file` | In-cluster PEP with a projected, audience-bound ServiceAccount token |
|
||||
| `env` | The token is already in the environment (CI, a wrapper) |
|
||||
| `command` | Workstation `warden sign` — mint a short-lived bound token per call |
|
||||
`policy.enabled` and the global `policy.fail_closed` are retired. The loader
|
||||
rejects either key so old and new controls cannot coexist as two sources of
|
||||
truth.
|
||||
|
||||
A workstation is not a ServiceAccount, which is why `command` exists. The token is
|
||||
read, sent, and dropped: never cached, written, or logged (ADR-0002). If a token
|
||||
is configured but cannot be obtained, the sign is **refused** under
|
||||
`fail_closed` — falling back to an anonymous call would defeat the gate.
|
||||
## Caller identity
|
||||
|
||||
### Readiness gate
|
||||
The production flex-auth pin authenticates ops-warden with Kubernetes
|
||||
TokenReview and binds `resource.system: ops-warden` to
|
||||
`system:serviceaccount:ops-warden:ops-warden`. Supported token sources are:
|
||||
|
||||
- `file` — projected ServiceAccount token for an in-cluster PEP;
|
||||
- `command` — short-lived `kubectl create token` on a workstation;
|
||||
- `env` — attended fallback;
|
||||
- `none` — no identity header; only useful for an intentionally unauthenticated
|
||||
development evaluator.
|
||||
|
||||
Tokens are resolved per call, never cached, logged, or echoed. Under a
|
||||
fail-closed zone, an unavailable caller token blocks. Under a fail-open zone it
|
||||
becomes a recorded evaluator failure; ops-warden never retries anonymously with
|
||||
a secret copied into its own state.
|
||||
|
||||
Re-establish the value-safe caller proof:
|
||||
|
||||
```bash
|
||||
python scripts/check_policy_caller_identity.py # offline
|
||||
python scripts/check_policy_caller_identity.py --url http://127.0.0.1:19090 # port-forward of the warn pin
|
||||
python3 scripts/check_policy_caller_identity.py \
|
||||
--url http://127.0.0.1:19090
|
||||
```
|
||||
|
||||
Exit 0 ready / 1 not ready / 2 bad input. It prints the token's length and a
|
||||
truncated fingerprint, never the value, so its output is safe to paste into a
|
||||
handoff message. A live `401` means the token was sent but rejected (audience or
|
||||
binding); `403` means it authenticated but may not represent `system: ops-warden`.
|
||||
Expected evidence is HTTP 200 with a decision id and anonymous HTTP 401 on the
|
||||
enforcing pin. The script reports only token length and a truncated fingerprint.
|
||||
|
||||
### Enablement is deferred by decision (ADR-0006)
|
||||
## Audit evidence
|
||||
|
||||
`policy.enabled` is **false, and that is a decision rather than a blocker.** The
|
||||
gate is ready: flex-auth's pin runs `callerAuth.mode: enforce`, the readiness
|
||||
gate exits 0 against it, and an anonymous `/v1/check` returns 401.
|
||||
Successful signing records:
|
||||
|
||||
It is not enabled because `policy.enabled` is one boolean over the whole repo,
|
||||
and with `fail_closed: true` it makes flex-auth a hard dependency of every
|
||||
`warden sign` — including the certs the ops-bridge tunnels depend on, one of
|
||||
which carries the policy call. Uniform enforcement across an estate under active
|
||||
refactor hardens the access needed to perform the refactor.
|
||||
- `policy_decision_id` when flex-auth returned one;
|
||||
- `policy_zone`;
|
||||
- `policy_failure_mode`;
|
||||
- `policy_outcome` (`allow`, `audit_only`, or `fail_open`).
|
||||
|
||||
`ADR-0006` scopes enforcement to security zones; `WARDEN-WP-0032` defines them.
|
||||
Do not set `policy.enabled: true` outside that model — a zone-blind enablement
|
||||
is out of order under the ADR, not merely inadvisable.
|
||||
A fail-open result must therefore be visible rather than indistinguishable from
|
||||
an unevaluated request. Denies do not reach the CA backend and produce no
|
||||
certificate.
|
||||
|
||||
The sequence below is retained as the *mechanics*, for whoever enables the gate
|
||||
for a zone once zones exist.
|
||||
## Rollout and rollback
|
||||
|
||||
### Flip sequence
|
||||
1. Validate `tenancy.yaml` and the workload declarations referenced by actor
|
||||
`zone_subject` entries.
|
||||
2. Compile the registry and inspect unknown/not-applicable results.
|
||||
3. Run `scripts/check_policy_caller_identity.py` against the enforcing pin.
|
||||
4. Deploy the same compiled registry revision and matching flex-auth policy
|
||||
package.
|
||||
5. Smoke an allow/advisory path, an enforced deny, and evaluator loss for one
|
||||
fail-open and one fail-closed zone.
|
||||
|
||||
1. Configure `caller_auth`; `check_policy_caller_identity.py` exits 0 offline.
|
||||
2. Smoke against a port-forward of the warn pin. The evidence is the **absence**
|
||||
of `caller authentication warning` in its log, not the `allow` — warn serves
|
||||
unauthenticated callers too, so an allow alone proves nothing.
|
||||
3. Ask flex-auth to set `callerAuth.mode: enforce` (their FLEX-WP-0016 T03).
|
||||
4. Re-run the gate against the enforcing pin.
|
||||
5. Only then: `policy.enabled: true`, `fail_closed: true`.
|
||||
|
||||
Reversing 3 and 5 401s every `warden sign`.
|
||||
|
||||
---
|
||||
|
||||
## Production rollout
|
||||
|
||||
**Keep `policy.enabled: false` until flex-auth is reachable** at `policy.flex_auth_url`
|
||||
with `fail_closed: true`, unreachable flex-auth blocks all signs.
|
||||
|
||||
### Operator checklist
|
||||
|
||||
| Step | Owner | Action |
|
||||
| --- | --- | --- |
|
||||
| 1 | flex-auth | Deploy runtime; confirm `curl <flex_auth_url>/healthz` → 200 (**FLEX-WP-0007**) |
|
||||
| 2 | flex-auth | Load production registry + policy package (`~/flex-auth/examples/ops-warden/`) |
|
||||
| 3 | ops-warden | Regenerate registry from inventory: `scripts/build_flex_auth_registry.py` |
|
||||
| 4 | ops-warden | Local smoke: `./scripts/policy_gate_production_smoke.sh` |
|
||||
| 5 | operator | Vault smoke: `make credential-exec-ops-warden-smoke` in `railiance-platform` (or manual `SMOKE_VAULT=1` fallback) |
|
||||
| 6 | operator | Set `policy.flex_auth_url` in `~/.config/warden/warden.yaml` — the pin is `flex-auth-ops-warden.flex-auth.svc.cluster.local:8080`, reached from a workstation via port-forward or tunnel |
|
||||
| 6a | ops-warden | Configure `policy.caller_auth`; `scripts/check_policy_caller_identity.py` exits 0 (see **Caller identity**) |
|
||||
| 6b | flex-auth | Set `callerAuth.mode: enforce` on the ops-warden pin (FLEX-WP-0016 T03) |
|
||||
| 7 | operator | Set `policy.enabled: true`; keep `fail_closed: true` |
|
||||
| 8 | operator | Allow smoke: `warden sign <actor>` — `signatures.log` has `policy_decision_id` |
|
||||
| 9 | operator | Deny smoke: e.g. `--ttl` above max — CLI shows flex-auth `reason`, no cert |
|
||||
|
||||
Cross-repo references:
|
||||
|
||||
- `~/flex-auth/workplans/FLEX-WP-0007-ops-warden-policy-gate-production-deployment.md`
|
||||
- `history/2026-06-23-flex-auth-production-pickup-suggestion.md`
|
||||
- `history/2026-06-23-flex-auth-policy-gate-production-smoke.md`
|
||||
|
||||
### Summary
|
||||
|
||||
1. Deploy the flex-auth registry and policy package to the production flex-auth
|
||||
runtime — **not** only the example fixtures.
|
||||
2. Set `policy.flex_auth_url` to the production flex-auth base URL.
|
||||
3. Enable `policy.enabled: true` only after steps 1–5 pass.
|
||||
4. Keep `fail_closed: true` unless an explicit break-glass procedure exists.
|
||||
5. Smoke allow and deny paths; preserve non-secret evidence only.
|
||||
|
||||
### Rollback
|
||||
|
||||
If signs are blocked after enabling the gate:
|
||||
|
||||
1. Set `policy.enabled: false` in `warden.yaml` (inventory + TTL gate only).
|
||||
2. Confirm `warden sign` succeeds without flex-auth.
|
||||
3. File a State Hub note to `flex-auth` with non-secret symptoms (HTTP status,
|
||||
`fail_closed` behaviour, actor name).
|
||||
4. Re-enable only after flex-auth runtime and registry are verified.
|
||||
|
||||
Evidence fields for the flip: flex-auth health URL, smoke script exit codes,
|
||||
`warden activity --kind sign --json` showing `policy_decision_id` on allow path.
|
||||
|
||||
---
|
||||
Rollback is a versioned profile or registry rollback. Do not reintroduce
|
||||
`policy.enabled: false`: that would erase per-zone evidence and recreate the
|
||||
global control ADR-0009 supersedes.
|
||||
|
||||
## See also
|
||||
|
||||
- `wiki/OpsWardenConfig.md` — full config reference
|
||||
- `wiki/CredentialRouting.md`
|
||||
- `~/flex-auth/docs/ops-warden-policy-gate-handoff.md` — flex-auth handoff
|
||||
- `flex-auth/INTENT.md`
|
||||
- `net-kingdom/docs/platform-identity-security-architecture.md`
|
||||
- `tenancy.yaml`
|
||||
- `docs/evidence/security-zone-admission-2026-08-22.md`
|
||||
- `wiki/OpsWardenConfig.md`
|
||||
- `wiki/WorkloadSecurityPosture.md`
|
||||
- `history/2026-08-19-flex-auth-caller-identity-evidence.md`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue