EJBCA REST Interface Tutorial

Automating the creation of certificates through the EJBCA REST interface can be demonstrated using tools such as Postman or SoapUI. Of course, this can then be implemented in the desired programming language or script. I will try to explain everything step by step, but it is still necessary to have some basic knowledge of EJBCA, administrative access to it and understand basic REST API concepts.

Prerequisites

In order for the REST Interface and Swagger UI to be active, in addition to a working EJBCA, it is necessary to do the following:

  1. For Swagger UI the EJBCA must be built in non-production mode

To build the EJBCA in non-production mode, set ejbca.productionmode=false in the conf/ejbca.properties file. If this was not set, it needs to be changed and the EJBCA redeployed.

  1. Activate REST in System Configuration

REST is disabled by default. It can be enabled in Admin WebSystem ConfigurationProtocol Configuration. To display the Swagger UI, at least REST Certificate Managementmust be enabled. I will also enable REST End Entity Management, as it will be needed later.

After these steps, Swagger UI can be found at localhost:8443/ejbca/swagger-ui.

REST calls (with Postman)

For GET requests, any Web Browser is sufficient. The following URL can simply be opened to check which CAs exist in the EJBCA.

https://localhost:8443/ejbca/ejbca-rest-api/v1/ca

The #MainProblem for beginners: TLS/mTLS

Now when the same URL is called via Postman (or some other application/script), SSL Errors are received:

  • Self signed certificate in certificate chain or
  • BAD CERTIFICATE

Those who want to understand these errors should read the previous post, everything is covered in detail there. I’m just going to do two things here:

  1. Add the TLS CA certificate to trusted certificates/Trust Store.
    In the context of EJBCA, this would be the Management CA certificate. In my case it is the Dragan CA certificate.
  2. Add a TLS client certificate that has appropriate access rights.
    Since the only TLS client I currently have is SuperAdmin, I’ll choose that one.

This step should be relatively easy to implement if you develop your own application. Try searching for “How to implement mTLS in {myProgrammingLanguage}”.

Where we left off

Now that REST calls work through Postman, parameters can be sent and other HTTP methods can be used.

Entity creation

In order for the EJBCA to create Certificates for a specific entity, that entity must first be registered in the EJBCA. This can be done manually through Admin WebRA FunctionsAdd End Entity.

Also, the same can be done with a REST call to:

https://localhost:8443/ejbca/ejbca-rest-api/v1/endentity

Let’s give it a try, I definitely need a TLS Client Key Store for Postman. It is not recommended to use SuperAdmin for everything, many forget that.

The previously shown form Add End Entity, is dynamically generated and changes depending on the selected profile. All the fields shown there should be sent as parameters in the request body. So I’m sending this request using the POST method this time.

POST https://localhost:8443/ejbca/ejbca-rest-api/v1/endentity
{
  "username": "SuperPostman",
  "password": "Fooo1234",
  "subject_dn": "CN=Postman,O=DX,C=BA",
  "ca_name": "DraganCA",
  "certificate_profile_name": "TLS_CLIENT",
  "end_entity_profile_name": "TLS_CLIENT",
  "token": "P12"
}

The response in case of an error is clear at this point. If this protocol was not activated, an “This service has been disabled.” error will be received. If everything went well, a 200 OK is received and a new entity in the EJBCA is created.

The prerequisite for the following REST call to work is that the entity exists and that its status is NEW.

Key Store (Key + Certificate) creation

If you don’t know what a Key Store is, you should immediately read HTTPS, SSL and TLS Explained. If you have already read that and know that these are keys that we receive from the CA (EJBCA) itself with the corresponding certificate, we can continue. To create a Key Store in Swagger there is this call:

https://localhost:8443/ejbca/ejbca-rest-api/v1/certificate/enrollkeystore

As the entity is created, only the following needs to be specified in the request body.

{
  "username": "SuperPostman",
  "password": "Fooo1234",
  "key_alg": "RSA",
  "key_spec": "2048"
}

The response should contain certificate, serial_number, response_format and certificate_chain.

When the value of certificate is Base64 decoded, a P12 Key Store file is obtained. It is literally possible to copy the content of certificate into Notepad++, select everything, go to PluginsMIME ToolsBase64 Decode and save it as a SuperPostman.p12 file for example. Congrats, you have just generated your first Key Store via the EJBCA REST interface.

