Categories
Kubernetes

Kubernetes: Can you keep a secret?

Can you keep a Secret? Kubernetes can.

https://kubernetes.io/docs/concepts/configuration/secret/

There are a few ways to create secrets within Kubernetes.

What we will learn

  • Default Service Account and Secret
  • Create from a literal command
  • Create from a file
  • Create from a folder
  • Create from a YAML file
  • Copy a secret from one namespace to another
  • Encoding and decoding (base64)
  • Pod — Mounting secrets within a pod
  • Deployment — MySQL deployment using a secret as the password

Notes

  • Mounted Secrets are updated automatically
  • A container using a Secret as a subPath volume mount will not receive Secret updates
  • All key values within a K8 cluster are base64 encoded by default
  • Key values within YAML files need to be base64 encoded

Quick Reference

kubectl get secrets
kubectl get secrets SECRET_NAME -o yaml
kubectl create secret generic --help
kubectl create secret generic SECRET_NAME --from-literal=password=YOUR_PASSWORD
kubectl create secret generic SECRET_NAME --from-literal=username=YOUR_USERNAME --from-literal=password=YOUR_PASSWORD

Create namespace

This is the namespace I will be using within this blog.

kubectl create -n itsmetommy

Default Service Account and Secret

You will notice that each namespace has a default ServiceAccount and a default Secret. When you create a pod, if you do not specify a ServiceAccount, it is automatically assigned the default ServiceAccount in the same namespace, which uses the default Secret token as credentials.

kubectl -n itsmetommy get serviceaccounts
NAME SECRETS AGE
default 1 25d
kubectl -n itsmetommy get secrets
NAME TYPE DATA AGE
default-token-2p2sw kubernetes.io/service-account-token 3 25d

Create from a literal command

Create secret

kubectl -n itsmetommy create secret generic literal-example --from-literal=username=tommy --from-literal=password=123456789

Get secret

kubectl -n itsmetommy get secret literal-example -o yaml
apiVersion: v1
data:
password: MTIzNDU2Nzg5
username: dG9tbXk=
kind: Secret
metadata:
creationTimestamp: 2018-12-10T21:46:54Z
name: literal-example
namespace: itsmetommy
resourceVersion: "342825"
selfLink: /api/v1/namespaces/itsmetommy/secrets/literal-example
uid: 1bdea529-fcc5-11e8-be43-080027beeecc
type: Opaque

You’ll notice that the key values are base64 encoded.

Decode secret

echo 'MTIzNDU2Nzg5' | base64 --decode
123456789
echo 'dG9tbXk=' | base64 --decode
tommy

Clean up

kubectl -n itsmetommy delete secret literal-example

Create from a file

Create files

echo -n 'tommy' > username
echo -n '123456789' > password

Create secret

kubectl -n itsmetommy create secret generic files-example --from-file=username --from-file=password

Get secret

kubectl -n itsmetommy get secret files-example -o yaml
apiVersion: v1
data:
password: MTIzNDU2Nzg5
username: dG9tbXk=
kind: Secret
metadata:
creationTimestamp: 2018-12-10T21:53:05Z
name: files-example
namespace: itsmetommy
resourceVersion: "343235"
selfLink: /api/v1/namespaces/itsmetommy/secrets/files-example
uid: f90f0f2f-fcc5-11e8-be43-080027beeecc
type: Opaque

You’ll notice that the key values are base64 encoded.

Decode secret

echo 'MTIzNDU2Nzg5' | base64 --decode
123456789
echo 'dG9tbXk=' | base64 --decode
tommy

Clean up

kubectl -n itsmetommy delete secret files-example

Create from a folder

Create folder

mkdir folder-example

Create files within dir

echo -n tommy > folder-example/username; echo -n 123456789 > folder-example/password

Create secret

kubectl -n itsmetommy create secret generic folder-example --from-file=folder-example

Get secret

kubectl -n itsmetommy get secret folder-example -o yaml
apiVersion: v1
data:
password: MTIzNDU2Nzg5
username: dG9tbXk=
kind: Secret
metadata:
creationTimestamp: 2018-12-11T23:32:39Z
name: folder-example
namespace: itsmetommy
resourceVersion: "407456"
selfLink: /api/v1/namespaces/itsmetommy/secrets/folder-example
uid: 0c68fc51-fd9d-11e8-be43-080027beeecc
type: Opaque

Decode secret

echo 'MTIzNDU2Nzg5' | base64 --decode
123456789
echo 'dG9tbXk=' | base64 --decode
tommy

Clean up

kubectl -n itsmetommy delete secret folder-example

Create from a YAML file

IMPORTANT: Each item must be base64 encoded.

Encode values

echo 'tommy' | base64
dG9tbXk=
echo '123456789' | base64
MTIzNDU2Nzg5

Create secret.yaml

apiVersion: v1
kind: Secret
metadata:
name: yaml-example
namespace: itsmetommy
type: Opaque
data:
username: dG9tbXk=
password: MTIzNDU2Nzg5

Create secret

kubectl -n itsmetommy create -f secret.yaml

Get secret

kubectl -n itsmetommy get secret yaml-example -o yaml
apiVersion: v1
data:
password: MTIzNDU2Nzg5
username: dG9tbXk=
kind: Secret
metadata:
creationTimestamp: 2018-12-10T23:10:20Z
name: yaml-example
namespace: itsmetommy
resourceVersion: "348464"
selfLink: /api/v1/namespaces/itsmetommy/secrets/yaml-example
uid: c3fccfda-fcd0-11e8-be43-080027beeecc
type: Opaque

