Property Value Substitution
Property value substitution enables you to achieve the following:
Define a configuration that is specific to a single instance. For example, set the location of the keystore on a particular host.
Define a configuration whose parameters vary between different environments. For example, change hostnames and passwords for test, development, and production environments.
Disable certain capabilities on specific servers. For example, disable a database backend and its replication agreement for one set of replicas while enabling it on another set of replicas. This makes it possible to use the same configuration for environments with different data sets.
Property value substitution uses configuration expressions to introduce variables into the server configuration. You set configuration expressions as the values of configuration properties. The effective property values can be evaluated in a number of ways.
Note
DS servers only resolve configuration expressions in the config/config.ldif
file on LDAP attributes whose names start with ds-cfg-*
. These correspond to configuration properties listed in this reference.
DS servers do not resolve configuration expressions anywhere else.
DS servers resolve expressions at startup to determine the configuration. DS commands that read the configuration in offline mode also resolve expressions at startup. When you use expressions in the configuration, you must make their values available before starting the server and also when running such commands.
Configuration expressions share their syntax and underlying implementation with other platform software. Configuration expressions have the following characteristics:
To distinguish them from static values, expression tokens are preceded by an ampersand and enclosed in braces. For example:
&{listen.port}
. The expression token in the example islisten.port
. The.
serves as the separator character.You can use a default value in an expression by including it after a vertical bar following the token.
For example, the following expression sets the default listen port value to 1389:
&{listen.port|1389}
.A configuration property can include a mix of static values and expressions.
For example, suppose
hostname
is set todirectory
. Then&{hostname}.example.com
evaluates todirectory.example.com
.You can define nested properties (that is, a property definition within another property definition).
For example, suppose
listen.port
is set to&{port.prefix}389
, andport.prefix
is set to2
. Then&{listen.port}
evaluates to2389
.You can read the value of an expression token from a file.
For example, if the cleartext password is stored in
/path/to/password.txt
, the following expression resolves to the cleartext password:&{file:/path/to/password.txt}
.You specify the file either by its absolute path, or by a path relative to the DS instance directory. In other words, if the DS instance directory is
/path/to/opendj
, then/path/to/opendj/config/keystore
andconfig/keystore
reference the same file.
DS servers define the following expression tokens by default. You can use these in expressions without explicitly setting their values beforehand:
ds.instance.dir
The file system directory holding the instance files required to run an instance of a server.
By default, the files are co-located with the product tools, libraries, and configuration files. You can change the location by using the
setup --instancePath
option.This evaluates to a directory, such as
/path/to/my-instance
.ds.install.dir
The file system directory where the server files are installed.
This evaluates to a directory, such as
/path/to/opendj
.
Expression Evaluation and Order of Precedence
You must define expression values before starting the DS server that uses them. When evaluated, an expression must return the appropriate type for the configuration property. For example, the listen-port
property takes an integer. If you set it using an expression, the result of the evaluated expression must be an integer. If the type is wrong, the server fails to start due to a syntax error.
If the expression cannot be resolved, and there is no default value in the configuration expression, DS also fails to start.
Expression resolvers evaluate expression tokens to literal values.
Expression resolvers get values from the following sources:
Environment variables
You set an environment variable to hold the value.
For example:
export LISTEN_PORT=1389
.The environment variable name must be composed of uppercase characters and underscores. The name maps to the expression token as follows:
Uppercase characters are lower cased.
Underscores,
_
, are replaced with.
characters.
In other words, the value of
LISTEN_PORT
replaces&{listen.port}
in the server configuration.Java system properties
You set a Java system property to hold the value.
Java system property names must match expression tokens exactly. In other words, the value of the
listen.port
system property replaces&{listen.port}
in the server configuration.Java system properties can be set in a number of ways. One way of setting system properties for DS servers is to pass them through the
OPENDJ_JAVA_ARGS
environment variable.For example:
export OPENDJ_JAVA_ARGS="-Dlisten.port=1389"
Expressions files (optional)
You set a key in a
.json
or.properties
file to hold the value. This optional mechanism is set using theDS_ENVCONFIG_DIRS
environment variable, or theds.envconfig.dirs
Java system property.Keys in
.properties
files must match expression tokens exactly. In other words, the value of thelisten.port
key replaces&{listen.port}
in the server configuration.The following example properties file sets the listen port:
listen.port=1389
JSON expression files can contain nested objects.
JSON field names map to expression tokens as follows:
The JSON path name matches the expression token.
The
.
character serves as the JSON path separator character.
The following example JSON file sets the listen address and listen port:
{ "listen": { "address": "192.168.0.10", "port": "1389" } }
In other words, the value of the
listen/port
field replaces&{listen.port}
in the server configuration.In order to use expression files, set the environment variable,
DS_ENVCONFIG_DIRS
, or the Java system property,ds.envconfig.dirs
, to a comma-separated list of the directories containing the expression files.Note the following constraints when using expression files:
Although DS browses the directories in the specified order, within a directory DS scans the files in a non-deterministic order.
DS reads all files with
.json
and.properties
extensions.DS does not scan subdirectories.
Do not define the same configuration token more than once in a file, as you cannot know in advance which value will be used.
You cannot define the same configuration token in more than one file in a single directory.
If the same token occurs in more than one file in a single directory, an error occurs.
If the same token occurs once in several files which are located in different directories, the first value that DS reads is used.
The preceding list reflects the order of precedence:
Environment variables override system properties, default token settings, and settings in any expression files.
System properties override default token settings, and any settings in expression files.
If
DS_ENVCONFIG_DIRS
ords.envconfig.dirs
is set, then the server uses settings found in expression files.Default token settings (
ds.config.dir
,ds.instance.dir
,ds.install.dir
).
For an embedded DS server, it is possible to change the expression resolvers, in the server configuration.
Using Multivalued Expressions
A single expression token can evaluate to multiple property values. Such expressions are useful with multivalued properties.
For example, suppose you choose to set a connection handler's ssl-cipher-suite
property. Instead of listing cipher suites individually, you use an ssl.cipher.suites
token that takes multiple values. The following example commands set the token value in the environment, stop the server, use the expression in the LDAP connection handler configuration while the server is offline, and then start the server again:
$export SSL_CIPHER_SUITES=\ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,\ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,\ TLS_EMPTY_RENEGOTIATION_INFO_SCSV
$stop-ds --quiet
$dsconfig \ set-connection-handler-prop \ --offline \ --handler-name LDAPS \ --add ssl-protocol:TLSv1.2 \ --add ssl-cipher-suite:'&{ssl.cipher.suites}' \ --no-prompt
$start-ds --quiet
Multiple values are separated by commas in environment variables, system properties, and properties files. They are formatted as arrays in JSON files.
Use one of the following alternatives to set the value of the ssl.cipher.suites
token. When the server evaluates &{ssl.cipher.suites}
, the result is the following property values:
ssl-cipher-suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 ssl-cipher-suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ssl-cipher-suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 ssl-cipher-suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ssl-cipher-suite: TLS_EMPTY_RENEGOTIATION_INFO_SCSV
- Environment Variable
export SSL_CIPHER_SUITES=\ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,\ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,\ TLS_EMPTY_RENEGOTIATION_INFO_SCSV
- System Property
export OPENDJ_JAVA_ARGS="-Dssl.cipher.suites=\ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,\ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,\ TLS_EMPTY_RENEGOTIATION_INFO_SCSV"
- Properties File
ssl.cipher.suites=\ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,\ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,\ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,\ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,\ TLS_EMPTY_RENEGOTIATION_INFO_SCSV
- JSON File
{ "ssl.cipher.suites": [ "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" ] }
Alternative JSON file that sets
ssl.protocol
as well:{ "ssl": { "protocol": "TLSv1.2", "cipher.suites": [ "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_EMPTY_RENEGOTIATION_INFO_SCSV" ] } }
In order to fully use the settings in this file, you would have to change the example to include the additional expression:
--add ssl-protocol:'&{ssl.protocol}'
.
Debugging Expressions
You can debug configuration expressions. Create a debug target for org.forgerock.config.resolvers
. The following example demonstrates the process:
$dsconfig \ create-debug-target \ --hostname localhost \ --port 4444 \ --bindDN uid=admin \ --bindPassword password \ --publisher-name "File-Based Debug Logger" \ --type generic \ --target-name org.forgerock.config.resolvers \ --set enabled:true \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --no-prompt
$dsconfig \ set-log-publisher-prop \ --hostname localhost \ --port 4444 \ --bindDN uid=admin \ --bindPassword password \ --publisher-name "File-Based Debug Logger" \ --set enabled:true \ --usePkcs12TrustStore /path/to/opendj/config/keystore \ --trustStorePasswordFile /path/to/opendj/config/keystore.pin \ --no-prompt
$stop-ds --restart --quiet
When the server starts, it logs debugging messages for configuration expressions. Do not leave debug logging enabled in production systems.