Skip to content

ACME server

PKIFactor includes an ACME server (RFC 8555). Your web servers, load balancers and Kubernetes clusters use a standard ACME client to obtain and renew their certificates from your own certificate authorities (Microsoft AD CS, EJBCA, Vault, ZetaCA and the others declared in PKIFactor), under the policy of a PKIFactor certificate profile.

Each certificate profile with ACME enabled publishes its own directory:

https://acme.example.com/acme/<acme_path>/directory

The profile decides everything the ACME client cannot: the issuing CA, the allowed key algorithms and names, the challenges, and whether an external account binding (EAB) key is required. Every certificate issued through ACME lands in the PKIFactor inventory and audit trail.

This page is for administrators. Client-side commands (certbot, win-acme, acme.sh, cert-manager) are in ACME clients.

Two ACME roles

This page covers PKIFactor as an ACME server: your servers come to it. PKIFactor can also act as an ACME client towards a public CA (Let's Encrypt, Sectigo, others) to obtain public certificates; that is a CA connector, described in Certificate authorities. The two share no account, key or directory.

Tested

Tested in the laboratory:

  • the RFC 8555 protocol core (account, order, authorization, challenge, finalization, download), external account binding, CAA checking, renewal information (ARI, RFC 9773), account key change and the TLS-ALPN-01 challenge;
  • cert-manager (Kubernetes) with an EAB key, against a PKIFactor profile;
  • the Kemp LoadMaster ACME client with a one-time EAB key, issuing from Microsoft AD CS: registration, refusal of a name outside the key's scope, issuance, then automatic renewal with no intervention; the renewal was linked to the certificate it replaced (see Kemp LoadMaster);
  • a directory request on an unknown ACME path returns 404.

Not tested: certbot, win-acme and acme.sh against PKIFactor (the commands in ACME clients are standard client usage); pre-authorization (newAuthz) and IP address identifiers, which are present in the code but were not exercised in the laboratory.

How it works

Step Who What happens
1 ACME client Reads the profile's directory, creates an account (with an EAB key if the profile requires one)
2 ACME client Places an order for one or more DNS names
3 PKIFactor Checks the names against the account's scope, then the CAA records of each name
4 ACME client Answers the challenge (HTTP-01, DNS-01 or TLS-ALPN-01), PKIFactor validates it
5 ACME client Sends its CSR; the names in the CSR must be exactly the validated names
6 PKIFactor Applies the profile and the issuance policies, has the CA sign the CSR, records the certificate
7 ACME client Downloads the certificate and its chain, installs it, and comes back before expiry

The private key is generated by the client and never reaches PKIFactor. Renewal is always started by the client: PKIFactor never pushes a certificate to an ACME client.

Approval: the validated challenge replaces manual approval. A profile with ACME enabled cannot require approval (see Approval and issuance policies).

Before you start

Item What to do
Public ACME host name The name clients use, for example acme.example.com. It is the ACME service's PUBLIC_ACME_URL (set by the appliance setup wizard, or in the .env file with Docker Compose). The directory and every URL returned to clients are built from it
TLS certificate of the ACME host Clients refuse a directory whose certificate is expired, does not carry the ACME name, or comes from a CA they do not trust. It is managed in Infrastructure > Service certificates (see Service certificates). If it comes from a private CA, every client must trust that CA
Network for HTTP-01 PKIFactor connects to each server on port 80. Private addresses are refused unless their network is declared (see Validating servers on private addresses)
Network for TLS-ALPN-01 PKIFactor connects to each server on port 443, with the same address rules as HTTP-01
DNS for DNS-01 PKIFactor reads the _acme-challenge TXT record through public DNS resolvers by default. For names that exist only in an internal DNS, see DNS-01 and internal zones
A certificate profile Linked to the issuing CA, with the key algorithms your clients generate (see Certificate profiles)

ACME is included with every license.

Enable ACME on a certificate profile

  1. Open Infrastructure > Certificate Profiles, then New Profile, or open an existing profile and click Edit Profile.
  2. Expand Automatic enrollment (ACME, EST, CMP, SCEP), then in ACME Protocol check Enable ACME for this profile.
  3. Under Challenge Types, check at least one of HTTP-01, DNS-01, TLS-ALPN-01.
  4. Check Require External Account Binding (EAB) unless the directory is meant to be open to anyone who can reach it.
  5. Save.

Enabling ACME unchecks and locks Require validation before issuance in the approval section.

The profile page then shows, in its ACME card, the challenges, the ACME Path, the Directory URL and the Enroll a server (ACME kit) button.

Field Values Notes
Enable ACME for this profile On / off Publishes the directory /acme/<acme_path>/directory
HTTP-01 On / off PKIFactor fetches http://<name>/.well-known/acme-challenge/<token> on port 80
DNS-01 On / off PKIFactor reads the TXT record _acme-challenge.<name>. The only challenge allowed for a wildcard name
TLS-ALPN-01 On / off PKIFactor opens TLS on port 443 with the ALPN protocol acme-tls/1 and checks the challenge certificate (RFC 8737)
Require External Account Binding (EAB) On / off Account creation requires a valid EAB key; the directory announces externalAccountRequired: true
ACME Path Generated Not entered: PKIFactor derives it from the profile name when ACME is first enabled (lower case, other characters replaced by -, a numeric suffix such as -2 if the path is taken). It then stays the same when the profile is renamed

Disabling ACME clears the path

Unchecking Enable ACME for this profile clears the path, the challenges and the EAB requirement. Clients then receive 404 on the directory. If you enable ACME again, a new path is generated from the current profile name: it may differ from the old one, and EAB keys limited to the old path no longer work.

Saving is refused if ACME is enabled without any challenge (ACME enabled requires at least one challenge (http-01, dns-01 or tls-alpn-01)) or together with manual approval (ACME enabled is incompatible with manual approval (challenge replaces human validation)); the interface prevents both.

Choosing the challenges

Challenge Proves Use it when Does not work for
HTTP-01 Control of the web server answering on port 80 for the name Web servers PKIFactor can reach on port 80 Wildcards; servers PKIFactor cannot reach
DNS-01 Control of the DNS zone Wildcards, internal names, servers PKIFactor cannot reach Clients without access to a DNS API (unless you add the record by hand)
TLS-ALPN-01 Control of the TLS service on port 443 Servers that expose only 443, with a client that supports it Wildcards; most common clients (certbot and cert-manager do not offer it)

A challenge type that is not enabled on the profile is refused, even if the client asks for it. For a wildcard name PKIFactor offers DNS-01 only.

External account binding (EAB)

Without EAB, anyone who reaches a directory can create an account and order certificates for any name they can validate. An EAB key ties account creation to a secret that an administrator hands out: a key identifier (kid) and an HMAC key.

Create an EAB key

  1. Open Infrastructure > External accounts (EAB) and click New EAB key.
  2. Fill in the dialog:

    Field Notes
    Description Required. Say who the key is for (server, team, ticket)
    Profile All profiles (global), or one ACME profile: the key then opens an account only on that profile's directory
    Scope Names the bound account may request, one per line: www.example.com, example.com, *.example.com, 192.0.2.10, 192.0.2.0/24. Empty: Unrestricted
    Single-use (1 EAB = 1 account) Checked by default: the key is consumed by the first account it binds
  3. Click New EAB key. The EAB key created dialog shows the Key ID (kid) and the HMAC key. Copy the HMAC key now: it is never shown again.

Give the client both values (--eab-kid and --eab-hmac-key for certbot and acme.sh, see ACME clients).

The Enroll a server (ACME kit) button on a profile can also create the key: it is then limited to that profile, single-use and unrestricted in scope.

How the scope is matched

Scope entry Allows
example.com example.com and every name below it (www.example.com, a.b.example.com)
*.example.com The same: example.com and every name below it
www.example.com www.example.com and names below it
192.0.2.10 That address only
192.0.2.0/24 Any address in the range

A wildcard order (*.example.com) is checked on its base name (example.com). Every name of an order must be in the scope, otherwise the order is refused with identifier '<name>' is outside this account's authorized scope.

One key, one account, one profile

  • The EAB key is checked only when the account is created. The account then keeps the profile and the scope it got from the key.
  • An account belongs to the profile on whose directory it was created. Using it on another profile's directory is refused (ACME account is registered on another ACME profile; use a distinct account key for this profile): use a separate account key per profile.
  • A single-use key accepts the same account key again (a client that registers twice), but refuses any other account key (EAB already used (single-use credential)).
  • The scope of a bound account cannot be edited. To change it, create a new key with the new scope and register a new account with it (a new account key on the client).

Key states

State Meaning
Active Can bind an account
Consumed Single-use key already used by an account
Disabled Refused for any new account (unknown or disabled EAB key); Enable reverses it

Disabling a key does not cut off its account

Disable only stops new accounts from being created with the key. An account already created with it keeps working, because the key is not checked again. PKIFactor offers no action to disable an ACME account; to stop a server, revoke its certificate and remove the client configuration on the server.

Via the API

curl -s -c jar -X POST https://clm.example.com/api/auth/login \
  --data-urlencode "email=admin@example.com" --data-urlencode "password=$PKF_PASSWORD"

# Create a single-use key, limited to one profile and to two names
curl -s -b jar -X POST https://clm.example.com/api/v1/admin/acme-eab \
  -H "Content-Type: application/json" \
  -d '{"description": "web01 (ticket CHG-1234)", "acme_path": "srv-web",
       "single_use": true, "allowed_identifiers": ["web01.example.com", "www.example.com"]}'
