Pregunta ¿Cómo puedo implementar ansible con contraseñas por host de forma segura?


Me gustaria usar ansible para gestionar un grupo de servidores existentes. He creado un ansible_hosts archivo, y probado con éxito (con el -K opción) con comandos que solo se dirigen a un único host

ansible -i ansible_hosts host1 --sudo -K # + commands ...

Mi problema ahora es que las contraseñas de los usuarios en cada host son diferentes, pero no puedo encontrar una manera de manejar esto en Ansible.

Utilizando -K, Solo se me solicita una única contraseña de sudo por adelantado, que luego parece ser probada para todos los hosts posteriores sin preguntar:

host1 | ...
host2 | FAILED => Incorrect sudo password
host3 | FAILED => Incorrect sudo password
host4 | FAILED => Incorrect sudo password
host5 | FAILED => Incorrect sudo password

Investigación hasta ahora:

  • una Pregunta de StackOverflow con una respuesta incorrecta ("use -K") y una respuesta del autor diciendo" Descubrí que necesitaba sudo sin contraseña "

  • los documentos ansibles, que dicen "El uso de sudo sin contraseña hace que las cosas sean más fáciles de automatizar, pero no es requerido"(énfasis mío)

  • Esta pregunta de seguridad StackExchange que lo toma como leído que NOPASSWD es requerido

  • artículo "Aprovisionamiento escalable y comprensible ..." que dice:

    "ejecutar sudo puede requerir escribir una contraseña, que es una forma segura de bloquear Ansible para siempre. Una solución simple es ejecutar visudo en el host de destino y asegurarse de que el usuario que Ansible usará para iniciar sesión no tenga que escribir una contraseña"

  • artículo "Libros de Juego Ansibles Básicos", que dice

    "Ansible podría iniciar sesión en el servidor de destino como root y evitar la necesidad de sudo, o permitir que el usuario de ansible tenga sudo sin contraseña, pero la idea de hacerlo hace que mi bazo amenace con saltar mi garganta y bloquear mi tráquea, así que no

    ¿Mis pensamientos exactamente, pero luego cómo extenderse más allá de un solo servidor?

  • problema ansible # 1227, "Ansible debe solicitar la contraseña de sudo para todos los usuarios en un libro de jugadas", que fue cerrado hace un año por mpdehaan con el comentario "No he visto mucha demanda de esto, creo que la mayoría de las personas se están sudolando desde una sola cuenta de usuario o usando Teclas la mayor parte del tiempo ".

Entonces ... ¿cómo están usando Ansible las personas en situaciones como estas? Ajuste NOPASSWD en /etc/sudoersReutilizar la contraseña en los hosts o habilitar el inicio de sesión de SSH de la raíz de la red parece una reducción drástica en la seguridad.


97
2017-12-09 11:49


origen


¿Hay alguna razón por la que no esté utilizando las claves SSH? - Trondh
Ya estoy usando claves SSH; no afectan sudo (que aún debe requerir una contraseña). - supervacuo
Es posible que esto no sea exactamente lo que está buscando, pero en los cuadros de Ubuntu todavía utilizo claves, es decir, poner mi clave pública en / root / authorized_keys para ingresar directamente como root. El inconveniente obvio es permitir inicios de sesión de raíz sobre ssh ... También deshabilito los inicios de sesión de contraseña sobre ssh y ejecuto fail2ban para mayor seguridad. - senorsmile
@senorsmile gracias por la respuesta! ¿Te importaría convertirlo en una respuesta para que te rechace por no leer la pregunta? - supervacuo
es decir la ansible_ssh_password la configuración solo se aplica a la contraseña SSH (la clave está en el nombre ...). Y ya estoy usando el inicio de sesión SSH basado en clave. - supervacuo


Respuestas:


Ciertamente has hecho tu investigación ...

De toda mi experiencia con ansible lo que estás buscando lograr, no está respaldado. Como mencionó, ansible declara que no requiere sudo sin contraseña, y usted tiene razón, no es así. Pero todavía no he visto ningún método para usar contraseñas de sudo múltiples dentro de ansible, sin, por supuesto, ejecutar configuraciones múltiples.

