AWSへSAML認証でサインイン

業務でSAMLが必要になりそうだったので、勉強のためにAWSにSAML認証でサインインするための手順を実施しました。備忘録としてまとめておきます。

# 使用するIdPとサービスプロバイダー
### IdP
トラスト・ログイン(旧SKUID)を使用します。法人向けサービスですが、無料プランなら個人でも使えます。SAMLの検証くらいなら無料プランで大丈夫です。
https://trustlogin.com/

### サービスプロバイダー
冒頭に記載の通り、AWSを利用します。SAMLできて個人でも触れるサービスって意外とない。

# IdP側の設定(1)
TrustLoginの管理ページにアクセスし、「アプリ」⇒「SAMLアプリ登録」をクリック。
適当にアプリケーション名を決め、メタデータをダウンロードをクリックします。ダウンロードしたメタデータはAWS側で使用します。このページには後で戻ってくるので、閉じないようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/776880/8146039c-d7ec-d735-c964-1b048c7ad655.png)

# サービスプロバイダー側の設定
AWSのIAMコンソールを開き、左側メニューからIDプロバイダーをクリックし、右上のプロバイダを追加をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/776880/92e7a816-20db-81fd-85bb-73a618100cf0.png)
適当にプロバイダ名を入力し、先ほどTrustLoginからダウンロードしたメタデータをアップロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/776880/ead5dda6-d7be-aa39-9cfe-68cace83e7f9.png)
プロバイダを追加したら、プロバイダのARNを控えておきます。ARNはIdP側で入力する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/776880/189da341-8eba-c2a5-8e39-ebda97bcb0f5.png)

次にロールを作成します。左側メニューからロールをクリックし、ロールの作成をクリックします。
「信頼されたエンティティの種類を選択」ではSAML2.0フェデレーションを選択します。SAMLプロバイダーには先ほど作成したSAMLプロバイダを選択し、「プログラムによるアクセスとAWSマネジメントコンソールによるアクセスを許可する」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/776880/34cf439c-730b-eca3-82ff-77521b7dbd56.png)
ロールとタグは適当に選択し、適当なロール名を入力してロールを作成します。（今回は、ロール：AmazonSNSReadOnlyAccess、タグ：なし、ロール名：TrustLogin_TEST_roleとしています。）
ロールを作成したら、ロールARNを控えておきます。こちらもIdP側で入力する必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/776880/cb45da07-00bb-6666-35e9-8e3e7929c17b.png)

# IdP側の設定(2)
AWS側でプロバイダとロールを作成したら、IdP側へ戻ります。
サービスプロバイダーの設定で、以下の情報を入力します。

- エンティティID：https://signin.aws.amazon.com/saml
- ネームIDフォーマット：persistent
- サービスへのACS URL：https://signin.aws.amazon.com/saml

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/776880/52db882c-8663-f976-28d5-0b194b1234cc.png)

また、SAML属性の設定で、以下のように設定します。

|属性指定名|属性種類|属性名| | |属性値|
|---|---|---|---|---|---|
|https://aws.amazon.com/SAML/Attributes/RoleSessionName|Basic |https://aws.amazon.com/SAML/Attributes/RoleSessionName|⇔|固定値|メールアドレス等(例：example@example)|
|https://aws.amazon.com/SAML/Attributes/Role|Basic |https://aws.amazon.com/SAML/Attributes/Role|⇔|固定値|  ロールARN,プロバイダARN|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/776880/bc1ca3eb-3e4b-c273-2013-5908b4451f76.png)

SAML属性を入力したら、登録します。

# SAML認証でログインできるかテスト
実際にログインができるか試します。
うまくログインできていれば、画面の上部に`ロール名/ユーザー名(RoleSessionNameで指定した値）@アカウントID`で表記されているはずです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/776880/596a452b-1726-ea40-65a7-7755d41ca21a.png)

# SAMLレスポンスをのぞいてみる
SAMLを構築する際にはデバッグできるようにならないといけません。そのため、今回のログインで利用しているSAMLレスポンスを見てみます。AWSのユーザーガイドに方法が記載されているので、そちらを参考に実施します。
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/troubleshoot_saml_view-saml-response.html
SAMLレスポンスのAttributeStatementを抜き出したのが以下です。

```xml:SAMLレスポンス
<samlp:Response ...(省略)...>
---(省略)---
  <Assertion ...(省略)...>
---(省略)---
    <AttributeStatement>
      <Attribute Name="https://aws.amazon.com/SAML/Attributes/RoleSessionName" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" FriendlyName="https://aws.amazon.com/SAML/Attributes/RoleSessionName">
        <AttributeValue>example@example</AttributeValue>
      </Attribute>
      <Attribute Name="https://aws.amazon.com/SAML/Attributes/Role" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" FriendlyName="https://aws.amazon.com/SAML/Attributes/Role">
        <AttributeValue>arn:aws:iam::xxxxxxxxxxxx:role/TrustLogin_TEST_role,arn:aws:iam::xxxxxxxxxxxx:saml-provider/TrustLogin_TEST</AttributeValue>
      </Attribute>
    </AttributeStatement>
  </Assertion>
</samlp:Response>
```

属性指定名と属性名に同じ値を割り当ててしまったのでわかりづらいですが、属性指定名が**Name**、属性種類が**NameFormat**、属性名が**FriendlyName**に対応し、属性値は`<AttributeValue>`で囲まれているようです。

#その他
- トラストログイン側のSAML属性の設定で、空白の項目があると、1行丸ごとSAMLレスポンスに出力されない**とき**がある。（されるときもあるのが厄介。原因の判明までにしばらくかかってしまった。。。）