# -> {"key_id": "...", "hmac_key": "...", "id": 7, ...}   (hmac_key is returned only here)

# List keys (never the HMAC key), with the ACME profiles
curl -s -b jar https://clm.example.com/api/v1/admin/acme-eab

# Disable / enable a key
curl -s -b jar -X POST https://clm.example.com/api/v1/admin/acme-eab/<key_id>/disable
curl -s -b jar -X POST https://clm.example.com/api/v1/admin/acme-eab/<key_id>/enable
An unknown or inactive profile path is refused with Profil ACME inconnu ou inactif : <path> (backend messages are in French in this version).

The enrollment kit

On a profile with ACME enabled, Enroll a server (ACME kit) opens the ACME enrollment kit dialog. It produces the commands for one server, with the profile's directory URL already filled in:

Field Notes
Platform nginx (certbot), Apache httpd (certbot), HAProxy (acme.sh), IIS / Windows (win-acme), Other Linux server (acme.sh)
Server contact (alerts) Required. The e-mail of the team running the server: it becomes the ACME account contact and receives the expiry and no-renewal alerts
Domain names One per line or comma-separated. A wildcard requires DNS-01
Challenge Automatic (per profile) picks HTTP-01 if the profile allows it, otherwise DNS-01
Generate an EAB credential for this server Checked and locked when the profile requires EAB

