Problema
Usando a versão mais recente e estável do Ansible, tenho um problema estranho em que meu manual fica travado em um servidor durante "Gathering_Facts", mas funciona bem em outros servidores similares ao usar o Sudo. No servidor Ansible, eu executo como meu usuário (usuário NIS) e uso o sudo (como root) no servidor remoto para fazer alterações. Se eu remover o Sudo dessa configuração, tudo funcionará bem.
Configuração
Versões de software
- SO : RHEL 6.4
- Versão Ansible : ansible 1.8.2
- Versão Sudo :
Sudo versão 1.8.6p3 Sudoers policy plugin version 1.8.6p3 Sudoers versão gramatical do arquivo 42 Sudoers I / O plugin versão 1.8.6p3
- Versão SSH : OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 de março de 2010
Mapa do servidor
-------- User1 @ Server1: sudo -H -S -p (Trava em fatos de coleta) / Usuário1 @ Ansible ---- \ -------- User1 @ Server2: sudo -H -S -p (funciona bem)
Comercial
- Usuário1: usuário acessível ao NIS nos Servidores1 e Servidores2.
- root: usuário root local para cada servidor.
Configuração Ansible
Partes relevantes do meu 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
Aqui está um manual de teste simples para tocar em um arquivo vazio e removê-lo. Realmente, só estou querendo testar se consigo que o Ansible use corretamente o sudo no servidor remoto. Se o manual funcionar, estou em boa 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
Configuração do Sudo
/ etc / sudoers
Host_Alias SRV = Server1, Server2
User_Alias SUPPORT = User1, User2, User3
SUPPORT SRV=(root) ALL
Essa configuração do sudo funciona bem em ambos os servidores. Sem problemas com o próprio sudo.
Como eu corro tudo
Muito simples:
$ ansible-playbook test.yml Senha SSH: senha sudo [o padrão é senha SSH]: PLAY [Servidor1: Servidor2] ******************************************** ** FATOS DE RECOLHA ************************************************** *************** ok: [Server2] falhou: [Server1] => {"falhou": true, "analisou": false} Desculpe, tente novamente. [sudo via ansible, key = mxxiqyvztlfnbctwixzmgvhwfdarumtq] senha: sudo: 1 tentativa incorreta de senha TAREFA: [crie um arquivo vazio para testar a conectividade e o acesso ao sudo] **************** alterado: [Server2] NOTIFICADO: [limpo] ********************************************* **************** alterado: [Server2] PLAY RECAP ************************************************** ******************** para tentar novamente, use: --limit @ / home / User1 / test.retry Server1: ok = 0 alterado = 0 inacessível = 0 falhou = 1 Server2: ok = 3 alterado = 2 inacessível = 0 falhou = 0
Falha, independentemente de eu digitar explicitamente as senhas SSH / Sudo e implicitamente (deixando o sudo passar o padrão para SSH).
Logs de servidor remoto
Servidor1 (falha)
/ var / log / secure
31 de dezembro 15:21:10 Server1 sshd [27093]: Senha aceita para User1 da porta xxxx 51446 ssh2 31 de dezembro 15:21:10 Server1 sshd [27093]: pam_unix (sshd: session): sessão aberta para o usuário User1 por (uid = 0) 31 de dezembro 15:21:11 Server1 sshd [27095]: solicitação do subsistema para sftp 31 de dezembro 15:21:11 Server1 sudo: pam_unix (sudo: auth): falha de autenticação; logname = Usuário1 uid = 187 euid = 0 tty = / dev / pts / 1 ruser = Usuário1 rhost = usuário = Usuário1 31 de dezembro 15:26:13 Server1 sudo: pam_unix (sudo: auth): falha na conversa 31 de dezembro 15:26:13 Server1 sudo: pam_unix (sudo: auth): auth não pôde identificar a senha para [User1] 31 de dezembro 15:26:13 Server1 sudo: User1: 1 tentativa de senha incorreta; TTY = pts / 1; PWD = / home / Usuário1; USUÁRIO = raiz; 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 dezembro 15:26:13 Server1 sshd [27093]: pam_unix (sshd: session): sessão fechada para o usuário User1
Server2 (funciona bem)
/ var / log / secure
31 de dezembro 15:21:12 Server2 sshd [31447]: senha aceita para User1 da porta xxxx 60346 ssh2 31 de dezembro 15:21:12 Server2 sshd [31447]: pam_unix (sshd: session): sessão aberta para o usuário User1 por (uid = 0) 31 de dezembro 15:21:12 Server2 sshd [31449]: solicitação do subsistema para sftp 31 de dezembro 15:21:12 Server2 sudo: Usuário1: TTY = pts / 2; PWD = / home / Usuário1; USUÁRIO = raiz; 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 dezembro 15:21:14 Server2 sshd [31447]: pam_unix (sshd: session): sessão fechada para o usuário User1
Saída STrace
Aqui está a saída do strace ao direcionar o comando ansible do usuário root. Comando:
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`
Servidor1
23650 select (0, NULL, NULL, NULL, {1, 508055}) = 0 (Tempo limite) Soquete 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 Pesquisa 23650 ([{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 fechar (10) = 0 23650 write (2, "Desculpe, tente novamente. \ N", 18) = 18 23650 gettimeofday ({1420050850, 238344}, NULL) = 0 Soquete 23650 (PF_FILE, SOCK_STREAM, 0) = 10 23650 connect (10, {sa_family = AF_FILE, caminho = "/ var / run / dbus / system_bus_socket"}, 33) = 0
Servidor2
6625 select (8, [5 7], [], NULL, NULL) =? ERESTARTNOHAND (a ser reiniciado) 6625 --- SIGCHLD (saída da criança) @ 0 (0) --- 6625 gravação (8, "\ 21", 1) = 1 6625 rt_sigreturn (0x8) = -1 EINTR (chamada do sistema interrompida) 6625 selecione (8, [5 7], [], NULL, NULL) = 1 (em [7]) 6625 leitura (7, "\ 21", 1) = 1 6625 wait4 (6636, [{WIFEXITED (s) && WEXITSTATUS (s) == 0}], WNOHANG | WSTOPPED, NULL) = 6636 6625 rt_sigprocmask (SIG_BLOCK, NULL, [], 8) = 0 Soquete 6625 (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 Pesquisa 6625 ([{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 fechar (6) = 0 6625 open ("/ 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_sblue = 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 é a configuração fi" ..., 4096) = 2980 6625 lido (6, "", 4096) = 0 6625 fechar (6) = 0 6625 munmap (0x7fbc3a59a000, 4096) = 0 6625 aberto ("/ etc / environment", O_RDONLY) = 6
Meu palpite
O Server1 não está recebendo a senha corretamente ou está solicitando / aguardando incorretamente uma senha. Isso não parece um problema do Sudo ou do Ansible (sozinhos, ambos funcionam muito bem), mas o Server1 parece não receber as credenciais (ou aderir a elas) de maneira semelhante ao Server2. Os servidores 1 e 2 servem a propósitos diferentes; portanto, é possível que eles tenham algumas diferenças de autenticação ou versão de pacote, mas ambos foram criados a partir do mesmo repositório; portanto, eles não devem ser tão diferentes.
Autenticação PAM
Eu pensei que talvez os sistemas tivessem configurações diferentes de PAM, fazendo com que as senhas fossem tratadas de maneira um pouco diferente. Comparei os arquivos /etc/pam.d/ (usando md5sum [file]
) e eles são os mesmos entre os dois sistemas.
Testes
Sudo STDIN
Testou outro problema em que o sudo não lia uma senha do STDIN, mas funcionava bem nos dois servidores.
Teste Sudo Ad-Hoc
-bash-4.1 $ ansible Server1 -m arquivo -a "dest = / tmp / ansible_test.txt state = touch" -sK Senha SSH: senha sudo [o padrão é senha SSH]: Servidor1 | sucesso >> { "alterado": verdadeiro, "dest": "/tmp/ansible_test.txt", "gid": 0, "group": "root", "mode": "0644", "proprietário": "raiz", "tamanho": 0, "state": "file", "uid": 0 }
Sucesso! Mas por que?!
TL; DR
- O Servidor1 parece estar aguardando o prompt da senha do sudo, enquanto o Servidor2 é executado corretamente.
- A execução de
ansible
"ad-hoc" no Server1 funciona bem. A execução como um manual falha.
Questões)
- O que poderia fazer com que minha configuração do Ansible Sudo funcionasse bem em um servidor e fosse rejeitada em outro?
- O Ansible executa a senha "passar" da máquina local para a remota de maneira diferente quando executa ad-hoc versus playbook? Eu assumi que eles seriam os mesmos.
Eu estou pensando que isso está chegando perto de simplesmente enviar um relatório de bug para a página do GitHub apenas pelo fato de o acesso ao sudo ter resultados diferentes, dependendo se eu estiver executando ad-hoc ou não.
Usando o @lulian como ponto de apoio nesta resposta, o problema se reduziu a um invasor
ansible_sudo_pass:
definido nos group_vars que estava substituindo a senha digitada--ask-sudo-pass
.Usando o seguinte:
Consegui descobrir que
write(4, "{{ password }}\n", 15)
estava sendo passado em vez da senha digitada. Após algumas pesquisas rápidas, encontreiansible_sudo_pass
definido nos meus group_vars que estavam substituindo minha senha digitada.Como um FYI para todos os outros, a
ansible_sudo_pass:
definição parece ter precedência sobre a--ask-sudo-pass
qual, a princípio, parecia contra-intuitiva. No final, esse é um erro do usuário, mas a metodologia da @ lulian em depurar a interação SSH, bem como a descoberta de relacionamentos entreansible_sudo_pass
e--ask-sudo-pass
deve ser muito útil para outras pessoas por aí. (Esperançosamente!)fonte
-e
e você pode contornar isso passando uma opção apropriada com-e
.