即使授予Sudo,Ansible也不能validationSudo

问题

使用最新,稳定的Ansible版本,我有一个奇怪的问题,我的剧本在“Gathering_Facts”挂在一台服务器上,但在使用Sudo时在其他类似的服务器上工作正常。 在Ansible服务器上,我以用户(NIS用户)身份运行,并在远程服务器上使用sudo (以root身份)进行更改。 如果我从这个设置删除Sudo,一切工作正常。

build立

软件版本

  • 操作系统 :RHEL 6.4
  • Ansible版本ansible 1.8.2
  • Sudo版本
     Sudo版本1.8.6p3
     Sudoers政策插件版本1.8.6p3
     Sudoers文件语法版本42
     Sudoers I / O插件版本1.8.6p3
    
  • SSH版本 :OpenSSH_5.3p1,OpenSSL 1.0.0-fips 2010年3月29日

服务器映射

                    -------- User1 @ Server1:sudo -H -S -p(挂在Gathering_Facts上)
                   /
 User1 @ Ansible ----
                   \
                    -------- User1 @ Server2:sudo -H -S -p(工作正常)

用户

  • User1:Server1和Server2上的NIS可访问用户。
  • root:每个服务器的本地root用户。

Ansibleconfiguration

我的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 

这是一个简单的testing手册,触摸一个空文件,然后删除它。 真的,我只想testing是否可以让Ansible在远程服务器上正确使用sudo。 如果剧本运行的话,我的状态很好。

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 

Sudoconfiguration

在/ etc / sudoers文件

 Host_Alias SRV = Server1, Server2 User_Alias SUPPORT = User1, User2, User3 SUPPORT SRV=(root) ALL 

这个sudoconfiguration在两个服务器上工作得很好。 sudo本身没有问题。

我如何运行它

很简单:

 $ ansible-playbook test.yml
 SSH密码: 
 sudo密码[默认为SSH密码]:

 PLAY [Server1:Server2] ******************************************** ** 

收集事实********************************************************* *************** 
好的:[Server2]
失败:[Server1] => {“failed”:true,“parsed”:false}

抱歉,请再试一次。
 [sudo via ansible,key = mxxiqyvztlfnbctwixzmgvhwfdarumtq]密码: 
 sudo:1不正确的密码尝试


任务:[创build空文件来testing连接和sudo访问] **************** 
已更改:[Server2]

通知:[清洁] ********************************************* **************** 
已更改:[Server2]

玩回扣************************************************ ******************** 
           要重试,请使用:--limit @ / home / User1 / test.retry

 Server1:ok = 0 changed = 0 unreachable = 0 failed = 1   
 Server2:ok = 3 changed = 2 unreachable = 0 failed = 0

无论我是否明确inputSSH / Sudo密码以及隐式(让sudo将默认值传递给SSH)都会失败。

远程服务器日志

Server1(失败)

在/ var /日志/安全

 Dec 31 15:21:10 Server1 sshd [27093]:从xxxx端口51446接收用户1的密码ssh2
 Dec 31 15:21:10 Server1 sshd [27093]:pam_unix(sshd:session):通过(uid = 0)为用户User1打开的会话
 Dec 31 15:21:11 Server1 sshd [27095]:sftp的子系统请求
 Dec 31 15:21:11 Server1 sudo:pam_unix(sudo:auth):authentication失败;  logname = User1 uid = 187 euid = 0 tty = / dev / pts / 1 ruser = User1 rhost = user = User1 
 Dec 31 15:26:13 Server1 sudo:pam_unix(sudo:auth):对话失败
 Dec 31 15:26:13 Server1 sudo:pam_unix(sudo:auth):auth无法识别[User1]的密码
 Dec 31 15:26:13 Server1 sudo:用户1:1不正确的密码尝试;  TTY = 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
 Dec 31 15:26:13 Server1 sshd [27093]:pam_unix(sshd:session):session for user User1 

Server2(运行良好)

在/ var /日志/安全

 Dec 31 15:21:12 Server2 sshd [31447]:来自xxxx端口的用户1的接受密码60346 ssh2
 Dec 31 15:21:12 Server2 sshd [31447]:pam_unix(sshd:session):通过(uid = 0)为用户User1打开的会话
 Dec 31 15:21:12 Server2 sshd [31449]:子系统请求sftp
 12月31日15:21:12 Server2 sudo: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
 Dec 31 15:21:14 Server2 sshd [31447]:pam_unix(sshd:session):session for user User1 

STrace输出

