docs: CRL-OCSP-DESIGN + lab-test-ca crl subcommand
Future real-CA revocation design; lab empty CRL generator only.
This commit is contained in:
parent
ca117eb458
commit
a973431935
4 changed files with 250 additions and 8 deletions
160
docs/CRL-OCSP-DESIGN.md
Normal file
160
docs/CRL-OCSP-DESIGN.md
Normal file
|
|
@ -0,0 +1,160 @@
|
||||||
|
# CRL / OCSP design (future real CA)
|
||||||
|
|
||||||
|
**Status:** design only — **not implemented** in staff-iam.
|
||||||
|
|
||||||
|
- No CRL distribution endpoint
|
||||||
|
- No OCSP responder
|
||||||
|
- No revocation API on enroll/mint paths
|
||||||
|
- Lab helper may emit an **empty** CRL file for local proxy experiments only ([`scripts/lab-test-ca.sh`](../scripts/lab-test-ca.sh) `crl`)
|
||||||
|
|
||||||
|
Production device-cert **mint** is still out of scope ([PKI-MINT-BACKLOG.md](./PKI-MINT-BACKLOG.md)). Lab mint (`LAB_CA_ENABLE=1`) is never a production CA and must not be treated as a revocation authority.
|
||||||
|
|
||||||
|
Canonical enroll contract: [ENROLL.md](../ENROLL.md). Lab CA: [TEST-CA-DESIGN.md](./TEST-CA-DESIGN.md). Platform revocation baseline: short lifetimes first; CRL/OCSP for intermediates and offboard bulk revoke (security-reference §6.4).
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
When (and only when) product ships a **real** production `Signer` for staff device certificates, operators need a documented revocation story:
|
||||||
|
|
||||||
|
1. How a lost/stolen workstation cert is invalidated before natural expiry.
|
||||||
|
2. How reverse proxies and mTLS terminators learn about revocations.
|
||||||
|
3. What staff-iam stores (metadata only) vs what the CA / edge owns.
|
||||||
|
4. What stays **out** of the IAM Node process (no in-process OCSP, no fake “revoked” demo PEMs).
|
||||||
|
|
||||||
|
This document is that story. It does **not** authorize implementing CRL/OCSP inside staff-iam today.
|
||||||
|
|
||||||
|
## Non-goals (now)
|
||||||
|
|
||||||
|
| Non-goal | Why |
|
||||||
|
|----------|-----|
|
||||||
|
| Ship CRL or OCSP HTTP from staff-iam | IAM is not a CA; default mint stays **501** |
|
||||||
|
| Soften mTLS with a stub “revoked” flag that is not backed by CA state | Violates “no fake crypto” |
|
||||||
|
| Require CRL checks for lab-only leaves | Lab leaves are short-lived (≤30d script cap; default 7d); throwaway trust |
|
||||||
|
| Put private CA keys or OCSP signing keys in the IAM user store | Keys stay in HSM / external PKI / `LAB_PKI_DIR` (lab only) |
|
||||||
|
| Browser “Revoke cert” that only flips `mtlsEnrolled` | Admin flag is enrollment policy, not cryptographic revocation |
|
||||||
|
|
||||||
|
## Recommended production model
|
||||||
|
|
||||||
|
Align with Verae security-reference provisioning:
|
||||||
|
|
||||||
|
| Control | Role |
|
||||||
|
|---------|------|
|
||||||
|
| **Short leaf lifetime** | Primary control (hours–days for staff device certs; renew via real mint path) |
|
||||||
|
| **CRL and/or OCSP on issuing intermediate** | Secondary control for early revoke and offboard |
|
||||||
|
| **Proxy / edge termination** | Performs chain verify **and** revocation check; forwards verify/DN headers to IAM |
|
||||||
|
| **staff-iam** | Stores enrollment flag + optional cert **metadata** (serial, fingerprint, notAfter); never signs CRL/OCSP itself unless product later splits a dedicated PKI service |
|
||||||
|
|
||||||
|
```
|
||||||
|
Corporate / HSM CA (or EST/SCEP/ACME delegate)
|
||||||
|
│ signs leaves
|
||||||
|
│ publishes CRL URI and/or OCSP URL in AIA/CRLDP
|
||||||
|
▼
|
||||||
|
Reverse proxy (mTLS terminate)
|
||||||
|
│ verify + CRL/OCSP (or short-lived-only policy)
|
||||||
|
│ forward ssl-client-verify / DN / optional PEM presence
|
||||||
|
▼
|
||||||
|
staff-iam GET /enroll/status · STAFF_MTLS_ENFORCE
|
||||||
|
│ mtlsEnrolled flag + future serial metadata
|
||||||
|
▼
|
||||||
|
Login / My security UI
|
||||||
|
```
|
||||||
|
|
||||||
|
**Preferred default for staff workstations:** short-lived client certs + automated renew, with OCSP stapling or CRL fetch at the **proxy**, not inside the IAM app.
|
||||||
|
|
||||||
|
## Options (choose at live-mint design time)
|
||||||
|
|
||||||
|
### A — Proxy-side only (recommended first)
|
||||||
|
|
||||||
|
- Issuing CA publishes CRL Distribution Points and/or OCSP in leaf/intermediate extensions.
|
||||||
|
- nginx / Caddy / Envoy / corporate WAF enables client-cert verify + revocation.
|
||||||
|
- staff-iam continues to trust `proxy.verifyOk` / DN headers only.
|
||||||
|
- Offboard: admin sets `mtlsEnrolled: false` **and** CA revokes serial (runbook both).
|
||||||
|
|
||||||
|
**Pros:** no new IAM crypto surface; matches today’s header contract.
|
||||||
|
**Cons:** revoke latency depends on CRL TTL / OCSP cache; operators must wire proxy correctly.
|
||||||
|
|
||||||
|
### B — CA-adjacent PKI service (not in IAM process)
|
||||||
|
|
||||||
|
- Dedicated signer service owns issue + revoke + CRL/OCSP endpoints.
|
||||||
|
- staff-iam calls `Signer.issue` / `Signer.revoke(serial)` over mTLS; never holds CA key.
|
||||||
|
- Status UI may show “revoked at CA” from metadata poll, not by serving CRL bytes.
|
||||||
|
|
||||||
|
**Pros:** clean AuthZ boundary; scalable OCSP.
|
||||||
|
**Cons:** new service + ops; still need proxy to enforce at TLS.
|
||||||
|
|
||||||
|
### C — In-process staff-iam OCSP/CRL (discouraged)
|
||||||
|
|
||||||
|
- Only if product explicitly requires IAM to be the issuing CA (unlikely).
|
||||||
|
- Would need HSM, AIA URLs, cache, audit, rate limits, and production hardening.
|
||||||
|
- **Do not** start here; backlog assumes external/HSM/EST signer first.
|
||||||
|
|
||||||
|
## Data staff-iam may hold later (metadata only)
|
||||||
|
|
||||||
|
When live mint ships, persist **at most**:
|
||||||
|
|
||||||
|
| Field | Use |
|
||||||
|
|-------|-----|
|
||||||
|
| `serial` (hex) | Correlate revoke + support |
|
||||||
|
| `fingerprint` (SHA-256 of DER) | Display / audit |
|
||||||
|
| `notAfter` | Renew warnings |
|
||||||
|
| `revokedAt` / `revokeReason` | UI + audit after CA confirms |
|
||||||
|
| `deviceId` (optional) | Bind to workstation record |
|
||||||
|
|
||||||
|
Never store leaf private keys, PKCS#12 passwords, or full cert PEM in the user JSON unless a separate encrypted secret store is designed. Audit events may log serial/fingerprint flags only (same rule as today’s `csr_attempt` — no PEM bodies).
|
||||||
|
|
||||||
|
## Revoke / offboard runbook (future)
|
||||||
|
|
||||||
|
1. Confirm identity (staff user + device).
|
||||||
|
2. Call CA revoke (CRL entry and/or OCSP revoked status) with reason (`keyCompromise` / `cessationOfOperation`).
|
||||||
|
3. Set `mtlsEnrolled: false` (and any device record) in IAM.
|
||||||
|
4. Optionally kill active sessions (orthogonal to cert crypto).
|
||||||
|
5. Wait for proxy CRL/OCSP cache TTL or force cache flush.
|
||||||
|
6. Verify: client cert no longer yields `proxy.verifyOk`; login enforce path denies.
|
||||||
|
|
||||||
|
Bulk tenant/staff offboard: revoke **all** serials bound to that principal at the CA, then clear IAM flags.
|
||||||
|
|
||||||
|
## Lab only — empty CRL helper
|
||||||
|
|
||||||
|
[`scripts/lab-test-ca.sh`](../scripts/lab-test-ca.sh) optional subcommand:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./scripts/lab-test-ca.sh crl [--dir DIR] [--out PATH]
|
||||||
|
```
|
||||||
|
|
||||||
|
- Requires an initialized lab CA (`init`).
|
||||||
|
- Writes a **valid, empty** CRL (no revoked serials) signed by the lab root, default `DIR/lab-empty.crl.pem`.
|
||||||
|
- Purpose: let a **local** dev proxy load a CRL file path so verify+CRL config can be smoke-tested without implying production revocation.
|
||||||
|
- **NOT FOR PRODUCTION.** Empty CRL does not revoke anything; lab root must not be in real trust stores.
|
||||||
|
- Does **not** add HTTP CRL/OCSP routes to staff-iam.
|
||||||
|
|
||||||
|
## HTTP surfaces (not shipped)
|
||||||
|
|
||||||
|
| Surface | Today | Future (product decision) |
|
||||||
|
|---------|--------|---------------------------|
|
||||||
|
| `POST /enroll/csr` | 501 default; lab 201 only | Real sign; still no CRL body |
|
||||||
|
| `POST /enroll/revoke` (name TBD) | absent | Optional: AuthZ’d request that calls external `Signer.revoke` |
|
||||||
|
| `GET /crl/...` or OCSP | absent | Prefer CA/proxy hostnames in cert AIA/CRLDP — not staff-iam origin |
|
||||||
|
| `GET /enroll/status` | proxy headers + flags | May add serial / notAfter / revokedAt metadata |
|
||||||
|
|
||||||
|
## Implementation order (blocked on product)
|
||||||
|
|
||||||
|
1. Choose production CA model in [PKI-MINT-BACKLOG.md](./PKI-MINT-BACKLOG.md) (external ACME/EST/HSM/delegated).
|
||||||
|
2. Decide Option A vs B for revocation enforcement (default **A**).
|
||||||
|
3. Document proxy verify+CRL/OCSP settings in operator ENROLL runbook.
|
||||||
|
4. Add `Signer.revoke` + IAM metadata fields when mint is real.
|
||||||
|
5. Only then consider bulk offboard automation and status UI revoke state.
|
||||||
|
6. **Never** enable lab empty-CRL or lab root as a production trust anchor.
|
||||||
|
|
||||||
|
## Hard rules
|
||||||
|
|
||||||
|
1. **No fake revocation** — do not return success on a revoke API that only flips a boolean without CA action.
|
||||||
|
2. **Proxy remains TLS source of truth** for “cert valid on this request.”
|
||||||
|
3. **Lab CRL is empty + lab-signed only** — experiments, not fleet security.
|
||||||
|
4. **Short lifetime remains the primary control**; CRL/OCSP are complementary.
|
||||||
|
5. Cross-link live-mint PRs: this doc + [PKI-MINT-BACKLOG.md](./PKI-MINT-BACKLOG.md) + [ENROLL.md](../ENROLL.md) + [TEST-CA-DESIGN.md](./TEST-CA-DESIGN.md).
|
||||||
|
|
||||||
|
## Related docs
|
||||||
|
|
||||||
|
- [PKI-MINT-BACKLOG.md](./PKI-MINT-BACKLOG.md) — live mint checklist; CRL/OCSP item
|
||||||
|
- [TEST-CA-DESIGN.md](./TEST-CA-DESIGN.md) — lab CA init/sign; never production
|
||||||
|
- [ENROLL.md](../ENROLL.md) — mTLS states, proxy headers, CSR scaffold
|
||||||
|
- [README.md](../README.md) — service overview and security gates
|
||||||
|
|
@ -79,10 +79,10 @@ Still left for live PKI: full checklist under “Left for live PKI” below.
|
||||||
|
|
||||||
Shipped for **lab/dev only** (loud warnings; never production):
|
Shipped for **lab/dev only** (loud warnings; never production):
|
||||||
|
|
||||||
- [x] [`scripts/lab-test-ca.sh`](../scripts/lab-test-ca.sh) — OpenSSL self-signed lab root (`init`) + sign CSR → leaf PEM/chain (`sign`); loud **NOT FOR PRODUCTION** warnings; default output `lab-pki/` (gitignored)
|
- [x] [`scripts/lab-test-ca.sh`](../scripts/lab-test-ca.sh) — OpenSSL self-signed lab root (`init`) + sign CSR → leaf PEM/chain (`sign`); optional empty **`crl`**; loud **NOT FOR PRODUCTION** warnings; default output `lab-pki/` (gitignored)
|
||||||
- [x] **Opt-in HTTP:** `LAB_CA_ENABLE=1` + lab-pki ready → `POST /enroll/csr` shells out to `sign` → **201** + `certificate` PEM + `X-Lab-CA: 1`
|
- [x] **Opt-in HTTP:** `LAB_CA_ENABLE=1` + lab-pki ready → `POST /enroll/csr` shells out to `sign` → **201** + `certificate` PEM + `X-Lab-CA: 1`
|
||||||
- [x] **Default off** → HTTP path stays **501**; `NODE_ENV=production` refuses lab path
|
- [x] **Default off** → HTTP path stays **501**; `NODE_ENV=production` refuses lab path
|
||||||
- [x] Documented in [ENROLL.md](../ENROLL.md) + [TEST-CA-DESIGN.md](./TEST-CA-DESIGN.md)
|
- [x] Documented in [ENROLL.md](../ENROLL.md) + [TEST-CA-DESIGN.md](./TEST-CA-DESIGN.md) + [CRL-OCSP-DESIGN.md](./CRL-OCSP-DESIGN.md)
|
||||||
|
|
||||||
| Layer | Lab path | Production mint (backlog below) |
|
| Layer | Lab path | Production mint (backlog below) |
|
||||||
|-------|----------|----------------------------------|
|
|-------|----------|----------------------------------|
|
||||||
|
|
@ -129,7 +129,7 @@ Checklist for a real in-app mint (product + security design required before codi
|
||||||
- [ ] Persist serial / fingerprint / notAfter for status and renew gates (store metadata only)
|
- [ ] Persist serial / fingerprint / notAfter for status and renew gates (store metadata only)
|
||||||
- [ ] `GET /enroll/status` (or successor) surfaces real cert metadata when present
|
- [ ] `GET /enroll/status` (or successor) surfaces real cert metadata when present
|
||||||
- [ ] Renew / re-key endpoint and expiry warnings; revoke on offboard
|
- [ ] Renew / re-key endpoint and expiry warnings; revoke on offboard
|
||||||
- [ ] CRL/OCSP or proxy-side revocation story documented
|
- [x] ~~CRL/OCSP or proxy-side revocation story documented~~ — [CRL-OCSP-DESIGN.md](./CRL-OCSP-DESIGN.md); lab empty CRL via `lab-test-ca.sh crl` (not production)
|
||||||
- [ ] Remove 501 scaffold; keep “no fake crypto” rule for tests (fixtures may use offline [`scripts/lab-test-ca.sh`](../scripts/lab-test-ca.sh) or a future gated test CA — see [TEST-CA-DESIGN.md](./TEST-CA-DESIGN.md); **never** default-on in server)
|
- [ ] Remove 501 scaffold; keep “no fake crypto” rule for tests (fixtures may use offline [`scripts/lab-test-ca.sh`](../scripts/lab-test-ca.sh) or a future gated test CA — see [TEST-CA-DESIGN.md](./TEST-CA-DESIGN.md); **never** default-on in server)
|
||||||
- [ ] Operator runbooks + ENROLL.md / README updated for the live path
|
- [ ] Operator runbooks + ENROLL.md / README updated for the live path
|
||||||
|
|
||||||
|
|
@ -146,7 +146,8 @@ If product later needs in-app production mint/renew, that is a **new** design (r
|
||||||
## Related docs
|
## Related docs
|
||||||
|
|
||||||
- [TEST-CA-DESIGN.md](./TEST-CA-DESIGN.md) — lab script (offline) + **future** gated test CA design; no HTTP fake mint
|
- [TEST-CA-DESIGN.md](./TEST-CA-DESIGN.md) — lab script (offline) + **future** gated test CA design; no HTTP fake mint
|
||||||
- [`scripts/lab-test-ca.sh`](../scripts/lab-test-ca.sh) — OpenSSL lab CA init/sign (NOT production; optional `LAB_CA_ENABLE=1` HTTP shell-out)
|
- [CRL-OCSP-DESIGN.md](./CRL-OCSP-DESIGN.md) — future real-CA revocation (proxy CRL/OCSP); lab empty CRL only
|
||||||
|
- [`scripts/lab-test-ca.sh`](../scripts/lab-test-ca.sh) — OpenSSL lab CA init/sign/crl (NOT production; optional `LAB_CA_ENABLE=1` HTTP shell-out)
|
||||||
- [ENROLL.md](../ENROLL.md) — mTLS states, `nextSteps`, `proxyHeadersSeen`, proxy header contract, admin workflow
|
- [ENROLL.md](../ENROLL.md) — mTLS states, `nextSteps`, `proxyHeadersSeen`, proxy header contract, admin workflow
|
||||||
- [README.md](../README.md) — install, usage, staff security gates (mTLS row: proxy headers only, no device-cert mint)
|
- [README.md](../README.md) — install, usage, staff security gates (mTLS row: proxy headers only, no device-cert mint)
|
||||||
- [TOTP.md](../TOTP.md) — authenticator 2FA (orthogonal gate)
|
- [TOTP.md](../TOTP.md) — authenticator 2FA (orthogonal gate)
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ Live mint product backlog and hard “no fake crypto” rules: [PKI-MINT-BACKLOG
|
||||||
| Item | Detail |
|
| Item | Detail |
|
||||||
|------|--------|
|
|------|--------|
|
||||||
| Path | [`scripts/lab-test-ca.sh`](../scripts/lab-test-ca.sh) |
|
| Path | [`scripts/lab-test-ca.sh`](../scripts/lab-test-ca.sh) |
|
||||||
| Offline | `init` → self-signed lab root under `lab-pki/` (gitignored); `sign --csr` → short-lived leaf PEM + chain on disk |
|
| Offline | `init` → self-signed lab root under `lab-pki/` (gitignored); `sign --csr` → short-lived leaf PEM + chain on disk; optional `crl` → empty lab CRL |
|
||||||
| Opt-in HTTP | `LAB_CA_ENABLE=1` + lab-pki ready → staff-iam shells out to `sign` on `POST /enroll/csr` → **201** + `X-Lab-CA: 1` |
|
| Opt-in HTTP | `LAB_CA_ENABLE=1` + lab-pki ready → staff-iam shells out to `sign` on `POST /enroll/csr` → **201** + `X-Lab-CA: 1` |
|
||||||
| Default | Flag **off** → `POST /enroll/csr` **501** (unchanged production scaffold) |
|
| Default | Flag **off** → `POST /enroll/csr` **501** (unchanged production scaffold) |
|
||||||
| Production refuse | `NODE_ENV=production` → lab path off even if `LAB_CA_ENABLE=1` |
|
| Production refuse | `NODE_ENV=production` → lab path off even if `LAB_CA_ENABLE=1` |
|
||||||
|
|
@ -92,7 +92,7 @@ Proxy trusts corp roots Dev proxy may trust lab-pki root (lab only)
|
||||||
```
|
```
|
||||||
platform/verae-staff-iam/
|
platform/verae-staff-iam/
|
||||||
scripts/
|
scripts/
|
||||||
lab-test-ca.sh # LAB ONLY: init root + sign CSR → PEM on disk
|
lab-test-ca.sh # LAB ONLY: init root + sign CSR + empty crl → PEM on disk
|
||||||
lab-pki/ # default output dir (gitignored; keys never committed)
|
lab-pki/ # default output dir (gitignored; keys never committed)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -186,6 +186,7 @@ Exact algorithms should match whatever production CA model is selected in [PKI-M
|
||||||
## Related docs
|
## Related docs
|
||||||
|
|
||||||
- [PKI-MINT-BACKLOG.md](./PKI-MINT-BACKLOG.md) — shipped proxy/schema/501 surface; live mint checklist; no-fake-crypto rules
|
- [PKI-MINT-BACKLOG.md](./PKI-MINT-BACKLOG.md) — shipped proxy/schema/501 surface; live mint checklist; no-fake-crypto rules
|
||||||
|
- [CRL-OCSP-DESIGN.md](./CRL-OCSP-DESIGN.md) — future production CRL/OCSP; lab empty CRL helper
|
||||||
- [ENROLL.md](../ENROLL.md) — mTLS states, proxy headers, CSR schema/scaffold
|
- [ENROLL.md](../ENROLL.md) — mTLS states, proxy headers, CSR schema/scaffold
|
||||||
- [README.md](../README.md) — service overview and security gates
|
- [README.md](../README.md) — service overview and security gates
|
||||||
- [TOTP.md](../TOTP.md) — orthogonal authenticator 2FA (real crypto; unrelated to device-cert mint)
|
- [TOTP.md](../TOTP.md) — orthogonal authenticator 2FA (real crypto; unrelated to device-cert mint)
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
# Usage:
|
# Usage:
|
||||||
# scripts/lab-test-ca.sh init [--dir DIR]
|
# scripts/lab-test-ca.sh init [--dir DIR]
|
||||||
# scripts/lab-test-ca.sh sign --csr PATH [--dir DIR] [--out PATH] [--days N] [--cn CN]
|
# scripts/lab-test-ca.sh sign --csr PATH [--dir DIR] [--out PATH] [--days N] [--cn CN]
|
||||||
|
# scripts/lab-test-ca.sh crl [--dir DIR] [--out PATH]
|
||||||
# scripts/lab-test-ca.sh warn
|
# scripts/lab-test-ca.sh warn
|
||||||
#
|
#
|
||||||
# Defaults: DIR=./lab-pki (gitignored). Requires openssl on PATH.
|
# Defaults: DIR=./lab-pki (gitignored). Requires openssl on PATH.
|
||||||
|
|
@ -53,13 +54,18 @@ Usage:
|
||||||
--days leaf notAfter (default ${DAYS_DEFAULT}, max 30 for lab)
|
--days leaf notAfter (default ${DAYS_DEFAULT}, max 30 for lab)
|
||||||
--cn optional subject CN override in the issued cert (lab only)
|
--cn optional subject CN override in the issued cert (lab only)
|
||||||
|
|
||||||
|
$SCRIPT_NAME crl [--dir DIR] [--out PATH]
|
||||||
|
Write a lab-only **empty** CRL (no revoked serials) signed by the lab root.
|
||||||
|
--out defaults to DIR/lab-empty.crl.pem
|
||||||
|
For local proxy CRL-path smoke tests only — NOT production revocation.
|
||||||
|
|
||||||
$SCRIPT_NAME warn
|
$SCRIPT_NAME warn
|
||||||
Print the lab-only warning and exit 0.
|
Print the lab-only warning and exit 0.
|
||||||
|
|
||||||
Environment:
|
Environment:
|
||||||
LAB_PKI_DIR Override default DIR when --dir omitted.
|
LAB_PKI_DIR Override default DIR when --dir omitted.
|
||||||
|
|
||||||
Exit codes: 0 ok · 1 usage/input · 2 missing openssl/CA · 3 sign failure
|
Exit codes: 0 ok · 1 usage/input · 2 missing openssl/CA · 3 sign/CRL failure
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -139,7 +145,7 @@ Root cert: lab-root.crt.pem (public)
|
||||||
Root key: lab-root.key.pem (PRIVATE — never commit, never production trust)
|
Root key: lab-root.key.pem (PRIVATE — never commit, never production trust)
|
||||||
With LAB_CA_ENABLE=1 the staff-iam server may shell-out sign against this dir.
|
With LAB_CA_ENABLE=1 the staff-iam server may shell-out sign against this dir.
|
||||||
Default (flag off) POST /enroll/csr stays 501. NEVER production.
|
Default (flag off) POST /enroll/csr stays 501. NEVER production.
|
||||||
See docs/TEST-CA-DESIGN.md, ENROLL.md, docs/PKI-MINT-BACKLOG.md.
|
See docs/TEST-CA-DESIGN.md, docs/CRL-OCSP-DESIGN.md, ENROLL.md, docs/PKI-MINT-BACKLOG.md.
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
echo "lab CA created:"
|
echo "lab CA created:"
|
||||||
|
|
@ -254,6 +260,79 @@ EOF
|
||||||
warn_banner
|
warn_banner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd_crl() {
|
||||||
|
local dir="" out=""
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--dir) dir="${2:-}"; shift 2 ;;
|
||||||
|
--out) out="${2:-}"; shift 2 ;;
|
||||||
|
-h|--help) usage; exit 0 ;;
|
||||||
|
*) echo "error: unknown crl arg: $1" >&2; usage >&2; exit 1 ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
need_openssl
|
||||||
|
warn_banner
|
||||||
|
dir="$(resolve_dir "$dir")"
|
||||||
|
local key="$dir/lab-root.key.pem"
|
||||||
|
local ca="$dir/lab-root.crt.pem"
|
||||||
|
|
||||||
|
if [[ ! -f "$key" || ! -f "$ca" ]]; then
|
||||||
|
echo "error: lab CA missing under $dir — run: $SCRIPT_NAME init --dir $dir" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$out" ]]; then
|
||||||
|
out="$dir/lab-empty.crl.pem"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Empty CRL: no revoked serials. Lab smoke-test fixture only.
|
||||||
|
local crl_cnf="$dir/lab-crl.cnf"
|
||||||
|
local crl_idx="$dir/lab-crl-index.txt"
|
||||||
|
local crl_attr="$dir/lab-crl-index.txt.attr"
|
||||||
|
: >"$crl_idx"
|
||||||
|
echo "unique_subject = no" >"$crl_attr"
|
||||||
|
cat >"$crl_cnf" <<EOF
|
||||||
|
[ ca ]
|
||||||
|
default_ca = lab_ca
|
||||||
|
|
||||||
|
[ lab_ca ]
|
||||||
|
dir = $dir
|
||||||
|
database = $crl_idx
|
||||||
|
serial = $dir/lab-root.srl
|
||||||
|
certificate = $ca
|
||||||
|
private_key = $key
|
||||||
|
default_md = sha256
|
||||||
|
default_days = 30
|
||||||
|
default_crl_days = 30
|
||||||
|
crlnumber = $dir/lab-crlnumber
|
||||||
|
copy_extensions = none
|
||||||
|
policy = policy_any
|
||||||
|
|
||||||
|
[ policy_any ]
|
||||||
|
commonName = optional
|
||||||
|
EOF
|
||||||
|
if [[ ! -f "$dir/lab-crlnumber" ]]; then
|
||||||
|
echo "01" >"$dir/lab-crlnumber"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! openssl ca -gencrl -config "$crl_cnf" -out "$out" 2>"$dir/last-crl.err"; then
|
||||||
|
echo "error: openssl gencrl failed:" >&2
|
||||||
|
cat "$dir/last-crl.err" >&2 || true
|
||||||
|
exit 3
|
||||||
|
fi
|
||||||
|
rm -f "$dir/last-crl.err"
|
||||||
|
|
||||||
|
echo "lab empty CRL written (NOT FOR PRODUCTION):"
|
||||||
|
echo " crl: $out"
|
||||||
|
echo " revoked entries: 0 (empty)"
|
||||||
|
openssl crl -in "$out" -noout -text 2>/dev/null | head -n 20 || true
|
||||||
|
echo
|
||||||
|
echo "Dev proxy only: point CRL path at this file if testing verify+CRL config."
|
||||||
|
echo "See docs/CRL-OCSP-DESIGN.md — empty lab CRL, never production revocation."
|
||||||
|
warn_banner
|
||||||
|
}
|
||||||
|
|
||||||
main() {
|
main() {
|
||||||
local cmd="${1:-}"
|
local cmd="${1:-}"
|
||||||
if [[ -z "$cmd" ]]; then
|
if [[ -z "$cmd" ]]; then
|
||||||
|
|
@ -265,6 +344,7 @@ main() {
|
||||||
case "$cmd" in
|
case "$cmd" in
|
||||||
init) cmd_init "$@" ;;
|
init) cmd_init "$@" ;;
|
||||||
sign) cmd_sign "$@" ;;
|
sign) cmd_sign "$@" ;;
|
||||||
|
crl) cmd_crl "$@" ;;
|
||||||
warn) warn_banner; exit 0 ;;
|
warn) warn_banner; exit 0 ;;
|
||||||
-h|--help|help) usage; exit 0 ;;
|
-h|--help|help) usage; exit 0 ;;
|
||||||
*)
|
*)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue