mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-10 08:38:53 +00:00
8564e2fcd688d358c48f39d3a4b8bc8a008eaf7c
1 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c03ea519c5 |
feat(est): per-profile dispatch — multi-profile env-var family + back-compat shim
EST RFC 7030 hardening master bundle Phases 0 + 1 of 13. Lays the
foundation for the remaining hardening phases (mTLS auth, HTTP Basic
auth, channel binding, server-keygen, admin observability, GUI, libest
e2e) without changing existing operator behavior — backward-compat
shim preserves the v2.0.66 single-issuer flat env-var setup.
WHAT LANDS:
Phase 0 — Frozen decisions
9 frozen decisions documented in
cowork/est-rfc7030-hardening-prompt.md::Phase 0 frozen decisions
(auth modes mTLS+Basic at GA; RFC 9266 channel binding; multi-profile
env-var family CERTCTL_EST_PROFILES; mTLS sibling URL
/.well-known/est-mtls/<pathID>; serverkeygen ships V2; fullcmc
deferred; renewal device-driven per RFC 7030 §4.2.2; csrattrs
algorithm allow-list profile-derived; libest as e2e reference).
Phase 1 — Multi-profile config + per-profile dispatch
internal/config/config.go: extended ESTConfig with Profiles slice;
added ESTProfileConfig struct with all field contracts (PathID +
IssuerID + ProfileID + EnrollmentPassword + MTLSEnabled +
MTLSClientCATrustBundlePath + ChannelBindingRequired +
AllowedAuthModes + RateLimitPerPrincipal24h + ServerKeygenEnabled).
Forward-looking fields (mTLS, HTTP Basic, channel binding,
rate limit, server-keygen) are dormant in Phase 1 — Phase 2-5 wire
the corresponding handlers; Validate() gates ensure operators can't
set incoherent combinations (MTLSEnabled=true without bundle path,
basic auth without password, mtls auth mode without MTLSEnabled,
ChannelBindingRequired without mTLS, ServerKeygenEnabled without
ProfileID).
loadESTProfilesFromEnv: mirrors loadSCEPProfilesFromEnv exactly.
Reads CERTCTL_EST_PROFILES=corp,iot,wifi and per-profile env vars
CERTCTL_EST_PROFILE_<NAME>_*. Lowercase PathID, uppercase env-var
name. parseAuthModes handles comma-separated normalization.
mergeESTLegacyIntoProfiles: back-compat shim. When CERTCTL_EST_PROFILES
is unset AND CERTCTL_EST_ENABLED=true, synthesizes a single-element
Profiles[0] with PathID="" so existing /.well-known/est/
operators see no behavior change.
validESTPathID + validESTAuthMode: shape validators. PathID matches
[a-z0-9-]+ with no leading/trailing hyphen (mirrors validSCEPPathID
exactly). Auth mode is one of {mtls, basic}.
Per-profile Validate(): refuses every documented misconfiguration
with operator-greppable error messages naming the offending profile
index + PathID + field. Mirrors the SCEP audit-closure pattern.
internal/api/router/router.go: refactored RegisterESTHandlers from
single-handler to map[string]ESTHandler. Empty PathID maps to legacy
/.well-known/est/ root (literal-string r.Register calls preserve
openapi-parity scanner behavior). Non-empty PathIDs dynamic-register
/.well-known/est/<pathID>/{cacerts,simpleenroll,simplereenroll,csrattrs}.
Mirrors the SCEP per-profile dispatch from commit
|