Edit Kubernetes Secrets

Janne Kemppainen |

Has your API key changed? Maybe you need to update a TLS certificate? There are many reasons why you’d want to edit secrets in Kubernetes. Luckily, this is relatively simple.

Secrets are normal objects inside Kubernetes, just like pods or ingresses. The secret data is stored as a base64 encoded string, so it’s not really plaintext, but it’s not encrypted either! Therefore you need to be careful of which access rights you give to the cluster so that you don’t leak sensitive information.

That base64 encoding adds some complexities when you need to change secret values.

For the rest of this post I will assume that you’ve already properly configured kubectl with access to a cluster.

How can you find a Kubernetes secret?

Before you can edit a secret you need to be able to locate it!

Each secret lives inside a namespace, and they are only accessible to services within the same namespace. Therefore the first thing you need to do is to see what namespaces you have inside the cluster:

$ kubectl get namespaces
NAME              STATUS   AGE
default           Active   14d
kube-node-lease   Active   14d
kube-public       Active   14d
kube-system       Active   14d
my-app            Active   2d

This gives you a complete list of all namespaces. Now you can list the secrets for your chosen namespace:

$ kubectl get secrets -n my-app
NAME                  TYPE                                  DATA   AGE
db-credentials        Opaque                                1      9h
default-token-z59b4   kubernetes.io/service-account-token   3      9h

If you need to check the current secret value you can query the YAML manifest:

$ kubectl get secret db-password -n my-app -o yaml
apiVersion: v1
data:
  password: bXktcGFzc3dvcmQ=
kind: Secret
metadata:
  creationTimestamp: "2021-10-14T19:56:47Z"
  name: db-credentials
  namespace: my-app
  resourceVersion: "329851"
  uid: af03fbbf-aa56-45ea-a1dc-24c118645749
type: Opaque

The -n flag is a shorthand for --namespace, and is -o for --output which sets the output format. As the data is base64 encoded you’ll have to decode the value to make sense of it.

$ echo "bXktcGFzc3dvcmQ=" | base64 --decode
my-password

There are also online services that can decode and encode base64 strings, but I wouldn’t use them to convert sensitive information.

Edit a secret with kubectl edit secret

Now we can continue to actually editing the secret. Since the secret value needs to be stored as a base64 string you’ll have to convert it to the proper format. One way to do this is to use the Linux/macOS command line again:

$ echo -n "my-new-password" | base64
bXktbmV3LXBhc3N3b3Jk

We need to use the -n argument to suppress the newline character from the end of the echo output that is piped to the base64 executable. If you omit the -n flag the secret will end with a \n character which can cause issues in your app! Copy the encoded value, then edit the secret with kubectl:

$ kubectl edit secret db-credentials -n my-app

The current secret manifest opens in your default text editor. Replace the secret data with the new value, then save and exit the editor and you’re done!

If your secret data is something that works well within a YAML file, such as a password, then it’s also possible to let Kubernetes handle the base64 conversion. Use the same command as before to open the editor, but this time add a new stringData field to the YAML file containing all the secret values that you want to change.

stringData:
  password: my-new-password

Kubernetes merges the stringData field to the data field automatically and performs the needed conversions. You don’t have to remove existing keys from the data field since stringData takes precedence when the same keys are defined in both fields.

You can verify that the value was updated after saving and closing the editor. If you close without changes the edit is going to be cancelled.

Delete and recreate a secret

The other easy option to update a secret is to delete the old secret and create a new one with the same name. The --ignore-not-found setting can be used when you’re not sure if the secret already exists or not. If you attempt to delete a non-existing secret without that option the command will fail.

$ kubectl delete secret db-credentials -n my-app --ignore-not-found=true
$ kubectl create secret generic db-credentials -n my-app --from-literal=password="my-password"

This option works really well when you want to fetch the secret data from a file:

$ kubectl create secret generic db-credentials -n my-app --from-file=password=db-password.txt

Note that with these options you don’t need to worry about encoding the secret value.

There is also a specific command for creating TLS certificate secrets that use the kubernetes.io/tls type:

$ kubectl create secret tls app-cert -n my-app --cert=cert.pem --key=cert.key

You can find all available flags for these commands and more from the kubectl reference.

Remember that you can verify the secret with this command:

$ kubectl get secret db-credentials -n my-app -o yaml

Add more data to a secret

If you want to add more data to the secret you will have to follow one of the previous steps. There is no way to append to a secret with a direct kubectl command. So for example if we need to include the database username we could delete the secret and create it again. This time I’m using environment variables to define the values.

$ export DB_USER="dbuser"
$ export DB_PASSWORD="my-new-password"
$ kubectl delete secret db-credentials -n my-app --ignore-not-found=true
$ kubectl create secret generic db-credentials -n my-app --from-literal=password=$DB_PASSWORD --from-literal=username=$DB_USER

Naturally, you could use the kubectl edit secret command as well.

Can you change the secret type in Kubernetes?

Once you have created a secret in the cluster you cannot change its type. Your only option is to delete and recreate the secret with the correct type. Alternatively, you could roll the change by creating a new secret with a different name and then pointing any resources to use it.

For example, if you want to change an Opaque secret to the kubernetes.io/tls type you’ll have to recreate it.

Final thoughts

So as you can see, editing secret values is not exactly difficult, but the base64 encoding can add some complexities to the process.

If you want to see more content like this then let me known on Twitter. I hope to see you on the next article!

Subscribe to my newsletter

What’s new with PäksTech? Subscribe to receive occasional emails where I will sum up stuff that has happened at the blog and what may be coming next.

powered by TinyLetter | Privacy Policy