AWS Managed Microsoft ADとADFSを構築する

# はじめに
AWS Managed Microsoft AD（以下、MSAD）では、ADユーザーをDomain Adminsグループ（ドメイン管理者グループ）に所属させることができません。したがって、Domain Adminsユーザーを必要とするサービスは構築することができません。ADFSも通常の構築手順ではDomain Adminsユーザーを必要としますが、Powershellを使うことでDomain Adminsユーザーを使用せずにMSADとADFSを構築することが可能です。本記事では、Adminユーザー以外のできるだけ最小の権限を持ったADユーザーでMSADとADFSを構築する方法をご紹介します。
# 環境構成
今回はMSADとADFSサーバー1台で構成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/d13253b9-f719-813c-21fe-c87ff9450f89.png)

【MSAD】
・ディレクトリのDNS名：example.com
・ディレクトリのNetBIOS 名：example

【ADFSサーバー】
・Windows Server 2016 Standard
# 事前準備
以下の作業は実施済みであるものとします。
・MSADの起動
・ADドメインの構築
・ADFSサーバー用EC2インスタンスの起動
・EC2インスタンスのADドメインへの参加
# 構築手順
EC2インスタンスにADFSをインストールし、AWSマネジメントコンソールにADユーザーのID・パスワードでSSO可能とするまでの手順を説明します。
## AD管理ツールのインストール
ADFSサーバー用EC2インスタンスにAD管理ツールをインストールします。（今回は簡単のためADFSサーバーとAD管理用サーバーを同居させますが、本番環境ではADFSサーバーとAD管理用サーバーは分けて構築するのが一般的です。）
1.　EC2インスタンスにログインし、サーバーマネージャーを起動します。
2.　[役割と機能の追加]をクリックし、サーバーの役割の選択までデフォルトで進めます。
3.　サーバーの役割の追加にてActive Directoryドメインサービスを選択し、デフォルトのまま最後まで進めます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/f507f466-a5ac-be05-407d-186dc58356c9.png)
4.　以下のようにスタートメニューからAD管理ツールが表示されていればインストール完了です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/51331898-7b33-54d4-1c89-6314c4cb49f1.png)
## MSADへのユーザー追加
MSADにADFS構築に必要となるユーザーを事前に追加しておきます。今回はAdminユーザー（MSADにおいてAWSが用意している管理ユーザー）以外のできるだけ最小の権限を持ったユーザーでADFSを構築する方針としているため、最低でも以下の1ユーザーを追加しておく必要があります。ADFSファームを構築する際に、本ユーザーをADFS構築用ユーザーとADFSサービスアカウントに指定してPowerShellコマンドを実行します。
【追加するユーザー】
・ADFS-Admin
【ユーザーが所属するグループ】
・AWS Delegated Administrators（※ADFS構築用ユーザーはこのグループに所属させる必要があります）
・Domain Users
## MSADへのコンテナ追加
MSADにコンテナと呼ばれるADオブジェクトを2つ追加します。このコンテナはADFSファーム内でのプライベートキーの共有に利用されます。**この手順は必ずADFS構築用ユーザー（本記事ではADFS-Admin）で行ってください。ADFSファーム構築コマンド実行時に権限エラーが発生する可能性があります。**

1.　ADFS構築用ユーザーでEC2インスタンスにログインし、PowerShellを起動します。
2.　以下のコマンドを実行し、実行結果のGuidをメモしておきます。

```powershell:Guidの取得
(New-Guid).Guid
```

3.　以下のコマンドを実行し、ADFSコンテナを作成します。

```powershell:ADFSコンテナの作成
New-ADObject -Name "ADFS" -Type Container -Path “OU=YourNetBIOSName,DC=YourDomainSuffix,DC=YourDomainRoot”
```
“OU=YourNetBIOSName,DC=YourDomainSuffix,DC=YourDomainRoot”の部分は適宜自身の環境のものに置き換えてください。
例）example.comドメインのexampleというOU直下にADFSコンテナを作成する場合、"OU=example,DC=example,DC=com" のように指定します。

4.　以下のコマンドを実行し、ADFSコンテナ直下にGuidコンテナを作成します。 

```powershell:Guidコンテナの作成
New-ADObject -Name "Guid" -Type Container -Path “CN=ADFS,OU=YourNetBIOSName,DC=YourDomainSuffix,DC=YourDomainRoot”
```

