Gestión de secretos con HashiCorp Vault

¿Cómo guardar secretos? ¿En el repositorio, en el sistema de implementación o en el sistema de gestión de configuración? ¿En una computadora personal, en servidores o tal vez en una caja debajo de la cama? ¿Y cómo gestionar los secretos para evitar fugas?

Sergey Noskov ( Albibek ), el jefe del grupo de seguridad de la información de la plataforma de Avito , conoce la respuesta a estas preguntas y compartirá con nosotros. En Avito, la Bóveda HashiCorp ha estado utilizando activamente la Bóveda HashiCorp durante dos años, tiempo durante el cual obtuvieron golpes y bombearon experiencia al nivel "Maestro".

En el artículo hablaremos exhaustivamente sobre Vault: qué es, dónde y cómo se usa en la empresa, cómo Avito maneja los secretos usando HashiCorp Vault, cómo se usan Puppet y Kubernetes, casos de uso con Puppet y otros SCM, qué problemas surgen, qué perjudica la seguridad y desarrolladores, y, por supuesto, comparten ideas sobre cómo solucionarlo.


¿Qué es un secreto?


Cualquier información confidencial:

  • inicio de sesión y contraseña, por ejemplo, a la base de datos;
  • Claves API
  • Clave de certificado del servidor (* .google.com)
  • clave de certificado de cliente (socios, dinero Yandex, QIWI);
  • clave para firmar aplicaciones móviles.

Toda la información que queremos mantener en secreto, la llamamos un secreto. Esto crea un problema de almacenamiento: almacenar en el repositorio es incorrecto, en forma cifrada; debe guardar las claves de cifrado en algún lugar.

HashiCorp Vault es una de las buenas soluciones al problema.

  • Almacena y gestiona llaves de forma segura.
  • Afilado en el mundo de los microservicios, desde el propio microservicio.
  • HashiCorp Vault ha hecho mucho para autenticar y autorizar el acceso a secretos, como las ACL y el principio de privilegios mínimos.
  • Interfaz REST con JSON.
  • La seguridad no es perfecta, pero a un nivel bastante alto.

En mi opinión, esta es una herramienta bastante conveniente.

¿Qué hay de nuevo en HashiCorp Vault?


La herramienta se está desarrollando y en los últimos años han aparecido muchas características interesantes: encabezados CORS para GUI sin intermediarios; GUI incorporada; integración nativa con Kubernetes; plugins para backends lógicos y de autenticación y framework.

La mayoría de los cambios que personalmente me gustaron son la capacidad de no escribir extensiones y adiciones que quedarán fuera de la herramienta.

Por ejemplo, hay Vault, desea expandirlo: escriba lógica adicional o su propia interfaz de usuario para la automatización, que automatizará algo. Antes de los cambios, tuve que generar un servicio adicional que Vault enfrenta y que representa todas las solicitudes: primero las solicitudes van al servicio, luego a Vault. Esto es malo porque en el servicio intermedio puede haber un nivel reducido de seguridad y todos los secretos lo atraviesan. ¡Los riesgos de seguridad son mucho mayores cuando el secreto pasa por varios puntos a la vez!

Problema de pollo y huevo


Cuando plantea el problema de almacenar información confidencial y decide cifrar, tan pronto como cifra algo, su secreto se mueve desde el lugar de cifrado hasta el lugar donde se almacena la clave. Esto sucede todo el tiempo: tan pronto como haya guardado un secreto en algún lugar o haya cambiado uno existente, tendrá otro y comenzará un círculo encantado: dónde guardar el secreto para acceder al secreto .

El secreto para acceder al secreto es esa parte de la seguridad llamada autenticación . La seguridad tiene otra parte: la autorización. En el proceso de autorización, se verifica si el usuario puede acceder exactamente donde está solicitando. En el caso de Vault, hay un tercero de confianza que decide si revela el secreto o no. La autorización solo resuelve parcialmente el problema.

Bóveda HashiCorp en Avito


En Avito, HashiCorp se instala en la única instalación grande en toda la red. HashiCorp Vault tiene muchos backends diferentes. También utilizamos el backend basado en el Cónsul de HashiCorp, porque Vault solo puede soportar su propia tolerancia a fallas a través del cónsul.

Unseal es una forma de no mantener la llave maestra en un solo lugar. Cuando se inicia Vault, cifra todo en una clave, y nuevamente aparece el problema del huevo y la gallina: dónde guardar un secreto, que cifrará todos los demás secretos. Para evitar este problema, Vault proporciona una clave compuesta, que requiere varias partes de la clave, que distribuimos a varios empleados. En Avito, configuramos Unseal en las opciones para 3 personas de 7. Si iniciamos Vault, al menos 3 personas deben ingresar e ingresar su parte de la clave para que comience a funcionar. La clave se divide en 7 partes y puede traer cualquiera de ellas.

Hemos preparado un pequeño Vault de prueba, un sandbox para desarrolladores donde pueden jugar. Tiene la forma de un contenedor Docker y crea secretos simples para que las personas puedan tocar la herramienta con las manos y sentirse cómodos. No hay Cónsul y agrupación en la caja de arena, es solo un sistema de archivos en el que Vault contiene secretos cifrados y un pequeño script para inicializar.

Esto es lo que ahora almacenamos en Vault:

  • Casi todos los secretos para los microservicios de Kubernetes: contraseñas de bases de datos, claves API, todo lo anterior.
  • Secretos para colocar en los servidores "de hierro" y LXC.
  • También ponemos secretos para las compilaciones de CI / CD en TeamCity en Vault. La cobertura no es del 100%, pero es bastante aceptable.
  • Las claves de todos los certificados: PKI interna, CA externas, por ejemplo, GeoTrust y similares.
  • Secretos comunes para equipos.

En el interior, Vault almacena todo solo en JSON, no siempre es conveniente y requiere acciones adicionales del desarrollador, por lo que básicamente publicamos secretos en forma de archivo.

Intentamos entregar secretos en forma de archivos.

No le decimos al desarrollador: "¡Ve a Vault, toma un secreto!", Pero coloca el archivo en el disco y di: "Desarrollador, aparecerá un archivo en tu disco, toma el secreto y ya descubriremos cómo obtenerlo de Vault y traerlo a ti ".


Adoptamos un acuerdo simple para los campos JSON, en el que indicamos con qué derechos cargar el archivo. Estos son metadatos para el sistema de archivos, y el campo de datos es una cadena codificada con el secreto mismo, que se convertirá en el contenido del archivo.

Marioneta + Hiera + Bóveda


Casi toda la infraestructura de Avito usa Puppet, implementa todos los servidores.

Puppet tiene una herramienta conveniente para organizar jerarquías: Hiera . Vault se integra muy bien con Hiera a través de un módulo adicional, porque la solicitud de valor-clave se envía a esta biblioteca, y Vault es la base de datos de valor-clave en sí, pero con todas las características de seguridad, con cifrado transparente y la posibilidad de elegir el acceso clave.

Por lo tanto, lo primero que implementamos es Vault in Puppet, pero con una adición: tenemos una capa intermedia llamada Router backend . Backend del enrutador: un módulo Hiera separado, solo archivos en el disco que dice a dónde debe ir Hiera para obtener la clave, en Vault o en otro lugar.

Es necesario para que Hiera no vaya a la Bóveda constantemente, porque ella siempre recorre toda la jerarquía. Este no es un problema o carga de Vault, sino una característica de Hiera. Por lo tanto, si deja solo el módulo para Vault sin el backend del enrutador, el Puppet master tardará mucho tiempo en recopilar la configuración para el agente Puppet, ya que verificará cada clave en el Vault.


Para Puppet, el problema de las gallinas y los huevos se resuelve debido al hecho de que la parte que autoriza es el Puppet master. Es él quien da el secreto para acceder al secreto. El Puppet master tiene acceso a todos los secretos a la vez, pero cada host solo puede recibir el que está destinado para él. El host en el Puppet master ya está autorizado por su certificado, que se genera localmente y no deja los límites del host. En principio, el secreto para acceder al secreto permanece, pero esto no es tan crítico.

Nuestro proceso de revelar un nuevo secreto en Puppet consiste en los siguientes pasos.

  • Tomamos un secreto en alguna parte: alguien nos lo da o lo apaga.
  • Poner un secreto en Vault, con una jerarquía como en Hiera: /puppet/role/www/site.ssl.key .
  • Registramos un prefijo en el manifiesto de Puppet, que indica que el archivo está en Vault y dónde obtenerlo.
  • Escribimos la ruta en Vault en YAML para el enrutador Hiera y el backend para que Hiera pueda encontrarlo.
  • Tire de la solicitud a través de GIT al repositorio de manifiesto.
  • Ejecute o espere a que se ejecute el agente de Puppet.

Los agentes títeres se escapan con nosotros cada 30 minutos, por lo que debe esperar un poco hasta que se revele el secreto. Esto no causa problemas: no compartimos secretos todos los días . Mientras Kubernetes no esté involucrado en el negocio, no hay muchos gastos generales y estamos listos para poner secretos en Vault con nuestras manos con una automatización mínima.

Una ventaja adicional es que obtenemos el "chip" Hiera: el secreto puede establecerse inmediatamente para un grupo de hosts o dependiendo del rol del host, que establecemos en el rol variable.

El único peligro : si tiene Puppet y usa Hiera, no sustituya nada que entre en las plantillas de variables porque muchos datos y variables se recopilan del lado del cliente. Si un atacante sustituye un hecho en el cliente, el maestro de marionetas le dará los secretos de otras personas. Asegúrese de verificar las variables : use solo aquellas que Puppet-master no permita determinar en el lado del cliente.

¿Qué hacer con SCM sin un asistente?


Si de repente no tienes Puppet, lo más probable es que sea Ansible. Para Chef y otros SCM centralizados, sus soluciones son un complemento que puede acceder a Vault. Ofrezco varias opciones que se pueden implementar con Ansible.

Agente local


Localmente para el servidor, genere un token, que en realidad es la contraseña para acceder a la Bóveda. El token es válido todo el tiempo. Puede actualizarlo o automatizarlo. Con esta ficha vas a la Bóveda y te quitas tus secretos.

La idea es que en su servidor donde necesita entregar secretos, el agente que viene a Vault está girando, mira todos los secretos y los pone en forma de archivos. Usamos el agente en varios servidores separados donde no hay Puppet.

Contras:

  • El token es fácil de ingresar en un segmento pequeño, pero si tiene varias docenas de servidores implementados por día, tendrá que generar un token para cada servidor y prescribir una política. Esto es inconveniente.
  • El token necesita ser actualizado.
  • Agrupar servidores por rol, propósito o hechos es difícil, debe sincronizarse con Vault.

Cifrado de tránsito


Vault tiene una función de cifrado de tránsito, cuya esencia es que Vault actúa como un servidor de cifrado . Simplemente le trae texto sin formato, y él, en su clave privada, que solo él tiene, cifra y emite el texto cerrado. Luego, elige quién puede descifrar este texto cerrado.

Ansible tiene una entidad, también llamada Vault. Esta no es una Bóveda HashiCorp, sino una Bóveda Ansible . No hay necesidad de confundir, y los secretos se pueden almacenar tanto en el primero como en el segundo. Ansible tiene un complemento listo para entregar secretos de Hashicorp Vault. Si le da acceso personal a Vault, puede descifrar secretos. Cuando lanza Ansible, va a Vault en su nombre, descifra los secretos que están encriptados en el repositorio y lo pone en producción.

También hay un inconveniente: cada administrador tiene acceso a los secretos . Pero hay una auditoría: Vault sabe cómo mantener un registro de actividad sobre qué usuario entró, qué secreto leyeron, a cuál tuvo acceso. Siempre sabes quién, cuándo y qué hizo con un secreto. Esta opción me parece buena.

Gran defecto # 1


El mayor inconveniente que nos causa el mayor dolor es que en Vault no se puede delegar el control total a ninguna parte de los datos a nadie. En Vault, el acceso al secreto se lleva a cabo de manera similar a los de UNIX: los nombres suelen estar separados por barras y el resultado es un "directorio". Cuando tienes ese camino, a veces quieres tomar parte del camino y dárselo a otra persona para que lo controle.


Por ejemplo, usted obtuvo certificados, llamados / certs , y desea entregarlos a oficiales de seguridad individuales que se ocupan de PKI. Vault no puede hacer esto. No puede otorgar el derecho de emitir derechos dentro de este prefijo, de modo que los propios guardias de seguridad puedan distribuir los derechos de los certificados a otra persona.

Vault no tiene la capacidad de otorgar derechos selectivos para otorgar derechos . Tan pronto como otorgó el derecho de otorgar derechos, también dio la oportunidad de obtener acceso completo a todos los secretos. En otras palabras, no puede dar acceso a la parte de Vault.

Este es uno de los mayores problemas. Tengo una idea de cómo resolverlo, te lo contaré más tarde.

Kubernetes


En RIT ++, hablé sobre un sistema separado que implementamos para Kubernetes : sirve como un tercero, va a la API, verifica el acceso y luego solicita un secreto en Vault.

Ahora nuestro sistema ha perdido relevancia, porque en Vault 0.9, apareció el soporte nativo para Kubernetes. Ahora Vault mismo sabe cómo ir a Kubernetes y asegurarse de que se permita el acceso al secreto. Lo hace con un token de cuenta de servicio . Por ejemplo, cuando tiene un pod desplegado, hay un JWT especial, firmado y autorizado para él, diseñado para solicitudes a la API de Kubernetes. Con un token, también puede iniciar sesión en Vault y obtener secretos específicamente para su espacio de nombres.

Todo se hace al nivel de Vault. Es cierto que será necesario iniciar un rol para cada espacio de nombres, es decir, decirle a Vault que existe dicho espacio de nombres, habrá autorización y registrar dónde ir a Kubernetes. Esto se hace una vez, y luego Vault irá a la API, confirmará la validez del JWT y emitirá su propio token de acceso.

Reglas de Kubernetes


En términos de nombre del servicio y metadatos adicionales, confiamos en los desarrolladores. Existe una pequeña posibilidad de que los desarrolladores puedan obtener accidental o intencionalmente los secretos de otros servicios que giran en un espacio de nombres, por lo que introdujimos una regla: un servicio , un espacio de nombres.

Nuevo microservicio? Obtenga un nuevo espacio de nombres con sus secretos. No puede cruzar la frontera hacia la vecina: hay su propio token de cuenta de servicio. La frontera de seguridad en Kubernetes en este momento es el espacio de nombres. Si en dos espacios de nombres diferentes necesita un secreto, cópielo.

Kubernetes tiene secretos kubernetes . Se almacenan en etcd en Kubernetes en forma no encriptada y se pueden "iluminar" en el tablero de instrumentos o cuando se inicia Kubectl get pods. Si la autenticación en etcd está deshabilitada en su clúster, o si le dio a alguien acceso completo de solo lectura, entonces todos los secretos son visibles para él. Es por eso que introdujimos dos reglas: está prohibido usar secretos de kubernetes y está prohibido especificar secretos en variables de entorno en manifiestos . Si escribe un secreto en el entorno en despliegue.yaml, esto es malo, porque el manifiesto en sí puede ser visto por cualquiera que no sea perezoso.

Entrega Kubernetes


Como dije, de alguna manera debemos poner el archivo en Kubernetes. Tenemos algún tipo de secreto: la esencia, la contraseña, que está escrita en JSON en Vault. ¿Cómo convertirlo en un archivo dentro del contenedor en Kubernetes ahora?


La primera opción de entrega.

  • Iniciamos un contenedor init especial.
  • Se parte de nuestra imagen.
  • La imagen contiene una pequeña utilidad que va a Vault con el token de cuenta de servicio, toma el secreto y lo coloca en el volumen Compartido.
  • Para la utilidad, se monta un volumen compartido especial solo en la memoria TMPFS para que los secretos no pasen por el disco.
  • Init-container va a Vault, pone en este volumen en forma de archivos todos los secretos que encuentra en la ruta especificada.
  • A continuación, el volumen compartido se monta en el contenedor principal en el que se requiere.
  • Cuando se inicia el contenedor principal, inmediatamente obtiene lo que el desarrollador necesita: secretos en forma de un archivo en el disco.

