Snippets: Kubernetes secrets base64 decoder
It is very common that we need to see the secret content when working with Kubernetes. Imagine that you have installed a Helm chart in your cluster with auto-generated credentials and you need to get them to login to the app UI, or maybe you are troubleshooting and you want to make sure that the secret has the data it is supposed to have. If that sounds familiar, you might find this snippet particularly useful.
Problem
Extracting values from a Kubernetes secret is quite easy but requires quite a bit of typing. Here’s one of the ways you can do it:
kubectl get secret someapp-credentials -o jsonpath='{.data.username}' | base64 -d
kubectl get secret someapp-credentials -o jsonpath='{.data.password}' | base64 -dNot so bad. Though for a person like me, who prefers to have k as an alias to kubectl because it’s just too much to type, doing this task regularly can become annoying pretty fast.
This is actually something I used to do a lot. But one day the level of frustration when typing all these commands reached the threshold so I sit to come up with a simple script that could become my “Swiss Army Knife” when it comes to working with Kubernetes secrets.
Solution
The core idea here is to support two use cases:
Print the decoded value of a single key in a secret
Print the entire
datasection of a secret with all values being decoded
Ideally it should support both getting secrets from the namespace of the current context and any other namespace in a very concise manner(typing -n namespace every time is just too much trouble). Below is the script itself. It utilizes a bit of bash, basic linux commands, and jq.
#!/bin/bash
if [ -z "$1" ]; then
echo "Usage: $0 [<namespace>/]<secret> [<key>]"
exit 1
fi
namespace_or_secret=$(echo $1 | awk -F '/' '{print $1}')
secret=$(echo $1 | awk -F '/' '{print $2}')
result=""
if [ -z "$secret" ]; then
secret=$namespace_or_secret
result=$(kubectl get secret $secret -o jsonpath='{.data}' | jq 'map_values(@base64d)')
else
namespace=$namespace_or_secret
result=$(kubectl -n $namespace get secret $secret -o jsonpath='{.data}' | jq 'map_values(@base64d)')
fi
if [ -z "$2" ]; then
echo $result | jq '.'
else
echo $result | jq -r --arg k "$2" '.[$k]'
fiNow I can get a decrypted content of any secret I need in any namespace with one very simple command(assuming you put it in /usr/local/bin/ksecret or $HOME/.local/bin/ksecret and grant chmod +x):
ksecret kube-system/default-token-bf4vdthe output looks like this:
{
"ca.crt": "-----BEGIN CERTIFICATE-----\nMIIC/jCCAeagAwIBAgIBADANBgkqhkiG9...",
"namespace": "kube-system",
"token": "eyJhbGciOiJSUzx1NiIsImtpZCI6ImRvTHJHVHZqWjNhU05pYlpDYl84cUlscTN..."
}or if I need just the token:
ksecret kube-system/default-token-bf4vd tokenthe output will be raw string ready for copy/paste:
eyJhbGciOiJSUzI1NiI...
It also supports getting keys with characters reserved by jq like .:
ksecret kube-system/default-token-bf4vd ca.crt
the output will be a properly formatted certificate:
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----