Generate commands shows the EAB key (once), the steps with a copy button for each command, and warnings, for example when the public ACME URL is not configured. Every generation is recorded in the audit trail as ACME_ENROLLMENT_KIT (profile, platform, challenge, names, EAB key identifier).

The kit is a convenience: a client can enroll directly against the directory. The kit generates commands for HTTP-01 and DNS-01 only (see Limits).

The kit builds its URLs from the acme_public_url setting, or from PUBLIC_ACME_URL when the setting is empty. It must be the same host as the ACME service's PUBLIC_ACME_URL.

Approval and issuance policies

  • No manual approval. Enabling ACME removes the approval requirement from the profile, so requests made on that profile from the interface are not approved either. Keep ACME profiles separate from profiles that need an approver.
  • The profile applies. The CSR is checked against the profile like any other request: allowed key algorithms, name filter, linked CA. A refusal reaches the client as a badCSR error carrying the backend's reason.
  • Issuance policies apply. A policy rule that blocks also blocks ACME orders: finalization fails with badCSR, and the error detail is the message written on the rule (or a generic refusal text when the rule has none), so the server operator sees why. The audit trail records POLICY_BLOCK with the rule, every name evaluated (common name and SANs) and the protocol. A rule that requires approval cannot stop an automated client: the certificate is issued and the audit trail records POLICY_AUTO_ALLOWED, with a failure outcome so that it stands out in the SIEM. If the policies cannot be evaluated (database error, rule that cannot be loaded), an ACME order is refused rather than allowed, the audit trail records POLICY_EVAL_ERROR, and the client can retry later. See Issuance policies.
  • The CSR must match the order. Its DNS names must be exactly the validated names, and its subject CN, if present, one of them.

CAA checking

Before validating a challenge for a DNS name, PKIFactor reads the name's CAA records (RFC 8659), walking up to the parent domains:

CAA situation Result
No CAA record anywhere up the tree Allowed
issue record (or issuewild for a wildcard) naming one of PKIFactor's CA identifiers Allowed
issue / issuewild records naming only other CAs Refused: CAA record forbids issuance: ...
Every DNS lookup failed Refused (fail-closed)

PKIFactor's CA identifiers come from ACME_CAA_IDENTIFIERS. When it is not set, they are derived from PUBLIC_ACME_URL: for https://acme.example.com, acme.example.com and example.com. A domain that publishes CAA records for a public CA only must add PKIFactor's identifier, for example:

example.com.  CAA 0 issue "acme.example.com"

The check can be turned off with ACME_CAA_ENABLED=false; do not do it in production. Each check is recorded in the ACME service's audit log (caa.check_passed, caa.check_failed).

Validating servers on private addresses

To prevent PKIFactor from being used to probe your internal network, HTTP-01 and TLS-ALPN-01 refuse targets on private, loopback, link-local, reserved and shared (100.64.0.0/10) addresses by default. Redirects are not followed, and the answer is limited in size.

To validate internal servers, declare their networks:

Where Format Priority
Setting acme_allowed_networks Comma-separated CIDR ranges, for example 198.51.100.0/24,203.0.113.0/24 Used when not empty; read again within a minute
Environment variable ACME_ALLOWED_NETWORKS of the ACME service JSON list, for example ["198.51.100.0/24"] Used when the setting is empty

When a list is declared, every target must be in it, public addresses included.

The acme_allowed_networks setting is not shown on the Settings page of the interface; set it through the API (below).

Saving the Settings page leaves this setting untouched (before version 1.8.29 it emptied it).

Via the API
curl -s -b jar -X PUT https://clm.example.com/api/v1/admin/settings \
  -H "Content-Type: application/json" \
  -d '{"settings": {"acme_allowed_networks": "198.51.100.0/24",
                    "acme_public_url": "https://acme.example.com"}}'

DNS-01 and internal zones

By default PKIFactor reads the TXT record through four public resolvers (Google, Cloudflare, Quad9, OpenDNS) and requires three of them to return the expected value. A name that exists only in an internal DNS therefore never validates.

For internal zones, set ACME_DNS_RESOLVERS on the ACME service to your resolvers (JSON list, for example ["198.51.100.53"]); all the listed resolvers must then return the value. The same resolvers are used for CAA lookups.

If _acme-challenge.<name> is a CNAME, PKIFactor follows it (up to five levels) and reads the TXT record at the target. This lets you delegate challenge records to a zone your clients can update through an API.

Renewal

ACME clients renew on their own schedule (certbot and acme.sh at 30 days before expiry by default). Each renewal is a new order. PKIFactor links the new certificate to the one it replaces when the account, the profile and the common name are the same, so the inventory shows a renewal chain, as for a renewal made in the interface.

The certificate page of an ACME certificate says Renewal driven by the ACME client: the Renew action of the interface would produce a certificate the server never sees.

Renewal information (ARI, RFC 9773)

The directory announces renewalInfo. A client that supports ARI asks PKIFactor when to renew:

  • by default the suggested window opens at two thirds of the certificate's lifetime;
  • after Request early renewal on the certificate page, the window opens at once, for one hour. Clients that read ARI renew at their next check (PKIFactor asks them to check again within 6 hours; each client has its own rhythm). Withdraw the request cancels it.

Clients that do not read ARI ignore the request; the certificate page shows the command to force a renewal on the server. Both actions are recorded in the audit trail (CERT_EARLY_RENEWAL_REQUESTED, CERT_EARLY_RENEWAL_CANCELLED). The request is refused on a certificate that was not issued through ACME (Réservé aux certificats émis via ACME : ailleurs, utilisez le renouvellement classique.).

Via the API
curl -s -b jar -X POST https://clm.example.com/api/v1/certificates/512/early-renewal
curl -s -b jar -X DELETE https://clm.example.com/api/v1/certificates/512/early-renewal

Account key change

A client that supports it can replace its account key (RFC 8555 key change). The account keeps its URL, its profile, its EAB binding and its scope; only the key changes. A key already used by another account is refused with HTTP 409.

Revocation

A client can revoke a certificate issued by PKIFactor's ACME server, signing the request either:

  • with the account key, if the certificate's DNS names are exactly those of one of the account's completed orders; or
  • with the certificate's own private key.

The certificate presented must be byte for byte one that this ACME server issued, and it must have been issued on the same ACME path. PKIFactor revokes it at the CA, marks it revoked in the inventory and records CERTIFICATE_REVOKED in the audit trail with the method acme. RFC 5280 reason codes are accepted; without a reason, unspecified is used.

Certificates issued through ACME can also be revoked from the interface like any other certificate (see Managing certificates).

What appears in PKIFactor

