
Los secretos son esenciales para operar muchos sistemas en producción. Su exposición accidental es uno de los principales riesgos que se deben mitigar adecuadamente. Los desarrolladores deben hacer todo lo posible por proteger los secretos de sus aplicaciones.
El problema se complica aún más cuando una empresa migra a una arquitectura de microservicios y varios servicios necesitan acceder a distintos secretos para funcionar correctamente. De ahí surge un nuevo reto: ¿cómo distribuir, gestionar, monitorear y rotar los secretos de las aplicaciones sin exponerlos accidentalmente?
Kubernetes Secrets
Kubernetes ofrece un objeto llamado Secret, que sirve para almacenar datos sensibles de las aplicaciones, como contraseñas, claves SSH, claves de API, tokens y demás. Un Kubernetes Secret puede inyectarse en el contenedor de un Pod como variable de entorno o montarse como archivo. Usar Kubernetes Secrets nos permite abstraer los datos sensibles y la configuración del despliegue de la aplicación.
Por ejemplo, un Kubernetes secret se puede crear con el comando kubectl create secret:
https://gist.github.com/02c582490747681776f1f480ec2f4165
o mediante el archivo db-credentials.yaml de Kubernetes, que describe el mismo secret:
Ten en cuenta que almacenar datos sensibles en un Kubernetes Secret no los vuelve seguros por sí mismo. De forma predeterminada, todos los datos en Kubernetes Secrets se guardan como texto plano codificado con base64.
A partir de la versión 1.13, Kubernetes admite el cifrado de los datos de Secrets en reposo, mediante el objeto EncryptionConfiguration con un proveedor de cifrado integrado o externo.
Lista de proveedores de cifrado actualmente soportados:
Proveedores integrados: aescbc, aesgsm, secretbox
Sin embargo, el cifrado de Secrets en reposo no se aplica por defecto. Y aun cuando está activado, no basta y no puede considerarse una solución completa de gestión de secretos.
Una solución completa de gestión de secretos también debe contemplar: distribución de secretos, rotación, control de acceso granular, registro de auditoría, monitoreo de uso, versionado, almacenamiento con cifrado robusto, una API práctica y SDK de cliente, además de otras funciones útiles.
Gestión de secretos en la nube
Varios proveedores de nube ofrecen servicios de gestión de secretos como parte de su plataforma, lo que te ayuda a proteger los secretos necesarios para acceder a aplicaciones, servicios y APIs. Con estos servicios ya no hace falta dejar información sensible escrita en texto plano dentro del código ni desarrollar un ciclo de vida casero para gestionar secretos. Los servicios de gestión de secretos te permiten controlar el acceso a los secretos de las aplicaciones mediante permisos granulares y auditoría.
Integrar Kubernetes con servicios de gestión de secretos
En general, cualquier aplicación puede usar el SDK/API específico del proveedor para acceder a los secretos almacenados en un servicio de gestión de secretos. Por lo común, esto requiere modificar el código de la aplicación o recurrir a algún tipo de script de arranque o a Init containers, mediante herramientas CLI de cliente o APIs web.
Hazlo fácil con la herramienta secrets-init
Hoy lanzamos doitintl/secrets-init, una herramienta open source (Apache License 2.0) que simplifica la integración de los servicios nativos de la nube de gestión de secretos con workloads en contenedores que se ejecutan en clusters de Kubernetes administrados o autogestionados.
En esencia, secrets-init es un sistema init minimalista, diseñado para ejecutarse como PID 1 dentro de un entorno de contenedor, de forma similar a dumb-init, y ofrece una integración fluida con varios servicios nativos de la nube de gestión de secretos, como:
¿Por qué necesitas un sistema init en un contenedor de Docker?
Te recomendamos leer la explicación del repositorio de Yelp dumb-init
En resumen:
- Reenvío adecuado de señales
- Recolección de procesos zombi huérfanos
Qué hace secrets-init
secrets-init se ejecuta como PID 1 y actúa como un sistema init simple que sirve de ENTRYPOINT o primer comando del contenedor: se encarga de lanzar un proceso hijo y de redirigir todas las señales del sistema a una sesión enraizada en ese proceso hijo. Esa es la esencia de un proceso init. Por otro lado, secrets-init también pasa casi todas las variables de entorno sin modificarlas, reemplazando las variables de secretos especiales con valores provenientes de los servicios de gestión de secretos.
Integración con Docker
secrets-init es un binario compilado estáticamente (sin dependencias externas) y se integra fácilmente en cualquier imagen de Docker. Descarga el binario secrets-init y úsalo como ENTRYPOINT del contenedor de Docker.
Por ejemplo:
https://gist.github.com/7efe25155c034ee1b978a2477b3224e4
Integración con Kubernetes
Para usar secrets-init con un objeto de Kubernetes (Pod/Deployment/Job/etc.) sin modificar la imagen de Docker, considera inyectar secrets-init en el Pod destino mediante un initContainer. Puedes usar la imagen de Docker doitint/secrets-init o crear la tuya. Copia el binario secrets-init desde el init container a un volumen compartido común y modifica el command del Pod para que ejecute secrets-init como primer comando.
Integración con AWS Secrets Manager
Para empezar a usar secrets-init con AWS Secrets Manager, basta con poner el ARN del secret de AWS como valor de la variable de entorno. secrets-init resolverá cualquier valor de entorno, usando el ARN especificado, al valor del secret referenciado.
Ejemplo de uso de secrets-init con un Job de Kubernetes:
https://gist.github.com/6ae6d57ed08b26c64f534f87fc1872df
Integración con AWS Systems Manager Parameter Store
Es posible usar AWS Systems Manager Parameter Store para almacenar parámetros de la aplicación en texto plano o cifrados (una especie de secretos).
Como en el ejemplo anterior, el usuario puede poner el ARN de AWS Parameter Store como valor de la variable de entorno. secrets-init resolverá cualquier valor de entorno, usando el ARN especificado, al valor del parámetro referenciado.
Ejemplo de formato de AWS Systems Manager Parameter Store:
https://gist.github.com/9a7a83ec1659c391412557e5af340f42
Para resolver secretos de AWS Secrets Manager y Parameter Store, secrets-init debe ejecutarse con un IAM role que tenga permisos para acceder a los secretos deseados.
Esto se consigue asignando un IAM Role al Pod de Kubernetes o a la Task de ECS. Consulta el blog post de EKS Introducing fine-grained IAM roles for service accounts.
También puedes asignar un IAM Role a la instancia EC2 donde corre el contenedor, pero esa opción es bastante menos segura y no se recomienda.
Integración con Google Secret Manager
Google Cloud lanzó hace poco un nuevo servicio para gestionar secretos en la nube: Google Secret Manager
El usuario puede poner el nombre del secret de Google, usando el prefijo que secrets-init reconoce (gcp:secretmanager:), seguido del nombre del secret (projects/{PROJECT_ID}/secrets/{SECRET_NAME} o projects/{PROJECT_ID}/secrets/{SECRET_NAME}/versions/{VERSION}) como valor de la variable de entorno. secrets-init resolverá cualquier valor de entorno, usando el nombre especificado, al valor del secret referenciado.
https://gist.github.com/65d46eb2b1fe44417a9d91828c94712d
Para resolver secretos de Google desde Google Secret Manager, secrets-init debe ejecutarse con un IAM role que tenga permisos para acceder a los secretos deseados.
Esto se logra asignando un IAM Role al Pod de Kubernetes con Workload Identity. También puedes asignar un IAM Role a la instancia GCE donde corre el contenedor, pero esa opción es menos segura.
(15–03–2020) Actualización: Kubernetes Admission Webhook
El proyecto kube-secrets-init implementa un admission webhook de Kubernetes que inyecta un initContainer en cualquier Pod con referencias explícitas (variable de entorno) o implícitas (Secrets y ConfigMaps de Kubernetes) a secretos en la nube.
Enlaces útiles
- Kubernetes GKE Workload Identity, blog post de DoiT
- doitintl/secrets-init, repositorio en GitHub
- kube-secrets-init, repositorio en GitHub del admission webhook de Kubernetes
Resumen
Espero que este post te resulte útil. Quedo atento a tus comentarios y a cualquier pregunta que tengas.
¿Quieres más artículos? Visita nuestro blog o sigue a Alexei en Twitter.