这是来自strace的输出,以root用户的命令为目标。 命令:

 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` 

服务器1

 23650 select(0,NULL,NULL,NULL,{1,0808055})= 0(超时)
 23650sockets(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:authentic”...,124,0,{sa_family = AF_NETLINK,pid = 0,groups = 00000000},12)= 124
 23650 poll([{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
 23650closures(10)= 0
 23650写(2,“对不起,再试一次。\ n”,18)= 18
 23650 gettimeofday({1420050850,238344},NULL)= 0
 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(要重新启动)
 6625 --- SIGCHLD(小孩退出)@ 0(0)---
 6625写(8,“\ 21”,1)= 1
 6625 rt_sigreturn(0x8)= -1 EINTR(中断的系统调用)
 6625 select(8,[5 7],[],NULL,NULL)= 1(在[7]中)
 6625阅读(7,“\ 21”,1)= 1
 6625 wait4(6636,[{WIFEXITED(s)&& WEXITSTATUS(s)== 0}],WNOHANG | WSTOPPED,NULL)= 6636
 6625 rt_sigprocmask(SIG_BLOCK,NULL,[],8)= 0
 6625sockets(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,groups = 00000000},12)= 120
 6625轮询([{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,...,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,...,8988,MSG_DONTWAIT,{sa_family = AF_NETLINK,pid = 0,groups = 00000000},[12])= 36
 6625 close(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_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#这是configuration文件”...,4096)= 2980
 6625阅读(6,“”,4096)= 0
 6625 close(6)= 0
 6625 munmap(0x7fbc3a59a000,4096)= 0
 6625打开(“/ etc / environment”,O_RDONLY)= 6

我猜

服务器1没有正确获取密码或不正确地询问/等待密码。 这看起来不像一个Sudo或Ansible问题(单独,它们都工作得很好),但Server1似乎没有像Server2一样接收凭据(或坚持他们)。 Server1&2服务于不同的目的,所以它们可能有一些authentication或包版本的差异,但它们都是从同一个存储库构build的; 因此,他们不应该是这样的不同。

PAMauthentication

我想也许系统有不同的PAMconfiguration导致密码处理有点不同。 我比较了/etc/pam.d/文件(使用md5sum [file] ),它们在两个系统之间是相同的。

testing

Sudo STDIN

testing了另一个问题 ,sudo不会从STDIN读取密码,但在两台服务器上都能正常工作。

testingSudo Ad-Hoc

 -bash-4.1 $ ansible Server1 -m文件-a“dest = / tmp / ansible_test.txt state = touch”-sK
 SSH密码: 
 sudo密码[默认为SSH密码]: 
 Server1 | 成功>>
     “改变”:是的, 
     “dest”:“/tmp/ansible_test.txt”, 
     “gid”:0, 
     “组”:“根”, 
     “模式”:“0644”, 
     “所有者”:“根”, 
     “size”:0, 
     “状态”:“文件”, 
     “uid”:0
 }

成功! 但为什么?!

TL; DR

  1. Server1似乎在等待sudo密码提示,而Server2运行得很好。
  2. 在Server1上运行安全的“ad-hoc”工作正常。 将其作为剧本运行失败。

问题(S)

  • 什么可能会导致我的Ansible Sudoconfiguration在一台服务器上正常工作,并在另一台服务器上被拒绝?
  • 当运行ad-hoc与playbook时,Ansible会不同地执行从本地机器到远程机器的密码“传递”? 我以为他们会是一样的。

我认为这只是简单地向GitHub页面提交一个错误报告,纯粹是因为sudo访问具有不同的结果,这取决于我是否正在运行ad hoc。

我会做的是使用

 strace -vfp `pidof sshd` 

并看看它失败的地方。

检查帐户,也许它是受限制的,但我敢打赌,你的/ etc / hosts文件有问题,或者在这个过程中被修改。

在这个答案中使用@lulian作为立足点,问题归结为stream氓ansible_sudo_pass:在group_vars中定义,它覆盖了为--ask-sudo-passinput的密码。

使用以下内容:

 while [[ -z $(ps -eaf|grep 'sshd: [U]ser1@pts/1') ]]; do continue done strace -ff -vfp $(ps -eaf|grep 'sshd: [U]ser1@pts/1'|awk '{print $2}') -o /root/strace_sshd1_2.out 

我能够发现write(4, "{{ password }}\n", 15)被传递,而不是input的密码。 经过一些快速search,我确实发现了在我的group_vars中定义的ansible_sudo_pass,它覆盖了我input的密码。

作为对所有其他人的参考, ansible_sudo_pass:定义似乎优先于--ask-sudo-pass ,起初似乎与直觉相反。 最后,这是用户错误,但@ luliandebuggingSSH交互的方法以及ansible_sudo_pass--ask-sudo-pass之间的关系发现应该对其他人非常有帮助。 (希望!)