即使給出了 Sudo Pass,Ansible 也無法驗證 Sudo
問題
使用最新、穩定的 Ansible 版本,我遇到了一個奇怪的問題,即我的劇本在“Gathering_Facts”期間掛在一台伺服器上,但在使用 Sudo 時在其他類似伺服器上執行良好。在 Ansible 伺服器上,我以我的使用者(NIS 使用者)身份執行,並在遠端伺服器上使用sudo(以 root 身份)進行更改。如果我從此設置中刪除 Sudo,一切正常。
設置
軟體版本
- 作業系統:RHEL 6.4
- Ansible 版本:ansible 1.8.2
- 須藤版本:
須藤版本 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 上) / 使用者1@Ansible ---- \ -------- User1@Server2: sudo -H -S -p (工作正常)
使用者
- User1:Server1 和 Server2 上的 NIS 可訪問使用者。
- root:每個伺服器的本地 root 使用者。
Ansible 配置
我的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
這是一個簡單的測試劇本,可以觸摸一個空文件,然後將其刪除。真的,我只是想測試我是否可以讓 Ansible 在遠端伺服器上正確使用 sudo。如果劇本完全執行,我的狀態很好。
測試.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
須藤配置
/etc/sudoers
Host_Alias SRV = Server1, Server2 User_Alias SUPPORT = User1, User2, User3 SUPPORT SRV=(root) ALL
此 sudo 配置在兩台伺服器上都可以正常工作。sudo 本身沒有問題。
我如何執行它
非常簡單:
$ ansible-playbook test.yml SSH 密碼: sudo 密碼 [預設為 SSH 密碼]: 播放 [Server1:Server2] ************************************************ ** 收集事實 ************************************************ *************** 好的:[伺服器2] 失敗:[Server1] => {“失敗”:真,“解析”:假} 抱歉,請再試一次。 [sudo via ansible, key=mxxiqyvztlfnbctwixzmgvhwfdarumtq] 密碼: sudo:1 次錯誤密碼嘗試 任務:[創建空文件以測試連接和 sudo 訪問] **************** 更改:[Server2] 通知:[乾淨] ************************************************ ****************** 更改:[Server2] 播放回顧 ************************************************ ******************** 要重試,請使用:--limit @/home/User1/test.retry Server1 : ok=0 更改=0 無法訪問=0 失敗=1 Server2 : 好的=3 更改=2 無法訪問=0 失敗=0
無論我是否顯式輸入 SSH/Sudo 密碼以及隱式輸入(讓 sudo 預設傳遞給 SSH),都會失敗。
遠端伺服器日誌
伺服器 1(失敗)
/var/log/安全
12 月 31 日 15:21:10 Server1 sshd[27093]:從 xxxx 埠 51446 ssh2 接受 User1 的密碼 12 月 31 日 15:21:10 Server1 sshd[27093]: pam_unix(sshd:session): 由 (uid=0) 為使用者 User1 打開的會話 12 月 31 日 15:21:11 Server1 sshd[27095]:對 sftp 的子系統請求 12 月 31 日 15:21:11 Server1 sudo: pam_unix(sudo:auth): 身份驗證失敗;logname=User1 uid=187 euid=0 tty=/dev/pts/1 ruser=User1 rhost=user=User1 12 月 31 日 15:26:13 Server1 sudo: pam_unix(sudo:auth): 對話失敗 12 月 31 日 15:26:13 Server1 sudo: pam_unix(sudo:auth): auth 無法辨識 [User1] 的密碼 12 月 31 日 15:26:13 Server1 sudo: User1: 1 次錯誤密碼嘗試;TTY=pts/1 ; 密碼=/home/User1;使用者=根;命令=/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 12 月 31 日 15:26:13 Server1 sshd[27093]: pam_unix(sshd:session): 使用者 User1 的會話關閉
Server2(執行良好)
/var/log/安全
12 月 31 日 15:21:12 Server2 sshd [31447]:從 xxxx 埠 60346 ssh2 接受 User1 的密碼 12 月 31 日 15:21:12 Server2 sshd[31447]: pam_unix(sshd:session): 由 (uid=0) 為使用者 User1 打開的會話 12 月 31 日 15:21:12 Server2 sshd[31449]:對 sftp 的子系統請求 12 月 31 日 15:21:12 Server2 sudo: User1 : TTY=pts/2 ; 密碼=/home/User1;使用者=根;命令=/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 12 月 31 日 15:21:14 Server2 sshd[31447]: pam_unix(sshd:session): 使用者 User1 的會話關閉
STrace 輸出
這是針對 root 使用者的 ansible 命令時 strace 的輸出。命令:
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 選擇(0,NULL,NULL,NULL,{1,508055})= 0(超時) 23650 套接字(PF_NETLINK,SOCK_RAW,9)= 10 23650 fcntl(10,F_SETFD,FD_CLOEXEC)=0 23650 讀取連結(“/proc/self/exe”,“/usr/bin/sudo”,4096)= 13 23650 發送至(10,“|\0\0\0L\4\5\0\1\0\0\0\0\0\0\0op=PAM:正宗”...,124, 0, {sa_family =AF_NETLINK,pid=0,組=00000000},12)= 124 23650 輪詢([{fd=10, events=POLLIN}], 1, 500) = 1 ([{fd=10, revents=POLLIN}]) 23650 從(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 從(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 關閉(10)= 0 23650 write(2, "對不起,再試一次。\n", 18) = 18 23650 gettimeofday({1420050850, 238344}, NULL) = 0 23650 套接字(PF_FILE,SOCK_STREAM,0)= 10 23650 連接(10,{sa_family=AF_FILE,路徑 =“/var/run/dbus/system_bus_socket”},33)= 0
伺服器2
6625 選擇(8,[5 7],[],NULL,NULL)=?ERESTARTNOHAND(待重新啟動) 6625 --- SIGCHLD(孩子退出)@ 0 (0) --- 6625 寫(8,“\21”,1)= 1 6625 rt_sigreturn(0x8) = -1 EINTR(中斷的系統呼叫) 6625 選擇(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 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 發送至(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,組=00000000},12)= 120 6625 輪詢([{fd=6,事件=POLLIN}],1, 500)= 1([{fd=6,revents=POLLIN}]) 6625 從(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 從(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 關閉(6)= 0 6625 打開(“/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# 這是配置文件"..., 4096) = 2980 6625 讀取(6,“”,4096)= 0 6625 關閉(6)= 0 6625 munmap(0x7fbc3a59a000,4096)= 0 6625 open("/etc/environment", O_RDONLY) = 6
我猜
Server1 未正確獲取密碼或錯誤地詢問/等待密碼。這看起來不像是 Sudo 或 Ansible 問題(單獨,它們都工作得很好),但 Server1 似乎沒有以與 Server2 類似的方式接收憑據(或遵守它們)。Server1 和 2 用於不同的目的,因此它們可能存在一些身份驗證或包版本差異,但它們都是從同一個儲存庫建構的;因此,它們不應該有什麼不同。
PAM 認證
我想也許系統有不同的 PAM 配置,導緻密碼的處理方式有所不同。我比較了 /etc/pam.d/ 文件(使用
md5sum [file]
),它們在兩個系統之間是相同的。測試
須藤標準輸入
測試了另一個問題,即 sudo 不會從 STDIN 讀取密碼,但這在兩台伺服器上都執行良好。
測試 Sudo Ad-Hoc
-bash-4.1$ ansible Server1 -m 文件 -a "dest=/tmp/ansible_test.txt state=touch" -sK SSH 密碼: sudo 密碼 [預設為 SSH 密碼]: 伺服器1 | 成功 >> { “改變”:是的, "dest": "/tmp/ansible_test.txt", “吉德”:0, “組”:“根”, “模式”:“0644”, “所有者”:“根”, “大小”:0, “狀態”:“文件”, “uid”:0 }
成功!但為什麼?!
TL; 博士
- Server1 似乎正在等待 sudo 密碼提示,而 Server2 執行良好。
- 在 Server1 上執行
ansible
“ad-hoc”工作正常。將其作為劇本執行失敗。問題)
- 什麼可能導致我的 Ansible Sudo 配置在一台伺服器上正常工作而在另一台伺服器上被拒絕?
- 在執行 ad-hoc 與 playbook 時,Ansible 是否以不同的方式執行從本地機器到遠端機器的密碼“傳遞”?我以為他們會是一樣的。
我認為這接近於簡單地向 GitHub 頁面送出錯誤報告,純粹是因為 sudo 訪問會產生不同的結果,這取決於我是否正在執行 ad-hoc。
在此答案中使用@lulian 作為立足點,問題歸結為
ansible_sudo_pass:
group_vars 中定義的流氓,它覆蓋了為--ask-sudo-pass
.使用以下內容:
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)
正在傳遞而不是輸入的密碼。經過一些快速搜尋,我確實ansible_sudo_pass
在我的 group_vars 中找到了定義,它覆蓋了我輸入的密碼。作為對其他人的僅供參考,該
ansible_sudo_pass:
定義似乎優先--ask-sudo-pass
於最初似乎違反直覺的定義。最後,這是使用者錯誤,但@lulian 調試 SSH 互動的方法以及與之間的關係發現ansible_sudo_pass
應該--ask-sudo-pass
對其他人非常有幫助。(希望!)
我會做的是使用
strace -vfp `pidof sshd`
看看哪裡出了問題。
還要檢查帳戶,也許它受到限製或其他原因,但我敢打賭,您的 /etc/hosts 文件有問題,或者在此過程中確實發生了變化。