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


9

問題

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

セットアップ

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

  • OS:RHEL 6.4
  • Ansibleバージョン:ansible 1.8.2
  • 須藤バージョン
    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ユーザー。

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

以下は、空のファイルをタップして削除する簡単なテストプレイブックです。実際、リモートサーバーでsudoをAnsibleで正しく使用できるかどうかをテストしたいだけです。プレイブックがまったく実行されれば、私は元気です。

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パスワード: 
sudoパスワード[デフォルトはSSHパスワード]:

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

収集の事実************************************************ *************** 
ok:[Server2]
失敗:[Server1] => {"失敗":true、 "解析":false}

申し訳ありませんが、もう一度やり直してください。
[Ansible経由のsudo、key = mxxiqyvztlfnbctwixzmgvhwfdarumtq]パスワード: 
sudo:1回の不正なパスワード試行


タスク:[接続と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

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)によってユーザー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; 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
12月31日15:26:13 Server1 sshd [27093]:pam_unix(sshd:session):ユーザーUser1のセッションが終了しました 

Server2(正常に実行)

/ var / log / secure

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; 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
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 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ソケット(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書き込み(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
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_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 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#これは構成ファイルです" ...、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パスワード: 
sudoパスワード[デフォルトはSSHパスワード]: 
サーバー1 | 成功>> {
    「変更」:true、 
    "宛先": "/tmp/ansible_test.txt"、 
    "gid":0、 
    "グループ": "ルート"、 
    "モード": "0644"、 
    "所有者": "ルート"、 
    「サイズ」:0、 
    "状態": "ファイル"、 
    「uid」:0
}

成功!しかし、なぜ?!

TL; DR

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

質問

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

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

回答:


4

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

strace -vfp `pidof sshd`

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

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


ありがとう、ルリアン。質問にいくつかの編集を適用しました。1つのセクションはSTrace出力です。2つのサーバー間で、ansibleプロセスがリモートサーバーで開始された後の処理方法に違いがあることは明らかです。その後の実行とトレースキャプチャは一貫していた。
BrM13、2015年

私はあなたがそのstrace -vfpからもっと必要があると思います、トップのsshdプロセスで手動でそれを実行し、出力に従ってください。パスワードを読んだ後は、PAMなどを通過する前にそのようなチャネルを閉じるだけだとは思いません。その時点で、sshd_configファイルとhosts.denyを確認してください。そこに何かがあるかどうかを確認してください。
2015年

私は以前あなたの提案を試しましたが、そこの重要な要素を見逃していたに違いありません(そのため、最初のSTraceでansibleプロセスを見ることにしました)。もう一度行ったところ、実際のパスワードの代わりに空の{{password}}変数が渡されているのを発見しました。あなたの回答が最終的に正しい軌道に乗ったので、別の「回答」を個別に送信することを選択しました。
BrM13、2015年

4

この回答で@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最初は直感に反するように見えたものよりも優先されるようです。結局のところ、これはユーザーエラーですが、SSHの相互作用をデバッグする@lulianの方法論、ansible_sudo_passおよび間の関係の発見は、--ask-sudo-pass他の人にとって非常に役立つはずです。(うまくいけば!)


1
Ansibleがコマンドラインオプションよりもファイル定義変数を優先するの直観に反し、動作が悪いと私は主張します。不思議なことに、これはでオプションを渡すと壊れていることを認識しており-e、で適切なオプションを渡すことでこれを回避できる場合があります-e
Christopher Cashell 2015
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.