Where What
Inventory Every ACME certificate, owned by the ACME service account, in the profile's organization. The request keeps the ACME order, account, contact e-mail, challenge type and path
Certificate page The private key is shown as generated by the ACME client and not held by PKIFactor; Renewal driven by the ACME client; Request early renewal
Infrastructure > ACME servers One line per ACME account and profile that obtained at least one certificate (see below)
Dashboard The ACME Certificates card

The ACME client itself sees only the protocol: its account status, its orders, authorizations and certificates. The account object returned to the client does not include the contact or a list of orders.

ACME servers page

Administration workspace, Infrastructure > ACME servers (page ACME-enrolled servers) lists the enrolled servers with their State, Domains, Profile, Contact, Last issued, Expires and number of Certificates:

State Meaning Action
Up to date Latest certificate valid, expiry more than 15 days away None
Due soon Latest certificate expires within 15 days and no renewal has been issued Check the client's timer or scheduled task
Late Latest certificate expired without renewal Repair the client, or retire the server
Revoked Latest certificate revoked Re-enroll after handling the cause

When e-mail is enabled, the daily expiry check e-mails the ACME account contact, and also the profile's notification address, at each alert threshold (30, 14, 7 and 1 days before expiry by default) and as long as no renewal exists: acme_cert_expiring above 7 days, acme_no_renewal at 7 days and below. For an account registered without a contact e-mail, the alert goes instead to the profile's notification address; if the profile has none, to the managers of the certificate's organization, then to its approvers, and as a last resort to the administrators. Registering clients with a contact e-mail remains the best practice, because it reaches the team that runs the server. A server that renews in time triggers nothing. See E-mail and notifications.

Via the API
curl -s -b jar https://clm.example.com/api/v1/admin/acme-enrollment/servers

Audit

Where Events
PKIFactor audit trail (Oversight workspace, Compliance > Audit Trail; see Audit trail) CERTIFICATE_ISSUED, CERTIFICATE_REVOKED, POLICY_BLOCK, POLICY_AUTO_ALLOWED, POLICY_EVAL_ERROR, ACME_EAB_CREATED, ACME_EAB_DISABLED, ACME_EAB_ENABLED, ACME_ENROLLMENT_KIT, CERT_EARLY_RENEWAL_REQUESTED, CERT_EARLY_RENEWAL_CANCELLED, and profile changes
ACME service audit log (database schema acme and the acme service log) Protocol events with the client address and user agent: account.created, account.key_changed, order.created, order.finalized, authorization.created, authorization.deactivated, challenge.validated, challenge.failed, caa.check_passed, caa.check_failed, certificate.issued, certificate.revoked, certificate.revoke_failed

Limits

Topic Behaviour in this version
Account update and deactivation Not supported: a request to change the contact or to deactivate the account is answered with the account unchanged
List of an account's orders Not provided
Disabling an ACME account No action in PKIFactor; see Key states
IP address identifiers (RFC 8738) Accepted by the protocol layer (HTTP-01 and TLS-ALPN-01 only), not tested end to end: do not rely on them
Pre-authorization (newAuthz) Present, not tested
Names per order At most 100 identifiers in one order (ACME_MAX_IDENTIFIERS_PER_ORDER); above, the order is refused as malformed
Enrollment kit HTTP-01 and DNS-01 only; TLS-ALPN-01 cannot be generated by the kit
Account key algorithms RS256, ES256, ES384, ES512
Rate limits (per ACME service instance) New account: 10 per hour per address. New order and finalization: 50 per hour per account. Challenge: 30 per minute. Certificate download: 60 per minute. Authorization: 120 per minute. Revocation: 10 per hour. Renewal information: 60 per minute. Above: rateLimited (HTTP 429)
PKIFactor as an ACME client of a public CA Does not change its own account key at the upstream CA

Settings reference

Name Where Default Role
PUBLIC_ACME_URL ACME service environment Set at installation Base of every URL returned to clients; default source of the CAA identifiers
acme_public_url Setting (API) Empty URL used by the enrollment kit and by the service certificate check; empty: PUBLIC_ACME_URL
acme_allowed_networks Setting (API) Empty Networks allowed as HTTP-01 and TLS-ALPN-01 targets
ACME_ALLOWED_NETWORKS ACME service environment Empty Same, when the setting is empty (JSON list)
ACME_DNS_RESOLVERS ACME service environment Empty (public resolvers) Resolvers for DNS-01 and CAA (JSON list)
ACME_DNS_TIMEOUT ACME service environment 5 DNS timeout in seconds
ACME_CAA_TOTAL_TIMEOUT ACME service environment 20 Total time in seconds allowed for the CAA lookup of one name, all parent domains included
ACME_MAX_IDENTIFIERS_PER_ORDER ACME service environment 100 Maximum number of names in one order
ACME_CAA_IDENTIFIERS ACME service environment Derived from PUBLIC_ACME_URL Values accepted in CAA issue / issuewild records (JSON list)
ACME_CAA_ENABLED ACME service environment true CAA checking

