Skip to content

ECA-15056: Database Maintenance Worker: Add cert-deletion-mode radio (Delete-Expired / Delete-Revoked / None) + ARCHIVED-status fix#1054

Open
John-D-B wants to merge 1 commit into
Keyfactor:mainfrom
John-D-B:fix-27-dbms-worker-revoked-reaper
Open

ECA-15056: Database Maintenance Worker: Add cert-deletion-mode radio (Delete-Expired / Delete-Revoked / None) + ARCHIVED-status fix#1054
John-D-B wants to merge 1 commit into
Keyfactor:mainfrom
John-D-B:fix-27-dbms-worker-revoked-reaper

Conversation

@John-D-B

@John-D-B John-D-B commented Jun 23, 2026

Copy link
Copy Markdown

Pull Request: Fix 27: DBMS Reaper for Revoked Certificates

Target title:

ECA-15056: Database Maintenance Worker:

    Add cert-deletion-mode radio (Delete-Expired / Delete-Revoked / None) + ARCHIVED-status fix

Author: JohnB, with AI pair-programming support by Anthropic Claude Code (Opus, 1M-context)

Target branch: main

Source branch: fix-27-dbms-worker-revoked-reaper


FYI: Customer EE feature request, accepted by Keyfactor engineering

  • EE support ticket #172467:

    https://support.keyfactor.com/hc/en-us/requests/172467

    "Need a mechanism to 'reap' (delete) revoked certificates from K8s certmanager churn."

    Marked solved by Keyfactor support after engineering accepted the request.

  • Engineering reference: ECA-15056

    (assigned 25 May 2026, tracked via Customer Success Manager).

  • Why this PR exists:

    The customer, having had the request accepted as an engineering task,

        is offering a working implementation rather than waiting in the EE backlog queue.

    Submitted into CE because that's the public contribution surface; the vendor's CE→EE propagation flow takes it from there.

  • Two PRs total: (from ELT fix-it list)

    https://github.com/John-D-B/Claudes/blob/main/2026-06-01.EJBCA-tools/elt/insights/CLAUDE-ejbca-fix-requests.md

    — Fix 27: the DBMS Worker option (this one)

    — Fix 26: REST DELETE endpoint


Summary

Restructure the Database Maintenance Worker's cert-side cleanup around

    a radio-button selection of three mutually-exclusive deletion modes.

This matches the three lifecycle buckets that cert-manager-style churn produces,

    and that operators reason about directly:

  • MODE_EXPIRED (default operational mode):

    Reaps any certificate past
    its notAfter regardless of revocation status. JPQL:

    expireDate < now − delayAfterExpiration.

    Catches the E (naturally expired) and R (revoked-and-expired) lifecycle buckets.

  • MODE_REVOKED (cleanup mode for accumulated revoked-by-reason zombies):

    Reaps any certificate whose revocationReason is in the
    operator-selected set, regardless of expiry. JPQL:

    status IN (REVOKED, ARCHIVED) AND revocationReason IN :reasons AND revocationDate < now − delayAfterRevocation

    Catches the r (revoked-but-not-yet-expired) and

        R (revoked-and-expired, including the archived status=60 substate) lifecycle buckets.

  • MODE_NONE (safety default for fresh workers):

    No certificate deletion; only the independent CRL-side reaper runs if its checkbox is ticked.

  • FYI: ELT status codes

$ ejbca-lifecycle-tool.py --help | less
  ...
  status codes (cert table 'S' column and count-line breakdown):
    A   active                  — certificate is not revoked, not expired
    E   expired (not revoked)   — cert is past notAfter, never revoked
    R   revoked + expired       — cert is revoked AND past notAfter (prunable from CRL)
    r   revoked + unexpired     — cert is revoked, still within validity (CRL must carry)
    ?   unknown                 — status doesn't map to the four above

  Count-line example (list -d4):
    Certificates:  35:  1:A active,  7:E expired,  20:R revoked+expired,  7:r revoked+unexpired

The widened status IN (REVOKED, ARCHIVED) filter in MODE_REVOKED is
the critical design fix vs the original status = REVOKED formulation:
EJBCA's post-expiry housekeeping transitions revoked-and-expired rows
from status=40 to status=60 (ARCHIVED) over time, and the original
filter silently excluded them — leaving operators with a real
accumulation of unsweepable rows on long-running stacks.

The CRL-side sweep (Match expired CRLs) remains a separate, independent
sweep over CRLData — orthogonal to the cert-deletion mode radio.

The cert-deletion mode didn't exist as a configurable option in CE
before this PR. Pre-PR, the admin-GUI form, the Type bean, and the
constants were present for the older deleteExpiredCertificates
checkbox, but no worker class implemented them, so configuring the
worker raised ClassNotFoundException at runtime. This PR ships the
first working DatabaseMaintenanceWorker.java in CE history and
restructures the existing GUI around the radio-mode design.

Layout of the refactored admin-GUI form:

    https://github.com/John-D-B/Claudes/blob/main/2026-06-01.EJBCA-tools/ejbca-ce/Docs/fix27-gui-mockup.png

Backward compatibility for pre-radio configurations (EE installs with
deleteExpiredCertificates=true in their property bag) is preserved
via a legacy-fallback in the bean: if certDeletionMode is absent, the
mode is derived from the legacy booleans (deleteExpiredCertificates=true
→ MODE_EXPIRED; deleteRevokedCertificates=true → MODE_REVOKED). Going
forward, certDeletionMode is the source of truth.

This is the foundation PR for ticket #172467 / engineering reference
ECA-15056 (already accepted by Keyfactor engineering 25 May 2026, per
the ticket "solved" / "tracked through engineering" status). A
follow-up PR (Fix 26) builds an on-demand REST equivalent
(DELETE /v1/certificate/{issuer_dn}/{serial}) on top of the EJB
primitive added here. The two PRs together fulfil the (a) and (b) parts
of the original ticket request.

External references

The "Fix-26" and "Fix-27" terms come from earlier work with JohnB's EJBCA Lifecycle Tool (ELT):

A user-visible demonstration of PKI workflow for this pull request is in JohnB's repository:

A PowerPoint overview is here:

The worker could delete expired certificates but had no path to bulk-delete
revoked-but-unexpired ones. Under a single-active-certificate constraint,
cert-manager-style renewals revoke each predecessor (SUPERSEDED) without
expiring it, so revoked rows accumulate with no scheduled cleanup.

Adds a mutually-exclusive cert-deletion mode (NONE / EXPIRED / REVOKED) with a
revocation-reason filter and an independent revoke-delay, plus
CertificateStoreSession primitives that delete by an AND-composition of
criteria. Existing deleteExpiredCertificates configs migrate to the new mode
for backward compatibility. Admin-GUI service form refactored to radio buttons.

Ref: ECA-15056 (Keyfactor support #172467)
@John-D-B John-D-B changed the title Database Maintenance Worker: add revoked-certificate deletion mode ECA-15056: Database Maintenance Worker: Add cert-deletion-mode radio (Delete-Expired / Delete-Revoked / None) + ARCHIVED-status fix Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants