지난 번에 이어 몇가지 모듈을 더 살펴 보겠습니다.
(6) 명령 수행
특정 명령을 수행하는 시나리오 입니다.
[root@labco7ans ansible]# cat 07.command.yml
---
- hosts: win
gather_facts: no
tasks:
- name: run an executable using win_command
win_command: whoami.exe
- name: run a cmd command
win_command: cmd.exe /c mkdir C:\test
[root@labco7ans ansible]# ansible-playbook -i hosts 07.command.yml
PLAY [win] ***********************************************************************************************************************************************************
TASK [run an executable using win_command] ***************************************************************************************************************************
changed: [172.16.3.106]
TASK [run a cmd command] *********************************************************************************************************************************************
changed: [172.16.3.106]
PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
생성되었습니다.
PS C:\> dir
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
<생략>
d----- 6/29/2020 4:33 PM Temp
d----- 6/30/2020 10:35 AM test
d-r--- 6/29/2020 4:46 PM Users
d----- 6/29/2020 4:45 PM Windows
그런데 이를 한번 더 실행하면 어떨까요?
[root@labco7ans ansible]# ansible-playbook -i hosts 07.command.yml
PLAY [win] ***********************************************************************************************************************************************************
TASK [run an executable using win_command] ***************************************************************************************************************************
changed: [172.16.3.106]
TASK [run a cmd command] *********************************************************************************************************************************************
fatal: [172.16.3.106]: FAILED! => {"changed": true, "cmd": "cmd.exe /c mkdir C:\\test", "delta": "0:00:00.140629", "end": "2020-06-30 01:35:51.440674", "msg": "non-zero return code", "rc": 1, "start": "2020-06-30 01:35:51.300045", "stderr": "A subdirectory or file C:\\test already exists.\r\n", "stderr_lines": ["A subdirectory or file C:\\test already exists."], "stdout": "", "stdout_lines": []}
PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106 : ok=1 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
stderr로 "A subdirectory or file C:\\test already exists.\r\n" 이 발생합니다.
이러한 command는 멱등성의 단위가 아닌 별개의 작업으로 간주됩니다.
한가지 더 살펴볼 것은 앞서 살펴본 예제에서도 있던 register입니다. register 를 whoami.exe 결과를 받아오는데 사용될 수도 있습니다. 예제를 조금 수정했습니다.
[root@labco7ans ansible]# cat 07.command2.yml
---
- hosts: win
gather_facts: no
tasks:
- name: run an executable using win_command
win_command: whoami.exe
register: output
- debug: msg="{{ output.stdout }}"
[root@labco7ans ansible]# ansible-playbook -i hosts 07.command2.yml
PLAY [win] ***********************************************************************************************************************************************************
TASK [run an executable using win_command] ***************************************************************************************************************************
changed: [172.16.3.106]
TASK [debug] *********************************************************************************************************************************************************
ok: [172.16.3.106] => {
"msg": "labw16ans\\administrator\r\n"
}
PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
(7) 환경 변수 설정
시스템 환경변수를 추가하는 시나리오 입니다.
[root@labco7ans ansible]# cat 08.env.yml
---
- hosts: win
gather_facts: no
tasks:
- name: Set an environment variable for all users
win_environment:
state: present
name: NewVariable
value: New Value
level: machine
[root@labco7ans ansible]# ansible-playbook -i hosts 08.env.yml
PLAY [win] ***********************************************************************************************************************************************************
TASK [Set an environment variable for all users] *********************************************************************************************************************
changed: [172.16.3.106]
PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
아래와 같이 생성되었습니다.
C:\Users\User1>set |findstr New
NewVariable=New Value
Windows 서버의 환경변수는 시스템 환경변수와 사용자 환경변수로 나뉩니다. 이를 level로 정의합니다. 하기 참고하시기 바랍니다.

