Web Service Interface

Introduction

The JAX-WS 2.0 Web Service Interface is used to access the basic functions remotely over client authenticated HTTPS. The functionality available through the Web Service Interface is documented in the EJBCA Web Service API Reference.

There is also a CLI that can be used for scripting WS calls remotely, see Using the Web Services CLI. Note that all web service calls are not available through the CLI.

When using the WS API, make sure the wsdl-host and modify-wsdl-address are configured as part of the TLS configuration. For more information, see application server-specific instructions on Application Servers.

Web Services through the RA

Using a Peer Connected RA it is possible to run a subset of WS API calls through the RA, which is tried to be executed on the CA first after polling by the CA using Peer Connectors. If the RA itself has active CAs the RA tries to process the requests first local, if not marked otherwise in the list below.

Local key generation and recovery is processed on the RA in every case (see function 'keyRecover').

Role configuration for the user of the WS API is done on the CA, and WS must be enabled in the role used by the Peer Connection for the RA. On the RA it is possible to disable WS in System Configuration.

The subset of API calls available through the RA are:

  • certificateRequest

  • checkRevokationStatus (anytime tried to be processed on the CA first)

  • crmfRequest

  • customLog

  • cvcRequest

  • editUser (anytime tried to be processed on the CA first)

  • findCerts

  • findUser

  • getAvailableCAs

  • getAvailableCAsInProfile

  • getAvailableCertificateProfiles

  • getCertificate

  • getCertificatesByExpirationTime

  • getCertificatesByExpirationTimeAndIssuer

  • getCertificatesByExpirationTimeAndType

  • getLastCAChain

  • getLastCertChain

  • getLatestCRL

  • getProfile

  • getPublisherQueueLength

  • getRemainingNumberOfApprovals

  • isApproved

  • isAuthorized

  • keyRecover (local keystore generation or recovery only processed on the RA)

  • pkcs10Request

  • pkcs12Req

  • republishCertificate

  • revokeCert (anytime tried to be processed on the CA first)

  • revokeCertBackdated (anytime tried to be processed on the CA first)

  • revokeCertWithMetadata (anytime tried to be processed on the CA first)

  • revokeUser

Web Services Authentication

The Web Services interface requires client certificate authentication from administrators, in the same way as the Admin GUI does. If you have a client certificate that works on the Admin GUI, you should also be able to use it for the Web Service interface.

Configuring Web Services Behavior

The sample property file conf/jaxws.properties.sample contains more information on how to configure the behavior of the EJBCA WS. Copy this to conf/jaxws.properties, edit and redeploy.

If the end entity profile information must be used to define default values when you create a user, the option Allow merge DN across all interfaces must be selected in the end entity profile, see End Entity Profiles Fields.

If multiple instances of a component exist, the merge is done from end to beginning, and the remaining values of this component type will be placed at the end.

For example, if you want to merge:

dn=cn=foo,..., dc=dc1, ..., dc=dc2, ...

with

dn=..., dc=mdc1, ..., dc=mdc2, ..., dc=mdc3, ...

the result will be:

dn=cn=foo, ..., dc=mdc1, ..., dc=mdc2, ..., dc=mdc3, ...

Configuring Web Services CLI

Edit the dist/ejbca-ws-cli/ejbcawsracli.properties before running the EJBCA WS CLI. The files contain descriptions of what can be configured. Note that this directory is recreated each time you build EJBCA, so copy it to a separate location if you intend to rebuild or redeploy EJBCA and keep the configuration.

Configuration for the Web Services CLI requires a P12 or JKS keystore. You can try the WS CLI using the superadmin.p12 keystore generated during the installation or generate a new JKS using the Admin GUI.

To create a JKS for a user using the command line, and adding the new user to the superadministrator role, run the following:

bin/ejbca.sh ra addendentity <1> <2> "C=..,O=..,CN=<1>" ManagementCA 1 JKS
bin/ejbca.sh ra setclearpwd <1> <2>
bin/ejbca.sh batch <1>
bin/ejbca.sh roles addmember "Temporary Super Administrator Group" ManagementCA WITHCOMMONNAME EQUALCASEINS <1>

