Inherit nginx x509 header config, add operator runbook
- LookupConfig: ssl-client-cert / ssl-cert-chain-prefix / certificate-chain-length now fall back to the built-in nginx provider's settings (Config scope, then KC_SPI_X509CERT_LOOKUP_NGINX_* env vars), so switching the provider to "hybrid" needs no duplicated Helm values. Explicit hybrid-scope settings still override. - Add LookupConfigTest covering inheritance, override, and defaults (14 tests total, all passing). - Add RUNBOOK.md: phase-by-phase deployment procedure sized to 30-min test windows, with verification checklists, forged-header negative test, rollback per phase, and failure triage table. - README/Dockerfile.example updated to match; stop tracking target/ build output (.gitignore added). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,9 @@ Per-request decision logic:
|
||||
No changes are needed to your realm's X509 browser authentication flow — the
|
||||
authenticator receives the cert the same way regardless of source.
|
||||
|
||||
> **Deploying this?** Follow the step-by-step operator guide in [RUNBOOK.md](RUNBOOK.md).
|
||||
> This README is the reference (config options, security rationale, troubleshooting).
|
||||
|
||||
---
|
||||
|
||||
## 1. Build
|
||||
@@ -71,9 +74,11 @@ Do NOT use `required`.
|
||||
# Switch the lookup provider from nginx to hybrid
|
||||
KC_SPI_X509CERT_LOOKUP_PROVIDER=hybrid
|
||||
|
||||
# Header carrying the user cert — COPY THE VALUE from your existing
|
||||
# KC_SPI_X509CERT_LOOKUP_NGINX_SSL_CLIENT_CERT (default "ssl-client-cert")
|
||||
KC_SPI_X509CERT_LOOKUP_HYBRID_SSL_CLIENT_CERT=ssl-client-cert
|
||||
# Header name: NOTHING TO ADD. The hybrid provider inherits ssl-client-cert,
|
||||
# ssl-cert-chain-prefix and certificate-chain-length from your existing
|
||||
# KC_SPI_X509CERT_LOOKUP_NGINX_* settings in the Helm values — leave them in place.
|
||||
# (Set KC_SPI_X509CERT_LOOKUP_HYBRID_SSL_CLIENT_CERT only to override; the startup
|
||||
# log line "inherited from the nginx provider config" confirms what was picked up.)
|
||||
|
||||
# Day-one: permissive mode (headers accepted from anyone, like today, but everything logged)
|
||||
KC_SPI_X509CERT_LOOKUP_HYBRID_TRUST_MODE=log
|
||||
@@ -94,9 +99,9 @@ All options (prefix `spi-x509cert-lookup-hybrid-`):
|
||||
|
||||
| Option | Default | Meaning |
|
||||
|---|---|---|
|
||||
| `ssl-client-cert` | `ssl-client-cert` | Header with the user cert (PEM, URL-encoded PEM, or base64 DER — auto-detected) |
|
||||
| `ssl-cert-chain-prefix` | `ssl-cert-chain` | Optional chain headers `<prefix>-0..n` |
|
||||
| `certificate-chain-length` | `1` | Max chain headers to read |
|
||||
| `ssl-client-cert` | inherits nginx setting, else `ssl-client-cert` | Header with the user cert (PEM, URL-encoded PEM, or base64 DER — auto-detected) |
|
||||
| `ssl-cert-chain-prefix` | inherits nginx setting, else `ssl-cert-chain` | Optional chain headers `<prefix>-0..n` |
|
||||
| `certificate-chain-length` | inherits nginx setting, else `1` | Max chain headers to read |
|
||||
| `trust-mode` | `log` | `log` = honor all headers, warn on untrusted; `enforce` = ignore headers from untrusted peers |
|
||||
| `trusted-proxy-cert-sha256` | — | Comma-separated SHA-256 fingerprints of the F5's client cert(s). **Strongest check.** List old+new during rotations. |
|
||||
| `trusted-proxy-subject-dn` | — | `\|`-separated exact subject DNs (RFC2253). Safe because TLS already validated the chain. Survives rotation. |
|
||||
@@ -115,15 +120,16 @@ browsers use to filter the cert-picker dialog.
|
||||
|
||||
## 4. Rollout / test plan (one 30-min cycle each, in order)
|
||||
|
||||
**Cycle 0 — no deploy, info gathering.** From the current deployment grab:
|
||||
`KC_SPI_X509CERT_LOOKUP_NGINX_SSL_CLIENT_CERT` (header name), truststore config, base image
|
||||
tag, and whether `start --optimized` is used. Ask the F5 team to start on the one-pager
|
||||
(section 6) in parallel.
|
||||
**Cycle 0 — no deploy, info gathering.** From the current deployment grab: truststore
|
||||
config, base image tag, and whether `start --optimized` is used. (The header name is
|
||||
inherited automatically from the existing `KC_SPI_X509CERT_LOOKUP_NGINX_*` values — no
|
||||
need to look it up.) Ask the F5 team to start on the one-pager (section 6) in parallel.
|
||||
|
||||
**Cycle 1 — deploy in log mode (zero behavior change expected).**
|
||||
Jar + `KC_HTTPS_CLIENT_AUTH=request` + provider=hybrid + `trust-mode=log`.
|
||||
Jar + `KC_HTTPS_CLIENT_AUTH=request` + provider=hybrid + `trust-mode=log`; keep all
|
||||
existing `KC_SPI_X509CERT_LOOKUP_NGINX_*` values in the Helm values file untouched.
|
||||
Verify: existing F5 CAC login still works. Then grep logs for `x509-hybrid`:
|
||||
- startup line shows the parsed config;
|
||||
- startup lines show the parsed config, including which nginx settings were inherited;
|
||||
- each F5 login logs `remoteAddr=` (→ your CIDR value) and `peer=` (→ `no-tls-client-cert`
|
||||
until the F5 presents one);
|
||||
- `header cert decoded using strategy '...'` (DEBUG) confirms the F5's encoding.
|
||||
|
||||
Reference in New Issue
Block a user