kubectl: get specific value from a secret in plaintext
Asked Answered
L

10

38

I want to get the value of a specific field of a secret in a shell script.

From the kubectl get secret documentation, it seems the standard way to get a secret returns the whole thing, in a specified format, with the values base64 encoded.

So, to get the bar field of the foo secret, output as an unencoded string, I'm doing this:

kubectl get secret foo -o json | jq -r ".data.bar" | base64 --decode

That is

  • get the whole foo secret as JSON
  • pipe to jq to read the bar field from the JSON
  • decode the value using base64

Is there a way to do this only using kubectl?

Or an elegant way in POSIX-compliant shell that doesn't rely on any dependencies like jq?

Lusatia answered 6/8, 2019 at 15:10 Comment(7)
Try this kubectl get secret foo --template={{.data.bar}} | base64 --decode no need of jqSometime
I don't know of any way to decode base64 using kubectl's internal mechanisms, but to get specific field from the secret, you can use jsonpath output: kubernetes.io/docs/reference/kubectl/jsonpath - You can pipe/combine the output with one of the methods here, to avoid base64 command dependency as well: #47800645Somnambulation
You can try using sed kubectl get secret foo | sed 's/^.*bar: \(.*\).*$/\1/' | base64 -dPlatinous
These are all very helpful options, thanks! Please post them as answers so I can upvote!Lusatia
$ kubectl get secret foo -o=jsonpath='{.data.bar}' | base64 -d but still need to pipe to base64 to decode.Holly
I think is nothing better can @Sometime answer,Potbellied
Let me put it as answer.Sometime
S
45

Try this

kubectl get secret foo --template={{.data.bar}} | base64 --decode

No need of jq.

Sometime answered 6/8, 2019 at 16:48 Comment(2)
It doesn't work now, if there's a hyphen in the name.Apathetic
@Searge, you can use the index function: kubectl get secrets foo --template='{{index .data "bar-bar"}}' | base64 --decodeEthiop
C
18

In cases when key contains dots:

apiVersion: v1
metadata:
  name: foo
data:
  bar.baz: RnVja2VkIFVwIEJleW9uZCBBbGwgUmVjb2duaXRpb24=

the syntax would be:

kubectl get secret foo -o jsonpath="{.data['bar\.baz']}" | base64 -d

Chastity answered 15/1, 2022 at 11:26 Comment(0)
C
12
kubectl get secret foo -o jsonpath={.data.bar} | base64 --decode

https://kubernetes.io/docs/reference/kubectl/jsonpath/

Cassidycassie answered 3/12, 2020 at 8:55 Comment(2)
This approach works for me even when the path contains a hyphen. Using --template doesn't (at least, not without some level of escaping it, which, well, escaped me)Akan
Just added a new answer showing the escaping for decoding secrets from hyphenated paths/keys directly from kubectl without needing to pipe to an external base64 executable.Brahmin
N
9

You can try the following command, it will decode all the values in the secret.

kubectl get secret <secret-name> -o json | jq '.data | map_values(@base64d)'
Nathannathanael answered 22/6, 2022 at 5:9 Comment(1)
The best answer!Chickasaw
M
8

This should work since Kubernetes 1.11 (see PR 60755):

kubectl get secret foo -o go-template='{{ .data.bar | base64decode }}'

Muss answered 12/10, 2019 at 15:7 Comment(0)
B
5

For a hyphenated key, here's the escaping trick to get the decoded value directly from kubectl:

kubectl get secret foo -o go-template='{{ index .data \"bar-baz\" | base64decode }}'

(Tested with kubectl 1.21.5)

Brahmin answered 28/3, 2022 at 19:53 Comment(1)
Question stipulates, “Is there a way to do this only using kubectl?” and besides actually answering the question, this answer deals correctly with the case of the secret key having a dot or dash. This should be the accepted answer.Paramagnetism
E
1

For those of you guys coming here via Google and want to do it from PowerShell, where base64 ist not available, use the following:

[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($(kubectl get secret foo -o jsonpath='{.data.bar}')))
Emotional answered 9/6, 2022 at 8:58 Comment(0)
R
1

As a combination from all of the above which works for a single entry containing - without additional tooling:

posix-shell:

kubectl get secret foo --template='{{ index .data "bar-baz" | base64decode }}'

powershell needs escaping:

kubectl get secret foo --template='{{ index .data `"bar-baz`" | base64decode }}'

If you want to have a reusable manifest file, you can convert data to stringData with the help of jq and yq

kubectl get secret foo -o json | jq -r 'del(.data) * {"stringData": .data|map_values(@base64d)}' | yq -p=json

or even without jq:

kubectl get secret foo -o yaml | yq '. * {"stringData": .data|map_values(@base64d)}|del(.data)'

the result can be edited and directly applied with kubectl apply. Be careful when you mix string with binary-data.

Rhodonite answered 3/4 at 14:25 Comment(0)
M
0

Here is a comprehensive bash solution:

kubereadsecret() {
secretname=$1
shift
dataname=$1
shift
keyname="{.data['$(echo $dataname | sed 's/[.]/\./g')']}"
kubectl get secret $secretname -o jsonpath=$keyname $* | base64 --decode
}

Martinsen answered 21/4, 2023 at 21:13 Comment(0)
P
0

An alternative approach using jq to get all decoded values of a secret:

kubectl get -o json secret/${secret_name} | jq -r '.data | to_entries[] | [.key, (.value | @base64d)] | @csv'
Perak answered 5/1 at 18:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.