【AWS】AWS環境上にADサーバを立てて、複数アカウントにシングル・サインオンする【ADFS】


# この記事で紹介すること

この記事では、複数のAWSアカウント間でSingle Sign-On(SSO)を実装するための方法について解説します。

AWSのアカウント間でSSOを実装するには、google等のアカウントを利用して認証を行う方法と、自前のActive Directory（AD)サーバの認証を利用するActive Directory Federation Services (ADFS) を用いる方法があります。

この記事では、後者のADFSを用いた認証を利用してSSOを実装する方法を紹介していきます。

# 前提知識

この記事ではADFSを用いたSAML認証プロバイダの作り方について紹介します。
以下の内容についてある程度触ったことのある方が見てわかる内容を目指しています。

* AWSのIAMを触ったことがある
* AWS Security Token Serviceがどのようなものかイメージがつく
* Active Directoryがどのようなものか知っている
* Windowsサーバを触ったことがある
* SSL証明書が何かわかる
* DNSの基本的な概念を理解している

# 作業環境

作業用のPCはmacを使用しています。
作業PC以外は全てAWS上のリソースを利用しています。

複数のアカウントにログインする。のを試すため、AWSのアカウントを２つ以上持っている事を前提とします。
AWSのアカウントはメールアドレスが異なれば同じクレジットカードでも作ることが出来るため、この記事の内容を試す前に２つ目のアカウントを取得することをおすすめします。

# なぜ、SSOが必要なのか

実装方法を紹介する前に、なぜSSOを利用しようと思ったかについて簡単に説明します。

私は、いつの間にか個人アカウントが何個も出来上がってしまいました。
最初は複数のアカウント間でSwitch Roleの機能を使ってアカウントを切り替えていたのですが、読み取り・操作等も考慮にいれるとアカウント番号を入力したりと切り替えがかなり面倒になっていました。

ADFSを利用したSSOであれば、一度ADサーバの認証を通してしまえばアカウント間・ロールの切り替え時に面倒な認証をしなくて良いのでストレスフリーです。

できるだけ面倒なことをしないために、あとIdP興味あるじゃろ？
という理由で個人環境にADFSを実装してみようというお話です。


### なお、今回は個人環境での利用を前提としているため可用性を考えた構成は取りません。落ちたら素直にIAMログインしよう！の精神です。


# 環境構成
今回実装する環境は以下のようになります。

### 環境構成図



### アカウント情報

|アカウント番号|用途　　　|以後のアカウント表記|
|:----------|:------|:---------------|
|123456789012|ADサーバ稼働アカウント|アカウント蘭子|
|098765432109|別アカウントにログイン出来るか確認用アカウント|アカウント幸子|

__ええ、趣味です。__


### AD+ADFSサーバ
今回はADとADFSは同一サーバ上（１台）で構成します。
SimpleADを利用して構築しても可能ですが、無料枠が750時間なのでEC2上で組んでいます。

* Windows Server 2012 R2 Japanese
* AMI ID:ami-af6f85ce
* インスタンスタイプ：t2.micro
* Windowsマシン名：ad01
* セキュリティグループはHTTPS/RDPを使用

### ドメイン
ADサーバで利用するドメインは以下のものを使用します。
今回はドメインは取得していない状態での作業を想定しているため、端末のhostsファイルを用いて名前解決をします。
__外部公開可能なドメインをお持ちの方はRoute53と組み合わせてそちらを利用しても大丈夫です__

```
adfs-sso.local
```

### IAMロール
ADFSによるフェデレーションログインでは、IAMロールの権限を引き受けることになるため、2つのアカウントにそれぞれ下記のポリシーを当てたロールを用意します。

* AdministratorAccess
* SecurityAudit


以上が今回使用する環境の説明です。
では、Windowsインスタンスを用意し実際に作業していきます。

# [アカウント蘭子] Windowsインスタンス上での作業

#### 前提条件：WindowsServerインスタンスが起動し、RDP接続が確立している

Windowsインスタンスに以下の役割をインストールします

* Active Directory ドメインサービス
* Active Directory Federation Services
* Webサーバー（IIS)

