Sudo Pass가 제공 되어도 Ansible이 Sudo를 인증하지 못함


9

문제

최신의 안정적인 Ansible 빌드를 사용하면 "Gathering_Facts"동안 내 플레이 북이 한 서버에서 중단되지만 Sudo를 사용할 때 다른 유사한 서버에서 제대로 작동하는 이상한 문제가 있습니다. Ansible 서버에서 사용자 (NIS 사용자)로 실행 하고 원격 서버에서 sudo (루트로)를 사용하여 변경합니다. 이 설정에서 Sudo를 제거하면 모든 것이 잘 작동합니다.

설정

소프트웨어 버전

  • 운영체제 : RHEL 6.4
  • 가능한 버전 : 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 (수집에 관한 사항 _Facts)
                  /
User1 @ Ansible ----
                  \
                   -------- User1 @ Server2 : sudo -H -S -p (정상 작동)

사용자

  • User1 : Server1 및 Server2 모두에서 NIS 액세스 가능한 사용자.
  • root : 각 서버의 로컬 루트 사용자

가능한 구성

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를 올바르게 사용할 수 있는지 테스트하고 싶습니다. 플레이 북이 전혀 없다면, 몸 상태가 좋은 것입니다.

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 비밀번호] :

[서버 1 : 서버 2] 재생 *********************************************** ** 

게이팅 사실 *************************************************** *************** 
확인 : [서버 2]
실패 : [Server1] => { "실패": true, "구문 분석": false}

죄송하지만 다시 시도하세요.
[ansible, key = mxxiqyvztlfnbctwixzmgvhwfdarumtq를 통한 sudo] 비밀번호 : 
sudo : 1 번의 잘못된 비밀번호 시도


작업 : [연결 및 sudo 액세스를 테스트하기 위해 빈 파일 만들기] **************** 
변경 : [Server2]

알림 : [청결] ​​************************************************ **************** 
변경 : [Server2]

재생 요약 *************************************************** ******************** 
           다시 시도하려면 다음을 사용하십시오. --limit @ / home / User1 / test.retry

Server1 : ok = 0 변경됨 = 0 도달 불가능 = 0 실패 = 1   
Server2 : ok = 3 변경됨 = 2 연결할 수 없음 = 0 실패 = 0

SSH / Sudo 비밀번호와 암시 적 모두를 명시 적으로 입력했는지 여부에 관계없이 실패합니다 (sudo pass 기본값을 SSH로 보냄).

원격 서버 로그

서버 1 (실패)

/ 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)
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 = / 홈 / 사용자 1; USER = 루트; 명령 = / 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)
12 월 31 일 15:21:12 Server2 sshd [31449] : sftp에 대한 서브 시스템 요청
12 월 31 일 15:21:12 Server2 sudo : User1 : TTY = pts / 2; PWD = / 홈 / 사용자 1; USER = 루트; 명령 = / 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 출력

다음은 루트 사용자의 사용 가능한 명령을 대상으로 할 때 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 닫기 (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, 경로 = "/ 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 (들) && 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 닫기 (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 읽기 (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가 STDIN에서 비밀번호를 읽지 않지만 두 서버에서 모두 잘 작동하는 다른 문제를 테스트 했습니다.

Sudo Ad-Hoc 테스트

-bash-4.1 $ ansible Server1 -m 파일 -a "dest = / tmp / ansible_test.txt state = touch"-sK
SSH 비밀번호 : 
sudo 비밀번호 [기본값은 SSH 비밀번호] : 
서버 1 | 성공 >> {
    "변경됨": true, 
    "dest": "/tmp/ansible_test.txt", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "소유자": "루트", 
    "크기": 0, 
    "상태": "파일", 
    "uid": 0
}

성공! 그런데 왜?!

TL; DR

  1. Server2가 정상적으로 실행되는 동안 Server1이 sudo 암호 프롬프트를 기다리는 것 같습니다.
  2. ansibleServer1 에서 "ad-hoc"을 실행하면 정상적으로 작동합니다. 플레이 북으로 실행하지 못했습니다.

질문

  • Ansible Sudo 구성이 한 서버에서 제대로 작동하고 다른 서버에서 거부되는 원인은 무엇입니까?
  • Ansible은 임시 또는 플레이 북을 실행할 때 로컬에서 원격 컴퓨터로 "패스"암호를 다르게 수행합니까? 나는 그들이 같을 것이라고 생각했다.

나는 이것이 임시 실행 여부에 따라 sudo 액세스가 다른 결과를 얻는다는 사실에 대해 단순히 GitHub 페이지에 버그 보고서를 제출하는 것에 가까워지고 있다고 생각합니다.

답변:


4

내가 할 일은 사용하는 것입니다

strace -vfp `pidof sshd`

어디에서 실패하는지 봅니다.

계정도 확인하십시오. 아마 제한적이거나 뭔가 있지만 내 베팅은 / etc / hosts 파일에 문제가 있거나 프로세스에서 변경되는 것입니다.


고마워요, 루리 안 질문에 몇 가지 수정 사항을 적용했으며 한 섹션은 STrace 출력입니다. 원격 서버에서 처리 프로세스가 시작된 후 두 서버간에 진행 방식에 차이가 있음이 분명합니다. 후속 실행 및 추적 캡처는 일관되었습니다.
BrM13

strace -vfp에서 더 많은 것이 필요하다고 생각합니다 .sshd 프로세스에서 수동으로 수행하고 출력을 따르십시오. 암호를 읽은 후에는 PAM 등을 거치기 전에 채널을 닫는 것이라고 생각하지 않습니다. 그 시점에서 sshd_config 파일과 hosts.deny ..에서 무언가를 찾을 수 있는지 확인하십시오.
Iulian

나는 당신의 제안을 전에 시도했지만, 거기에 중요한 요소를 놓쳤을 것입니다 (따라서 초기 STrace에서 가능한 과정을 보도록 선택했습니다). 다시 이동 한 후 실제 비밀번호 대신 빈 {{password}} 변수가 전달되는 것을 발견했습니다. 귀하의 답변이 결국 제게 올바른 길을 찾게되었으므로 다른 "답변"을 별도로 제출하셨습니다.
BrM13

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.