Ansible로 sudoers.d 파일 확인

Ansible로 sudoers.d 파일 확인

저는 우리 환경 전체에서 sudoers 파일을 관리하는 데 사용하는 Ansible 플레이북을 가지고 있습니다. 우리는 최소한의 sudoers 파일을 /etc/sudoers에 유지하고 추가하려는 모든 항목은 /etc/sudoers.d 아래의 별도 파일에 저장됩니다.

내 Ansible 플레이북에는 이러한 파일을 푸시하기 위한 다음 작업이 포함되어 있습니다.

- name: copy sudoers files
  copy:
    src: "{{ item }}"
    dest: "/etc/sudoers.d/{{ item }}"
    backup: yes
    owner: root
    group: root
    mode: 0440
    validate: /usr/sbin/visudo -cf %s
  with_items:
    - admins
    - apache
    - monitor

작업에는 파일을 커밋하기 전에 파일이 유효한지 확인하는 유효성 검사 절이 포함되어 있으며 이는 일반적으로 잘 작동했습니다. 그러나 오늘 업데이트로 인해 sudo가 중단되는 문제가 발생했습니다. 파일이 유효성 검사 단계를 통과했지만 기본 /etc/sudoers 파일의 User_Alias와 동일한 이름을 가진 User_Alias가 포함되어 있습니다. 그 후에 sudo를 실행하려고 시도하면 구문 분석 오류가 발생했습니다.

제 질문은 이것입니다. 이와 같은 오류를 포착할 수 있는 Ansible의 sudoers 파일 업데이트를 어떻게 테스트합니까? 파일이 제 위치에 있으면 를 실행하여 오류를 포착할 수 있지만 visudo -c유효성 검사 단계가 작동하지 않으므로 이를 입력하면 됩니다. Ansible에는 %s자리 표시자가 필요하며, 그렇지 않은 경우에도 파일을 visudo -c포착하지 못하도록 파일을 제자리에 복사하기 전에 유효성 검사가 수행됩니다.

답변1

이것을 시도해 보셨나요:

- copy:
    src: '{{ item }}'
    dest: '/etc/sudoers.d/{{ item }}'
    owner: root
    group: root
    mode: 0440
    validate: 'bash -c "cat /etc/sudoers %s | visudo -cf-"'

그것은 나를 위해 작동합니다.

답변2

나는 그것을 작동시켰다. 내가 한 일은 다음과 같습니다. 먼저 /etc/sudoers.stage.d에 스테이징 디렉터리를 생성하고 /etc/sudoers.d의 내용을 여기에 복사하는 일련의 Ansible 작업을 추가했습니다. 그런 다음 이 준비 영역에 파일을 업로드하고, 변경된 파일이 있으면 사용자 지정 스크립트를 실행하여 활성화합니다.

이제 플레이북의 논리는 다음과 같습니다.

- name: delete staging area
  file:
    path: "/etc/sudoers.stage.d"
    state: absent
  changed_when: false

- name: copy /etc/sudoers.d to staging area
  shell: "cp -rp /etc/sudoers.d /etc/sudoers.stage.d"
  changed_when: false

- name: stage sudoers files
  copy:
    src: "{{item}}"
    dest: "/etc/sudoers.stage.d/{{item}}"
    backup: yes
    owner: root
    group: root
    mode: 0440
    validate: /usr/sbin/visudo -cf %s
  with_items:
    - admins
    - apache
    - monitor
  register: sudoers_d

- block:
  - name: push out activate script
    copy:
      src: activate_sudoers.sh
      dest: /usr/local/bin/activate_sudoers.sh
      owner: root
      group: root
      mode: 0700

  - name: activate change
    shell: /bin/sh /usr/local/bin/activate_sudoers.sh /etc/sudoers.stage.d

  when: sudoers_d.changed

activate_sudoers.sh 스크립트의 모습은 다음과 같습니다.

#!/bin/sh

function usage {
    echo "Usage: $0 <stage directory>" >&2
    exit 1
}

function abort {
    echo "*** Error detected" >&2
    [ "$#" -gt 0 ] && echo "***" $@ >&2
    exit 1
}

PATH=/usr/bin:/bin:/usr/sbin:/sbin
export PATH

test $# -eq 1 || usage
test -d "$1" || abort "Stage directory $1: missing or not a directory"
test -d /etc/sudoers.old.d && rm -rf /etc/sudoers.old.d
test -d /etc/sudoers.old.d && abort "Failed to remove /etc/sudoers.old.d"

mv /etc/sudoers.d /etc/sudoers.old.d \
  && mv "$1" /etc/sudoers.d \
  && visudo -c

if [ $? -eq 0 ]; then
    # Success - clean up
    rm -rf /etc/sudoers.old.d
    exit 0
else
    # Failure - roll back
    rm -rf /etc/sudoers.d
    mv /etc/sudoers.old.d /etc/sudoers.d
    abort "sudoers update failed"
fi

내가 기대했던 것보다 조금 더 길고 복잡하지만 작업은 완료됩니다. 이 내용이 동일한 문제를 겪고 있는 다른 사람에게 유용할 수 있기를 바랍니다.

답변3

Ansible 모듈에서만 동일한 작업을 수행합니다.

- name: Creating assemble directory
  file:
    path: /etc/sudoers.stage.d
    state: directory
    mode: 0600

- name: Applying sudoers.d files on assemble directory
  template:
    src: "{{ item }}.j2"
    dest: /etc/sudoers.stage.d/{{ item }}
    mode: 0400
  loop:
    - 10-wheel
    - 20-sys
  register: check

- name: Copying original sudoers to the assemble directory
  copy:
    remote_src: yes
    src: /etc/sudoers
    dest: /etc/sudoers.stage.d/99-sudoers
  when: check.changed

- name: Removing include line from 99-sudoers
  lineinfile:
    path: /etc/sudoers.stage.d/99-sudoers
    state: absent
    regex: ^#includedir /etc/sudoers.d
  when: check.changed

- name: Assembling unique config for validation
  assemble:
    src: /etc/sudoers.stage.d
    dest: /etc/sudoers.stage
    mode: 0600
    validate: visudo -cf %s
  when: check.changed

- name: Applying sudoers configurations
  template:
    src: "{{ item }}.j2"
    dest: /etc/sudoers.d/{{ item }}
    mode: 0440
  loop:
    - 10-wheel
    - 20-sys
  when: check.changed

관련 정보