Managing a secret on kubernetes

Most of the services we will be deploying on kubernetes are going to rely on having access to secrets to retrieve or push data to another service: Let's check how to work with the secrets on kubernetes

$ kubectl create secret
Create a secret using specified subcommand.

Available Commands:
  docker-registry Create a secret for use with a Docker registry
  generic         Create a secret from a local file, directory or literal value
  tls             Create a TLS secret

  kubectl create secret [flags] [options]

Use "kubectl <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).

On kubernetes there's an object called "secret" that we can use to store secrets. We can, of course, create a secret using a yaml file but for demo purposes I think it makes more sense to create it imperatively using kubectl. We can push data to the secret using --from-literal (password from the command line) or --from-file (password is stored on a file). In any case the format would be --from-file=[key=]source/--from-literal=[key=]source

For exemple, to create a secret with username jordi.prats and password not_so_secret the command would be:

$ kubectl create secret generic democredentials \
                --from-literal=username=jordi.prats \

Just to make it a little safer we could use a file to store the data so this way the secret won't be in the command history

$ kubectl create secret generic democredentials \

After creating the secret we can check it:

$ kubectl get secret democredentials
NAME              TYPE     DATA   AGE
democredentials   Opaque   2      69s

With describe we won't be able to actually see the secret:

$ kubectl describe secret democredentials
Name:         democredentials
Namespace:    kube-system
Labels:       <none>
Annotations:  <none>

Type:  Opaque

password:  13 bytes
username:  11 bytes

On the other hand, if we retrieve the secret as a yaml we will be able to see the secret:

$ kubectl get secret democredentials -o yaml
apiVersion: v1
  password: bm90X3NvX3NlY3JldA==
  username: am9yZGkucHJhdHM=
kind: Secret
  creationTimestamp: "2020-12-23T06:57:45Z"
  - apiVersion: v1
    fieldsType: FieldsV1
        .: {}
        f:password: {}
        f:username: {}
      f:type: {}
    manager: kubectl-create
    operation: Update
    time: "2020-12-23T06:57:45Z"
  name: democredentials
  namespace: kube-system
  resourceVersion: "4576550"
  selfLink: /api/v1/namespaces/kube-system/secrets/democredentials
  uid: ba87853f-16c8-426a-b840-945bf40a6f0e
type: Opaque

On the data section of the yaml we can see that there are the fields we added to the secret (username/password) with it's value encoded using base64, we can retrieve the secrets by decoding these strings:

$ echo 'am9yZGkucHJhdHM=' | base64 -d
$ echo 'bm90X3NvX3NlY3JldA==' | base64 -d

We can also use the jsonpath to retrieve just the encoded string so we can use it on scripts more easily, for example:

$ kubectl get secret democredentials -o jsonpath="{.data.password}"
$ kubectl get secret democredentials -o jsonpath="{.data.password}" | base64 -d

Posted on 23/12/2020