Vagrant で作成した Windows ゲストに Ansible でプロビジョニングする最小設定

Vagrant で作成した Windows ゲストに Ansible でプロビジョニングする際の **最小設定** についてです。
[ググって出てきた直近の記事](http://dackdive.hateblo.jp/entry/2016/03/11/094501) の写経で上手くいかなかったため色々試行錯誤した結果を残しておきます。

## 各種ツールのバージョン

- Python: 2.7.11
- Ansible: 2.1.0.0
- Vagrant: 1.8.4
- Virtual Box: 5.0.24 r108355

## Vagrantfile

```ruby
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "chusiang/win10-x64-ansible"
  config.vm.guest = "windows"
  config.vm.communicator = "winrm"

  config.winrm.username = "IEUser"
  config.winrm.password = "Passw0rd!"

  # 状況に合わせて
  # config.vm.provider "virtualbox" do |vb|
  #   vb.memory = "2048"
  #   vb.customize ["modifyvm", :id, "--vram", "128"]
  #   vb.customize ["modifyvm", :id, "--clipboard", "bidirectional"]
  # end

  # 必要であれば
  config.vm.network "forwarded_port", guest: 3389, host: 3389, id: "rdp", auto_correct: true

  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "playbook.yml"
    # ansible.inventory_path = 指定しない
    ansible.host_vars = {
      "default" => {
        "ansible_ssh_port" => 55986,
        "ansible_winrm_server_cert_validation" => "ignore"
      }
    }
    # ansible.verbose = "v"
  end
end
```

### config.vm.box

既存の記事では [modernIE](https://atlas.hashicorp.com/modernIE/) を利用しているようなのですが、
このグループが実はMicrosoft公式ではなく個人の開発者が作成していたものであり、
Microsoftが公式を作成したため2016年7月をもって開発終了、取得が不可能になってしまいました。 [^1]

また、公式の方は [Microsoft](https://atlas.hashicorp.com/Microsoft/) にあるのですが、WinRM のセットアップがなされていません。

今回は [Atlas](https://atlas.hashicorp.com/boxes/search) を検索して WinRM セットアップ済みとなっているものを利用しています。

### config.vm.guest

ググった記事ではどれもが記述するように書いてあるのですが、消してもいけました。

ただし、 Vagrant の [ドキュメント](https://www.vagrantup.com/docs/vagrantfile/machine_settings.html) には必要とあるので、
より複雑なことをするためには必要になるかもしれないので念のために記述しておきます。

### config.vm.communicator

Windows との接続に SSH ではなく、 WinRM を使うために記述します。

### config.winrm.username / config.winrm.password

WinRM での接続の際に利用するユーザー・パスワードです。 

Windows の Vagrant Box には、 Vagrant Box お約束 [^2] の `vagrant/vagrant` が用意されていないため、 Windows VM でお約束の `IEUser/Passw0rd!` を記述します。

### config.vm.provider

ここの中身は都合に合わせて設定します。必須ではありません。

### config.vm.network

`config.vm.communicator` に `winrm` を記述しておくと WinRM で利用する 5985 と 5986 のポートフォーワーディングが自動で行われます。

しかし、 `vagrant rdp` で利用する rdp ポートは自動で行われないため記述しておきます。必須ではありません。

### config.vm.provision

#### ansible.playbook

実行する Playbook のパスです。
Playbook の内容としては今回は接続を確認するだけのもののため以下のようにしています。

```yaml
---
  - hosts: default
    tasks:
      - action: win_ping
```

`hosts` には Vagrant がデフォルトで指定する `default` を設定しています。

#### ansible.inventory_path

Ansible のインベントリファイルのパスを指定できますが、今回は指定せずに Vagrant が自動生成するものを利用します。

自前のインベントリファイルを利用すると Ansible 実行時に `--extra-vars='ansible_ssh_user=vagrant'` などと指定されて若干面倒なことになります。

#### ansible.host_vars

これを指定しないで実行すると自動生成されたインベントリファイルは以下のようになります。

```
default ansible_connection=winrm ansible_ssh_host=127.0.0.1 ansible_ssh_port=55985 ansible_ssh_user='IEUser' ansible_ssh_pass='Passw0rd!' 
```

これの実行結果は

```
fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "ssl: [SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:590)", "unreachable": true}
```

となるように、 SSL に対応していないポートに SSL 接続してしまっているので、

```ruby
"ansible_ssh_port" => 55986
```

と SSL 接続対応しているポートに差し替えます。

さらに上記だけだと

```
fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "ssl: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)", "unreachable": true}
```

という証明書エラーが出てしまうので、

```ruby
"ansible_winrm_server_cert_validation" => "ignore"
```

とすることで、証明書エラーを回避します。

#### ansible.verbose

Ansible のログレベルの設定です。必要に応じて `v` を増やしてください。

## 成果物

https://github.com/kobanyan/ansible-vagrant-windows-guest-sample

<div class="github-card" data-github="kobanyan/ansible-vagrant-windows-guest-sample" data-width="400" data-height="" data-theme="default"></div>
<script src="//cdn.jsdelivr.net/github-cards/latest/widget.js"></script>

[^1]: https://joecod.es/retiring-modernie-vagrant-boxes/
[^2]: https://www.vagrantup.com/docs/boxes/base.html