Skip to content

v2.227

Latest

Choose a tag to compare

@github-actions github-actions released this 10 Sep 17:14

What's Changed

Added

  • A CA that holds only its certificate, as one created by signing an external CA request (a Windows sub-CA signed by a UCM root), is flagged as such in the list and its details, and its private key can be imported afterwards (POST /api/v2/cas/<id>/key, key checked against the certificate) so it can sign; taking it offline is refused until then (#348, reported by @j2r2k2)

Fixed

  • CA revocation, reviewed after v2.226: a CA under a revoked ancestor is shown as revoked upstream, with signing actions withheld, and the pickers that name a signing CA (issue form, CSR signing, sub-CA parent, ACME, SCEP, EST, XCEP/WSTEP, TSA, policies) offer only CAs that can sign, the corresponding settings refusing any other; certificateHold is refused for a CA, since a CA revocation is permanent; a revoked CA is not taken offline; a CA whose row lost its revoked flag (older backup, import before its parent) still reads as revoked from the parent's record, a second revocation keeps the original date, and the parent's CRL lists a revoked child CA even without that record; a CA under a revoked ancestor can still install a certificate from a healthy issuer or renew its request; the SCEP dashboard tile follows the chain; the status badge is translated and a Revoked counter appears on the CA page; the certificate list stays on an existing page after the last row of the last page goes away and ignores a reload that a later filter change overtook; revocation warnings are translated (follow-up to #343)
  • Delegated OCSP responders now sign the responses. No issuance path emitted id-pkix-ocsp-nocheck, so the configured responder was refused at answer time and the CA signed with its own identity; every path now emits it, renewals included (#347, reported by @j2r2k2)
  • One rule for a delegated responder, shared by assignment, the eligibility list and the responder: issued and signed by the CA, valid, not revoked, OCSPSigning EKU, Key Usage with digitalSignature, nocheck, and a readable private key that is the certificate's own. A refusal names the reason, also in the responder settings (#347)
  • Responder changes take effect at once: assigning, removing, revoking, renewing or deleting a responder drops the CA's cached answers, and an answer never claims to be current beyond the responder's own expiry (#347)
  • Responders with Ed25519, Ed448 or DSA keys sign on both response paths; Ed25519 and Ed448 keys can be imported or uploaded (stored as PKCS#8); an Ed25519 or Ed448 certificate keeps its key type when renewed (#347)
  • Imports refuse a private key that is not the certificate's. Re-importing an existing certificate or CA without a key drops a stored key that is not the new certificate's and says so; an unreadable stored key, or an HSM key that cannot be reached, refuses the update and leaves the record untouched (#347)
  • Re-import targets the right record among homonyms: the one holding the certificate's key, told apart by the issuer's key identifier or signature when a CA is cross-signed; a certificate that matches none of several homonyms is refused. A CA waiting for its certificate, or holding a renewal request, is completed through the certificate upload path (#347)
  • A renewed certificate imported onto a revoked record is no longer published as revoked: the revoked serial stays on the list and the record follows its new certificate. Both import routes now keep a CA's serial, subject key identifier, issuing CA and path length in step with the certificate, and apply a revocation the parent still holds (#347)
  • A CA certificate answering an intermediate request pending in the certificate list is created with that request's key; a foreign CA that merely shares the subject of a pending CA becomes a new CA. CAs with Ed25519 or Ed448 keys are refused at import with the reason, since they could sign neither certificates nor CRLs (#347)
  • Signatures made with HSM-resident RSA-3072, RSA-4096, P-384 and P-521 keys verify again: the providers hashed with a digest chosen from the key size while the signature named SHA-256. The signature now names the digest the provider signs with, on every signing path (certificates, CRLs, OCSP, timestamps) (#347)
  • An HSM-backed CA without a delegated responder answered every single-certificate OCSP request with an internal error; a sub-CA whose record no longer points at its real issuer is still found by signature, so its OCSP status is good rather than unknown; a serial lookup is verified against the stored certificate, the serial column mixing decimal and hexadecimal forms (#347)
  • A request issued through the approval workflow yields the same certificate as the same request issued directly, extra extended key usages included, and the approval is linked to the certificate it produced (#347)
  • Backups: restoring a backup written before the CA revocation fields existed no longer un-revokes a CA; a CA's offline state, validity dates, origin and CRL, OCSP, AIA and CPS settings are restored; a certificate's invalidity date is exported and restored; a revocation record for an unknown CA is skipped instead of aborting the restore on PostgreSQL; a wrong restore password is reported as such (#347)
  • A backup no longer loses revocations: CA revocation state and the persistent revocation list are exported and restored, and a restore reports how many records it brought back (follow-up to #343)
  • Restoring a backup that contains a CA still awaiting its externally signed certificate no longer aborts the whole restore; its pending request travels with the backup (follow-up to #343)
  • Revoking a CA publishes the certificate it currently holds, under the CA that really signed it, after a renewal or a cross-signature as well; DSA-signed CAs, self-issued sub-CAs and looping or over-deep chains no longer bypass the signing block on a revoked chain (follow-up to #343)
  • The certificate list, its counters, the dashboard and the Prometheus metrics count the same records: a pending request is not a certificate, a record with an empty certificate or request is read the same way everywhere, a certificate without validity dates counts as valid, and the Orphan filter is computed by the server over every certificate (follow-up to #345)
  • The certificate list filters form the same buckets as the counters, valid, expiring, expired and revoked never overlapping, and the list shows what the server selected (follow-up to #345)
  • An on-demand backup password is refused with the exact reason, the dialog applies the same rule (at least 12 characters, 8 distinct, 6 distinct from 16) and counts characters the way the server does; the same rule applies to the settings backup route and the scheduled backup password, and a failed scheduled backup is recorded in the audit trail (#346, reported by @kiar1404-de)

Security

  • Private keys created by the certificate issue form and by the Smart Import are now encrypted at rest like every other path; the HSM public key lookup no longer commits the caller's transaction (#347)

📜 Recent release history (last 2 versions)

[2.226] - 2026-09-09

Added

  • Intermediate CA revocation: Revoke CA on an intermediate (POST /api/v2/cas/<id>/revoke, write:cas) with the RFC 5280 reasons and optional invalidity date. The serial goes on the parent's persistent revocation list, the parent's CRL is regenerated and its OCSP responder answers revoked. The revoked CA and everything below it can no longer sign (issue form, CSRs, renewals, sub-CAs, ACME, EST, SCEP, WSTEP, TSA, OCSP responders); its own CRL keeps being served. The record belongs to the parent and outlives the CA row, so a deleted and re-imported CA comes back revoked. Roots and CAs with an external issuer are not revocable here. When the parent cannot regenerate its CRL, the response says so. New Revoked status and filter, audit action ca_revoked (#343, reported by @j2r2k2)

Fixed

  • An active filter survives an action performed from a certificate's detail window, on the certificates and SSH certificates pages; the Orphan filter works on the first load (#345, reported by @kiar1404-de)
  • The OCSP responder answered unknown for the certificate of an intermediate CA: it now recognises the certificates of the CAs signed by the requested issuer and answers good or revoked (#344, reported by @j2r2k2)

[2.225] - 2026-09-09

Added

  • A CSR generated in UCM can be completed by a certificate issued elsewhere. The workflow for a public or third-party CA (generate the CSR in UCM, download it, have it signed, import the certificate) ended with a certificate record that had no private key: the import matched existing records on subject and issuer, which a CSR record never has, so the certificate was stored as a separate keyless entry and could not be exported with its key. The import (Certificates page and Smart Import) now recognises a certificate whose public key is that of a pending CSR, completes that CSR record and keeps its private key, so the certificate exports with the key like any other; the match is made on the key pair, so it holds when the CA rewrites the subject. A key that arrives alongside the certificate is attached when the CSR was uploaded without one. The CSR page also gained Download Private Key on a pending CSR that holds its key (GET /api/v2/csrs/<id>/export?format=key, or POST with a password for encrypted PKCS#8), gated like every direct key export by the admin-only read:private_keys permission and recorded in the audit log (#341, reported by @kiar1404-de)

Fixed

  • A certificate issued from a CSR generated in UCM no longer appears as "CSR for " in the certificates list. The generator described the request that way and signing kept the description, which the list shows as the certificate's name. A generated CSR is now described by its CN, and signing or completing a CSR created before this release drops the old prefix (#342, reported by @kiar1404-de)

Full history: CHANGELOG.md


Installation

Docker (Recommended)

# From Docker Hub
docker pull neyslim/ultimate-ca-manager:2.227

# Or from GitHub Container Registry
docker pull ghcr.io/neyslim/ultimate-ca-manager:2.227

# Run
docker run -d -p 8443:8443 \
  -e SECRET_KEY=$(openssl rand -hex 32) \
  --name ucm neyslim/ultimate-ca-manager:2.227

Debian/Ubuntu

wget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.227/ucm_2.227_all.deb
sudo dpkg -i ucm_2.227_all.deb
sudo apt-get install -f

Fedora/RHEL

wget https://github.com/NeySlim/ultimate-ca-manager/releases/download/v2.227/ucm-2.227-1.fc43.noarch.rpm
sudo dnf install ./ucm-2.227-1.fc43.noarch.rpm

Silent/Automated Install

# Skip firewall prompts for CI/automation
sudo UCM_PORT=8443 UCM_FIREWALL=no dpkg -i ucm_2.227_all.deb

Default Credentials

  • Username: admin
  • Password: changeme123

Change the password immediately after first login!

Documentation