WindowsサーバーにAnsibleから接続する

Windows2016のサーバーを、Ansibleで操作するための、接続設定を行います。公式のWindows関連のAnsibleマニュアルはこちら。

Windows Guides — Ansible Documentation

検証した環境

  • Host側
    • Windows2016 DataCnenter
  • Clinet側
    • Windows10 Pro
    • WSL(Ubuntu 18.04)
    • Python 3.6.7
    • ansible 2.7.6

Host側

Host側として利用できるWindowsは、以下の条件があります。

Windows2016のサーバーであれば、初期インストール時点にて、おおよそ必要な前提条件を満たしています。

Powershellのバージョン。バージョン5が入っています。

PS C:\Users\Administrator> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.14393.693
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14393.693
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

.NET Frameworkのバージョン。バージョン4.6が入っています。

PS C:\Users\Administrator> reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full"

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full
    CBS    REG_DWORD    0x1
    Install    REG_DWORD    0x1
    InstallPath    REG_SZ    C:\Windows\Microsoft.NET\Framework64\v4.0.30319\
    Release    REG_DWORD    0x60632
    Servicing    REG_DWORD    0x0
    TargetVersion    REG_SZ    4.0.0
    Version    REG_SZ    4.6.01586

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\1033
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full\1041

WinRMについて。インストール済みで起動済みです。

PS C:\Users\Administrator> Get-Service | Where-Object { $_.Name -eq "WinRM" }

Status   Name               DisplayName
------   ----               -----------
Running  WinRM              Windows Remote Management (WS-Manag...

ただし、デフォルト有効となっているWinRMのLinstnerは、HTTPのみとなっています。

PS C:\Users\Administrator> winrm enumerate winrm/config/Listener
Listener
    Address = *
    Transport = HTTP
    Port = 5985
    Hostname
    Enabled = true
    URLPrefix = wsman
    CertificateThumbprint
    ListeningOn = 127.0.0.1, 192.168.10.104, ::1, 2001:0:2841:aa90:442:3e69:2024:4e0e, 2405:6580:a0e0:6800:10c6:e15:d427:f527, fe80::5efe:192.168.10.104%11, fe80::442:3e69:2024:4e0e%2, fe80::10c6:e15:d427:f527%6

HTTPSのListenerを用意しておきたく、Ansible社にて公開されているPowerShellスクリプトを実行します。

https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1

上記Powershellスクリプトでは、以下の処理を実行してくれています。

  • WinRMサービスの起動
  • リモートからPowershell実行のための、Enable-PSRemotingの有効化
  • UAC権限に邪魔されないために、リモートUAC権限の無効化
  • 自己署名証明書の作成
  • Basic認証を有効化
  • CredSSP(Credential Security Support Provider)の有効化
  • Windows Firewallに、WinRMのHTTP利用ポートである 5985 で穴あけ
  • Windows Firewallに、WinRMのHTTPS利用ポートである 5986 で穴あけ

ダウンロードしてきて実行。

PS C:\Users\Administrator> $url = "https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"
PS C:\Users\Administrator> $file = "$env:temp\ConfigureRemotingForAnsible.ps1"
PS C:\Users\Administrator> (New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
PS C:\Users\Administrator> powershell.exe -ExecutionPolicy ByPass -File $file
Self-signed SSL certificate generated; thumbprint: 6F658CB46D7167184413DBD9680901CF3FAB7E2E


wxf                 : http://schemas.xmlsoap.org/ws/2004/09/transfer
a                   : http://schemas.xmlsoap.org/ws/2004/08/addressing
w                   : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
lang                : ja-JP
Address             : http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
ReferenceParameters : ReferenceParameters

OK

これでHTTPS用Listenerが用意できました。

PS C:\Users\Administrator> winrm enumerate winrm/config/Listener
Listener
    Address = *
    Transport = HTTP
    Port = 5985
    Hostname
    Enabled = true
    URLPrefix = wsman
    CertificateThumbprint
    ListeningOn = 127.0.0.1, 192.168.10.104, ::1, 2001:0:2841:aa90:442:3e69:2024:4e0e, 2405:6580:a0e0:6800:10c6:e15:d427:f527, fe80::5efe:192.168.10.104%11, fe80::442:3e69:2024:4e0e%2, fe80::10c6:e15:d427:f527%6

Listener
    Address = *
    Transport = HTTPS
    Port = 5986
    Hostname = WIN-E66MG3UGR83
    Enabled = true
    URLPrefix = wsman
    CertificateThumbprint = 6F658CB46D7167184413DBD9680901CF3FAB7E2E
    ListeningOn = 127.0.0.1, 192.168.10.104, ::1, 2001:0:2841:aa90:442:3e69:2024:4e0e, 2405:6580:a0e0:6800:10c6:e15:d427:f527, fe80::5efe:192.168.10.104%11, fe80::442:3e69:2024:4e0e%2, fe80::10c6:e15:d427:f527%6

別のWindows端末から、WinRMを設定したWindows2016サーバに、外部接続できるかどうか検証してみます。以下のコマンドにて、HTTPS通信で接続できます。尚、利用されている証明書は上記Ansible社スクリプトで作成された自己署名証明書となり、CommonNameはHostnameが利用されています。IPアドレス指定で接続する際には、証明書Verifyエラーが発生するので、それを無視する設定を入れています。

PS C:\Users\Administrator> $so = New-PsSessionOption –SkipCACheck -SkipCNCheck
PS C:\Users\Administrator> Enter-PSSession -ComputerName 192.168.10.104 -Credential 192.168.10.104 -UseSSL -SessionOption $so

Client側

続いてClient側の設定をして、WindowsサーバにAnsibleから接続確認してみます。

PythonからWinRMを操作できるパッケージ pywinrm をインストールします。バージョンは 0.3.0 以上である必要があります。

$ sudo pip3 install pywinrm
$ sudo pip3 list | grep pywinrm
pywinrm (0.3.0)

接続確認用のインベントリー・ファイルを用意します。

[windows]
192.168.10.104

[windows:vars]
ansible_user=Administrator
ansible_password=***************
ansible_connection=winrm
ansible_port=5986
ansible_winrm_server_cert_validation=ignore

Windows接続用に用意されているInventory Option一覧は、下記から確認できます。

Windows Remote Management — Ansible Documentation

接続できることを確認して、完了です。

$ ansible -i hosts all -m win_ping
192.168.10.104 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}