Kubernetes Secrets Volumes vs Environment Variables

7/16/2018

Is there a recommended way to use Kubernetes Secrets? They can be exposed as environment variables or using a volume mount. Is one more secure than the other?

-- Muhammad Rehan Saeed
docker-volume
environment-variables
kubernetes
kubernetes-secrets
kubernetes-security

7 Answers

1/7/2020

Mounted Secrets are updated automatically

  • When a secret being already consumed in a volume is updated, projected keys are eventually updated as well. Kubelet is checking whether the mounted secret is fresh on every periodic sync. However, it is using its local cache for getting the current value of the Secret. 

  • in an multi container pod, each container inside a pod has to request the secret volume in its volumeMounts for it to be visible within the container. This can be used to construct useful security partition at pod level. 

With above finding from official docs secret by volume mount look a better option.

-- DT.
Source: StackOverflow

7/16/2018

Secrets are by default safer than environment variables, since they are encrypted and have a thinner scope than an environment variable which is exposed in the underlying environment where a process is run.

In Kubernetes if I'm not mistaken that functionality is definitely limited to base64 encoding/decoding, so in practice it does not provide real encryption-as-a-service.

But if you are lean on providing a better security control over your application's secrets and integrating it seamlessly with Kubernetes, you should definitely check out Vault by Hashicorp, which I think it's an amazing tool and one of it's main objectives is to provide as easily as possible encryption-as-a-service and reduce problems such as the phenomenon of secret sprawling.

-- André B
Source: StackOverflow

1/7/2020

kubernetes secrets as the name, are objects used to store sensitive data such as user name and passwords with encryption.

example :

kubectl create secret generic cloudsql-user-credentials --from-literal=username=[user] --from-literal=password=[password]

ConfigMaps can be used to store fine-grained information: properties. yaml example:

apiVersion: v1
kind: ConfigMap
metadata:
  name: example
  namespace: docker4openshift
data:
  app.database.name: [instance.db.name]

In general secrets are used for pass & user, configmap for database name etc.

-- Tiago Medici
Source: StackOverflow

3/19/2020

I've also had the same question and have been looking for a definitive answer regarding environment variables vs. volumes. I can't find anything, just discussions like these. The Kuberentes documentation doesn't address this either, except to noted by DT. above, and even that is lacking a bit. Addressing some of what's discussed here I have my opinions, which aren't necessarily correct, just what I've been able to surmise. If I'm misunderstanding something I welcome corrections. Here's my understanding:

  1. Like bells17 I don't see any difference in security between environment vars and volumes/files, both are easily accessible just by logging into the pod.
  2. WRT 12 factor apps, I agree with jamesconant. I don't think there is any difference. In both cases they're part of the secret specification which is the source of the information regardless of whether it gets projected as a file or an environment variable. You can put the secret spec (and other specs) in a separate repo if needed to fully separate code from configuration.
  3. Secrets are not secure unless encrypted at rest in etcd. As noted by Andre B other options like Vault are possible.
-- Rich
Source: StackOverflow

11/26/2019

I agree with TMCs answer, but wanted to add a note for those that are thinking, "But what about 12-factor??". Objections are sometimes raised against using volume-mounted secrets because 12F seemingly requires configs be stored as ENV vars. First, these are suggested, voluntary, your-mileage-may-vary best-practices suggestions. Second, there is this section:

In a twelve-factor app, env vars are granular controls, each fully orthogonal to other env vars. They are never grouped together as “environments”, but instead are independently managed for each deploy. This is a model that scales up smoothly as the app naturally expands into more deploys over its lifetime.

source: https://12factor.net/config

Basically, coupled with the rest of the description I understand the guiding principles of 12F Config management to be:

  • Keep config out of source
  • Be able to inject config into source artifact (e.g. a docker container)
  • Be able to make granular changes to the set of required configuration values

In my humble opinion, volume mounted Kubernetes Secrets can accomplish these goals depending on what sort of Secret objects you create and how you manage them.

-- jamesconant
Source: StackOverflow

11/19/2018

https://www.oreilly.com/library/view/velocity-conference-2017/9781491985335/video316233.html

Kubernetes secrets exposed by environment variables may be able to be enumerated on the host via /proc/. If this is the case it's probably safer to load them via volume mounts.

-- tmc
Source: StackOverflow

1/8/2020

I don't think there is any difference in safety. Because If a node is compromised, they can see the secret.

example:

---
apiVersion: v1
kind: Secret
metadata:
  name: mount
type: Opaque
data:
  foo: ""

---
apiVersion: v1
kind: Secret
metadata:
  name: env
type: Opaque
data:
  BAR: "BAR"


---
apiVersion: v1
kind: Pod
metadata:
  name: mount
spec:
  containers:
    - name: nginx
      image: nginx
      ports:
      - containerPort: 80
      envFrom:
        - secretRef:
            name: env
      volumeMounts:
      - name: mount
        mountPath: "/opt/mount"
        readOnly: true
  volumes:
  - name: mount
    secret:
      secretName: mount
$ kubectl exec mount -- ls -la /opt/mount
total 0
drwxrwxrwt 3 root root 100 Jan  8 03:00 .
drwxr-xr-x 1 root root  19 Jan  8 03:00 ..
drwxr-xr-x 2 root root  60 Jan  8 03:00 ..2020_01_08_03_00_13.066710719
lrwxrwxrwx 1 root root  31 Jan  8 03:00 ..data -> ..2020_01_08_03_00_13.066710719
lrwxrwxrwx 1 root root  10 Jan  8 03:00 foo -> ..data/foo

$ kubectl exec mount -- env | grep BAR
BAR=

$ docker ps | grep mount
8dbde26864a4        nginx                                                                                "nginx -g 'daemon of…"   8 minutes ago       Up 8 minutes                            k8s_nginx_mount_default_3438a94b-e4af-41a7-8d85-7668fcbd9928_0
$ docker inspect 8dbde26864a4 | grep -A 1 '"Env"'
            "Env": [
                "BAR=",
$ docker inspect 8dbde26864a4 | grep '"Source"' | grep mount
"Source": "/var/lib/kubelet/pods/3438a94b-e4af-41a7-8d85-7668fcbd9928/volumes/kubernetes.io~secret/mount"
$ ls -la /var/lib/kubelet/pods/3438a94b-e4af-41a7-8d85-7668fcbd9928/volumes/kubernetes.io~secret/mount
合計 0
drwxrwxrwt 3 root root 100  18 12:00 .
drwxr-xr-x 4 root root  46  18 12:00 ..
drwxr-xr-x 2 root root  60  18 12:00 ..2020_01_08_03_00_13.066710719
lrwxrwxrwx 1 root root  31  18 12:00 ..data -> ..2020_01_08_03_00_13.066710719
lrwxrwxrwx 1 root root  10  18 12:00 foo -> ..data/foo

And you can see the secret design proposal https://github.com/kubernetes/community/blob/master/contributors/design-proposals/auth/secrets.md

It is written like this

If a node is compromised, the only secrets that could potentially be exposed should be the secrets belonging to containers scheduled onto it

So I think the secret does not seem to guarantee the protection of the container's secret when a node is compromised.

-- bells17
Source: StackOverflow