All checks were successful
CI Pipeline / Rust Format Check (push) Successful in 6s
CI Pipeline / Clippy Lints (push) Successful in 52s
CI Pipeline / Rust Unit Tests (push) Successful in 1m10s
CI Pipeline / Security Audit (push) Successful in 1m26s
CI Pipeline / Frontend Lint & Type Check (push) Successful in 15s
CI Pipeline / Build .deb & Release (push) Has been skipped
* feat(pki): add CRL generation, distribution endpoint, and enrollment bundle extension Implements manager-side CRL infrastructure for issue #7: - Add CertAuthority::generate_crl() using rcgen 0.13 - Add GET /api/v1/pki/crl.pem public endpoint - Extend PkiBundle with ca_chain and crl_pem fields - Update enrollment route to include CRL in bundle - Mount pki route as public endpoint - Add proptest dev-dependency * style: fix cargo fmt in enrollment.rs --------- Co-authored-by: Draco Lunaris <331325+Draco-Lunaris@users.noreply.github.com>
3.1 KiB
3.1 KiB
PR 1: Manager-side CRL generation + endpoint + enrollment bundle
Branch: feat/7-crl-manager-side
Target issue: https://github.com/Draco-Lunaris/Linux-Patch-Manager/issues/7
Pre-implementation
- Read existing
pm-ca/src/ca.rsto understand CA structure - Confirm rcgen 0.13 is the chosen library
- Confirm sub-CA handling: extend
PkiBundlewithca_chainfield - Read design doc decisions table (concerns 1-12)
Code changes
-
pm-ca/src/ca.rs: Add
generate_crl(db: &PgPool) -> Result<String>function- Query
certificatesforstatus='revoked' AND not_after > NOW() - Build CRL using rcgen 0.13
CertificateRevocationList - Sign with CA private key
- Return PEM-encoded CRL
- Query
-
pm-core/src/models.rs: Extend
PkiBundlewithca_chain: Stringfield- Concatenated PEM bundle of full chain (intermediate + root) for sub-CA mode
- For root mode, contains just the root cert (same as ca_crt)
-
pm-web/src/routes/pki.rs (NEW):
GET /api/v1/pki/crl.pemroute- Public endpoint (no auth, CRLs are self-authenticating)
Cache-Control: max-age=3600- Returns latest cached CRL (regenerated on schedule or on revoke)
-
pm-web/src/routes/enrollment.rs: Include CRL in enrollment response
- Fetch current CRL via
generate_crl() - Add
crl_pem: Stringto response
- Fetch current CRL via
-
pm-web/src/main.rs: Wire up background CRL regeneration task
- Regenerate every 12 hours
- Hook into
revoke_certto trigger immediate regeneration - Store latest CRL in shared state (ArcSwap or similar)
-
crates/pm-web/src/state.rs (or similar): Shared state for cached CRL
Tests
-
Unit tests in
pm-ca/src/ca.rs:generate_crlproduces valid X.509 CRL signed by test CA- Revoked serials appear in CRL
- Non-revoked serials do not appear
- Expired certs (not_after < now) are excluded
- Empty table produces CRL with zero revoked entries
-
Property tests (proptest):
- Random revoked cert data: CRL is always parseable, signature always verifies
- Single-byte mutations to CRL fail signature verification
-
Fuzz harness (cargo-fuzz):
- Target:
pm_ca::ca::generate_crl - Target:
pm_ca::ca::parse_crl(if we add parsing)
- Target:
-
Integration tests in
pm-web/tests/:GET /pki/crl.pemreturns 200 + valid PEM + correct Cache-Control- Enrollment bundle includes CRL
- Enrollment bundle includes
ca_chainfield
Documentation
- docs/security/revocation.md (NEW): Revocation policy and operational behavior
- docs/api/REST_API.md (or equivalent): Document
GET /pki/crl.pem - Inline doc comments on new public functions/structs
- CHANGELOG.md entry for the release
Pre-PR checklist
cargo buildcleancargo testall passcargo clippy --all-targets --all-features -- -D warningscleancargo fmt --checkclean- CI on GitHub passes
Out of scope for PR 1 (deferred to later PRs)
- Agent-side consumption (PR 2, in linux-patch-api repo)
- Health check schema additions (PR 3)
- Agent health response field (PR 4)
- Health aggregation logic (PR 5)
- E2E test harness (PR 6)