Using the Web Services CLI

The EJBCA Client Toolbox includes a Web Service CLI tool.

To use the Web Service CLI client, copy the directory with all included files to the computer you want to remotely administer from. Then create a JKS or P12 file with the appropriate access rights (see Access rules required when using the Web Service API), and finally configure the file ejbcawsracli.properties. In this file you should specify the hostname of the CA server, the name of the keystore and the password to unlock it. The settings are documented in the file ejbcacsracli.properties.

To list each sub-command, run:

ejbcaClientToolBox.sh EjbcaWsRaCli

To view detailed help on using the CLI, run:

ejbcaClientToolBox.sh EjbcaWsRaCli "subcommand"

Example usage:

ejbcaClientToolBox.sh EjbcaWsRaCli pkcs12req testuser2 foo123 2048 NONE tmp
ejbcaClientToolBox.sh EjbcaWsRaCli revokeendentity testuser2 SUPERSEDED fals

An example workflow of adding an end entity and making a request with a CSR could look like:

./ejbcaClientToolBox.sh EjbcaWsRaCli edituser testuser foo123 false "CN=testuser" NULL NULL ManagementCA 1 USERGENERATED NEW END_ENTITY_PROFILE CERTIFICATE_PROFILE NULL
./ejbcaClientToolBox.sh EjbcaWsRaCli pkcs10req testuser foo123 csr.pem PEM NONE .

The two calls can instead be combined into a single transaction using the efficient certreq WS call:

./ejbcaClientToolBox.sh EjbcaWsRaCli certreq testuser "CN=testuser" NULL ManagementCA END_ENTITY_PROFILE CERTIFICATE_PROFILE csr.pem PKCS10 PEM NONE .

If your CA requires approvals in order to issue certificates, use the two-way process and check if approvals have been completed according to the following example:

./ejbcaClientToolBox.sh EjbcaWsRaCli edituser testuser foo123 false "CN=testuser" NULL NULL ManagementCA 1 USERGENERATED NEW EMPTY ENDUSER NULL
<...>
Waiting for approval: Add Entity request has been added for approval by authorized administrators.
Approval requestID: 1845592727
 
# If you now try to enroll you will get an error, since the above edituser command has not been executed:
./ejbcaClientToolBox.sh EjbcaWsRaCli pkcs10req testuser foo123 ~/tmp/1.csr PEM NONE .
Error: USER_WRONG_STATUS: null
org.ejbca.ui.cli.ErrorAdminCommandException: org.ejbca.core.protocol.ws.client.gen.EjbcaException_Exception: Got request with status GENERATED (40), NEW, FAILED or INPROCESS required: testuser.
 
# You can run a command to check how many approvals are remaining, use this to poll the CA for when the request is approved (don't poll too often though):
./ejbcaClientToolBox.sh EjbcaWsRaCli getremainingnumberofapprovals 1845592727
Approvals remaining: 1
 
# Approve the request in RA GUI (or Admin GUI), and check again:
./ejbcaClientToolBox.sh EjbcaWsRaCli getremainingnumberofapprovals 1845592727
Approvals remaining: 0
 
# Now you can enroll:
./ejbcaClientToolBox.sh EjbcaWsRaCli pkcs10req testuser foo123 ~/tmp/1.csr PEM NONE .

Web Services CLI TLS Debugging

As the WS API and WS CLI use client certificate authentication, both the server and client need to be configured correctly. The WS CLI is configured in the file ejbcawsracli.properties and the server is configured during the installation.

Issues can arise when you use client certificates issued by another CA than the one issuing the server certificate (and you need to add more CAs to the server truststore), or when using a proxy before the CA server (and you need to configure TLS client authentication and pass-through in the proxy).

To troubleshoot, enable TLS debugging to allow printing the full Java TLS debug information when running clientToolBox. To enable the TLS debugging, set the following environment variable before running the CLI:

export JAVA_OPT=-Djavax.net.debug=all
./ejbcaClientToolBox.sh ...

Using the Web Service API for Integration

You can use the Web Service interface to integrate EJBCA from other applications.