Por lo tanto, no puedo ofrecerle la solución exacta que está buscando, pero sí preguntó ...

"Entonces ... ¿cómo están utilizando Ansible las personas en situaciones como éstas?   NOPASSWD en / etc / sudoers, reutilizando contraseñas en hosts o habilitando   el inicio de sesión de SSH de la raíz parece una reducción bastante drástica de la seguridad ".

Te puedo dar una opinión sobre eso. Mi caso de uso es de 1k nodos en múltiples centros de datos que brindan soporte a una firma global de SaaS en la que tengo que diseñar / implementar algunos controles de seguridad increíblemente estrictos debido a la naturaleza de nuestro negocio. La seguridad es siempre un acto de equilibrio, más facilidad de uso menos seguridad, este proceso no es diferente si está ejecutando 10 servidores o 1,000 o 100,000.

Es absolutamente correcto no utilizar los inicios de sesión de root a través de la contraseña o las claves ssh. De hecho, el inicio de sesión de raíz se debe desactivar por completo si los servidores tienen un cable de red conectado.

Hablemos sobre la reutilización de contraseñas, en una gran empresa, ¿es razonable pedir a los administradores de sistemas que tengan contraseñas diferentes en cada nodo? para un par de nodos, tal vez, pero mis administradores / ingenieros se amotinarían si tuvieran que tener contraseñas diferentes en 1000 nodos. Implementar eso también sería casi imposible, cada usuario tendría que almacenar sus propias contraseñas en algún lugar, ojalá un keypass, no una hoja de cálculo. Y cada vez que coloca una contraseña en un lugar donde se puede extraer en texto sin formato, ha disminuido considerablemente su seguridad. Preferiría que ellos supieran, de memoria, una o dos contraseñas realmente sólidas que tener que consultar un archivo de Keypass cada vez que necesitaban iniciar sesión o invocar sudo en una máquina.

Por lo tanto, la reutilización de la contraseña y la estandarización son algo completamente aceptable y estándar incluso en un entorno seguro. De lo contrario, no es necesario que existan ldap, keystone y otros servicios de directorio.

Cuando nos movemos a usuarios automáticos, las teclas ssh funcionan muy bien para que ingreses, pero aún necesitas pasar por sudo. Sus opciones son una contraseña estandarizada para el usuario automatizado (que es aceptable en muchos casos) o para habilitar NOPASSWD como lo ha señalado. La mayoría de los usuarios automatizados solo ejecutan unos pocos comandos, por lo que es bastante posible y ciertamente deseable habilitar NOPASSWD, pero solo para comandos aprobados previamente. Yo sugeriría usar su administración de configuración (ansible en este caso) para administrar su archivo sudoers para que pueda actualizar fácilmente la lista de comandos sin contraseña.

Ahora, hay algunos pasos que puede seguir una vez que comience a escalar para aislar aún más el riesgo. Si bien tenemos 1000 o más nodos, no todos ellos son servidores de 'producción', algunos son entornos de prueba, etc. No todos los administradores pueden acceder a los servidores de producción, aquellos que pueden usar su misma clave de usuario / contraseña SSO como lo harían en cualquier otro lugar . Pero los usuarios automatizados son un poco más seguros, por ejemplo, una herramienta automatizada a la que pueden acceder los administradores que no pertenecen a la producción tiene un usuario y credenciales que no se pueden usar en la producción. Si desea iniciar ansible en todos los nodos, tendrá que hacerlo en dos lotes, una para la no producción y otra para la producción.

Sin embargo, también utilizamos Puppet, ya que es una herramienta de gestión de la configuración, por lo que la mayoría de los cambios en todos los entornos se eliminarán a través de ella.

Obviamente, si la solicitud de característica que citó se vuelve a abrir / completar, lo que está buscando hacer sería totalmente compatible. Aun así, sin embargo, la seguridad es un proceso de evaluación de riesgos y compromiso. Si solo tiene unos pocos nodos para los que puede recordar las contraseñas sin tener que recurrir a una nota post-it, las contraseñas separadas serían un poco más seguras. Pero para la mayoría de nosotros, no es una opción viable.


