Sudo

即使給出了 Sudo Pass,Ansible 也無法驗證 Sudo

  • November 10, 2017

問題

使用最新、穩定的 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; 博士

  1. Server1 似乎正在等待 sudo 密碼提示,而 Server2 執行良好。
  2. 在 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 文件有問題,或者在此過程中確實發生了變化。

引用自:https://serverfault.com/questions/655626