If you are using another language than Java, start by downloading the WSDL file at http://hostname:8080/ejbca/ejbcaws/ejbcaws?wsdl. With this you can use your programming language tools to generate client stubs.

When using Java you can find the required libs in dist/ejbcawscli and its lib subdirectory.

To initialize the Web Service using TLS with client Certificate:

CryptoProviderTools.installBCProvider();
String urlstr = "https://localhost:8443/ejbca/ejbcaws/ejbcaws?wsdl";
System.setProperty("javax.net.ssl.trustStore","p12/wstest.jks");
System.setProperty("javax.net.ssl.trustStorePassword","foo123");
System.setProperty("javax.net.ssl.keyStore","p12/wstest.jks");
System.setProperty("javax.net.ssl.keyStorePassword","foo123");
QName qname = new QName("http://ws.protocol.core.ejbca.org/", "EjbcaWSService");
EjbcaWSService service = new EjbcaWSService(new URL(urlstr),qname);
ejbcaraws = service.getEjbcaWSPort();

Using Java 11 it doesn't always work to set the properties above, and the System.setProperty lines above can then be replaced with direct initialization of the default SSLSocketFactory:

HttpsURLConnection.setDefaultSSLSocketFactory(getSSLFactory(p12/wstest.jks, "foo123".toCharArray()));

WS code example call to find all users having 'Smith' in their subject DN:

UserMatch usermatch = new UserMatch();
usermatch.setMatchwith(UserMatch.MATCH_WITH_DN);
usermatch.setMatchtype(UserMatch.MATCH_TYPE_CONTAINS);
usermatch.setMatchvalue("Smith");
List<UserDataVOWS> result = ejbcaraws.findUser(usermatch);

Example generating a certificate from a PKCS10 request:

UserDataVOWS user1 = new UserDataVOWS();
user1.setUsername("WSTESTUSER1");
user1.setSubjectDN("CN=WSTESTUSER1");
user1.setCaName("ManagementCA");
user1.setEmail(null);
user1.setSubjectAltName(null);
user1.setEndEntityProfileName("EMPTY");
user1.setCertificateProfileName("ENDUSER");
KeyPair keys = KeyTools.genKeys("2048", AlgorithmConstants.KEYALGORITHM_RSA);
PKCS10CertificationRequest pkcs10 = new PKCS10CertificationRequest("SHA256WithRSA",
CertTools.stringToBcX500Name("CN=NOUSED"), keys.getPublic(), null, keys.getPrivate());
 
CertificateResponse certenv = ejbcaraws.certificateRequest(user1,
CertificateHelper.CERT_REQ_TYPE_PKCS10,
new String(Base64.encode(pkcs10.getEncoded())),
null, CertificateHelper.RESPONSETYPE_CERTIFICATE);
X509Certificate cert = certenv.getCertificate();

Example checking the revocation status of a certificate:

RevokeStatus revokestatus = ejbcaraws.checkRevokationStatus(cert.getIssuerDN.toString,cert.getSerialNumber().toString(16));
if(revokestatus != null){
if(revokestatus.getReason() != RevokeStatus.NOT_REVOKED)){
// Certificate is revoked
}else{
// Certificate isn't revoked
}
}else{
// Certificate doesn't exist
}

Developing against the Web Service SOAP API

The SOAP API is compatible with all development languages that can handle SOAP messages. This includes programming languages such as Java, C# and PHP. The normal approach is to use your programming languages tools to generate client stubs, which are classes to be used in your client program. For Java, such stub classes are already included as part of the clientToolBox WS client provided.

Client stubs are generated from the WSDL file, which includes all information to use the WS API. The WSDL can be accessed from your installed EJBCA at https://localhost:8443/ejbca/ejbcaws/ejbcaws?wsdl. In the WSDL all methods and parameters are described, but without detailed documentation. For example, the following is described in the WSDL for the getProfile method:

<xs:complexType name="getProfile">
<xs:sequence>
<xs:element name="arg0" type="xs:int"/>
<xs:element minOccurs="0" name="arg1" type="xs:string"/>
</xs:sequence>
</xs:complexType>

