Secret stores
Secret stores are repositories for cryptographic keys and credentials. IDM supports the following secret store types:
-
File secret stores, which have one file that stores many secrets
-
Filesystem secret stores, which have many files that each store one secret
-
Property secret stores, which store secrets in properties
-
Hardware Security Module (HSM) secret stores, which involve security devices (for example, a YubiKey)
Configure secret stores
You can configure secret stores in your project’s conf/secrets.json
file, which has the following default configuration:
{
"stores" : [
{
"name" : "mainKeyStore",
"class" : "org.forgerock.openidm.secrets.config.KeyStoreSecretStore",
"config" : {
"file" : "&{idm.data.dir}/security/keystore.jceks",
"storetype" : "JCEKS",
"providerName" : "SunJCE",
"storePassword" : "changeit",
"mappings" : [
{
"secretId" : "decrypt",
"aliases" : [
"openidm-sym-default"
],
"types" : [
"ENCRYPT",
"DECRYPT"
]
}
]
}
},
{
"name" : "mainTrustStore",
"class" : "org.forgerock.openidm.secrets.config.KeyStoreSecretStore",
"config" : {
"file" : "&{idm.data.dir}/security/truststore",
"storetype" : "JKS",
"providerName" : "SUN",
"storePassword" : "changeit",
"mappings" : [
{
"secretId" : "sign",
"aliases" : [
"server-cert"
],
"types" : [
"SIGN"
]
}
]
}
}
],
"populateDefaults" : true
}
The mainKeyStore
and mainTrustStore
properties configure the default secret stores. IDM requires these properties in order to start up. Do not change the property names because they are also provided to third-party products that need a single keystore and a single truststore.
mainKeyStore
-
The main keystore references a Java Cryptography Extension Keystore (JCEKS) located at
/path/to/openidm/security/keystore.jceks
. mainTrustStore
-
The main truststore references a file-based truststore located at
/path/to/openidm/security/truststore
.
You can manage these keystores and truststores using the keytool
command, included in your Java installation. For information about the keytool
command, refer to https://docs.oracle.com/en/java/javase/17/docs/specs/man/keytool.html.
Each configured store has a name
and class
, and the following configuration properties:
file
-
For file-based secret stores, this property references the path to the store file, for example,
&{idm.install.dir}/security/keystore.jceks}
. Hardware security modules do not have afile
property. storetype
-
The type of secret store. IDM supports a number of store types, including JCEKS, JKS, PKCS #11, and PKCS #12.
providerName
-
Sets the name of the cryptographic service provider; for example,
SunPKCS11
orsoftHSM
. If no provider is specified, the JRE default is used. storePassword
-
The password to the secret store. For the default IDM keystore and truststore, the password is
changeit
. You should change this password in a production deployment, as described in Changing the default keystore password. mappings
-
This object lets you map keys and certificates in the secret stores to functionality in IDM. A secrets mapping object has the following structure:
{ "secretId" : "idm.config.encryption", "types": [ "ENCRYPT", "DECRYPT" ], "aliases": [ "&{openidm.config.crypto.alias|openidm-sym-default}" ] }
-
secretId
is the name of the secret. ThesecretId
should indicate the purpose that the secret should be used for. For example,idm.config.encryption
indicates that the mapping is used to encrypt and decrypt sensitive configuration properties, whileidm.password.encryption
indicates that the mapping is used to encrypt and decrypt passwords. -
types
indicates what the keys are used for. The supported types are:Type Definition GENERIC
Used for credentials, such as passwords
ENCRYPT
Used to encrypt data
DECRYPT
Used to decrypt data
SIGN
Used to sign data
VERIFY
Used to verify data
-
aliases
are the key aliases in the secret store that are used for this purpose. You can add as many aliases as necessary. The first alias in the list determines which alias is the active one. Active secrets are used for signature generation and encryption.The aliases in the default keystore are described in The IDM keystore.
The default secret IDs and the aliases they are mapped to are listed in Mapping secretIDs to key aliases.
-
All these properties have a resolvable property value by default; for example
For more information, refer to Property value substitution. |
Mapping secretIDs to key aliases
The following table describes the default secrets and their alias mappings:
secretId |
alias |
Description | Supported types |
||
---|---|---|---|---|---|
|
|
Encryption keystore for legacy JSON objects that do not contain a |
|
||
|
|
Encrypts configuration information |
|
||
|
|
Encrypts managed user passwords |
|
||
|
|
Encrypts JWT session tokens |
|
||
|
|
Signs JWT session tokens using HMAC |
|
||
|
|
Encrypts JWT self-service tokens |
|
||
|
|
Signs JWT session tokens using RSA |
|
||
|
|
Encrypts confidential assignment attributes |
|
||
|
|
The |
|
||
|
|
The password for Prometheus |
|
||
|
|
The password for the Felix web console |
|
||
|
|
The password for Workflow emails |
|
||
|
|
The password for the default HTTP client proxy |
|
Configure email service secret rotation
You can store the basic auth credentials for the email service using purposes. You can store both the username and password or just the password.
Store password as secret
To store the email service password credential as a secret:
-
Configure a purpose called
idm.basic.auth.email
in yourconf/secrets.json
file. The purpose must resolve to the password for the basic auth connection to the email service. For example:{ "name":"secretVolume", "class": "org.forgerock.openidm.secrets.config.FileSystemStore", "config": { "format": "PLAIN", "directory": "&{idm.install.dir}/secrets", "mappings": [ { "secretId": "idm.basic.auth.email", "types": [ "GENERIC" ] } ] } }
-
In the
auth
settings of your email configuration, update thepassword
value to use the purpose:{ ... "auth" : { "enable" : true, "username" : "example", "password": { "$purpose" : { "name" : "idm.basic.auth.email" } } }, ... }
Store username and password as a secret
To store the username and password as a secret:
-
Configure a purpose called
idm.basic.auth.email
in yourconf/secrets.json
file:{ "name":"secretVolume", "class": "org.forgerock.openidm.secrets.config.FileSystemStore", "config": { "format": "PLAIN", "directory": "&{idm.install.dir}/secrets", "mappings": [ { "secretId": "idm.basic.auth.email", "types": [ "GENERIC" ] } ] } }
The purpose must resolve to a JSON object with two fields,
username
andpassword
:{ "username" : "exampleUsername", "password" : "changeit" }
-
In the
auth
settings of your email configuration, update theusername
andpassword
values to use the purpose. You must supply ajsonPointer
value that indicates the property name in the secret’s JSON structure. For example:{ ... "auth" : { "enable" : true, "username" : { "$purpose" : { "name" : "idm.basic.auth.email", "jsonPointer" : "/username" } }, "password" : { "$purpose" : { "name" : "idm.basic.auth.email", "jsonPointer" : "/password" } } }, ... }
Configure secret rotation for connectors
Connectors that support encrypted credentials support storing them in a secret. You can store the principal
and credentials
, or just the credentials
.
Store the credentials as a secret
-
Configure a purpose called
icf.ldap.credentials
in yourconf/secrets.json
file. The purpose must resolve to the connector’scredentials
value:{ "name":"secretVolume", "class": "org.forgerock.openidm.secrets.config.FileSystemStore", "config": { "format": "PLAIN", "directory": "&{idm.install.dir}/secrets", "mappings": [ { "secretId": "icf.ldap.credentials", "types": [ "GENERIC" ] } ] } }
-
In the
configurationProperties
property of the connector’s provisioner file, update thecredentials
value to use the new secret:{ ... "credentials" : { "$purpose": { "name": "icf.ldap.credentials" } }, ... }
Store the principal and credentials as a secret
The following procedure demonstrates how to store the LDAP connector’s principal
and credentials
in a file system based secret store:
-
Configure a purpose called
icf.ldap.credentials
in yourconf/secrets.json
file:{ "name":"secretVolume", "class": "org.forgerock.openidm.secrets.config.FileSystemStore", "config": { "format": "PLAIN", "directory": "&{idm.install.dir}/secrets", "mappings": [ { "secretId": "icf.ldap.credentials", "types": [ "GENERIC" ] } ] } }
The purpose must resolve to a JSON object with two fields,
principal
andsecret
:{ "principal" : "uid=admin", "secret" : "changeit" }
-
In the
configurationProperties
property of the connector’s provisioner file, update theprincipal
andcredentials
values to use the new purpose. You must supply ajsonPointer
value that indicates the property name in the secret’s JSON structure. For example:{ ... "configurationProperties" : { "principal" : { "$purpose": { "name": "icf.ldap.credentials", "jsonPointer": "/principal" } }, "credentials" : { "$purpose": { "name": "icf.ldap.credentials", "jsonPointer": "/secret" } } } ... }
If you change the value of the secret after the initial configuration, you must call the reloadSecrets
connector action on the connector to complete the update:
+
curl \ --header "X-OpenIDM-Username: openidm-admin" \ --header "X-OpenIDM-Password: openidm-admin" \ --header "Accept-API-Version: resource=1.0" \ --request POST \ --header "content-type: application/json" \ --data '' \ "http://localhost:8080/openidm/system/ldap?_action=reloadSecrets" { "status": "ok" }
Store rsFilter client secret as a secret
You can use a secret to contain the rsFilter’s client secret:
-
Remove the
rsFilter/clientSecret
field fromconf/authentication.json
. -
In
conf/secrets.json
, define a purpose calledidm.rs.filter.client.secret
. This example shows how to do this using a filesystem secret store:"name":"secretVolume", "class": "org.forgerock.openidm.secrets.config.FileSystemStore", "config": { "format": "PLAIN", "directory": "&{idm.install.dir}/secrets", "mappings": [ { "secretId": "idm.rs.filter.client.secret", "types": [ "GENERIC" ]}]} }
-
Ensure that secret’s value resolves to the client secret of the OAuth2 client in PingAM.