Manage configuration placeholders using the API
PingOne Advanced Identity Cloud lets you add placeholders to your configuration so you can reference the value of an ESV variable or an ESV secret instead of defining a static value.
For example, if you created an ESV variable named esv-email-provider-port
, you could reference its value by adding a placeholder of {"$int" : "&{esv.email.provider.port}"}
to your configuration.
To set a default value in a configuration placeholder, include it after a vertical bar. For example, the following expression sets a default email provider port of 465: {"$int" : "&{esv.email.provider.port|465}"}
. If no ESV is set, the default value of 465 is used instead.
If you add a placeholder to your configuration and do not set a corresponding ESV or specify a default value, you will not be able to complete a successful promotion.
A configuration property can include a mix of static values and placeholders. For example, if you set esv-hostname
to id
, then &{esv.hostname}.example.com
evaluates to id.example.com
.
Examples
Configure tenant email provider
This example shows how to configure placeholders in your tenant email provider configuration. Learn more in Email provider.
-
Get an access token. Learn more in Get an access token.
-
Get the email provider configuration:
Show request
$ curl \ --request GET 'https://<tenant-env-fqdn>/openidm/config/external.email' \ --header 'Content-Type: application/json' \ --header 'Accept-API-Version: resource=1.0' \ --header 'Authorization: Bearer <access-token>' (1)
1 Replace <access-token> with the access token created in step 1. Show response
{ "_id": "external.email", "auth": { "enable": true, "password": "changeit", "username": "example.user" }, "connectiontimeout": 30000, "debug": false, "from": "\"Example User\" <example.user@example.com>", "host": "localhost", "port": 465, "smtpProperties": [], "ssl": { "enable": true }, "starttls": { "enable": false }, "threadPoolSize": 21, "timeout": 30000, "writetimeout": 30000 }
-
Create a local copy of the email provider configuration from step 2, then substitute in ESV placeholders:
{ "auth": { "enable": true, "password": "&{esv.email.provider.password}",(1) "username": "&{esv.email.provider.username}"(2) }, "connectiontimeout": 30000, "debug": false, "from": "\"Example User\" <&{esv.email.provider.from.email}>",(3) "host": "localhost", "port": { "$int": "&{esv.email.provider.port}"(4) }, "smtpProperties": [], "ssl": { "enable": { "$bool": "&{esv.email.provider.use.ssl}"(5) } }, "starttls": { "enable": false }, "threadPoolSize": 21, "timeout": 30000, "writetimeout": 30000 }
1 Substitution for ESV placeholder &{esv.email.provider.password}
.2 Substitution for ESV placeholder &{esv.email.provider.username}
.3 Substitution for ESV placeholder &{esv.email.provider.from.email}
.4 Substitution for ESV placeholder &{esv.email.provider.port}
.5 Substitution for ESV placeholder &{esv.email.provider.use.ssl}
.The following table summarizes the ESVs that correspond with the above placeholders:
ESV name ESV type Example value esv-email-provider-password
Secret
n/a
esv-email-provider-username
Variable
String
example.user
esv-email-provider-from-email
Variable
String
example.user@example.com
esv-email-provider-port
Variable
Integer
465
esv-email-provider-use-ssl
Variable
Boolean
true
-
Update the email provider configuration:
Show request
$ curl \ --request PUT 'https://<tenant-env-fqdn>/openidm/config/external.email' \ --header 'Content-Type: application/json' \ --header 'Accept-API-Version: resource=1.0' \ --header 'Authorization: Bearer <access-token>' \(1) --data-raw '<email-provider-configuration>'(2)
1 Replace <access-token> with the access token created in step 1. 2 Replace <email-provider-configuration> with the local copy of the email-provider configuration modified in step 3. Show response
{ "_id": "external.email", "auth": { "enable": true, "password": "&{esv.email.provider.password}", "username": "&{esv.email.provider.username}" }, "connectiontimeout": 30000, "debug": false, "from": "\"Example User\" <&{esv.email.provider.from.email}>", "host": "localhost", "port": { "$int": "&{esv.email.provider.port}" }, "smtpProperties": [], "ssl": { "enable": { "$bool": "&{esv.email.provider.use.ssl}" } }, "starttls": { "enable": false }, "threadPoolSize": 20, "timeout": 30000, "writetimeout": 30000 }
Configure CORS
This example shows how to configure placeholders in your tenant CORS configuration. Learn more in Configure cross-origin resource sharing.
-
Get an access token. Learn more in Get an access token.
-
Get the CORS configuration:
Show request
$ curl \ --request POST 'https://<tenant-env-fqdn>/am/json/global-config/services/CorsService/?_action=nextdescendents' \ --header 'Content-Type: application/json' \ --header 'Accept-API-Version: resource=1.0' \ --header 'Authorization: Bearer <access-token>' (1)
1 Replace <access-token> with the access token created in step 1. Show response
{ "result": [ { "maxAge": 600, "exposedHeaders": [], "acceptedHeaders": [ "accept-api-version", "x-requested-with" ], "allowCredentials": true, "acceptedMethods": [ "GET", "POST", "PUT", "DELETE" ], "acceptedOrigins": [ "https://example.org", "https://example.com", "https://openam-example.forgeblocks.com" ], "enabled": true, "_id": "example-cors-config",(1) "_type": { "_id": "configuration", "name": "Cors Configuration", "collection": true } } ] }
1 The ID of the CORS configuration; in this example it is example-cors-config
. -
Create a local copy of the CORS configuration from step 2, then substitute in ESV placeholders:
{ "maxAge": 600, "exposedHeaders": [], "acceptedHeaders": [ "accept-api-version", "x-requested-with" ], "allowCredentials": true, "acceptedMethods": [ "GET", "POST", "PUT", "DELETE" ], "acceptedOrigins": { "$array": "&{esv.cors.accepted.origins}"(1) }, "enabled": true, "_id": "example-cors-config", "_type": { "_id": "configuration", "name": "Cors Configuration", "collection": true } }
1 Substitution for ESV placeholder &{esv.cors.accepted.origins}
.The following table summarizes the ESV that corresponds with the above placeholder:
ESV name ESV type Example value esv-cors-accepted-origins
Variable
Array
["https://example.org","https://example.com","https://openam-example.forgeblocks.com"]
-
Update the CORS configuration:
Show request
$ curl \ --request PUT 'https://<tenant-env-fqdn>/am/json/global-config/services/CorsService/configuration/<cors-id>' \(1) --header 'Content-Type: application/json' \ --header 'Accept-API-Version: resource=1.0' \ --header 'Authorization: Bearer <access-token>' \(2) --data-raw '<cors-configuration>'(3)
1 Replace <cors-id> with the CORS configuration ID you found in step 2; for example, example-cors-config
.2 Replace <access-token> with the access token created in step 1. 3 Replace <cors-configuration> with the local copy of the CORS configuration modified in step 3. Show response
{ "_id": "example-cors-settings", "_rev": "1594160724", "maxAge": 600, "exposedHeaders": [], "acceptedHeaders": [ "accept-api-version", "x-requested-with" ], "allowCredentials": true, "acceptedMethods": [ "GET", "POST", "PUT", "DELETE" ], "acceptedOrigins": { "$array": "&{esv.cors.accepted.origins}" }, "enabled": true, "_type": { "_id": "configuration", "name": "Cors Configuration", "collection": true } }
Configure a journey node
This example shows how to configure placeholders in an LDAP decision node, but the approach can be adapted to configure placeholders in any journey node.
-
Get an access token. Learn more in Get an access token.
-
Get the configuration of the journey that contains the LDAP decision node so you can extract the ID of the node:
Show request
$ curl \ --request GET 'https://<tenant-env-fqdn>/am/json/realms/root/realms/<realm>/realm-config/authentication/authenticationtrees/trees/<journey-name>' \(1) (2) --header 'Content-Type: application/json' \ --header 'Accept-API-Version: resource=1.0' \ --header 'Authorization: Bearer <access-token>' (3)
1 Replace <realm> with the realm that contains the journey that contains the LDAP decision node; for example, alpha
.2 Replace <journey-name> with the name of the journey that contains the LDAP decision node; for example, UpdatePassword
.3 Replace <access-token> with the access token created in step 1. Show response
{ "_id": "ldapJourney", "_rev": "1341035508", "identityResource": "managed/alpha_user", "uiConfig": { "categories": "[]" }, "entryNodeId": "76e74888-73e1-46e2-aa33-5e4c8b07ccec", "nodes": { "76e74888-73e1-46e2-aa33-5e4c8b07ccec": { "x": 249, "y": 171.015625, "connections": { "outcome": "c12abfe7-ae71-42e6-a6b3-e8f4d4d05549" }, "nodeType": "PageNode", "displayName": "Page Node" }, "2082c1ad-f5ad-4b6d-aada-dd4fff4dc6f3": {(1) "x": 510, "y": 181.015625, "connections": { "CANCELLED": "e301438c-0bd0-429c-ab0c-66126501069a", "EXPIRED": "e301438c-0bd0-429c-ab0c-66126501069a", "FALSE": "e301438c-0bd0-429c-ab0c-66126501069a", "LOCKED": "e301438c-0bd0-429c-ab0c-66126501069a", "TRUE": "70e691a5-1e33-4ac3-a356-e7b6d60d92e0" }, "nodeType": "LdapDecisionNode", "displayName": "LDAP Decision" } }, "staticNodes": { "startNode": { "x": 50, "y": 250 }, "70e691a5-1e33-4ac3-a356-e7b6d60d92e0": { "x": 792, "y": 181 }, "e301438c-0bd0-429c-ab0c-66126501069a": { "x": 795, "y": 307 } }, "enabled": true }
1 The ID of the LdapDecisionNode
node; in this example, it is2082c1ad-f5ad-4b6d-aada-dd4fff4dc6f3
. -
Get the configuration of the LDAP decision node:
Show request
$ curl \ --request GET 'https://<tenant-env-fqdn>/am/json/realms/root/realms/<realm>/realm-config/authentication/authenticationtrees/nodes/LdapDecisionNode/<node-id>' \(1) (2) (3) --header 'Content-Type: application/json' \ --header 'Accept-API-Version: resource=1.0' \ --header 'Authorization: Bearer <access-token>' (4)
1 Replace <realm> with the realm that contains the journey that contains the LDAP decision node; for example, alpha
.2 The node name specified is LdapDecisionNode
.3 Replace <node-id> with the node ID you found in step 2; for example, 2082c1ad-f5ad-4b6d-aada-dd4fff4dc6f3
.4 Replace <access-token> with the access token created in step 1. Show response
{ "_id": "2082c1ad-f5ad-4b6d-aada-dd4fff4dc6f3", "_rev": "-752122233", "searchFilterAttributes": [ "mail" ], "userProfileAttribute": "uid", "primaryServers": [ "userstore-0.userstore:1389", "userstore-1.userstore:1389", "userstore-2.userstore:1389" ], "ldapConnectionMode": "LDAP", "trustAllServerCertificates": false, "heartbeatInterval": 10, "returnUserDn": true, "searchScope": "SUBTREE", "heartbeatTimeUnit": "SECONDS", "secondaryServers": [], "ldapOperationsTimeout": 0, "userCreationAttrs": [], "minimumPasswordLength": 8, "accountSearchBaseDn": [ "o=example" ], "adminPassword": null, "adminDn": "uid=admin", "beheraEnabled": true, "_type": { "_id": "LdapDecisionNode", "name": "LDAP Decision", "collection": true }, "_outcomes": [ { "id": "TRUE", "displayName": "True" }, { "id": "FALSE", "displayName": "False" }, { "id": "LOCKED", "displayName": "Locked" }, { "id": "CANCELLED", "displayName": "Cancelled" }, { "id": "EXPIRED", "displayName": "Expired" } ] }
-
Create a local copy of the node configuration from step 3, then substitute in ESV placeholders:
{ "searchFilterAttributes": [ "mail" ], "userProfileAttribute": "uid", "primaryServers" : { "$list": "&{esv.journey.ldap.primary.servers}"(1) }, "ldapConnectionMode": "LDAP", "trustAllServerCertificates": false, "heartbeatInterval": { "$int": "&{esv.journey.ldap.heartbeat.interval}"(2) }, "returnUserDn": true, "searchScope": "SUBTREE", "heartbeatTimeUnit": "&{esv.journey.ldap.heartbeat.unit}",(3) "secondaryServers": [], "ldapOperationsTimeout": 0, "userCreationAttrs": [], "minimumPasswordLength": 8, "accountSearchBaseDn": [ "o=example" ], "adminPassword": { "$string": "&{esv.journey.ldap.password}"(4) }, "adminDn": "&{esv.journey.ldap.username}",(5) "beheraEnabled": { "$bool": "&{esv.journey.ldap.behera.enabled}"(6) }, "_type": { "_id": "LdapDecisionNode", "name": "LDAP Decision", "collection": true }, "_outcomes": [ { "id": "TRUE", "displayName": "True" }, { "id": "FALSE", "displayName": "False" }, { "id": "LOCKED", "displayName": "Locked" }, { "id": "CANCELLED", "displayName": "Cancelled" }, { "id": "EXPIRED", "displayName": "Expired" } ] }
1 Substitution for ESV placeholder &{esv.journey.ldap.primary.servers}
.2 Substitution for ESV placeholder &{esv.journey.ldap.heartbeat.interval}
.3 Substitution for ESV placeholder &{esv.journey.ldap.heartbeat.unit}
.4 Substitution for ESV placeholder &{esv.journey.ldap.password}
.5 Substitution for ESV placeholder &{esv.journey.ldap.username}
.6 Substitution for ESV placeholder &{esv.journey.ldap.behera.enabled}
.The following table summarizes the ESVs that correspond with the above placeholders:
ESV name ESV type Example value esv-journey-ldap-primary-servers
Variable
List
userstore-0.userstore:1389,userstore-1.userstore:1389,userstore-2.userstore:1389
esv-journey-ldap-heartbeat-interval
Variable
Integer
10
esv-journey-ldap-heartbeat-unit
Variable
String
SECONDS
esv-journey-ldap-password
Secret
n/a
changeit
esv-journey-ldap-username
Variable
String
uid=myadmin
esv-journey-ldap-behera-enabled
Variable
Boolean
false
-
Update the configuration of the LDAP decision node:
Show request
$ curl \ --request PUT 'https://<tenant-env-fqdn>/am/json/realms/root/realms/<realm>/realm-config/authentication/authenticationtrees/nodes/LdapDecisionNode/<node-id>' \(1) (2) (3) --header 'Content-Type: application/json' \ --header 'Accept-API-Version: resource=1.0' \ --header 'Authorization: Bearer <access-token>' \(4) --data-raw '<node-configuration>'(5)
1 Replace <realm> with the realm that contains the journey that contains the LDAP decision node; for example, alpha
.2 The node name specified is LdapDecisionNode
.3 Replace <node-id> with the node ID you found in step 2; for example, 2082c1ad-f5ad-4b6d-aada-dd4fff4dc6f3
.4 Replace <access-token> with the access token created in step 1. 5 Replace <node-configuration> with the local copy of the node configuration modified in step 4. Show response
{ "_id": "2082c1ad-f5ad-4b6d-aada-dd4fff4dc6f3", "_rev": "1359037709", "searchFilterAttributes": [ "mail" ], "userProfileAttribute": "uid", "primaryServers": { "$list": "&{esv.journey.ldap.servers}" }, "ldapConnectionMode": "LDAP", "trustAllServerCertificates": false, "heartbeatInterval": { "$int": "&{esv.journey.ldap.heartbeat.interval}" }, "returnUserDn": true, "searchScope": "SUBTREE", "heartbeatTimeUnit": "&{esv.journey.ldap.heartbeat.unit}", "secondaryServers": [], "ldapOperationsTimeout": 0, "userCreationAttrs": [], "minimumPasswordLength": 8, "accountSearchBaseDn": [ "o=example" ], "adminPassword": { "$string": "&{esv.journey.ldap.password}" }, "adminDn": "&{esv.journey.ldap.username}", "beheraEnabled": { "$bool": "&{esv.journey.ldap.behera.enabled}" }, "_type": { "_id": "LdapDecisionNode", "name": "LDAP Decision", "collection": true }, "_outcomes": [ { "id": "TRUE", "displayName": "True" }, { "id": "FALSE", "displayName": "False" }, { "id": "LOCKED", "displayName": "Locked" }, { "id": "CANCELLED", "displayName": "Cancelled" }, { "id": "EXPIRED", "displayName": "Expired" } ] }
Configure a federation provider secret
This example shows how to configure a placeholder for a federation provider secret.
-
Get an access token. Learn more in Get an access token.
-
Get the configuration of the federation provider:
Show request
$ curl \ --request GET 'https://<tenant-env-fqdn>/am/json/realms/root/realm-config/services/SocialIdentityProviders/oidcConfig/<provider-id>' \(1) --header 'Content-Type: application/json' \ --header 'Accept-API-Version: resource=1.0' \ --header 'Authorization: Bearer <access-token>' (2)
1 Replace <provider-id> with the name of your federation provider; for example, ms-azure-provider
.2 Replace <access-token> with the access token created in step 1. Show response
{ "clientId": "my-client-id", "pkceMethod": "S256", "wellKnownEndpoint": "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "authorizationEndpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize", "clientSecret": null, "issuerComparisonCheckType": "EXACT", "encryptJwtRequestParameter": false, "scopeDelimiter": " ", "scopes": [ "User.Read", "openid" ], "issuer": "ForgeRock", "userInfoResponseType": "JSON", "acrValues": [], "encryptedIdTokens": false, "enabled": true, "jwtRequestParameterOption": "NONE", "authenticationIdKey": "id", "uiConfig": { "buttonCustomStyle": "background-color: #fff; border-color: #8b8b8b; color: #8b8b8b;", "buttonCustomStyleHover": "background-color: #fff; border-color: #8b8b8b; color: #8b8b8b;", "buttonDisplayName": "Azure", "buttonImage": "img/azure-logo.6be3c5e8.svg", "iconBackground": "#0078d7", "iconFontColor": "white" }, "privateKeyJwtExpTime": 600, "revocationCheckOptions": [], "enableNativeNonce": true, "userInfoEndpoint": "https://graph.microsoft.com/oidc/userinfo", "jwtSigningAlgorithm": "NONE", "redirectURI": "https://openam-federation-preview.forgeblocks.com/login/admins", "clientAuthenticationMethod": "CLIENT_SECRET_POST", "responseMode": "DEFAULT", "useCustomTrustStore": false, "tokenEndpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/token", "_id": "ms-azure-provider", "_type": { "_id": "oidcConfig", "name": "Client configuration for providers that implement the OpenID Connect specification.", "collection": true } }
-
Create a local copy of the federation provider configuration from step 2, then substitute an ESV placeholder for the application secret:
{ "clientId": "my-client-id", "pkceMethod": "S256", "wellKnownEndpoint": "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "authorizationEndpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize", "clientSecret": { "$string":"&{esv.ms.azure.provider}" (1) }, "issuerComparisonCheckType": "EXACT", "encryptJwtRequestParameter": false, "scopeDelimiter": " ", "scopes": [ "User.Read", "openid" ], "issuer": "ForgeRock", "userInfoResponseType": "JSON", "acrValues": [], "encryptedIdTokens": false, "enabled": true, "jwtRequestParameterOption": "NONE", "authenticationIdKey": "id", "uiConfig": { "buttonCustomStyle": "background-color: #fff; border-color: #8b8b8b; color: #8b8b8b;", "buttonCustomStyleHover": "background-color: #fff; border-color: #8b8b8b; color: #8b8b8b;", "buttonDisplayName": "Azure", "buttonImage": "img/azure-logo.6be3c5e8.svg", "iconBackground": "#0078d7", "iconFontColor": "white" }, "privateKeyJwtExpTime": 600, "revocationCheckOptions": [], "enableNativeNonce": true, "userInfoEndpoint": "https://graph.microsoft.com/oidc/userinfo", "jwtSigningAlgorithm": "NONE", "redirectURI": "https://openam-federation-preview.forgeblocks.com/login/admins", "clientAuthenticationMethod": "CLIENT_SECRET_POST", "responseMode": "DEFAULT", "useCustomTrustStore": false, "tokenEndpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/token", "_id": "ms-azure-provider", "_type": { "_id": "oidcConfig", "name": "Client configuration for providers that implement the OpenID Connect specification.", "collection": true } }
1 Substitution for ESV placeholder &{esv.ms.azure.provider}
. -
Update the federation provider configuration:
Show request
curl \ --request PUT 'https://<tenant-env-fqdn>/am/json/realms/root/realm-config/services/SocialIdentityProviders/oidcConfig/<provider-id>' \ (1) --header 'Content-Type: application/json' \ --header 'Accept-API-Version: resource=1.0' \ --header 'Authorization: Bearer <access-token>' \(2) --data-raw '<provider-configuration>' (3)
1 Replace <provider-id> with the name of your federation provider; for example, ms-azure-provider
.2 Replace <access-token> with the access token created in step 1. 3 Replace <provider-configuration> with the local copy of the provider configuration modified in step 3. Show response
{ "clientId": "my-client-id", "pkceMethod": "S256", "wellKnownEndpoint": "https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration", "authorizationEndpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/authorize", "clientSecret": { "$string":"&{esv.ms.azure.provider}" }, "issuerComparisonCheckType": "EXACT", "encryptJwtRequestParameter": false, "scopeDelimiter": " ", "scopes": [ "User.Read", "openid" ], "issuer": "ForgeRock", "userInfoResponseType": "JSON", "acrValues": [], "encryptedIdTokens": false, "enabled": true, "jwtRequestParameterOption": "NONE", "authenticationIdKey": "id", "uiConfig": { "buttonCustomStyle": "background-color: #fff; border-color: #8b8b8b; color: #8b8b8b;", "buttonCustomStyleHover": "background-color: #fff; border-color: #8b8b8b; color: #8b8b8b;", "buttonDisplayName": "Azure", "buttonImage": "img/azure-logo.6be3c5e8.svg", "iconBackground": "#0078d7", "iconFontColor": "white" }, "privateKeyJwtExpTime": 600, "revocationCheckOptions": [], "enableNativeNonce": true, "userInfoEndpoint": "https://graph.microsoft.com/oidc/userinfo", "jwtSigningAlgorithm": "NONE", "redirectURI": "https://openam-federation-preview.forgeblocks.com/login/admins", "clientAuthenticationMethod": "CLIENT_SECRET_POST", "responseMode": "DEFAULT", "useCustomTrustStore": false, "tokenEndpoint": "https://login.microsoftonline.com/common/oauth2/v2.0/token", "_id": "ms-azure-provider", "_type": { "_id": "oidcConfig", "name": "Client configuration for providers that implement the OpenID Connect specification.", "collection": true } }