- 1 Overview
- 2 ACME overview
- 3 Use cases (stories)
- 4 Scope
- 5 Feature management
- 6 Design
- 6.1 Overview of Dogtag ACME service
- 6.2 Design at a glance
- 6.3 Deploying the ACME service
- 6.4 Database
- 6.5 Issuer
- 6.6 Replicated configuration
- 6.7 TLS requirements
- 6.8 Scalability
- 7 Upgrade
- 8 How to use
- 9 Test plan
Automated Certificate Management Environment (ACME) is a protocol for automated identity verification and issuance of certificates asserting those identities. The initial and predominant use case is for Web PKI, i.e. automated issuance of domain validated (DV) certificates. Automation enables better security through shorter-lived certificates, more pervasive security through automatic deployment of TLS and cost-savings by eliminating repetitive human effort.
Dogtag PKI has implemented an ACME server. The purpose of this design is to use the Dogtag ACME service to support ACME use cases in FreeIPA.
ACME is defined and extended in the following IETF documents:
- RFC 8555: The main spec,
- RFC 8737:
- RFC 8738:
- Others already published or being developed by the ACME working group
ACME currently has two validation challenges defined: DNS (client creates some DNS records to prove control of a domain) and HTTP (client creates some HTTP records to prove control of a domain).
ACME clients create accounts on an ACME server by registering a public key; future messages are authenticated and communications between server and client are encrypted using the client's key. There is no specific provision for using ACME with existing accounts, or creating an ACME account linked to some other account.
An ACME account orders a certificate for a set of identifiers. The currently defined identifer types are
ip. The server creates challenges that they client can use to prove "control" of the identifiers. Currently defined challenge types are
http-01 (provision an HTTP resource at the location reached via the identifier),
dns-01 (provision a DNS TXT record at the forward or IP-reverse name) and
tls-alpn-01 (TLS-based challenge using ALPN extension). After completing challenges, the client finalizes the order and the server issues the certificate.
ACME also defines operations for certificate revocation and account key rollover. RFC 8555 does not state whether ACME servers or clients are required to support these operations.
Use cases (stories)
As a developer I want to use FreeIPA to issue my certificates over ACME protocol so that I can develop and test using the same protocol I will utilize in production.
As a system administrator I want the FreeIPA CA to provide an ACME server so that I can automatically acquire and renew certificates.
As a IT security officer I want the organisation's CA to provide ACME to reduce costs and barriers to using TLS for all internal services.
The motivating (and so far only) use case of ACME is essentially anonymous clients create accounts, prove "control" of (DNS) names, then request certificates for those names. The question that arises is: how does ACME fit into an enterprise environment where hosts and services already have identities, can prove those identities to a CA, and a CA can enforce rules about which identities can be issued what kinds of certificates? There is no clear, general answer to this question at present.
There is also the matter of ACME clients and what features they support. They support what has been defined: the
dns identifier and some or all of the defined challenges (
tls-alpn-01). They generally do not support additional layers of authentication (e.g. GSS-API). There are specifications in development for an "authority token" challenge, and challenges for other kinds of names (e.g. email addresses for S/MIME use case, IP address certificates, code signing certificates). But these have not been finalised.
The conclusion is that people are asking for ACME as it is defined and in use today, i.e. anonymous ACME clients using the aforementioned challenges to prove control of a domain name, and acquire a certificate for it. It is the same as what is done out on the open Internet by Let's Encrypt and others, only behind the corporate firewall. The FreeIPA CA is the issuer, and the prevailing DNS view is used when validating challenges.
Additional authentication and authorisation layers are deferred. We can implement them when we have a clear use case. It would be a separate design proposal.
Initially the only configuration available is to enable or disable the servicing of requests by the Dogtag ACME service. This is accomplished via the
# enable the service ipa-acme-manage enable # disable the service ipa-acme-manage disable
These commands operate on a per-server basis. Subsequent work will enable deployment-wide configuration of the ACME service (by replicating the configuration over LDAP). With that change, an
acme plugin for the FreeIPA API will allow users with the appropriate privileges to control the ACME service. The
ipa-acme-manage command will be deprecated or removed. Examples of what the commands may look like (non-prescriptive):
# enable service ipa acme-manage --enabled=1 # enable issuance of wildcard certificates ipa acme-manage --wildcard=1 # set profile to use ipa acme-manage --profile=customProfile # set CA to use ipa acme-manage --ca="ACME sub-CA" # set enabled challenges (http-01 enabled, dns-01 disabled) ipa acme-manage --challenges=http-01 # show configuration ipa acme-info
Overview of Dogtag ACME service
The Dogtag ACME service is an optional component, implemented as a Tomcat application. When deployed it runs as part of the
pki-tomcatd process alongside any other Dogtag subsystems (CA, KRA).
The implementation supports different issuer backends, e.g. Dogtag (
PKIIssuer) or a local NSS database (
NSSIssuer). The ACME service manages ACME accounts, orders and challenges and functions as a registration authority (RA) that uses the configured issuer to issue certificates.
The implementation supports different databases, including LDAP and PostgreSQL.
Currently only the
dns identifier and
dns-01 challenges are implemented. This covers the primary use case and a large majority of clients.
Apart from issuer and database, there are currently few configuration options. These include whether to enable the service at all (i.e. to service requests, or respond
503 to all requests), and whether to allow wildcard certificates.
The configuration source is configurable but only local file-based configuration has been implemented. This means that until a distributed configuration source is implemented, the Dogtag ACME service must be configured on a per-server basis.
Design at a glance
The major aspects of the design are as follows. Each item is elaborated in its own subsection.
- Deploy the Dogtag ACME service on all CA replicas
- Configure Dogtag ACME service to use Dogtag CA to issue certificates, using a suitable profile provided by FreeIPA.
- Configure Dogtag ACME service to store ACME objects in LDAP under
- Provide commands to manage the FreeIPA ACME service, including enable/disable.
- Update the HTTP configuration to proxy ACME requests to Dogtag.
- Add the
ipa-ca.$DOMAINDNS name to the FreeIPA HTTP certificate to enable ACME clients to use that domain name.
Deploying the ACME service
There are two main options on how to deploy the ACME capability within a FreeIPA deployment.
- Deploy ACME service on all CA replicas. This would mean clients could use the established
ipa-ca.$DOMAINDNS name to access the ACME service. No administrator actions are required to configure the ACME service, other than to enable it. The ACME service will be automatically deployed on new CA servers, and on existing CA servers upon upgrade.
- Deploy ACME service on select CA replicas. Define a new ACME server role. Administrators choose the CA servers on which to configure the ACME role. A new DNS name points to ACME servers in the topology (e.g.
ipa-acme.$DOMAIN). Implement behaviour to manage this DNS name when using FreeIPA's internal DNS. The requirement to manage this DNS name is imposed on administrators when not using FreeIPA's internal DNS.
Option #1 was chosen because it is simplier for administrators and the implementation is simplier.
Because ACME requires the use of TLS, both options impose the requirement to add a new DNS name to the FreeIPA HTTP certificate. See #TLS requirements for details.
In addition to creating the configuration files as described in the following sections, FreeIPA shall run the following two commands to create and deploy the Dogtag ACME service instance:
pki-server acme-create pki-server acme-deploy
Configure the Dogtag ACME service to use the
ou=acme,o=ipaca subtree via
class=org.dogtagpki.acme.database.LDAPDatabase basedn=ou=acme,o=ipaca configFile=/etc/pki/pki-tomcat/ca/CS.cfg
configFile directive tells the
LDAPDatabase where to find database connection settings.
The ACME schema is automatically added in new installations. See #Upgrade for upgrade steps.
Create the ACME object heirarchy under
dn: ou=nonces,ou=acme,o=ipaca objectClass: organizationalUnit ou: nonces dn: ou=accounts,ou=acme,o=ipaca objectClass: organizationalUnit ou: accounts dn: ou=orders,ou=acme,o=ipaca objectClass: organizationalUnit ou: orders dn: ou=authorizations,ou=acme,o=ipaca objectClass: organizationalUnit ou: authorizations dn: ou=challenges,ou=acme,o=ipaca objectClass: organizationalUnit ou: challenges
attributeTypes: ( acmeExpires-oid NAME 'acmeExpires' SYNTAX 184.108.40.206.4.1.14220.127.116.11.24 EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SINGLE-VALUE ) attributeTypes: ( acmeValidatedAt-oid NAME 'acmeValidatedAt' SYNTAX 18.104.22.168.4.1.1422.214.171.124.24 EQUALITY generalizedTimeMatch ORDERING generalizedTimeOrderingMatch SINGLE-VALUE ) attributeTypes: ( acmeStatus-oid NAME 'acmeStatus' SYNTAX 126.96.36.199.4.1.14188.8.131.52.15 EQUALITY caseIgnoreMatch SINGLE-VALUE ) attributeTypes: ( acmeError-oid NAME 'acmeError' SYNTAX 184.108.40.206.4.1.14220.127.116.11.15 SINGLE-VALUE ) attributeTypes: ( acmeNonceValue-oid NAME 'acmeNonceValue' SUP name SINGLE-VALUE ) attributeTypes: ( acmeAccountId-oid NAME 'acmeAccountId' SUP name SINGLE-VALUE ) attributeTypes: ( acmeAccountContact-oid NAME 'acmeAccountContact' SYNTAX 18.104.22.168.4.1.1422.214.171.124.15 EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch ) attributeTypes: ( acmeAccountKey-oid NAME 'acmeAccountKey' SYNTAX 126.96.36.199.4.1.14188.8.131.52.15 SINGLE-VALUE ) attributeTypes: ( acmeOrderId-oid NAME 'acmeOrderId' SUP name SINGLE-VALUE ) attributeTypes: ( acmeIdentifier-oid NAME 'acmeIdentifier' SYNTAX 184.108.40.206.4.1.14220.127.116.11.15 EQUALITY caseIgnoreMatch ) attributeTypes: ( acmeAuthorizationId-oid NAME 'acmeAuthorizationId' SUP name ) attributeTypes: ( acmeAuthorizationWildcard-oid NAME 'acmeAuthorizationWildcard' SYNTAX 18.104.22.168.4.1.1422.214.171.124.7 EQUALITY booleanMatch SINGLE-VALUE ) attributeTypes: ( acmeChallengeId-oid NAME 'acmeChallengeId' SUP name SINGLE-VALUE ) attributeTypes: ( acmeToken-oid NAME 'acmeToken' SYNTAX 126.96.36.199.4.1.14188.8.131.52.15 ) objectClasses: ( acmeNonce-oid NAME 'acmeNonce' STRUCTURAL MUST ( acmeNonceValue $ acmeExpires ) ) objectClasses: ( acmeAccount-oid NAME 'acmeAccount' STRUCTURAL MUST ( acmeAccountId $ acmeAccountKey $ acmeStatus ) MAY acmeAccountContact ) objectClasses: ( acmeOrder-oid NAME 'acmeOrder' STRUCTURAL MUST ( acmeOrderId $ acmeAccountId $ acmeStatus $ acmeIdentifier $ acmeAuthorizationId ) MAY ( acmeError $ userCertificate $ acmeExpires ) ) objectClasses: ( acmeAuthorization-oid NAME 'acmeAuthorization' STRUCTURAL MUST ( acmeAuthorizationId $ acmeAccountId $ acmeIdentifier $ acmeStatus ) MAY ( acmeExpires $ acmeAuthorizationWildcard ) ) objectClasses: ( acmeChallenge-oid NAME 'acmeChallenge' ABSTRACT MUST ( acmeChallengeId $ acmeAccountId $ acmeAuthorizationId $ acmeStatus ) MAY ( acmeValidatedAt $ acmeError ) objectClasses: ( acmeChallengeDns01-oid NAME 'acmeChallengeDns01' SUP acmeChallenge STRUCTURAL MUST acmeToken )
The template for
class=org.dogtagpki.acme.issuer.PKIIssuer url=https://$FQDN:8443 profile=acmeServerCert username=$USER password=$PASSWORD
class tells the Dogtag ACME service to use the
PKIIssuer issuer implementation.
PKIIssuer to use the Dogtag CA on the same host.
PKIIssuer what profile to use. See #Profile for details of what this profile must contain.
PKIIssuer how to authenticate to the Dogtag CA.
issuer.conf must have ownership
pkiuser:pkiuser and mode
200. See #Authentication to CA for details.
Authentication to CA
The PKI backend must authenticate to Dogtag. The IPA RA credential is not suitable because the
pki-tomcatd process cannot access it. Furthermore the IPA RA credential is in the wrong format (Dogtag uses JSS and requires an NSS DB) and we want to eventually get rid of the IPA RA and use GSS-API proxy authentication for authentication between the FreeIPA framework and Dogtag.
Remaining options considered were:
- A shared "ACME RA" Dogtag (not IPA) user account, with password authentication (we don't want to introduce any more certificates). The password would be distributed among CA replicas via Custodia and must be stored so that only
pki-tomcatdcan read it. The account requires permission to issue certificates using the configured profile, and to revoke certificates issued by it.
- A Dogtag user account per server with unique password (avoiding need to replicate password securely). The accounts need the same permission as the previous option, which could be achieved via a group membership. The same file readership requirements apply.
- Implement most of the remainder of the GSS-API authentication to Dogtag effort so that we can use GSS-API authentication between the ACME service and the Dogtag CA subsystem. This is a complex (risky) and time-consuming effort. The upside is that it's a big step toward resolving one of the biggest and longest-running problems in the FreeIPA architecture.
The chosen option was #2. Therefore the implementation is required to:
- Create the
ACME Agentsgroup (once only)
Add a Dogtag ACL allowing members of
ACME Agentsto revoke certificates (once only):
certServer.ca.certs:execute :allow (execute) group="ACME Agents" :ACME Agents may execute cert operations
executepermission sounds like it has a large scope but it indeed only grants permission to revoke (or unrevoke) a certificate.
- For each CA server create the
acme-$FQDNuser, with membership in
ACME Agentsand a unique password (to be written in
Requirements for the certificate profile configuration are described in #Profile.
The ACME profile shall be called
acmeServerCert. As with other included profiles it is defined as a template:
/usr/share/ipa/profiles/acmeServerCert.cfg. The definition is similar to
caIPAserviceCert but there are a few important differences:
Only members of the
ACME Agentsgroup can issue certificates using this profile:
The certificate lifetime is 90 days:
SANToCNDefaultcomponent is used to populate the Subject DN field because some ACME clients create CSRs with an empty Subject field:
policyset.serverCertSet.9.default.class_id=sanToCNDefaultImpl policyset.serverCertSet.9.default.name=SAN to CN Default
Not yet implemented.
Story: As an administrator, I want to be able to configure and control the FreeIPA ACME service deployment-wide, so that configuration is kept consistent without additional effort.
This will require implementing an LDAP-based configuration source in the Dogtag ACME service. Because the configuration will be managed by ordinary FreeIPA users, it may be necessary to store that configuration in the FreeIPA LDAP database (as opposed to
o=ipaca). Therefore it might be necessary for the configuration source to authenticate to LDAP using a FreeIPA principal and GSS-API.
An appropriate service princpial already exists:
dogtag/$FQDN. But if GSS-API is required it will be necessary to achieve this via the ldapjdk library. There does appear to be some GSS-API ldapbind code in ldapjdk but its status is unknown.
The configuration source will either need to execute a persistent search (preferred) or regularly poll the LDAP configuration object and look for changes to the configuration.
ACME requires TLS. Therefore we must add the
ipa-ca.$DOMAIN DNS name to the FreeIPA HTTP certificate on each CA server.
To simplify the implementation, we actually add the
ipa-ca.$DOMAIN DNS name to the HTTP certificate on every IPA server whether or not it is a CA replica. The DNS name does (or is expected to) only point at CA servers, so this is not an operational issue. The security implication (relative to having the name on the HTTP certs of CA servers) is that HTTP TLS key compromise of an IPA server that is not a CA server allows it to impersonate
ipa-ca.$DOMAIN and therefore the ACME server. This is a modest risk because compromise of that key is already a catastrophe. The avoidance of complexity due the fact that IPA servers can acquire the CA role at any time seems well worth it.
To implement this change we need to:
- on installation (including ipa-replica-install and ipa-ca-install) ensure the HTTP service certificate gets (re)issued to include the include the alias.
- on upgrade (existing CA replicas), update the Certmonger tracking request for the HTTP service certificate to include the alias, then renew the cert.
This change was implemented in https://pagure.io/freeipa/issue/8186.
Pruning expired certificates
Not yet implemented.
If ACME is used heavily, lots of short-lived certificates will pile up in the Dogtag database. We should implement pruning of expired certificates, with knobs to enable/disable (DISABLED by default). This scenario is not ACME-specific and there is an existing ticket: https://pagure.io/dogtagpki/issue/1750.
Pruning expired ACME objects
Not yet implemented.
The ACME service database stores account, order, authorization and challenge objects. The growth of the database will be approximately linear in the number of orders (certificate requests), unless some cleanup operations are performed.
Order objects may have an expiry. Expired orders could be pruned from the database. The expiry could be set at (for example) 24 hours while the order is not yet
valid (i.e. before a certificate is actually issued), and reset when the certificate is issued to the
notAfter date of the certificate. The order therefore expires when it seems the client has "given up", or when the certificate expires. It can then be deleted.
Authorization and challenge objects can also expire, and be pruned in a similar way.
Accounts themselves have no expiry in the data model and semantics of ACME. But if needed, accounts could be pruned if they are at least some minimum age, but have no orders. This indicates that the account is inactive (all orders have expired and been removed; an active ACME client will create new orders to renew the certificates it manages).
ACME protocol nonces are currently created in the LDAP database. They are therefore replicated. The performance impact has not been measured but rapid additional and deletion of small objects throughout the protocol steps may be some "low hanging fruit" if ACME load causes replication issues.
Client behaviour has not been adequately analysed to know whether restriction of nonces to a single server (e.g. an in-memory cache) is viable when the ACME server's DNS name points to several servers.
- Update the LDAP schema with the contents of
- Deploy the ACME service using the same subroutine as used during installation. This subroutine must already detect and skip "once per deployment" operations that were already completed (e.g. creating the LDAP object hierarchy) so there is no special consideration of these scenarios during upgrade.
How to use
See #Feature management for a description of administrator operations.
For the client side, use an ACME client program to create an ACME account, request certificates and (if required) revoke certificates. There are many ACME clients and elaborating all the usage scenarios is out of scope of this document. But see #Test plan for some specific scenarios using the Certbot and mod_md clients.
As a concrete example, here is how you could use Certbot to register an account and acquire a certificate from the FreeIPA ACME service:
# certbot --server https://ipa-ca.ipa.local/acme/directory \ register -m firstname.lastname@example.org --agree-tos --no-eff-email # certbot --server http://ipa-ca.ipa.local/acme/directory \ certonly --standalone --domain $(hostname)
ACME clients available on Fedora include Certbot (a general purpose client) and mod_md (an Apache httpd module). These can be tested independently.
The test setup is a single FreeIPA server with CA role, and a single client. All steps in the test scenarios outlined below are on the client unless stated otherwise.
Enabling ACME service
- [Server] Deploy a server with CA.
- [Client] Use Curl to request ACME directory object and ensure ACME service responds 503 (it has not been enabled yet).
- [Client] Use Curl to request ACME directory object again; should succeed.
Certbot HTTP challenge
- Register account.
- Request certificate using
--standaloneHTTP server. Succeeds.
Certbot DNS challenge
Not yet implemented.
Assume account already registered (previous test).
- Request certificate using
--manualmode with hooks to create/clean up required TXT records. Succeeds.
Not yet implemented.
Assume account already registered and certificates have been successfully issued (previous tests).
- Revoke a certificate. Succeeds.
- Confirm via
ipa cert-showcommand that certificate was revoked.
mod_md HTTP challenge
httpdconfiguration to use
mod_mdfor machine's FQDN.
httpd(and wait a few seconds).
- Gracefuly restart
htttpd(to pick up certificate, assuming mod_md was able to acquire one).
- [Server] Use Curl to retrieve page hosted at client over HTTPS. Succeeds.