The manual equivalent of this request would be RA WebEnrollUse Username.

Certificate creation

If a higher level of security is required, a different approach is used. To avoid having the private key in a file (where it can be exported and copied), it can be generated in a USB Tokens or Smart Card (from which it cannot be extracted or copied). In this case, it is necessary to generate a CSR and use:

https://localhost:8443/ejbca/ejbca-rest-api/v1/certificate/pkcs10enroll

To keep things simple, I will generate a TLS Client certificate for a Operator of my Dragan CA. The entity will be created similar as before, but I will not use Smart Cards. Just simple OpenSSL commands that generate a Private Key and a CSR file. If smart cards, applets, domain controller configuration and so on… were included here, this post would be endless. So let’s continue.

It is very important for the entity to set the Token as user generated. So the call to create the entity will look like this:

POST https://draganca:8443/ejbca/ejbca-rest-api/v1/endentity
{
  "username": "DXOperator",
  "password": "Fooo1234",
  "subject_dn": "CN=DXOperator,O=DX,C=BA",
  "ca_name": "DraganCA",
  "certificate_profile_name": "TLS_CLIENT",
  "end_entity_profile_name": "TLS_CLIENT",
  "token": "USERGENERATED"
}

With the following commands I created a RSA 2048 key and a CSR for it.

openssl genrsa -out DXOperator.key
openssl req -sha256 -new -subj "/C=BA/O=DX/CN=DXOperator" -key DXOperator.key -out DXOperator.csr

This is the request. Of course, I didn’t write the whole CSR here, just the shortened “MIICh…V8shQ==”.

POST https://localhost:8443/ejbca/ejbca-rest-api/v1/certificate/pkcs10enroll
{
  "certificate_request": "MIICh...V8shQ==",
  "certificate_profile_name": "TLS_CLIENT",
  "end_entity_profile_name": "TLS_CLIENT",
  "certificate_authority_name": "DraganCA",
  "username": "DXOperator",
  "password": "Fooo1234",
  "include_chain": true,
  "response_format": "DER"
}

The response should again contain certificate, serial_number, response_format and certificate_chain. And this time when the certificate value is Base64 decoded and saved as a CER (e.g. DXOperator.cer) file, we get a certificate that can be used in combination with its keys.

The manual equivalent of this request would be RA WebEnrollMake New Request. And then for Key-pair generation select Provided by user.

Renewing existing certificates

Entities for which certificates are generated are given the status GENERATED. If the entity already has the status GENERATED and a new certificate needs to be created for it, the status must be changed back to NEW. This is done using:

https://localhost:8443/ejbca/ejbca-rest-api/v1/endentity/{endentity_name}/setstatus

My SuperPostman certificate is expiring soon. But if I try enrollkeystore, I get “Got request with status GENERATED (40). Status NEW, FAILED or INPROCESS required: SuperPostman.” So it is necessary to do the following.

POST https://localhost:8443/ejbca/ejbca-rest-api/v1/endentity/SuperPostman/setstatus
{
  "password": "Fooo1234",
  "token": "P12",
  "status": "NEW"
}

After this, it is possible to do enrollkeystore again and get a new Key Store.

The manual equivalent of this would be to find the entity through Admin Web and edit it, so that the status is set to NEW.

Disclaimer

Non-Production Mode/Swagger UI

Usually PKI systems have multiple environments, so in addition to production we have development or test, these are the only environments where Swagger should be enabled. The EJBCA in production should have an ejbca.productionmode=true entry in the configuration, or omitted, as it is the default mode.

Fooo1234

I used Fooo1234 for all passwords, never use passwords like this in real production systems. This password is a logical evolution of the famous foo123, after Utimaco introduced a minimum of 8 characters.

Programming languages

A programming language with HTTP support must be chosen if you want to create your own application. With Python it would be the easiest in my opinion.

Foreign influence

This post was not funded or influenced by my current employer or Keyfactor/PrimeKey itself. More precisely, it arose only out of a need to demonstrate this functionality, which is a huge problem for many to implement. I hope it will help others, as well as me, if needed in the future.

More Info: docs.keyfactor.com

Leave a Reply

Your email address will not be published. Required fields are marked *