Can Kubernetes secrets store newlines?

11/14/2018

I've created a secret from a file using a command like:

kubectl create secret generic laravel-oauth \
        --from-file=./.work-in-progress/oauth_private.key \
        --from-file=./.work-in-progress/oauth_public.key

However it seems new lines are stripped from the files (when using the secrets as ENV variables).

There is a 'encoding' note in the docs that state:

The serialized JSON and YAML values of secret data are encoded as base64 strings. Newlines are not valid within these strings and must be omitted. When using the base64 utility on Darwin/macOS users should avoid using the -b option to split long lines. Conversely Linux users should add the option -w 0 to base64 commands or the pipeline base64 | tr -d '\n' if -w option is not available.

However I assumed this only applies for 'manually' created secrets via YAML files.

-- Chris Stryczynski
kubernetes

3 Answers

11/15/2018

It seems newlines work fine (maybe I ran into another issue earlier).

Here is a full example:

#!/usr/bin/env bash
set -euo pipefail

printf "123\n456\n789" > ./.work-in-progress/example.txt

kubectl create secret generic example-test \
        --from-file=./.work-in-progress/example.txt \
        --dry-run -o yaml | kubectl apply -f -

cat <<EOF | kubectl apply -f -
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: example
  labels:
    app: example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: example
  template:
    metadata:
      labels:
        app: example
    spec:
      volumes:
      - name: example-test-volume
        secret:
          secretName: example-test
      containers:
        - name: app
          command: ["sleep", "99999999"]
          image: busybox:latest
          imagePullPolicy: IfNotPresent
          volumeMounts:
            - name: example-test-volume
              mountPath: /tmp/example
          env:
            - name: exampleenv
              valueFrom:
                secretKeyRef:
                  name: example-test
                  key: example.txt


EOF
-- Chris Stryczynski
Source: StackOverflow

11/14/2018

The note you refer to is for the base64 encoded string itself (not the content that was encoded).

Using secrets as env var will potentially expose them via the dashboard "preview eye" (if you use the Kube Dashboard), you should mount them into a directory and make the app load them from there instead; I fell for that too and was surprised I was able to view the secret.

I've not come across the stripping of new line characters, as the above command would simply do a base64 of the content (including new line chars). That said, storing the secrets b64 encoded is not exactly safe either, you should consider using sealed-secrets (bitnami) instead, it works just like normal secrets, but is actually encrypted at rest.

HTH, Alex

-- Alex
Source: StackOverflow

11/14/2018

The new lines are not stripped the files are just base64 encoded as mentioned in the other answers too. For example:

# mycert.pem
-----BEGIN CERTIFICATE-----
xxxxxx
xxxxxx
...
-----END CERTIFICATE-----

Then:

$ kubectl create secret generic mysecret --from-file=./cert.pem

Then:

$ kubectl get secret mysecret -o=yaml

apiVersion: v1
data:
  cert.pem: <base64 encoded string>
kind: Secret
metadata:
  creationTimestamp: 2018-11-14T18:11:46Z
  name: mysecret
  namespace: default
  resourceVersion: "20180431"
  selfLink: /api/v1/namespaces/default/secrets/mysecret
  uid: xxxxxx
type: Opaque

Then if you decode it, you will get the original secret.

$ echo '<base64 encoded string>' | base64 -D
-----BEGIN CERTIFICATE-----
xxxxxx
xxxxxx
...
-----END CERTIFICATE-----

Also, this is not necessarily secure at rest. If you are looking for more security you can use something like Hashicorp Vault or as alluded by @Alex Bitnami's sealed secrets.

-- Rico
Source: StackOverflow