shankar0123
5834e5b866
fix(est): plumb context through ESTService.ReloadTrust to satisfy contextcheck
...
CI golangci-lint v2.11.4 flagged internal/api/handler/admin_est.go:178:
the AdminESTServiceImpl.ReloadTrust method took ctx context.Context but
called svc.ReloadTrust() with no context, then the underlying
ESTService.ReloadTrust used context.Background() internally for the
audit RecordEvent call. That's the contextcheck linter's textbook
'context discarded at boundary' violation.
Fix: change ESTService.ReloadTrust signature to ReloadTrust(ctx
context.Context) and forward the caller-supplied ctx into
auditService.RecordEvent. AdminESTServiceImpl.ReloadTrust now passes
its received ctx through. The HTTP handler already forwards
r.Context() one layer up, so the request-scoped trace identifiers now
flow end-to-end into the audit row instead of being severed at the
service boundary.
Verified locally with golangci-lint v2.11.4 (the same version CI runs)
against ./internal/api/handler/... ./internal/service/... — '0
issues.' All cmd/* binaries build clean, go test -short -count=1
green for both packages.
2026-04-30 01:59:04 +00:00
shankar0123
43075a1b5c
EST RFC 7030 hardening master bundle Phases 5-7: end-to-end serverkeygen
...
+ profile-driven csrattrs + admin observability with per-status
counters + reload-trust endpoint.
Phase 5 — RFC 7030 §4.4 server-driven key generation:
- internal/pkcs7/envelopeddata_builder.go is the inverse of the
existing parser/decryptor: AES-256-CBC content cipher + RSA PKCS#1
v1.5 keyTrans + per-call random IV. Round-trip pinned in test
(BuildEnvelopedData → ParseEnvelopedData → Decrypt returns the
original plaintext byte-for-byte).
- ESTService.SimpleServerKeygen runs the full §4.4 flow: parse client
CSR → require RSA pubkey for keyTrans → resolve per-profile
algorithm (RSA-2048 default; honors AllowedKeyAlgorithms) → in-
memory keygen → re-build CSR with server pubkey → run existing
issuer pipeline → marshal PKCS#8 → CMS-EnvelopedData wrap to a
synthetic recipient cert wrapping the device's CSR-supplied pubkey
→ zeroize plaintext + PKCS#8 bytes → return CertPEM + ChainPEM
+ EncryptedKey. Typed sentinels ErrServerKeygenRequiresKey-
Encipherment / ErrServerKeygenUnsupportedAlgorithm /
ErrServerKeygenDisabled.
- ESTHandler.ServerKeygen + ServerKeygenMTLS emit RFC 7030 §4.4.2
multipart/mixed with random per-response boundary; per-profile
SetServerKeygenEnabled gate returns 404 when off (defense in depth
even if the route was registered).
- New routes POST /.well-known/est/[<PathID>/]serverkeygen +
/.well-known/est-mtls/<PathID>/serverkeygen; openapi.yaml +
openapi-parity guard updated.
Phase 6 — Real csrattrs implementation:
- New CertificateProfile.RequiredCSRAttributes []string + migration
000022_certificate_profiles_csrattrs.up.sql. The migration also
lands the previously-unwired must_staple column (closes the 5.6
follow-up loop where the field shipped at the domain + service
layer but the postgres scan/insert/update never persisted it).
- domain.EKUStringToOID + AttributeStringToOID lookup tables: id-kp-*
EKUs (RFC 5280 §4.2.1.12) + RFC 5280 DN attributes + RFC 2985
PKCS#10 attributes + Microsoft Intune device-serial OID.
- ESTService.GetCSRAttrs replaces the v2.0.x nil/204 stub with a
profile-derived SEQUENCE OF OID ASN.1 marshal. Unknown EKU /
attribute strings dropped + warning-logged so a typo doesn't take
down the entire endpoint.
Phase 7 — Admin observability + counters + reload-trust:
- internal/service/est_counters.go: estCounterTab (sync/atomic; 12
named labels) + ESTStatsSnapshot per-profile shape +
ESTService.Stats(now) zero-allocation accessor + ReloadTrust()
SIGHUP-equivalent + SetESTAdminMetadata setter.
- Counter ticks wired into processEnrollment + SimpleServerKeygen at
every success/failure leg.
- internal/api/handler/admin_est.go mirrors AdminSCEPIntune verbatim:
Profiles + ReloadTrust handlers + AdminESTServiceImpl. Both
endpoints admin-gated (M-008 triplet pinned + admin_est.go added
to AdminGatedHandlers).
- New routes GET /api/v1/admin/est/profiles + POST /api/v1/admin/
est/reload-trust; openapi.yaml documented; openapi-parity guard
reproduced clean.
- cmd/server/main.go grows estServices map populated by the per-
profile EST loop + handed to AdminEST. New MTLSTrust() +
HasMTLSTrust() accessors on ESTHandler so main.go can pull the
trust holder for the admin-metadata wire-up.
- Per-profile counter isolation regression test
(internal/service/est_profile_counter_isolation_test.go) proves
a future shared-counter refactor would fail at compile-time
pointer-identity check.
Pre-commit verification (sandbox): gofmt clean, go vet clean
(excluding repository/postgres which the sandbox can't build —
disk-space testcontainers download), staticcheck clean across
cms/trustanchor/api/handler/api/router/scep/intune/ratelimit/
service/pkcs7/domain/cmd/server, go test -short -count=1 green
for every non-postgres package. G-3 docs-drift guard reproduced
locally clean (Phases 5-7 added zero new env vars; Phase 1
already documented per-profile SERVER_KEYGEN_ENABLED).
Spec preserved at cowork/est-rfc7030-hardening-prompt.md. Phases
8-13 (GUI ESTAdminPage / CLI+MCP / libest e2e / bulk revocation /
docs/est.md / release prep) remain — post-2.1.0 work.
2026-04-29 23:57:45 +00:00