El desarrollador solo necesita recordar el camino en el que se encuentra su secreto.

Usamos algo como este prefijo:

/k8s/<cluster>/<namespace>/<service>/some_secret 

El nombre del prefijo contiene el nombre del clúster, el espacio de nombres y el nombre del servicio. Cada servicio tiene su propio secreto, cada espacio de nombres tiene su propio secreto.

La segunda opción es su propio punto de entrada . Ahora nos estamos moviendo hacia él en Avito, porque los desarrolladores tienen problemas con init-container. En el diagrama, esta opción está a la derecha.

No todos pueden permitirse su propio punto de entrada. Podemos, así que en cada contenedor forzamos nuestro punto de entrada especial.

Nuestro punto de entrada hace lo mismo que init-container: va a Vault con un token de cuenta de servicio, toma secretos y los apaga. Además de los archivos, los vuelve a colocar en el entorno. Tiene la oportunidad de ejecutar la aplicación como lo recomienda el concepto de la aplicación Twelve-Factor : la aplicación toma todas las configuraciones, incluidos los secretos, de las variables de entorno.

Las variables de entorno no son visibles en el manifiesto y el tablero, ya que se configuran mediante PID 1 (el proceso del contenedor principal) al inicio. Estas no son variables de entorno de despliegue.yaml, sino variables de entorno establecidas por punto de entrada en el proceso. No son visibles en el tablero, no son visibles, incluso si realiza kubectl exec en un contenedor, porque en este caso se inicia otro proceso, paralelo al PID1.

Flujo de trabajo


Desde el punto de vista organizacional, el proceso es el siguiente. El desarrollador aprende del defensor de la seguridad o de la documentación que no debe guardar secretos en el repositorio, sino solo en Vault. Luego viene a nosotros y nos pregunta dónde guardar secretos: envía una solicitud a seguridad para establecer un prefijo. En el futuro, puede crear un prefijo sin una solicitud, inmediatamente al crear un servicio.

El desarrollador está esperando, y esto es malo, porque lo principal para él es el tiempo de comercialización. Luego lee las instrucciones, trata con archivos largos: "inserte esa línea allí, inserte esta línea aquí". Un desarrollador nunca antes había iniciado un contenedor init, pero se ve obligado a resolverlo y registrarlo en deploy.yaml (diagrama de timón).

Commit -> deploy -> feel pain -> fix -> repeat

Se compromete, espera a que TeamCity se despliegue, ve errores en TeamCity, comienza a sentir dolor, trata de arreglar algo, experimenta dolor nuevamente. Además, se superpone que cada lanzamiento en TeamCity todavía se puede poner en cola. A veces, un desarrollador no puede resolverlo por sí mismo, viene a nosotros y lo resolvemos juntos.

Básicamente, el desarrollador sufre debido a sus propios errores: contenedor de inicio especificado incorrectamente o no leyó la documentación .

La seguridad también tiene problemas. El guardia de seguridad recibe una aplicación en la que siempre hay poca información, y todavía descubrimos las preguntas que faltan: averiguar los nombres de los clústeres, el espacio de nombres del servicio, ya que el desarrollador no los indica en la aplicación y ni siquiera siempre sabe qué es. Cuando descubrimos todo, creamos políticas y roles en Vault, prescribimos políticas a grupos y, junto con el desarrollador, comenzamos a descubrir dónde y por qué cometió un error, y juntos leemos los registros.

La unidad "Arquitectura" ayuda a resolver el problema ocultándose del desarrollador de despliegue.yaml. Están desarrollando una pieza que genera todo para el desarrollador, incluido el punto de entrada. Debido al hecho de que sustituimos nuestro punto de entrada, podemos usarlo no solo para entregar secretos, sino también para otras cosas que puede necesitar hacer al inicio.

