The value of argocd-secret is further encoded to base64

6/2/2020

When managing secrets in argocd, I encode the value in argocd-secret with base64 and set it to manifest.

In that case, although I use kusotomize, build and apply it, secret encoded by base64 will be encoded to base64 further.

$ echo -n "clientid" | base64
Y2xpZW50aWQ=

$ echo -n "clientsecret" | base64
Y2xpZW50c2VjcmV0
---
apiVersion: v1
kind: Secret
metadata:
  name: argocd-secret
type: Opaque
stringData:
  dex.github.clientID: Y2xpZW50aWQ=
  dex.github.clientSecret: Y2xpZW50c2VjcmV0

If you use kustomize build to build and check the difference, it looks like this

$ kustomize build --load_restrictor none overlays/dev/ap-northeast-1/argocd | k diff -f -

+  dex.github.clientID: WTJ4cFpXNTBhV1E9
+  dex.github.clientSecret: WTJ4cFpXNTBjMlZqY21WMA==

I don't understand why something encoded by base64 is encoded further. I'm going to ask for someone's help.

Thanks.

-- jadejoe
argocd
kubernetes
kubernetes-secrets
kustomize

2 Answers

6/4/2020

I reproduced your case and it looks like it isn't further encoded by kustomize but by kubectl (either by kubectl client itself or by kube-apiserver performing the operation requested by e.g. kubectl apply command).

And here you can find a fragment that sheds some light on why this is actually happening:

The Secret contains two maps: data and stringData. The data field is used to store arbitrary data, encoded using base64. The stringData field is provided for convenience, and allows you to provide secret data as unencoded strings.

The data field serves for storing the data already encoded using base64 and value of this field isn't further encoded when we apply the Secret. The stringData however behaves quite differently. It allows you to provide secret data as unencoded strings and for that reason it is further encoded when you run kubectl apply. In your example you use stringData field and although it contains already encoded data, it is treated as any other string and in consequence is encoded again.

Solution: simply use data rather than stringData map in your Secret and your base64 encoded strings won't be encoded again during the resource creation.

-- mario
Source: StackOverflow

6/4/2020

It's actually secret controller who encodes the string. So, you can't pass an encoded string into a yaml. You need to leave it in plain text:

$ echo -n demo | base64
ZGVtbw==
$ echo -n ZGVtbw== | base64
WkdWdGJ3PT0=

$ kubectl create secret generic demo --from-literal=key=demo
secret/demo created
$ kubectl create secret generic demo2 --from-literal=key=ZGVtbw==
secret/demo2 created

$ kubectl get secret demo demo2 -oyaml
apiVersion: v1
items:
- apiVersion: v1
  data:
    key: ZGVtbw==        <- word demo got encoded
  kind: Secret
  metadata:
    creationTimestamp: "2020-06-04T13:41:27Z"
    name: demo
    namespace: default
    resourceVersion: "10118413"
    selfLink: /api/v1/namespaces/default/secrets/demo
    uid: bc39444c-e4f6-43ba-b151-705e15811831
  type: Opaque

- apiVersion: v1
  data:
    key: WkdWdGJ3PT0=    <- encoded string of demo got encoded further
  kind: Secret
  metadata:
    creationTimestamp: "2020-06-04T13:41:47Z"
    name: demo2
    namespace: default
    resourceVersion: "10118469"
    selfLink: /api/v1/namespaces/default/secrets/demo2
    uid: 2fe63343-06b4-4f47-94cd-9fe8e12fb388
  type: Opaque
kind: List
metadata:
  resourceVersion: ""
  selfLink: ""

Note: this was not always like that. And it can actually change again. Back in the days, you had to encode it, then you must not, then again...

-- suren
Source: StackOverflow