In Kubernetes, secret resources are base64 encoded. This is an example yaml file from the official documentation:
apiVersion: v1
kind: Secret
metadata:
name: test-secret
data:
USERNAME: bXktYXBwCg==
PASSWORD: YV44KXlcNzw4QUF4YWEoeV54
Where the two pieces of secret data: a username and a password were base64 encoded using:
echo -n 'my-app' | base64
echo -n 'a^8)y\7<8AAxaa(y^x' | base64
The workflow I would like is to have a version of the yaml file with my naked secrets and a Makefile
which could produce the base64 encoded version.
This is where I got to before I got stuck:
The input (my-secrets-naked.yaml
):
apiVersion: v1
kind: Secret
metadata:
name: test-secret
data:
USERNAME: my-app
PASSWORD: a^8)y\7<8AAxaa(y^x
The Makefile
:
base64:
@echo "Computing base64 of secret values..."
cat my-secrets-naked.yaml | bash base64_secrets.sh > my-secrets-base64.yaml
The base64_secrets.sh
script:
sed -r 's/(\s+[A-Z]\S+:\s*)(.*)/echo "\1$(echo -n "\2" | base64 -w0 )"/e;s/ -//'
The command: make base64
The output (my-secrets-base64.yaml
):
apiVersion: v1
kind: Secret
metadata:
name: test-secret
data:
USERNAME: bXktYXBw
PASSWORD: YV44KXkHPDhBQXhhYSh5Xng=
Ideally, I would like the sed
inside the Makefile
rather than a separate script but I couldn't figure it out. But most importantly the base64 for the PASSWORD is wrong! It breaks for secrets with backslashes in, in this case the \7
causes problems. I can't figure out how to echo the unescaped characters whilst still using the \2
back reference from the preceding sed
. (echo -E
doesn't work, it takes \2
literally. No luck with printf '%s' \2
either).
I know it seems like a specific question - but a good solution for this could be useful for all Kubernetes users?
If I get this workflow working I intend to extend it so the Makefile produces a 3rd file with the secrets redacted and hashed so safe to be committed in git, whilst still knowing when something changed.
I'm using Ubuntu 16.04, sed (GNU sed) 4.2.2.
Consider using the stringData
field instead of the data
field and you can pass in unencoded value. It will still be stored as data
internally and shows as such when queried back.
DESCRIPTION:
Secret holds secret data of a certain type. The total bytes of the values in the Data field must be less than MaxSecretSize bytes.
FIELDS:
type <string>
Used to facilitate programmatic handling of secret data.
apiVersion <string>
APIVersion defines the versioned schema of this representation of an
object. Servers should convert recognized schemas to the latest internal
value, and may reject unrecognized values. More info:
http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources
data <object>
Data contains the secret data. Each key must be a valid DNS_SUBDOMAIN or
leading dot followed by valid DNS_SUBDOMAIN. The serialized form of the
secret data is a base64 encoded string, representing the arbitrary (possibly
non-string) data value here. Described in
https://tools.ietf.org/html/rfc4648#section-4
kind <string>
Kind is a string value representing the REST resource this object
represents. Servers may infer this from the endpoint the client submits
requests to. Cannot be updated. In CamelCase. More info:
http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds
metadata <Object>
Standard object's metadata. More info:
http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
stringData <object>
stringData allows specifying non-binary secret data in string form. It is
provided as a write-only convenience method. All keys and values are merged
into the data field on write, overwriting any existing values. It is never
output when reading from the API.
I would perhaps suggest using JSON rather than YAML though.
you can do this with perl.
cat Makefile
base64:
@echo "Computing base64 of secret values..."
cat my-secrets-naked.yaml|perl -MMIME::Base64 -npe 's/^(\s+[A-Z]+:\s+)(.*)./"$1".encode_base64($2)/es;' > my-secrets-base64.yaml
Here is the output:
cat my-secrets-base64.yaml
apiVersion: v1
kind: Secret
metadata:
name: test-secret
data:
USERNAME: bXktYXBw
PASSWORD: YV44KXlcNzw4QUF4YWEoeV54