권한 상승 이해하기: become
권한 상승 이해하기: become (Understanding privilege escalation: become)
Ansible은 기존의 권한 상승 시스템을 사용해서 작업을 root 권한으로, 또는 다른 사용자의 권한으로 실행해요. 이 기능은 머신에 로그인한 사용자(원격 사용자)와 다른 사용자로 '되어(become)' 실행할 수 있게 해 주기 때문에 become이라고 불러요. become 키워드는 sudo, su, pfexec, doas, pbrun, dzdo, ksu, runas, machinectl 같은 기존 권한 상승 도구를 사용해요.
출처: 문서
본문
Ansible은 기존 권한 상승 시스템을 사용해서 작업을 root 권한으로, 또는 다른 사용자의 권한으로 실행해요. 이 기능은 머신에 로그인한 사용자(원격 사용자)와 다른 사용자로 '되어(become)' 실행하도록 해 주기 때문에 become이라고 불러요. become 키워드는 sudo, su, pfexec, doas, pbrun, dzdo, ksu, runas, machinectl 등 기존 권한 상승 도구를 사용해요.
become 사용하기
become 사용은 플레이 또는 작업 지시문, 연결 변수, 명령줄로 제어할 수 있어요. 여러 방식으로 권한 상승 속성을 설정했다면 일반 우선순위 규칙을 확인해서 어떤 설정이 사용될지 이해하세요.
Ansible에 포함된 모든 become 플러그인의 전체 목록은 플러그인 목록에서 찾을 수 있어요.
Become 지시문
become을 제어하는 지시문은 플레이 또는 작업 레벨에서 설정할 수 있어요. 호스트마다 자주 다른 연결 변수를 설정해서 이것들을 덮어쓸 수 있어요. 이 변수와 지시문은 독립적이에요. 예를 들어 become_user를 설정한다고 become이 설정되지는 않아요.
become — 권한 상승을 활성화하려면 true로 설정.
become_user — 원하는 권한을 가진 사용자로 설정 — 로그인하는 사용자가 아니라 become할 사용자예요. 호스트 레벨에서 설정할 수 있도록 become: true를 의미하지는 않아요. 기본값은 root예요.
become_method — (플레이 또는 작업 레벨) ansible.cfg에 설정된 기본 메서드를 덮어써요. Become 플러그인 중 아무거나 사용하도록 설정.
become_flags — (플레이 또는 작업 레벨) 작업이나 롤에 특정 플래그를 사용하도록 허용. 흔한 용도는 셸이 nologin으로 설정된 상태에서 사용자를 nobody로 바꾸는 것이에요. (Ansible 2.2에 추가됨)
예를 들어 root가 아닌 사용자로 연결했을 때 시스템 서비스를 관리하려면(root 권한 필요), become_user의 기본값(root)을 사용할 수 있어요:
- name: Ensure the httpd service is running
service:
name: httpd
state: started
become: true
apache 사용자로 명령을 실행하려면:
- name: Run a command as the apache user
command: somecommand
become: true
become_user: apache
셸이 nologin인 상태에서 nobody 사용자로 무언가를 하려면:
- name: Run a command as nobody
command: somecommand
become: true
become_method: su
become_user: nobody
become_flags: '-s /bin/sh'
sudo 비밀번호를 지정하려면 ansible-playbook을 --ask-become-pass(줄여서 -K)와 함께 실행하세요. become을 사용하는 플레이북을 실행했는데 멈춘 것 같다면, 대부분 권한 상승 프롬프트에서 걸린 것이에요. CTRL-c로 멈추고 -K 옵션과 적절한 비밀번호로 플레이북을 다시 실행하세요.
Become 연결 변수
관리 노드나 그룹마다 다른 become 옵션을 정의할 수 있어요. 이 변수들은 인벤토리에서 정의하거나 일반 변수로 사용할 수 있어요.
ansible_become — become 지시문을 덮어쓰고 권한 상승을 사용할지 여부를 결정.
ansible_become_method — 어떤 권한 상승 메서드를 사용할지.
ansible_become_user — 권한 상승을 통해 become할 사용자를 설정. ansible_become: true를 의미하지 않음.
ansible_become_password — 권한 상승 비밀번호를 설정. 비밀을 평문으로 두지 않는 방법은 암호화된 변수와 파일 사용하기를 참고하세요.
ansible_common_remote_group — setfacl과 chown이 모두 실패할 때 Ansible이 임시 파일의 그룹을 chgrp로 바꿔볼지 결정. 자세한 내용은 '비특권 사용자로 become하기의 위험'을 참고하세요. (버전 2.10에 추가됨)
예를 들어 webserver라는 서버에서 모든 작업을 root로 실행하고 싶지만 manager 사용자로만 연결할 수 있다면, 인벤토리 항목을 이렇게 사용할 수 있어요:
webserver ansible_user=manager ansible_become=true
참고: 위에서 정의한 변수들은 모든 become 플러그인에 공통이지만, 플러그인별 변수로 대체할 수도 있어요. 각 플러그인이 가진 옵션 목록과 정의 방법은 해당 플러그인 문서를 확인하세요. Ansible의 become 플러그인 전체 목록은 Become 플러그인에서 찾을 수 있어요.
Become 명령줄 옵션
--ask-become-pass(줄여서-K) — 권한 상승 비밀번호를 물어봄. become이 사용된다는 뜻은 아니에요. 이 비밀번호는 모든 호스트에 사용된다는 점을 주의하세요.--become(줄여서-b) — become으로 작업 실행 (비밀번호를 암시하지 않음).--become-method=BECOME_METHOD— 사용할 권한 상승 메서드 (기본값=sudo). 유효한 선택:[ sudo | su | pbrun | pfexec | doas | dzdo | ksu | runas | machinectl ].--become-user=BECOME_USER— 이 사용자로 작업 실행 (기본값=root).--become/-b를 암시하지 않음.
become의 위험과 한계
권한 상승은 대부분 직관적이지만, 동작 방식에는 몇 가지 한계가 있어요. 사용자들은 예상치 못한 일을 피하려고 이것들을 알아두어야 해요.
비특권 사용자로 become하기의 위험
Ansible 모듈은 원격 머신에서 파라미터를 모듈 파일에 대입(substitute)하고, 그 파일을 원격 머신에 복사한 뒤, 마지막으로 그곳에서 실행하는 방식으로 실행돼요.
모듈 파일이 become을 사용하지 않고 실행되거나, become_user가 root이거나, 원격 머신에 root로 연결하면 모든 것이 정상이에요. 이런 경우 Ansible은 모듈 파일을 사용자와 root만 읽을 수 있는 권한, 또는 전환되는 비특권 사용자만 읽을 수 있는 권한으로 만듭니다.
하지만 연결 사용자와 become_user가 모두 비특권일 때는, 모듈 파일이 Ansible이 연결한 사용자(remote_user)로 작성되는데도, 그 파일은 Ansible이 become하도록 설정된 사용자가 읽을 수 있어야 해요. Ansible이 이 문제를 해결하는 방식은 플랫폼에 따라 다를 수 있어요. POSIX 시스템에서는 Ansible이 다음과 같은 방식으로 문제를 해결해요:
- 먼저, setfacl이 원격
PATH에 설치되어 있고, 원격 호스트의 임시 디렉터리가 POSIX.1e 파일시스템 ACL 지원으로 마운트되어 있다면, Ansible은 POSIX ACL을 사용해서 모듈 파일을 두 번째 비특권 사용자와 공유해요. - POSIX ACL을 사용할 수 없거나 setfacl을 실행할 수 없다면, Ansible은 비특권 사용자로서 그렇게 하는 것을 지원하는 시스템에서 chown으로 모듈 파일의 소유권을 바꾸려고 시도해요.
- Ansible 2.11에서 새로 추가된 것으로, 이 시점에 Ansible은 chmod +a를 시도해요. 이것은 파일에 ACL을 설정하는 macOS 특유의 방식이에요.
- Ansible 2.10에서 새로 추가된 것으로, 위의 모든 것이 실패하면 Ansible은 구성 설정
ansible_common_remote_group의 값을 확인해요. 많은 시스템에서 특정 사용자가 파일의 그룹 소유권을 자신이 속한 그룹으로 바꾸는 것을 허용해요. 그래서 두 번째 비특권 사용자(become_user)가 Ansible이 연결한 사용자(remote_user)와 공통 UNIX 그룹을 갖고 있고,ansible_common_remote_group이 그 그룹으로 정의되어 있다면, Ansible은 chgrp로 모듈 파일의 그룹 소유권을 그 그룹으로 바꿔서become_user가 읽을 수 있게 만들 수 있어요.
이 시점에서 ansible_common_remote_group이 정의되어 있고 chgrp를 시도했으며 성공했다면, Ansible은 새 그룹 소유권으로 충분하다고 가정하고(중요하게도 확인하지는 않아요) 더 이상 폴백하지 않아요. 즉 Ansible은 become_user가 실제로 remote_user와 그룹을 공유하는지 확인하지 않아요. 명령이 성공적으로 끝나기만 하면 Ansible은 결과를 성공으로 간주하고 아래의 world_readable_temp 확인으로 진행하지 않아요.
ansible_common_remote_group이 설정되어 있지 않고 위의 chown이 실패했거나, ansible_common_remote_group이 설정되어 있는데 chgrp(또는 이어지는 그룹 권한 chmod)가 성공하지 않은 종료 코드를 반환했다면, Ansible은 마지막으로 world_readable_temp 옵션을 확인해요. 이것이 설정되어 있다면 Ansible은 모듈 파일을 world-readable 임시 디렉터리에 world-readable 권한으로 두어 become_user(그리고 부수적으로 시스템의 다른 모든 사용자)가 파일 내용을 읽을 수 있게 해요. 모듈에 전달된 파라미터 중 민감한 것이 있고 원격 머신을 신뢰하지 않는다면 이것은 잠재적 보안 위험입니다.
모듈 실행이 끝나면 Ansible은 임시 파일을 삭제해요.
위의 논리 흐름을 완전히 피하는 방법은 여러 가지가 있어요:
- pipelining을 사용하세요. pipelining이 활성화되면 Ansible은 모듈을 클라이언트의 임시 파일에 저장하지 않아요. 대신 모듈을 원격 Python 인터프리터의 stdin으로 파이프해요. Pipelining은 파일 전송을 수반하는 Python 모듈(예: copy, fetch, template)이나 비-Python 모듈에서는 동작하지 않아요.
- 비특권 사용자로 become하는 것을 피하세요.
becomeroot이거나become을 사용하지 않으면 임시 파일이 UNIX 파일 권한으로 보호돼요. Ansible 2.1 이상에서는 관리 머신에 root로 연결한 뒤become으로 비특권 계정에 접근해도 UNIX 파일 권한이 안전해요.
참고: Solaris ZFS 파일시스템에는 파일시스템 ACL이 있지만 그 ACL은 POSIX.1e 파일시스템 ACL이 아니에요(NFSv4 ACL이에요). Ansible은 이 ACL을 사용해 임시 파일 권한을 관리할 수 없으므로, 원격 머신이 ZFS를 쓰면 world_readable_temp 옵션에 의존해야 할 수 있어요.
(버전 2.1에서 변경됨)
Ansible은 모르는 사이에 become을 안전하지 않게 사용하기 어렵게 만들어요. Ansible 2.1부터 Ansible은 become으로 안전하게 실행할 수 없으면 기본적으로 오류를 내요. pipelining이나 POSIX ACL을 쓸 수 없고, 비특권 사용자로 연결해야 하며, 다른 비특권 사용자로 실행하도록 become을 사용해야 하고, 관리 노드가 실행하려는 모듈을 세계 공개(world readable)로 두기에 충분히 안전하다고 판단한다면, world_readable_temp 옵션을 켜서 이 오류를 경고로 바꾸고 2.1 이전처럼 작업이 실행되게 할 수 있어요.
(버전 2.10에서 변경됨)
Ansible 2.10은 앞서 언급한 ansible_common_remote_group 폴백을 도입했어요. 활성화되면 remote_user와 become_user가 모두 비특권 사용자일 때 사용돼요. 이 폴백이 언제 발생하는지 자세한 내용은 위 본문을 참고하세요.
참고: 앞서 언급했듯이
ansible_common_remote_group과world_readable_temp가 모두 활성화되어 있으면 world-readable 폴백이 발동할 가능성이 낮은데도 Ansible이 여전히 모듈 파일에 접근하지 못할 수 있어요. 그룹 소유권 변경이 성공한 뒤에는 Ansible이 더 이상 폴백하지 않고,become_user가 실제로 '공통 그룹'의 구성원인지 확인도 하지 않기 때문이에요. 이는 그러한 확인에 원격 머신과의 또 다른 왕복 연결이 필요하고, 이는 시간이 많이 걸리는 작업이기 때문이라는 설계 결정이에요. 다만 Ansible은 이 경우 경고를 내보내요.
모든 연결 플러그인이 지원하지는 않음
권한 상승 메서드는 사용 중인 연결 플러그인도 지원해야 해요. 대부분의 연결 플러그인은 become을 지원하지 않으면 경고해요. 일부는 항상 root로 실행되므로(jail, chroot 등) 그냥 무시하기도 해요.
호스트당 하나의 메서드만 활성화 가능
메서드를 체인으로 연결할 수 없어요. sudo /bin/su -로 사용자를 become할 수 없어요. sudo에서 그 사용자로 명령을 실행할 권한이 있거나, 그 사용자로 직접 su할 수 있어야 해요(pbrun, pfexec 등 다른 지원 메서드도 동일해요).
권한 상승은 일반적이어야 함
특정 명령으로만 권한 상승 권한을 제한할 수 없어요. Ansible은 특정 명령을 사용해 작업을 수행하지 않을 때도 있고, 매번 바뀌는 임시 파일 이름에서 모듈(코드)을 실행해요. 허용된 명령이 '/sbin/service'나 '/bin/chmod'라면 Ansible에서 실패할 거예요. 그 경로들이 Ansible이 모듈을 실행하려고 만든 임시 파일과 일치하지 않기 때문이에요. 특정 명령 경로만 실행하도록 sudo/pbrun/doas 환경을 제한하는 보안 규칙이 있다면, 이 제약이 없는 특수 계정에서 Ansible을 사용하거나, AWX나 Red Hat Ansible Automation Platform을 사용해서 SSH 자격 증명에 대한 간접 접근을 관리하세요.
pamd_systemd가 채운 환경 변수에 접근하지 못할 수 있음
systemd를 init으로 사용하는 대부분의 Linux 배포판에서 become이 사용하는 기본 메서드는 systemd의 의미에서 새 "세션"을 열지 않아요. pam_systemd 모듈이 새 세션을 완전히 초기화하지 않기 때문에, ssh로 연 보통 세션과 비교하면 예상 밖의 일이 있을 수 있어요: pam_systemd가 설정하는 일부 환경 변수, 특히 XDG_RUNTIME_DIR이 새 사용자에게 채워지지 않고 대신 상속되거나 그냥 비워져요.
이것은 XDG_RUNTIME_DIR에 의존해서 버스에 접근하는 systemd 명령을 호출하려고 할 때 문제를 일으킬 수 있어요:
$ echo $XDG_RUNTIME_DIR
$ systemctl --user status
Failed to connect to bus: Permission denied
become이 pam_systemd를 거쳐 새 systemd 세션을 열도록 강제하려면 become_method: machinectl을 사용할 수 있어요.
자세한 내용은 이 systemd 이슈를 참고하세요.
임시 파일 오류 메시지 해결하기
- "Failed to set permissions on the temporary files Ansible needs to create when becoming an unprivileged user"
- 이 오류는
setfacl명령을 제공하는 패키지를 설치하면 해결할 수 있어요. (대개acl패키지지만 OS 문서를 확인하세요.)
become과 네트워크 자동화
버전 2.6부터 Ansible은 enable 모드(또는 privileged EXEC 모드)에 들어가는 것을 지원하는 모든 Ansible 관리 네트워크 플랫폼에서 권한 상승(enable 모드 진입)을 위한 become을 지원해요. become을 사용하면 provider 딕셔너리의 authorize와 auth_pass 옵션을 대체해요.
네트워크 장치에서 권한 상승에 become을 사용하려면 연결 유형을 connection: ansible.netcommon.network_cli 또는 connection: ansible.netcommon.httpapi로 설정해야 해요. 자세한 내용은 플랫폼 옵션 (Platform Options) 문서를 확인하세요.
권한 상승된 권한은 필요한 특정 작업에만, 또는 전체 플레이에, 또는 모든 플레이에 사용할 수 있어요. become: true와 become_method: enable을 추가하면 Ansible은 그 파라미터가 설정된 작업, 플레이, 플레이북을 실행하기 전에 enable 모드에 들어가도록 지시해요.
이 오류 메시지가 보이면, 그 오류를 만든 작업이 성공하려면 enable 모드가 필요하다는 뜻이에요:
Invalid input (privileged mode required)
특정 작업에 enable 모드를 설정하려면 작업 레벨에 become을 추가하세요:
- name: Gather facts (eos)
arista.eos.eos_facts:
gather_subset:
- "!hardware"
become: true
become_method: enable
단일 플레이의 모든 작업에 enable 모드를 설정하려면 플레이 레벨에 become을 추가하세요:
- hosts: eos-switches
become: true
become_method: enable
tasks:
- name: Gather facts (eos)
arista.eos.eos_facts:
gather_subset:
- "!hardware"
모든 작업에 enable 모드 설정하기
모든 플레이의 모든 작업을 권한 모드로 실행하길 원하는 경우가 많은데, 이는 group_vars를 사용하는 것이 가장 좋아요:
group_vars/eos.yml
ansible_connection: ansible.netcommon.network_cli
ansible_network_os: arista.eos.eos
ansible_user: myuser
ansible_become: true
ansible_become_method: enable
enable 모드용 비밀번호
enable 모드에 들어가려면 비밀번호가 필요하다면 다음 두 가지 방식 중 하나로 지정할 수 있어요:
- --ask-become-pass 명령줄 옵션 제공
ansible_become_password연결 변수 설정
참고: 비밀번호는 평문으로 저장해서는 안 된다는 점을 기억하세요. 비밀번호와 기타 비밀을 Ansible Vault로 암호화하는 방법은 Ansible Vault를 참고하세요.
authorize와 auth_pass
Ansible은 여전히 레거시 네트워크 플레이북을 위해 connection: local로 enable 모드를 지원해요. connection: local로 enable 모드에 들어가려면 모듈 옵션 authorize와 auth_pass를 사용하세요:
- hosts: eos-switches
ansible_connection: local
tasks:
- name: Gather facts (eos)
eos_facts:
gather_subset:
- "!hardware"
provider:
authorize: true
auth_pass: " {{ secret_auth_pass }}"
네트워크 장치 enable 모드에 become을 일관되게 사용하도록 플레이북을 업데이트하는 것을 권장해요. authorize와 provider 딕셔너리는 향후 폐기될 거예요. 자세한 내용은 플랫폼 옵션 (Platform Options) 문서를 확인하세요.
become과 Windows
Ansible 2.3부터 become은 runas 메서드를 통해 Windows 호스트에서 사용할 수 있어요. Windows에서의 become은 비-Windows 호스트에서와 같은 인벤토리 설정과 호출 인자를 사용해요. 따라서 설정과 변수 이름은 become_user를 제외하면 이 문서에 정의된 것과 같아요. Windows에는 become_user의 합리적인 기본값이 없으므로 become을 사용할 때 필수예요. 자세한 내용은 ansible.builtin.runas become 플러그인을 참고하세요.
become은 다른 사용자의 신분을 취하는 데 사용할 수 있지만, Windows 호스트에는 다른 용도도 있어요. 중요한 용도 중 하나는 WinRM에서 실행할 때 부과되는 일부 제한, 예를 들어 제한된 네트워크 위임이나 WUA API 같은 금지된 시스템 호출 접근을 우회하는 것이에요. ansible_user와 같은 사용자로 become을 사용하면 이러한 제한을 우회하고 WinRM 세션에서 보통 접근할 수 없는 명령을 실행할 수 있어요.
참고: Windows에서는 권한이 낮은 계정으로 연결하고 become으로 권한을 높일 수 없어요. Become은 연결 계정이 이미 대상 호스트의 Administrator인 경우에만 사용할 수 있어요.
관리 권한 (Administrative rights)
Windows의 많은 작업은 완료하려면 관리자 권한이 필요해요. runas become 메서드를 사용하면 Ansible은 become 사용자에게 사용 가능한 전체 권한으로 모듈을 실행하려고 시도해요. 사용자 토큰을 높이는 데 실패하면 실행 중에는 제한된 토큰을 계속 사용해요.
사용자는 높은 권한으로 become 프로세스를 실행하려면 SeDebugPrivilege가 있어야 해요. 이 권한은 기본적으로 Administrators에게 할당돼요. 디버그 권한이 없으면 become 프로세스는 제한된 권한과 그룹 집합으로 실행돼요.
Ansible이 얻을 수 있었던 토큰의 유형을 확인하려면 다음 작업을 실행하세요:
- name: Check my username
ansible.windows.win_whoami:
become: true
출력은 아래와 비슷할 거예요:
ok: [windows] => {
"account": {
"account_name": "vagrant-domain",
"domain_name": "DOMAIN",
"sid": "S-1-5-21-3088887838-4058132883-1884671576-1105",
"type": "User"
},
"authentication_package": "Kerberos",
"changed": false,
"dns_domain_name": "DOMAIN.LOCAL",
"groups": [
{
"account_name": "Administrators",
"attributes": [
"Mandatory",
"Enabled by default",
"Enabled",
"Owner"
],
"domain_name": "BUILTIN",
"sid": "S-1-5-32-544",
"type": "Alias"
},
{
"account_name": "INTERACTIVE",
"attributes": [
"Mandatory",
"Enabled by default",
"Enabled"
],
"domain_name": "NT AUTHORITY",
"sid": "S-1-5-4",
"type": "WellKnownGroup"
},
],
"impersonation_level": "SecurityAnonymous",
"label": {
"account_name": "High Mandatory Level",
"domain_name": "Mandatory Label",
"sid": "S-1-16-12288",
"type": "Label"
},
"login_domain": "DOMAIN",
"login_time": "2018-11-18T20:35:01.9696884+00:00",
"logon_id": 114196830,
"logon_server": "DC01",
"logon_type": "Interactive",
"privileges": {
"SeBackupPrivilege": "disabled",
"SeChangeNotifyPrivilege": "enabled-by-default",
"SeCreateGlobalPrivilege": "enabled-by-default",
"SeCreatePagefilePrivilege": "disabled",
"SeCreateSymbolicLinkPrivilege": "disabled",
"SeDebugPrivilege": "enabled",
"SeDelegateSessionUserImpersonatePrivilege": "disabled",
"SeImpersonatePrivilege": "enabled-by-default",
"SeIncreaseBasePriorityPrivilege": "disabled",
"SeIncreaseQuotaPrivilege": "disabled",
"SeIncreaseWorkingSetPrivilege": "disabled",
"SeLoadDriverPrivilege": "disabled",
"SeManageVolumePrivilege": "disabled",
"SeProfileSingleProcessPrivilege": "disabled",
"SeRemoteShutdownPrivilege": "disabled",
"SeRestorePrivilege": "disabled",
"SeSecurityPrivilege": "disabled",
"SeShutdownPrivilege": "disabled",
"SeSystemEnvironmentPrivilege": "disabled",
"SeSystemProfilePrivilege": "disabled",
"SeSystemtimePrivilege": "disabled",
"SeTakeOwnershipPrivilege": "disabled",
"SeTimeZonePrivilege": "disabled",
"SeUndockPrivilege": "disabled"
},
"rights": [
"SeNetworkLogonRight",
"SeBatchLogonRight",
"SeInteractiveLogonRight",
"SeRemoteInteractiveLogonRight"
],
"token_type": "TokenPrimary",
"upn": "[email protected]",
"user_flags": []
}
label 키 아래의 account_name 항목이 사용자에게 관리 권한이 있는지 결정해요. 반환될 수 있는 라벨과 그 의미는 다음과 같아요:
Medium: Ansible이 높은 토큰을 얻지 못해 제한된 토큰으로 실행됐어요. 모듈 실행 중 사용자에게 할당된 권한의 일부만 사용 가능하고, 사용자에게 관리 권한은 없어요.High: 높은 토큰이 사용됐고 사용자에게 할당된 모든 권한이 모듈 실행 중 사용 가능해요.System:NT AUTHORITY\System계정이 사용되며 사용 가능한 가장 높은 수준의 권한을 가져요.
출력은 사용자에게 부여된 권한 목록도 보여줘요. 권한 값이 disabled이면 그 권한이 로그온 토큰에 할당되었지만 활성화되지 않았어요. 대부분의 시나리오에서 이런 권한은 필요할 때 자동으로 활성화돼요.
2.5보다 오래된 Ansible 버전에서 실행하거나 일반 runas 상승 과정이 실패하면, 높은 토큰을 다음으로 얻을 수 있어요:
become_user를System으로 설정 — 운영 체제를 완전히 제어해요.- Ansible이 WinRM으로 연결하는 사용자에게
SeTcbPrivilege를 부여.SeTcbPrivilege는 운영 체제를 완전히 제어하는 높은 수준의 권한이에요. 어떤 사용자에게도 기본적으로 이 권한이 주어지지 않으며, 이 권한을 사용자나 그룹에 부여할 때는 주의해야 해요. 이 권한에 대한 자세한 내용은 운영 체제의 일부로 작동 (Act as part of the operating system)을 참고하세요. Windows 호스트에서 이 권한을 설정하려면 아래 작업을 사용할 수 있어요:- name: grant the ansible user the SeTcbPrivilege right ansible.windows.win_user_right: name: SeTcbPrivilege users: '{{ansible_user}}' action: add - 호스트에서 UAC를 끄고 사용자가 되기 전에 재부팅. UAC는
최소 권한(least privilege)원칙으로 계정을 실행하도록 설계된 보안 프로토콜이에요. 다음 작업을 실행해서 UAC를 끌 수 있어요:- name: turn UAC off win_regedit: path: HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\policies\system name: EnableLUA data: 0 type: dword state: present register: uac_result - name: reboot after disabling UAC win_reboot: when: uac_result is changed
참고:
SeTcbPrivilege를 부여하거나 UAC를 끄면 Windows 보안 취약점이 생길 수 있으므로, 이 단계를 취할 때는 주의해야 해요.
로컬 서비스 계정 (Local service accounts)
Ansible 2.5 이전에는 become이 Windows에서 로컬 또는 도메인 사용자 계정으로만 동작했어요. System이나 NetworkService 같은 로컬 서비스 계정은 그 이전 버전에서 become_user로 사용할 수 없었어요. 이 제한은 Ansible 2.5 릴리스 이후 풀렸어요. become_user 아래에 설정할 수 있는 세 가지 서비스 계정은 다음과 같아요:
- System
- NetworkService
- LocalService
로컬 서비스 계정은 비밀번호가 없으므로 ansible_become_password 파라미터가 필요하지 않고, 지정해도 무시돼요.
비밀번호 없이 become 사용하기
Ansible 2.8부터 become은 해당 계정의 비밀번호 없이 Windows 로컬 또는 도메인 계정을 become할 수 있어요. 이 방법이 동작하려면 다음 요구 사항이 충족되어야 해요:
- 연결 사용자에게
SeDebugPrivilege권한이 할당되어 있음 - 연결 사용자가
BUILTIN\Administrators그룹의 일부임 become_user가SeBatchLogonRight또는SeNetworkLogonRight사용자 권한 중 하나를 가짐
비밀번호 없이 become을 사용하는 방법은 두 가지가 있어요:
- 계정이 이미 로그온되어 있다면 기존 로그온 세션의 토큰을 복제
- 원격 호스트에서만 유효한 로그온 토큰을 생성하기 위해 S4U 사용
첫 번째 시나리오에서 become 프로세스는 그 사용자 계정의 다른 로그온에서 생성돼요. 이것은 기존 RDP 로그온이나 콘솔 로그온일 수 있는데, 항상 그런 것은 보장되지 않아요. 예약 작업(Scheduled Task)의 'Run only when user is logged on' 옵션과 비슷해요.
become 계정의 다른 로그온이 존재하지 않는 경우에는 S4U를 사용해서 새 로그온을 만들고 그것을 통해 모듈을 실행해요. 이것은 예약 작업의 'Do not store password' 옵션과 함께 쓰는 'Run whether user is logged on or not'과 비슷해요. 이 시나리오에서는 become 프로세스가 일반 WinRM 프로세스처럼 네트워크 리소스에 접근할 수 없어요.
비밀번호 없는 become과 비밀번호가 없는 계정을 become하는 것을 구분하려면 ansible_become_password를 정의하지 않은 채로 두거나 ansible_become_password:로 설정하세요.
참고: Ansible이 실행될 때 사용자에 대한 기존 토큰이 존재한다는 보장이 없으므로, become 프로세스가 로컬 리소스에만 접근할 가능성이 높아요. 작업이 네트워크 리소스에 접근해야 한다면 비밀번호와 함께 become을 사용하세요.
비밀번호가 없는 계정 (Accounts without a password)
참고: 일반적인 보안 모범 사례로, 비밀번호가 없는 계정을 허용하는 것은 피해야 해요.
Ansible로 비밀번호가 없는 Windows 계정(예: Guest 계정)을 become할 수 있어요. 비밀번호가 없는 계정을 become하려면 변수를 평소처럼 설정하되 ansible_become_password: ''로 설정하세요.
이런 계정에서 become이 동작하려면 먼저 로컬 정책 계정: 로컬 계정의 빈 비밀번호 사용을 콘솔 로그온으로만 제한 (Accounts: Limit local account use of blank passwords to console logon only)을 비활성화해야 해요. 이것은 GPO(그룹 정책 개체)로 하거나 이 Ansible 작업으로 할 수 있어요:
- name: allow blank password on become
ansible.windows.win_regedit:
path: HKLM:\SYSTEM\CurrentControlSet\Control\Lsa
name: LimitBlankPasswordUse
data: 0
type: dword
state: present
참고: 이것은 비밀번호가 없는 계정에만 해당해요. become_user에 비밀번호가 있다면 여전히 그 계정의 비밀번호를
ansible_become_password아래에 설정해야 해요.
Windows용 become 플래그
Ansible 2.5는 runas become 메서드에 become_flags 파라미터를 추가했어요. 이 파라미터는 become_flags 작업 지시문으로 설정하거나 Ansible 구성에서 ansible_become_flags로 설정할 수 있어요. 이 파라미터에 대해 초기에 지원되는 두 가지 유효한 값은 logon_type과 logon_flags예요.
참고: 이 플래그들은 LocalSystem 같은 로컬 서비스 계정이 아니라 일반 사용자 계정을 become할 때만 설정해야 해요.
logon_type 키는 수행할 로그온 작업의 종류를 설정해요. 값은 다음 중 하나로 설정할 수 있어요:
interactive: 기본 로그온 유형. 프로세스가 로컬에서 프로세스를 실행할 때와 같은 컨텍스트에서 실행돼요. 모든 WinRM 제한을 우회하며 권장되는 방법이에요.batch: 비밀번호가 설정된 예약 작업과 비슷한 배치 컨텍스트로 프로세스를 실행해요. 대부분의 WinRM 제한을 우회해야 하며,become_user가 대화형으로 로그온할 수 없을 때 유용해요.new_credentials: 호출 사용자와 동일한 자격 증명으로 실행하지만, 아웃바운드 연결은become_user와become_password의 컨텍스트로 실행돼요.runas.exe /netonly와 비슷해요.logon_flags플래그도netcredentials_only로 설정해야 해요. 프로세스가 다른 자격 증명 집합으로 네트워크 리소스(예: SMB 공유)에 접근해야 할 때 이 플래그를 사용하세요.network: 캐시된 자격 증명 없이 네트워크 컨텍스트로 프로세스를 실행해요. 그 결과는 자격 증명 위임 없이 일반 WinRM 프로세스를 실행하는 것과 같은 유형의 로그온 세션이며, 같은 제한 아래에서 동작해요.network_cleartext:network로그온 유형과 같지만, 네트워크 리소스에 접근할 수 있도록 자격 증명을 캐시해요. 자격 증명 위임과 함께 일반 WinRM 프로세스를 실행하는 것과 같은 유형의 로그온 세션이에요.
자세한 내용은 dwLogonType을 참고하세요.
logon_flags 키는 새 프로세스를 만들 때 Windows가 사용자를 어떻게 로그온할지 지정해요. 값은 다음 중 없음 또는 여러 개로 설정할 수 있어요:
with_profile: 기본 로그온 플래그 집합. 프로세스가HKEY_USERS레지스트리 키의 사용자 프로필을HKEY_CURRENT_USER로 로드해요.netcredentials_only: 프로세스가 호출자와 같은 토큰을 사용하지만, 원격 리소스에 접근할 때는become_user와become_password를 사용해요. 신뢰 관계가 없는 도메인 간 시나리오에서 유용하며,new_credentialslogon_type과 함께 사용해야 해요.
기본적으로 logon_flags=with_profile이 설정돼요. 프로필을 로드하고 싶지 않으면 logon_flags=를, 프로필을 netcredentials_only로 로드하려면 logon_flags=with_profile,netcredentials_only를 설정하세요.
자세한 내용은 dwLogonFlags를 참고하세요.
Windows 작업에서 become_flags를 사용하는 몇 가지 예시는 다음과 같아요:
- name: copy a file from a fileshare with custom credentials
ansible.windows.win_copy:
src: \\server\share\data\file.txt
dest: C:\temp\file.txt
remote_src: true
vars:
ansible_become: true
ansible_become_method: runas
ansible_become_user: DOMAIN\user
ansible_become_password: Password01
ansible_become_flags: logon_type=new_credentials logon_flags=netcredentials_only
- name: run a command under a batch logon
ansible.windows.win_whoami:
become: true
become_flags: logon_type=batch
- name: run a command and do not load the user profile
ansible.windows.win_whomai:
become: true
become_flags: logon_flags=
Windows에서 become의 한계
- Windows Server 2008, 2008 R2, Windows 7에서
async와become으로 작업을 실행하는 것은 Ansible 2.7 이상을 사용할 때만 동작해요. - 기본적으로 become 사용자는 대화형 세션으로 로그온하므로, Windows 호스트에서 그렇게 할 권리가 있어야 해요.
SeAllowLogOnLocally권한을 상속하지 않거나SeDenyLogOnLocally권한을 상속하면 become 프로세스가 실패해요. 권한을 추가하거나logon_type플래그를 설정해서 사용하는 로그온 유형을 바꾸세요. - Ansible 2.3 이전에는
ansible_winrm_transport가basic또는credssp일 때만 become이 동작했어요. 이 제한은 Ansible 2.4 릴리스 이후 Windows Server 2008(non-R2 버전)을 제외한 모든 호스트에서 풀렸어요. ansible_become_method: runas를 사용하려면 Secondary Logon 서비스인seclogon이 실행 중이어야 해요.runas를 사용하려면 연결 사용자가 이미 Windows 호스트의 Administrator여야 해요. 대상 become 사용자는 Administrator일 필요는 없어요.
더 알아보기 (Learn more)
- become 플러그인 목록 — Ansible에 포함된 become 플러그인 살펴보기
- Ansible Vault — 비밀번호를 비롯한 비밀을 암호화하는 방법
- 네트워크 자동화 플랫폼 옵션 — 네트워크 장치에서 become 사용 시 연결 유형 설정