Secrets object and secret stores
IG uses the ForgeRock Commons Secrets API to manage secrets, such as passwords and cryptographic keys.
For more information about how IG manages secrets, see Secrets.
Default secrets object (deprecated)
This object is deprecated; use SecretsProvider instead. For more information, refer to the Deprecated section of the Release Notes. |
IG automatically creates a secrets object in each route in the
configuration, and in config.json
and admin.json
.
When the secrets object is not used to declare a secrets store in the configuration, IG creates a default SystemAndEnvSecretStore in the local secrets service. When the secrets object is used to declare a secrets store, the default is not installed in the local secrets service.
Properties
"stores"
: array of SecretStore references, required-
One or more of the following secret stores:
SecretsProvider
Uses the specified secret stores to resolve queried secrets, such as passwords and cryptographic keys. Attempts to resolve the secret with the secret stores in the order that they are declared in the array.
Usage
{
"name": string,
"type": "SecretsProvider",
"config": {
"stores": [ SecretStore reference, ... ]
}
}
This object can alternatively be configured in a compact format, without the SecretsProvider declaration, as follows:
-
With an inline secret store:
"secretsProvider": { "type": "secret store type1", "config": {...} }
-
With multiple inline secret stores:
"secretsProvider": [ { "type": "secret store type1", "config": {...} } { "type": "secret store type2", "config": {...} } ]
-
With a referenced secret store:
"secretsProvider": "mySecretStore1"
-
With multiple referenced secret stores:
"secretsProvider": [ "mySecretStore1", "mySecretStore2" ]
See Example for more example configurations.
Properties
"stores"
: array of SecretStore references, required-
One or more secret stores to provide access to stored secrets. Configure secret stores described in Secrets.
Example
The following SecretsProvider is used in Discover and dynamically register with OpenID connect providers.
"secretsProvider": {
"type": "SecretsProvider",
"config": {
"stores": [
{
"type": "KeyStoreSecretStore",
"config": {
"file": "/path/to/keystore.p12",
"mappings": [
{
"aliases": [ "myprivatekeyalias" ],
"secretId": "private.key.jwt.signing.key"
}
],
"storePasswordSecretId": "keystore.secret.id",
"storeType": "PKCS12",
"secretsProvider": "SystemAndEnvSecretStore-1"
}
}
]
}
}
The following example shows the equivalent SecretsProvider configuration with an inline compact format:
"secretsProvider": {
"name": "KeyStoreSecretStore-1",
"type": "KeyStoreSecretStore",
"config": {
"file": "/path/to/keystore.p12",
"mappings": [
{
"aliases": [ "myprivatekeyalias" ],
"secretId": "private.key.jwt.signing.key"
}
],
"storePasswordSecretId": "keystore.secret.id",
"storeType": "PKCS12"
}
}
The following example shows the equivalent SecretsProvider configuration with a compact format, referencing a KeyStoreSecretStore object in the heap:
"secretsProvider": "KeyStoreSecretStore-1"
Secret stores
Base64EncodedSecretStore
Manage a repository of generic secrets, such as passwords or simple shared secrets, whose values are base64-encoded, and hard-coded in the route.
This Secret store can only manage secrets of the GenericSecret
type.
The secrets provider queries the Base64EncodedSecretStore for a named secret,
identified by the secret-id
in the "secret-id": "string"
pair. The
Base64EncodedSecretStore returns the matching secret.
The secrets provider builds the secret, checking that the secret’s constraints are met, and returns a unique secret. If the secret’s constraints are not met, the secrets provider cannot build the secret and the secret query fails.
Secrets from Base64EncodedSecretStore never expire.
Use Base64EncodedSecretStore for testing or evaluation only, to store passwords locally. In production, use an alternative secret store. |
For a description of how secrets are managed, refer to Secrets.
Usage
{
"name": string,
"type": "Base64EncodedSecretStore",
"config": {
"secrets": map or configuration expression<map>
}
}
Properties
"secrets"
: map or configuration expression<map>, required-
Map of one or more data pairs with the format
Map<String, String>
, where:-
The key is the ID of a secret used in a route
-
The value is the base64-encoded value of a secret, or a configuration expression that evaluates to the base64-encoded value of a secret
The following formats are allowed:
{ "secrets": { "secret-id": "configuration expression<string>", ... } }
{ "secrets": "configuration expression<map>" }
In the following example, the property is a map whose values are provided by strings:
{ "type": "Base64EncodedSecretStore", "config": { "secrets": { "agent.password": "d2VsY29tZQ==", "crypto.header.key": "Y2hhbmdlaXQ=" } } }
In the following example, the property is a map whose values are provided by a configuration token and a configuration expression. The values are substituted when the route is loaded:
{ "type": "Base64EncodedSecretStore", "config": { "secrets": { "agent.password": "&{secret.value|aGVsbG8=}", "crypto.header.key": "${readProperties('file.property')['b64.key.value']}" } } }
-
Log level
To facilitate debugging secrets for the Base64EncodedSecretStore, in
logback.xml
add a logger defined by the fully qualified package name
of the Base64EncodedSecretStore. The following line in logback.xml
sets the log level to ALL
:
<logger name="org.forgerock.openig.secrets.Base64EncodedSecretStore" level="ALL">
Example
For an example that uses Base64EncodedSecretStore, refer to client-credentials.json
in
Using OAuth 2.0 client credentials.
FileSystemSecretStore
Manage a store of secrets held in files, specified as follows:
-
Each file must contain only one secret.
-
The file must be in the directory specified by the property
directory
. -
The filename must match the
mappings
propertysecretId
. -
The file content must match the
mappings
propertyformat
. For example, if the mapping specifiesBASE64
, the file content must be base64-encoded.
This Secret store can manage secrets of both GenericSecret
and CryptoKey
types when used with dedicated formats.
Secrets are read lazily from the filesystem.
The secrets provider queries the FileSystemSecretStore for a named secret, identified by the name of a file in the specified directory, without the prefix/suffix defined in the store configuration. The FileSystemSecretStore returns the secret that exactly matches the name.
The secrets provider builds the secret, checking that the secret’s constraints are met, and returns a unique secret. If the secret’s constraints are not met, the secrets provider cannot build the secret and the secret query fails.
For a description of how secrets are managed, refer to Secrets.
Usage
{
"name": string,
"type": "FileSystemSecretStore",
"config": {
"directory": configuration expression<string>,
"format": SecretPropertyFormat reference,
"suffix": configuration expression<string>,
"mappings": [ object, ... ],
"leaseExpiry": configuration expression<duration>,
"autoRefresh": object
}
}
Properties
"directory"
: configuration expression<string>, required-
File path to a directory containing secret files. This object checks the specified directory, but not its subdirectories.
format
: SecretPropertyFormat reference, optional-
Format in which the secret is stored. Use one of the following values, or define a format:
-
BASE64
: Base64-encoded -
PLAIN
: Plain text
Default:
BASE64
-
"suffix"
: configuration expression<string>, optional-
File suffix.
When set, the FileSystemSecretStore will append that suffix to the secret ID and try to find a file with the mapped name.
Default: None
"mappings"
: array of objects, optional-
One or more mappings to define a secret:
secretId
: configuration expression<secret-id>, required-
The ID of the secret used in your configuration.
format
: SecretPropertyFormat reference, required-
The format and algorithm of the secret. Use SecretKeyPropertyFormat or PemPropertyFormat.
"leaseExpiry"
: configuration expression<duration>, optional-
The amount of time that secrets produced by this store can be cached before they must be refreshed.
If the duration is
zero
orunlimited
, IG issues a warning, and uses the default value.Default: 5 minutes
"autoRefresh"
: object, optional-
Automatically reload the FileSystemSecretStore when a file is edited or deleted on the filesystem in the configured directory.
{ "enabled": configuration expression<boolean>, "executor": ScheduledExecutorService reference }
enabled
: configuration expression<boolean>, optional-
Flag to enable or disable automatic reload:
-
true
: Enable -
false
: Disable
Default:
true
-
"executor"
: ScheduledExecutorService reference, optional-
A ScheduledExecutorService to monitor the filesystem.
Default: The default ScheduledExecutorService in the heap
Log level
To facilitate debugging secrets for the FileSystemSecretStore, in
logback.xml
add a logger defined by the fully qualified package name
of the property resolver. The following line in logback.xml
sets the
log level to ALL
:
<logger name="org.forgerock.secrets.propertyresolver" level="ALL">
Example
For an example that uses FileSystemSecretStore, see Pass runtime data in a JWT signed with a PEM.
HsmSecretStore
Manage a store of secrets with a hardware security module (HSM) device or a software emulation of an HSM device, such as SoftHSM.
This Secret store can only manage secrets of the CryptoKey
type.
The secrets provider queries the HsmSecretStore for a named secret,
identified by a secret ID and a stable ID, corresponding to the
secret-id
/aliases
mapping. The HsmSecretStore returns a list of matching
secrets.
The secrets provider builds the secret, checking that the secret’s constraints are met, and returns a unique secret. If the secret’s constraints are not met, the secrets provider cannot build the secret and the secret query fails.
For a description of how secrets are managed, refer to Secrets.
Usage
{
"name": string,
"type": "HsmSecretStore",
"config": {
"providerName": configuration expression<string>,
"storePasswordSecretId": configuration expression<secret-id>,
"secretsProvider": SecretsProvider reference,
"mappings": [ object, ... ],
"leaseExpiry": configuration expression<duration>,
"storePassword": configuration expression<secret-id> //deprecated
}
}
Properties
"providerName"
: configuration expression<string>, required-
The name of the pre-installed Java Security Provider supporting an HSM. Use a physical HSM device, or a software emulation of an HSM device, such as SoftHSM.
For the SunPKCS11 provider, concatenate
"providerName"
with the prefixSunPKCS11-
. For example, declare the following for the nameFooAccelerator
:"providerName": "SunPKCS11-FooAccelerator"
"storePasswordSecretId"
: configuration expression<secret-id>, required-
The secret ID of the password to access the HsmSecretStore.
This secret ID must point to a
GenericSecret
.For information about how IG manages secrets, refer to Secrets.
"secretsProvider"
: SecretsProvider reference, optional-
The SecretsProvider object to query for the
storePassword
.Default: The route’s default secret service. For more information, refer to Default secrets object.
"mappings"
: array of objects, required-
One or more mappings of one secret ID to one or more aliases.
The following example maps a secret ID to two aliases:
"mappings": [ { "secretId": "global.pcookie.crypt", "aliases": [ "rsapair72-1", "rsapair72-2" ] } ]
"leaseExpiry"
: configuration expression<duration>, optional-
The amount of time that secrets produced by this store can be cached before they must be refreshed.
If the duration is
zero
orunlimited
, IG issues a warning, and uses the default value.Default: 5 minutes
"storePassword"
: configuration expression<secret-id>, required if storePasswordSecretId not set
The use of this property is deprecated; use storePasswordSecretId instead.
For more information, refer to the Deprecated
section of the Release Notes.
|
The secret ID of the password to access the HsmSecretStore.
+ For information about how IG manages secrets, refer to Secrets.
Log level
To facilitate debugging secrets for the HsmSecretStore, in
logback.xml
add a logger defined by the fully qualified package name
of the HsmSecretStore. The following line in logback.xml
sets the
log level to ALL
:
<logger name="org.forgerock.secrets.keystore" level="ALL">
Example
To set up this example:
-
Set up and test the example in JwtBuilderFilter, and then replace the KeyStoreSecretStore in that example with an HsmSecretStore.
-
Set an environment variable for the HsmSecretStore password,
storePassword
, and then restart IG.For example, if the HsmSecretStore password is
password
, set the following environment variable:export HSM_PIN='cGFzc3dvcmQ='
The password is retrieved by the SystemAndEnvSecretStore, and must be base64-encoded.
-
Create a provider config file, as specified in the PKCS#11 Reference guide.
-
Depending on your version of Java, create a
java.security.ext
file for the IG instance, with the following content:security.provider.<number>=<provider-name> <path-to-provider-cfg-file>
or
security.provider.<number>=<class-name> <path-to-provider-cfg-file>
-
Start the IG JVM with the following system property that points to the provider config file:
-Djava.security.properties=file://path-to-security-extension-file
The following example route is based on the examples in JwtBuilderFilter, replacing the KeyStoreSecretStore with an HsmSecretStore:
{
"name": "hsm-jwt-signature",
"condition": "${find(request.uri.path, '/hsm-jwt-signature$')}",
"baseURI": "http://app.example.com:8081",
"heap": [
{
"name": "SystemAndEnvSecretStore-1",
"type": "SystemAndEnvSecretStore"
},
{
"name": "AmService-1",
"type": "AmService",
"config": {
"agent": {
"username": "ig_agent",
"passwordSecretId": "agent.secret.id"
},
"secretsProvider": "SystemAndEnvSecretStore-1",
"url": "http://am.example.com:8088/openam"
}
},
{
"name": "HsmSecretStore-1",
"type": "HsmSecretStore",
"config": {
"providerName": "SunPKCS11-SoftHSM",
"storePasswordSecretId": "hsm.pin",
"secretsProvider": "SystemAndEnvSecretStore-1",
"mappings": [{
"secretId": "id.key.for.signing.jwt",
"aliases": [ "signature-key" ]
}]
}
}
],
"handler": {
"type": "Chain",
"config": {
"filters": [{
"name": "SingleSignOnFilter-1",
"type": "SingleSignOnFilter",
"config": {
"amService": "AmService-1"
}
}, {
"name": "UserProfileFilter-1",
"type": "UserProfileFilter",
"config": {
"username": "${contexts.ssoToken.info.uid}",
"userProfileService": {
"type": "UserProfileService",
"config": {
"amService": "AmService-1"
}
}
}
}, {
"name": "JwtBuilderFilter-1",
"type": "JwtBuilderFilter",
"config": {
"template": {
"name": "${contexts.userProfile.commonName}",
"email": "${contexts.userProfile.rawInfo.mail[0]}"
},
"secretsProvider": "HsmSecretStore-1",
"signature": {
"secretId": "id.key.for.signing.jwt"
}
}
}, {
"name": "HeaderFilter-1",
"type": "HeaderFilter",
"config": {
"messageType": "REQUEST",
"add": {
"x-openig-user": ["${contexts.jwtBuilder.value}"]
}
}
}],
"handler": "ReverseProxyHandler"
}
}
}
JwkSetSecretStore
A secret store of JSON Web Keys (JWK) from a local or remote JWK Set.
This Secret store can only manage secrets of the CryptoKey
type.
The secrets provider builds the secret, checking that the secret’s constraints are met, and returns a unique secret. If the secret’s constraints are not met, the secrets provider cannot build the secret and the secret query fails.
For a description of how secrets are managed, refer to Secrets.
For information about JWKs and JWK Sets, refer to JSON Web Key (JWK).
Usage
{
"name": string,
"type": "JwkSetSecretStore",
"config": {
"jwkUrl": configuration expression<url>,
"handler": Handler reference,
"cacheTimeout": configuration expression<duration>,
"cacheMissCacheTime": configuration expression<duration>,
"leaseExpiry": configuration expression<duration>
}
}
Properties
"jwkUrl"
: configuration expression<url>, required-
A URL that contains the client’s public keys in JWK format.
"handler"
: Handler reference, optional-
An HTTP client handler to communicate with the
jwkUrl
.Usually set this property to the name of a ClientHandler configured in the heap, or a chain that ends in a ClientHandler.
Default: ClientHandler
"cacheTimeout"
: configuration expression<duration>, optional-
Delay before the cache is reloaded. The cache contains the
jwkUrl
.The cache cannot be deactivated. If a value lower than 10 seconds is configured, a warning is logged and the default value is used instead.
Default: 2 minutes
"cacheMissCacheTime"
: configuration expression<duration>, optional-
If the
jwkUrl
is looked up in the cache and is not found, this is the delay before the cache is reloaded.Default: 2 minutes
"leaseExpiry"
: configuration expression<duration>, optional-
The amount of time that secrets produced by this store can be cached before they must be refreshed.
If the duration is
zero
orunlimited
, IG issues a warning, and uses the default value.Default: 5 minutes
Log level
To facilitate debugging secrets for the JwkSetSecretStore, in
logback.xml
add a logger defined by the fully qualified package name of the
JwkSetSecretStore. The following line in logback.xml
sets the log level to ALL
:
<logger name="org.forgerock.secrets.jwkset" level="ALL">
Example
For an example of how to set up and use JwkSetSecretStore to validate signed access tokens, refer to Validate signed access_tokens with the StatelessAccessTokenResolver and JwkSetSecretStore.
In the following example, a StatelessAccessTokenResolver validates a signed access token by using a JwkSetSecretStore:
"accessTokenResolver": {
"type": "StatelessAccessTokenResolver",
"config": {
"secretsProvider": {
"type": "JwkSetSecretStore",
"config": {
"jwkUrl": "http://am.example.com:8088/openam/oauth2/connect/jwk_uri"
},
"issuer": "http://am.example.com:8088/openam/oauth2",
"verificationSecretId": "verification.secret.id"
}
}
}
The JWT signature is validated as follows:
-
If the JWT contains a
kid
with a matching secret in the JWK set:-
The secrets provider queries the JwkSetSecretStore for a named secret.
-
The JwkSetSecretStore returns the matching secret, identified by a stable ID.
-
The StatelessAccessTokenResolver tries to validate the signature with that named secret. If it fails, the token is considered as invalid.
In the route, note that the property
verificationSecretId
must be configured but is not used in named secret resolution. -
-
If the JWT contains a
kid
without a matching secret in the JWK set:-
The secrets provider queries the JwkSetSecretStore for a named secret.
-
Because the referenced JWK set doesn’t contain a matching secret, named secret resolution fails. IG tries valid secret resolution in the same way as when the JWT doesn’t contain a
kid
.
-
-
If the JWT doesn’t contain a
kid
:-
The secrets provider queries the JwkSetSecretStore for list of valid secrets, whose secret ID is
verification.secret.id
. -
The JwkSetSecretStore returns all secrets in the JWK set whose purpose is signature verification. For example, signature verification keys can have the following JWK parameters:
{ "use": "sig" }
{ "key_opts": [ "verify" ] }
Secrets are returned in the order that they are listed in the JWK set.
-
The StatelessAccessTokenResolver tries to validate the signature with each secret sequentially, starting with the first, and stopping when it succeeds.
-
If none of the valid secrets can verify the signature, the token is considered as invalid.
-
KeyStoreSecretStore
Manages a secret store for cryptographic keys and certificates, based on a standard Java keystore.
Legacy keystore types such as JKS and JCEKS are supported but are not secure. Consider using the PKCS#12 keystore type. |
This Secret store can only manage secrets of the CryptoKey
type.
The secrets provider queries the KeyStoreSecretStore for a named secret,
identified by a secret ID and a stable ID, corresponding to the
secret-id
/aliases
mapping. The KeyStoreSecretStore returns a secret
that exactly matches the name, and whose purpose matches the secret ID and any
purpose constraints.
The secrets provider builds the secret, checking that the secret’s constraints are met, and returns a unique secret. If the secret’s constraints are not met, the secrets provider cannot build the secret and the secret query fails.
For a description of how secrets are managed, refer to Secrets.
Usage
{
"name": string,
"type": "KeyStoreSecretStore",
"config": {
"file": configuration expression<string>,
"storeType": configuration expression<string>,
"storePasswordSecretId": configuration expression<string>,
"entryPasswordSecretId": configuration expression<string>,
"secretsProvider": SecretsProvider reference,
"mappings": [ object, ... ],
"leaseExpiry": configuration expression<duration>,
"autoRefresh": object,
"storePassword": configuration expression<string>, //deprecated
"keyEntryPassword": configuration expression<string> //deprecated
}
}
Properties
"file"
: configuration expression<string>, required-
The path to the KeyStore file.
"storeType"
: configuration expression<string>, optional-
The secret store type.
"storePasswordSecretId"
: configuration expression<secret-id>, optional-
The secret ID of the password to access the KeyStore.
This secret ID must point to a
GenericSecret
.IG searches for the value of the password until it finds it, first locally, then in parent routes, then in
config.json
.To create a store password, add a file containing the password. The filename must corresponds to the secret ID, and the file content must contain only the password, with no trailing spaces or carriage returns.
Default: None; the KeyStore is not password-protected
"entryPasswordSecretId"
: configuration expression<secret-id>, optional-
The secret ID of the password to access entries in the KeyStore.
This secret ID must point to a
GenericSecret
.To create an entry password, add a file containing the password. The filename must correspond to the secret ID, and the file content must contain only the password, with no trailing spaces or carriage returns.
When this property is used, the password must be the same for all entries in the KeyStore. If the KeyStore uses different passwords for entries,
entryPasswordSecretId
doesn’t work.Default: The value of
storePasswordSecretId
"secretsProvider"
: SecretsProvider reference, optional-
The SecretsProvider object to query for the keystore password and key entry password. For more information, see SecretsProvider.
Default: The route’s default secret service. For more information, see Default secrets object.
"mappings"
: array of objects, required-
One or more mappings of one secret ID to one or more aliases. The secret store uses the mappings as follows:
-
When the secret is used to create signatures or encrypt values, the secret store uses the active secret, the first alias in the list.
-
When the secret is used to verify signatures or decrypt data, the secret store tries all of the mapped aliases in the list, starting with the first, and stopping when it finds a secret that can successfully verify signature or decrypt the data.
"mappings": [ { "secretId": "id.key.for.signing.jwt", "aliases": [ "SigningKeyAlias", "AnotherSigningKeyAlias" ] }, { "secretId": "id.key.for.encrypting.jwt", "aliases": ["EncryptionKeyAlias"] } ]
-
"leaseExpiry"
: configuration expression<duration>, optional-
The amount of time that secrets produced by this store can be cached before they must be refreshed.
If the duration is
zero
orunlimited
, IG issues a warning, and uses the default value.Default: 5 minutes
"autoRefresh"
: object, optional-
Automatically reload the KeystoreSecretStore when the keystore is edited or deleted.
{ "enabled": configuration expression<boolean>, "executor": ScheduledExecutorService reference }
enabled
: configuration expression<boolean>, optional-
Flag to enable or disable automatic reload:
-
true
: Enable -
false
: Disable
Default:
true
-
"executor"
: ScheduledExecutorService reference, optional-
A ScheduledExecutorService to monitor the keystore.
Default: The default ScheduledExecutorService in the heap
"storePassword"
: configuration expression<secret-id>, required-
This property is deprecated; use the storePasswordSecretId
instead. For more information, refer to the Deprecated section of the Release Notes.The secret ID of the password to access the KeyStore.
This secret ID must point to a
GenericSecret
.IG searches for the value of the password until it finds it, first locally, then in parent routes, then in
config.json
.To create a store password, add a file containing the password. The filename must corresponds to the secret ID, and the file content must contain only the password, with no trailing spaces or carriage returns.
"keyEntryPassword"
: configuration expression<secret-id>, optional-
This property is deprecated; use the entryPasswordSecretId
instead. For more information, refer to the Deprecated section of the Release Notes.The secret ID of the password to access entries in the KeyStore.
This secret ID must point to a
GenericSecret
.To create an entry password, add a file containing the password. The filename must correspond to the secret ID, and the file content must contain only the password, with no trailing spaces or carriage returns.
When this property is used, the password must be the same for all entries in the keystore. If the keystore uses different passwords for entries,
keyEntryPassword
doesn’t work.Default: The value of
storePassword
Log level
To facilitate debugging secrets for the KeyStoreSecretStore, in
logback.xml
add a logger defined by the fully qualified package name
of the KeyStoreSecretStore. The following line in logback.xml
sets the
log level to ALL
:
<logger name="org.forgerock.secrets.keystore" level="ALL">
Example
For examples of routes that use KeyStoreSecretStore, see the examples in JwtBuilderFilter.
In the following example, a StatelessAccessTokenResolver validates a signed access token by using a KeyStoreSecretStore:
"accessTokenResolver": {
"type": "StatelessAccessTokenResolver",
"config": {
"secretsProvider": {
"type": "KeyStoreSecretStore",
"config": {
"file": "IG_keystore.p12",
"storeType": "PKCS12",
"storePasswordSecretId": "keystore.secret.id",
"entryPasswordSecretId": "keystore.secret.id",
"mappings": [{
"secretId": "verification.secret.id",
"aliases": [ "verification.key.1", "verification.key.2" ]
}]
},
"issuer": "http://am.example.com:8088/openam/oauth2",
"verificationSecretId": "verification.secret.id"
}
}
}
The JWT signature is validated as follows:
-
If the JWT contains a
kid
with a mapped value, for exampleverification.key.1
:-
The secrets provider queries the KeyStoreSecretStore for a named secret with the secret ID
verification.secret.id
and the stable IDverification.key.1
. -
Because the KeyStoreSecretStore contains that mapping, the KeyStoreSecretStore returns a named secret.
-
The StatelessAccessTokenResolver tries to validate the JWT signature with the named secret. If it fails, the token is considered as invalid.
-
-
If the JWT contains a
kid
with an unmapped value, for example,verification.key.3
:-
The secrets provider queries the KeyStoreSecretStore for a named secret with the secret ID
verification.secret.id
and the stable IDverification.key.3
. -
Because the KeyStoreSecretStore doesn’t contain that mapping, named secret resolution fails. IG tries valid secret resolution in the same way as when the JWT doesn’t contain a
kid
.
-
-
If the JWT doesn’t contain a
kid
:-
The secrets provider queries the KeyStoreSecretStore for all valid secrets, whose alias is mapped to the secret ID
verification.secret.id
. There are two valid secrets, with aliasesverification.key.1
andverification.key.2
. -
The StatelessAccessTokenResolver first tries to verify the signature with
verification.key.1
. If that fails, it triesverification.key.2
. -
If neither of the valid secrets can verify the signature, the token is considered as invalid.
-
SystemAndEnvSecretStore
Manage a store of secrets from system properties and environment variables.
This secret store can manage secrets of both GenericSecret
and CryptoKey
types when used with dedicated formats.
A secret ID must conform to the convention described in secret-id. The reference is then transformed to match the environment variable name, as follows:
-
Periods (.) are converted to underscores.
-
Characters are transformed to uppercase.
For example, my.secret.id
is transformed to MY_SECRET_ID
.
The secrets provider queries the SystemAndEnvSecretStore for a named secret, identified by the name of a system property or environment variable. The SystemAndEnvSecretStore returns a secret that exactly matches the name.
The secrets provider builds the secret, checking that the secret’s constraints are met, and returns a unique secret. If the secret’s constraints are not met, the secrets provider cannot build the secret and the secret query fails.
For a description of how secrets are managed, refer to Secrets.
Usage
{
"name": string,
"type": "SystemAndEnvSecretStore",
"config": {
"format": SecretPropertyFormat reference,
"mappings": [ object, ... ],
"leaseExpiry": configuration expression<duration>
}
}
Properties
format
: SecretPropertyFormat reference, optional-
Format in which the secret is stored. Use one of the following values, or define a format:
-
BASE64
: Base64-encoded -
PLAIN
: Plain text
Default:
BASE64
-
"mappings"
: array of objects, optional-
One or more mappings to define a secret:
secretId
: configuration expression<secret-id>, required-
The ID of the secret used in your configuration.
format
: SecretPropertyFormat reference, required-
The format and algorithm of the secret. Use SecretKeyPropertyFormat or PemPropertyFormat.
"leaseExpiry"
: configuration expression<duration>, optional-
The amount of time that secrets produced by this store can be cached before they must be refreshed.
If the duration is
zero
orunlimited
, IG issues a warning, and uses the default value.Default: 5 minutes
Log level
To facilitate debugging secrets for the SystemAndEnvSecretStore, in
logback.xml
add a logger defined by the fully qualified package name
of the property resolver. The following line in logback.xml
sets the
log level to ALL
:
<logger name="org.forgerock.secrets.propertyresolver" level="ALL">
Example
For an example of how to uses a SystemAndEnvSecretStore to manage a password, see the example in Authenticate with SSO through the default authentication service
Secret property formats
PemPropertyFormat
The format of a secret used with a mappings configuration in FileSystemSecretStore and SystemAndEnvSecretStore. Privacy-Enhanced Mail (PEM) is a file format for storing and sending cryptographic keys, certificates, and other data, based on standards in https://www.rfc-editor.org/rfc/rfc7468[Textual Encodings of PKIX, PKCS, and CMS Structures. By default, OpenSSL generates keys using the PEM format.
Encryption methods and ciphers used for PEM encryption must be supported by the Java Cryptography Extension.
PEM keys have the following format, where the PEM label is associated to the type of stored cryptographic material:
-----BEGIN {PEM label}-----
Base64-encoded cryptographic material
-----END {PEM label}-----
PEM Label | Stored Cryptographic Material |
---|---|
|
X.509 Certificate |
|
X.509 SubjectPublicKeyInfo |
|
PKCS#8 Private Key |
|
Encrypted PKCS#8 Private Key |
|
EC Private Key |
|
PKCS#1 RSA Private Key |
|
PKCS#1 RSA Public Keys |
|
PKCS#1-style DSA Private Key |
|
HMAC Secret Keys |
|
AES Secret Keys |
|
Generic Secrets (passwords, API keys, etc) |
Note the following points about the key formats:
-
PKCS#1 is the standard that defines RSA. For more information, see RFC 8017: RSA Public Key Syntax.
-
PKCS#1-style DSA and EC keys are not defined in any standard, but are adapted from the RSA format.
-
HMAC SECRET KEY
,AES SECRET KEY
, andGENERIC SECRET
are a ForgeRock extension, and not currently supported by any other tools.The following example is non-standard PEM encoding of an HMAC symmetric secret key. The payload is base64-encoded random bytes that are the key material, with no extra encoding.
-----BEGIN HMAC SECRET KEY----- Pj/Vel...thB0U= -----END HMAC SECRET KEY-----
Run the following example command to create the key:
cat <<EOF -----BEGIN HMAC SECRET KEY----- $(head -c32 /dev/urandom | base64) -----END HMAC SECRET KEY----- EOF
Usage
{
"name": string,
"type": "PemPropertyFormat",
"config": {
"decryptionSecretId": configuration expression<secret-id>,
"secretsProvider": SecretsProvider reference
}
}
Properties
"decryptionSecretId"
: configuration expression<secret-id>, optional-
The secret ID for the secret to decrypt a PKCS#8 private key.
This secret ID must point to a
GenericSecret
. "secretsProvider"
: SecretsProvider reference, required whendecryptionSecretId
is used-
The SecretsProvider object to query for the decryption secret. For more information, see SecretsProvider.
Example
For examples of use, see Pass runtime data in a JWT signed with a PEM and Pass runtime data in a JWT signed and encrypted with a PEM.
SecretKeyPropertyFormat
The format of a secret used with a secret store.
Usage
{
"name": string,
"type": "SecretKeyPropertyFormat",
"config": {
"format": SecretPropertyFormat reference,
"algorithm": configuration expression<string>
}
}
Properties
format
: SecretPropertyFormat reference, optional-
Format in which the secret is stored. Use one of the following values, or define a format:
-
BASE64
: Base64-encoded -
PLAIN
: Plain text
Default:
BASE64
-
"algorithm"
: configuration expression<string>, required-
The algorithm name used for encryption and decryption. Use algorithm names given in Java Security Standard Algorithm Names.
TLS specific elements
SecretsKeyManager
Uses the Commons Secrets API to manage keys that authenticate a TLS connection to a peer. The configuration references the keystore that holds the keys.
Usage
{
"name": string,
"type": "SecretsKeyManager",
"config": {
"signingSecretId": configuration expression<secret-id>,
"secretsProvider": SecretsProvider reference
}
}
Properties
"signingSecretId"
: configuration expression<secret-id>, required-
The secret ID used to retrieve private signing keys.
This secret ID must point to a
CryptoKey
. "secretsProvider"
: SecretsProvider reference, required-
The SecretsProvider to query for secrets to resolve the private signing key. For more information, see SecretsProvider.
Example
The following example uses a private key found from a keystore for TLS handshake.
{
"type": "SecretsKeyManager",
"config": {
"signingSecretId": "key.manager.secret.id",
"secretsProvider": {
"type": "KeyStoreSecretStore",
"config": {
"file": "path/to/certs/ig.example.com.p12",
"storePasswordSecretId": "keystore.pass",
"secretsProvider": "SecretsPasswords",
"mappings": [{
"secretId": "key.manager.secret.id",
"aliases": [ "ig.example.com" ]
}]
}
}
}
}
SecretsTrustManager
Uses the Commons Secrets API to manage trust material that verifies the credentials presented by a peer. Trust material is usually public key certificates. The configuration references the secrets store that holds the trust material.
Usage
{
"name": string,
"type": "SecretsTrustManager",
"config": {
"verificationSecretId": configuration expression<secret-id>,
"secretsProvider": SecretsProvider reference,
"checkRevocation": configuration expression<boolean>
}
}
Properties
"verificationSecretId"
: configuration expression<secret-id>, required-
The secret ID to retrieve trusted certificates.
This secret ID must point to a
CryptoKey
. "secretsProvider"
: SecretsProvider reference, required-
The SecretsProvider to query for secrets to resolve trusted certificates. For more information, see SecretsProvider.
"checkRevocation"
: configuration expression<boolean>, optional-
Specifies whether to check for certificate revocation.
Default:
true
Example
The following example trusts a list of certificates found in a given keystore:
{
"type": "SecretsTrustManager",
"config": {
"verificationSecretId": "trust.manager.secret.id",
"secretsProvider": {
"type": "KeyStoreSecretStore",
"config": {
"file": "path/to/certs/truststore.p12",
"storePasswordSecretId": "keystore.pass",
"secretsProvider": "SecretsPasswords",
"mappings": [{
"secretId": "trust.manager.secret.id",
"aliases": [ "alias-of-trusted-cert-1", "alias-of-trusted-cert-2" ]
}]
}
}
}
}