The following covers configuration of EST in RA Mode.

Configuring Aliases in RA Mode

This covers configuring aliases in RA Mode.

Giving access to EST in RA mode enables RAs to issue certificates very freely, with the contents for Subject DN and altName defined by the request sent by the RA. You can limit allowed certificate fields and content using end entity and certificate profiles, but RA mode should typically be used only for trusted RAs.

The following displays the EST alias configuration screen (System Configuration > EST Configuration).

The following lists available EST alias configuration options.

ValueDescription
RA Name Generation SchemeDN: Will take a part of the request DN, and use it as the username (use the list to choose which parts). Several DN attributes can be specified to have fall-back. For example: UID;SN;CN. First, try UID. If it does not exist try SN, etc.
RANDOM: Will generate a 12 character long random username.
FIXED: Enter the DN attributes manually as a semicolon delimited String (e.g. CN;UID;SN), instead of adding the values via the Add button when the DN radio button is selected.
USERNAME: Use entire request DN as username.
RA Name Generation PrefixSpecify a prefix to the generated username. '${RANDOM}' can be used to have a 10 random chars as prefix.
RA Name Generation PostfixSpecify a postfix to the generated username. '${RANDOM}' can be used to have a 10 random chars as postfix.
eThe CA that this alias will issue certificate from.
End Entity ProfileThe End Entity Profile that enrolling end entities will have applied to them. This defines the required DN and altName naming fields.
Certificate ProfileThe Certificate Profile that enrolling end entities will have applied to them. This controls the certificate type, that is, key usage and other extensions.
Require Client CertificateSpecifies if a client certificate is required to enroll. The client certificate does not need to be known by EJBCA (if the option web.reqcertindb in conf/web.properties is set to false), but the issuing CA is. The client certificate needs to belong to a Role with full RA rights.
Client username/passwordSets a username and password to enroll. The username will be given full RA rights. If a client certificate is required, both client certificate and username/password will be checked for initial enrollment. For Renewal (re-enroll) username and password are never required, but client certificate is always required.
Certificate Renewal with Same KeysIf Allow is selected, a re-enrollment request may be performed for the same public key as before. Note that client certificate is always required for renewal, while username/password is never required, regardless of the settings above.
Enable server side key generationThis enables server side key generation via the serverkeygen functionality as per RFC 7030 for the corresponding alias.


Although you can configure an EST alias without client username and without requiring client certificate, such an EST alias cannot be used since either certificate or username/password authentication is required for the initial enrollment.

Network Ports and TLS Client Certificate Authentication

Using EST can be challenging from a network configuration point of view. Some calls such as cacerts can be performed over TLS, but with no requirement of client certificate authentication. The call simpleenroll can be performed over TLS, with or without client certificate authentication (see configuration options above). A call to simplereenroll however always requires client certificate authentication to authenticate with the clients current certificate, in order to automatically approve renewal and issuance of a new certificate. For serverkeygen i.e. for server side key generation, the first call must be with RA administrative certificate authentication or with basic authentication with username/password as configured in alias. Subsequent calls to serverkeygen can happen with RA credentials i.e. certificate or username or enrolled keypair and certificate. Administrator needs to enable server side key generation functionality for individual aliases.

EJBCA offers different installation options, such as direct server deployment in Wildfly, containers, software and hardware appliances. The port for EST communication needs to be chosen carefully based on the installation type.

In the case of direct server deployment, you can set up TLS and client certificate authentication in Wildfly in the following ways:

  • 3-port separation:
    • port 8080: without TLS support for non-confidential public communication
    • port 8442: TLS with only server authentication
    • port 8443: TLS with server and client authentication (m-TLS)
  • 2-port separation:
    • port 8080: without TLS support for non-confidential public communication
    • port 8443: TLS with server and client authentication (m-TLS)

For 3-port separation, port 8442 is to used for communications without certificate authentication, and port 8443 when certificate authentication or m-TLS is needed. In RA mode, certificate authentication may be mandated for specific EST aliases or configurations. This allows secure initial enrollment or the simpleenroll operation. Note that the EST simplereenroll operation always needs certificate authentication.

For 2-port separation, port 8443 can be used for all scenarios.

