ACME
This page describes future functionality which isn't yet available for general release.
ENTERPRISE EDITION This is an EJBCA Enterprise Edition (EE) feature.
ACME Overview
The Automatic Certificate Management Environment (ACME) is a protocol that a Certificate Authority (CA) and an applicant can use to automate the process of verification and certificate issuance.
Supported Operations
The ACME RFC Internet-Draft is a working document. The EJBCA implementation currently complies with IETF - ACME Draft 12.
Operation |
URL |
Description |
Draft Reference |
directory |
/ejbca/acme/directory |
Provides a JSON object describing the other commands. |
|
newNonce |
/ejbca/acme/newNonce |
Before any POST action is performed, the client needs to retrieve an anti-replay nonce from the server. |
|
newAccount |
/ejbca/acme/newAccount |
|
|
updateAccount |
/ejbca/acme/acct/{accountId} |
|
|
newOrder |
/ejbca/acme/newOrder |
|
|
challengeResponse |
/ejbca/acme/acct/{accountId}/authz/{authorizationId}/{challengeId} |
|
|
newAuthz |
/ejbca/acme/newAuthz |
Only if Pre-Authorization Allowed is enabled in the Alias configuration. |
|
finalizeOrder |
/ejbca/acme/acct/{accountId}/orders/{orderId}/finalize |
|
|
revokeCert |
/ejbca/acme/revokeCert |
|
|
keyChange |
/ejbca/acme/keyChange |
|
Base URL
The ACME service is available on the following URLs
Default alias with client authentication |
https://<server>:8443/ejbca/acme/directory |
Default alias without client authentication |
https://<server>:8442/ejbca/acme/directory |
Custom alias <alias_name> with client authentication |
https://<server>:8443/ejbca/acme/<alias_name>/directory |
Custom alias <alias_name> without client authentication |
https://<server>:8442/ejbca/acme/<alias_name>/directory |
EJBCA Specifics
-
Approvals in EJBCA for certificate issuance and revocation cannot be used with ACME.
-
All ACME operations are performed over the peers protocol. Thus it is perfectly possible to use an external RA running EJBCA as an ACME proxy.
-
Validators for CAA checking ect. are configured as described in Validators.
-
You need to set up separate aliases for each end entity profile/certificate profile and CA.
Configuration
Enabling ACME
The ACME protocol is by default disabled. To enable the service, go to Admin Web > System Configuration > Protocol Configuration and select Enable for ACME.
Managing ACME Configurations
Much like other protocols in EJBCA, several different ACME configurations can be maintained at the same time using aliases.
To configure ACME, select ACME Configuration under the System Configuration menu.
Global Fields
The following fields are defined globally for all ACME operations.
Field |
Description |
Default ACME Configuration |
The configuration to use if the specified alias doesn't exist. |
Replay Nonce Validity Number |
Defines the validity in milliseconds of a generated replay nonce. |
Alias Specific Fields
The following lists ACME specific for each individual alias:
Field |
Description |
End Entity Profile |
The end entity profile to use for end entities enrolled using this alias. The CA signing the certificate is the default CA of this end entity profile, and the certificate profile used for the certificate is the default certificate profile of this end entity profile. |
Pre-Authorization Allowed |
Pre-authorization, as defined in section 7.4.1 of the draft. |
Require External Account Binding |
External Account Binding, as defined in section 7.3.5 of the draft. |
Wildcard Certificate Issuance Allowed |
Whether this alias can be used to issue certificates with wildcard DNS names in their SANs. See section 7.1.3 of the draft. |
Site URL |
URL to a website describing this CA, optional. See section 7.1.1 of the draft. |
Terms of Service URL |
URL to your terms of service for ACME, optional. See section 7.1.1 of the draft. |
Terms of Service Requires New Approval |
Specifies whether users must approve the new version if the Terms of Service URL is changed. |
DNS Resolver |
A specified DNS resolver, will be used when processing dns01 challenges. |
Trust Anchor (DNSSEC) |
The ICANN trust anchor, configurable should it ever change. |
End Entity Profile Configuration
The following settings should be used for an end entity profile used with ACME:
|
Option |
Should be |
|
Username |
Auto-generated |
|
Password (or Enrollment Code) |
Leave empty |
|
Batch generation (clear text pwd storage) |
Use |
|
End Entity E-mail |
Use, Required, Modifiable |
Subject DN Attributes |
CN, Common name |
Required, Modifiable |
|
Default Certificate Profile |
<The certificate profile to use> |
|
Default CA |
<The CA signing the certificate> |
|
Default Token |
User Generated |
Authentication and Validation
EJBCA currently supports the two validation methods defined in section 8 of the draft: http01 and dns01.
HTTP Challenge (http01)
If the client chooses to use the http01 challenge type, it intends to prove that it controls the domain requested in the certificate by provisioning a resource under the same domain name. As per the draft, EJBCA will send out a challenge to the client, which the client will sign using it's private key and provide on the domain in a known location for EJBCA to retrieve. EJBCA will then be able to use the public key provided in the original request to verify domain control.
DNS Challenge (dns01)
If the client instead chooses to use the dns01 challenge type, it instead obligates itself to supply a TXT record on the containing the same token response as described above. As per the draft, DNSSEC is required for dns01 challenges.
Compatibility with ACME Clients
EJBCA is compatible with the following ACME clients (taken from Letsencrypt's list of compatible ACME clients):
EJBCA ACME with Certbot
Certbot used to be Let's Encrypt's official client, but is now maintained by the Electronic Frontier Foundation. It is one of the most used ACME clients. This client supports issuance, renewal and revocation operations, which are all supported by EJBCA. Documentation is available here.
By default it uses Let's Encrypts servers, but you can use the --server option to specify an alternative server URL:
--server https:
//localhost:8442/ejbca/acme/directory
You may also use the "server" option in cli.ini.
EJBCA ACME with PJAC
Porunov Java ACME Client (PJAC) is an application based on acme4j , a Java ACME library implementation. To try out EJBCA with PJAC, follow this guide:
https://github.com/porunov/acme_client/wiki/Get-a-certificate-for-multiple-domains
but configure PJAC to have EJBCA instance as its ACME service by adding extra parameter
-u https:
//localhost:8442/ejbca/acme/directory
to every acme_client.jar command execution, for example step 5 in the guide would look like this:
java -jar acme_client.jar --
command
register -a
/etc/pjac/account
.key
--with-agreement-update -u https:
//localhost
:8442
/ejbca/acme/directory
EJBCA ACME with ACME Tiny
-
git clone https:
//github.com/diafygi/acme-tiny.git
-
Change EJBCA ACME urls
-DEFAULT_CA =
"https://acme-v02.api.letsencrypt.org"
# DEPRECATED! USE DEFAULT_DIRECTORY_URL INSTEAD
-DEFAULT_DIRECTORY_URL =
"https://acme-v02.api.letsencrypt.org/directory"
+
+DEFAULT_CA =
"https://{ejbca_url}:8442"
# DEPRECATED! USE DEFAULT_DIRECTORY_URL INSTEAD
+DEFAULT_DIRECTORY_URL =
"https://{ejbca_url}:8442/ejbca/acme/directory"
-
Prepare input for ACME
# Generate
private
key
openssl genrsa
4096
> account.key
# Generate CSR
openssl req -
new
-sha256 -key account.key -subj
"/emailAddress=acme_test@primekey.com/CN=my.acme"
> account.csr
-
Launch ACME Tiny (Tested with Python2)
sudo python acme_tiny.py --account-key ./account.key --csr ./account.csr --acme-dir ./acme-dir/ --contact
'mailto:acme@primekey.com'
> ./signed_chain.crt
where --acme-dir ./acme-dir/ - might be integrated/point to your current web server (eg. Apache2 /var/www/html/.well-known/acme-challenge/)
Workflow Examples
The following is list of ACME calls to perform to get a certificate:
getDirectory request
just for verifying that EJBCA ACME service is up and running
GET /acme/directory HTTP/
1.1
{
"newNonce"
:
"https://footrust.local:8443/ejbca/acme/newNonce"
,
"newAccount"
:
"https://footrust.local:8443/ejbca/acme/newAccount"
,
"newOrder"
:
"https://footrust.local:8443/ejbca/acme/newOrder"
,
"newAuthz"
:
"https://footrust.local:8443/ejbca/acme/newAuthz"
,
"revokeCert"
:
"https://footrust.local:8443/ejbca/acme/revokeCert"
,
"keyChange"
:
"https://footrust.local:8443/ejbca/acme/keyChange"
,
"meta"
:{
"termsOfService"
:
"https://footrust.com/acme/terms"
,
"website"
:
"https://footrust.com"
,
"caaIdentities"
:[
"footrust.com"
],
"externalAccountRequired"
:
false
}
}
newAccount
to create a new ACME account to EJBCA. EJBCA uses public key to verify the JWS (i.e., the "jwk" element of the JWS header) to authenticate future requests from the account. EJBCA supports RSA and EC key types.
POST https:
//localhost:8442/ejbca/acme/newAccount HTTP/1.1
Content-Type: application/jose+json
{
"protected"
: base64url({
"alg"
:
"ES256"
,
"jwk"
: {...},
"nonce"
:
"6S8IqOGY7eL2lsGoTZYifg"
,
"url"
:
"https://example.com/acme/newAccount"
}),
"payload"
: base64url({
"termsOfServiceAgreed"
:
true
,
"contact"
: [
"mailto:cert-admin@example.com"
,
"tel:+12025551212"
]
}),
"signature"
:
"RZPOnYoPs1PhjszF...-nh6X1qtOFPB519I"
}
newOrder request
to create a new ACME order
POST /acme/newOrder HTTP/
1.1
Content-Type: application/jose+json
{
"protected"
: base64url({
"alg"
:
"ES256"
,
"kid"
:
"https://example.com/acme/acct/1"
,
"nonce"
:
"5XJ1L3lEkMG7tR6pA00clA"
,
"url"
:
"https://example.com/acme/new-order"
}),
"payload"
: base64url({
"identifiers"
: [
{
"type"
:
"dns"
,
"value"
:
"example.com"
}
],
"notBefore"
:
"2016-01-01T00:00:00Z"
,
"notAfter"
:
"2016-01-08T00:00:00Z"
}),
"signature"
:
"H6ZXtGjTZyUnPeKn...wEA4TklBdh3e454g"
}
newOrder response contains info about challenges. You can read more about challenges from here.
newAuthz request
POST /acme/newAuthz HTTP/
1.1
Host: example.com
Content-Type: application/jose+json
{
"protected"
: base64url({
"alg"
:
"ES256"
,
"jwk"
: {...},
"nonce"
:
"uQpSjlRb4vQVCjVYAyyUWg"
,
"url"
:
"https://example.com/acme/newAuthz"
}),
"payload"
: base64url({
"identifier"
: {
"type"
:
"dns"
,
"value"
:
"example.net"
}
}),
"signature"
:
"nuSDISbWG8mMgE7H...QyVUL68yzf3Zawps"
}
challengeResponse request
To prove to EJBCA's ACME service that you possess control over the domain
POST /acme/acct/{accountId}/authz/{authorizationId}/{challengeId} HTTP/
1.1
Content-Type: application/jose+json
{
"protected"
: base64url({
"alg"
:
"ES256"
,
"kid"
:
"https://example.com/acme/acct/1"
,
"nonce"
:
"Q_s3MWoqT05TrdkM2MTDcw"
,
"url"
:
"https://example.com/acme/authz/1234/0"
}),
"payload"
: base64url({}),
"signature"
:
"9cbg5JO1Gf5YLjjz...SpkUfcdPai9uVYYQ"
}
finalizeOrder request
To generate the certificate
POST /acme/acct/{accountId}/orders/{orderId}/finalize HTTP
1.1
Content-Type: application/jose+json
{
"protected"
: base64url({
"alg"
:
"ES256"
,
"kid"
:
"https://example.com/acme/acct/1"
,
"nonce"
:
"MSF2j2nawWHPxxkE3ZJtKQ"
,
"url"
:
"https://example.com/acme/order/asdf/finalize"
}),
"payload"
: base64url({
"csr"
:
"MIIBPTCBxAIBADBFMQ...FS6aKdZeGsysoCo4H9P"
,
}),
"signature"
:
"uOrUfIIk5RyQ...nw62Ay1cl6AB"
}
Response to finalizeOrder call is the certificate
Status Codes
HTTP Status Code |
Description |
200 |
Success |
201 |
Created |
204 |
No content |
400 |
Bad request |
401 |
Unauthorized |
403 |
Forbidden |
404 |
Not found |
409 |
Conflict |