Environment variables are set in the .env file with Docker Compose (see Docker Compose) and apply after a restart of the ACME service.

Check a directory

curl -s https://acme.example.com/acme/srv-web/directory
{"newNonce": "https://acme.example.com/acme/srv-web/new-nonce",
 "newAccount": "https://acme.example.com/acme/srv-web/new-account",
 "newOrder": "https://acme.example.com/acme/srv-web/new-order",
 "newAuthz": "https://acme.example.com/acme/srv-web/new-authz",
 "revokeCert": "https://acme.example.com/acme/srv-web/revoke-cert",
 "keyChange": "https://acme.example.com/acme/srv-web/key-change",
 "renewalInfo": "https://acme.example.com/acme/srv-web/renewalInfo",
 "meta": {"externalAccountRequired": true, "acmePath": "srv-web"}}

Enable ACME on a profile via the API

curl -s -b jar -X PUT https://clm.example.com/api/v1/clm/templates/12 \
  -H "Content-Type: application/json" \
  -d '{"acme_enabled": true, "acme_http01_enabled": true, "acme_dns01_enabled": true,
       "acme_tlsalpn01_enabled": false, "acme_eab_required": true,
       "requires_approval": false}'
The response contains the generated acme_path.

Troubleshooting

Errors returned by the ACME server are ACME problem documents; clients usually print the detail text quoted below.

Symptom Cause and fix
Unknown ACME endpoint: <path> (HTTP 404) on the directory Wrong path, ACME disabled on the profile, or profile inactive. Copy the Directory URL from the profile page
This ACME endpoint requires External Account Binding (eab-kid/eab-hmac-key) The profile requires EAB: create a key and pass it at registration
External account binding rejected: unknown or disabled EAB key Wrong key identifier, or key disabled
External account binding rejected: EAB key not valid for this ACME profile The key is limited to another profile: create one for this profile
External account binding rejected: EAB signature mismatch HMAC key copied wrongly. It cannot be shown again: create a new key
External account binding rejected: EAB already used (single-use credential) The key was consumed by another account key, typically after the client lost its account key (reinstallation, deleted Kubernetes Secret). Create a new key
ACME account is registered on another ACME profile; use a distinct account key for this profile The client reuses an account key created on another profile's directory: use a separate account key
identifier '<name>' is outside this account's authorized scope The name is not in the EAB key's scope: create a new key with the right scope and a new account
CAA record forbids issuance: ... The domain's CAA records do not name PKIFactor: add PKIFactor's identifier to them
challenge type '<type>' not enabled for this identifier/profile The challenge is not enabled on the profile, or HTTP-01 / TLS-ALPN-01 was used for a wildcard
Challenge validation failed with HTTP-01 PKIFactor could not fetch the token on port 80: name not resolving, firewall, private address not declared (the ACME service log shows HTTP-01 blocked: private/reserved IP), or an HTTP to HTTPS redirect on port 80 (redirects are not followed)
Challenge validation failed with DNS-01 TXT record not yet visible to the resolvers, or internal-only zone without ACME_DNS_RESOLVERS
badCSR at finalization The profile or an issuance policy refused the request: key algorithm not allowed, name outside the profile's filter, blocking rule. The detail carries the reason: for a blocking rule, the message written on the rule; otherwise the backend's reason (in French in this version). The matching POLICY_BLOCK event in the audit trail names the rule
CSR DNS SAN does not match ACME identifiers The CSR does not carry exactly the ordered names
Account creation answers Account eligibility temporarily unverifiable; retry later The ACME service could not reach the PKIFactor backend to read the profile: check the backend, then retry
Clients fail on the directory with a TLS error The ACME host certificate is expired, lacks the ACME name, or comes from a CA the client does not trust: see Service certificates
Rate limit exceeded. Please retry later. (HTTP 429) A limit of the table above was reached: wait and retry
A server stays Late on the ACME servers page The client no longer runs (timer disabled, server switched off). Repair it or retire the server and revoke its certificate