web-dev-qa-db-ja.com

Ansibleは、sudoパスが指定されている場合でも、sudoの認証に失敗します

問題

最新の安定したAnsibleビルドを使用すると、「Gathering_Facts」中にプレイブックが1つのサーバーでハングするが、Sudoを使用すると他の同様のサーバーで正常に機能するという奇妙な問題があります。 Ansibleサーバーでは、ユーザー(NISユーザー)として実行し、リモートサーバーで(rootとして)Sudoを使用して変更を加えます。このセットアップからSudoを削除すると、すべてが正常に動作します。

セットアップ

ソフトウェアのバージョン

  • [〜#〜] os [〜#〜]:RHEL 6.4
  • Ansibleバージョン:ansible 1.8.2
  • Sudoバージョン
     Sudoersバージョン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(Hathers on Gathering_Facts)
 /
User1@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を正しく使用できるかどうかをテストしたいだけです。プレイブックがまったく実行されれば、私は元気です。

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

Sudoの構成

/ etc/sudoers

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

このSudo構成は、両方のサーバーで正常に機能します。 Sudo自体に問題はありません。

すべてを実行する方法

非常にシンプル:

 $ ansible-playbook test.yml 
 SSH password:
 Sudo password [defaults to SSH password]:
 
 PLAY [Server1:Server2] ********************************************** 
 
ギャザリングの事実****************************************** ********************* 
 ok:[Server2] 
 failed:[Server1] => {"failed":true、 "parsed":false} 
 
申し訳ありませんが、もう一度お試しください。
 [Ansible via key = mxxiqyvztlfnbctwixzmgvhwfdarumtq]パスワード:[.____。 ____。] 
 
タスク:[空のファイルを作成して、接続とSudoアクセスをテストします] **************** 
変更:[サーバー2] 
 
通知:[クリーン] ********************************* **************************** 
変更:[Server2] 
 
 PLAY RECAP ************************************************** ****************** 
再試行するには、次を使用します:--limit @/home/User1/test.retry 
 
 Server1:ok = 0 changed = 0 unr eachable = 0 failed = 1 
 Server2:ok = 3 changed = 2 unreachable = 0 failed = 0 

SSH/Sudoパスワードと暗黙的に(SudoをデフォルトでSSHに渡すように)両方を明示的に入力したかどうかに関係なく失敗します。

リモートサーバーログ

Server1(失敗)

/ var/log/secure

 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)
 Dec 31 15:21:11によってユーザーUser1のために開かれたセッションServer1 sshd [27095]:sftpに対するサブシステム要求
 Dec 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 
 Dec 31 15:26:13 Server1 Sudo:pam_unix(Sudo:auth):conversation failed 
 12月31日15:26:13 Server1 Sudo:pam_unix(Sudo:auth):authが[User1]のパスワードを識別できませんでした
 Dec 31 15:26:13 Server1 Sudo:User1:1個の不正なパスワード試み; TTY = pts/1; PWD =/home/User1; USER = root;コマンド=/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 ):ユーザーUser1のセッションが終了しました

Server2(正常に実行)

/ var/log/secure

 Dec 31 15:21:12 Server2 sshd [31447]:xxxxポート60346 ssh2からのUser1の受け入れられたパスワード
 Dec 31 15:21:12 Server2 sshd [31447]:pam_unix(sshd:session ):(uid = 0)
 Dec 31 15:21:12 Server2 sshd [31449]によってユーザーUser1のために開かれたセッション:sftp 
 Dec 31 15:21:12 Server2 Sudoに対するサブシステム要求: User1:TTY = pts/2; PWD =/home/User1; USER = root;コマンド=/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 ):ユーザー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 select(0、NULL、NULL、NULL、{1、508055})= 0(タイムアウト)
 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: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 
 23650 close(10)= 0 
 23650 write(2、 "申し訳ありませんが、もう一度やり直してください。\ n"、18)= 18 
 23650 gettimeofday({1420050850、238344}、NULL)= 0 
 23650靴下et(PF_FILE、SOCK_STREAM、0)= 10 
 23650 connect(10、{sa_family = AF_FILE、path = "/ var/run/dbus/system_bus_socket"}、33)= 0 

サーバー2

 6625 select(8、[5 7]、[]、NULL、NULL)=? ERESTARTNOHAND(再起動予定)
 6625 --- SIGCHLD(子が終了しました)@ 0(0)--- 
 6625 write(8、 "\ 21"、1)= 1 
 6625 rt_sigreturn(0x8)= -1 EINTR(システムコールの中断)
 6625 select(8、[5 7]、[]、NULL、NULL)= 1([7]内)
 6625 read(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 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 poll([{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_DO NTWAIT、{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 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#これは構成fi "...、4096)= 2980 
 6625 read(6、" "、4096)= 0 
 6625 close(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]を使用)、2つのシステム間で同じです。

テスト

須藤STDIN

テスト済み 別の問題 ここで、SudoはSTDINからパスワードを読み取れませんが、両方のサーバーで正常に機能しました。

Sudoアドホックのテスト

-bash-4.1 $ ansible Server1 -m file -a "dest =/tmp/ansible_test.txt state = touch" -sK 
 SSH password:
 Sudo password [defaults to SSHパスワード]:
サーバー1 |成功>> {
 "変更":true、
 "dest": "/tmp/ansible_test.txt"、
 "gid":0、
 " group ":" root "、
" mode ":" 0644 "、
" owner ":" root "、
" size ":0、
"状態 ":"ファイル "、
" uid ":0 
} 

成功!しかし、なぜ?!

TL; DR

  1. Server2が正常に実行されている間、Server1はSudoパスワードプロンプトを待機しているようです。
  2. Server1でansible "ad-hoc"を実行すると問題なく動作します。プレイブックとして実行すると失敗します。

質問

  • Ansible Sudo構成が1つのサーバーで正常に動作し、別のサーバーで拒否される原因は何ですか?
  • Ansibleは、アドホックとPlaybookを実行するときに、ローカルマシンからリモートマシンへのパスワード「パス」を異なる方法で実行しますか?同じだと思いました。

アドホックを実行しているかどうかによってSudoアクセスの結果が異なるという事実だけで、これは単にGitHubページにバグレポートを送信することに近づいていると思います。

9
BrM13

この回答の足がかりとして@lulianを使用すると、問題はgroup_varsで定義された不正な_ansible_Sudo_pass:_になり、_--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)が渡されていることがわかりました。少し検索したところ、実際に入力したパスワードを上書きしていたgroup_varsに_ansible_Sudo_pass_が定義されていました。

他のすべての人にとって参考になるように、_ansible_Sudo_pass:_の定義は_--ask-Sudo-pass_より優先されるようですが、最初は直感に反しているように見えました。結局、これはユーザーエラーですが、SSH相互作用のデバッグにおける@lulianの方法論、および_ansible_Sudo_pass_と_--ask-Sudo-pass_の関係の発見は、他の人にとって非常に役立つはずです。 (うまくいけば!)

4
BrM13

私がやろうとしていることは

strace -vfp `pidof sshd`

それがどこで失敗しているかを確認してください。

アカウントも確認してください。おそらく制限されているか何かですが、私の賭けは、/ etc/hostsファイルに問題があるか、プロセス中に変更されることです。

4
Iulian