Creation of Secrets within Kubernetes
Secrets are means of storing and managing sensitive information such as passwords, tokens and keys. They are more secure then using ConfigMaps, which store the data in plain text but it should be noted they do not encrypt the data but encode it as Base64.
This post will describe 3 different ways of creating secrets, 2 of which do not rely on manual Base64 encoding and a method of building the manifest file with manually encoded strings.
Creating a Secret Using Files
We will create a secret using a couple of files that contain a username and password, which are in plain text.
salterje@k8s-master:~/YAML/secrets$ ls -lh
total 8.0K
-rw-rw-r-- 1 salterje salterje 23 Jul 12 15:11 password.txt
-rw-rw-r-- 1 salterje salterje 6 Jul 12 15:10 username.txt
salterje@k8s-master:~/YAML/secrets$ cat username.txt
admin
salterje@k8s-master:~/YAML/secrets$ cat password.txt
SuperSecretPassword123
salterje@k8s-master:~/YAML/secrets$
salterje@k8s-master:~/YAML/secrets$ kubectl create secret generic mysecret \
--from-file=username.txt \
--from-file=password.txt
This will create a secret object called mysecret which will have two fields contained within it.
The object can be checked using kubectl get secrets mysecret and more information can be gleaned by using kubectl describe secrets mysecret
salterje@k8s-master:~/YAML/secrets$ kubectl get secrets mysecret
NAME TYPE DATA AGE
mysecret Opaque 2 11m
salterje@k8s-master:~/YAML/secrets$ kubectl describe secrets mysecret
Name: mysecret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
password.txt: 23 bytes
username.txt: 6 bytes
salterje@k8s-master:~/YAML/secrets$
It can be seen that unlike a ConfigMap object the data is not displayed. Even looking at the output YAML file the original data is not displayed as plain text.
salterje@k8s-master:~/YAML/secrets$ kubectl get secrets mysecret -o yaml
apiVersion: v1
data:
password.txt: U3VwZXJTZWNyZXRQYXNzd29yZDEyMwo=
username.txt: YWRtaW4K
kind: Secret
metadata:
creationTimestamp: "2020-07-12T15:13:46Z"
managedFields:
name: mysecret
namespace: default
resourceVersion: "288441"
selfLink: /api/v1/namespaces/default/secrets/mysecret
uid: b7496c8b-3d58-490c-8156-6c124c0d6178
This shows that the original information has been replaced with Base64 strings.
Of course the original data can still be extracted by decoding the Base64 value to reveal the original string.
salterje@k8s-master:~/YAML/secrets$ echo "U3VwZXJTZWNyZXRQYXNzd29yZDEyMwo=" | base64 --decode
SuperSecretPassword123
salterje@k8s-master:~/YAML/secrets$ echo "YWRtaW4K" | base64 --decode
admin
It can be seen that the string containing the data to be decoded should be enclosed in quotes.
Creating a Secret Manually
The secret can also created directly by writing the manifest YAML directly and creating the object with a suitable create or apply command.
The first thing that needs to be done to allow this is to take the string to be encoded and convert it to Base64.
salterje@k8s-master:~/YAML/secrets$ echo -n "admin" | base64
YWRtaW4=
salterje@k8s-master:~/YAML/secrets$ echo -n "SuperSecretPassword123" | base64
U3VwZXJTZWNyZXRQYXNzd29yZDEyMw==
The following YAML manifest can then be created using the Base64 strings generated.
vi mysecret-manifest.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret2
type: Opaque
data:
username: YWRtaW4=
password: U3VwZXJTZWNyZXRQYXNzd29yZDEyMw==
salterje@k8s-master:~/YAML/secrets$ kubectl apply -f mysecret-manifest.yaml
Creating the Manifest File Using the StringData Parameter
The previous methods relied on either importing the desired strings from external files or building a manifest file with pre-encoded Base64 strings. Another way is to combine the steps and allow Kubernetes to encode the strings entered into the manifest file automatically.
This is done using the StringData parameter.
salterje@k8s-master:~/YAML/secrets$ cat mysecret-manifest2.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysecret3
type: Opaque
stringData:
username: admin
password: SuperSecretPassword123
To build the secret simply run the kubectl apply -f command with the manifest file.
salterje@k8s-master:~/YAML/secrets$ kubectl apply -f mysecret-manifest2.yaml
secret/mysecret3 configured
salterje@k8s-master:~/YAML/secrets$ kubectl apply -f mysecret-manifest2.yaml
secret/mysecret3 configured
salterje@k8s-master:~/YAML/secrets$ kubectl get secrets mysecret3
NAME TYPE DATA AGE
mysecret3 Opaque 2 6m27s
salterje@k8s-master:~/YAML/secrets$ kubectl describe secrets mysecret3
Name: mysecret3
Namespace: default
Labels: <none>
Annotations:
Type: Opaque
Data
====
password: 22 bytes
username: 5 bytes
Conclusions
Secrets are built in a similar way to ConfigMaps and can be used in similar ways. The data within the object is encoded as Base64 data that is a little more secure then using a ConfigMap object (although this should not be confused with encryption).
The choice of where to store the manifest files that are used to create the Secret will dictate if the data should be stored in plaintext or Base64.