Since version 4.2, MongoDB provides a new interesting feature called Externally Sourced Configuration File Values. It allows administrators to specify that particular variables will have their values loaded from an external resource.
The external resources that are supported, at this time, are:
- REST APIs, which will cause MongoDB to perform HTTP GET requests to a given URL
- Processes, which will cause MongoDB to run a specified binary and use the returned value
This feature has a lot of use cases, and providing the x509 certificate password without having it stored in the file is one of them. It can easily achieve it with the following configuration:
1 2 3 4 5 6 7 | net: tls: … certificateKeyFile: "/etc/tls/mongod.pem" certificateKeyFilePassword: __exec: "/usr/bin/getCertificatePassword" type: "string" |
or by using REST API:
1 2 3 4 5 6 7 | net: tls: … certificateKeyFile: "/etc/tls/mongod.pem" certificateKeyFilePassword: __rest: "https://apiserver.invalid/getCertificatePassword" type: "string" |
Within the scope of Externally Sourced Configuration File Values, MongoDB also introduces a unique feature, allowing users to use only the expected value. For instance, if someone wants to protect from the external resource mistakenly returning a wrong value, the user can provide a SHA256-HMAC digest of the expected value. By using that, the value is known to an administrator, can be used by MongoDB, and it’s still not stored in the configuration file.
Let’s consider the trivial example of:
1 2 3 4 5 6 7 | … port: __exec: "/usr/local/bin/getPort" type: "string" trim: "whitespace" digest: c50bdabc0c9268b72c483eba6bc9a449c486bafbda077759aff214f1437dc152 digest_key: 0123456789abcdef |
The /usr/local/bin/getPort
is a simple script that returns a single integer:
1 2 | #!/bin/bash echo 21010 |
The digest key was chosen randomly, and the digest itself is sha256-hmac of literal 21010
:
1 2 | $ echo -ne 21010 | openssl dgst -sha256 -mac hmac -macopt hexkey:0123456789abcdef (stdin)= c50bdabc0c9268b72c483eba6bc9a449c486bafbda077759aff214f1437dc152 |
After starting it, MongoDB works fine, and it uses 21010/tcp
As defined in the provider script:
1 2 3 4 5 | # mongod -f /etc/mongod.conf --configExpand "rest,exec" {"t":{"$date":"2021-10-21T12:55:18.767Z"},"s":"I", "c":"CONTROL", "id":23318, "ctx":"main","msg":"Processing config expansion","attr":{"expansion":"__exec","node":"net.port"}} # netstat -nlput | grep -i 21010 tcp 0 0 127.0.0.1:21010 0.0.0.0:* LISTEN 1463/mongod |
After changing the returned value to 201011
, but leaving the expected digest unchanged, MongoDB refuses to start and returns an error:
1 2 3 4 | # mongod -f /etc/mongod.conf --configExpand "rest,exec" {"t":{"$date":"2021-10-21T12:55:51.458Z"},"s":"I", "c":"CONTROL", "id":23318, "ctx":"main","msg":"Processing config expansion","attr":{"expansion":"__exec","node":"net.port"}} SHA256HMAC of config expansion KQG2ytlnfaqo8gU1UG/q1eTf2fEdPUJYXIernXF8Qj8= does not match expected digest: xQvavAySaLcsSD66a8mkScSGuvvaB3dZr/IU8UN9wVI= try 'mongod --help' for more information |
As the expected and received value digest changed, MongoDB decided not to trust the received value. This could be used for passwords and tokens in real-life scenarios as the data won’t be stored in the config file, but MongoDB will still accept only a single expected value. This provides integrity of the critical configuration data but still allows MongoDB to be more flexible in fetching data from remote endpoints.
Complete the 2021 Percona Open Source Data Management Software Survey