Configuring ForgeRock Identity Management (IDM) To Use Multiple Keystores or PKCS12 Type Keystores

By Tom Wood

Introduction

When deploying ForgeRock Identity Management (IDM), you may have specific organisational requirements for handling certificates which would benefit from the use of separate keystores for each of the different encryption purposes used by IDM. Alternatively, you may wish to have certificates stored in different types of keystores (e.g. JCEKS and PKCS12) for operational purposes or simply use a PKCS12 keystore for all of your certificates — all of these options are supported by IDM.

The steps in this blog were tested against IDM 7.1.2 but this same functionality should apply from IDM 6.5.0 onwards.

Thanks go to my colleague Min Lim for her original investigation and analysis of IDM’s configuration and behaviour in the use cases to follow.

Jetty

ForgeRock IDM runs within a Jetty container whose configuration is distributed alongside IDM within the zip file available from BackStage. While IDM’s secrets.json configuration allows you to give your keystores and truststores a reference ‘name’ of any value, the Jetty implementation requires that it’s keys are stored within keystore defined with the name mainKeyStore and those certificates it should trust are included in the mainTrustStore.

These two stores are also used by any third party tools which use the javax.net.ssl.keystore properties to access a keystore via IDM.

Keystores

For this example, I have created three keystores within my ./openidm/security folder:

keystore.jceks

% keytool -list -storetype JCEKS -keystore keystore.jceks -storepass changeit

Keystore type: JCEKS
Keystore provider: SunJCE
Your keystore contains 4 entries

openidm-jwtsessionhmac-key, 27 Apr 2022, SecretKeyEntry,
openidm-localhost, 27 Apr 2022, PrivateKeyEntry,
Certificate fingerprint (SHA-256): AF:CA:CB:E3:C5:D8:AA:02:CC:77:FB:46:95:D8:D4:31:84:FF:E1:AA:04:DA:AF:22:7A:47:26:67:A4:C4:DD:05
openidm-selfservice-key, 27 Apr 2022, SecretKeyEntry,
openidm-sym-default, 27 Apr 2022, SecretKeyEntry,

keystoreTwo.jceks

% keytool -list -storetype JCEKS -keystore keystoreTwo.jceks -storepass changeit

Keystore type: JCEKS
Keystore provider: SunJCE
Your keystore contains 1 entry

selfservice, 27 Apr 2022, PrivateKeyEntry,
Certificate fingerprint (SHA-256): EA:DF:0C:69:53:AD:9E:54:DB:D2:F4:E4:64:FD:88:01:89:3E:1B:ED:0A:46:03:F9:ED:EB:15:84:C3:6E:6F:65

keystoreThree.p12

% keytool -list -storetype PKCS12 -keystore keystoreThree.p12 -storepass changeit

Keystore type: PKCS12
Keystore provider: SUN
Your keystore contains 1 entry

selfservice, 27 Apr 2022, PrivateKeyEntry,
Certificate fingerprint (SHA-256): EA:DF:0C:69:53:AD:9E:54:DB:D2:F4:E4:64:FD:88:01:89:3E:1B:ED:0A:46:03:F9:ED:EB:15:84:C3:6E:6F:65

For ease, the initial keystore was simply generated by starting a fresh IDM installation for the first time. The generated keystore was then duplicated with the self-service certificate removed from the original keystore.jceks and all other keys removed from keystoreTwo.jceks . keystoreThree.p12 was generated via keytool from keystoreTwo.jceks.

IDM Configuration

The only changes required to IDM’s configuration occur within the secrets.json file, or https://[host]:[port]/openidm/config/secrets if you’re making the changes via REST.

Step 1:

Remove the idm.selfservice.encryption secretId / purpose object from the list of secretIds in the mainKeyStore configuration

Step 2:

Add a new configuration entry for your new keystore which includes the idm.selfservice.encryption secretId with the correct certificate alias for your keystore, e.g.

{
  "name": "newKeyStore",
  "class": "org.forgerock.openidm.secrets.config.FileBasedStore",
  "config": {
    "file": "&{idm.install.dir}/security/keystoreTwo.jceks",
    "storetype": "JCEKS",
    "providerName": "SunJCE",
    "storePassword": "changeit",
    "mappings": [
      {
        "secretId": "idm.selfservice.encryption",
        "types": [
          "ENCRYPT",
          "DECRYPT"
        ],
        "aliases": [
          "selfservice"
        ]
      }
    ]
  }
}

While it is not strictly necessary, if your IDM instance was running when this change was made, restart it to re-read the configured keystores.

Your IDM instance is now updated to use the certificate stored within keystoreTwo.jceks for the idm.selfservice.encryption purpose.

Using PKCS12 certificates

When using a PKCS12 keystore, a slight change is needed to the configuration added to secrets.json to adjust the storeType and providerName as follows:

{
  "name": "newKeyStore",
  "class": "org.forgerock.openidm.secrets.config.FileBasedStore",
  "config": {
    "file": "&{idm.install.dir}/security/keystoreThree.p12",
    "storetype": "PKCS12",
    "providerName": "SunJSSE",
    "storePassword": "changeit",
    "mappings": [
      {
        "secretId": "idm.selfservice.encryption",
        "types": [
          "ENCRYPT",
          "DECRYPT"
        ],
        "aliases": [
          "selfservice"
        ]
      }
    ]
  }
}

Example configurations demonstrating a full conversion to PKCS12 ( `secrets-One-PKCS12.json`), two JCEKS keystores (`secrets-Two-JCEKS.json`) or one JCEKS and one PKCS12 keystore ( `secrets-TwoPKCS12.json`) are available on GitHub: