Hardening Kubernetes: Secretos
Si queremos empezar a securizar nuestros proyectos de Kubernetes, podemos empezar con buenas prácticas no almacenando en claro objetos con datos sensibles, como contraseñas, llaves SSH o tokens de OAuth.
El uso de Secretos te permite controlar la manera en que se usan los datos sensibles, y reduce notablemente el riesgo de exposición de esos datos sensibles a usuarios no autorizados.
Esta información se suele colocar en las especificaciones de los Pods o en imágenes de contenedores.
Un secreto puede ser generado tanto por un usuario como por el propio sistema. Cuando lo hace el sistema, se generan automáticamente mediante cuentas de servicios con credenciales de API.
Kubernetes crea automáticamente secretos que contienen credenciales para acceder a la API y modifica automáticamente sus Pods para usar este tipo de secreto.
Otros datos interesantes sobre los secretos:
- Los secretos son objetos con espacios de nombres, es decir, existen en el contexto de un espacio de nombres
- Puede acceder a ellos a través de un volumen o una variable de entorno desde un contenedor que se ejecuta en un pod
- Los datos secretos en los nodos se almacenan en volúmenes tmpfs
- Existe un límite de tamaño por secreto de 1 MB
- El servidor API almacena secretos como texto sin formato en etcd
- La creación y el uso automático de credenciales de API se puede deshabilitar o anular si se ve necesario. Sin embargo, si todo lo que se necesita es acceder de forma segura al servidor API, este es el flujo de trabajo recomendado.
El problema de los secretos es que se cifran en base64. Con lo que tú puede crear un secreto de la siguiente forma:
1 2 3 |
raulunzue@KBMASTER:~$ echo -n 'elblogdenegu' | base64 ZWxibG9nZGVuZWd1 |
Por ejemplo, creamos un usuario y contraseña:
1 2 3 |
echo -n 'admin' | base64 YWRtaW4= |
1 2 3 |
echo -n '1f2d1e2e67df' | base64 MWYyZDFlMmU2N2Rm |
E implementarlos con un fichero YAML de la siguiente forma:
1 2 3 4 5 6 7 8 |
apiVersion: v1 kind: Secret metadata: name: mysecret type: Opaque data: username: YWRtaW4= password: MWYyZDFlMmU2N2Rm |
Pero también descifrarlos fácilmente con otro comando:
1 2 3 |
echo 'YWRtaW4' | base64 --decode echo 'MWYyZDFlMmU2N2Rm' | base64 --decode |
Y esto es un gran problema, si almacenamos todos nuestros usuarios y contraseñas, por ejemplo, en un repositorio.
Para paliar estas cosas, deberíamos ir un paso adelante y utilizar herramientas tipo KubeSealed. Que es una herramienta que te permite cifrar secretos mediante un recurso que se llama SealedSecret.
PROYECTO: https://github.com/bitnami-labs/sealed-secrets
Se instala mediante el binario de KubeSealed, lo que hace es cifrar mediante una key específica para el clúster, utilizando el certificado del clúster de Kubernetes donde se aplica. Para trabajar con la herramienta deberemos llevar los secretos a JSON.
En la web del proyecto os explican su instalación con Helm:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
raulunzue@KBMASTER:/usr/local/bin$ brew install kubeseal /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/brew.sh: line 4: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8): No such file or directory /bin/bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8) /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/brew.sh: line 4: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8): No such file or directory /bin/bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8) /home/linuxbrew/.linuxbrew/Homebrew/Library/Homebrew/brew.sh: line 4: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8): No such file or directory ==> Downloading <a href="https://linuxbrew.bintray.com/bottles/patchelf-0.10.x86_64_linux.bottle.1.tar.gz">https://linuxbrew.bintray.com/bottles/patchelf-0.10.x86_64_linux.bottle.1.tar.gz</a> ==> Downloading from <a href="https://akamai.bintray.com/7f/7f19eacef4e3d18d9c82a4f4060bd86abeb912a4a76fa37c29f0bb104a38b2a2?__gda__=exp=1591045240~hmac=7815af">https://akamai.bintray.com/7f/7f19eacef4e3d18d9c82a4f4060bd86abeb912a4a76fa37c29f0bb104a38b2a2?__gda__=exp=1591045240~hmac=7815af</a> ######################################################################## 100.0% ==> Downloading <a href="https://linuxbrew.bintray.com/bottles/kubeseal-0.12.4.x86_64_linux.bottle.tar.gz">https://linuxbrew.bintray.com/bottles/kubeseal-0.12.4.x86_64_linux.bottle.tar.gz</a> ==> Downloading from <a href="https://akamai.bintray.com/83/83a5abe17baa28f13d5ad6241c161a97243b0ccdb0dcfa58172a1ce63837ca34?__gda__=exp=1591045240~hmac=05bb19">https://akamai.bintray.com/83/83a5abe17baa28f13d5ad6241c161a97243b0ccdb0dcfa58172a1ce63837ca34?__gda__=exp=1591045240~hmac=05bb19</a> ######################################################################## 100.0% ==> Installing dependencies for kubeseal: patchelf ==> Installing kubeseal dependency: patchelf /bin/bash: warning: setlocale: LC_ALL: cannot change locale (en_US.UTF-8) ==> Pouring patchelf-0.10.x86_64_linux.bottle.1.tar.gz 🍺 /home/linuxbrew/.linuxbrew/Cellar/patchelf/0.10: 8 files, 921.5KB ==> Installing kubeseal ==> Pouring kubeseal-0.12.4.x86_64_linux.bottle.tar.gz 🍺 /home/linuxbrew/.linuxbrew/Cellar/kubeseal/0.12.4: 5 files, 33.6MB También se puede instalar con Helm: raulunzue@KBMASTER:~$ helm search hub sealed URL CHART VERSION APP VERSION DESCRIPTION <a href="https://hub.helm.sh/charts/stable/sealed-secrets">https://hub.helm.sh/charts/stable/sealed-secrets</a> 1.10.1 0.12.1 A Helm chart for Sealed Secrets raulunzue@KBMASTER:~$ helm install stable/sealed-secrets --generate-name NAME: sealed-secrets-1591042254 LAST DEPLOYED: Mon Jun 1 22:11:01 2020 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None NOTES: You should now be able to create sealed secrets. |
-
1Install client-side tool into /usr/local/bin/
1 2 3 4 5 6 7 8 9 |
GOOS=$(go env GOOS) GOARCH=$(go env GOARCH) wget <a href="https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.12.1/kubeseal-$GOOS-$GOARCH">https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.12.1/kubeseal-$GOOS-$GOARCH</a> sudo install -m 755 kubeseal-$GOOS-$GOARCH /usr/local/bin/kubeseal ---- |
Generaríamos un secreto:
1 2 3 |
raulunzue@KBMASTER:~$ echo -n elblogdenegu | kubectl create secret generic mysecret --dry-run --from-file=foo=/dev/stdin -o json >ebdnsecret.json W0601 22:16:05.684421 7753 helpers.go:535] --dry-run is deprecated and can be replaced with --dry-run=client. |
Lo revisamos con cat ebdnsecret.json y vemos como está cifrado:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
raulunzue@KBMASTER:~$ cat ebdnsecret.json { "kind": "Secret", "apiVersion": "v1", "metadata": { "name": "mysecret", "creationTimestamp": null }, "data": { "foo": "ZWxibG9nZGVuZWd1" } } |
Probamos a descifrarlo como hemos dicho para secretos en base64:
1 2 3 |
raulunzue@KBMASTER:~$ echo 'ZWxibG9nZGVuZWd1 ' | base64 -d elblogdenegubase64: entrada inválida |
Instalamos kubeseal controller:
1 2 3 |
raulunzue@KBMASTER:~$ kubectl apply -f <a href="https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.7.0/controller.yaml">https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.7.0/controller.yaml</a> raulunzue@KBMASTER:~$ kubectl apply -f <a href="https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.7.0/sealedsecret-crd.yaml">https://github.com/bitnami-labs/sealed-secrets/releases/download/v0.7.0/sealedsecret-crd.yaml</a> |
Para cifrarlo con Kubeseal lo hacemos con el siguiente comando:
1 |
raulunzue@KBMASTER:~$ kubeseal < ebdnsecret.json > ebdnsecretsealed.json |
Lo volvemos a comprobar con cat y verificamos el encriptado es totalmente más seguro, y es un recurso “SealedSecret”.
1 |
raulunzue@KBMASTER:~$ cat ebdnsecretsealed.json |
Y aplicamos el nuevo secreto:
1 |
raulunzue@KBMASTER:~$ kubectl apply -f ebdnsecretsealed.json |
Y verificamos que disponemos de él:
1 |
raulunzue@KBMASTER:~$ kubectl get sealedsecrets |
Y revisamos los secretos:
1 |
raulunzue@KBMASTER:~$ kubectl get secrets |
Podemos ver nuestro secreto:
1 |
raulunzue@KBMASTER:~$ kubectl get secrets ebdnsecret -o yaml |
¿Te ha gustado la entrada SÍGUENOS EN TWITTER?
Te ha gustado la entrada SGUENOS EN TWITTER O INVITANOS A UN CAFE?