Convert OPEN-ISSUES #4 external items to READY ops packages without shipping production mint. LAB_CA_ENABLE stays default off; NODE_ENV= production still refuses lab; default POST /enroll/csr remains 501. - docs/PROD-CA-CUTOVER-RUNBOOK.md (mint/renew/revoke cutover) - docs/AUTHZ-ENROLL-DESIGN.md (gates before dropping 501) - docs/CRL-OCSP-DEPLOY-CHECKLIST.md (proxy/CA revoke deploy) - Cross-links from README, ENROLL, PKI-MINT-BACKLOG, refuse/design docs npm test: 19/19 PASS
8 KiB
8 KiB
CRL / OCSP production deploy checklist (READY package)
Status: READY package — operator checklist to deploy production revocation (CRL and/or OCSP) for staff device certificates.
Not implemented in staff-iam. No CRL/OCSP HTTP routes ship from this service. Lab lab-test-ca.sh crl emits an empty lab-signed CRL for local experiments only — never production.
Design background: CRL-OCSP-DESIGN.md.
Cutover context: PROD-CA-CUTOVER-RUNBOOK.md.
AuthZ revoke path: AUTHZ-ENROLL-DESIGN.md.
Hard rules
- Primary control = short leaf lifetime; CRL/OCSP are complementary.
- Proxy / edge performs chain verify and revocation check — not the IAM Node process.
- staff-iam does not serve
GET /crlor OCSP — prefer AIA/CRLDP URLs on the issuing CA hostnames. - Lab empty CRL is not a revoke authority; lab root must not be in production trust stores.
- No fake revoke — flipping
mtlsEnrolled: falsewithout CA revoke is policy only, not crypto revoke. - LAB_CA_ENABLE stays default off; production refuses lab mint.
Choose enforcement option
| Option | Where revoke is checked | staff-iam role |
|---|---|---|
| A. Proxy-side only (recommended first) | nginx/Caddy/Envoy/WAF loads CRL or OCSP against client cert | Headers only; metadata later |
| B. CA-adjacent PKI service | Signer publishes CRL/OCSP; proxy still enforces TLS | IAM calls Signer.revoke |
| C. In-process IAM OCSP/CRL | Discouraged | Do not start here |
Default deploy path: A.
Pre-flight (CA)
- R-01 Issuing intermediate (or leaf profile) embeds CRL Distribution Points and/or AIA OCSP URL
- R-02 CRL/OCSP endpoints are HTTPS (or org-approved distribution), highly available, independent of staff-iam uptime
- R-03 CRL sign key / OCSP responder key custody documented (HSM preferred); not the IAM app key
- R-04 CRL validity / nextUpdate cadence agreed (e.g. ≤ 24h) and OCSP cache skew understood
- R-05 Reason codes mapped:
keyCompromise,cessationOfOperation,affiliationChanged(offboard) - R-06 Short-lived leaf policy documented if org skips CRL for leaves shorter than cache TTL
- R-07 Lab root /
lab-pkiabsent from production trust + CRL fetch config
Proxy deploy (Option A)
- R-10 Production trust store = corporate root/intermediate only
- R-11 Client cert verify on for staff doors (fail closed on
FAILED/ absent when enforce intended) - R-12 Revocation mode enabled:
- CRL file/URL periodic fetch, or
- OCSP (stapling where applicable; client-cert OCSP leaf check per proxy docs)
- R-13 Soft-fail vs hard-fail policy explicit:
- Hard-fail recommended for staff mTLS when OCSP/CRL unreachable (document availability needs)
- Soft-fail only with compensating short lifetime + monitoring
- R-14 Forward verify/DN headers to staff-iam per ENROLL.md
- R-15 Header spoofing blocked (proxy strips inbound client-supplied verify headers)
- R-16 Document cache TTL and how to force flush after emergency revoke
nginx sketch (names only — adapt to platform)
# illustrative — not a copy-paste production profile
ssl_client_certificate /etc/ssl/staff-ca-chain.pem;
ssl_verify_client on;
# ssl_crl /etc/ssl/staff-ca.crl; # if CRL file mode
# OCSP: per nginx/OpenSSL build capabilities — configure in org template
proxy_set_header X-SSL-Client-Verify $ssl_client_verify;
proxy_set_header X-SSL-Client-DN $ssl_client_s_dn;
Exact header names must match what staff-iam already reads (see ENROLL.md). Do not invent production hostnames here.
Caddy / Envoy
- Use org-standard mTLS + revoke modules.
- Same requirements: verify + revoke + forward identity headers + strip spoofed inbound.
CA-adjacent Signer (Option B add-on)
- R-20
Signer.revoke({ serial, reason })API live and audited - R-21 Revoke publishes to CRL and/or OCSP within agreed SLA (e.g. ≤ 5 minutes)
- R-22 staff-iam (when live mint ships) dual-writes: Signer.revoke + metadata
revokedAt+mtlsEnrolled: false - R-23 Bulk offboard job: all serials for principal → revoke → clear IAM flags
- R-24 Monitoring: revoke latency, CRL publish failures, OCSP error rate
staff-iam deploy attestation
- R-30 No CRL/OCSP listen sockets on staff-iam service
- R-31
NODE_ENV=production,LAB_CA_ENABLEunset - R-32
GET /enroll/statusstill reflects proxy verify — IAM does not claim crypto revoke itself - R-33 When metadata exists (future): status may show
serial/revokedAtfrom store, still subordinate to proxy check - R-34 Admin UI never offers “Revoke” that only flips a boolean without CA action (if button ships, it must call Signer)
Offboard / emergency revoke runbook
- Identify user + device + cert serial (from CA inventory or future IAM metadata).
- Revoke at CA (Option A portal/CLI or Option B
Signer.revoke) with reason. - IAM: set
mtlsEnrolled: false; optionally invalidate sessions. - Flush or wait proxy CRL/OCSP cache (R-16).
- Verify:
- Present revoked cert → proxy verify fail / revoke fail
GET /enroll/statuswithout good cert → notverifyOkSTAFF_MTLS_ENFORCE=1login path denies enrolled user without valid cert
- Ticket serial, time, reason, actor (no PEM bodies in tickets if avoidable).
Bulk tenant offboard: revoke all serials, then clear flags; do not rely on flag clear alone.
Lab vs production (do not confuse)
| Item | Lab | Production |
|---|---|---|
| CRL helper | ./scripts/lab-test-ca.sh crl → empty lab CRL |
Real CA CRL with serials |
| Trust | dev proxy + lab-root only on lab machines | Corporate chain only |
| OCSP | none in staff-iam | CA/responder hosts |
| Mint | optional LAB_CA_ENABLE=1 |
external PKI or Signer; lab refused |
| Empty CRL | smoke config only | Insufficient as revoke proof |
# LAB ONLY — never production trust
./scripts/lab-test-ca.sh init --dir ./lab-pki
./scripts/lab-test-ca.sh crl --dir ./lab-pki --out ./lab-pki/lab-empty.crl.pem
# point a *local* dev proxy at lab-root + empty CRL for config syntax checks only
Acceptance tests (ops)
- T-01 Valid unrevoked client cert → proxy OK → IAM status shows proxy present
- T-02 Unknown/untrusted cert → proxy fail → no spoofed verify header reaches IAM
- T-03 Revoked serial after cache TTL → proxy fail
- T-04 Emergency flush path works within agreed RTO
- T-05 staff-iam production still returns 501 on
POST /enroll/csruntil live Signer cutover - T-06
LAB_CA_ENABLE=1on production binary still does not mint (server refuse) - T-07 Monitoring alerts on CRL fetch fail / OCSP unhealthy
Do not
- Do not serve CRL/OCSP from staff-iam origin by default
- Do not load lab empty CRL in production
- Do not soft-fail revoke checks without short-lived certs + explicit risk acceptance
- Do not treat IAM enrollment flag as cryptographic revocation
- Do not enable lab CA to “work around” missing production CRL
Still left (ops / product)
- Live CA CRL/OCSP hostnames and certs (out-of-band)
- Proxy config in org IaC
- Signer.revoke when model B/C mint ships
- Optional IAM metadata + status UI revoke state after live mint
Related
- CRL-OCSP-DESIGN.md — architecture options A/B/C
- PROD-CA-CUTOVER-RUNBOOK.md
- AUTHZ-ENROLL-DESIGN.md
- PRODUCTION-PKI-REFUSE.md
- PKI-MINT-BACKLOG.md
- TEST-CA-DESIGN.md
- ENROLL.md
scripts/lab-test-ca.shcrl— LAB ONLY