"Guid"の部分を前述の手順で取得したGuidに置き換えてください。
## ADFS機能のインストール

1.　ローカルの管理者アカウントでEC2インスタンスにログインし、PowerShellを起動します。
2.　以下のコマンドを実行し、ADFSの機能をインストールします。

```powershell:ADFS機能のインストール
Install-WindowsFeature ADFS-Federation
```
## SSL証明書の取得
今回の構築ではPowerShellで自己署名SSL証明書を発行します。自己署名SSL証明書はWindowsのIIS機能を利用しても発行できますが、PowerShellで発行した方がサブジェクト名などの設定変更が容易で汎用性が高いです。
1.　EC2インスタンスにログインし、PowerShellを起動します。
2.　以下のコマンドを実行し、SSL証明書を発行します。

```powershell:SSL証明書の発行
New-SelfSignedCertificate -Subject "adfs.example.com" -DnsName "adfs.example.com" -CertStoreLocation "cert:\LocalMachine\My" -KeyAlgorithm RSA -KeyLength 2048 -KeyExportPolicy Exportable -NotAfter (Get-Date).AddYears(5)
```

・サブジェクト名やDNS名は適宜自身の環境のものに置き換えてください。（サブジェクト名はADFSのサービス名となります。）
・AddYears()内の数字で証明書の有効期限を指定可能です。今回は5年にしています。
・発行した証明書の拇印（Thumbprint）は次の手順で使うためメモしておいてください。

## ADFSファームの構築
1.　ローカルの管理者アカウントでEC2インスタンスにログインし、PowerShellを起動します。
2.　作成したコンテナを利用するように変数を設定します。

```powershell:AdminConfig
$adminConfig = @{"DKMContainerDn"="CN=Guid,CN=ADFS,OU=YourNetBIOSName,DC=YourDomainSuffix,DC=YourDomainRoot"}
```

前述の手順で作成したGuidコンテナを指定するように上記コマンドを置き換えてください。

3.　追加したユーザーを利用するために変数を設定します

```powershell:AdminCred
$adminCred = (get-credential)
```

認証情報の入力を求められるので、前述の手順で追加したユーザー（ADFS-Admin）のユーザー名とパスワードを入力してください。

4.　ADFSファーム構築コマンドを実行します。

```powershell:Install-ADFSFarm
Install-ADFSFarm -CertificateThumbprint <Thumbprint ID> -FederationServiceName "YourFederationServiceName" -ServiceAccountCredential $adminCred -Credential $adminCred -OverwriteConfiguration -AdminConfiguration $adminConfig -SigningCertificateThumbprint <Thumbprint ID> -DecryptionCertificateThumbprint <Thumbprint ID>
```

・"YourFederationServiceName"の部分はSSL証明書のサブジェクト名と同一にする必要があります。
・＜Thumbprint ID＞ の部分はSSL証明書の拇印に置き換えてください。

## IISのインストールと設定
ADFSサーバーにWebサーバーとしての機能を持たせるためIIS（Internet Information Services）をインストールします。
1.　EC2インスタンスにログインし、PowerShellを起動します。
2.　以下のコマンドを実行し、IISをインストールします。

```powershell:IISのインストール
Install-WindowsFeature -name Web-Server -IncludeManagementTools
```

3.　サーバーマネージャーを起動し、右上の[ツール]からIISの管理画面を起動します。
4.　[サイト]をクリックし、Default Web Siteを選択した状態で[バインド]をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/43a26ade-3734-bffa-3724-549a24ff1ff2.png)
5.　[追加]をクリックし、サイトバインドの追加画面を開き、HTTPSのサイトバインドを追加します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/38a6de5d-843f-fd46-8577-d1ef435a9e30.png)
SSL証明書には前述の手順で発行した自己署名入りSSL証明書を指定します。

## IdPの作成
1.　ADFSサーバーからフェデレーションメタデータを取得します。

```:URL
https://＜ADFSサーバーのFQDN＞/FederationMetadata/2007-06/FederationMetadata.xml
```

※今回はDNSで名前解決ができないため、クライアントPCのhostsファイル等で名前解決を行います。

