Problema
Utilizando la última versión estable de Ansible, tengo un problema extraño en el que mi libro de jugadas se cuelga en un servidor durante "Gathering_Facts" pero funciona bien en otros servidores similares cuando uso Sudo. En el servidor Ansible, ejecuto como mi usuario (usuario NIS) y uso sudo (como root) en el servidor remoto para realizar cambios. Si elimino Sudo de esta configuración, todo funciona bien.
Preparar
Versiones de software
- OS : RHEL 6.4
- Versión ansible: ansible 1.8.2
- Versión de sudo :
Sudo versión 1.8.6p3 Complemento de políticas de Sudoers versión 1.8.6p3 Sudoers file grammar version 42 Sudoers I / O plugin versión 1.8.6p3
- Versión SSH : OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 de marzo de 2010
Mapa del servidor
-------- Usuario1 @ Servidor1: sudo -H -S -p (Se bloquea en Gathering_Facts) / / Usuario1 @ Ansible ---- \ -------- Usuario1 @ Servidor2: sudo -H -S -p (Funciona bien)
Los usuarios
- Usuario1: usuario accesible NIS en Servidor1 y Servidor2.
- root: usuario raíz local para cada servidor.
Configuración Ansible
Partes relevantes de mi ansible.cfg .
ansible.cfg
sudo = true
sudo_user = root
ask_sudo_pass = True
ask_pass = True
...
gathering = smart
....
# change this for alternative sudo implementations
sudo_exe = sudo
# what flags to pass to sudo
#sudo_flags = -H
...
# remote_user = ansible
Aquí hay un libro de jugadas de prueba simple para tocar un archivo vacío y luego eliminarlo. Realmente, solo quiero probar si puedo obtener Ansible para usar correctamente sudo en el servidor remoto. Si el libro de jugadas funciona, estoy en buena forma.
TEST.yml
---
- hosts: Server1:Server2
vars:
- test_file: '/tmp/ansible_test_file.txt'
sudo: yes
tasks:
- name: create empty file to test connectivity and sudo access
file: dest={{ test_file }}
state=touch
owner=root group=root mode=0600
notify:
- clean
handlers:
- name: clean
file: dest={{ test_file }}
state=absent
Configuración de sudo
/ etc / sudoers
Host_Alias SRV = Server1, Server2
User_Alias SUPPORT = User1, User2, User3
SUPPORT SRV=(root) ALL
Esta configuración de sudo funciona bien en AMBOS servidores. No hay problemas con sudo en sí.
Cómo lo ejecuto todo
Muy simple:
$ ansible-playbook test.yml Contraseña SSH: contraseña de sudo [predeterminada a la contraseña SSH]: PLAY [Servidor1: Servidor2] ******************************************** ** ** HECHOS DE REUNIÓN ************************************************ *************** ok: [Servidor2] error: [Servidor1] => {"error": verdadero, "analizado": falso} Perdón intente de nuevo. [sudo via ansible, clave = mxxiqyvztlfnbctwixzmgvhwfdarumtq] contraseña: sudo: 1 intento de contraseña incorrecta TAREA: [cree un archivo vacío para probar la conectividad y el acceso a sudo] **************** cambiado: [Servidor2] NOTIFICADO: [limpio] ********************************************* **************** cambiado: [Servidor2] PLAY RECAP ************************************************ ******************** para volver a intentar, use: --limit @ / home / User1 / test.retry Servidor1: ok = 0 cambiado = 0 inalcanzable = 0 fallido = 1 Servidor2: ok = 3 cambiado = 2 inalcanzable = 0 fallido = 0
Falla independientemente de si ingreso explícitamente tanto las contraseñas SSH / Sudo como implícitamente (dejando que sudo pase por defecto a SSH).
Registros remotos del servidor
Servidor1 (falla)
/ var / log / secure
31 de diciembre 15:21:10 Servidor1 sshd [27093]: Contraseña aceptada para Usuario1 del puerto xxxx 51446 ssh2 31 de diciembre 15:21:10 Servidor1 sshd [27093]: pam_unix (sshd: sesión): sesión abierta para el usuario Usuario1 por (uid = 0) 31 de diciembre 15:21:11 Servidor1 sshd [27095]: solicitud del subsistema para sftp 31 de diciembre 15:21:11 Servidor1 sudo: pam_unix (sudo: auth): error de autenticación; logname = Usuario1 uid = 187 euid = 0 tty = / dev / pts / 1 ruser = Usuario1 rhost = usuario = Usuario1 31 de diciembre 15:26:13 Server1 sudo: pam_unix (sudo: auth): conversación fallida 31 de diciembre 15:26:13 Servidor1 sudo: pam_unix (sudo: auth): auth no pudo identificar la contraseña para [Usuario1] 31 de diciembre 15:26:13 Sudo servidor1: Usuario1: 1 intento de contraseña incorrecta; TTY = pts / 1; PWD = / inicio / Usuario1; USUARIO = raíz; COMANDO = / bin / sh -c echo SUDO-SUCCESS-mxxiqyvztlfnbctwixzmgvhwfdarumtq; LANG = C LC_CTYPE = C / usr / bin / python /tmp/.ansible/tmp/ansible-tmp-1420039272.66-164754043073536/setup; rm -rf /tmp/.ansible/tmp/ansible-tmp-1420039272.66-164754043073536/> / dev / null 2> & 1 31 de diciembre 15:26:13 Servidor1 sshd [27093]: pam_unix (sshd: sesión): sesión cerrada para el usuario Usuario1
Servidor2 (funciona bien)
/ var / log / secure
31 de diciembre 15:21:12 Servidor2 sshd [31447]: Contraseña aceptada para Usuario1 desde el puerto xxxx 60346 ssh2 31 de diciembre 15:21:12 Servidor2 sshd [31447]: pam_unix (sshd: sesión): sesión abierta para el usuario Usuario1 por (uid = 0) 31 de diciembre 15:21:12 Server2 sshd [31449]: solicitud del subsistema para sftp 31 de diciembre 15:21:12 sudo Servidor2: Usuario1: TTY = pts / 2; PWD = / inicio / Usuario1; USUARIO = raíz; COMANDO = / bin / sh -c echo SUDO-SUCCESS-vjaypzeocvrdlqalxflgcrcoezhnbibs; LANG = C LC_CTYPE = C / usr / bin / python /tmp/.ansible/tmp/ansible-tmp-1420039272.68-243930711246149/setup; rm -rf /tmp/.ansible/tmp/ansible-tmp-1420039272.68-243930711246149/> / dev / null 2> & 1 31 de diciembre 15:21:14 Servidor2 sshd [31447]: pam_unix (sshd: sesión): sesión cerrada para el usuario Usuario1
Salida de almacenamiento
Aquí está la salida de strace cuando se dirige al comando ansible del usuario raíz. Mando:
while [[ -z $(ps -fu root|grep [a]nsible|awk '{print $2}') ]]; do
continue
done
strace -vfp $(ps -fu root|grep [a]nsible|awk '{print $2}') -o /root/strace.out`
Servidor 1
23650 select (0, NULL, NULL, NULL, {1, 508055}) = 0 (Tiempo de espera) Conector 23650 (PF_NETLINK, SOCK_RAW, 9) = 10 23650 fcntl (10, F_SETFD, FD_CLOEXEC) = 0 23650 readlink ("/ proc / self / exe", "/ usr / bin / sudo", 4096) = 13 23650 sendto (10, "| \ 0 \ 0 \ 0L \ 4 \ 5 \ 0 \ 1 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0op = PAM: auténtico" ..., 124, 0, {sa_family = AF_NETLINK, pid = 0, grupos = 00000000}, 12) = 124 23650 encuesta ([{fd = 10, eventos = POLLIN}], 1, 500) = 1 ([{fd = 10, revents = POLLIN}]) 23650 recvfrom (10, "$ \ 0 \ 0 \ 0 \ 2 \ 0 \ 0 \ 0 \ 1 \ 0 \ 0 \ 0b \\\ 0 \ 0 \ 0 \ 0 \ 0 \ 0 | \ 0 \ 0 \ 0L \ 4 \ 5 \ 0 \ 1 \ 0 \ 0 \ 0 "..., 8988, MSG_PEEK | MSG_DONTWAIT, {sa_family = AF_NETLINK, pid = 0, grupos = 00000000}, [12]) = 36 23650 recvfrom (10, "$ \ 0 \ 0 \ 0 \ 2 \ 0 \ 0 \ 0 \ 1 \ 0 \ 0 \ 0b \\\ 0 \ 0 \ 0 \ 0 \ 0 \ 0 | \ 0 \ 0 \ 0L \ 4 \ 5 \ 0 \ 1 \ 0 \ 0 \ 0 "..., 8988, MSG_DONTWAIT, {sa_family = AF_NETLINK, pid = 0, grupos = 00000000}, [12]) = 36 23650 cerrar (10) = 0 23650 escribir (2, "Lo siento, inténtalo de nuevo. \ N", 18) = 18 23650 gettimeofday ({1420050850, 238344}, NULL) = 0 Conector 23650 (PF_FILE, SOCK_STREAM, 0) = 10 23650 connect (10, {sa_family = AF_FILE, ruta = "/ var / run / dbus / system_bus_socket"}, 33) = 0
Servidor2
6625 select (8, [5 7], [], NULL, NULL) =? ERESTARTNOHAND (Para reiniciar) 6625 --- SIGCHLD (Niño salido) @ 0 (0) --- 6625 escritura (8, "\ 21", 1) = 1 6625 rt_sigreturn (0x8) = -1 EINTR (llamada de sistema interrumpida) 6625 select (8, [5 7], [], NULL, NULL) = 1 (en [7]) 6625 lectura (7, "\ 21", 1) = 1 6625 wait4 (6636, [{WIFEXITED (s) && WEXITSTATUS (s) == 0}], WNOHANG | WSTOPPED, NULL) = 6636 6625 rt_sigprocmask (SIG_BLOCK, NULL, [], 8) = 0 6625 socket (PF_NETLINK, SOCK_RAW, 9) = 6 6625 fcntl (6, F_SETFD, FD_CLOEXEC) = 0 6625 readlink ("/ proc / self / exe", "/ usr / bin / sudo", 4096) = 13 6625 sendto (6, "x \ 0 \ 0 \ 0R \ 4 \ 5 \ 0 \ 6 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0 \ 0op = PAM: session_c" ..., 120, 0, {sa_family = AF_NETLINK, pid = 0, grupos = 00000000}, 12) = 120 6625 encuesta ([{fd = 6, eventos = POLLIN}], 1, 500) = 1 ([{fd = 6, revents = POLLIN}]) 6625 recvfrom (6, "$ \ 0 \ 0 \ 0 \ 2 \ 0 \ 0 \ 0 \ 6 \ 0 \ 0 \ 0 \ 330 \ 355 \ 377 \ 377 \ 0 \ 0 \ 0 \ 0x \ 0 \ 0 \ 0R \ 4 \ 5 \ 0 \ 6 \ 0 \ 0 \ 0 "..., 8988, MSG_PEEK | MSG_DONTWAIT, {sa_family = AF_NETLINK, pid = 0, grupos = 00000000}, [12]) = 36 6625 recvfrom (6, "$ \ 0 \ 0 \ 0 \ 2 \ 0 \ 0 \ 0 \ 6 \ 0 \ 0 \ 0 \ 330 \ 355 \ 377 \ 377 \ 0 \ 0 \ 0 \ 0x \ 0 \ 0 \ 0R \ 4 \ 5 \ 0 \ 6 \ 0 \ 0 \ 0 "..., 8988, MSG_DONTWAIT, {sa_family = AF_NETLINK, pid = 0, grupos = 00000000}, [12]) = 36 6625 cerrar (6) = 0 6625 abierto ("/ etc / security / pam_env.conf", O_RDONLY) = 6 6625 fstat (6, {st_dev = makedev (253, 1), st_ino = 521434, st_mode = S_IFREG | 0644, st_nlink = 1, st_uid = 0, st_gid = 0, st_blksize = 4096, st_blocks = 8, st_size = 2980, st_atime = 2014/12 / 31-16: 10: 01, st_mtime = 2012/10 / 15-08: 23: 52, st_ctime = 2014/06 / 16-15: 45: 35}) = 0 6625 mmap (NULL, 4096, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) = 0x7fbc3a59a000 6625 read (6, "# \ n # Esta es la configuración fi" ..., 4096) = 2980 6625 lectura (6, "", 4096) = 0 6625 cerrar (6) = 0 6625 munmap (0x7fbc3a59a000, 4096) = 0 6625 abierto ("/ etc / environment", O_RDONLY) = 6
Mi conjetura
El Servidor1 no está obteniendo la contraseña correctamente o está pidiendo / esperando incorrectamente una contraseña. Esto no parece un problema de Sudo o Ansible (solo, ambos funcionan bien), pero el Servidor1 no parece recibir las credenciales (o adherirse a ellas) de manera similar a Servidor2. Los servidores 1 y 2 tienen diferentes propósitos, por lo que es posible que tengan algunas diferencias de autenticación o de versión del paquete, pero ambos se crearon desde el mismo repositorio; por lo tanto, no deberían ser tan diferentes.
Autenticación PAM
Pensé que tal vez los sistemas tenían diferentes configuraciones de PAM, lo que hacía que las contraseñas se manejaran de manera un poco diferente. Comparé los archivos /etc/pam.d/ (usando md5sum [file]
), y son los mismos entre los dos sistemas.
Pruebas
Sudo STDIN
Probé otro problema en el que sudo no leía una contraseña de STDIN, pero funcionaba bien en ambos servidores.
Prueba Sudo Ad-Hoc
-bash-4.1 $ ansible Server1 -m archivo -a "dest = / tmp / ansible_test.txt state = touch" -sK Contraseña SSH: contraseña de sudo [predeterminada a la contraseña SSH]: Servidor1 | éxito >> { "cambiado": verdadero, "dest": "/tmp/ansible_test.txt", "gid": 0, "group": "root", "modo": "0644", "propietario": "raíz", "tamaño": 0, "estado": "archivo", "uid": 0 }
¡Éxito! ¡¿Pero por qué?!
TL; DR
- El Servidor1 parece estar esperando la solicitud de contraseña de sudo mientras el Servidor2 funciona bien.
- Ejecutar
ansible
"ad-hoc" en el Servidor1 funciona bien. Ejecutarlo como un libro de jugadas falla.
Pregunta (s)
- ¿Qué podría causar que mi configuración de Ansible Sudo funcione bien en un servidor y sea rechazada en otro?
- ¿Ansible realiza la contraseña "pasar" de máquina local a remota de manera diferente cuando se ejecuta ad-hoc versus playbook? Asumí que serían lo mismo.
Estoy pensando que esto se está acercando a simplemente enviar un informe de error a la página de GitHub simplemente por el hecho de que el acceso a sudo tiene diferentes resultados dependiendo de si estoy ejecutando ad-hoc o no.
Usando @lulian como punto de apoyo en esta respuesta, el problema se redujo a un pícaro
ansible_sudo_pass:
definido en group_vars que anulaba la contraseña ingresada--ask-sudo-pass
.Usando lo siguiente:
Pude encontrar que
write(4, "{{ password }}\n", 15)
se estaba pasando en lugar de la contraseña ingresada. Después de una búsqueda rápida, de hecho encontréansible_sudo_pass
definido en mi group_vars que anulaba mi contraseña ingresada.Como un FYI para todos los demás, la
ansible_sudo_pass:
definición parece tener prioridad sobre lo--ask-sudo-pass
que, al principio, parecía contrario a la intuición. Al final, esto es un error del usuario, pero la metodología de @ lulian para depurar la interacción SSH, así como el descubrimiento de la relación entreansible_sudo_pass
y--ask-sudo-pass
debería ser muy útil para otros. (¡Ojalá!)fuente
-e
, y es posible que pueda evitar esto pasando una opción adecuada con-e
.