52
2017-12-30 16:53



Gracias, @Zeb: había imaginado que los usuarios con docenas a miles de servidores utilizarían NOPASSWD de todos modos, por razones de cordura (probablemente respaldadas por reglas de firewall más estrictas etc.), pero es bueno leer su caso de uso y sus pensamientos sobre el modelo de amenaza. - supervacuo
Un comentario, sin embargo, sobre su sugerencia sobre restringir a "preaprobado" sudo comandos (que se me ocurrió cuando descubrí que NOPASSWD es bastante requerido). Desafortunadamente, esto parece completamente sin soporte también - ansible no hace promesas acerca de llamar p.ej.  chown o mkdir binarios directamente, y necesita ser capaz de sudo /bin/sh para la mayoría de los módulos para trabajar. - supervacuo
Me parece recordar que uno de mis ingenieros se quejó de eso hace un tiempo, eso es molesto. - Zeb


A partir de Ansible 1.5, es posible utilizar un bóveda encriptada para host_vars y otras variables. Esto al menos le permite almacenar un host (o por grupo) ansible_sudo_passvariable de forma segura. Desafortunadamente, --ask-vault-pass solo solicitará una contraseña de bóveda única por cada invocación, por lo que aún estará limitado a una contraseña de bóveda única para todos los hosts que usarán juntos.

Sin embargo, para algunos usos, esto puede ser una mejora con respecto a tener una única contraseña de sudo en múltiples hosts, ya que un atacante sin acceso a sus host_vars cifrados todavía necesitaría una contraseña de sudo por separado para cada máquina (o grupo de máquinas) que él o ella ataque.


36
2018-05-10 20:32



los ansible_sudo_pass La opción también parece nueva, y parece hacer lo que estaba pidiendo. Una contraseña de bóveda única es ideal para mis propósitos, también. ¡Gracias! - supervacuo
¿Hay alguna forma de evitar el cifrado? todos  host_vars utilizando este método? (una limitación potencial señalada por Alex Dupuy) - supervacuo
@supervacuo: para evitar encriptar todas las vars del host, solo use un directorio var del host que contenga main.yml (sin cifrar) y secret.yml (encriptado) - vea la última parte de esta sección doc donde se habla del grupo "raleigh": la misma técnica funciona para las variables host y las variables group. Lo uso mucho, la única variación es que si solo se necesita un secreto para algunos playbooks, puede ser útil almacenarlo en un árbol diferente por completo e incluirlo a través de una ruta que incluya el nombre de host o var. - RichVel
Si he cifrado el valor 'ansible_ssh_pass' en la bóveda, ¿también necesito duplicar el valor 'ansible_sudo_pass'? ¿Hay alguna manera de que el segundo valor sudo_pass refine el primer valor 'ssh_pass'? - emeraldjava


Con Ansible 1.5, es posible configurar el ansible_sudo_pass variable usando lookup('password', …):

ansible_sudo_pass: "{{ lookup('password', 'passwords/' + inventory_hostname) }}"

Encuentro esto más conveniente que usar archivos en host_vars/ por varias razones:

  • En realidad uso with_password: "passwords/{{ inventory_hostname}} encrypt=sha256_crypt" para proporcionar las contraseñas para el desplegar usuario remoto (que luego es necesario para sudo) Así que ya están presentes en los archivos. (Aunque hacer estas búsquedas de texto simple pierde el valor de sal almacenado en el archivo cuando se genera el valor hash).

  • Esto mantiene solo las contraseñas en el archivo (no ansible_sudo_pass: texto simple conocido) para un aumento de epsilon en la seguridad criptográfica. Más importante aún, significa que no está cifrando todas las demás variables específicas del host, para que puedan leerse sin la contraseña de la bóveda.

  • Al colocar las contraseñas en un directorio separado, es más fácil mantener los archivos fuera del control de origen o utilizar una herramienta como git-cripta para almacenarlos en forma cifrada (puede usar esto con Ansible anterior que carece de la función de bóveda). Utilizo git-crypt y, como solo compruebo el repositorio descifrado en sistemas de archivos encriptados, no me molesto con la bóveda y, por lo tanto, no necesito escribir una contraseña de bóveda. (Usar ambos sería por supuesto más seguro).

