AnsibleでWindows ServerにActive Directoryを構成する

# はじめに

前回の実践編がWindowsクライアントを想定していたので、今回はWindowsサーバを想定したものとしてActive Directory（正式にはActive Directory Domain Services）をインストールし構成する。

操作する側はAnsible 1.7.1だが、今回はWindows Server 2012 R2を操作する。
使用するインベントリファイルは以下の通り。

```txt:hosts
[winserver]
10.0.2.173

[winserver:vars]
ansible_ssh_user=Administrator
ansible_ssh_pass=<Administratorユーザのパスワード>
ansible_ssh_port=5986
ansible_connection=winrm
```

## これまでのお話

準備編：[AnsibleでWindowsを操作する準備をする](http://qiita.com/yunano/items/f9d5652a296931a09a70)
実践編1： [AnsibleでChocolateyを使ってWindowsアプリをインストールする](http://qiita.com/yunano/items/5677685b61816f6e62a3)

# Active Directory Domain Servicesの構成

Active Directory Domain Servicesのインストールにはwin_featureモジュールを使用する。
nameに指定すべき名前はPowerShellで`Get-WindowsFeature`を実行すると得られる（Name欄）。
ちなみに`Get-WindowsFeature`はWindows 8.1等のWindowsクライアントOSでは使用できないが、1.7.1時点ではそもそも[WindowsクライアントOSに対してwin_featureモジュールは使用できないようだ](https://github.com/ansible/ansible/issues/8798)。

```
# ansible winserver -i hosts -m win_feature -a 'name=AD-Domain-Services include_management_tools=yes'
```

この後構成が終わって再起動が掛かった後、ネットワークプロファイルがドメインプロファイルに変更されるので、ファイアウォールにドメインプロファイル用のWinRMの穴を開けて、再起動後も引き続きAnsibleと通信できるようにしておく。

```
# ansible winserver -i hosts -m raw -a 'netsh advfirewall firewall add rule Profile=domain name="Allow WinRM HTTPS" d=in localport=5986 protocol=TCP action=allow'
```

Windows Server 2008まではActive Directory Domain Servicesの構成にはdcpromoを使用したが、2012ではdcpromoがdeprecatedになっているため、PowerShellの以下のコマンドレットのいずれかを使用する。

* Install-ADDSForest（新しいフォレストを追加する）
* Install-ADDSDomain（新しいドメインを既存のフォレストに追加する）
* Install-ADDSDomainController（既存のドメインにドメインコントローラーを追加する）

今回は最初のActive Directory Domain Servicesサーバを立てることにするのでInstall-ADDSForestを使用する。

どのようなオプションでInstall-ADDSForestなどを実行すべきかを得る方法は以下のURLの「スクリプトの表示」の箇所を参照のこと。
http://dev.classmethod.jp/server-side/server/adonaws/

[前回](http://qiita.com/yunano/items/5677685b61816f6e62a3)書いた通り、PowerShellコマンドレットの実行にはrawモジュールではエラーになり、scriptモジュールを使用する必要がある。

今回はWindows側に実行させるps1スクリプトを作るところからやってみよう。
これはlocal_actionモジュールでローカルに対してtemplateモジュールを使用することで達成した。どうやらWindows側に影響を与えないlocal_actionモジュールなどは普通に使用できるようだ。

この辺りはPlaybookにしないと面倒なので、Active Directory Domain Servicesのインストールの箇所からまとめて以下のようになった。

```yaml:adds.yml
- hosts: winserver
  gather_facts: no
  vars:
    ad_opts:
      DomainName: hogehoge.localdomain
      DomainMode: Win2012R2
      ForestMode: Win2012R2
      SafeModeAdministratorPassword: HOGEhoge1
      DatabasePath: 'C:\ADDS\NTDS'
      LogPath: 'C:\ADDS\NTDS'
      SysvolPath: 'C:\ADDS\SYSVOL'
  tasks:
    - win_feature:
        name: AD-Domain-Services
        include_management_tools: yes
    - raw: 'netsh advfirewall firewall add rule Profile=domain name="Allow WinRM HTTPS" d=in localport=5986 protocol=TCP action=allow'
    - local_action: template src=Install-ADDSForest.ps1.j2 dest=./Install-ADDSForest.ps1
    - script: 'Install-ADDSForest.ps1'
```

ps1スクリプトのテンプレートファイルは以下のようになる。
SafeModeAdministratorPasswordオプションだけそのままでは渡せないので条件分岐している。
（ちなみに、SafeModeAdministratorPasswordで指定するパスワードは「ディレクトリ復元モード」時にのみ使用するために新しく作るパスワードであり、従来のAdministatorユーザのものではない）

```Install-ADDSForest.ps1.j2
Install-ADDSForest -Force
{%- for key, value in ad_opts.iteritems() -%}
{%- if key == 'SafeModeAdministratorPassword' %}
 -{{ key }} (ConvertTo-SecureString -AsPlainText -Force -String "{{ value }}")
{%- else %}
 -{{ key }} "{{ value }}"
{%- endif -%}
{%- endfor -%}
```

以下を実行する。

```
# ansible-playbook -i hosts adds.yml
```

# まとめ

* win_featureモジュールはWindows Serverに対してのみ使用できる。nameに指定すべき名前はPowerShellのGet-WindowsFeatureコマンドレットをWindows Server上で使用すると得られる。
* local_actionモジュールのような、Windows側に影響を与えないようなモジュールは普通に使用できる。