Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Revocation Sources

A signer produces bundles from one revocation source per CA. Since 0.2.0 every source is authenticated: a CRL must carry a signature that verifies under an independently configured issuer certificate, and a directory population is bound to the identity of the directory it came from. A source that cannot be authenticated never becomes a bundle.

SourcetypeProvidesBundle completeness it can support
CRL filecrlrevoked serialspartial only
389 DS syncrepldogtag-syncevery issued certificate with statuspartial or authoritative-complete

CRL sources

[[ca]]
label = "enterprise-ca"

[ca.source]
type        = "crl"
path        = "/var/lib/hoike/crl/enterprise-ca.crl"   # DER or PEM
issuer_cert = "/etc/hoike/trust/enterprise-ca.crt"      # required

issuer_cert is trusted configuration, not a certificate discovered alongside the CRL. Its subject and public key must match the CA identity the bundle is scoped to; a mismatch is a configuration error. The standalone hoike sign command takes the same certificate through --issuer.

Verification profile

CheckBehaviour
SignatureMust verify under issuer_cert. Supported: ECDSA P-256 with SHA-256; RSA PKCS#1 v1.5 with SHA-256/384/512 and 2048–8192-bit keys; ML-DSA-44/65/87. RSA-PSS and P-384 are rejected explicitly.
Issuer bindingCRL issuer name must equal the certificate subject; the authority key identifier, when present, must match.
Validity windowthisUpdate must be in the past and nextUpdate in the future, with a small clock-skew allowance. An expired or future-dated CRL is rejected; the previous bundle stays in service.
Delta and indirect CRLsRejected. hoike only consumes complete, direct CRLs.
Critical extensionsUnknown critical extensions cause rejection rather than being ignored.

Freshness and response validity

The signed response window is derived from the source, never the other way round. validity_secs and batch jitter can shorten a response’s nextUpdate but cannot extend it past the CRL’s own nextUpdate. If a CA publishes short-lived CRLs, batch_interval must be shorter still; hoike check warns when the configured interval cannot keep responses fresh.

Why a CRL is always partial

A CRL enumerates revocations; it says nothing about which serials were ever issued. hoike therefore cannot distinguish “issued and good” from “never issued” and marks CRL-derived bundles completeness = "partial". Unknown serials receive an unknown response, never good. Do not set authoritative-complete on a CRL source; the signer refuses it.

389 DS syncrepl sources

The dogtag-sync source (build with --features dogtag-sync) performs RFC 4533 content synchronization against a Dogtag or Red Hat Certificate System certificate repository in 389 Directory Server. The initial refresh loads the full population; later refreshes send a sync cookie and receive only changes.

[ca.source]
type              = "dogtag-sync"
ldap_url          = "ldaps://ds.pki.example.com:636"
base_dn           = "ou=certificateRepository,ou=ca,o=pki-ca-CA"
bind_dn           = "uid=hoike-reader,ou=people,o=pki-ca-CA"
bind_password_env = "HOIKE_LDAP_PASSWORD"          # prefer over bind_password
filter            = "(objectClass=certificateRecord)"
tls               = "ldaps"                        # see TLS and Mutual TLS
ca_cert           = "/etc/hoike/tls/ds-ca.pem"
cookie_path       = "/var/lib/hoike/state/enterprise-ca.sync"

Grant the bind identity read-only access to the repository subtree. hoike requests only cn, serialno, certStatus, revokedOn, revReason, and notAfter; it does not need the certificate blobs. notAfter supplies each certificate’s expiry, which is what makes archive_cutoff_secs effective on this source.

Status mapping

Directory certStatusBundle entry
VALIDgood
REVOKED, REVOKED_EXPIREDrevoked, with revokedOn as the revocation time and revReason as the reason; a missing or unparsable time or reason fails the refresh
INVALID, EXPIREDexcluded from positive issuance (responders answer unknown)
missing or unrecognisederror — the refresh fails and no bundle is published

A missing or unknown status is never treated as good.

Checkpoints

The population and the sync cookie are checkpointed together, atomically, in a file whose name is derived from cookie_path plus the source identity (endpoint, base, filter, bind identity, transport, CA identity — never the password). On restart the checkpoint restores the population and resumes incremental sync. A cookie that belongs to a different source identity, or a legacy cookie-only file from 0.1.x, is ignored and a full refresh runs. Only the directory’s syncRefreshRequired result triggers a full refresh otherwise.

Operational consequences:

  • Size the signer’s storage and refresh window for a full repository load; it will happen after migration and after any source-identity change.
  • Back up and restore the state directory as one unit; the checkpoint and the anti-rollback marks must stay consistent.
  • Run one signer process per state directory and one active signer per CA. hoike serializes within a process but does not fence competing processes.

Pruning expired entries (archive_cutoff_secs)

Because syncrepl delivers each certificate’s notAfter, a directory-backed CA can bound bundle size by dropping long-expired certificates:

[[ca]]
label               = "enterprise-ca"
archive_cutoff_secs = 2592000   # drop entries expired more than 30 days ago

An entry is pruned only when its notAfter is known and notAfter + archive_cutoff_secs is already in the past. Entries with unknown expiry are never dropped, so a revoked certificate can never silently degrade to unknown. This is why the feature is a no-op for CRL sources (a CRL carries no per-certificate expiry) — hoike check warns if you set archive_cutoff_secs > 0 on a CRL-backed CA. The default 0 disables pruning.

authoritative-complete

Because syncrepl delivers positive issuance data, a directory-backed CA may set:

[[ca]]
label        = "enterprise-ca"
completeness = "authoritative-complete"

With this setting a serial that is absent from the population is answered good-less — the responder returns unknown — but the bundle’s manifest asserts that the population is complete, which downstream tooling can use to treat unknown as “not issued”. The assertion is only made when a refresh succeeds; a failed or partial refresh keeps the previous generation and its completeness claim. Set it only when the bind identity’s scope, base DN, and filter demonstrably cover every certificate the CA issues.

Migration from 0.1.x

ChangeAction
issuer_cert is mandatory for CRL sourcesAdd it, or the signer refuses to start
Cookie-only sync files are ignoredExpect one full directory refresh after upgrade
partial is now the default completenessExplicitly set authoritative-complete where it was previously implied
Delta and indirect CRLs no longer acceptedPoint path at the complete CRL