How To Store Kubernetes Secrets In Git Repositories securely using Bitnami Sealed Secrets

Pre-requisites:

  1. Running Kubernetes Cluster

Installation:

Step 1: Installing the kubeseal Client

root@devopsguyvm:~# wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.16.0/kubeseal-linux-amd64 -O kubeseal
--2021-10-20 10:32:11-- https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.16.0/kubeseal-linux-amd64
Resolving github.com (github.com)... 13.234.210.38
root@devopsguyvm:~# sudo install -m 755 kubeseal /usr/local/bin/kubeseal
root@devopsguyvm:~# kubeseal --help
Usage of kubeseal:
--add_dir_header If true, adds the file directory to the header
--allow-empty-data Allow empty data in the secret object
root@devopsguyvm:~# wget https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.16.0/controller.yaml
--2021-10-20 10:24:30-- https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.16.0/controller.yaml
Resolving github.com (github.com)... 13.234.176.102
root@devopsguyvm:~# kubectl apply -f controller.yaml
Warning: rbac.authorization.k8s.io/v1beta1 Role is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 Role
role.rbac.authorization.k8s.io/sealed-secrets-service-proxier created
role.rbac.authorization.k8s.io/sealed-secrets-key-admin created
service/sealed-secrets-controller created
Warning: rbac.authorization.k8s.io/v1beta1 RoleBinding is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 RoleBinding
rolebinding.rbac.authorization.k8s.io/sealed-secrets-service-proxier created
customresourcedefinition.apiextensions.k8s.io/sealedsecrets.bitnami.com created
rolebinding.rbac.authorization.k8s.io/sealed-secrets-controller created
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRoleBinding is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRoleBinding
clusterrolebinding.rbac.authorization.k8s.io/sealed-secrets-controller created
Warning: rbac.authorization.k8s.io/v1beta1 ClusterRole is deprecated in v1.17+, unavailable in v1.22+; use rbac.authorization.k8s.io/v1 ClusterRole
clusterrole.rbac.authorization.k8s.io/secrets-unsealer created
serviceaccount/sealed-secrets-controller created
deployment.apps/sealed-secrets-controller created
root@devopsguyvm:~# kubectl get pods -n kube-system | grep sealed-secrets-controller
sealed-secrets-controller-5b54cbfb5f-8zmz5 1/1 Running 0 28s
root@devopsguyvm:~# kubectl create secret generic my-secret --from-literal=key=value --dry-run=client -o json |kubeseal | tee secret.yaml
{
"kind": "SealedSecret",
"apiVersion": "bitnami.com/v1alpha1",
"metadata": {
"name": "my-secret",
"namespace": "default",
"creationTimestamp": null
},
"spec": {
"template": {
"metadata": {
"name": "my-secret",
"namespace": "default",
"creationTimestamp": null
},
"data": null
},
"encryptedData": {
"key": "AgAmQWAVgI0sZHlR0YbKRt54FRI8Lk9o9Gk9whJxM3NhqmyRVE3TMXhm5oPJe9iHnCUvYeKr8aaN8RWrPyCTLUg2pQsnGJLEiXUZUNAMXXUoIMZF+XquwYXMFJVPuXWCC7cuW6t4NeEeZ7Eklf4T9z4TnTFME4/d6JkH02u7ALC7fjoso9jfxusgEPzIJlJuB4YWIT0OXi8VqCq3WdWc3tWgyEfrva7ZglS8bX/pXVrTWeQ9hnal5KcncvjeFTya4PWJrtxAGgLGn1BPga4JzWQKVlkkDwQ9NMBkEI4aKA6Ecs1LpzCilA6cFVZ2KVEI2nLBojYvs7oQT5XEHCpc/8j9M6b9HVi8rSaNy8AVf9ZMKEZ0jDo97YExXkjloD68p6u+fCvBBbOwmauE7sLC2eZCCPNs93LTQpWgTy165D/S80Zkjd3CPOB5ER/egHbDKahkvoqJBOTstqzjT6XYIb0PMHz3108kmHSjW0do9zUkaI6rzwmhPj9tDEB3q3PC90j2h9mso14uaBpMsqV9qmViR4OTJwb90lIqi6+Agvr/rxA8MiMvAF1XkPovXi7SF2jOUzC3Kt0CVCsl1enf8JtiuRB1Hjtzlv8eRUunMu5wvm9ymabbGhDbrExQVdJNXCuSERb3RIgKfiMh1XTxxKW0tL2KDQ5vE/f2pyXeEPs/lxvStuunRnhA1DB11GZhpVVSNhFEig=="
}
}
}
root@devopsguyvm:~# kubectl apply -f secret.yaml
sealedsecret.bitnami.com/my-secret created

SealedSecret Scopes

No one apart from the running controller can decrypt the SealedSecret, not even the author of the Secret.It’s a general best practice to disallow users to have direct access to read secrets. You can create RBAC rules to forbid low-privilege users from reading Secrets. You can also restrict users to only be able to read Secrets from their namespace.

  • strict (default): In this case, you need to seal your Secret considering the name and the namespace. You can’t change the name and the namespaces of your SealedSecret once you've created it. If you try to do that, you get a decryption error.
  • namespace-wide: This scope allows you to freely rename the SealedSecret within the namespace for which you’ve sealed the Secret.
  • cluster-wide: This scope allows you to freely move the Secret to any namespace and give it any name you wish.
$ kubeseal --scope cluster-wide --format yaml <secret.yaml >sealed-secret.yaml
  • sealedsecrets.bitnami.com/namespace-wide: "true" for namespace-wide
  • sealedsecrets.bitnami.com/cluster-wide: "true" for cluster-wide

How it is working?

Sealed Secrets are a “one-way” encrypted Secret that can be created by anyone, but can only be decrypted by the controller running in the target cluster. The Sealed Secret is safe to share publicly, upload to git repositories, post to twitter, etc. Once the SealedSecret is safely uploaded to the target Kubernetes cluster, the sealed secrets controller will decrypt it and recover the original Secret.

  • A controller that runs in-cluster, and implements a new SealedSecret Kubernetes API object via the “third party resource” mechanism.
  • A kubeseal command line tool that encrypts a regular Kubernetes Secret object (as YAML or JSON) into a SealedSecret.

References:

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Akshay Bobade

Akshay Bobade

I have total 3 Plus years of experience as a Devops engineer and currently dealing with Cloud, Containers, Kubernates and Bigdata technologies.