2026-08-22 15:36:37 +02:00
|
|
|
# Zone-aware policy-gated signing
|
2026-06-17 08:22:45 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
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.
|
2026-06-17 08:22:45 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
Authority stays split:
|
2026-06-17 08:22:45 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
- 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.
|
2026-06-17 08:22:45 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
Binding decisions: `ADR-0009` (current) and `ADR-0006` (superseded rationale).
|
|
|
|
|
|
|
|
|
|
## Request path
|
2026-06-17 08:22:45 +02:00
|
|
|
|
|
|
|
|
```text
|
2026-08-22 15:36:37 +02:00
|
|
|
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
|
2026-06-17 08:22:45 +02:00
|
|
|
```
|
|
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
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.
|
2026-06-17 08:22:45 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
## Compiled membership
|
2026-06-17 08:22:45 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
`scripts/build_flex_auth_registry.py` compiles inventory actor resources. Each
|
|
|
|
|
actor carries an explicit `zone_subject`:
|
2026-06-17 08:22:45 +02:00
|
|
|
|
|
|
|
|
```yaml
|
2026-08-22 15:36:37 +02:00
|
|
|
actors:
|
|
|
|
|
agt-state-hub-bridge:
|
|
|
|
|
type: agt
|
|
|
|
|
principals: [agt-task-bridge]
|
|
|
|
|
ttl_hours: 24
|
|
|
|
|
zone_subject:
|
|
|
|
|
applicability: applicable
|
|
|
|
|
workload_id: ops-bridge-tunnel
|
2026-06-17 08:22:45 +02:00
|
|
|
```
|
|
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
The compiler consumes zone-engine's resolved view when available and emits
|
|
|
|
|
resource attributes:
|
2026-06-24 12:44:32 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
```json
|
|
|
|
|
{
|
|
|
|
|
"workload_id": "ops-bridge-tunnel",
|
|
|
|
|
"security_zone": "z2-continuity",
|
|
|
|
|
"security_zone_admission": "satisfied",
|
|
|
|
|
"security_zone_revision": "sha256:..."
|
|
|
|
|
}
|
2026-06-24 12:44:32 +02:00
|
|
|
```
|
|
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
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.
|
2026-06-24 12:44:32 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
`trust_zone: platform` was a dormant, unrelated field and is retired. It must
|
|
|
|
|
not coexist with `security_zone` as a competing membership source.
|
2026-06-24 12:44:32 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
Build the snapshot:
|
2026-06-24 12:44:32 +02:00
|
|
|
|
|
|
|
|
```bash
|
2026-08-22 15:36:37 +02:00
|
|
|
python3 scripts/build_flex_auth_registry.py \
|
|
|
|
|
~/.config/warden/inventory.yaml \
|
|
|
|
|
--zone-resolutions /path/to/zone-resolved-view.json \
|
2026-06-24 12:44:32 +02:00
|
|
|
-o registry/flex-auth/production_registry_snapshot.json
|
|
|
|
|
```
|
|
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
Omitting `--zone-resolutions` is safe: applicable actors resolve `unknown`, not
|
|
|
|
|
to a guessed zone.
|
2026-06-24 12:44:32 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
## PEP failure modes
|
Send a caller identity to flex-auth so policy.enabled can flip
flex-auth's flex-auth-ops-warden pin (FLEX-WP-0016) TokenReviews the caller and
binds resource.system: ops-warden to system:serviceaccount:ops-warden:ops-warden.
policy.py posted /v1/check with no Authorization header, so the pin logs
"caller authentication warning" and can only run callerAuth.mode: warn — which,
under ADHOC-2026-08-17-T01, is exactly what blocks policy.enabled: true.
- policy.caller_auth (none | file | env | command) + src/warden/caller_identity.py:
token resolved per call, never cached, written, or logged (ADR-0002)
- both check_sign_policy and check_fetch_policy attach the bearer header; an
unobtainable token fails closed rather than retrying anonymously
- scripts/check_policy_caller_identity.py: read-only gate, prints length and a
truncated fingerprint only, distinguishes 401 (audience/binding) from 403
- example config: caller_auth block, and flex_auth_url corrected — it pointed at
flex-auth.flex-auth.svc, a Service that does not exist
- WARDEN-WP-0031, PolicyGatedSigning caller-identity section and flip sequence
Default stays mode: none, so behaviour is unchanged until an operator opts in.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 15:08:34 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
The initial build profile accepted by ops-warden is:
|
Send a caller identity to flex-auth so policy.enabled can flip
flex-auth's flex-auth-ops-warden pin (FLEX-WP-0016) TokenReviews the caller and
binds resource.system: ops-warden to system:serviceaccount:ops-warden:ops-warden.
policy.py posted /v1/check with no Authorization header, so the pin logs
"caller authentication warning" and can only run callerAuth.mode: warn — which,
under ADHOC-2026-08-17-T01, is exactly what blocks policy.enabled: true.
- policy.caller_auth (none | file | env | command) + src/warden/caller_identity.py:
token resolved per call, never cached, written, or logged (ADR-0002)
- both check_sign_policy and check_fetch_policy attach the bearer header; an
unobtainable token fails closed rather than retrying anonymously
- scripts/check_policy_caller_identity.py: read-only gate, prints length and a
truncated fingerprint only, distinguishes 401 (audience/binding) from 403
- example config: caller_auth block, and flex_auth_url corrected — it pointed at
flex-auth.flex-auth.svc, a Service that does not exist
- WARDEN-WP-0031, PolicyGatedSigning caller-identity section and flip sequence
Default stays mode: none, so behaviour is unchanged until an operator opts in.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 15:08:34 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
| 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 |
|
Send a caller identity to flex-auth so policy.enabled can flip
flex-auth's flex-auth-ops-warden pin (FLEX-WP-0016) TokenReviews the caller and
binds resource.system: ops-warden to system:serviceaccount:ops-warden:ops-warden.
policy.py posted /v1/check with no Authorization header, so the pin logs
"caller authentication warning" and can only run callerAuth.mode: warn — which,
under ADHOC-2026-08-17-T01, is exactly what blocks policy.enabled: true.
- policy.caller_auth (none | file | env | command) + src/warden/caller_identity.py:
token resolved per call, never cached, written, or logged (ADR-0002)
- both check_sign_policy and check_fetch_policy attach the bearer header; an
unobtainable token fails closed rather than retrying anonymously
- scripts/check_policy_caller_identity.py: read-only gate, prints length and a
truncated fingerprint only, distinguishes 401 (audience/binding) from 403
- example config: caller_auth block, and flex_auth_url corrected — it pointed at
flex-auth.flex-auth.svc, a Service that does not exist
- WARDEN-WP-0031, PolicyGatedSigning caller-identity section and flip sequence
Default stays mode: none, so behaviour is unchanged until an operator opts in.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 15:08:34 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
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.
|
Send a caller identity to flex-auth so policy.enabled can flip
flex-auth's flex-auth-ops-warden pin (FLEX-WP-0016) TokenReviews the caller and
binds resource.system: ops-warden to system:serviceaccount:ops-warden:ops-warden.
policy.py posted /v1/check with no Authorization header, so the pin logs
"caller authentication warning" and can only run callerAuth.mode: warn — which,
under ADHOC-2026-08-17-T01, is exactly what blocks policy.enabled: true.
- policy.caller_auth (none | file | env | command) + src/warden/caller_identity.py:
token resolved per call, never cached, written, or logged (ADR-0002)
- both check_sign_policy and check_fetch_policy attach the bearer header; an
unobtainable token fails closed rather than retrying anonymously
- scripts/check_policy_caller_identity.py: read-only gate, prints length and a
truncated fingerprint only, distinguishes 401 (audience/binding) from 403
- example config: caller_auth block, and flex_auth_url corrected — it pointed at
flex-auth.flex-auth.svc, a Service that does not exist
- WARDEN-WP-0031, PolicyGatedSigning caller-identity section and flip sequence
Default stays mode: none, so behaviour is unchanged until an operator opts in.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 15:08:34 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
Configuration:
|
Send a caller identity to flex-auth so policy.enabled can flip
flex-auth's flex-auth-ops-warden pin (FLEX-WP-0016) TokenReviews the caller and
binds resource.system: ops-warden to system:serviceaccount:ops-warden:ops-warden.
policy.py posted /v1/check with no Authorization header, so the pin logs
"caller authentication warning" and can only run callerAuth.mode: warn — which,
under ADHOC-2026-08-17-T01, is exactly what blocks policy.enabled: true.
- policy.caller_auth (none | file | env | command) + src/warden/caller_identity.py:
token resolved per call, never cached, written, or logged (ADR-0002)
- both check_sign_policy and check_fetch_policy attach the bearer header; an
unobtainable token fails closed rather than retrying anonymously
- scripts/check_policy_caller_identity.py: read-only gate, prints length and a
truncated fingerprint only, distinguishes 401 (audience/binding) from 403
- example config: caller_auth block, and flex_auth_url corrected — it pointed at
flex-auth.flex-auth.svc, a Service that does not exist
- WARDEN-WP-0031, PolicyGatedSigning caller-identity section and flip sequence
Default stays mode: none, so behaviour is unchanged until an operator opts in.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 15:08:34 +02:00
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
policy:
|
2026-08-22 15:36:37 +02:00
|
|
|
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
|
Send a caller identity to flex-auth so policy.enabled can flip
flex-auth's flex-auth-ops-warden pin (FLEX-WP-0016) TokenReviews the caller and
binds resource.system: ops-warden to system:serviceaccount:ops-warden:ops-warden.
policy.py posted /v1/check with no Authorization header, so the pin logs
"caller authentication warning" and can only run callerAuth.mode: warn — which,
under ADHOC-2026-08-17-T01, is exactly what blocks policy.enabled: true.
- policy.caller_auth (none | file | env | command) + src/warden/caller_identity.py:
token resolved per call, never cached, written, or logged (ADR-0002)
- both check_sign_policy and check_fetch_policy attach the bearer header; an
unobtainable token fails closed rather than retrying anonymously
- scripts/check_policy_caller_identity.py: read-only gate, prints length and a
truncated fingerprint only, distinguishes 401 (audience/binding) from 403
- example config: caller_auth block, and flex_auth_url corrected — it pointed at
flex-auth.flex-auth.svc, a Service that does not exist
- WARDEN-WP-0031, PolicyGatedSigning caller-identity section and flip sequence
Default stays mode: none, so behaviour is unchanged until an operator opts in.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 15:08:34 +02:00
|
|
|
caller_auth:
|
2026-08-22 15:36:37 +02:00
|
|
|
mode: command
|
|
|
|
|
command:
|
|
|
|
|
- kubectl
|
|
|
|
|
- create
|
|
|
|
|
- token
|
|
|
|
|
- ops-warden
|
|
|
|
|
- -n
|
|
|
|
|
- ops-warden
|
|
|
|
|
- --audience
|
|
|
|
|
- flex-auth
|
|
|
|
|
- --duration
|
|
|
|
|
- 10m
|
Send a caller identity to flex-auth so policy.enabled can flip
flex-auth's flex-auth-ops-warden pin (FLEX-WP-0016) TokenReviews the caller and
binds resource.system: ops-warden to system:serviceaccount:ops-warden:ops-warden.
policy.py posted /v1/check with no Authorization header, so the pin logs
"caller authentication warning" and can only run callerAuth.mode: warn — which,
under ADHOC-2026-08-17-T01, is exactly what blocks policy.enabled: true.
- policy.caller_auth (none | file | env | command) + src/warden/caller_identity.py:
token resolved per call, never cached, written, or logged (ADR-0002)
- both check_sign_policy and check_fetch_policy attach the bearer header; an
unobtainable token fails closed rather than retrying anonymously
- scripts/check_policy_caller_identity.py: read-only gate, prints length and a
truncated fingerprint only, distinguishes 401 (audience/binding) from 403
- example config: caller_auth block, and flex_auth_url corrected — it pointed at
flex-auth.flex-auth.svc, a Service that does not exist
- WARDEN-WP-0031, PolicyGatedSigning caller-identity section and flip sequence
Default stays mode: none, so behaviour is unchanged until an operator opts in.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 15:08:34 +02:00
|
|
|
```
|
|
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
`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.
|
Send a caller identity to flex-auth so policy.enabled can flip
flex-auth's flex-auth-ops-warden pin (FLEX-WP-0016) TokenReviews the caller and
binds resource.system: ops-warden to system:serviceaccount:ops-warden:ops-warden.
policy.py posted /v1/check with no Authorization header, so the pin logs
"caller authentication warning" and can only run callerAuth.mode: warn — which,
under ADHOC-2026-08-17-T01, is exactly what blocks policy.enabled: true.
- policy.caller_auth (none | file | env | command) + src/warden/caller_identity.py:
token resolved per call, never cached, written, or logged (ADR-0002)
- both check_sign_policy and check_fetch_policy attach the bearer header; an
unobtainable token fails closed rather than retrying anonymously
- scripts/check_policy_caller_identity.py: read-only gate, prints length and a
truncated fingerprint only, distinguishes 401 (audience/binding) from 403
- example config: caller_auth block, and flex_auth_url corrected — it pointed at
flex-auth.flex-auth.svc, a Service that does not exist
- WARDEN-WP-0031, PolicyGatedSigning caller-identity section and flip sequence
Default stays mode: none, so behaviour is unchanged until an operator opts in.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 15:08:34 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
## Caller identity
|
Send a caller identity to flex-auth so policy.enabled can flip
flex-auth's flex-auth-ops-warden pin (FLEX-WP-0016) TokenReviews the caller and
binds resource.system: ops-warden to system:serviceaccount:ops-warden:ops-warden.
policy.py posted /v1/check with no Authorization header, so the pin logs
"caller authentication warning" and can only run callerAuth.mode: warn — which,
under ADHOC-2026-08-17-T01, is exactly what blocks policy.enabled: true.
- policy.caller_auth (none | file | env | command) + src/warden/caller_identity.py:
token resolved per call, never cached, written, or logged (ADR-0002)
- both check_sign_policy and check_fetch_policy attach the bearer header; an
unobtainable token fails closed rather than retrying anonymously
- scripts/check_policy_caller_identity.py: read-only gate, prints length and a
truncated fingerprint only, distinguishes 401 (audience/binding) from 403
- example config: caller_auth block, and flex_auth_url corrected — it pointed at
flex-auth.flex-auth.svc, a Service that does not exist
- WARDEN-WP-0031, PolicyGatedSigning caller-identity section and flip sequence
Default stays mode: none, so behaviour is unchanged until an operator opts in.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 15:08:34 +02:00
|
|
|
|
2026-09-08 16:46:00 +02:00
|
|
|
An HTTP 401 or 403 from the policy service refuses the operation under every
|
|
|
|
|
outage profile. It is an explicit caller-authentication or system-binding refusal,
|
|
|
|
|
not evaluator unavailability. Resolve the admitted caller and resource contract;
|
|
|
|
|
do not retry with a different resource owner or disable caller enforcement.
|
|
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
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:
|
Send a caller identity to flex-auth so policy.enabled can flip
flex-auth's flex-auth-ops-warden pin (FLEX-WP-0016) TokenReviews the caller and
binds resource.system: ops-warden to system:serviceaccount:ops-warden:ops-warden.
policy.py posted /v1/check with no Authorization header, so the pin logs
"caller authentication warning" and can only run callerAuth.mode: warn — which,
under ADHOC-2026-08-17-T01, is exactly what blocks policy.enabled: true.
- policy.caller_auth (none | file | env | command) + src/warden/caller_identity.py:
token resolved per call, never cached, written, or logged (ADR-0002)
- both check_sign_policy and check_fetch_policy attach the bearer header; an
unobtainable token fails closed rather than retrying anonymously
- scripts/check_policy_caller_identity.py: read-only gate, prints length and a
truncated fingerprint only, distinguishes 401 (audience/binding) from 403
- example config: caller_auth block, and flex_auth_url corrected — it pointed at
flex-auth.flex-auth.svc, a Service that does not exist
- WARDEN-WP-0031, PolicyGatedSigning caller-identity section and flip sequence
Default stays mode: none, so behaviour is unchanged until an operator opts in.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 15:08:34 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
- `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.
|
Send a caller identity to flex-auth so policy.enabled can flip
flex-auth's flex-auth-ops-warden pin (FLEX-WP-0016) TokenReviews the caller and
binds resource.system: ops-warden to system:serviceaccount:ops-warden:ops-warden.
policy.py posted /v1/check with no Authorization header, so the pin logs
"caller authentication warning" and can only run callerAuth.mode: warn — which,
under ADHOC-2026-08-17-T01, is exactly what blocks policy.enabled: true.
- policy.caller_auth (none | file | env | command) + src/warden/caller_identity.py:
token resolved per call, never cached, written, or logged (ADR-0002)
- both check_sign_policy and check_fetch_policy attach the bearer header; an
unobtainable token fails closed rather than retrying anonymously
- scripts/check_policy_caller_identity.py: read-only gate, prints length and a
truncated fingerprint only, distinguishes 401 (audience/binding) from 403
- example config: caller_auth block, and flex_auth_url corrected — it pointed at
flex-auth.flex-auth.svc, a Service that does not exist
- WARDEN-WP-0031, PolicyGatedSigning caller-identity section and flip sequence
Default stays mode: none, so behaviour is unchanged until an operator opts in.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 15:08:34 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
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.
|
Send a caller identity to flex-auth so policy.enabled can flip
flex-auth's flex-auth-ops-warden pin (FLEX-WP-0016) TokenReviews the caller and
binds resource.system: ops-warden to system:serviceaccount:ops-warden:ops-warden.
policy.py posted /v1/check with no Authorization header, so the pin logs
"caller authentication warning" and can only run callerAuth.mode: warn — which,
under ADHOC-2026-08-17-T01, is exactly what blocks policy.enabled: true.
- policy.caller_auth (none | file | env | command) + src/warden/caller_identity.py:
token resolved per call, never cached, written, or logged (ADR-0002)
- both check_sign_policy and check_fetch_policy attach the bearer header; an
unobtainable token fails closed rather than retrying anonymously
- scripts/check_policy_caller_identity.py: read-only gate, prints length and a
truncated fingerprint only, distinguishes 401 (audience/binding) from 403
- example config: caller_auth block, and flex_auth_url corrected — it pointed at
flex-auth.flex-auth.svc, a Service that does not exist
- WARDEN-WP-0031, PolicyGatedSigning caller-identity section and flip sequence
Default stays mode: none, so behaviour is unchanged until an operator opts in.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 15:08:34 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
Re-establish the value-safe caller proof:
|
ADR-0006: enforcement is zone-scoped; defer the policy.enabled flip
flex-auth enforced its ops-warden pin (FLEX-WP-0016 T03) and the gate verified
clean against it: readiness exits 0, decision:f3f7c88f9585582a, anonymous
/v1/check now 401. Everything needed to set policy.enabled: true was in place.
It stays false, by decision. policy.enabled is a single repo-wide boolean, 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 itself. Uniform enforcement across an estate being
actively rebuilt hardens the access needed to perform the rebuild.
The repo already refuses one-dimensional posture: WP-0015 shipped environment
and maturity axes, WP-0029 added organization_posture. A global flag ignores all
three. ADR-0006 records that enforcement belongs to a zone, and binds future
work — a zone-blind enforcement flag is out of order, not merely unwise.
WARDEN-WP-0032 drafts the zone model, leading with the ownership question:
whether this is ops-warden's to own or NetKingdom canon to consume (ADR-0005).
WP-0031 is finished with T05 cancelled and resuming as WP-0032-T05.
Also replaces the hand-run kubectl port-forward with a managed ops-bridge
tunnel, flex-auth-ops-warden-railiance01 (-L 19090:10.43.1.165:8080).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 20:31:28 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
```bash
|
|
|
|
|
python3 scripts/check_policy_caller_identity.py \
|
|
|
|
|
--url http://127.0.0.1:19090
|
|
|
|
|
```
|
2026-06-24 12:44:32 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
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.
|
2026-06-24 12:44:32 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
## Audit evidence
|
2026-06-24 12:44:32 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
Successful signing records:
|
2026-06-17 08:22:45 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
- `policy_decision_id` when flex-auth returned one;
|
|
|
|
|
- `policy_zone`;
|
|
|
|
|
- `policy_failure_mode`;
|
|
|
|
|
- `policy_outcome` (`allow`, `audit_only`, or `fail_open`).
|
2026-07-01 23:32:38 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
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.
|
2026-07-01 23:32:38 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
## Rollout and rollback
|
2026-07-01 23:32:38 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
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.
|
2026-07-01 23:32:38 +02:00
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
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.
|
2026-06-17 08:22:45 +02:00
|
|
|
|
|
|
|
|
## See also
|
|
|
|
|
|
2026-08-22 15:36:37 +02:00
|
|
|
- `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`
|