2.　AWSマネジメントコンソールにログインし、IAMからIDプロバイダーを作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/d1808cda-6851-8e8b-43d9-cfb3af879faf.png)
・プロバイダーのタイプ：SAML
・プロバイダ名：任意
・メタデータドキュメント：前の手順でダウンロードしたXMLファイル

作成したIdPのARNは後述の手順で利用するためメモしておきます。

## ADグループとIAMロールの紐付け
ユーザーが認証をクリアした際に、ユーザーが所属するADグループに応じてIAMロールを担わせるため、ADFSサーバーでグループとロールを紐付ける設定を行います。
1.　EC2インスタンスにログインし、サーバーマネージャーからADFS管理画面を起動します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/5e9b5a38-038c-fdc5-a619-ebe1bc5150e3.png)

2.　[証明書利用者信頼]を右クリックし、[証明書利用者信頼の追加]を選択します。
3.　データソースの選択にて以下を入力し、それ以外はすべてデフォルトで完了します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/686fb2f4-ee17-f9e4-d71a-f536b6cdaad9.png)

```:URL
https://signin.aws.amazon.com/static/saml-metadata.xml
```

4.　追加された証明書利用者信頼を右クリックし、[要求発行ポリシーの編集]を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/516585d8-ac09-430f-8713-daca41f5135b.png)

5.　4つの要求発行ポリシーを追加します。
①Windowsアカウント名を名前IDに変換
②UPN（User Principal Name）をセッション名に設定
③ユーザーが属するグループ名の取得
④グループ名とロール名のマッピング

以下、詳細手順
①Windowsアカウント名を名前IDに変換
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/c12e28d6-9944-a03f-0bf9-b71e0c3a88eb.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/6f6babbf-3d90-e903-1ff5-c949f03f8f3f.png)

②UPNをセッション名に設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/0317e99b-337c-424e-af23-7b8c30946cfc.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/30fb691a-98a2-fec8-008d-4bc05729f0b0.png)

```:URL
https://aws.amazon.com/SAML/Attributes/RoleSessionName
```

③ユーザーが属するグループ名の取得
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/aeed34f9-8295-7da4-f2fc-771506f1025d.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/0fb97c08-0c8a-0aeb-ffc5-5d92e631f8de.png)

```:
c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Issuer == "AD AUTHORITY"] => add(store = "Active Directory", types = ("http://temp/variable"), query = ";tokenGroups;{0}", param = c.Value);
```

④グループ名とロール名のマッピング
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/4923dac7-088b-8e9d-9509-d37417584199.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/327788/f7389ff6-2d63-2aef-0598-afd361a66089.png)

```:
c:[Type == "http://temp/variable", Value =~ "(?i)^グループ名プレフィックス-"] => 
issue(Type = "https://aws.amazon.com/SAML/Attributes/Role", Value = RegExReplace(c.Value, "グループ名プレフィックス-", "IdPのARN,arn:aws:iam::アカウント番号:role/"));
```
・上記のマッピングルールではマッピング元のグループ名に何らかのプレフィックスを付与することを想定しています。ADFSで利用するグループを他のグループと識別可能とすることで、不要なグループがロール名にマッピングされることを防ぎます。
例）グループ名プレフィックスをADFSとした場合、ADFS-Developerグループに所属するユーザーにはDeveloperという名前のIAMロールが付与されます。
・IdPのARNやアカウント番号は自身の環境のものに置き換えてください。

以上でADFS構築作業は完了です。
# 動作確認
1.　ADユーザー、ADグループを作成し、ユーザーをグループに所属させます。
・ADグループ名：ADFS-Test

2.　IAMロールを作成します。
・IAMロール名：Test

3.　以下のURLをブラウザに入力します。

```:URL
https://＜ADFSサーバーのFQDN＞/adfs/ls/IdpInitiatedSignOn.aspx
```

4.　ユーザー名とパスワードを入力してログインします。
AWSマネジメントコンソールが表示され、Testロールが付与されていることが確認できたら成功です。
# おわりに
今回はPowershellを使ってMSADとADFSを構築する方法をご紹介しました。GUIでADFSを構築する手順はいろいろと有用な記事が見つけられたのですが、CUIを使って構築する方法は情報が少なく、かなり苦労して構築手順を確立しました。MSADを立ててみたけどADFSの構築方法が分からないという方の手助けになれば幸いです。