There are two parameters to the method arg0 that is an integer and arg1 that is a string. The Javadoc WS API documentation contains detailed descriptions of the arguments, see WS API documentation and specifically EjbcaWS.

The API documentation covers methods for the parameters, return value, privileges needed to use the method (based on the TLS client certificate), and errors that can occur, returned as SOAP error classes. For example, the following is documented for the getProfile method:

Parameters:
profileId - ID of the profile we want to retrieve.
profileType - The type of the profile we want to retrieve. 'eep' for End Entity Profiles and 'cp' for Certificate Profiles
Returns:
a byte array containing the specified profile in XML format

Now you can use your client stubs, in your preferred programming language, to call the WS SOAP getProfile method with an integer and a string parameter, getting back a profile in XML format.

Sample Code

See the file modules/ejbca-ws/src/org/ejbca/core/protocol/ws/common/IEjbcaWS for more detailed instructions of the API. Sample code can be taken from:

Web Service Message Debugging

A very useful tool when developing against the WS API especially if you are not using clientToolBox CLI, but integrating it from your own code, is to look at the actual SOAP messages for working messages. You can then:

  • Run clientToolBox to test a workflow, using the official CLI.

  • Debug SOAP messages according to below.

  • Verify that your code produces the same SOAP messages.

  • Look in the SOAP messages returned how to get the information, also from exceptions.

Log the SOAP messages to facilitate debugging, by adding the following to JAVA_OPTS:

-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true

In JBoss 7/EAP6/WildFly 9 and 10, this can be done by adding the above line to JAVA_OPTS in JBOSS_HOME/bin/standalone.conf. For example:

if [ "x$JAVA_OPTS" = "x" ]; then
JAVA_OPTS="-Xms1303m -Xmx1303m -XX:MetaspaceSize=256M -XX:MaxMetaspaceSize=512m -Djava.net.preferIPv4Stack=true"
JAVA_OPTS="$JAVA_OPTS -Djboss.modules.system.pkgs=$JBOSS_MODULES_SYSTEM_PKGS -Djava.awt.headless=true"
else
echo "JAVA_OPTS already set in environment; overriding default settings with values: $JAVA_OPTS"
fi
JAVA_OPTS="$JAVA_OPTS -Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true"

Accessrules Required when Using the Web Service API

All the calls require HTTPS client authentication. The keystore used must be set up as a regular administrator and access rules according to the following:

Common for all calls (except isAuthorized, existsHardToken, isApproved that only needs a valid trusted certificate):

  • /administrator

  • /ca/'related CA'

editUser:

  • /ra_functionality/create_end_entity and/or edit_end_entity

  • / endentityprofilesrules /end entity profile of user/create_end_entity and/or edit_end_entity

findUser, findCert:

  • /ra_functionality/view_end_entity

  • /ra_functionality/end entity profile of the user/view_end_entity

pkcs10Request, pkcs12req:

  • /ra_functionality/view_end_entity

  • /ra_functionality/edit_end_entity (only required for non key recovery)

  • /ra_functionality/keyrecovery (only required for key recovery)

  • /ra_functionality/end entity profile of the user/view_end_entity

  • / endentityprofilesrules /end entity profile of the user/keyrecovery (only required for key recovery)

  • / endentityprofilesrules /end entity profile of the user/keyrecovery (only required for non key recovery)

  • /ca_functionality/create_certificate

certificateRequest, softTokenRequest:

  • /ra_functionality/create_end_entity and/or edit_end_entity

  • / endentityprofilesrules /end entity profile of user/create_end_entity and/or edit_end_entity

  • /ca_functionality/create_certificate

revokeCert, revokeToken: These calls support approvals.

  • /ra_functionality/revoke_end_entity

  • / endentityprofilesrules /end entity profile of the user/revoke_end_entity

revokeUser: This call support approvals.

  • /ra_functionality/revoke_end_entity

  • / endentityprofilesrules/ end entity profile of the user/revoke_end_entity

  • /ra_functionality/delete_end_entity (only if users should be deleted)

  • /endentityprofilesrules /end entity profile of the user/delete_end_entity (only if users should be deleted)

