Secrets
Secrets
Es un objeto muy parecido a ConfigMap, con la diferencia que secrets se utiliza para pasar datos sensibles, como tockens, usuarios, contraseñás, etc... La forma de pasar los datos es la misma que con configMap a trabes de volumenes o variables de entorno.
Secrets no encripta solo codifica los datos pasados a base64.
Consola
He creado un archivo que contiene datos sensibles y voy a crear un secret con ellos dentro.
sudo kubectl create secret generic mysecret --from-file=./secrets/secrets-files/secret.txt
secret/mysecret created
➜ sudo kubectl get secret mysecret
NAME TYPE DATA AGE
mysecret Opaque 1 61s
Como se puede ver a continuación el secret se crea con el contenido codificado a base64, que no es nada seguro, pero es lo que ofrece kubernetes.
➜ sudo kubectl describe secret mysecret
Name: mysecret
Namespace: default
Labels: <none>
Annotations: <none>
Type: Opaque
Data
====
secret.txt: 29 bytes
➜ sudo kubectl get secret mysecret -o yaml
apiVersion: v1
data:
secret.txt: c2VjcmV0bzE9aG9sYQpzZWNyZXRvMj1hZGlvcwo=
kind: Secret
metadata:
creationTimestamp: "2020-04-10T08:23:30Z"
name: mysecret
namespace: default
resourceVersion: "235029"
selfLink: /api/v1/namespaces/default/secrets/mysecret
uid: d28711a2-8954-44f3-a50b-0df3282762e4
type: Opaque
# se puede decodificar revirtiendo el base64 y ver l contenido del archivo.
➜ echo c2VjcmV0bzE9aG9sYQpzZWNyZXRvMj1hZGlvcwo= | base64 --decode
secreto1=hola
secreto2=adios
Template
desde un template yaml se puede pasar los datos de diferentes modos con:
data
: en esta opción se pasaran en base64 directamentestringData
: con esta opción se pasan los datos literales para luego kubernetes haga el codificado a base64.
apiVersion: v1
kind: Secret
metadata:
name: mysecret2
type: Opaque
stringData:
username: admin
password: "12345"
---
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
En los dos templates anteriores el resultado es el mismo.
➜ sudo kubectl apply -f secrets/secret-stringdata.yml
secret/mysecret2 created
➜ sudo kubectl get secret mysecret2 -o yaml
[sudo] password for debian:
apiVersion: v1
data:
password: MTIzNDU=
username: YWRtaW4=
kind: Secret
...
Seguro
Como podemos ver esta opción que proporciona kubernetes muy segura no es, pero se puede jugar con ella para mantener versiones en el git, utilizando variables de entorno.
Suponemos que tenemos un git y no queremos exponer las contraseñas, puedes asignar variables de entorno a la versión de git, para después remplazarlas con envsubst, sed
u otro, para finalmente desplegar el secret.
apiVersion: v1
kind: Secret
metadata:
name: mysecret3
type: Opaque
stringData:
username: $USER
password: $PASSWORD
remplazar variables y desplegar secret.
# creo variables
➜ export PASSWORD=contrasena
➜ export USER=jorge
# remplazo variables
➜ envsubst < secrets/secure.yml > tmp.yml
# jemplo final
➜ cat tmp.yml
apiVersion: v1
kind: Secret
metadata:
name: mysecret3
type: Opaque
stringData:
username: jorge
password: contrasena
# y desplego con el nuevo yaml
➜ sudo kubectl apply -f tmp.yml
secret/mysecret3 created
➜ sudo kubectl get secret mysecret3 -o yaml
apiVersion: v1
data:
password: Y29udHJhc2VuYQ==
username: am9yZ2U=
kind: Secret
Utilizarlos
La manera de poder utilizar los secrets en un contenedor o pod es mediante volumenes o variables de entorno o mediante ambos.
Volumen
En el siguiente yaml estoy incorporando tanto el secret como el pod, no es necesario que estén juntos solo es por visualización.
se muestra como a volumes
se le asigna el valor del secret secretName
mysecret y este sera montado en la ruta /opt/
con permisos read only.
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
stringData:
username: admin
password: "12345"
---
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: nginx:alpine
volumeMounts:
- name: test
mountPath: "/opt"
readOnly: true
volumes:
- name: test
secret:
secretName: mysecret
una vez desplegado se ve como efectivamente en /opt/
se han montado dos archivos con los valores del secret.
➜ sudo kubectl apply -f secrets/pod-vol-secret.yml
secret/mysecret created
pod/mypod created
➜ sudo kubectl exec -it mypod -- sh
/ # ls /opt/
password username
items
En los volumenes, si añadimos el valor de items
se puede especificar que nombre tendrá el archivo una vez dentro del contenedor.
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: nginx:alpine
volumeMounts:
- name: test
mountPath: "/opt"
readOnly: true
volumes:
- name: test
secret:
secretName: mysecret
items:
- key: username
path: user.txt
- key: password
path: pass.txt
➜ sudo kubectl apply -f secrets/pod-vol-secret.yml
secret/mysecret configured
pod/mypod created
➜ sudo kubectl exec -it mypod -- sh
/ # ls /opt/
pass.txt user.txt
Variables entorno
otra manera de asignar los datos de secret dentro de un pod son con las variables de entorno, donde se asigna cada valor del secret a una variable de entorno. No es necesario asignar todos los valores, si se quiere se puede asignar solo uno o mas.
apiVersion: v1
kind: Secret
metadata:
name: mysecret
type: Opaque
stringData:
username: admin
password: "12345"
---
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: nginx:alpine
env:
- name: SECRET_USER
valueFrom:
secretKeyRef:
name: mysecret
key: username
- name: SECRET_PASSWORD
valueFrom:
secretKeyRef:
name: mysecret
key: password
➜ sudo kubectl apply -f secrets/pod-env-secret.yml
secret/mysecret configured
pod/mypod created
➜ sudo kubectl exec -it mypod -- sh
/ # echo $SECRET_USER
admin
/ # echo $SECRET_PASSWORD
12345
/ #