¿Cómo hacer que Ansible use una contraseña si la clave fue rechazada?

14

Mis nuevas instancias de servidor están configuradas para iniciar sesión en root a través de ssh con contraseña. Quiero que mi libro de jugadas de Ansible lo reconfigure para que use claves en su lugar y desactive el inicio de sesión raíz con contraseña en la primera ejecución, por lo que necesito algo como esto:

  • intenta iniciar sesión con la clave
  • si no puede iniciar sesión con la clave:

    • iniciar sesión con contraseña
    • añadir clave a claves_autorizadas
    • deshabilitar el inicio de sesión raíz con contraseña
    • opcionalmente reconectarse usando la llave
  • hacer otras tareas

¿Cómo puedo lograr eso?

EDITAR : Para ser claros, no estoy preguntando cómo agregar una clave o deshabilitar la raíz, eso es solo por contexto. Estoy preguntando cómo recurrir a la contraseña si no se puede autenticar con la clave. Con --ask-passo ansible_ssh_passconfigurado, Ansible ni siquiera intentará usar la autenticación de clave pública

petr0
fuente
Buena pregunta, ¿qué has intentado hasta ahora?
Dawud
1
Llevé la configuración ssh a un libro de jugadas separado y la ejecuté con la opción -k, luego ejecuté el libro de jugadas principal sin -k (usando la clave del agente). Sin embargo, esperaba que se pueda envolver en un solo libro de jugadas ...
petr0
@ petr0 Esto funciona para mí cuando la contraseña de solicitud de acceso es para un usuario diferente a la clave (es decir, cuando cambia de usuario remoto después de deshabilitar ssh con contraseña). No estoy seguro si eso ayuda.
DylanYoung

Respuestas:

6

Puede probar la PreferredAuthenticationsopción, configurándola en publickey,password. El valor predeterminado incluye estos en este orden, junto con otras opciones, por lo que ansible presumiblemente está configurando esto. Agregarlo a través de -oo el cliente ssh_configpuede evitar esto.

Es posible que pueda usar un script de envoltura. Por ejemplo, con esto dentro key_or_password.shy otro pass.shque proporciona la contraseña, se ejecutará bash key_or_password.sh root@hostuna clave pública seguida de un inicio de sesión de contraseña no interactivo.

export DISPLAY=dummy:0
export SSH_ASKPASS=$PWD/pass.sh
exec setsid ssh -v -o 'PreferredAuthentications publickey,password' "$@"

El registro indica con qué método tuvo éxito, p. Ej.

debug1: Authentication succeeded (publickey).
eisd
fuente
7

Esto es lo que hago si ansible_useres diferente para la 'primera ejecución' del libro de jugadas (por ejemplo, si solo tiene un rootusuario y va a configurar un nuevo usuario con una clave SSH):

  • Guarde la contraseña ansible_passcomo lo haría si estuviera usando los inicios de sesión de contraseña (recuerde usar Vault), esta debería ser la contraseña del usuario que está usando para la 'primera ejecución' del libro de jugadas.
  • Establezca ansible_userel nombre de usuario del usuario que desea usar después de la primera ejecución cuando los usuarios estén configurados correctamente en el servidor.
  • Establezca una variable ansible_user_first_runpara el usuario que va a usar para la 'primera ejecución' del libro de jugadas, por ejemplo root.
  • Use un comando local para intentar conectarse al servidor con la clave SSH correcta, usando ignore_errorsychanged_when: False
  • Si eso falla, actualice ansible_userel valor deansible_user_first_run

Aquí está el código:

---
- name: Check if connection is possible
  command: ssh -o User={{ ansible_user }} -o ConnectTimeout=10 -o PreferredAuthentications=publickey -o PubkeyAuthentication=yes {{ inventory_hostname }} echo "Worked"
  register: result
  connection: local
  ignore_errors: yes
  changed_when: False
- name: If no connection, change user_name
  connection: local
  set_fact:
    ansible_user: "{{ ansible_user_first_run }}"
  when: result|failed

Nota: Vale la pena configurarlo transport = sshya que paramiko puede fallar inesperadamente al iniciar sesión en el servidor en algunas configuraciones (por ejemplo, cuando el servidor está configurado para no aceptar contraseñas, y está intentando primero con una clave y luego una contraseña ... ¡extraño!) También el transporte ssh es más rápido, por lo que vale la pena de todos modos.

Nota adicional: si está utilizando este método, debe especificar gather_facts: falseen su archivo de definición de libro de jugadas para que las tareas de configuración / recopilación de datos no se ejecuten automáticamente antes de llegar a la etapa de prueba de contraseñas. Si necesita alguno de los hechos ansibles, deberá llamar explícitamente setupa su rol antes de acceder a cualquiera de los datos normalmente disponibles en lugares como ansible_devices, etc. Una buena forma de hacerlo es llamar setupcon una whencláusula que verifique si el hecho de que está usando está vacío o no antes de llamarlo en su rol.

Tom Bull
fuente
Su solución es buena, pero debe agregar un gather_facts: nopara detener ansible el intentar conectarse al iniciar el libro de jugadas :)
k4cy
Estás en lo correcto. He recogido recolectar_factos en todos mis libros de jugadas, así que tengo que llamar explícitamente a 'configuración'. Olvidé mencionar esto en la respuesta, lo actualizaré ahora.
Tom Bull
5

Puedes usar --ask-pass cuando ejecutes ansible-playbook.

Para otras tareas que solicitó, se puede lograr por varios medios, por ejemplo, copiar el módulo.
La desactivación del inicio de sesión raíz también se puede hacer, p. creando plantillas sshd_confo insertando una línea en el archivo conf.

titus
fuente
--ask-pass (que es lo mismo que -k) es lo que estoy haciendo y escribí al respecto en el comentario anterior
petr0