Problème
En utilisant la dernière version stable d'Ansible, j'ai un problème étrange où mon playbook se bloque sur un serveur pendant "Gathering_Facts" mais fonctionne correctement sur d'autres serveurs similaires lors de l'utilisation de Sudo. Sur le serveur Ansible, j'exécute en tant qu'utilisateur (utilisateur NIS) et j'utilise sudo (en tant que root) sur le serveur distant pour apporter des modifications. Si je supprime Sudo de cette configuration, tout fonctionne bien.
Installer
Versions logicielles
- OS : RHEL 6.4
- Version Ansible : ansible 1.8.2
- Version Sudo :
Sudo version 1.8.6p3 Plugin de politique Sudoers version 1.8.6p3 Sudoers file grammar version 42 Sudoers I / O plugin version 1.8.6p3
- Version SSH : OpenSSH_5.3p1, OpenSSL 1.0.0-fips 29 mars 2010
Carte du serveur
-------- User1 @ Server1: sudo -H -S -p (se bloque sur Gathering_Facts) / Utilisateur1 @ Ansible ---- \ -------- User1 @ Server2: sudo -H -S -p (fonctionne très bien)
Utilisateurs
- Utilisateur1: utilisateur accessible NIS sur Server1 et Server2.
- root: utilisateur root local pour chaque serveur.
Configuration ansible
Parties pertinentes de mon 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
Voici un playbook de test simple pour toucher un fichier vide puis le supprimer. Vraiment, je veux juste tester si je peux obtenir qu'Ansible utilise correctement sudo sur le serveur distant. Si le playbook fonctionne, je suis en bonne forme.
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
Configuration de Sudo
/ etc / sudoers
Host_Alias SRV = Server1, Server2
User_Alias SUPPORT = User1, User2, User3
SUPPORT SRV=(root) ALL
Cette configuration sudo fonctionne très bien sur les DEUX serveurs. Aucun problème avec sudo lui-même.
Comment je gère tout cela
Très simple:
$ ansible-playbook test.yml Mot de passe SSH: mot de passe sudo [par défaut le mot de passe SSH]: JOUER [Serveur1: Serveur2] ******************************************** ** RASSEMBLEMENT FAITS ************************************************ *************** ok: [Server2] a échoué: [Server1] => {"failed": true, "parsed": false} Désolé réessayez. [sudo via ansible, key = mxxiqyvztlfnbctwixzmgvhwfdarumtq] mot de passe: sudo: 1 tentative de mot de passe incorrect TÂCHE: [créer un fichier vide pour tester la connectivité et l'accès sudo] **************** modifié: [Server2] AVIS: [nettoyer] ********************************************* **************** modifié: [Server2] PLAY RECAP ************************************************ ******************** pour réessayer, utilisez: --limit @ / home / User1 / test.retry Server1: ok = 0 changé = 0 inaccessible = 0 a échoué = 1 Server2: ok = 3 changé = 2 inaccessible = 0 a échoué = 0
Échoue indépendamment du fait que j'entre explicitement les mots de passe SSH / Sudo ainsi qu'implicitement (en laissant sudo passer par défaut à SSH).
Journaux du serveur distant
Server1 (échoue)
/ var / log / secure
31 décembre 15:21:10 Server1 sshd [27093]: mot de passe accepté pour l'utilisateur1 à partir du port xxxx 51446 ssh2 31 décembre 15:21:10 Server1 sshd [27093]: pam_unix (sshd: session): session ouverte pour l'utilisateur User1 par (uid = 0) 31 décembre 15:21:11 Server1 sshd [27095]: demande de sous-système pour sftp 31 décembre 15:21:11 Server1 sudo: pam_unix (sudo: auth): échec d'authentification; logname = User1 uid = 187 euid = 0 tty = / dev / pts / 1 ruser = User1 rhost = user = User1 31 décembre 15:26:13 Server1 sudo: pam_unix (sudo: auth): la conversation a échoué 31 décembre 15:26:13 Sudo Server1: pam_unix (sudo: auth): l'auth n'a pas pu identifier le mot de passe pour [User1] 31 décembre 15:26:13 Sudo Server1: Utilisateur1: 1 tentative de mot de passe incorrect; ATS = pts / 1; PWD = / home / User1; USER = root; COMMAND = / 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 décembre 15:26:13 Server1 sshd [27093]: pam_unix (sshd: session): session fermée pour l'utilisateur User1
Server2 (fonctionne très bien)
/ var / log / secure
31 décembre 15:21:12 Server2 sshd [31447]: mot de passe accepté pour l'utilisateur 1 du port xxxx 60346 ssh2 31 décembre 15:21:12 Server2 sshd [31447]: pam_unix (sshd: session): session ouverte pour l'utilisateur User1 par (uid = 0) 31 décembre 15:21:12 Server2 sshd [31449]: demande de sous-système pour sftp 31 décembre 15:21:12 Sudo Server2: User1: TTY = pts / 2; PWD = / home / User1; USER = root; COMMAND = / 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 décembre 15:21:14 Server2 sshd [31447]: pam_unix (sshd: session): session fermée pour l'utilisateur User1
Sortie STrace
Voici la sortie de strace lors du ciblage de la commande ansible de l'utilisateur root. Commander:
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`
Server1
23650 select (0, NULL, NULL, NULL, {1, 508055}) = 0 (Timeout) Prise 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: authentique" ..., 124, 0, {sa_family = AF_NETLINK, pid = 0, groupes = 00000000}, 12) = 124 23650 sondage ([{fd = 10, events = 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, groups = 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, groups = 00000000}, [12]) = 36 23650 fermer (10) = 0 23650 écriture (2, "Désolé, réessayez. \ N", 18) = 18 23650 gettimeofday ({1420050850, 238344}, NULL) = 0 Prise 23650 (PF_FILE, SOCK_STREAM, 0) = 10 23650 connect (10, {sa_family = AF_FILE, path = "/ var / run / dbus / system_bus_socket"}, 33) = 0
Server2
6625 select (8, [5 7], [], NULL, NULL) =? ERESTARTNOHAND (À redémarrer) 6625 --- SIGCHLD (sortie de l'enfant) @ 0 (0) --- 6625 écriture (8, "\ 21", 1) = 1 6625 rt_sigreturn (0x8) = -1 EINTR (appel système interrompu) 6625 select (8, [5 7], [], NULL, NULL) = 1 (dans [7]) 6625 lu (7, "\ 21", 1) = 1 6625 wait4 (6636, [{WIFEXITED (s) && WEXITSTATUS (=) 0}], WNOHANG | WSTOPPED, NULL) = 6636 6625 rt_sigprocmask (SIG_BLOCK, NULL, [], 8) = 0 Prise 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, groupes = 00000000}, 12) = 120 6625 sondage ([{fd = 6, events = 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, groups = 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, groups = 00000000}, [12]) = 36 6625 fermer (6) = 0 6625 ouvert ("/ 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 # This is the configuration fi" ..., 4096) = 2980 6625 lu (6, "", 4096) = 0 6625 fermer (6) = 0 6625 munmap (0x7fbc3a59a000, 4096) = 0 6625 ouvert ("/ etc / environment", O_RDONLY) = 6
My Guess
Server1 n'obtient pas le mot de passe correctement ou demande / attend de manière incorrecte un mot de passe. Cela ne ressemble pas à un problème Sudo ou Ansible (seuls, ils fonctionnent tous les deux très bien), mais Server1 ne semble pas recevoir les informations d'identification (ou y adhérer) d'une manière similaire à Server2. Les serveurs 1 et 2 ont des objectifs différents, il est donc possible qu'ils présentent des différences d'authentification ou de version de package, mais ils ont tous deux été construits à partir du même référentiel; par conséquent, ils ne devraient pas être SI différents.
PAM Auth
Je pensais que les systèmes avaient peut-être différentes configurations PAM, ce qui entraînait un traitement différent des mots de passe. J'ai comparé les fichiers /etc/pam.d/ (en utilisant md5sum [file]
), et ils sont les mêmes entre les deux systèmes.
Les tests
Sudo STDIN
Test d' un autre problème où sudo ne lirait pas un mot de passe de STDIN, mais cela fonctionnait bien sur les deux serveurs.
Testez Sudo Ad-Hoc
-bash-4.1 $ ansible Server1 -m fichier -a "dest = / tmp / ansible_test.txt state = touch" -sK Mot de passe SSH: mot de passe sudo [par défaut le mot de passe SSH]: Server1 | succès >> { "changé": vrai, "dest": "/tmp/ansible_test.txt", "gid": 0, "groupe": "racine", "mode": "0644", "propriétaire": "root", "taille": 0, "état": "fichier", "uid": 0 }
Succès! Mais pourquoi?!
TL; DR
- Server1 semble attendre l'invite de mot de passe sudo tandis que Server2 fonctionne très bien.
- L'exécution
ansible
"ad-hoc" sur Server1 fonctionne très bien. L'exécuter en tant que playbook échoue.
Des questions)
- Qu'est-ce qui pourrait faire que ma configuration Ansible Sudo fonctionne correctement sur un serveur et être rejetée sur un autre?
- Ansible exécute-t-il le «mot de passe» du mot de passe de la machine locale à la machine distante différemment lors de l'exécution ad-hoc par rapport à Playbook? J'ai supposé qu'ils seraient les mêmes.
Je pense que cela se rapproche de la simple soumission d'un rapport de bogue à la page GitHub uniquement sur le fait que l'accès sudo a des résultats différents selon que j'exécute ad-hoc ou non.
En utilisant @lulian comme point d'ancrage dans cette réponse, le problème est venu à un voyou
ansible_sudo_pass:
défini dans les group_vars qui remplaçait le mot de passe entré pour--ask-sudo-pass
.En utilisant ce qui suit:
J'ai été en mesure de trouver ce qui
write(4, "{{ password }}\n", 15)
était passé au lieu du mot de passe entré. Après quelques recherches rapides, j'ai effectivement trouvéansible_sudo_pass
défini dans mes group_vars qui remplaçait mon mot de passe entré.En tant qu'INF pour tout le monde, la
ansible_sudo_pass:
définition semble avoir la priorité sur--ask-sudo-pass
ce qui, au premier abord, semblait contre-intuitif. En fin de compte, c'est une erreur de l'utilisateur, mais la méthodologie de @ lulian dans le débogage de l'interaction SSH ainsi que la découverte de relations entreansible_sudo_pass
et--ask-sudo-pass
devraient être très utiles pour les autres. (Avec un peu de chance!)la source
-e
, et vous pouvez peut-être contourner cela en passant une option appropriée avec-e
.