The network configuration is less complicated when using a hardware or software appliance, where EST can be used without mentioning a port, e.g. https://ejbca.example.com. This is applicable to both with and without client certificate authentication. The proxy in front of EJBCA allows optional client authentication similar to a 2-port separation but with default HTTP port 80 and HTTPS port 443. Thus, all HTTPS communication is subject to optional client authentication. 

If using a proxy in front of JBoss/WildFly you can enable EST working on the single TLS port (i.e. a simple URL like https://ejbca.example.com/), by making client certificate authentication optional. Such and endpoint proxy configuration is easy to do with Apache or Nginx and is used in PrimeKey's Appliance and Cloud products.

Testing - Client Interoperability

Cisco libest

Clone libest from Cisco and build according to instructions:

$ cd examples/client

$ # via environment specify the initial CA certificate to use for verifying TLS connection.
$ cp <path to server cert> server.pem
$ export EST_OPENSSL_CACERT=server.pem

$ # Where to save certs
$ mkdir certs

$ # Optionally get new CA certificates
$ ./estclient -g -s <ip or hostname to EJBCA> -p 8442 -o certs --pem-output

$ # certs should now contain a cacert-0-0.pem file
$ # enroll with CA. publicCert.pem and privetKey.pem are the TLS client cert I wish to use for auth. RequestDN will be 'CN=myclient'
$ ./estclient -e -s <ip or hostname to EJBCA> -p 8443 -o certs -c publicCert.pem -k privateKey.pem -u estadmin -h foo123 --pem-output --common-name myclient

$ # certs will now contain a cert-0-0.pem and key-x-x.pem
$ # client cert is about to expire, reenroll, requires client certificate authentication to the server
$ ./estclient -r -s <ip or hostname to EJBCA> -p 8443 -o tmp -c tmp/cert-0-0.pem -k tmp/key-x-x.pem --pem-output

$ # certs should now contain an updated cert-0-0.pem

# for server side key generation
# first we generate a private key 
openssl req -nodes -newkey rsa:2048 -keyout device.key -out device.csr -outform DER -subj "/CN=myclient_forkeygen"

# then use the -q option for serverkeygen along with the generated key in previous step
./estclient -q -s <ip or hostname to EJBCA> -p 8442 -o outputDir -u estadmin -h foo123 --pem-output --common-name myclient_forkeygen  -x device.key -v 
# outputDir will now contain a cert-0-0.pem and key-0-0.pem, but we need to add We need to add -----BEGIN RSA PRIVATE KEY----- header and -----END RSA PRIVATE KEY----- footer 
# manually to private key file key-0-0.key to use it during reenroll or to verify with openssl.

# inspect the generated key used in request and notice the modulus is different as mentioned in certificate
openssl rsa -in device.key -check -text
# but it is same as the private key received in response
openssl rsa -in outputDir/key-0-0.key -check -text

# for subsequent key generation: 
./estclient -q -s 127.0.0.1 -p 8443 -o outputDir2 --pem-output --common-name registered_client -x device.key -v -c "outputDir/cert-0-0.pem" -k "outputDir/key-0-0.key"
BASH

Curl

You can also test access to EST URLs using curl commands.

Here is a full work-flow example using CURL, where initial enrollment uses username/password EST authentication, and re-enroll using the existing client certificate.

# Get CA certificates
curl https://<hostname to EJBCA>:8442/.well-known/est/<name of alias>/cacerts -o cacerts.p7 --cacert ManagementCA.cacert.pem

# Generate a key and CSR for a "device"
# Make sure the subject DN and subject alternative name matches the end entity profile.
openssl req -nodes -newkey rsa:2048 -keyout device.key -out device.csr -outform DER -subj "/CN=123456789"
openssl base64 -in device.csr -out device.b64 -e

# Make initial enrollment, using EST password authentication (client certificate is also possible)
curl -v --cacert ManagementCA.cacert.pem --user estadmin:foo123 --data @device.b64 -o device-p7.b64 -H "Content-Type: application/pkcs10" -H "Content-Transfer-Encoding: base64" https://<hostname to EJBCA>:8442/.well-known/est/<name of alias>/simpleenroll

# Convert the response into a PEM encoded certificate
openssl base64 -in device-p7.b64 -out device-p7.der -d
openssl pkcs7 -inform DER -in device-p7.der -print_certs -out device-cert.pem

# Generate a new key and CSR for the device, to renew with
openssl req -nodes -newkey rsa:2048 -keyout device-new.key -out device-new.csr -outform DER -subj "/CN=123456789"
openssl base64 -in device-new.csr -out device-new.b64 -e

# Re-enroll by the device, authenticating with the existing key/certificate
curl -v --cacert ManagementCA.cacert.pem --key device.key --cert device-cert.pem --data @device-new.b64 -o device-new-p7.b64 -H "Content-Type: application/pkcs10" -H "Content-Transfer-Encoding: base64" https://<hostname to EJBCA>:8443/.well-known/est/<name of alias>/simplereenroll

# Convert the response into a PEM encoded certificate
openssl base64 -in device-new-p7.b64 -out device-new-p7.der -d
openssl pkcs7 -inform DER -in device-new-p7.der -print_certs -out device-new-cert.pem
CODE

ManagementCA.cacert.pem is the Root CA certificate of the CA chain that issued the TLS server cert and needs to be configured with curl in order for the TLS connection to be established. ManagementCA is the name in a default EJBCA installation and the cert can be downloaded from the CA UI or RA UI. The examples above use port 8442 for TLS with server authentication, and port 8443 for TLS with both client and server authentication (when using a client authentication certificate and private key). The standard TLS port, 443, is used when running an Apache proxy in front or EJBCA, such as is the case with an EJBCA Enterprise Cloud instance or a PrimeKey PKI Appliance. For EJBCA Enterprise Cloud instances or the PrimeKey PKI Appliance, port 443 will work for calls with or without client certificate authentication.

You can also authenticate as EST admin using a client certificate. The command is slightly different, using certificate authentication in addition to the username/password:

# Enroll
$ curl -v --cacert ManagementCA.cacert.pem --user estadmin:foo123 --cert ra-cert.pem --key ra-key.pem --data @device.b64 -o device-p7.b64 -H "Content-Type: application/pkcs10" \
-H "Content-Transfer-Encoding: base64" https://<hostname to EJBCA>/.well-known/est/simpleenroll

# Re-enroll
$ curl -v --cacert ManagementCA.cacert.pem --key device.key --cert device-cert.pem --data @device-new.b64 -o device-new-p7.b64 -H "Content-Type: application/pkcs10" -H "Content-Transfer-Encoding: base64" https://<hostname to EJBCA>/.well-known/est/simplereenroll
CODE

For server side key generation using curl, first ensure "Enable server side key generation" is checked in the alias; then,

serverkeygen ra

# follow the same steps as simpleenroll to generate the base64 encoded csr
openssl req -nodes -newkey rsa:2048 -keyout device.key -out device.csr -outform DER -subj "/CN=123456789"
openssl base64 -in device.csr -out device.b64 -e

# send request to server
curl -v --cacert ManagementCA.cacert.pem --user estadmin:foo123 --data @device.b64 -o device-keypair -H "Content-Type: application/pkcs10" -H "Content-Transfer-Encoding: base64" https://172.17.2.104:8442/.well-known/est/est/serverkeygen

# we may manually parse the contents of device-keypair file and split it to separate files for key and certificate or use the script in mentioned below
./parse_server_keygen_response device-keypair

# inspect the generated key used in request and notice the modulus is different as mentioned in certificate
openssl rsa -in device.key -check -text
# but it is same as the private key received in response
openssl rsa -in enrolled-key.key -check -text
 
# parse the certificate response similar to during simpleenroll
openssl base64 -in device-p7.b64 -out device-p7.der -d
openssl pkcs7 -inform DER -in device-p7.der -print_certs -out device-cert.pem
openssl x509 -in device-cert.pem -noout -text

### reenroll or subsequent key generation port 8443 is used for mutual TLS with the key and certificate generated previously
curl -v --cacert ManagementCA.cacert.pem --cert device-cert.pem --key enrolled-key.key --data @device.b64 -o device-keypair2 -H "Content-Type: application/pkcs10" -H "Content-Transfer-Encoding: base64" https://127.0.0.1:8443/.well-known/est/est/serverkeygen
BASH

The script to separate the serverkeygen response into private key and certificate is available here 

Perl EST Client

There is a very complete Perl EST client and test suite at https://github.com/killabytenow/pest.

Example workflow using pest enrolling a device against an EST alias authenticated with username/password. The pest client also supports client certificate authentication.

./pest --url https://localhost:8442/.well-known/est/estnew -C ~/tmp/ManagementCA.cacert.pem -O -o output cacerts
./pest --url https://localhost:8442/.well-known/est/estnew -C ~/tmp/ManagementCA.cacert.pem -u estadmin:foo123 -s "/CN=123456/O=PrimeKey/C=SE" -O -o output -B simpleenroll
TEXT

Renewal is done using TLS client certificate authentication, using the old certificate and private key.

./pest --url https://localhost:8443/.well-known/est/estnew -C ~/tmp/ManagementCA.cacert.pem -c output/enroll-001.pem -k output/private.key -O -o output_new -B simplereenroll
CODE

You can also request a name change using the pest client, which results in a 400 Bad Request from EJBCA since the renewed certificate must have the same subject DN as the old one used for TLS authentication.

./pest --url https://localhost:8443/.well-known/est/estnew -C ~/tmp/ManagementCA.cacert.pem -c output/enroll-001.pem -k output/private.key -s "/CN=987654/O=PrimeKey/C=SE" -O -o output_new -B simplereenroll
CODE

If using a proxy in front of JBoss/WildFly you can enable EST working on the single TLS port (i.e. a simple URL like https://ejbca.example.com/). Such and endpoint proxy configuration is easy to do with Apache or Nginx and is used in PrimeKey's Appliance and Cloud products.

Workflow Example

Example enrollment, where an RA gets CA certificate first and then gets a client certificate, using username/password authentication (the EST client acts as an RA). Next, the client performs a renewal, authenticating with the client certificate issued previously.

EST configuration is an EST alias with the name est and the following settings:

Setting

Value

EST Operational ModeRA

Default CA

EST CA

End Entity Profile

EST EE Profile (with only CN required DN attribute)

Certificate Profile

Profile Default

Require Client Certificate

false

Client Username

estadmin

Client Password

foo123

Certificate Renewal with Same Keys

false

Download the CA certificate of the EJBCA TLS connection (usually the default is Management CA), and set the environment variable needed for estclient:

$ export EST_OPENSSL_CACERT=/tmp/ManagementCA.cacert.pem
BASH

Run the following estclient commands to generate a key and get a certificate from the CA:

$ mkdir certs

# Get CA certificate, by "RA:
$ ./estclient -g -s 127.0.0.1 -p 8442 -o certs --pem-output

# Inspect the fetched CA certificate 
$ openssl x509 -in certs/cacert-0-0.pem -text -noout

# Get client certificate, by "RA", authenticated with username/password
$ ./estclient -e -s 127.0.0.1 -p 8442 -o certs -u estadmin -h foo123 --pem-output --common-name myclient

# Inspect the fetched client certificate 
$ openssl x509 -in certs/cert-0-0.pem -text -noout

# Re-enroll, directly by the client when certificate is about to expire, using the old client cert to authenticate with:
$ ./estclient -r -s 127.0.0.1 -p 8443 -o certs -c certs/cert-0-0.pem -k certs/key-x-x.pem -u estadmin -h foo123 --pem-output

# Inspect the new, renewed, client certificate  
$ openssl x509 -in certs/cert-0-0.pem -text -noout

# Revoke the clients certificates by going to CA UI and using Search End Entities to find the end entity and revoke certificates.
# Try to re-enroll again, which will not work with a revoked client certificates.
$ ./estclient -r -s 127.0.0.1 -p 8443 -o certs -c certs/cert-0-0.pem -k certs/key-x-x.pem --pem-output

# Enroll with an EC key. First we have to generate the key, a Prime256v1 key on this case, and then use this key for enrollment.
openssl ecparam -name prime256v1 -genkey -noout -out prime256v1-key.pem
./estclient -e -s 127.0.0.1 -p 8442 -o certs -u estadmin -h foo123 --pem-output --common-name myclient -x prime256v1-key.pem
$ openssl x509 -in certs/cert-0-0.pem -text -noout

# Re-enroll, also with EC, using the same key (using the same key can be dissalowed in the EST alias).
./estclient -r -s 127.0.0.1 -p 8443 -o certs -c certs/cert-0-0.pem -k prime256v1-key.pem --pem-output -x prime256v1-key.pem
$ openssl x509 -in certs/cert-0-0.pem -text -noout
BASH