ライトウェルブログ

2022/01/07証明書認証でWinRM通信してみた!

こんにちは、ライトウェルAnsibleチームの増田です。

 

突然ですが、みなさんAnsibleでWindows仮想マシンへの通信時の認証方法はどうされていますか?
Basic認証の利用が一般的かと思いますが、
ユーザ、パスワードの入力だけだとやっぱり不安…
という方もいらっしゃるのではないでしょうか??

そこで2022年最初のブログでは、
AnsibleからWindows仮想マシンへのCertificate認証で通信してみた件についてまとめます!

Certificate認証についてですが、
Anisbleの公式ドキュメントを参考に検証を進めました。

大まかですが、作業の流れは下記のとおりです。

  1. OpenSSLで証明書(cert.penおよびcert_key.pem)の作成
  2. Windows仮想マシンに①で作成した証明書をインポートする
  3. 証明書をユーザアカウントにマッピングする
  4. WinRMの証明書通信の有効化
  5. AnsibleからWindows仮想マシンへwin_pingしてみる

 

1.OpenSSLで証明書(cert.pen/cert_key.pem)の作成

証明書はOpenSSLやPowerShellで作成可能です。
今回はAnsibleサーバとは別でOpenSSLサーバを構築し、証明書の作成を行いました。

  • OpenSSLサーバにログインし、以下のコマンドを実行します。
    ここではansibleというユーザ用の証明書を作成します。
#ユーザ名の設定
USERNAME="ansbile"

#openssl.confの作成
cat > openssl.conf << EOL
distinguished_name = req_distinguished_name
[req_distinguished_name]
[v3_req_client]
extendedKeyUsage = clientAuth
subjectAltName = otherName:1.3.6.1.4.1.311.20.2.3;UTF8:$USERNAME@localhost
EOL

#環境変数OPENSSL_CONFを定義する
export OPENSSL_CONF=openssl.conf

#SSL証明書の作成
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -out cert.pem -outform PEM -keyout cert_key.pem -subj "/CN=$USERNAME" -extensions v3_req_client

#openssl.confの削除
rm openssl.conf

  • 証明書が作成されていることを確認します。

 

2.Windows仮想マシンに①で作成した証明書をインポートする

  • OpenSSLサーバで作成した証明書をWinSCP等で取り出し、
    対象のWindows仮想マシンに配置します。今回はC:\tempに配置しました。

  • Powershellを起動し、OpenSSLサーバで発行した証明書を
    ローカルコンピュータの証明書ストアの信頼されたルート証明機関にインポートを行います。
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import("C:\temp\cert.pem")
$store_name = [System.Security.Cryptography.X509Certificates.StoreName]::Root
$store_location = [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
$store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $store_name, $store_location
$store.Open("MaxAllowed")
$store.Add($cert)
$store.Close()

  • 続いて、クライアント証明書の公開鍵を
    ローカルコンピュータの証明書ストアの信頼されたユーザにインポートします。
$cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2
$cert.Import("C:\temp\cert.pem")
$store_name = [System.Security.Cryptography.X509Certificates.StoreName]::TrustedPeople
$store_location = [System.Security.Cryptography.X509Certificates.StoreLocation]::LocalMachine
$store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList $store_name, $store_location
$store.Open("MaxAllowed")
$store.Add($cert)
$store.Close()

 

3.証明書をユーザアカウントにマッピングする

  • 証明書をインポートしたら、これをansibleというユーザに対してマッピングします。
    (手順1の証明書作成時に指定したユーザに対してマッピングを行います)
$username = "ansible"
$password = ConvertTo-SecureString -String Password123 -AsPlainText -Force
$credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password

  • ansibleというユーザーの証明書の拇印を確認し、WinRMに登録を行います。
$thumbprint = (Get-ChildItem -Path cert:\LocalMachine\root | Where-Object { $_.Subject -eq "CN=$username" }).Thumbprint

New-Item -Path WSMan:\localhost\ClientCertificate `
     -Subject "$username@localhost" `
     -URI * `
     -Issuer $thumbprint `
     -Credential $credential `
     -Force

  • 証明書ストアで信頼されたルート証明機関と信頼されたユーザを確認してみると
    発行先・発行元がansibleとなっている証明書が登録されていることが確認できました。

 

4.WinRMの証明書通信の有効化

  • WinRMの証明書認証はデフォルトで無効となっています。
    以下のコマンドを実行し証明書認証を有効にします。
winrm set winrm/config/service/Auth '@{Certificate="true"}'

<デフォルト>

<コマンド実行後>

  • 基本認証でWinRM通信が行われないように、基本認証は無効化しました。
winrm set winrm/config/service/Auth '@{Basic="false"}'

 

5.AnsibleからWindows仮想マシンへwin_pingしてみる

  • inventoryに証明書認証時に必要な以下の変数を記載します。
    証明書認証でWinRM通信するので、ansible_userやansible_passwordは記載していません!!
[windows]
172.16.186.141

[windows:vars]
ansible_connection=winrm
ansible_port=5986
ansible_winrm_server_cert_validation=ignore
ansible_winrm_transport=certificate
ansible_winrm_cert_pem=/root/.ssh/cert.pem
ansible_winrm_cert_key_pem=/root/.ssh/cert_key.pem

  • win_pingモジュールを実行します。
ansible windows -i inventory -m win_ping

成功しました~!!😆🎉
基本認証はFalseにしているし、この成功はちゃんと証明書認証で
WinRM通信できているってことですよね!!!?

さらに、WinRMの暗号化されていないデータの転送を許可しない設定をしても
win_pingが成功することも確認できました!
これでセキュリティ対策もバッチリな状態でAnsibleを利用できますね🙂

 

おわりに

証明書認証を使ったWinRMについて、ハードルが高そうなイメージがありましたが、
情報が少ないだけで、そこまで難しいものではないと感じました。

よりセキュアにAnsibleを活用していただくために、
証明書認証を使う方法もあるということをこれからお伝えしていけたらいいなと思っています。

 

トップページに戻る