-
Notifications
You must be signed in to change notification settings - Fork 43
CA Handler for OpenXPKI
This handler allows certificate enrollment from OpenXPKI, as ACME support appears to be available only in the commercial version.
Although connecting to OpenXPKI was previously possible via the generic EST CA handler, this dedicated handler is preferred because it supports revocation operations and allows specifying certificate profiles.
To use this handler, ensure you have:
- A running OpenXPKI instance with an activated RPC server.
- An RPC endpoint that supports
RequestCertificate
,RevokeCertificate
, andSearchCertificate
, as described in the example configuration. - A client certificate and key in PEM format for authentication with OpenXPKI.
- A certificate profile.
To ensure compatibility with acme2certifier, adjust the OpenXPKI configuration:
By default, acme2certifier expects a full certificate chain (including the root certificate) in the response to a RequestCertificate
call. Modify the export_certificate
parameter in the OpenXPKI endpoint configuration file (config.d/realm.tpl/rpc/
) as follows:
policy:
export_certificate: fullchain
Although certificate polling is supported via the polling_timeout
parameter in acme_srv.cfg
, manual or dual approval should be skipped to ensure smooth enrollment operations. Set approval_points
to 1
in config.d/realm.tpl/rpc/
:
policy:
approval_points: 1
Some ACME clients, such as Certbot, generate CSRs without a subject name, causing OpenXPKI to reject them. To address this, modify the OpenXPKI certificate profile (config.d/realm.tpl/profile/
) to use the first Subject Alternative DNS name (SAN DNS.0) as the CN when no CN is present:
style:
# RPC endpoint name, e.g., "enroll"
enroll:
subject:
dn: "[% IF CN.0 && CN.0 != '' %]CN=[% CN.0 %][% ELSE %]CN=[% SAN_DNS.0 %][% END %]"
- acme2certifier will issue certificates on behalf of the end nodes. This needs to be allowed in OpenXPKI. Please see more info on enroll modes (especially
Signer on Behalf
section) here: Enrollment Workflow. For this, you will need to set the client certificate as anauthorized_signer
for your RPC endpoint. You can set this inconfig.d/realm.tpl/rpc/enroll.yaml
:
authorized_signer:
rule1:
# Full DN
subject: CN=cn-of-your-client-cert-here(?:,.+|$)
Modify the acme2certifier configuration (acme_srv.cfg
) and add the following parameters:
[CAhandler]
handler_file: examples/ca_handler/openxpki_ca_handler.py
host: <URL>
client_key: <filename>
client_cert: <filename>
ca_bundle: <filename>
cert_profile_name: <name>
endpoint_name: <name>
polling_timeout: <seconds>
- host – URL of the OpenXPKI server.
- client_cert – Client certificate in PEM or PKCS#12 format, used for authentication.
- client_key – (Required if using PEM format) Key file used for authentication.
- cert_passphrase – (Required if using PKCS#12 format) Passphrase for accessing the PKCS#12 container.
-
cert_passphrase_variable (optional) – Environment variable containing the certificate passphrase (overridden if
cert_passphrase
is set inacme_srv.cfg
). -
ca_bundle (optional) – CA certificate chain in PEM format needed to validate the OpenXPKI server certificate. Accepts
True
,False
, or a filename (default:True
). - cert_profile_name – Name of the OpenXPKI certificate profile to be used.
- endpoint_name – Name of the OpenXPKI RPC endpoint.
-
polling_timeout – Timeout (in seconds) for enrollment operations (default:
0
, polling disabled). -
request_timeout (optional) – Timeout (in seconds) for OpenXPKI requests (default:
5s
). -
allowed_domainlist (optional) – List of domain names allowed for enrollment (JSON format). Example:
["bar.local", "bar.foo.local"]
(default:[]
).
Use your preferred ACME client for certificate enrollment. A list of clients used in our regression testing is available in the disclaimer section of our README.
acme2certifier supports the the Automated Certificate Management Environment (ACME) Profiles Extension draft allowing an acme-client to specify a cert_profile_name
parameter to be submitted to the CA server.
The list of supported profiles must be configured in acme_srv.cfg
[Order]
profiles: {"profile1": "http://foo.bar/profile1", "profile2": "http://foo.bar/profile2", "profile3": "http://foo.bar/profile3"}
Once enabled, a client can specify the cert_profile_name to be used as part of an order request. Below an example for lego:
docker run -i -v $PWD/lego:/.lego/ --rm --name lego goacme/lego -s http://<acme-srv> -a --email "[email protected]" -d <fqdn> --http run --profile profile2
Further, this handler makes use of the header_info_list feature allowing an ACME client to specify a certificate profile to be used during certificate enrollment. This feature is disabled by default and must be activated in acme_srv.cfg
as shown below
[Order]
...
header_info_list: ["HTTP_USER_AGENT"]
The ACME client can then specify the profileID as part of its user-agent string.
Example for acme.sh:
docker exec -i acme-sh acme.sh --server http://<acme-srv> --issue -d <fqdn> --standalone --useragent cert_profile_name=acme_clt --debug 3 --output-insecure
Example for lego:
docker run -i -v $PWD/lego:/.lego/ --rm --name lego goacme/lego -s http://<acme-srv> -a --email "[email protected]" --user-agent cert_profile_name=acme_clt -d <fqdn> --http run
This handler can use the eab profiling feature to allow individual enrollment configuration per acme-account as well as restriction of CN and SANs to be submitted within the CSR. The feature is disabled by default and must be activatedd in acme_srv.cfg
[EABhandler]
eab_handler_file: examples/eab_handler/kid_profile_handler.py
key_file: <profile_file>
[CAhandler]
eab_profiling: True
Below is an example key file used during regression testing:
{
"keyid_00": {
"hmac": "V2VfbmVlZF9hbm90aGVyX3ZlcnkfX2xvbmdfaG1hY190b19jaGVja19lYWJfZm9yX2tleWlkXzAwX2FzX2xlZ29fZW5mb3JjZXNfYW5faG1hY19sb25nZXJfdGhhbl8yNTZfYml0cw",
"cahandler": {
"cert_profile_name": ["acmeca2", "acmeca1"],
"allowed_domainlist": ["www.example.com", "www.example.org", "*.acme"]
}
},
"keyid_01": {
"hmac": "YW5vdXRoZXJfdmVyeV9sb25nX2htYWNfZm9yX2tleWlkXzAxX3doaWNoIHdpbGxfYmUgdXNlZF9kdXJpbmcgcmVncmVzc2lvbg",
"cahandler": {
"cert_profile_name": "acmeca2",
"allowed_domainlist": ["www.example.com", "www.example.org", "*.acme"],
"ca_name": "acmeca"
}
},
"keyid_02": {
"hmac": "dGhpc19pc19hX3ZlcnlfbG9uZ19obWFjX3RvX21ha2Vfc3VyZV90aGF0X2l0c19tb3JlX3RoYW5fMjU2X2JpdHM",
"cahandler": {
"allowed_domainlist": ["www.example.com", "www.example.org"]
}
},
"keyid_03": {
"hmac": "YW5kX2ZpbmFsbHlfdGhlX2xhc3RfaG1hY19rZXlfd2hpY2hfaXNfbG9uZ2VyX3RoYW5fMjU2X2JpdHNfYW5kX3Nob3VsZF93b3Jr"
}
}