Use Kubernetes secrets as environment variables inside a config map

11/28/2019

I have an application in a container which reads certain data from a configMap which goes like this

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  application.yaml: |
        server:
          port: 8080
          host: 0.0.0.0

        ##
        ## UCP configuration.
        ## If skipped, it will default to looking inside of the connections.xml file.
        database:
            ApplicationDB:
                username: username
                password: hello123

Now I created a secret for the password and mounted as env variable while starting the container.

apiVersion: v1
kind: Secret
metadata:
  name: appdbpassword
type: Opaque
stringData:
  password: hello123

My pod looks like:

apiVersion: v1
kind: Pod
metadata:
  name: {{ .Values.pod.name }}
spec:
  containers:
    - name: {{ .Values.container.name }}
      image: {{ .Values.image }}
      command: [ "/bin/sh", "-c", "--" ]
      args: [ "while true; do sleep 30; done;"]
      env:
      - name: password
        valueFrom:
          secretKeyRef:
            name: appdbpassword
            key: password
      volumeMounts:
      - name: config-volume
        mountPath: /app/app-config/application.yaml
        subPath: application.yaml
  volumes:
    - name: config-volume
      configMap:
        name: app-config

I tried using this env variable inside the configMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  application.yaml: |
        server:
          port: 8080
          host: 0.0.0.0

        ##
        ## UCP configuration.
        ## If skipped, it will default to looking inside of the connections.xml file.
        database:
            ApplicationDB:
                username: username
                **password: ${password}**

But my application is unable to read this password. Am I missing something here?

EDIT:

I cannot change the application.yaml to any other form as my server looks for application.yaml in source path. Do we have any way to use that environment variable in values.yaml(helm) file and use it in the configmap?

-- Bhargav Behara
kubernetes
kubernetes-helm
kubernetes-pod
kubernetes-secrets

2 Answers

11/28/2019

your ${password} variable will not be replaced by its value as application.yaml is a static file. If you use this yaml file in some configuration then it is possible that it will get replaced by its value.

consider a scenario where instead of application.yaml pass this file

application.sh: |
       echo "${password}"

now go inside /app/app-config you will see application.sh file . And now do sh application.sh you will see the value of environment variable.

I hope this might clear your point.

-- shubham_asati
Source: StackOverflow

11/28/2019

You cannot use a secret in ConfigMap as they are intended to non-sensitive data (See here).

Also you should not pass Secrets using env's as it's create potential risk (Read more here why env shouldn't be used). Applications usually dump env variables in error reports or even write the to the app logs at startup which could lead to exposing Secrets.

The best way would be to mount the Secret as file. Here's an simple example how to mount it as file:

spec:
  template:
    spec:
      containers:
      - image: "my-image:latest"
        name: my-app
        ...
        volumeMounts:
          - mountPath: "/var/my-app"
            name: ssh-key
            readOnly: true
      volumes:
        - name: ssh-key
          secret:
            secretName: ssh-key

Kubernetes documentation explains well how to use and mount secrets.

-- acid_fuji
Source: StackOverflow