このエラーが発生する原因
Windowsホストを対象にAnsibleプレイブックを実行すると、次のエラーが表示されます:
fatal: [win_host]: UNREACHABLE! => {"msg": "ssl: HTTPSConnectionPool(host='192.168.1.10', port=5986): Max retries exceeded with url: /wsman"}
接続がそもそも確立されていません。原因は主に3つ考えられます:ポートが開いていない、SSLハンドシェイクが失敗した、またはAnsibleが証明書を信頼していない。状況に合ったものを選び、以下の手順を進めてください。
根本原因
- WindowsホストでWinRM HTTPSリスナーが設定されていない
- ポート5986がWindowsファイアウォールまたは上流のネットワークファイアウォールでブロックされている
- 自己署名証明書がAnsibleに信頼されていない(
validate_certs: falseが未設定) - Ansibleコントローラーに
pywinrmパッケージがインストールされていないか古い - インベントリの
ansible_winrm_transportまたは接続変数が間違っている
クイックフィックス:テスト用に証明書検証を無効化する
社内ラボやステージング環境の多くは自己署名証明書を使用しています。デフォルトでは、Ansibleはそのような接続を完全に拒否します。診断中に証明書検証を回避するため、インベントリまたはgroup_varsに以下を追加してください:
[windows:vars]
ansible_user=Administrator
ansible_password=YourPassword
ansible_connection=winrm
ansible_winrm_scheme=https
ansible_port=5986
ansible_winrm_transport=ntlm
ansible_winrm_server_cert_validation=ignore
次に、簡単な接続テストを実行します:
ansible win_host -m win_ping
これが成功した場合、問題はSSL証明書のみです。それ以外の原因はありません。恒久的な修正のセクションに進んでください。
ステップ1:WinRMが実際に動作しているか確認する
WindowsマシンにRDPまたはコンソールでアクセスし、PowerShellで以下を実行します:
Get-Service WinRM
winrm enumerate winrm/config/listener
ポート5986でTransport=HTTPSを示すリスナーが必要です。出力がポート5985のHTTPのみを示している場合、HTTPSリスナーがセットアップされていません。
自己署名証明書を使用してWinRM HTTPSを一度に立ち上げます:
# AdministratorとしてWindowsホストでRun
$cert = New-SelfSignedCertificate -DnsName "$(hostname)" -CertStoreLocation Cert:\LocalMachine\My
$thumbprint = $cert.Thumbprint
New-WSManInstance -ResourceURI winrm/config/listener `
-SelectorSet @{Address="*"; Transport="HTTPS"} `
-ValueSet @{CertificateThumbprint=$thumbprint}
# 代わりにAnsibleが管理するセットアップスクリプトを使用することを推奨:
$url = "https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1"
$file = "$env:temp\ConfigureRemotingForAnsible.ps1"
(New-Object -TypeName System.Net.WebClient).DownloadFile($url, $file)
powershell.exe -ExecutionPolicy ByPass -File $file
Ansibleのスクリプトは証明書の作成、リスナーのセットアップ、ファイアウォールルールを一度に処理します。複数のホストをセットアップする場合に特に便利です。
ステップ2:Windowsファイアウォールでポート5986を開放する
New-NetFirewallRule -DisplayName "Ansible WinRM HTTPS" `
-Direction Inbound `
-Protocol TCP `
-LocalPort 5986 `
-Action Allow
AWS、Azure、またはGCPで実行している場合は、セキュリティグループまたはNSGも忘れずに確認してください。クラウドレイヤーがVPCレベルでトラフィックをブロックしている場合、Windowsファイアウォールのルールは意味をなしません。
Ansibleコントローラーから、ポート5986が実際に到達可能かテストします:
nc -zv 192.168.1.10 5986
# または
curl -k https://192.168.1.10:5986/wsman
curlからHTTP 401や500が返ってきた場合、ポートは開いておりWinRMは動作しています。接続拒否またはタイムアウトの場合は、ファイアウォールがまだブロックしています。
ステップ3:AnsibleコントローラーにpywinrmをInstallする
pywinrmがなければWinRM接続はできません。Ansibleがプロトコルを処理するためにこのパッケージが必要です:
pip install pywinrm
pip install pywinrm[kerberos] # Kerberosを使用するドメイン環境
pip install pywinrm[credssp] # CredSSP認証を使用する場合
インストールされているか確認し、バージョンをチェックします(0.4.x以降が必要):
pip show pywinrm
恒久的な修正:Windows証明書を信頼する
本番環境にserver_cert_validation=ignoreを適用するのは危険です。自動化に対する中間者攻撃の扉を開くことになります。正しい修正は、WindowsホストのCert書をエクスポートし、Ansibleコントローラーの信頼ストアに追加することです。
Windowsホストで証明書をエクスポートします:
$cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -match "$(hostname)"}
Export-Certificate -Cert $cert -FilePath C:\winrm_cert.cer -Type CERT
winrm_cert.cerをAnsibleコントローラーにコピーし(scp、SMB共有など)、変換してインストールします:
# .cer(DER形式)をPEMに変換
openssl x509 -inform DER -in winrm_cert.cer -out winrm_cert.pem
# Ubuntu/Debian
cp winrm_cert.pem /usr/local/share/ca-certificates/winrm_cert.crt
update-ca-certificates
# RHEL/CentOS
cp winrm_cert.pem /etc/pki/ca-trust/source/anchors/
update-ca-trust extract
次に、インベントリを更新して適切に検証するようにします:
[windows:vars]
ansible_winrm_server_cert_validation=validate
ansible_winrm_ca_trust_path=/path/to/winrm_cert.pem
参考:完全な動作インベントリ
以下はHTTPS上のNTLMで動作する完全なインベントリです。コピーして適宜修正してください:
[windows]
win_host ansible_host=192.168.1.10
[windows:vars]
ansible_user=Administrator
ansible_password=YourSecurePassword
ansible_connection=winrm
ansible_winrm_scheme=https
ansible_port=5986
ansible_winrm_transport=ntlm
ansible_winrm_server_cert_validation=ignore
Active Directoryのドメイン参加ホストの場合はKerberosに切り替えてください。より安全でトークン委任を適切に処理します:
ansible_winrm_transport=kerberos
ansible_user=user@DOMAIN.COM
修正を確認する
まずwin_pingから始めます。AnsibleがWindowsに対して持つ最も軽量な接続テストです:
ansible win_host -m win_ping
期待される出力:
win_host | SUCCESS => {
"changed": false,
"ping": "pong"
}
pingが通ったら、実際のコマンドを実行してスタック全体がエンドツーエンドで動作することを確認します:
ansible win_host -m win_shell -a "Get-ComputerInfo | Select-Object WindowsProductName"
これらすべての手順を実施してもSSLエラーが発生する場合は、詳細度を4に上げてハンドシェイクのトレースをgrepします:
ansible win_host -m win_ping -vvvv 2>&1 | grep -i ssl
ハンドシェイクの出力から、証明書のCN不一致、期限切れの証明書、信頼されていないCAなど、失敗している箇所が正確にわかります。

