fix: confine PDP checks to the admitted local transport
Assistant: codex Assistant-Model: gpt-6-astra Assistant-Session: 01a12d13-27f2-7163-b8c0-f682af02772c
This commit is contained in:
parent
0db6adef69
commit
d379a3dfba
6 changed files with 268 additions and 50 deletions
|
|
@ -23,21 +23,40 @@ $ getent hosts this-service-does-not-exist.flex-auth.svc.cluster.local
|
|||
`*.svc.cluster.local` name answers with one unrelated public address. Sending
|
||||
there ships the CheckRequest body and our bearer token to a third party.
|
||||
|
||||
`flex-auth.decision-record.v1` carries **no signature**, and every digest in it
|
||||
is either sent by us or published in flex-auth's repo, so a forger reproduces
|
||||
all three exactly. Digests establish integrity of the binding, never
|
||||
`flex-auth.decision-record.v1` supports a detached Ed25519 signature on the
|
||||
producer side (FLEX-WP-0024), but this consumer does not yet verify it against
|
||||
independently admitted keys. Without that verification, every binding digest
|
||||
is either sent by us or published in flex-auth's repo, so a forger can
|
||||
reproduce those digests. Digests establish integrity of the binding, never
|
||||
authenticity of the source. As flex-auth put it in `FLEX-DEC-2026-010`:
|
||||
|
||||
> Fail-closed protects against a PDP that is ABSENT, not against one that LIES.
|
||||
|
||||
Until detached signatures ship (`FLEX-WP-0024`), the address shape is the only
|
||||
thing standing in for responder authenticity. That is why it is enforced.
|
||||
The literal loopback address restriction limits the destination; it does not
|
||||
prove responder identity. The operator must verify the cluster and named pod
|
||||
behind the port-forward. Signed consumer enforcement, independently admitted
|
||||
verification keys, rotation and downgrade tests remain open in SECRETS-WP-0014
|
||||
and Custodian G13. Producer support alone does not close that gap.
|
||||
|
||||
The Check client disables automatic redirects, environment/system proxies and
|
||||
the process-global urllib opener. A 3xx response fails closed without contacting
|
||||
the redirect destination. URLs must be HTTP(S) bare origins with a literal
|
||||
loopback IP and optional nonzero port: no hostname (including `localhost`),
|
||||
userinfo, path prefix, query, fragment or whitespace/control characters. Existing
|
||||
`localhost` configuration must use `127.0.0.1` or `[::1]`. Invalid configuration
|
||||
is rejected before reading the bearer file. Responses are limited to 512 KiB;
|
||||
oversized, invalid UTF-8 and non-object JSON bodies fail closed. These rules also
|
||||
apply when the approval flow invokes the PDP client.
|
||||
|
||||
Regression tests use disposable local HTTP servers and synthetic credentials;
|
||||
they do not demonstrate identity or signature verification on the native pin.
|
||||
|
||||
## The supported path
|
||||
|
||||
Loopback `kubectl port-forward` to the named pod. It resolves no DNS name,
|
||||
targets one pod explicitly, and rides the Kubernetes API server's TLS with our
|
||||
cluster credentials — so it authenticates the responder transitively. Note this
|
||||
Use literal loopback `kubectl port-forward` to the admitted named pod after
|
||||
verifying the cluster identity and pod identity. That path rides the Kubernetes
|
||||
API server's TLS with the operator's cluster credentials; the client cannot infer
|
||||
that binding from its local URL. Note this
|
||||
is the exact reverse of the caller direction, where port-forward bypasses the
|
||||
NetworkPolicy (`FLEX-WP-0023`); the two properties point opposite ways and
|
||||
summarising either as "the network protects it" gets one backwards.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue