AWS WorkspacesでGoogle Authenticationを使う

# 概要
AWS WorkspaceでMFAを実現する方法です。
本稿では、パスワード、クライアント証明書、Google Authentication (OTP) の3要素で認証後 Workspacesにログインできるように設定してみます。
以下に記載の情報は2018/2/11時点です。

# 構築手順
## 参考資料
以下の資料には必要な情報がほぼすべて書いてありますので、これを読めばそれほど苦労せずに構築できます。
- [GoogleAuthenticatorを利用してAmazon WorkSpacesへ多要素認証ログインする](http://blog.enokawa.co/2018/01/11/login-to-amazon-workspaces-with-google-authenticator/)
- [Google Authenticator を使って Amazon WorkSpaces に多要素認証ログイン](http://aws.typepad.com/sajp/2014/10/google-authenticator.html)
基本的に、前者の資料のほうが新しいですので、そちらをベースに構築をすすめ、必要に応じて後者の資料を参照するのがよいかと思います。
これらの資料には書いていないのですが、構築中に以下のライブラリをコピーする必要があります。

```
$ sudo cp /usr/local/lib/security/pam_google_authenticator.so /usr/lib64/security
```

## ネットワークを構築
* VPCを作成
* VPC内にサブネットを3つ作成
1つはWorkspacesのWindows10、残りの2つはActiveDirectoryとRADIUSで使います。Workspacesはサブネットを分ける必要はありませんので、最低2つのサブネットでも大丈夫です。

## RADIUSサーバーを構築
* EC2でAmazon Linux 2でインスタンスを作成します。小規模な運用ならt2.microで十分いけます。
* 必要なパッケージをインストールします。

```
$ sudo yum install freeradius freeradius-utils git gcc pam-devel qrencode qrencode-libs qrencode-devel autoconf automake libtool
```

* Google Authenticatorのファイルを構築

```
$ cd
$ git clone https://github.com/google/google-authenticator-libpam.git
$ cd /home/ec2-user/google-authenticator-libpam/
$ ./bootstrap.sh
$ ./configure
$ make
$ sudo make install
```

* RADIUSのグループを作成

```
$ sudo groupadd radius-enabled
```

* /etc/raddb/radiusd.conf を変更

```console:修正前
user = radiusd
group = radiusd
```

```console:修正後
user = root
group = root
```

* /etc/raddb/usersを変更

```console:追加
DEFAULT    Group != "radius-enabled", Auth-Type := Reject
           Reply-Message = "Your account has been disabled."
DEFAULT    Auth-Type := PAM
```

* /etc/raddb/sites-available/defaultを変更

```console:修正前
# pam
```

```console:修正後
pam
```

* /etc/pam.d/radiusdを変更

```console:修正前
#%PAM-1.0
auth       include     password-auth
account    required    pam_nologin.so
account    include     password-auth
password   include     password-auth
session    include     password-auth
```

```console:修正後
#%PAM-1.0
#auth       include     password-auth
#account    required    pam_nologin.so
#account    include     password-auth
#password   include     password-auth
#session    include     password-auth
auth requisite pam_google_authenticator.so
account required pam_permit.so
session required pam_permit.so
```

* /etc/raddb/clients.confを変更

```console:追加
client from-vpc {
    ipaddr     = 172.16.0.0
    netmask    = 16
    secret     = testing123
    shortname  = from-vpc
}
```

* モジュール関係

```console
$ sudo ln -s /etc/raddb/mods-available/pam /etc/raddb/mods-enabled/pam
$ sudo cp /usr/local/lib/security/pam_google_authenticator.so /usr/lib64/security
```

* サービスを起動

```console
$ sudo systemctl enable radiusd
$ sudo systemctl start radiusd
$ sudo systemctl status radiusd
```

status表示でおかしなところがないか確認してください。
以下のような表示になっていれば問題ないです。

```console
Active: active (running) since Mon 2018-02-12 04:53:34 UTC; 3min 59s ago
```

* ユーザーを登録

```console
$ sudo useradd -g radius-enabled mhishi
$ sudo -u mhishi /usr/local/bin/google-authenticator
```
いろいろと質問されるので、基本的に ```y``` で答えていけばよいですが、1.5分のwindowを4分にのばしますか、という質問には```n```とするのがよいかと思います。サーバーもスマホも時刻は十分に正確ですので。
登録が終わったらスマホにGoogle Authenticatorをセットアップしてください。

* テストしてみます

```console
$ radtest mhishi 000000 172.16.2.206 10 testing123
Sent Access-Request Id 66 from 0.0.0.0:53281 to 172.16.2.206:1812 length 76
        User-Name = "mhishi"
        User-Password = "000000"
        NAS-IP-Address = 172.16.2.206
        NAS-Port = 10
        Message-Authenticator = 0x00
        Cleartext-Password = "000000"
Received Access-Accept Id 66 from 172.16.2.206:1812 to 0.0.0.0:0 length 20
```

コマンド中の```000000```のところはスマホに表示されているOTPを入力してください。上記のように、正常に認証されると```Access-Accept```と出力されますが、認証できない場合は```Access-Reject```になります。

## Directoryを構築
* Active Directoryを構築

AWS Consoleから、Workspacesへ移動し、Directory からMicrosoft ADを作成します。なお、Simple ADはMFAに対応していません。
ADの作成画面では、DNSはpublicに利用可能なものである必要はありません。適当にしてください。また、管理者は表示されている通り```Admin```ですので注意が必要です。
VPCとサブネットは、先ほど作成したものを指定してください。

* AD Connectorを構築

同様にConsoleからAD Connectorを作成し、先ほど作成したMicrosoft ADに接続するよう指定してください。
Connectorが作成でしたら、そのConnectorをActionから登録してください。Console上では、Microsoft ADとAD Connectorが表示されていますが、この段階でAD Connectorのほうが登録済み、Microsoft ADは登録されていない状態になっている必要があります。

* AD管理環境を構築

運用を楽にするため、ADを管理するための環境を構築します。
EC2でWindows Serverをセットアップしてください。t2.microで問題ありません。Windowsが起動したら、AD ManagementのFeatureを追加してください。さらに、このWindowsを先ほど構築したMicrosoft ADに参加させます。

* ユーザーを登録

さきほどのWindows ServerからADに接続し、RADIUSと同じユーザーを作成してください。

* Workspacesを作成

AWS ConsoleからWorkspacesを作成してください。特別難しい設定はありません。
作成後、Active Directoryのユーザーでログインすることができることを確認してください。（MFAはまだ使えませんが）

* RADIUSと接続しGoogle Authenticatorを有効化

AWS ConsoleからRADIUSサーバーに紐づいているセキュリティグループを編集し、AD ConnectorのIPアドレスからUDP 1812ポートへのアクセスを許可します。
AWS ConsoleからWorkspacesへ移動し、ディレクトリ画面に行きます。ここでAD Connectorをチェックし詳細の更新を選択します。
詳細画面にMFA認証セクションがあるので、そこに必要事項を入力します。プロトコルはPAPで、タイムアウトは10秒、試行回数は3回ぐらいを指定しておきます。
再度Workspacesのログイン画面に行くと、OTPを入力するフィールドが増えているはずです。

* クライアント証明書でのログインを有効化

まず、opensslなどでオレオレ証明書を作成します(すでにPKIの仕組みをお持ちのかたは、そちらをお使いください)。証明書ができたら、Root CAの証明書をパソコンの信頼済みルート証明に追加し、またクライアント証明書も追加しておきます。
さらに、AWS ConsoleのWorkspacesからディレクトリに移動し、AD Connectorの詳細の更新画面に行きます。「アクセス制御」セクションで、信頼されたWindows、MacOSからのアクセスを許可をそれぞれチェックし、ROOT CAの証明書をインポートします。その他プラットフォームからのアクセスは拒否しておきます。
この設定が完了すると、クライアント証明書がインストールされたWindows/MACからしかアクセスできないようになります。