Secrets Resolution in Config Maps
In general, services may have secrets or sensitive data inside their configuration files (Config Maps),
such as connection strings or credentials. This usually performed for grouping a set of configuration properties together
and reduce the clutter generated by a large number of environment variables.
Since these configuration are stored in plain text (differently from Secrets),
anybody with the access to them can read their content.
Therefore, to prevent unauthorized access to those details, the initial approach for solving this issue was to interpolate variables within config maps, using the {{<env_var_name>}}
syntax.
For example, assuming the client identifier for our application is stored within the environment variable APP_CLIENT_ID
and we wanted to add such value
to a config map using the interpolation feature of mlp
, we would write a config map as follows:
{
"cool-config": {
"app": {
"client-id": "{{APP_CLIENT_ID}}"
}
}
}
Although this solution avoids writing secrets in plain text while config maps are stored in a repository (for versioning them), it does not prevent users with access to K8s config maps to read those secrets once configurations are deployed.
To address this pitfall and provide an agnostic solution that works with any deploy tool, we introduced within our service a logic of secrets resolution, which allows injecting secrets within configuration files only within the service at runtime (after a config maps is mounted and read by the service).
Secrets can be injected via secret resolution within a config map as:
- plain text, that is providing the real or interpolated value
- reference to an environment variable
- reference to a file, either its full content or the internal key of a
.ini
file
These are the services versions that support this feature in their config maps:
Service | Version |
---|---|
Projection Storer | >=1.2.0 |
Real-Time Updater | planned |
Single View Trigger Generator | >=3.3.1 |
Single View Creator | planned |
Control Plane | >=1.1.0 |
Fabric BFF | >=1.0.0 |
Please, verify in the documentation and in the service configuration schema which config properties support secret resolution mechanism.
Plain Text
The field is set to be a string and it is loaded directly from the Config Map itself.
{
"some-entry": {
// ...,
"some-secret-field": {
"url": "{{CONNECTION_STRING}}"
}
}
}
Remember to use external environment variables, to avoid store them in plain in your Console configuration!
This mode provides backward compatibility with any of your existing configuration, so that
- you may upgrade your services with confidence without the need to change your config maps
- you may try out the secret resolution method and potentially revert your changes without breaking your services
Environment Variable
The field is populated by a microservice environment variable.
{
"some-entry": {
// ...,
"some-secret-field": {
"url": {
"type": "env",
"key": "<ENVIRONMENT VARIABLE NAME>"
}
}
}
}
By default the value contained in the environment variable that is referenced within the secret is expected to be a plain text.
However, the secret definition allows to define the encoding
property to base64
, so that the value contained in the
environment variable can be written in base64
format.
{
"some-entry": {
// ...,
"some-secret-field": {
"url": {
"type": "env",
"key": "<ENVIRONMENT VARIABLE NAME>",
"encoding": "base64"
}
}
}
}
File Reference
The field is populated by the content of a file mounted inside the microservice, such as file a K8s secret.
To help in creating K8s secrets it is available mpl
tool which automate secrets creation of the ones configured in the mlp.yaml
file that can be found within your Console Project repository.
Full Content
{
"some-entry": {
// ...
"some-secret-field": {
"url": {
"type": "file",
"path": "/path/to/file"
}
}
}
}
Using the above configuration the service will load the whole file content within the configuration property (in this case some-secret-field
).
Single key from .ini file
Secret resolution of files supports also the .ini
format, that is a file with key-value pair values.
Consequently, it is possible to specify which key within the selected file should be loaded in the microservice configmap's property.
{
"some-entry": {
// ...
"some-secret-field": {
"url": {
"type": "file",
"path": "/path/to/file.ini",
"key": "KEY_NAME"
}
}
}
}
For example, let's consider the above configuration and the following .ini
file:
KEY_NAME=cool-secret
OTHER_KEY=uninteresting-secret
which is mounted as secret in the microservice at the path /path/to/file.ini
. As a result, the value that
the microservice will read when accessing the config property some-secret-field
is cool-secret
associated to KEY_NAME
key.