# Deploying KeyMaster

**📌 NOTE**\
For deployment instructions for KeyMaster 6.1 and earlier, see [Deploying KeyMaster (&lt; 6.2)](keymaster-installing-keymaster-pre-6.2.0.md).

This page describes how to deploy KeyMaster as part of a custom web application.

For information on deploying KeyMaster packaged with Caplin’s FX Professional, FX Sales, and FX Corporate web applications, please see the deployment instructions that accompany each application. Contact your Caplin account manager for details.

## Requirements

To implement KeyMaster authentication in your own web applications, you require:

* **Java**: Red Hat OpenJDK 8 or Red Hat OpenJDK 11.
* **Java web application server**: Apache Tomcat 8.5 (servlet specification 3.1) or Apache Tomcat 9.0 (servlet specification 4.0)
* **OpenSSL**: See [Generating encryption keys for production deployments](#generating-encryption-keys-for-production-deployments), below.
* **KeyMaster Java SDK:** The kit provides libraries and examples for implementing KeyMaster in Java web applications. Available from [Caplin Downloads](/account/downloads).
* **Liberator auth module with KeyMaster support:** One of the following Caplin auth modules:
  * Caplin Permissioning Service (available from [Caplin Downloads](/account/downloads))
  * Token Permissioning (included with Liberator)

+
If Caplin’s Liberator auth modules do not fit your requirements, you can create a custom auth module using Liberator’s [C Auth API](https://docs.caplin.com/developer/api/auth_c_sdk/latest/) or [Java Auth API](https://docs.caplin.com/developer/api/auth_java_sdk/latest/).

* **UTC system clocks**: System clocks of application hosts and Liberator hosts set to UTC and synchronised with the same time source.

## Recommendations

Caplin recommend that servlets read their configuration from JNDI environment entries in the web application context, which is configured outside of the web application directory and persists between upgrades of the web application.

```plantuml
@startsalt
scale 1.25
{
{T
 + <color:goldenrod><&folder></color> apache-tomcat-//version//
 ++ <color:goldenrod><&folder></color> conf   
 +++ <color:goldenrod><&folder></color> Catalina
 ++++ <color:goldenrod><&folder></color> //host//
 +++++ <color:cornflowerblue><&file></color> //webapp//.xml | <color:gray><&arrow-left> **Web application context**</color>
 ++ <color:goldenrod><&folder></color> webapps
 +++ <color:goldenrod><&folder></color> //webapp//
 ++++ <color:goldenrod><&folder></color> WEB-INF
 +++++ <color:cornflowerblue><&file></color> web.xml | <color:gray><&arrow-left> Web application deployment descriptor</color>
 +++ <color:cornflowerblue><&file></color> //webapp//.war
}
}
@endsalt
```

All Caplin web applications expose some of their configuration as JNDI environment entries. For more information on JNDI configuration in Caplin’s web applications, see the following pages:

* [Caplin FX Professional JNDI configuration](../../../fx-professional/fxpro-jndi-configuration.md)
* [Caplin FX Sales JNDI configuration](../../../fx-sales/st-jndi-configuration.md)
* [Caplin FX Corporate JNDI configuration](../../../fx-corporate/fxcorp-j2ee-container-config.md) 

For more information about configuring JNDI resources in Apache Tomcat 8, see the following links in the Apache Tomcat 8 documentation:

* [JNDI Resources How-To](https://tomcat.apache.org/tomcat-8.5-doc/jndi-resources-howto.html)
* [The Context Container](https://tomcat.apache.org/tomcat-8.5-doc/config/context.html)

## Overview of KeyMaster authentication

Caplin KeyMaster is a token-based authentication scheme that enables Liberator to delegate user authentication to a trusted third-party server, which issues signed tokens that Liberator accepts as evidence of user identity.

At an abstract level, KeyMaster authentication comprises three stages: user sign-in, token issue, and token validation:

```plantuml
participant Client
participant Server as "Application Server"
participant Liberator

== User sign-in ==

Client -> Server: Sign in
Client <-- Server: Success

== Token issue ==

Client -> Server: Request KeyMaster token
note over Server: Sign token with\nKeyMaster private key
Client <-- Server: Token issued

== Token validation ==

Client -> Liberator: Open connection with Liberator (present KeyMaster token)
note over Liberator: Validate token with\nKeyMaster public key
Client <-- Liberator: Connection established
```

## Example implementations in the KeyMaster Java SDK

The KeyMaster Java SDK includes two sets of example implementations for deployment on Apache Tomcat:

```plantuml
@startsalt
scale 1.25
{
{T
 + <color:goldenrod><&folder></color> KeyMasterJava-//version//   
 ++ <color:goldenrod><&folder></color> examples
 +++ <color:goldenrod><&folder></color> keymaster    | <color:gray><&arrow-left> Examples with container-managed security</color>
 +++ <color:goldenrod><&folder></color> signon    | <color:gray><&arrow-left> Examples with application-managed security</color> 
}
}
@endsalt
```

### Keymaster examples

The **keymaster** directory contains example KeyMaster implementations with container-managed security:

```plantuml
skinparam BoxPadding 10

box Web Browser
participant StreamLinkJS
endbox

box Java Web Application
participant ApacheTomcat as "Apache Tomcat" <<Web container>>
participant KeyMasterServlet as "KeyMaster" <<Servlet>>
endbox

box Caplin Platform
participant Liberator
endbox

StreamLinkJS -> ApacheTomcat: Sign in
ApacheTomcat -> ApacheTomcat: Validate credentials
StreamLinkJS <-- ApacheTomcat: Success

StreamLinkJS -> KeyMasterServlet: Request KeyMaster token
note over KeyMasterServlet: Get username from\n""HttpServletRequest"".
KeyMasterServlet -> KeyMasterServlet: Sign token with\nKeyMaster private key.
StreamLinkJS <-- KeyMasterServlet: Token issued

StreamLinkJS -> Liberator: Open connection with Liberator (present KeyMaster token)
Liberator -> Liberator: Validate token with\nKeyMaster public key
StreamLinkJS <-- Liberator: Connection established

```

The examples are based on the `com.caplin.keymaster` package.

For more information on container-managed security in Apache Tomcat, see [Realms Configuration How-To](https://tomcat.apache.org/tomcat-8.5-doc/realm-howto.html).

### Signon examples

The **signon** directory contains example KeyMaster implementations with application-managed security:

```plantuml
skinparam BoxPadding 10

box Web Browser
participant StreamLinkJS
endbox

box Java Web Application
participant SignOnServlet as "SignOn" <<Servlet>>
participant AuthenticationFilter as "Authentication" <<Request Filter>>
participant KeyMasterServlet as "KeyMaster" <<Servlet>>
endbox

box Caplin Platform
participant Liberator
endbox

StreamLinkJS -> SignOnServlet: Request supported parameters
StreamLinkJS <-- SignOnServlet 

StreamLinkJS -> SignOnServlet: Sign in with credentials
SignOnServlet -> SignOnServlet: Validate credentials
note over SignOnServlet: Store username\nin ""HttpSession"".
StreamLinkJS <-- SignOnServlet: Success

StreamLinkJS -> AuthenticationFilter: Request KeyMaster token
note over AuthenticationFilter: Check username is\nstored in ""HttpSession""
AuthenticationFilter -> KeyMasterServlet
note over KeyMasterServlet: Get username from\n""HttpSession"".
KeyMasterServlet -> KeyMasterServlet: Sign token with\nKeyMaster private key.
StreamLinkJS <-- KeyMasterServlet: Token issued

StreamLinkJS -> Liberator: Request connection (present KeyMaster token)
Liberator -> Liberator: Validate token with\nKeyMaster public key
StreamLinkJS <-- Liberator: Connection established
```

The examples are based on the `com.caplin.signon` package ([KeyMaster SignOn Framework](https://docs.caplin.com/developer/api/keymaster_signon_framework/latest/)), which is used to implement application-managed security in Caplin FX Professional, Caplin FX Sales, and Caplin FX Corporate.

The method used by the SignOn servlet to validate credentials is implementation specific, and you can tailor it to your infrastructure and requirements.

## Configuring Liberator

Enable an auth module that supports authentication by KeyMaster token, and set the location of the KeyMaster public key in the auth module’s configuration.

Follow the steps below:

1. Deactivate Liberator’s default OpenPermissioning blade:

   ```
   $ ./dfw deactivate OpenPermissioning
   ```
2. Deploy or activate an auth module that supports authentication by KeyMaster token, such as the Permissioning Service, or Token Permissioning:

   **Deploying the Permissioning Service**

   ```
   $ cp CPB_PermissioningService-__version__.tar.gz kits
   $ ./dfw deploy
   ```

   **Activating the Token Permissioning blade**

   ```
   $ ./dfw activate TokenPermissioning
   ```
3. In the Deployment Framework configuration override file for your chosen auth module, use the [`add-sigkey`](../datasource/datasource-keymaster-configuration.md#add-sigkey) configuration item to define the key used to validate KeyMaster token signatures.

   As an example, the Permissioning Service blade includes an `add-sigkey` block for Caplin’s default KeyMaster public key (don’t use this default key in production):

   **global_config/overrides/PermissioningService/Liberator/etc/rttpd.conf**

   ```
   add-sigkey
      key-id               Caplin
      timeout              600 ①
      keyfile              "${SSLCERT_PATH}/keymaster_public.der" ②
      hashing-algorithm    sha256
   end-sigkey
   ```
   1. The `timeout` option specifies the maximum age of a signature in seconds. Signatures older than this value will be rejected.
   2. The `keyfile` option specifies the path to KeyMaster’s public key. The example above uses the Deployment Framework configuration variable `SSLCERT_PATH`, which defaults to `global_config/ssl`.

## Generating encryption keys for production deployments

The KeyMaster Java SDK, Caplin web applications, and the Caplin Deployment Framework include complementary sets of default encryption keys. These keys are included for your convenience in setting up deployment and testing environments, but should not be used in production.

**❗ IMPORTANT**\
Do not use Caplin’s default encryption keys in production deployments.

### Generating new KeyMaster encryption keys

To generate new keys for KeyMaster deployments, follow the steps below:

1. Run the script below to generate new encryption keys:

   ```bash
   #!/bin/bash

   # PKCS1 private key.
   openssl genrsa -out privatekey_pkcs1.pem 2048

   # Convert PKCS1 private key to PKCS8. Compatible with KeyMaster Java.
   openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in privatekey_pkcs1.pem -out privatekey.pem

   # Export public key. Compatible with Caplin Liberator.
   openssl rsa -pubout -outform DER -in privatekey_pkcs1.pem -out keymaster_public.der
   ```
2. Copy the public key, `keymaster_public.der`, to the Deployment Framework directory `global_config/ssl` on all Liberator hosts:

   ```plantuml
   @startsalt
   scale 1.25
   {
   {T
    + <color:goldenrod><&folder></color> deployment-framework-//version//   
    ++ <color:goldenrod><&folder></color> global_conf
    +++ <color:goldenrod><&folder></color> ssl
    ++++ <color:cornflowerblue><&file></color> **keymaster_public.der**
   }
   }
   @endsalt
   ```
3. Copy the PKCS8 private key, `privatekey.pem`, to `__tomcat_root__/conf/keymaster`:

   ```plantuml
   @startsalt
   scale 1.25
   {
   {T
    + <color:goldenrod><&folder></color> apache-tomcat-//version//   
    ++ <color:goldenrod><&folder></color> conf
    +++ <color:goldenrod><&folder></color> keymaster
    ++++ <color:cornflowerblue><&file></color> **privatekey.pem**
   }
   }
   @endsalt
   ```
4. Update the Java web application’s configured location of the KeyMaster private key:
   * If your KeyMaster servlet loads configuration from JNDI environment entries (recommended), then add or update the following JNDI environment entry in `__tomcat_root__/conf/Catalina/__hostname__/__webapp__.xml`:

     ```xml
     <Environment
       name="caplin.keymaster.privatekey.filename"
       value="../../conf/keymaster/privatekey.pem"
       type="java.lang.String"
       override="false" /> ①
     ```
     1. Set the `override` attribute to `false` to prevent an identically named environment entry in the web application’s `WEB-INF/web.xml` file from overriding this environment entry.
   * If your KeyMaster servlet loads configuration from servlet initialisation parameters, update the following configuration in your web application’s web deployment descriptor (`WEB-INF/web.xml`) and rebuild the WAR file:

     ```xml
     <init-param>
       <param-name>caplin.keymaster.privatekey.filename</param-name>
       <param-value>../../conf/keymaster/privatekey.pem</param-value>
     </init-param>
     ```

### Generating new SignOn encryption keys

The `EncryptedSignOnServlet.java` example encrypts user credentials before submitting them to the SignOn servlet.

If your implementation of the SignOn servlet is based on the Encrypted SignOn Servlet example, follow the steps below to generate new encryption keys:

1. Run the script below to generate a new set of encryption keys:

   ```bash
   #!/bin/bash

   # PKCS1 private key
   openssl genrsa -out privatekey_pkcs1.pem 2048

   # Convert PKCS1 private key to PKCS8
   openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in privatekey_pkcs1.pem -out privateSignonKey.pem

   # Export public key.
   openssl rsa -in privateSignonKey.pem -outform PEM -pubout -out publicSignonKey.pem
   ```
2. Copy both `privateSignonKey.pem` and `publicSignonKey.pem` to `__tomcat_root__/conf/signon/`:

   ```plantuml
   @startsalt
   scale 1.25
   {
   {T
    + <color:goldenrod><&folder></color> apache-tomcat-//version//   
    ++ <color:goldenrod><&folder></color> conf
    +++ <color:goldenrod><&folder></color> signon
    ++++ <color:cornflowerblue><&file></color> **privateSignonKey.pem**
    ++++ <color:cornflowerblue><&file></color> **publicSignonKey.pem**
   }
   }
   @endsalt
   ```
3. Update the Java web application’s configured location of the SignOn servlet’s key pair:
   * If your SignOn servlet loads configuration from JNDI environment entries (recommended), then add or update the following JNDI environment entries in `__tomcat_root__/conf/Catalina/__hostname__/__webapp__.xml`:

     ```xml
     <Environment
       name="caplin.signon.privatekey.filename"
       value="../../conf/signon/privateSignonKey.pem"
       type="java.lang.String"
       override="false" /> ①
     <Environment
       name="caplin.signon.publickey.filename"
       value="../../conf/signon/publicSignonKey.pem"
       type="java.lang.String"
       override="false" /> ①
     ```
     1. Set the `override` attribute to `false` to prevent an identically named environment entry in the web application’s `WEB-INF/web.xml` file from overriding this environment entry.
   * If your KeyMaster servlet loads configuration from servlet initialisation parameters, update the servlet parameters for the SignOn servlet in your web application’s web deployment descriptor (`WEB-INF/web.xml`) and rebuild the WAR file:

     ```xml
     <init-param>
       <param-name>caplin.signon.privatekey.filename</param-name>
       <param-value>../../conf/signon/privateSignonKey.pem</param-value>
     </init-param>
     <init-param>
       <param-name>caplin.signon.publickey.filename</param-name>
       <param-value>../../conf/signon/publicSignonKey.pem</param-value>
     </init-param>
     ```

## Troubleshooting

If the system clocks of application server hosts and Liberator hosts are not synchronised, then you may see the following message in the Liberator log file:

```
NOTIFY: Signature expired for key_id [key id] - [timestamp] denying login
```

Liberator’s [`signature-validtime`](../datasource/datasource-keymaster-configuration.md#signature-validtime) configuration item determines Liberator’s tolerance of clock drift between the web application server host and the Liberator host. If the apparent age of a token is older than [`signature-validtime`](../datasource/datasource-keymaster-configuration.md#signature-validtime) seconds, then Liberator rejects the token.

## Testing a KeyMaster servlet

To check that a KeyMaster servlet has been deployed successfully, follow the steps below:

1. Open a web browser and navigate to the URL of your KeyMaster servlet.
2. Sign in when requested. If sign in is successful, a KeyMaster token is returned to your browser:

   **Example KeyMaster token for user 'admin'**

   ```properties
   credentials=ok
   username=admin
   token=hf46Rt6wNOwAryZji9Eeu5ADkbSzLxoq93yUsf5w3da56atw0vB/gEQOpBi/O5xSgxI3Ixw7QA3kz6oVkmdpa2XbQCxCZa/HebBu1sSnEMm+dmJrceg6cvVVxqL2FCDZFceUfd2ThWunecU4VwbNXT2puDNsDX4dvFuyip2qwDY=~20140411112017~0~~~admin
   ```

---

**See also**:

* [Hardening KeyMaster security](keymaster-making-keymaster-secure.md)
* [Caplin Permissioning](../platform-architecture/permissioning.md)
