In k8s administration, resources like secrets are not well maintained. kubeseal provides a relatively simple way to encrypt the original secret resource and decrypt it through the controller as a way to circumvent the risk of secret leakage.

install kubeseal

1
2
3
4
$ wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.18.0/kubeseal-0.18.0-linux-amd64.tar.gz
$ tar -xvf kubeseal-0.18.0-linux-amd64.tar.gz
$ cp kubeseal /usr/local/bin/
$ kubeseal --version

Install controller.

1
$ kubectl apply -f https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.18.0/controller.yaml

After executing the above command, a controller Pod will be started under the kube-system namespace.

1
2
$ k get pod -n kube-system |grep seal
sealed-secrets-controller-b9fb75d85-k4csm    1/1     Running   0          7h28m

After the pod starts, use port forwarding to map to local.

1
$ kubectl -n kube-system port-forward svc/sealed-secrets-controller 8080:8080

Usage

Generate an encrypted file

First create a local file called secret-example.yaml. The value of the secret field before encoding is: mysupersecret

1
2
3
4
5
6
apiVersion: v1
kind: Secret
metadata:
  name: secret-example
data:
  secret: bXlzdXBlcnNlY3JldAo=

Use the following command to convert secret-example.yaml, to the encrypted file sealed-secret-example.yaml.

1
$ kubeseal --secret-file secret-example.yaml --sealed-secret-file sealed-secret-example.yaml

The contents of sealed-secret-example.yaml are as follows, and spec.encryptedData.secret is the encrypted content.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  creationTimestamp: null
  name: secret-example
  namespace: kube-system
spec:
  encryptedData:
    secret: AgB1ZZg8+J+0HLymOQZdTfWVQZiNkhm5X6WULJuBAAEaQQNhM8i2TV2I1SgKT4sUOCRv90XA1oeFld3XoGPjvYE3leOD1cvK1dDVqno6mNLRziokISk/9fB3cVE2GVgyCud//M53xNpVemDufgsJS2q/KGIOeNEijk9ZM2FaKoLDwtPaVNL0NfmC2xne2XtWJp+/eMOREhbubQhnj5M/Se75axazviuDNf6Ss9fAuR38Msd5DXnKBtyrckEHSa8TDn8ErssOh0ogX14e0/ThN3EWJecSBtx7Xfd0m90+vjmvWevMag442349aquR/qLo0mg40mhcCqSBw/MjaIGZ2F5XRufG1WEP43OgLMTixN2lLSU3eYTrv5t075taI9WJgoOl0DD8UA74EMpX7RMKTiXD6C0XngKmMKg5fUK7JNLFfwHMRPi4zNTwJa9ViDyD0iAJrGGbmMso/nHEtwOtrLE5Rrf0kLQ5N6Lj57gOBdqu903/vDM4Jm695GvEWL2aR3ShOxasHCuZeXj8Q5+KYWeF9sySiJH8bwEtaw6x7j9AxBOwjxWYD0Jvj9KhtlqBa4okSDc3bcgRKGhsSXQx6jOumI5rj+V542hkB6Z8JOtJ17VmzR6XDQDmqSl1FqqwKD5n5yUy5Kf6pJYBnsgKn3TzesQ6JfQbyRLTh1Pn3odOYCnp+Ixbd0Tgn0n5m0KO3RX0hiwGoe0hObIZcsF36g==
  template:
    data: null
    metadata:
      creationTimestamp: null
      name: secret-example
      namespace: kube-system

You can save the encrypted file to gitlab.

To create an encrypted file.

1
2
3
4
5
6
$ k create -f sealed-secret-example.yaml
sealedsecret.bitnami.com/secret-example created

$ k get sealedsecrets.bitnami.com
NAME             AGE
secret-example   6s

After creating the encrypted file, the controller will decrypt it and generate the corresponding secret.

1
2
$ k get secrets |grep secret-example
secret-example                                   Opaque                                1      2m15s

Looking at the contents of the secret resource generated by the controller, you can see that data.secret is the same as the secret-example.yaml file created above.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
$ k get secret secret-example -oyaml
apiVersion: v1
data:
  secret: bXlzdXBlcnNlY3JldAo=
kind: Secret
metadata:
  creationTimestamp: "2022-06-10T00:50:40Z"
  name: secret-example
  namespace: kube-system
  ownerReferences:
  - apiVersion: bitnami.com/v1alpha1
    controller: true
    kind: SealedSecret
    name: secret-example
    uid: 57a5b691-9bb5-4dac-800a-1a1baa878299
  resourceVersion: "675560"
  uid: e0db31ad-082b-4596-9fd0-28cc810d86f4
type: Opaque

The ealedSecret and the corresponding secret resource must be located in the same namespace.

TIPS

  • The following API is supported by kubeseal.

    Route Description
    /healthz Health check route useful for the readiness and liveness probes and for creating an external probe; for example with blackbox exporter.
    /metrics Endpoint for the Prometheus to retrieve the controller’s metrics.
    /v1/verify Validates a secret.
    /v1/rotate Rotates the secret.
    /v1/cert.pem Retrieves the public certificate.
  • The certificate used by the controller in the above example is self-generated, and you can also specify your own certificate, which is more convenient for migration and management.

  • With kubeseal there may be a confusion that if the user mounts the secret of other namespace directly, then this may cause the secret to be leaked. There is an official explanation for this, e.g. you can restrict the namespaces and resource types that users can access via RBAC. See README for more information.