Capítulo 5.2 - Secrets
Objetivos de Aprendizaje
Al final de este capítulo, usted será capaz de:
- Comprender qué es un Secret y por qué utilizarlo
- Crear Secrets de diferentes maneras
- Usar Secrets en sus Pods de forma segura
- Comprender las limitaciones de seguridad de los Secrets
- Aplicar buenas prácticas para la gestión de secrets
Introducción
Los Secrets son similares a los ConfigMaps pero están diseñados para almacenar datos sensibles como contraseñas, tokens de API, claves privadas y certificados.
Importante: Los Secrets de Kubernetes no están cifrados por defecto. Solo están codificados en base64.
¿Qué es un Secret?
Un Secret es un objeto de Kubernetes que almacena datos sensibles. Por defecto, los Secrets están codificados en base64 (no cifrados).
Tipos de Secrets
Kubernetes soporta varios tipos de Secrets:
- Opaque: Datos arbitrarios (por defecto)
- kubernetes.io/dockerconfigjson: Credenciales para registros Docker
- kubernetes.io/tls: Certificados TLS
- kubernetes.io/service-account-token: Tokens de Service Account
¿Por qué Usar Secrets?
Problemas Sin Secrets
Problemas:
- Contraseñas hardcodeadas en el código
- Riesgo de exposición en Git
- Difícil de rotar
- Sin gestión centralizada
Ventajas Con Secrets
Ventajas:
- Separados del código de la aplicación
- Gestión centralizada
- Rotación facilitada
- Integración con herramientas externas (Vault, etc.)
Creación de Secrets
Método 1: Desde Literales
kubectl create secret generic db-secret \
--from-literal=username=admin \
--from-literal=password=secretpassword123
Método 2: Desde un Archivo
Crear un archivo password.txt:
mysecretpassword
kubectl create secret generic db-secret \
--from-file=password=password.txt
Método 3: Desde un Archivo YAML
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: YWRtaW4= # base64 de "admin"
password: cGFzc3dvcmQxMjM= # base64 de "password123"
Importante: Los valores en data deben estar codificados en base64.
Para codificar:
echo -n "admin" | base64
# Resultado: YWRtaW4=
Tipos de Secrets Especializados
Secret Docker Registry
Para acceder a un registro Docker privado:
kubectl create secret docker-registry regcred \
--docker-server=docker.io \
--docker-username=myuser \
--docker-password=mypassword \
--docker-email=myuser@example.com
Uso en un Pod:
spec:
containers:
- name: app
image: private-registry.io/myapp:1.0
imagePullSecrets:
- name: regcred
Secret TLS
Para certificados SSL/TLS:
kubectl create secret tls tls-secret \
--cert=tls.crt \
--key=tls.key
Uso en los Pods
Método 1: Variables de Entorno (Una Clave)
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: my-app:1.0
env:
- name: DB_USERNAME
valueFrom:
secretKeyRef:
name: db-secret
key: username
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
Método 2: Todas las Claves (envFrom)
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: my-app:1.0
envFrom:
- secretRef:
name: db-secret
Método 3: Como Volumen (Archivos)
apiVersion: v1
kind: Pod
metadata:
name: app-pod
spec:
containers:
- name: app
image: my-app:1.0
volumeMounts:
- name: secrets
mountPath: /etc/secrets
readOnly: true
volumes:
- name: secrets
secret:
secretName: db-secret
defaultMode: 0400 # Permisos: solo lectura
Resultado: Cada clave se convierte en un archivo en /etc/secrets/ con el valor decodificado.
Seguridad de los Secrets
Limitaciones Importantes
Importante:
- Los Secrets están codificados en base64, no cifrados
- Accesibles para cualquiera que tenga acceso a etcd
- Visibles con
kubectl get secret -o yaml - Los logs pueden exponer los secrets
Buenas Prácticas de Seguridad
- Activar el Cifrado en Reposo
Crear un archivo encryption-config.yaml:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-secret>
- identity: {} # Permite el descifrado
- Usar External Secrets Operator
Para integrar con Vault, AWS Secrets Manager, etc.
- RBAC Restringido
Limitar el acceso a los Secrets con RBAC:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["db-secret"]
verbs: ["get"]
- Nunca Comitear los Secrets
- Usar
.gitignorepara los archivos de secrets - Usar herramientas de gestión de secrets
- Rotación regular
Ejemplo Completo
Paso 1: Crear el Secret
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
type: Opaque
data:
database_url: cG9zdGdyZXNxbDovL3VzZXI6cGFzc0BkYjoxMjM0L215ZGI=
api_key: c2VjcmV0X2FwaV9rZXlfMTIzNDU2
jwt_secret: bXlfanN0X3NlY3JldF9rZXlfZm9yX3NpZ25pbmc=
Paso 2: Usar en un Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
replicas: 3
selector:
matchLabels:
app: webapp
template:
metadata:
labels:
app: webapp
spec:
containers:
- name: webapp
image: my-app:1.0
envFrom:
- secretRef:
name: app-secrets
volumeMounts:
- name: certs
mountPath: /etc/ssl/certs
readOnly: true
volumes:
- name: certs
secret:
secretName: tls-secret
defaultMode: 0400
Comandos Útiles
Ver un Secret (Codificado)
kubectl get secret db-secret
kubectl describe secret db-secret
kubectl get secret db-secret -o yaml
Decodificar un Secret
# Ver el valor decodificado
kubectl get secret db-secret -o jsonpath='{.data.password}' | base64 -d
Modificar un Secret
kubectl edit secret db-secret
Nota: Los valores deben estar en base64 en el editor.
Eliminar un Secret
kubectl delete secret db-secret
Rotación de Secrets
Proceso de Rotación
Pasos:
- Crear un nuevo Secret con un nombre diferente
- Actualizar el Deployment para referenciar el nuevo Secret
- Esperar a que los Pods se reinicien
- Eliminar el Secret antiguo
External Secrets Operator
Para una gestión avanzada con herramientas externas:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-secret
spec:
secretStoreRef:
name: vault-backend
kind: SecretStore
target:
name: db-secret
data:
- secretKey: password
remoteRef:
key: production/database/password
Resumen
En este capítulo, usted ha aprendido:
Secret: Objeto de Kubernetes para datos sensibles (base64, no cifrado por defecto)
Tipos: Opaque, docker-registry, TLS, service-account-token
Creación: kubectl create, YAML con valores base64
Uso: Variables de entorno o volúmenes
Seguridad: Activar cifrado en reposo, RBAC, External Secrets
Limitaciones: Solo base64, visible en etcd, logs
Rotación: Crear nuevo secret, actualizar, eliminar el antiguo
Próximos Pasos
Capítulo 5.3: Inyección en los Pods
Capítulo 5.4: Buenas Prácticas
Lab 5.2: Gestión de Secrets
Capítulo creado el: Diciembre 2024