Problemas obvios con los secretos de Kubernetes.


  • Flujo de trabajo muy complicado tanto para el desarrollador como para el guardia de seguridad.
  • No puedes delegar nada a nadie. El guardia de seguridad tiene acceso completo a la Bóveda, y el acceso parcial no es posible (ver Big Flaw # 1).
  • Las dificultades surgen al mover desarrolladores de un clúster a otro, de un espacio de nombres a otro, cuando se necesitan secretos compartidos, porque inicialmente se supone que los diferentes secretos son diferentes en diferentes clústeres.

Decimos: “¿Por qué necesitas secretos de producción en el clúster de desarrollo? Obtenga un secreto de prueba, ¡adelante! Como resultado, hay minas y secretos que son difíciles de manejar. Si el secreto ha cambiado, no debe olvidarse de él, vaya y cámbielo por todas partes, y aunque no hay forma de determinar que es el mismo secreto, excepto por el nombre del servicio.

Idea: Kubernetes KMS


En las nuevas versiones de Kubernetes, el subsistema KMS, Servicio de administración de claves, es una nueva función de cifrado secreto de Kubernetes. En v1.11 estaba en estado alfa, en v1.12 se transfirió a beta.

La imagen es del sitio del proyecto del proveedor de KMS para Vault, y hay un error en ella. Si lo encuentra, escriba en los comentarios.

El significado de KMS es eliminar un único inconveniente: el almacenamiento de datos sin cifrar en etcd.

KMS, como Ansible, puede hacer esto.

  • Ve a algún lado, encripta el secreto nativo de Kubernetes y ponlo en forma encriptada.
  • Si es necesario, entregue a la cápsula, descifre y coloque en forma descifrada.

Los desarrolladores han escrito un servicio especial que hace esto usando cifrado de tránsito. La idea parece estar funcionando, pero es importante recordar que los secretos dejan de estar solo bajo el control de Vault y van a otra parte, dentro del área de responsabilidad de los administradores de Kubernetes.

Contras KMS.

  • Descentralización del almacenamiento : toma de control de Vault a Kubernetes (etcd) . Los secretos se vuelven incontrolables por Vault, y es bueno como un depósito centralizado de secretos. Resulta que la mitad de los secretos en Vault, y la otra mitad en otro lugar.
  • Solución solo de Kubernetes . Si tienes una infraestructura solo de Kubernetes, recoges Vault y casi no piensas lo que está almacenado allí, porque contiene solo las claves de cifrado que administra correctamente: rotar regularmente, etc. Los secretos están en Kubernetes, y esto es conveniente.
  • Es difícil compartir secretos entre grupos . Para cada nuevo clúster, debe comenzar de nuevo, copiando secretos como en el caso de una sola Bóveda puede no funcionar.

Pros de KMS.

  • Soporte nativo en Kubernetes, incluida la ocultación al mostrar el entorno.
  • Autorización en el área de responsabilidad de Kubernetes .
  • Prácticamente no se necesita soporte de Vault .
  • Rotación de llave fuera de la caja .

CI / CD: TeamCity


Todo es simple en TeamCity, porque JetBrains escribió un complemento que puede prescribir secretos para acceder al secreto, encriptarlos con TeamCity y luego sustituirlo en porcentaje en la plantilla en algún lugar de la plantilla. En este momento, el agente TeamCity mismo va a Vault, toma el secreto y lo trae a la compilación como parámetro.

Se necesitan algunos secretos durante la implementación, por ejemplo, migración de base de datos o alertas en Slack. AppRole se inicia para cada proyecto; la configuración también contiene un secreto (datos para AppRole), pero se ingresa en modo de solo escritura; TeamCity no permite leerlo más tarde.

TeamCity se encarga de que cuando un secreto ingrese a los registros de compilación, se disfrace automáticamente. Como resultado, el secreto no "pasa" a través del disco o se borra del disco utilizando las herramientas de TeamCity. Como resultado, toda la seguridad del secreto está bien garantizada por TeamCity y el complemento, y no se requieren bailes adicionales con una pandereta

¿CI / CD no es TeamCity?


Estos son los principales problemas a considerar si está utilizando un sistema diferente (no TeamCity) como CI.

  • Aislamiento: limite el alcance de un secreto a un proyecto, equipo, etc.
  • Quién autoriza el acceso al secreto.
  • Excluya la capacidad de ver el secreto de la parte que autoriza.
  • Una etapa separada de la compilación es importar el secreto a los archivos.
  • Limpia después de ti mismo.

Como resultado, lo más probable es que escriba algo muy similar al complemento TeamCity para su CI / CD. La parte que autoriza aquí probablemente sea CI / CD, y será ella quien decidirá si esta compilación puede tener acceso a este secreto y si debe proporcionar el secreto en función de los resultados.

Es importante no olvidar limpiar los resultados de la compilación al final del ensamblaje , si se colocaron en un disco, o asegurarse de que solo estén en la memoria.

Certificaciones


Los certificados no tienen nada de especial: utilizamos Vault principalmente para su almacenamiento.


Vault tiene un back-end PKI especial para emitir certificados, en el que puede crear una Autoridad de certificación y firmar nuevos certificados. Tenemos una PKI interna única ... La CA raíz y la CA de segundo nivel existen por separado, y ya administramos la CA de tercer nivel a través de Vault. Para almacenar certificados emitidos de cualquier nivel, incluidos los certificados firmados por CA externas, utilizamos un prefijo separado y colocamos allí casi todos los certificados válidos para fines de contabilidad y monitoreo. El formato para almacenar certificados es propietario, adecuado para almacenar una clave privada separada y el certificado en sí.

Resumen


Demasiado trabajo manual para el guardia de seguridad, demasiado umbral de entrada para el desarrollador y sin herramientas de delegación integradas, aunque realmente quiero ...

Como ser Entonces comienzan los sueños.

Ideas: como hacerlo mejor


¿Cómo puedo deshacerme de un montón de copias de un secreto?

Entrega maestro-esclavo


Tenemos un secreto maestro y un demonio especial que camina, mira el secreto y sus metadatos, lo pone donde sea necesario, resulta ser un secreto esclavo. En el camino donde el demonio envió al esclavo, nada se puede cambiar a mano, porque el demonio vendrá y volverá a colocar el secreto maestro encima del esclavo.

Al principio queríamos hacer un mecanismo de enlace simbólico para indicar simplemente: "¡Busque este secreto allí!", Como en Linux. Resultó que hay problemas con los derechos de acceso: no se sabe cómo verificar los derechos de acceso, como en Linux o no, con rutas principales, con transiciones entre puntos de montaje. Hay demasiados momentos ambiguos y posibilidades de cometer un error, por lo que rechazamos los enlaces simbólicos.

Autorización de propiedad


Lo segundo que queremos hacer es determinar el propietario de cada secreto . Por defecto, el secreto pertenece a la persona que lo creó. Si es necesario, puede ampliar el área de responsabilidad de la unidad emitiendo un grupo de propietarios.

Cuando aprendamos a delegar, le daremos al propietario el derecho a un secreto, y él podrá hacer con el secreto lo que quiera.

  • Difundido en k8s: se genera una política, se crea una copia esclava.
  • Propagación en el servidor: se genera una política, se crea una copia esclava.
  • Difundido en CI / CD - ...
  • Transferencia a otro propietario.
  • Dar nuevo acceso, generar nuevas ACL.

Ahora somos responsables de todos los secretos y la seguridad, pero queremos transferir la responsabilidad al creador. La seguridad no se verá afectada , porque la persona que nos solicitó mantener un secreto comprende que necesita mantener un secreto de manera segura y es consciente de su responsabilidad.

Como es el propietario del secreto, para la opción de entrega maestro-esclavo, podría elegir dónde y en qué formato se le debe entregar el secreto. Resulta que el propietario maneja todo por sí mismo, no hay necesidad de enviar solicitudes, puede tomar el prefijo necesario usted mismo, también puede crear y eliminar secretos usted mismo.

Delegación a través de plantillas de ACL


La política de acceso de la Lista de control de acceso en Vault se divide en dos partes:

  • Lista de control de acceso en la vista clásica, que describe el acceso al prefijo, qué forma de leer y escribir, qué solo leer, etc.
  • Al crear una ACL dentro, puede escribir un asterisco al final, lo que significa "este prefijo y todo lo que está debajo". El prefijo se puede asignar como una operación separada, dada al usuario o grupo, es decir, adjuntada a varias entidades diferentes.

En este momento, solo el administrador de Vault puede cambiar la ACL. Después de obtener acceso a dicha ACL, puede prescribir todo lo que desee dentro, por ejemplo, la path “*” { capabilities = [sudo, ...] } , y obtener acceso completo. Esta es la esencia de Biggest Flaw # 1: es imposible prohibir cambiar el contenido de ACL.

Queremos establecer las ACL con una plantilla preparada que contenga la ruta y los marcadores de posición en los que se permite generar nuevas ACL para esta plantilla.

Ejemplo


A continuación se muestra la fuente amarilla, la ruta de acceso de la ACL estándar terminada de Vault y las acciones permitidas en esta ruta. Lo consideramos como una ACL para obtener permiso para cambiar otra ACL a continuación, que se proporciona en forma de plantilla.


Queremos delegar el acceso a / k8s, permitimos que solo se generen dichas plantillas. Por ejemplo, otorgue acceso de solo lectura a un clúster específico, espacio de nombres, servicio, pero no cambie el campo de capacidades.


Además, queremos dar permiso para vincular estas ACL y emitir diferentes derechos.

Aplicamos la plantilla para otorgar derechos al desarrollador. Al $ vault write policy-mgr/create/k8s-microservice ... plantillas, ejecutó el $ vault write policy-mgr/create/k8s-microservice ... Y como resultado, obtuvimos una ACL que establece cluster = prod, namespace = ..., service = ... etc. Los derechos se establecieron automáticamente, se creó una política con el nombre /k8s/some-srv ; este es solo el nombre de ACL que se puede generar a partir de la plantilla.


Como resultado, el desarrollador, a nuestra discreción, asigna esta ACL a cualquier persona que quiera, y se convierte en el propietario, puede administrarla en secreto: eliminar, dar y quitar a usuarios y grupos. Ahora la persona misma es responsable de su prefijo: administra todos los secretos, genera ACL de acuerdo con la plantilla, puede asignar ACL a los que desee. Naturalmente, también podemos limitarlo.

Toda la magia funciona con la nueva entidad Vault: complementos . Son un servicio separado, muy similar al que mencioné al principio, y funcionan casi exactamente igual. La única diferencia importante es que no son representantes. Los complementos se lanzan "al costado" de Vault, y lanza su proceso principal de Vault. Debido a esto, todas las solicitudes no pasan por el servicio, sino a Vault, que ya interactúa con el complemento y le envía una solicitud verificada y aprobada.

Sobre los complementos, cómo están organizados y cómo escribirlos, puede leerlos en el sitio web de Vault . Es mejor escribirlos en Go, que es bastante simple, porque Hay un marco para Go. Vault se comunica con el complemento a través de grpc, lo lanza como un servicio, pero no se asuste, no lo toca, todo ya está en el marco. Simplemente escribe una aplicación REST más o menos estándar en la que especifica puntos finales, les da funciones listas para usar, controladores que tendrán lógica en ellos.

No tengas miedo de romper algo en la Bóveda principal. Un complemento es un servicio separado. Incluso si su complemento entró en pánico y se bloqueó, no interrumpirá el trabajo de Vault. Vault simplemente reiniciará el complemento y continuará funcionando.

Además, hay configuraciones adicionales para el complemento en sí: siempre verifica las sumas hash para que nadie cambie el binario. Se proporciona la seguridad de ejecutar complementos .

Enlaces utiles:



Hablaremos sobre DevOps y seguridad, CI / CD, k8s, Puppet y todo eso en HighLoad ++ (el más cercano en San Petersburgo en abril) y DevOpsConf . Ven y comparte tu experiencia o mira a los demás. Para no olvidar, suscríbase al blog y al boletín informativo , en el que le recordaremos los plazos y recopilaremos materiales útiles.

Source: https://habr.com/ru/post/438740/


All Articles