Creating and Using Secrets in OpenShift

Creating Secrets (like creating ConfigMaps) is a vital part of Managing OpenShift workloads and is an exam objectives of the EX280 exam. Knowing how they work and how to configure them (from the command-line) will give you a better understanding of Secrets.

Secrets, how do they work

Secrets provide information (like config files or credentials) to workloads in your cluster. You can use a secret to provide a username and password to your pod or to add a SSL certificate to it.

No data on the node

When exposing secrets using volumes the data is stored in a tmpfs filesystem. This means that the data in de secret is not directly exposed to the node that the pod’s are running on1.

This provides a bit more security than that of ConfigMaps.

Secret types

There are 3 secret types available for you to us. Don’ worry, they are quite easy to keep apart:

  • docker-registry secrets are used by the internal docker registry of your container platform
  • tls secrets are used to provide tls certificates, keys or other supporting files to a pod
  • generic secrets are used to store everything from an API key to a config file

I will be discussing generic secrets in this post.

Encoding vs Encryption

An important factor to know when working with secrets are that they are not encrypted. The “secret” part of secrets is that they are not readable without decoding them. By default secrets are encodes in a base64 encoding. When you create a secret with, for example, a password key=value pair; the value will be encoded in base64.

We can simulate this in bash:

$ echo 'encoded_password' | base64
ZW5jb2RlZF9wYXNzd29yZAo=

$ echo 'ZW5jb2RlZF9wYXNzd29yZAo=' | base64 -d
encoded_password

In this case the key=value pair would be rendered in our secret like this (because only the value is encoded, and not the key):

password=ZW5jb2RlZF9wYXNzd29yZAo=

When we create a secret from yaml we need to encode it first. But when we create a secret with oc create the cluster takes care of this encoding for us. If you would use oc edit to live edit a secret, don’t forget to encode the string you are replacing.

Creating a secret

Creating a secret can be done by creating a yaml file and applying it to the cluster or by using the oc create secret command.

Creating a secret from yaml

Creating a secret form a yaml definition is quite easy when you know the layout. You always get an example from the official documentation or use oc explain secrets

The following is a yaml secret with our own value filled in:

# our-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: test-secret
  namespace: project-of-secrets
type: Opaque 
data: 
  password: ZW5jb2RlZF9wYXNzd29yZAo=

If we wanted to create a secret from this we would do so with:

$ oc apply -f our-secret.yaml 

Creating a secret from the cli

If your in a hurry (or don’t want to create yaml files for all your secrets). You can create a secret without a definition file.

As a demo you can setup a special testing namespace. As you can see in my yaml example I called this one project-of-secrets:

$ oc new-project project-of-secrets 

From Literal

You could create a secret from the command-line with the following command:

$ oc create secret generic \
  SECRET_NAME \
  --from-literal KEY1=VALUE1 \
  --from-literal KEY2=VALUE2

As an example:

$ oc create secret generic test-secret-literal \
--from-literal password=encoded_secret 
secret/test-secret-literal created

From File

If you want your secret to be filled with an entire file:

$ oc create secret generic \
  SECRET_NAME \
  --from-file KEY1=/PATH/TO/FILE1 

As an example:

$ echo "Our verry secret file" > secret-file.txt
$ oc create secret generic test-secret-file --from-file secret-file.txt
secret/test-secret-file created

Adding a secret to a pod

Secrets can be supplied to a pod much like ConfigMaps. For more info on those, I wrote an entire blog regarding the creation and usage of them.

Just like ConfigMaps we can provide secret data to pods as ENV variables or as a volume. We will use the secret/test-secret-literal and our demoapp as an example, you can create a demo app with:

$ oc new-app --name demoapp --docker-image bitnami/nginx
--> Creating resources ...
    imagestream.image.openshift.io "demoapp" created
    deployment.apps "demoapp" created
    service "demoapp" created

Secret as ENV Variable

We use the oc set env command to set a secret as ENV Vars for our pod:

$ oc set env deployment/demoapp \
--from secret/test-secret-literal
deployment.extensions/demoapp updated 

We can now see the secret in action when we enter the pod:

$ oc get pods
NAME                       READY   STATUS    RESTARTS   AGE
demoapp-557f47dccb-2gzvp   1/1     Running   0          41s
$ oc rsh demoapp-557f47dccb-2gzvp bash
(pod) $ env | grep -i password
PASSWORD=encoded_secret

Using a prefix

You can also prefix your secrets in the pod using the --prefix option. This will add a prefix like mysql_ or our_prefix_ to all the key’s that are being added. Tis can be quite handy for example when you want to use the mysql app because that app expects all values to be prefixed.

As an example, we will create a secret from-literal and then add it with a prefix:

$ oc create secret generic prefix-example \
  --from-literal key=a_value
secret/prefix-example created

And then we add it with the --prefix option:

$ oc set env deployment/demoapp \
  --from secret/prefix-example \
  --prefix our_prefix_ \
deployment.extensions/demoapp updated

Now, when we enter the pod and echo the ENV variables we will see the key being prefixed:

$ oc get pods -o name
pod/demoapp-6c9b77c-dw4c2
$ oc rsh pod/demoapp-6c9b77c-dw4c2 bash
(pod) $ env | grep -i 'key'
our_prefix_KEY=a_value

Secret as file

Warning: Mounting a volume on path that already exists on a pod will make all files in that directory inaccessible

To create a volume that will hold the secret we use the oc set volume command:

$ oc set volume \
  deployment/demoapp \
  --add \
  --type secret \
  --mount-path /etc/secret \
  --secret-name test-secret-literal
info: Generated volume name: volume-zjmsq
deployment.extensions/demoapp volume updated 

We can see the mounted secret action from the pod in actions as well:

$ rsh demoapp-557f47dccb-2gzvp bash
(pod) $ cat /etc/secret/password
encoded_secret

As you can see a file is created with the name of the key containing the value of the value from our secret.

Closing thoughts

Secrets might not be as secret as you would hope but they provide a fundamental way of exposing sensitive data to our pods on OpenShift and you will certainly encounter them on a daily basis if you manage any kind of Container Cluster.

See more of my EX280 and OpenShift related posts here

  1. https://docs.openshift.com/container-platform/4.9/nodes/pods/nodes-pods-secrets.html#nodes-pods-secrets-about_nodes-pods-secrets 


Found this useful? Consider sponsoring me or buying me a cup of coffee at KoFi