ACME

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.

    ACME Reference

    Each EJBCA release is bundled with an auto-generated ACME reference available on the URL https://localhost:8442/ejbca/doc/acme/ if deployed, or online on www.ejbca.org/docs/acme.

    images/download/attachments/23856584/image2018-10-9_10-55-10.png

    Swagger UI

    Swagger UI allows you to visualize and interact with the API’s resources. The Swagger UI playground is available in your browser on the URL https://localhost:8443/ ejbca/swagger-ui (use port 8443 since ACME uses client certificate authentication).

    You can switch between displaying ACME or the REST API using the Swagger UI Select a spec list.

    images/download/attachments/23856584/image2018-10-9_10-57-19.png

    • Swagger UI is only available if you build EJBCA in non-production mode, i.e. with ejbca.productionmode=false set in conf/ejbca.properties.

    • The Swagger UI for ACME will only be available if ACME is activated as a protocol, see Enabling ACME.

    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.

    7.1.1

    newNonce

    /ejbca/acme/newNonce

    Before any POST action is performed, the client needs to retrieve an anti-replay nonce from the server.

    7.2

    newAccount

    /ejbca/acme/newAccount

     

    7.3

    updateAccount

    /ejbca/acme/acct/{accountId}

     

    7.3.2

    newOrder

    /ejbca/acme/newOrder

     

    7.4

    challengeResponse

    /ejbca/acme/acct/{accountId}/authz/{authorizationId}/{challengeId}

     

    7.5.1

    newAuthz

    /ejbca/acme/newAuthz

    Only if Pre-Authorization Allowed is enabled in the Alias configuration.

    7.4.1

    finalizeOrder

    /ejbca/acme/acct/{accountId}/orders/{orderId}/finalize

     

    7.1.3

    revokeCert

    /ejbca/acme/revokeCert

     

    7.6

    keyChange

    /ejbca/acme/keyChange

     

    7.3.6

    URL Endpoints and Aliases

    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/directory?configurationId=<alias_name>

    Custom alias <alias_name> without client authentication

    https://<server>:8442/ejbca/acme/directory?configurationId=<alias_name>

    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 etc. 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.

    images/download/attachments/23856584/Screen_Shot_2018-08-02_at_14.41.27.png

    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.

    images/download/attachments/23856584/Screen_Shot_2018-08-02_at_14.44.14.png









    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

    Example of ACME Alias configuration.

    images/download/attachments/23856584/acme.jpg

    The following table lists ACME specific fields 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.

    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.

    RequireclientapprovalforTermsof Servicechanges

    Specifies whether users must approve the new version if the Terms of Service URL is changed.

    DNS Resolver

    A specified DNS resolver, used when processing dns01 challenges.

    DNS Port

    Port used for DNS communications.

    DNSSEC Trust Anchor

    The ICANN trust anchor, configurable should it ever change.

    External Account Binding is an optional feature and will not be supported in this release! The corresponding field in the directory output (externalAccountRequired) is false by default and it is not changeable for now.

    End Entity Profile Configuration

    The following settings should be used for an end entity profile used with ACME.

    Field

    Value

    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 http01 and dns01, defined in section 8 of the draft.

    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 its 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 chooses to use the dns01 challenge type, it instead obligates itself to supply a TXT record 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, supporting issuance, renewal and revocation operations, which are all supported by EJBCA. For more information, refer to the Certbot Documentation.

    Certbot by default uses Let's Encrypts servers. To specify an alternative server URL, use the --server option:

    --server https://localhost:8442/ejbca/acme/directory

    Note that you can also use the server option in cli.ini.

    Example Scenarios

    Prerequisites

    The following examples assume that a Ubuntu machine with JBoss 6.4 is used and that EJBCA is accessible under https://localhost:8442 public HTTPS, using certbot 0.26.1.

    First, run the following command in the command line to ensure that a connection to the ACME server is up and running:

    curl -k https://localhost:8442/ejbca/acme/directory

    The successful output of the above command should be as follows (showing the resources available in the EJBCA ACME server), otherwise the scenarios will fail:

    {"newNonce":"https://localhost:8442/ejbca/acme/newNonce","newAccount":"https://localhost:8442/ejbca/acme/newAccount","newOrder":"https://localhost:8442/ejbca/acme/newOrder","revokeCert":"https://localhost:8442/ejbca/acme/revokeCert","keyChange":"https://localhost:8442/ejbca/acme/keyChange","meta":{"termsOfService":"https://example.com/acme/terms","website":"https://www.example.com/","caaIdentities":[],"externalAccountRequired":false}}

    HTTP Validation Scenario

    1. Issue certificate for an identifier (example.com) using HTTP validation:

      Setup a local HTTP server (for example Apache with the default working directory /var/www/html). Add the following virtual host under /etc/apache2/sites-available/example.com.conf:

      <VirtualHost *:80>
      ServerName example.com
       
      DocumentRoot "/var/www/html/"
       
      </VirtualHost>

      Enable the site using the command:

      sudo a2ensite example.com

      Then run:

      sudo service apache2 reload

      Next, restart Apache:

      sudo /etc/init.d/apache2 restart

      Then add the following line to your /etc/hosts file:

      127.0.0.1 example.com
    2. Having Certbot installed on your machine, try the following command (EJBCA should be up and running with ACME enabled and with an ACME alias configured with appropriate end entity profile):

      sudo certbot --no-verify-ssl certonly --webroot -w /var/www/html/ -d example.com --server https://localhost:8442/ejbca/acme/directory

      The command should run successfully and in the display a message similar to the following:

      IMPORTANT NOTES:
       - Congratulations! Your certificate and chain have been saved at:
       /etc/letsencrypt/live/example.com/fullchain.pem
       Your key file has been saved at:
       /etc/letsencrypt/live/example.com/privkey.pem
       Your cert will expire on 2020-08-21. To obtain a new or tweaked
       version of this certificate in the future, simply run certbot
       again. To non-interactively renew *all* of your certificates, run
       "certbot renew"
       - If you like Certbot, please consider supporting our work by:

      Go to EJBCA Admin Web and search for End Entities, there should be one with the status Generated and CN = example.com.

      The error message The client lacks sufficient authorization :: The client lacks sufficient authorization indicates a conflict between the new account creation and existing ACME accounts. To resolve, remove everything under /etc/letsencrypt/live, /etc/letsencrypt/accounts and /etc/letsencrypt/keys and try again.

    3. To revoke the certificate issued in the step above, run the following command:

      sudo certbot --no-verify-ssl --server https://localhost:8442/ejbca/acme/directory revoke --cert-path /etc/letsencrypt/live/example.com/fullchain.pem

      If asked for deleting the just issued certificate, reply with Y. The following success message must be shown:

      Congratulations! You have successfully revoked the certificate that was located at /etc/letsencrypt/live/example.com/fullchain.pem

      Go to EJBCA Admin Web and check the status for the corresponding End Entity certificate and make sure it is revoked.

    4. In order to issue a certificate for a wildcard domain do as follows:
      First you need to enable the wildcard certificate issuance via Acme Configuration alias page.
      Then run the same command as in step two providing a wildcard domain as identifier.

      sudo certbot --no-verify-ssl certonly --webroot -w /var/www/html/ -d *.example.com --server https://localhost:8442/ejbca/acme/directory

      The rest of procedure should be same as above.

    DNS Validation Scenario

    1. Issue certificate for an identifier (allow.klaan.nu) using Domain Name System Security Extensions ( DNSSEC ) validation:
      Make sure you have a DNS server setup which you can add TXT records to. In this example, dnsmasq is used, included in most Linux distributions.

      The EJBCA ACME server currently supports DNSSEC validation and this example uses allow.klaan.nu to be able to pass DNSSEC validation.

    2. To issue the certificate, run the following command in the command line:

      sudo certbot --no-verify-ssl certonly --manual --preferred-challenges=dns -d allow.klaan.nu --server https://localhost:8442/ejbca/acme/directory

      The --manual flag is used to run Certbot interactively and allow preparing the DNS server with the DNS challenge offered by the ACME server.

      Agree to your IP being logged by replying Yes to the following:

      Are you OK with your IP being logged?
      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      (Y)es/(N)o:

      Certbot displays the TXT record challenge offered by the ACME server which have to be provisioned in the DNS server. Before pressing Enter, run the following command to provision the TXT record in dnsmasq:

      sudo dnsmasq --port="1453" --txt-record="_acme-challenge.allow.klaan.nu, pULO3RjCbzqjWH0JK2FQ5BDe-5SI2Eo2Vn1l_fmrtdk" --listen-address="127.0.0.1" --interface="lo" --bind-interfaces

      The port number used above is just an example. Note that the port number must equal the port set for the ACME Alias currently used by the EJBCA ACME server, configured in Admin Web>System Configuration>ACME Configuration. In addition, the DNS Resolver field needs to be set to localhost in the ACME Configuration Alias page, see Alias Specific Fields.

      After running the above command, press Enter in the Certbot command prompt to continue. A message similar to the following is displayed for a successful certificate issuance:

      IMPORTANT NOTES:
       - Congratulations! Your certificate and chain have been saved at:
         /etc/letsencrypt/live/allow.klaan.nu/fullchain.pem
         Your key file has been saved at:
         /etc/letsencrypt/live/allow.klaan.nu/privkey.pem
         Your cert will expire on 2020-08-21. To obtain a new or tweaked
         version of this certificate in the future, simply run certbot
         again. To non-interactively renew *all* of your certificates, run
         "certbot renew"
       - If you like Certbot, please consider supporting our work by:
      
         Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
         Donating to EFF:                    https://eff.org/donate-le
      

      Ensure that the certificate is issued in EJBCA by checking that the Admin Web End Entity Search page includes a row with CN equal to allow.klaan.nu and a valid certificate.

    3. To revoke the certificate issued in the previous step, run:

      sudo certbot --no-verify-ssl --server https://localhost:8442/ejbca/acme/directory revoke --cert-path /etc/letsencrypt/live/allow.klaan.nu/fullchain.pem

      The following message displays if successful:

      Congratulations! You have successfully revoked the certificate that was located
      at /etc/letsencrypt/live/allow.klaan.nu/fullchain.pem

      Make sure that the certificate is revoked with the reason Unspecified in EJBCA by checking its status in the Admin Web End Entity Search page.

    4. To issue a certificate for a wildcard domain do as follows:
      First enable the wildcard certificate issuance via Acme Configuration alias page.
      Then issue the following (example) command.

      sudo certbot --no-verify-ssl certonly --manual --preferred-challenges=dns -d *.allow.klaan.nu --server https://localhost:8442/ejbca/acme/directory

      Rest of the procedure is similar to the above.

    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, just follow these guides for Example scenarios.

    EJBCA is tested with the following PJAC flows:

    • Get a certificate for multiple domains

    • Renew a certificate for multiple domains

    • Get a wildcard certificate

    • Revoke certificate

    • Deactivate account

    • Pre-authorization (does not seem to be part of PJAC, but is supported by underlying acme4j)

    • HTTP01 and DNS01 challenge types

    images/s/en_US/7901/58be3fa11e9ad58113c0ea45e7063389a7c7d344/_/images/icons/emoticons/warning.svg Note that you need to configure PJAC to have the EJBCA instance as its ACME service, by adding an extra '-u' parameter to acme_client.jar command executions:

    -u https://localhost:8442/ejbca/acme/directory

    For example, the 5th step in the Get a certificate for multiple domains guide would look like this:

    Step 5 from the PJAC guide
    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

    1. Clone the repository:

      git clone https://github.com/diafygi/acme-tiny.git
    2. 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"
    3. 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
    4. 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 and/or point to your current web server, for example Apache2 /var/www/html/.well-known/acme-challenge/.

    Workflow Examples

    The following lists ACME calls to perform in order to get a certificate.

    getDirectory request

    Verifies that the 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

    Creates a new ACME account to EJBCA. EJBCA uses a public key to verify the JWS (that is, 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"
    }

    The newOrder response contains information about challenges. For more information, refer to the section 7.5.1 of the draft.

    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"
    }

    The response to the 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