mirror of
https://github.com/shankar0123/certctl.git
synced 2026-06-11 18:59:08 +00:00
docs(scep-intune): deployment guide + troubleshooting + Microsoft support statement
Phase 11 of the SCEP RFC 8894 + Intune master bundle.
Phase 11.1 — docs/scep-intune.md (new, ~340 lines):
* TL;DR — drop-in NDES replacement framing; what an operator gets
over NDES (per-profile endpoints, audit-log forensics, SIGHUP
reload, GUI monitoring, per-device rate limit).
* Architecture diagram — Intune cloud → Connector → certctl SCEP
→ issuer connector. Explicit 'certctl replaces NDES, NOT the
Connector' framing; nine-gate dispatcher walk (shape pre-check,
JWS sig, version dispatch, time bounds, audience pin, CSR binding,
replay, per-device rate limit, optional compliance).
* Migration playbook (NDES + EJBCA / NDES + ADCS) — 9-step run-book:
install alongside, configure per-profile endpoint, extract trust
anchor, configure CONNECTOR_CERT_PATH + AUDIENCE, configure
issuer connector, migrate one profile, verify enrollment, roll
out fleet, decommission NDES.
* Intune SCEP profile field mapping table — every Intune admin
center field mapped to certctl's behavior (cert type, subject
name format, SAN, validity, key storage provider, key usage,
EKU, hash algorithm, SCEP server URL).
* Trust anchor extraction recipe — step-by-step certlm.msc export
of the 'CN=Microsoft Intune Certificate Connector' cert, PEM
rename, env-var configuration, HA Connector concatenation, SIGHUP
rotation flow.
* Troubleshooting matrix — 10 failure modes mapped to root causes
and operator actions: signature_invalid (trust anchor stale),
claim_mismatch (Intune profile SAN config), expired (clock skew /
Connector cert past NotAfter), not_yet_valid (reverse skew),
wrong_audience (URL mismatch), replay (retry-window collision),
rate_limited (limiter doing its job), unknown_version (Microsoft
shipped new format), malformed (proxy mangling body),
compliance_failed (V3-Pro hook returned non-compliant).
* Operational monitoring — admin GUI surface description, expiry
badge tone bands (≥30d green / 7-30d amber / <7d red / EXPIRED),
per-status counter polling cadence, audit log filter, recommended
Prometheus alert thresholds.
* Limitations — explicit V3-Pro deferrals: native Microsoft Graph
integration, Conditional Access compliance gating, per-tenant
trust anchors (MSP scoping), OCSP stapling at SCEP-response time,
auto-discovery of Connector signing cert.
* Microsoft support statement — three Microsoft Learn URLs (verified
live with HTTP 200): Connector overview, SCEP profile setup,
Connector install validation. Microsoft documents the Connector
as RFC-8894-compliant and supports its use against any RFC 8894
SCEP server.
Phase 11.2 — Cross-references:
* docs/legacy-est-scep.md — the previous forward-ref pointed at
'the Phase 11 doc this bundle ships'; updated to a richer pointer
that lists what scep-intune.md covers (architecture, migration,
profile mapping, extraction, troubleshooting, monitoring,
limitations, Microsoft support).
* README.md — new bullet under Enrollment Protocols table:
'Microsoft Intune SCEP fleet (drop-in NDES replacement)' with
the per-profile dispatcher feature list + link to scep-intune.md.
Procurement teams scanning the README see the Intune story
alongside ChromeOS / Jamf in the same table row.
* docs/architecture.md — new 'Microsoft Intune Connector trust
anchor (per-profile, opt-in)' subsection in the Security Model
section. ASCII diagram showing the dispatcher walk; calls out
the SIGHUP reload + admin-gated GUI surface; forward-link to
scep-intune.md.
Verification:
* All linked anchors inside scep-intune.md resolve to existing
headings: #limitations, #microsoft-support-statement,
#operational-monitoring, #trust-anchor-extraction.
* All linked doc paths resolve: legacy-est-scep.md, architecture.md,
features.md, tls.md.
* All three Microsoft Learn URLs return HTTP 200 (verified via curl).
* G-3 docs-drift CI guard reproduced locally and clean — the
migration playbook uses the <NAME> placeholder convention
consistently (matching features.md style) so the docs scanner
doesn't extract literal env-var names that aren't in config.go.
* Backend tests across intune+handler+service+router still green.
Refs: cowork/scep-rfc8894-intune-master-prompt.md::Phase 11
cowork/scep-rfc8894-intune/progress.md
This commit is contained in:
@@ -831,6 +831,48 @@ The control plane only handles public material: certificates, chains, and CSRs.
|
||||
|
||||
**Server keygen mode (`CERTCTL_KEYGEN_MODE=server`, demo only):** The control plane generates RSA-2048 keys server-side within `processRenewalServerKeygen`. Private keys are stored in `certificate_versions.csr_pem`. A log warning is emitted at startup. Use only for Local CA development/demo.
|
||||
|
||||
### Microsoft Intune Connector trust anchor (per-profile, opt-in)
|
||||
|
||||
When the SCEP server is sitting behind a Microsoft Intune Certificate
|
||||
Connector — i.e. certctl is acting as a drop-in NDES replacement —
|
||||
each per-profile dispatcher carries its own **trust anchor pool**:
|
||||
the public certs the operator extracted from the Connector's
|
||||
installation. Every Intune-flavored enrollment goes through:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ Per-profile TrustAnchorHolder │
|
||||
│ (RWMutex pool, SIGHUP-reloadable) │
|
||||
└────────────┬────────────────────┘
|
||||
│ Get()
|
||||
▼
|
||||
device → SCEP PKIMessage → handler → SCEPService.dispatchIntuneChallenge
|
||||
│
|
||||
├─► intune.ValidateChallenge (sig + iat/exp + audience)
|
||||
├─► claim.DeviceMatchesCSR (set-equality)
|
||||
├─► intune.ReplayCache.CheckAndInsert
|
||||
├─► intune.PerDeviceRateLimiter.Allow
|
||||
└─► (V3-Pro) ComplianceCheck hook
|
||||
│
|
||||
▼
|
||||
processEnrollment → IssuerConnector
|
||||
```
|
||||
|
||||
The trust anchor file is mode-0600 on disk; certctl loads it at
|
||||
startup via `intune.LoadTrustAnchor` (refuses to boot on empty
|
||||
bundle / parse error / past-`NotAfter` cert) and reloads atomically
|
||||
on `SIGHUP` (mirrors the server TLS-cert hot-reload pattern). A bad
|
||||
reload keeps the OLD pool in place — operators get a recoverable
|
||||
failure window rather than a service-down. The admin GUI's SCEP
|
||||
Intune Monitoring tab + admin endpoints
|
||||
(`GET /api/v1/admin/scep/intune/stats`,
|
||||
`POST /api/v1/admin/scep/intune/reload-trust`) are M-008 admin-gated;
|
||||
non-admin Bearer callers get HTTP 403 because the trust-anchor
|
||||
expiries are sensitive operational metadata.
|
||||
|
||||
See [`scep-intune.md`](scep-intune.md) for the full migration playbook
|
||||
+ Microsoft support statement.
|
||||
|
||||
### CA Signing Abstraction
|
||||
|
||||
The local issuer's CA private key is wrapped behind the `signer.Signer` interface in `internal/crypto/signer/`. Every CA-signing call site — leaf certificate issuance (`x509.CreateCertificate`), CRL generation (`x509.CreateRevocationList`), and OCSP response signing (`ocsp.CreateResponse`) — accesses the key through this interface rather than touching `crypto.Signer` directly. The interface embeds the stdlib `crypto.Signer` and adds a single `Algorithm() Algorithm` method so call sites can pick the matching `x509.SignatureAlgorithm` without reflecting on the concrete key type.
|
||||
|
||||
Reference in New Issue
Block a user