Reputation: 5647
I would like to use kubectl
to print out all key-value pairs in my Secrets. I cannot figure out how to do this in one line with the -o --jsonpath
flag or by piping into jq
. I could certainly make a script to do this but I feel there must be a better way, given that the kubernetes GUI is pretty straightforward and liberal when it comes to letting you view Secrets.
Say I create secret like so:
kubectl create secret generic testsecret --from-literal=key1=val1 --from-literal=key2=val2
Now I can run kubectl get secret testsecret -o json
to get something like:
{
"apiVersion": "v1",
"data": {
"key1": "dmFsMQ==",
"key2": "dmFsMg=="
},
...
}
I can do something like
kubectl get secret testsecret -o jsonpath='{.data}'
or
kubectl get secret testsecret -o json | jq '.data'
to get my key-value pairs in non-list format then I'd have to base64 --decode
the values.
What is the easiest way to get a clean list of all my key-value pairs? Bonus points for doing this across all Secrets (as opposed to just one specific one, as I did here).
Upvotes: 26
Views: 39842
Reputation: 1135
For my needs I wrote a shell function, a wrapper around jq, that allows me to filter by names and decode secrets. It doesn't depend on a kubectl version but requires jq in $PATH. It's quite simple in use:
divulge() {
[ -t 0 ] && [ $# -eq 0 ] && {
echo "\
Discover kubernetes secrets
Usage:
kubectl get secrets [NAME] -o json | divulge [OPTIONS] [REGEXP]
Options:
-g Global search (find all matches, not just the first)
-i Case insensitive search
-m Multi line mode (. will match newlines)
-n Ignore empty matches
-p Both s and m modes are enabled
-s Single line mode (^ -> \A, $ -> \Z)
-l Find longest possible matches
-x Extended regex format (ignore whitespace and comments)
-r Output raw strings, not JSON texts; values are placed between [ and ]
and marked with the prefix unsafe, if contain at least a whitespace
-C Colorize JSON
-M Monochrome JSON
Follow the below link to learn more about REGEXP:
https://jqlang.github.io/jq/manual/#Regularexpressions"
return
}
unset DIVULGE_FLAGS DIVULGE_RAW DIVULGE_OPTS
while getopts ':gimnpslxrCM' arg
do
case "$arg" in
g | i | m | n | p | s | l | x )
DIVULGE_FLAGS="$DIVULGE_FLAGS$arg" ;;
r ) DIVULGE_RAW=1 ;;
C | M ) DIVULGE_OPTS="$DIVULGE_OPTS -$arg" ;;
* ) echo "Illegal option: -$OPTARG">&2 ; return 1 ;;
esac
done
shift $(( OPTIND-1 ))
# shellcheck disable=SC2086
jq $DIVULGE_OPTS \
--arg regex "$1" \
--arg flags "$DIVULGE_FLAGS" \
--arg raw "$DIVULGE_RAW" \
-r '(.items?[]? // .)
| .data
| select(.)
| with_entries(
select(
.key
| test($regex; $flags)
)
| .value |= @base64d
)
| (
if $raw == ""
then
select(. != {})
else
to_entries
| map(
(
if .value | test("\\s")
then
"unsafe "
else
"safe "
end
) + .key + " [" + .value + "]"
)
| .[]
end
)'
}
A standalone version can be found by this link.
Upvotes: -1
Reputation: 11
Kubernetes get all secretes base64 decode them, and ignore null values.
# kubectl get secrets -A -o json | jq '.items[] | \
select(null != .data) | {name: .metadata.name,data: .data|map_values(@base64d)}' \
> all_secrets_decoded.json
Upvotes: 1
Reputation: 187
When using the accepted answer you may come across exception
jq: error (at <stdin>:96): Cannot iterate over null (null)
This might be because some json might not be fully formed, use an additional filter
kubectl get secrets -o json | jq '.items[] | select(null != .data) | {name: .metadata.name,data: .data|map_values(@base64d)}'
The above will ensure to produce expected results
Upvotes: 6
Reputation: 2453
I read this question as asking for how to decode all secrets in one go. I built on the accepted answer to produce a one-liner to do this:
kubectl get secrets -o json | jq '.items[] | {name: .metadata.name,data: .data|map_values(@base64d)}'
This has the added benefit of listing the name of the secret along with the decoded values for readability.
Upvotes: 26
Reputation: 113
If you need to extract tls certificates and/or keys from a kubernetes secret and you have an older jq version not supporting map_values(@base64d):
kubectl get secrets tls-cert -o json | jq '.data' | cut -d '"' -f 4 | tr -d '{}' | base64 --decode
Upvotes: 2
Reputation: 116790
Sufficiently recent versions of jq have a filter for decoding base64 but it can only be used if the value that was encoded is a valid JSON string.
Anyway, you could start by trying:
.data | map_values(@base64d)
Upvotes: 16