![スクリーンショット_2016-06-30_17_51_41.jpg](https://qiita-image-store.s3.amazonaws.com/0/52141/6a494c4e-1a92-ef26-effb-539800e36ba9.jpeg "スクリーンショット_2016-06-30_17_51_41.jpg")


IISに関しては、ADFS構築時にSSL証明書の入力を求められるため、オレオレ証明書を簡単に用意するために導入しています。

役割のインストールが終了したらWindwosのホスト名を変更します。

__ホスト名変更（参考）__

![スクリーンショット_2016-06-30_18_12_47.jpg](https://qiita-image-store.s3.amazonaws.com/0/52141/2b4ed2b5-0563-ad57-fb21-2e51dc6c5cbc.jpeg "スクリーンショット_2016-06-30_18_12_47.jpg")


一通りの作業が完了したら下記の手順で作業をしていきます。

1. Active Directoryの構築
2. ADサーバのグループとユーザーの作成
3. SSL証明書の準備
4. Active Directory Federation Servicesの設定


## Active Directoryの構築

AD環境を準備します。

__新しいフォレストを作成し、ルートドメイン名を入力します__

![スクリーンショット 2016-06-30 17.57.16.png](https://qiita-image-store.s3.amazonaws.com/0/52141/96925cd5-c29b-8a7d-6ec0-a803bb26c684.png "スクリーンショット 2016-06-30 17.57.16.png")

__デフォルト値のままでパスワードを指定します__

```
今回使用したパスワード：adadmin123!
```


![スクリーンショット 2016-06-30 17.59.59.png](https://qiita-image-store.s3.amazonaws.com/0/52141/1ac77f2a-2714-0e9f-9ce9-8be7ec775b12.png "スクリーンショット 2016-06-30 17.59.59.png")

### 以後は全てデフォルト値のままで次へを選択

![スクリーンショット 2016-06-30 18.03.28.png](https://qiita-image-store.s3.amazonaws.com/0/52141/769a2e21-ba39-d4ca-1764-240f8fbd6d44.png "スクリーンショット 2016-06-30 18.03.28.png")

上記画面まで遷移したら「インストール」します

再起動すればADサーバの構築は完了です。

## グループとユーザーの作成

Active Directory上にユーザーと、ユーザーが所属するグループを作成します。
マネジメントコンソールへのログインは、このユーザーのログイン情報を元に今後行います。

__Active Directory ユーザーとコンピュータを起動__

![スクリーンショット_2016-06-30_18_15_58.jpg](https://qiita-image-store.s3.amazonaws.com/0/52141/a8abca50-9536-91e5-e719-07365578efe9.jpeg "スクリーンショット_2016-06-30_18_15_58.jpg")

今回はOU：AWSを作成してその中にユーザーを追加しました。これは、後で作ったものを表示する際に見やすくするためにしています。

Usersの中にそのままユーザーを作成しても問題ありません。

__ユーザーAdminを作成します__

![スクリーンショット 2016-06-30 18.20.26.png](https://qiita-image-store.s3.amazonaws.com/0/52141/316686c7-a077-4e4a-a260-7d2db2ca3723.png "スクリーンショット 2016-06-30 18.20.26.png")


![スクリーンショット 2016-06-30 18.21.08.png](https://qiita-image-store.s3.amazonaws.com/0/52141/82ca70f5-bf5a-7edc-10eb-e43be5013d02.png "スクリーンショット 2016-06-30 18.21.08.png")


今回使用したパスワード ```awsPass123!```


後の手順でメールAD情報のメールアドレスを使用するため設定しておきます

![スクリーンショット 2016-07-01 16.31.41.png](https://qiita-image-store.s3.amazonaws.com/0/52141/045a47b3-a2f9-7f8a-c821-1455f09a5e76.png "スクリーンショット 2016-07-01 16.31.41.png")


__続けてグループを作成します__

![スクリーンショット 2016-06-30 18.33.31.png](https://qiita-image-store.s3.amazonaws.com/0/52141/6d523ee7-e47f-9396-8fd3-322825fb0a72.png "スクリーンショット 2016-06-30 18.33.31.png")

ここでのグループ名の名づけ方には注意が必要です。後のADFSの設定で、このグループ名とAWS側のロールの名前を紐付ける必要があります。
今回後に設定する書式では```アカウント番号12桁-ロール名``` となります。

従って、個々では上記の様に名付けてください。

無論、蘭子アカウントなのでこの番号になっていますが、ここは個々人の環境により異なります。

__このようになっていれば完了です__

![スクリーンショット 2016-06-30 18.37.23.png](https://qiita-image-store.s3.amazonaws.com/0/52141/7dd2fd64-325b-7162-344d-d3c0f834215d.png "スクリーンショット 2016-06-30 18.37.23.png")

#### Adminを作成したグループに追加します

![スクリーンショット_2016-07-01_16_30_22.jpg](https://qiita-image-store.s3.amazonaws.com/0/52141/50aa6d66-0206-e9ec-167c-eada95cc617e.jpeg "スクリーンショット_2016-07-01_16_30_22.jpg")



## SSL証明書の準備

ADFSを用いたSSOの実装にはHTTPS通信を使います。
よって、サーバにSSL証明書をインストールする必要があります。

自身で認証局の証明書を持っている方はその証明書をインストールし、使用してください。
ここでは、所謂オレオレ証明書（自己署名の証明書）を使用する手順を紹介します。


__IISの管理画面を出します__

![スクリーンショット_2016-06-30_18_40_22.jpg](https://qiita-image-store.s3.amazonaws.com/0/52141/0efb1e2d-c8d0-6ee8-5224-b8e9385f7135.jpeg "スクリーンショット_2016-06-30_18_40_22.jpg")

__サーバー証明書を選択__

![スクリーンショット_2016-06-30_18_41_53.jpg](https://qiita-image-store.s3.amazonaws.com/0/52141/db8a33cf-f5c4-e409-aa74-5d3e30fcd235.jpeg "スクリーンショット_2016-06-30_18_41_53.jpg")


__自己署名入り証明書の作成を選択__

![スクリーンショット_2016-06-30_18_43_54.jpg](https://qiita-image-store.s3.amazonaws.com/0/52141/2915ce91-29d5-5de9-43ea-c31dbf56181a.jpeg "スクリーンショット_2016-06-30_18_43_54.jpg")

## ADFSの構築
Active Directory Federation Servicesの設定をします。
 
__サーバーマネージャーから飛びます__ 
 
![スクリーンショット 2016-06-30 18.48.58.png](https://qiita-image-store.s3.amazonaws.com/0/52141/cd3bd345-3c12-d003-913b-9da8bd5a2a5e.png "スクリーンショット 2016-06-30 18.48.58.png")

__デフォルト値のまま進めます__

![スクリーンショット 2016-06-30 18.50.12.png](https://qiita-image-store.s3.amazonaws.com/0/52141/7f6bbabf-492f-1812-92e5-826b194a50e9.png "スクリーンショット 2016-06-30 18.50.12.png")

そのまま進み、証明書の選択へ

![スクリーンショット 2016-06-30 18.50.57.png](https://qiita-image-store.s3.amazonaws.com/0/52141/bd187b6b-3f00-3b42-c0f0-b89c9a71d199.png "スクリーンショット 2016-06-30 18.50.57.png")

ここで、先ほどインストールした証明書を選択します。
フェデレーションサービスの表示名は、SSOで認証するときにページに表示されるだけなのでお好きな文字列を入れてください。

__PowerShellを使用します__

![スクリーンショット 2016-06-30 18.55.06.png](https://qiita-image-store.s3.amazonaws.com/0/52141/caa746c9-0a37-d5d4-c800-9ed99160e32a.png "スクリーンショット 2016-06-30 18.55.06.png")

ホップアップに記載されているように、PowerShellコマンドを打ち込まないと上の選択が出来ないため、PowerShellで下記コマンドを入力します

```ps:コマンド
Add-KdsRootKey -EffectiveTime(get-Date).AddHours(-10)
```

![スクリーンショット 2016-06-30 19.00.46.png](https://qiita-image-store.s3.amazonaws.com/0/52141/85c96740-8169-5905-51f7-d3f83c914591.png "スクリーンショット 2016-06-30 19.00.46.png")

```adfsadmin``` を作成しました。

移後はそのまま画面を進め「構成」します。


# [アカウント蘭子] IdPの作成

### メタデータのXMLを取得します。

Windowsサーバー上から取得しても良いのですが、後ほどhostsに登録するので下記のように
クライアントのhostsに追記します

#### IPAddressは各環境のインスタンスのGIPで置き換えてください

```:/etc/hosts
00.000.00.00    ad01.adfs-sso.local

```

クライアントから下記URLに接続します。
環境の名称等を変更している方はad01.adfs-sso.localの部分を適時自身の環境に合わせてください。


#### 今まで一言も触れてきませんでしたが、SGでHTTPSを許可しないと接続できません。

```:url
https://ad01.adfs-sso.local/FederationMetadata/2007-06/FederationMetadata.xml
```

オレオレ証明なので警告は出てきますがアクセスします


![スクリーンショット 2016-07-01 16.03.39.png](https://qiita-image-store.s3.amazonaws.com/0/52141/eb75a729-4f6c-09ae-e36b-4e2c4f0f4660.png "スクリーンショット 2016-07-01 16.03.39.png")

接続するとXMLファイルが落ちてきます。このファイルは次の手順で使用します。


### AWS上にIｄPを作成します。

コンソール上のIAMに __IDプロバイダ__ というものがあるのでそちらを選択します

#### 作成を押下してSAML選びます

![スクリーンショット 2016-07-01 11.04.18.png](https://qiita-image-store.s3.amazonaws.com/0/52141/2aad551f-9c07-b1a9-fda0-e2e8ffa142f6.png "スクリーンショット 2016-07-01 11.04.18.png")

先ほど取得したXMLを選択して作成します。

#### 作成したプロバイダのARNを控えておきます。後ので順で使用します。

![スクリーンショット_2016-07-01_16_07_45.jpg](https://qiita-image-store.s3.amazonaws.com/0/52141/aa05fa96-89c0-14dc-c703-7504c1ff408b.jpeg "スクリーンショット_2016-07-01_16_07_45.jpg")



### ここからが今回の設定で一番重要です

Windowsサーバに戻って作業します。作成したAD上のグループとAWSのIAMグループのひも付け等を行います。


![スクリーンショット 2016-06-30 19.46.52.png](https://qiita-image-store.s3.amazonaws.com/0/52141/c62df088-5d7d-8d12-5ef2-941962151c4c.png "スクリーンショット 2016-06-30 19.46.52.png")

![スクリーンショット 2016-06-30 19.47.32.png](https://qiita-image-store.s3.amazonaws.com/0/52141/a25950f4-cd9e-b443-d6a7-4bb5f0f7b803.png "スクリーンショット 2016-06-30 19.47.32.png")


![スクリーンショット 2016-06-30 19.48.17.png](https://qiita-image-store.s3.amazonaws.com/0/52141/7e52044b-b8f7-bf0a-0fc0-c9eaafdb528c.png "スクリーンショット 2016-06-30 19.48.17.png")

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

デフォルトのまま最後まで確定します。

![スクリーンショット_2016-07-01_10_22_30.jpg](https://qiita-image-store.s3.amazonaws.com/0/52141/23537025-431e-69d9-c0aa-82a4d5201d09.jpeg "スクリーンショット_2016-07-01_10_22_30.jpg")


![スクリーンショット 2016-06-30 19.50.22.png](https://qiita-image-store.s3.amazonaws.com/0/52141/3e128e2b-0dd1-a6c9-95f6-0a24c1839311.png "スクリーンショット 2016-06-30 19.50.22.png")

この変換のルールをこれから４つ作成します。
この辺は下記の参考にもまとめましたが詳細は以下の記事を参考にしてください。
ここでは、今回やるための設定のみを紹介します。

[Active Directory資産を活用したAWS Management ConsoleへのSSO](http://dev.classmethod.jp/cloud/aws/adfs-aws-sso/)
[ADFS利用による複数AWSアカウントへのSSO](http://dev.classmethod.jp/cloud/aws/adfs-sso-multi-aws-account/)
[ADFS 3.0を使ってActive DirectoryのアカウントでAWSにログインする](http://blog.serverworks.co.jp/tech/2016/05/20/adfs-3-0%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6active-directory%E3%81%AE%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%81%A7aws%E3%81%AB%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%99%E3%82%8B/)



### 【1つ目】WindowsID　-> 名前ID (入力方向の要求を変換)

![スクリーンショット 2016-07-01 10.31.56.png](https://qiita-image-store.s3.amazonaws.com/0/52141/51f872ed-16a9-b814-1471-3166e287aa14.png "スクリーンショット 2016-07-01 10.31.56.png")

### 【2つ目】E-mail Address (LDAP属性を要求として送信)

![スクリーンショット 2016-07-01 10.47.58.png](https://qiita-image-store.s3.amazonaws.com/0/52141/2d410357-4b5f-fd39-599c-4b396ead073d.png "スクリーンショット 2016-07-01 10.47.58.png")

```:Emailの値
https://aws.amazon.com/SAML/Attributes/RoleSessionName
```

### 【3つ目】ADのグループ名取得 (カスタム規則を使用して要求を送信)

![スクリーンショット 2016-07-01 10.51.50.png](https://qiita-image-store.s3.amazonaws.com/0/52141/c4d5870c-cc4d-b8c0-30ca-931e9101415f.png "スクリーンショット 2016-07-01 10.51.50.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);
```

#### 【4つ目】AWSのIAMロール名取得 (カスタム規則を使用して要求を送信)

![スクリーンショット 2016-07-01 16.13.39.png](https://qiita-image-store.s3.amazonaws.com/0/52141/24172c98-4630-0660-69af-0f8bfb84929e.png "スクリーンショット 2016-07-01 16.13.39.png")



```:入力値
c:[Type == "http://temp/variable", Value =~ "(?i)^アカウント番号-"]
 => issue(Type = "https://aws.amazon.com/SAML/Attributes/Role", Value = RegExReplace(c.Value, "アカウント番号-", "ここに先ほど控えたプロバイダのARNを入力する,arn:aws:iam::アカウント番号:role/ADFS-"));
```

#### プロバイダのARNは自身の環境のものに置き換えてください。



いま最後に作成した４つ目のルールをログインしたいアカウントの数だけ増やしていくことでSSOでログインするアカウントを増やしていけます。

# [アカウント蘭子] IAMロールの作成

先ほど作成したADFSのルールに対応するIAMロールを作成します。
４つ目のルールで使用した入力値で、AWSのロールの頭が __ADFS-__ で始まるものをマッチングさせると記述しました。
従って、AWS上で作成するIAMロールは __ADFS-XXXX__ というネーミングに従う必要があります。

ADFS-Admin
という名前でAdministratorの権限を持つロールを１つ
ADFS-ReadOnly	
という名前でSecurityAuditの権限を持つロールを１つ
合計２つのロールを作成しましょう

#### 注意するところは下の2箇所です

![スクリーンショット_2016-07-01_16_21_03.jpg](https://qiita-image-store.s3.amazonaws.com/0/52141/854a3703-1e48-25dc-7b01-0fec03ed4c9d.jpeg "スクリーンショット_2016-07-01_16_21_03.jpg")

![スクリーンショット_2016-07-01_16_21_23.jpg](https://qiita-image-store.s3.amazonaws.com/0/52141/6e97cb71-dba1-b51b-5b4b-b5dc9e290aa4.jpeg "スクリーンショット_2016-07-01_16_21_23.jpg")


# [アカウント蘭子] 認証のテスト

以上でアカウント蘭子に対してのSSOの設定が完了しました。
では実際にアクセスしてテストしてみましょう。

```:url
https://ad01.adfs-sso.local/adfs/ls/IdpInitiatedSignOn.aspx
```

#### ADサーバで作成したユーザのメールアドレスとパスワードでログインします

手順にそって作成していれば

|ユーザー名|admin@adfs-sso.local|
|:-----|:-----|
|パスワード|awsPass123!|

でログインができます

![スクリーンショット_2016-07-01_16_33_36.jpg](https://qiita-image-store.s3.amazonaws.com/0/52141/a1d376a1-338d-189d-d4aa-97c6addbc413.jpeg "スクリーンショット_2016-07-01_16_33_36.jpg")

画面のように、作成したロール権限を選択してログインが可能です。
読み取りのみ可能、管理者権限があるの2種類でログインが出来ることを確認してください。


#### ATODEKESUは私の都合上付いているだけなので気にしないでください。


# [アカウント蘭子] Windowsインスタンス上での作業
2つ目のアカウントを追加しましょう。
といっても、一度やっている事を再度やり直すだけです。

## [Active Directory] グループの追加

ADサーバ上でグループを２つ作成し、Adminユーザーを追加しましょう

```:グループ名
098765432109-Admin
098765432109-ReadOnly
```

## [ADFS] 設定の追加

### IdPの作成
先ほどの手順と同様にプロバイダを作成し、ARNを控えておきます

### ルールの追加
Windowsサーバ上で __4つ目】AWSのIAMロール名取得 (カスタム規則を使用して要求を送信)__ を行います。
ARNの値は幸子アカウントのものを使用します

### IAMロールの作成
蘭子アカウントと同じ手順で同じものを作成します。


# [アカウント幸子] 認証のテスト
もう一度ログインして、蘭子アカウント、幸子アカウントの両方でログイン出来るかを確認します。


# まとめ
かなり長くなってしまいましたが、AWS環境でのSSOを構築することができました。
IAMユーザーは増えてくると管理が面倒なのでADサーバに寄せる事ができるのは良いことだと思います。

# 参考
クラメソさんマジクラメソさん
[Active Directory資産を活用したAWS Management ConsoleへのSSO](http://dev.classmethod.jp/cloud/aws/adfs-aws-sso/)
[ADFS利用による複数AWSアカウントへのSSO](http://dev.classmethod.jp/cloud/aws/adfs-sso-multi-aws-account/)
[ADFS 3.0を使ってActive DirectoryのアカウントでAWSにログインする](http://blog.serverworks.co.jp/tech/2016/05/20/adfs-3-0%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6active-directory%E3%81%AE%E3%82%A2%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%81%A7aws%E3%81%AB%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E3%81%99%E3%82%8B/)