fetchUserData: It is possible to turn of authorization of this call in the jaxws.properties

  • /userdatasourcesrules/'user data source'/fetch_userdata

genTokenCertificate: Important this call also supports approvals, and the default behaviour is when someone without the '/administrator' access is creating a call then will a GenerateTokenApprovalRequest be created. This behaviour can be turned off in the jaxws.properties file.

  • /ra_functionality/create_end_entity and/or edit_end_entity

  • /endentityprofilesrules/end entity profile of user/create_end_entity and/or edit_end_entity

  • /ra_functionality/revoke_end_entity (if overwrite flag is set)

  • /endentityprofilesrules/end entity profile of user/revoke_end_entity (if overwrite flag is set)

  • /ca_functionality/create_certificate

  • /ca/'ca of all requested certificates'

republishCertificate:

  • /ra_functionality/view_end_entity

  • /endentityprofilesrules/end entity profile of the user/view_end_entity

customLog: No CA access rule is required.

  • /secureaudit/log_custom_events (must be configured in advanced mode when editing access rules)

deleteUserDataFromSource:

  • /userdatasourcesrules/'user data source'/remove_userdata (for all the given user data sources)

getCertificate: no requirement of the '/administrator' flag

  • /ca_functionality/view_certificate

caCertResponse, caRenewCertRequest:

  • /ca_functionality/renew_ca

createCryptoToken (Available in Enterprise Edition only):

  • /cryptotoken/modify

generateCryptoTokenKeys (Available in Enterprise Edition only):

  • /cryptotoken/keys/generate/'related CryptoToken'

createCA (Available in Enterprise Edition only):

  • /

addSubjectToRole, removeSubjectFromRole (Available with Enterprise Edition only):

  • /ca/'related CAs (All the CAs that issued the certificates of every member in the the related role)'

  • /system_functionality/edit_administrator_privileges

getCertificatesByExpirationTime, getCertificatesByExpirationTimeAndIssuer, getCertificatesByExpirationTimeAndType:

  • No other access rules are required

Error codes on Web Services

Business error code have been added in order to discriminate exception of type EjbcaException.

The following code sample shows how to use error codes :

try {
ejbcaraws.editUser(user1);
} catch(EjbcaException_Exception e) {
if(org.cesecore.ErrorCode.CERT_PROFILE_NOT_EXISTS.getInternalErrorCode().equals(e.getFaultInfo().getErrorCode().getInternalErrorCode())) {
log.error("No such certifcate profile.");
}
}

The error codes are described in org.cesecore.ErrorCode and src/test/org/ejbca/core/protocol/ws/CommonEjbcaWSTest.java.

WS Transaction Logging

WS transaction logging is performed in a similar way as the logging for the OCSP responder, see OCSP Audit and Account Logging.

Note however that different tags are used:

  • LOG_TIME: The time the call took place

  • SESSION_ID: A random 32 Byte long String generated when the OCSP-responder is started.

  • LOG_ID: An integer identifying that starts from 1 and is increased for every received request.

  • REPLY_TIME: The time it took to return from the WS method.

  • METHOD: Name of the called WS method.

  • ERROR_MESSAGE: An error message with information of the error. If the call returned successfully then 'NO_ERROR'.

  • ADMIN_DN: Subject DN for the client certificate in the call.

  • ADMIN_ISSUER_DN: Issuer DN of the client certificate in the call

The configuration is specified in conf/jaxws.properties. In the JBoss logger configuration, use org.ejbca.core.protocol.ws.logger.TransactionLogger as category name for the appender.

Example sections for a JBoss standalone.xml to enable WS transaction logging:

<size-rotating-file-handler name="WSTRANS" autoflush="true">
<formatter>
<named-formatter name="PATTERN"/>
</formatter>
<file relative-to="jboss.server.log.dir" path="wstrans.log"/>
<rotate-size value="100M"/>
<max-backup-index value="10"/>
<append value="true"/>
</size-rotating-file-handler>
 
<logger category="org.ejbca.core.protocol.ws.logger.TransactionLogger">
<level name="DEBUG"/>
<handlers>
<handler name="WSTRANS"/>
</handlers>
</logger>