Configure Secrets

Configure Secrets

In this tutorial, we will discuss about how to configure Secrets in Kubernetes.

Configure Secrets

In the previous tutorials, we discussed how to define environment variables and configure configmaps in a POD definition file.

Let us assume we have a simple python web application that connects to a MySQL database.

import os 
from flask import Flask 

app = Flask(__name__)

@app.route("/")
def main():
    mysql.connector.connect(host="mysql", database="ashok", user="ashok", password="ashok123")
    
    return render_template("hellp.html", color=fetchcolor())
    
if __name__ == __main__:
    app.run(host="0.0.0.0", port="8080")

If you look closely into the code you will see the host name, user name and password hard coded. This is of course not good idea.

As we discussed in the previous tutorial, one option would be to move these values into a ConfigMap.

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  DB_HOST: mysql
  DB_USER: ashok
  DB_DATABASE: ashok
  DB_PASSWORD: ashok123

The ConfigMap stores configuration data in plain text format. So while it would be okay to move the host name, database and user name into ConfigMap. But it is definitely not the right place to store password in ConfigMap. This is where secrets coming.

Secrets are used to store sensitive information like passwords or keys. They’re similar to ConfigMap except that they’re stored in an encoded or hashed format.

As with ConfigMaps, there are 2 steps involved in working with secrets. First create the secret and second injected into POD.

There are 2 ways of creating a secret. The imperative way – without using secret definition file and the declarative way by using a secret definition file.

Imperative method

With the imperative method, you can directly specify the key value pairs in the command line itself.

To create a secret of the given values, run the following command.

$ kubectl create secret generic <secret-name> --from-literal=<key>=<value>

E.g

$ kubectl create secret generic app-secret --from-literal=DB_HOST=mysql

If you wish to add additional key value pairs then simply specify the –from-leteral options multiple times

$ kubectl create secret generic app-secret --from-literal=DB_HOST=mysql --from-literal=DB_USER=ashok --from-literal=DB_PASSWORD=ashok123

However this will get complicated when you have too many configuration items. Another way to input configuration data is through a file.

$ kubectl create secret generic <secret-name> --from-file=app-secret.properties
$ kubectl create secret generic app-secret --from-file=<path-to-file>
Declarative Approach

In this approach we create a definition file just like how we did for the ConfigMap. The file has apiVersion, kind, metadata and data.

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-secret
data:
  DB_HOST=mysql 
  DB_USER=ashok
  DB_PASSWORD=ashok123

However one thing we discussed about secrets was that used to store sensitive data and are stored in an encoded format.

Here we have specified the data in plain text which is not very safe. So while creating a secret with declarative approach you must specify the secret values in a hashed format.

So you must specify the data in an encoded form like as below,

apiVersion: v1
kind: ConfigMap
metadata:
  name: app-secret
data:
  DB_HOST=bXlzcWw= 
  DB_USER=YXNob2s=
  DB_PASSWORD=YXNob2sxMjM=

But how do you convert the data from plain text to an encoded format? On a Linux host run the command echo -n followed by the text you are trying to convert, which is mysql in this case and pipe that to the base64 utility.

$ echo -n mysql | base64
bXlzcWw=

$ echo -n ashok | base64
YXNob2s=

$ echo -n ashok123 | base64
YXNob2sxMjM=

To view secrets run the following command

$ kubectl get secrets
NAME                        TYPE                                  DATA   AGE
default-token-kdm9m         kubernetes.io/service-account-token   3      8h
app-secret                  Opaque                                3      2h

Above command lists the newly created secret along with another secret previously created by Kubernetes for its internal purpose.

To view more information on the newly created secret, run the following command.

$ kubectl describe secrets

The above command shows the attributes in the secret. But hides the value themselves. To view the values as well, run the following command.

$ kubectl get secret app-secret -o yaml

The above command will display YAML format. You can now see the hashed values as well. So how do you decode these hashed values?

Use the same base64 command used earlier to encode it. But this time add a decode option to it.

$ echo -n bXlzcWw= | base64 --decode
mysql

$ echo -n YXNob2s= | base64 --decode
ashok

$ echo -n YXNob2sxMjM= | base64 --decode
ashok123

Now that we have secret created. Let us proceed with step 2, configuring it with a POD.

apiVersion: v1
kind: Pod
metadata:
  name: my-web-app
spec:
  containers:
  - name: my-web-app-container
    image: my-web-app
    ports:
      - containerPort: 8080
    envFrom:
      - secretRef:
          name: app-secret
Configure Secrets
Scroll to top