はじめに
-
2016/8/3 Serverspecでのテストを追記
-
ansibleも2.1になってWindows Serverのサポートも強化され、そろそろ手を出しても良さそうな感じになってきました。
-
ということで、ansibleを利用する前のWindowsServer側の設定とIISのインストール、Windowsグループ、ユーザの設定を自動構築し、serverspecでテストするところまでやってみたいと思います。
-
記事中で使ったplaybookのサンプルはGithub uzresk/ansible-serverspec-windows-samplesからどうぞ。
前提となる環境
- 以下の環境で動作確認をしています。
- 尚、本文中ではansible自体のインストール手順は割愛しています。
ansible実行ホスト
- CentOS6.7
- ansible2.1.0
- serverspec 2.36.0
- IP:192.168.1.99
ansible適用ホスト
- WindowsServer2012R2
- opentableのイメージを使ってvagrantで起動しました。
- IP:192.168.1.25
ansibleで環境構築
ansibleで環境構築する前準備
winrmを有効化する
- Ansible で Windows の構成管理を行う場合には Windows Remote Management( WinRM)を有効化する必要があるようです。
winrmを有効化するスクリプトの取得
- power shellを管理者権限で起動した後に以下のコマンドを使ってansibleが提供しているwinrmを有効化するスクリプトを取得します。
Invoke-WebRequest -Uri https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1 -OutFile ConfigureRemotingForAnsible.ps1
NetworkCategoryの変更
- Windows System PrepによるとNetworkCategoryをprivateに変更しないといけない模様
Set-NetConnectionProfile -InterfaceAlias (Get-NetConnectionProfile -IPv4Connectivity Internet).InterfaceAlias -NetworkCategory Private
- 確認するにはこのコマンド(NetworkCategoryがprivateになっていることを確認)
Get-NetConnectionProfile -IPv4Connectivity Internet
winrmを有効化
PS C:\Users\vagrant> powershell -ExecutionPolicy RemoteSigned .\ConfigureRemotingForAnsible.ps1
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 : en-US
Address : http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous
ReferenceParameters : ReferenceParameters
Ok.
windows serverでwinrmのポートを確認する
- Powershellを起動して以下のコマンドを実行
- 5986と5985ポートが空いているのがわかりますね。ちなみに5986はhttps、5985はhttpです。
Get-Item WSMan:\localhost\Listener\*\Port
WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Listener\Listener_1305953032
Type Name SourceOfValue Value
---- ---- ------------- -----
System.String Port 5986
WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Listener\Listener_1084132640
Type Name SourceOfValue Value
---- ---- ------------- -----
System.String Port 5985
pipをインストール
get-pip.pyを取得
curl -x http://PROXY_HOST:PROXY_PORT -O https://bootstrap.pypa.io/get-pip.py
pipをインストール
- プロキシを設定
export http_proxy=http://PROXY_HOST:PROXY_PORT
export https_proxy=http://PROXY_HOST:PROXY_PORT
- インストール
python get-pip.py
winrmをインストール
pip install pywinrm
winrm経由でansibleが実行できるかを確認する
プロキシの除外設定
- winrmはhttp/https通信であるため、プロキシの設定を行っている場合は、ansible対象ホストを除外設定する必要がある。
export no_proxy="192.168.1.25"
inventryファイル(hosts)の設定
- 余談ですが、ansible2.0からはansible_ssh_userなどはdeprecatedになって、sshを取った変数名が推奨されます。
- ansible windows inventory
[windows]
192.168.1.25
[windows:vars]
ansible_user=vagrant
ansible_password=vagrant
ansible_port=5985
ansible_connection=winrm
- https(5986)で接続するには以下のように証明書の検証をしないようにinventoryファイルを構成すれば接続できます。(pythonの2.7.9から証明書の検証が行われるようになったそうです)
[windows]
192.168.1.25
[windows:vars]
ansible_user=vagrant
ansible_password=vagrant
ansible_port=5986
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore
win_pingを使って疎通確認
[root@52ae470c2708 scripts]# ansible -i hosts windows -m win_ping
192.168.1.25 | SUCCESS => {
"changed": false,
"ping": "pong"
}
WindowsServerの設定をansibleで!
- ansibleでwindows serverを構成するためのモジュール群は以下に記載があります。
- Windows Modules
IISをインストールしてみる
- win_featureに記載があるplaybookを使ってインストールしてみます。
- 私の環境ではうまくいかず、include_sub_features: noとして実行したところうまく動きました。
- 参考:win_feature for iis with sub features: yes fails on 2012 R2 #3640
[root@52ae470c2708 ansible-scripts]# cat roles/iis/tasks/main.yml
- name: Install IIS
win_feature:
name: "Web-Server"
state: present
restart: yes
include_sub_features: no
include_management_tools: yes
[root@52ae470c2708 ansible-scripts]# ansible-playbook -i hosts site.yml
PLAY [windows] *****************************************************************
TASK [iis : Install IIS] *******************************************************
changed: [192.168.1.25]
PLAY RECAP *********************************************************************
192.168.1.25 : ok=1 changed=1 unreachable=0 failed=0
- http://192.168.1.25/にアクセスすると無事IISのデフォルトページが表示されました。
グループとユーザをつくってみよう
グループを作成する
- グループを作成するにはwin_groupモジュールを使います。
[root@52ae470c2708 ansible-scripts]# cat roles/group/tasks/main.yml
---
- name: create test-group
win_group:
name: test-group
descriptsion: test group
state: present
ユーザを作成する
- ユーザを作成するにはwin_userモジュールを使います。
[root@52ae470c2708 ansible-scripts]# cat roles/user/tasks/main.yml
---
- name: Add User
win_user:
name: test
password: "@Password1"
groups: ["test-group"]
- パスワードポリシーに違反した場合はplaybook実行時に以下のようなエラーがでます
TASK [user : Add User] *********************************************************
fatal: [192.168.1.25]: FAILED! => {"changed": false, "failed": true, "msg": "Exception calling \"SetInfo\" with \"0\" argument(s): \"The password does not meet the password policy requirements. Check the minimum password length, password complexity and password history requirements.\r\n\""}
- 実行後、サーバマネージャ - コンピュータの管理 - ローカルユーザとグループからユーザとグループが追加できていることが確認できると思います。
Serverspec
Serverspecを使ってwindowsをテストする為の前準備
- Serverspecもansible同様winrmを使って接続します。Linuxをテストする時と比べて必要になるのはwinrmのモジュールのみです。
winrmをインストールする
gem install winrm
接続の仕方もwinrm経由に変更
- ここでは、TARGET_HOST、USER、PASSWORDを環境変数から取得しwinrmの接続で利用しています。
[root@52ae470c2708 serverspec]# cat spec/spec_helper.rb
require 'serverspec'
require 'net/ssh'
require 'winrm'
set :backend, :winrm
RSpec.configure do |c|
host = ENV['TARGET_HOST']
user = ENV['USER'].dup
pass = ENV['PASSWORD'].dup
puts user
puts pass
endpoint = "http://" + host + ":5985/wsman"
c.winrm = ::WinRM::WinRMWebService.new(endpoint, :ssl, :user => user, :pass => pass)
c.winrm.set_timeout 300 # 5 minutes max timeout for any operation
end
テストしてみよう
IISがインストールされていることをテストする
- ここではインストールされているか否かとポートがListenしているか否かをテストしてみたいと思います。
- インストールされているか否かはServerspecのResourceTypeにwindows_featureがあるのでこれを利用します。ポートがListendしているか否かについてはLinux同様portを利用します。
iis_spec.rb
require 'spec_helper'
describe windows_feature('Web-Server') do
it { should be_installed.by("powershell") }
end
describe port(80) do
it { should be_listening.with('tcp') }
end
グループ、ユーザのテスト
group_spec.rb
require 'spec_helper'
describe group('test-group') do
it { should exist }
end
user_spec.rb
require 'spec_helper'
describe user('test') do
it { should exist }
it { should belong_to_group 'test-group' }
end
実行
- 全部無事テストが通りましたね。
[root@52ae470c2708 windows]# rake spec
(in /scripts/ansible-serverspec-windows-samples/first-step/serverspec)
env TARGET_HOST=192.168.1.25 /root/.rbenv/versions/2.3.1/bin/ruby -I/root/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rspec-support-3.4.1/lib:/root/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/lib /root/.rbenv/versions/2.3.1/lib/ruby/gems/2.3.0/gems/rspec-core-3.4.4/exe/rspec --pattern spec/\{windows\}/\*_spec.rb
vagrant
vagrant
Group "test-group"
WARN WinRM::WinRMWebService : WinRM::WinRMWebService#run_powershell_script is deprecated. Use WinRM::CommandExecutor#run_powershell_script instead
should exist
Windows feature "Web-Server"
WARN WinRM::WinRMWebService : WinRM::WinRMWebService#run_powershell_script is deprecated. Use WinRM::CommandExecutor#run_powershell_script instead
should be installed by "powershell"
Port "80"
WARN WinRM::WinRMWebService : WinRM::WinRMWebService#run_powershell_script is deprecated. Use WinRM::CommandExecutor#run_powershell_script instead
should be listening with tcp
User "test"
WARN WinRM::WinRMWebService : WinRM::WinRMWebService#run_powershell_script is deprecated. Use WinRM::CommandExecutor#run_powershell_script instead
should exist
WARN WinRM::WinRMWebService : WinRM::WinRMWebService#run_powershell_script is deprecated. Use WinRM::CommandExecutor#run_powershell_script instead
should belong to group "test-group"
Finished in 2.35 seconds (files took 0.48295 seconds to load)
5 examples, 0 failures
おわりに
- はじめる前はWinRMとか面倒だなーとか色々思いましたが拍子抜けするほど簡単にできましたので二の足を踏んでいる人はまずはやってみるとよさそうです。
- ansibleは1.7でサポート開始されたころよりもwindows系のモジュールが増えたことでこれからますます活躍の場が増えていきそうですね。
- ansibleはwindowsとlinuxでモジュールが別れていますが、serverspecは一つのResourceTypeで複数のOSをカバーできるようなので学習コストが少なく良い感じですね。