공식문서의 Notes에서도 언급된 내용은, 이 module 자체가 변경사항을 전파하지 않는다는 점입니다(This module does not broadcast change events). 그러하므로 변경사항을 세션이나 시스템에 반영하기 위해 새로운 세션을 생성하거나 reboot이 필요할 수 있습니다.
참고: https://docs.ansible.com/ansible/latest/modules/win_environment_module.html#win-environment-module
자매품으로 win_path 모듈로 세부 element를 수정할 수 있습니다. 기본적인 환경변수 추가는 win_envrionment를 사용하시기 바랍니다.
참고: https://docs.ansible.com/ansible/latest/modules/win_path_module.html#win-path-module
(8) 레지스트리 관리
레지스트리를 관리하는 시나리오는 아래와 같습니다.
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kbdhid\Parameters의 CrashOnCtrlScroll를 1로 세팅
[root@labco7ans ansible]# cat 09.reg.yml
---
- hosts: win
gather_facts: no
tasks:
- name: Add or update registry with dword entry 'CrashOnCtrlScroll', and containing 1 as the hex value
win_regedit:
path: HKLM:\SYSTEM\CurrentControlSet\Services\Kbdhid\Parameters
name: CrashOnCtrlScroll
data: 0x1
type: dword
[root@labco7ans ansible]# ansible-playbook -i hosts 09.reg.yml
PLAY [win] ***********************************************************************************************************************************************************
TASK [Add or update registry with dword entry 'CrashOnCtrlScroll', and containing 1 as the hex value] ****************************************************************
changed: [172.16.3.106]
PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
아래와 같이 값이 입력되었습니다.
<사전>
C:\>reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kbdhid\Parameters
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kbdhid\Parameters
WorkNicely REG_DWORD 0x0
<사후>
C:\>reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kbdhid\Parameters
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kbdhid\Parameters
WorkNicely REG_DWORD 0x0
CrashOnCtrlScroll REG_DWORD 0x1
다른 방법은 별도의 reg 파일을 작성 후 win_regmerge로 적용시킬 수도 있습니다. 이 경우 앞서 살펴본 win_copy로 필요한 reg 파일을 전달하고 적용시킬 수 있습니다.
참고: https://docs.ansible.com/ansible/latest/modules/win_regmerge_module.html#win-regmerge-module
(9) 페이지파일 설정
페이지 파일을 설정하는 시나리오입니다.
[root@labco7ans ansible]# ansible win -i hosts -m win_pagefile
172.16.3.106 | SUCCESS => {
"automatic_managed_pagefiles": true,
"changed": false,
"pagefiles": []
}
[root@labco7ans ansible]# cat 10.pagefile.yml
---
- hosts: win
gather_facts: no
tasks:
- name: Disable AutomaticManagedPagefile and set C pagefile
win_pagefile:
drive: C
initial_size: 2048
maximum_size: 2048
automatic: no
state: present
[root@labco7ans ansible]# ansible-playbook -i hosts 10.pagefile.yml
PLAY [win] ***********************************************************************************************************************************************************
TASK [Disable AutomaticManagedPagefile and set C pagefile] ***********************************************************************************************************
changed: [172.16.3.106]
PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@labco7ans ansible]# ansible win -i hosts -m win_pagefile
172.16.3.106 | SUCCESS => {
"automatic_managed_pagefiles": false,
"changed": false,
"pagefiles": [
{
"caption": "C:\\ 'pagefile.sys'",
"description": "'pagefile.sys' @ C:\\",
"initial_size": 2048,
"maximum_size": 2048,
"name": "C:\\pagefile.sys"
}
]
}
페이지 파일 세팅을 적용하기 위해 reboot이 필요할 수 있습니다. reboot 시나리오를 추가했습니다. pagefile 단계가 changed 상태가되면 reboot이 진행되는 시나리오입니다.
[root@labco7ans ansible]# cat 10.pagefile2.yml
---
- hosts: win
gather_facts: no
tasks:
- name: Disable AutomaticManagedPagefile and set C pagefile
win_pagefile:
drive: C
initial_size: 4096
maximum_size: 4096
automatic: no
state: present
register: pagefile
- name: Reboot server
win_reboot:
msg: "Page file moved,rebooting..."
pre_reboot_delay: 15
when: pagefile.changed
[root@labco7ans ansible]# ansible-playbook -i hosts 10.pagefile2.yml
PLAY [win] ***********************************************************************************************************************************************************
TASK [Disable AutomaticManagedPagefile and set C pagefile] ***********************************************************************************************************
changed: [172.16.3.106]
TASK [Reboot server] *************************************************************************************************************************************************
changed: [172.16.3.106]
PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@labco7ans ansible]# ansible win -i hosts -m win_pagefile
172.16.3.106 | SUCCESS => {
"automatic_managed_pagefiles": false,
"changed": false,
"pagefiles": [
{
"caption": "C:\\ 'pagefile.sys'",
"description": "'pagefile.sys' @ C:\\",
"initial_size": 4096,
"maximum_size": 4096,
"name": "C:\\pagefile.sys"
}
]
}
(10) 로컬 보안 정책 관리
로컬 보안 정책(secpol)을 변경하는 시나리오입니다.
먼저 secedit을 export해서 변경하려는 값을 살펴 봅니다.
C:\>SecEdit.exe /export /cfg C:\temp\output.ini
The task has completed successfully.
See log %windir%\security\logs\scesrv.log for detail info.
C:\>type C:\temp\output.ini
[Unicode]
Unicode=yes
[System Access]
MinimumPasswordAge = 0
MaximumPasswordAge = 42
MinimumPasswordLength = 0
PasswordComplexity = 1
<생략>
MaximumPasswordAge 을 90으로 변경해 보는 시나리오를 수행해보겠습니다.
파일에서 확인한 내용으로 section에서 [System Access] 를 필요한 key와 value 를 각각 설정합니다.
[root@labco7ans ansible]# cat 11.secpol.yml
---
- hosts: win
gather_facts: no
tasks:
- name: Set the maximum password age
win_security_policy:
section: System Access
key: MaximumPasswordAge
value: 90
[root@labco7ans ansible]# ansible-playbook -i hosts 11.secpol.yml
PLAY [win] ***********************************************************************************************************************************************************
TASK [Set the maximum password age] **********************************************************************************************************************************
changed: [172.16.3.106]
PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
아래와 같이 변경되었습니다.
C:\>SecEdit.exe /export /cfg C:\temp\output2.ini
The task has completed successfully.
See log %windir%\security\logs\scesrv.log for detail info.
C:\>type C:\temp\output2.ini | findstr Password
MinimumPasswordAge = 0
MaximumPasswordAge = 90
MinimumPasswordLength = 0
PasswordComplexity = 1
PasswordHistorySize = 0
<생략>
(11) 업데이트 적용
윈도우즈의 패치는 아래와 같이 진행할 수 있습니다.
- name: Install all critical and security updates
win_updates:
category_names:
- CriticalUpdates
- SecurityUpdates
state: installed
register: update_result
- name: Reboot host if required
win_reboot:
when: update_result.reboot_required
다만 Windows 서버의 업데이트는 약간의 복잡성을 가지고 있습니다. 상기의 시나리오는 MS나 WSUS 로의 업데이트가 가능한 환경이라는 전제가 되있어야합니다.
Air-gapped 환경이라면 아래와 같은 시나리오도 생각해 볼 수 있습니다.
- 웹서버 세팅 > 업데이트 파일을 Docroot에 복사 > playbook (win_get_url + win_hotfix로 설치)
업데이트 파일 이동을 위해 win_copy를 생각할 수도 있겠지만 win_copy의 경우 WinRM 상에서 동작하므로 용량이 큰 경우 효과적이지 않습니다 (Because win_copy runs over WinRM, it is not a very efficient transfer mechanism. If sending large files consider hosting them on a web service and using [win_get_url](https://docs.ansible.com/ansible/latest/modules/win_get_url_module.html#win-get-url-module) instead.) 공식문서의 커맨트를 따라 win_get_url을 사용했습니다.
혹은 download.windowsupdate.com을 URL 방화벽으로 오픈이 가능하다면 아래와 같이 진행할 수도 있습니다.
- name: Download KB3172729 for Server 2012 R2
win_get_url:
url: http://download.windowsupdate.com/d/msdownload/update/software/secu/2016/07/windows8.1-kb3172729-x64_e8003822a7ef4705cbb65623b72fd3cec73fe222.msu
dest: C:\temp\KB3172729.msu
- name: Install hotfix
win_hotfix:
hotfix_kb: KB3172729
source: C:\temp\KB3172729.msu
state: present
register: hotfix_result
- name: Reboot host if required
win_reboot:
when: hotfix_result.reboot_required
마지막 시나리오로 SSU 업데이트를 적용해 보겠습니다.
[root@labco7ans ansible]# cat 12.update.yml
---
- hosts: win
gather_facts: no
tasks:
- name: Download SSU(KB4550994) for Server 2016
win_get_url:
url: http://download.windowsupdate.com/c/msdownload/update/software/secu/2020/04/windows10.0-kb4550994-x64_1df8a8ea245041495f3b219fb22f3849908d8e27.msu
dest: C:\temp\KB4550994.msu
- name: Install hotfix
win_hotfix:
hotfix_kb: KB4550994
source: C:\temp\KB4550994.msu
state: present
register: hotfix_result
- name: Reboot host if required
win_reboot:
when: hotfix_result.reboot_required
[root@labco7ans ansible]# ansible-playbook -i hosts 12.update.yml
PLAY [win] ***********************************************************************************************************************************************************
TASK [Download SSU(KB4550994) for Server 2016] ***********************************************************************************************************************
changed: [172.16.3.106]
TASK [Install hotfix] ************************************************************************************************************************************************
changed: [172.16.3.106]
TASK [Reboot host if required] ***************************************************************************************************************************************
skipping: [172.16.3.106]
PLAY RECAP ***********************************************************************************************************************************************************
172.16.3.106 : ok=2 changed=2 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
SSU 패치라 reboot task는 skip 되었고, 아래 결과를 보면 KB4550994 가 설치된 것을 알 수 있습니다.
C:\>wmic qfe
Caption CSName Description FixComments HotFixID InstallDate InstalledBy InstalledOn Name ServicePackInEffect Status
http://support.microsoft.com/?kbid=3192137 LABW16ANS Update KB3192137 NT AUTHORITY\SYSTEM 9/12/2016
http://support.microsoft.com/?kbid=4550994 LABW16ANS Security Update KB4550994 LABW16ANS\Administrator 6/30/2020
이를 마지막으로 Windows 서버에서 ansible을 활용해 사용해볼만한 Windows Module을 살펴봤습니다.
참고
https://docs.ansible.com/ansible/latest/modules/win_feature_module.html#win-feature-module
https://docs.ansible.com/ansible/latest/user_guide/windows_usage.html#use-cases
'IaC' 카테고리의 다른 글
ansible - windows 모듈 (1) (0) | 2022.02.04 |
---|