También puedes usar el buscar funcionar con ansible_ssh_pass; esto puede incluso ser posible con versiones anteriores de Ansible que no tienen ansible_sudo_pass.


22
2018-05-26 19:33



yo finalmente Intenté esto (¡gracias!), pero no puedo ver cómo funcionaría sin él. git-crypt; por lo que puedo ver. Parece ansible aún no tiene soporte Para usar lookup en una bóveda encriptada. los password módulo de documentos digamos que hay un soporte aún no documentado para el almacenamiento encriptado, pero todavía tengo que encontrar detalles. ¿Alguna pista? - supervacuo


Utilizando pasar es un método simple para proporcionar ansible con contraseñas de sudo. pass almacena una contraseña por archivo, lo que facilita compartir las contraseñas a través de git u otros métodos. También es seguro (usando GnuPG) y si está utilizando gpg-agent, le permite usar ansible sin ingresar una contraseña en cada uso.

Para proporcionar la contraseña almacenada como servers/foo para servidor foo Para ansible, úsalo en un archivo de inventario como este:

[servers]
foo ansible_sudo=True \
    ansible_sudo_pass="{{ lookup('pipe', 'pass servers/foo') }}"

Dado que desbloqueaste la clave para gpg-agent anteriormente, esto se ejecutará ansible sin la necesidad de ingresar ninguna contraseña.


17
2018-01-19 19:51



Una solución tan excelente, gracias! - Leng


Este es un hilo bastante viejo, sin embargo:

  • Utilizamos dos sistemas de autenticación diferentes, la gestión de las máquinas se realiza desde las estaciones de trabajo locales en mi equipo.
  • Escribí un vars_plugin para Ansible (una implementación bastante completa se puede encontrar en https://gist.github.com/mfriedenhagen/e488235d732b7becda81) que diferencia varios sistemas de autenticación:
  • El nombre del sistema de autenticación es específico del grupo.
  • El usuario de login / sudo utilizado es específico del grupo y del administrador
  • Así que extraigo al usuario del entorno del administrador y la contraseña correspondiente a través de la biblioteca python-keyring desde una contraseña segura (usamos el llavero de Mac OS X, pero también se admite desde la documentación Kwallet Gnome y _win_crypto).
  • Establecí los permisos de las contraseñas en el llavero de Mac OS X para notificarme sobre el hecho de que la seguridad del programa de la línea de comandos solicita acceso a una contraseña para cada sistema de autenticación utilizado por los hosts, así que ejecuto "ansible -s all -m ping" y recibo dos indicaciones (una para cada sistema de autenticación) donde presiono la barra espaciadora y ansible recoge las contraseñas.

3
2018-03-03 17:33



Esto se ve muy claro, gracias. Me gusta la idea de no tener que almacenar contraseñas en dos lugares. En este momento estoy atascado con KeepassX (porque el llavero de GNOME no parece muy portátil) pero quizás pueda hacer python-keepass ¿trabajo? - supervacuo
Según tengo entendido, python-keyring es una abstracción para esto, por lo que sus colegas pueden usar otros sistemas operativos. ¿O guarda su keepassx db en un dispositivo USB y tiene que administrar desde estaciones de trabajo con diferentes sistemas operativos? - Mirko Friedenhagen
entendido; Quise decir que ya tengo que usar KeepassX para tener acceso a contraseñas en sistemas que no son de GNOME, por lo que almacenarlas en gnome-keyring significaría mantener registros duplicados. Aún así es mejor que usar NOPASSWD, aunque… - supervacuo


Una posible forma de hacerlo es utilizando variables ambientales.

p.ej.

pass1=foo pass2=bar ansible-playbook -i production servers.xml

Luego, en las jugadas, puedes buscar la contraseña de sudo usando:

lookup('env', 'pass1') 
lookup('env', 'pass2') 

0
2017-07-21 08:57