Decode secret

echo 'MTIzNDU2Nzg5' | base64 --decode
123456789
echo 'dG9tbXk=' | base64 --decode
tommy

Clean up

kubectl -n itsmetommy delete secret yaml-example

Copy a secret from one namespace to another

Copy SECRET_NAME from NAMESPACE_A to NAMESPACE_B.

kubectl get secret -n NAMESPACE_A SECRET_NAME --export -o yaml \
| kubectl apply -n NAMESPACE_B -f -

OR you can use jq.

Install jq.

brew install jq

Copy SECRET_NAME from NAMESPACE_A to NAMESPACE_B.

kubectl -n NAMESPACE_A get secret SERECT_NAME -o json \
| jq '.metadata.namespace = "NAMESPACE_B"' \
| kubectl create -f -

Encoding and decoding (base64)

As you’ve seen already within this blog, I’ve decoded and encoded key values. At this point, it should be review.

  • All key values are base64 encoded by default
  • Key vaules within YAML files need to be base64 encoded

Decode secret

echo 'MTIzNDU2Nzg5' | base64 --decode
123456789
echo 'dG9tbXk=' | base64 --decode
tommy

Encode secret

echo 'tommy' | base64
dG9tbXk=
echo '123456789' | base64
MTIzNDU2Nzg5

Clone git repository

You may clone my repo if you’d like to follow along.

https://github.com/itsmetommy/kubernetes-secret

Pod — Mounting secrets within a pod

I am going to go over a few different options.

  • pod-01 — Specify path
  • pod-02 — Specify path and key value
  • pod-03 — Specify permission
  • pod-04 — Specify path & permission
  • pod-05 — Environment variables

cd into the pods directory

cd pods

First create the secret that all pods will use.

kubectl create -f mysecret.yaml

Create pod-01 — Specify path

Apply pod

kubectl apply -f pod-01.yaml

Describe pod

Note: Notice the mount is read only.

kubectl -n itsmetommy describe pods pod-01

View secrets within pod

kubectl -n itsmetommy exec pod-01 -- cat /etc/foo/username
tommy
kubectl -n itsmetommy exec pod-01 -- cat /etc/foo/password
123456789

Create pod-02 — Specify path and key value

Apply pod

kubectl apply -f pod-02.yaml

Describe pod

Note: Notice the mount is read only.

kubectl -n itsmetommy describe pods pod-02

View secret within pod.

kubectl -n itsmetommy exec pod-02 -- cat /etc/foo/my-group/my-username
tommy

Create pod-03 — Specify permission

Apply pod

kubectl apply -f pod-03.yaml

Describe pod

kubectl -n itsmetommy describe pods pod-03

View secret file permissions within pod

kubectl -n itsmetommy exec pod-03 -it -- ls -l /etc/foo/..data/
total 8
-r-------- 1 root root 9 Dec 10 23:56 password
-r-------- 1 root root 5 Dec 10 23:56 username

Create pod-04 — Specify path & permission

Apply

kubectl apply -f pod-04.yaml

Describe pod

kubectl -n itsmetommy describe pods pod-04

View secret file permissions within pod

kubectl -n itsmetommy exec pod-04 -it -- ls -l /etc/foo/..data/my-group
total 4
-rwxrwxrwx 1 root root 5 Dec 11 00:01 my-username

Create pod-05 — Environment variables

Apply pod

kubectl apply -f pod-05.yaml

Describe pod

kubectl -n itsmetommy describe pods pod-05

View environment variables within pod

kubectl -n itsmetommy exec pod-05 -it -- env | grep SECRET
SECRET_USERNAME=tommy
SECRET_PASSWORD=123456789

kubectl -n itsmetommy exec pod-05 -it -- bash
root@pod-05:/# echo $SECRET_USERNAME
tommy
root@pod-05:/# echo $SECRET_PASSWORD
123456789

Clean up

kubectl -n itsmetommy delete pods -l app=secret-examples
kubectl -n itsmetommy delete secret mysecret

Deployment — MySQL deployment using a secret as the password

cd into the mysql directory

cd mysql

Create MySQL password secret

kubectl -n itsmetommy create secret generic mysql-pass --from-literal=password=123456789

Apply deployment

This will create a Deployment, PersistentVolume, PersistentVolumeClaim and Service.

kubectl apply -f .

Get pod

kubectl -n itsmetommy get pods | grep mysql
mysql-7844645f76-t557s 1/1 Running 0 1m

Connect to mysql

Note: Use password 123456789.

kubectl -n itsmetommy exec mysql-7844645f76-t557s -it -- mysql -p

Get secrets

kubectl -n itsmetommy get secrets mysql-pass -o yaml
apiVersion: v1
data:
password: MTIzNDU2Nzg5
kind: Secret
metadata:
creationTimestamp: 2018-12-11T00:25:23Z
name: mysql-pass
namespace: itsmetommy
resourceVersion: "353539"
selfLink: /api/v1/namespaces/itsmetommy/secrets/mysql-pass
uid: 3f9ca5ca-fcdb-11e8-be43-080027beeecc
type: Opaque

Decode secret

echo 'MTIzNDU2Nzg5' | base64 --decode
123456789

Clean up

kubectl delete -f .
kubectl -n itsmetommy delete secret mysql-pass