Allows to template multiple Kubernetes Secrets into one file which is not supported by Kubernetes.
Whenever multiple secrets are needed inside files, e.g. when applications are using configuration files that include secrets.
We assume that applications configuration (files) are stored in Configmaps. Instead of directly mounting the configfile to application containers, it is mounted to the k8s-multi-secret-to-file init container. All secrets needed by the application are also mounted to the init container, allowing the templating mechanism to inject secrets into application configuration. The rendered templates are available to application containers using shared volumes between init containers and regular containers inside one Pod.
The example inside examples/simple
can be used for development when operating locally. Example docker command for local use is:
docker run -v $(pwd)/tests/secrets:/var/run/secrets/spreadgroup.com/multi-secret/secrets -v $(pwd)/examples/simple/templates:/var/run/secrets/spreadgroup.com/multi-secret/templates -v $(pwd)/examples/rendered:/var/run/secrets/spreadgroup.com/multi-secret/rendered docker.io/library/k8s-multi-secret-to-file:local
Make sure the directory mounted to /var/run/secrets/spreadgroup.com/multi-secret/rendered
already exists.
Parameter | Default value | Description |
---|---|---|
continue-on-missing-key | false | Templating of configfiles fails if a (secret) key is missing. This flag allows to continue on missing keys. |
left-delimiter | {{ | Left delimiter for internal templating. Change if this delimiter conflicts with your config format. |
right-delimiter | }} | Right delimiter for internal templating. Change if this delimiter conflicts with your config format. |
secret-path | /var/run/secrets/spreadgroup.com/multi-secret/secrets | Path were secrets are read from. Can be changed for local development or testing. Should not matter when using the container. |
target-base-dir | /var/run/secrets/spreadgroup.com/multi-secret/rendered | Path were rendered files are stored. Can be changed for local development or testing. Should not matter when using the container. |
template-base-dir | /var/run/secrets/spreadgroup.com/multi-secret/templates | Path were template files are read from. Can be changed for local development or testing. Should not matter when using the container. |
A working example can be found in examples/k8s
. The files inside manifests directory can be deployed to a Kubernetes cluster.
-
wrap a configfile inside a configmap, and use
{{ index .Secrets "<secret name>" "<secret key>" }}
as placeholder. (using theindex
function here to allow special chars in secret names and keys)... data: secret-config: |- key1={{ index .Secrets "apache-demo" "secret1" }} key2={{ index .Secrets "apache-demo" "secret2" }} ...
-
provide secrets inside Kubernetes Secrets
... data: secret1: dmFsdWVGcm9tU2VjcmV0 secret2: Mm5kVmFsdWVGcm9tU2VjcmV0 ...
-
configure an init-container using
k8s-multi-secret-to-file
, e.g.... initContainers: image: ghcr.io/spreadshirt/k8s-multi-secret-to-file:latest imagePullPolicy: Always name: secret-init ...
-
provide secrets as files to the init container.
/var/run/secrets/spreadgroup.com/multi-secret/secrets
is the default secret path inside the init-container. For each Secret, configure the volumes:... volumes: - name: apache-demo secret: defaultMode: 420 secretName: apache-demo ...
and the volumeMounts:
... volumeMounts: - mountPath: /var/run/secrets/spreadgroup.com/multi-secret/secrets/apache-demo name: apache-demo readOnly: true ...
-
configure Volumes to allow interaction between the init-container and the application
... volumes: - emptyDir: { } name: init-share - configMap: name: apache-demo-cfg name: configmap ...
-
mount configfile and target path to init-container (IMPORTANT: don't mount the configfile directly to the application container!)
... volumeMounts: - mountPath: /var/run/secrets/spreadgroup.com/multi-secret/rendered name: init-share - mountPath: /var/run/secrets/spreadgroup.com/multi-secret/templates/path/to/secret/config name: configmap subPath: secret-config ...
/var/run/secrets/spreadgroup.com/multi-secret/templates
and/var/run/secrets/spreadgroup.com/multi-secret/rendered
are the default paths for templates and the results, this can be configured, if necessary -
mount the rendered config file to the application container
... volumeMounts: - mountPath: /path/to/secret/config name: init-share subPath: path/to/secret/config ...
-
deploy the application and check the rendered file inside the application container
$ kubectl exec apache-demo-8479b98dd4-82jnn -c apache -- cat /path/to/secret/config key1=valueFromSecret key2=2ndValueFromSecret
This extension allows you to use dynamic keys in your secrets, which could happen if you use an external Secret operator for example.
When is this useful? E.g. if you use keys inside Secrets to represent some kind of hierarchical configuration:
value: my-value
value_aws: aws-specific-value
value_azure: azure-specific-value
Use the following line to access it: value={{ getValueByFirstMatchingKey (index .Secrets "secretValues") "value_aws" "value" }}
This will return the value for the first matching key in .Secrets.secretValues
, aws-specific-value
but would fall back to my-value
in case it does not find a value for key value_aws
.