diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 78f107a..3a96f61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1275,6 +1275,7 @@ jobs: CERTCTL_AUDIT_EXCLUDE_PATHS| CERTCTL_TLS_| CERTCTL_TLS_INSECURE_SKIP_VERIFY| + CERTCTL_SCEP_| CERTCTL_SERVER_CA_BUNDLE_PATH| CERTCTL_SERVER_TLS_INSECURE_SKIP_VERIFY| CERTCTL_QA_[A-Z_]+ diff --git a/docs/features.md b/docs/features.md index f72b6c0..e2a5832 100644 --- a/docs/features.md +++ b/docs/features.md @@ -649,7 +649,7 @@ SCEP uses a single URL (`/scep?operation=...`). The handler extracts PKCS#10 CSR | `CERTCTL_SCEP_RA_CERT_PATH` | (none) | Path to PEM-encoded RA (Registration Authority) certificate. **Required when `CERTCTL_SCEP_ENABLED=true`** for the RFC 8894 PKIMessage path: SCEP clients encrypt their PKCS#10 CSR to this cert's public key (EnvelopedData wrapper, RFC 8894 §3.2.2) and the server signs the outbound CertRep PKIMessage signerInfo with the matching key (RFC 8894 §3.3.2). Generation: a self-signed cert with `CN=-RA` and the `id-kp-emailProtection` / `id-kp-cmcRA` EKU is sufficient — see [`legacy-est-scep.md`](legacy-est-scep.md) for the openssl recipe. The preflight gate at startup also enforces a cert/key match, non-expired NotAfter, and an RSA-or-ECDSA public-key algorithm. | | `CERTCTL_SCEP_RA_KEY_PATH` | (none) | Path to PEM-encoded private key matching `CERTCTL_SCEP_RA_CERT_PATH`. **Required when `CERTCTL_SCEP_ENABLED=true`.** File MUST be mode `0600` (owner read/write only); preflight refuses to load a world- or group-readable RA key as defense-in-depth against credential leak. The server reads this file once at startup; rotation requires a restart. | | `CERTCTL_SCEP_PROFILES` | (none, single-profile mode) | Comma-separated list of SCEP profile names enabling **multi-endpoint dispatch** (Phase 1.5). When set, certctl exposes one `/scep/` endpoint per name (e.g. `CERTCTL_SCEP_PROFILES=corp,iot,server` produces `/scep/corp`, `/scep/iot`, `/scep/server`). Each name also drives the env-var prefix for the per-profile config below. When unset, certctl runs in legacy single-profile mode using the flat `CERTCTL_SCEP_*` env vars above (which synthesise a single-element profile bound to the legacy `/scep` root path). PathID must be a path-safe slug (`[a-z0-9-]`, no leading/trailing hyphen); names get lowercased for the URL path and uppercased for the env-var prefix. | -| `CERTCTL_SCEP_PROFILE__ISSUER_ID` | (none) | Per-profile issuer binding when `CERTCTL_SCEP_PROFILES` is set. `` is the upper-cased profile name from the list (e.g. `CERTCTL_SCEP_PROFILE_CORP_ISSUER_ID=iss-corp-laptop`). Same per-profile env-var prefix `CERTCTL_SCEP_PROFILE_` is also used for `_PROFILE_ID`, `_CHALLENGE_PASSWORD`, `_RA_CERT_PATH`, `_RA_KEY_PATH` — see the four rows below. Required for every profile listed in `CERTCTL_SCEP_PROFILES`. Each profile is independently validated at startup; per-profile failures log the offending PathID. | +| `CERTCTL_SCEP_PROFILE__ISSUER_ID` | (none) | Per-profile issuer binding when `CERTCTL_SCEP_PROFILES` is set. `` is the upper-cased profile name from the list (so a `CERTCTL_SCEP_PROFILES` entry of `corp` resolves the issuer-id env var key with `` replaced by `CORP`, the path-id `_ISSUER_ID` suffix unchanged). Same per-profile env-var prefix `CERTCTL_SCEP_PROFILE_` is also used for `_PROFILE_ID`, `_CHALLENGE_PASSWORD`, `_RA_CERT_PATH`, `_RA_KEY_PATH` — see the four rows below. Required for every profile listed in `CERTCTL_SCEP_PROFILES`. Each profile is independently validated at startup; per-profile failures log the offending PathID. | | `CERTCTL_SCEP_PROFILE__PROFILE_ID` | (none) | Per-profile optional `CertificateProfile` constraint, mirroring the legacy `CERTCTL_SCEP_PROFILE_ID`. Leave unset to allow the issuer's defaults. | | `CERTCTL_SCEP_PROFILE__CHALLENGE_PASSWORD` | (none) | Per-profile shared secret. **Required for every profile** in `CERTCTL_SCEP_PROFILES` (CWE-306: per-profile auth boundary). Empty value at startup fails the boot with the offending PathID in the structured log. | | `CERTCTL_SCEP_PROFILE__RA_CERT_PATH` | (none) | Per-profile RA certificate PEM path. Same semantics as `CERTCTL_SCEP_RA_CERT_PATH` but scoped to one profile. **Required for every profile.** |