ADFS利用による複数AWSアカウントへのSSO
西澤です。ここのところアカウントを集約する方法を色々と調べているのですが、先日のAWS Directory Service(Simple AD)のみでユーザ管理(AWS Management Console編)で色々と方法を模索している中で、AWS Directory Serviceが用意してくれるアクセスURLでは、複数のAWSアカウントを束ねて管理することは実現できないことがわかった為、これをADFSを利用することで実現する方法をご紹介します。
設定方針
全てのアカウントはAWS Directory Service(Simple AD)上のユーザで集約して管理をします。IAMユーザは作成することなく、複数のAWSアカウントへのアクセス制御を行います。
構成
ADFSの裏で利用するDirectory Serviceは、今回もAWS Directory Service(Simple AD)を利用しました。もちろん普通のWindows ADでもアカウント管理を集約できていれば問題ありません。
セキュリティグループとIAMロールのマッピング
ユーザ管理は1つのActive Directoryに集約し、複数のAWSアカウントを制御します。以下のようにマッピングする方針でユーザを用意しました。
ADセキュリティグループ | AWSアカウント | IAMロール |
111111111111-Production | 111111111111 | ADFS-Production |
2222222222222-Production | 222222222222 | ADFS-Production |
ADユーザ作成
下記のようにADユーザを用意します。AWS Directory Service(Simple AD)のみでユーザ管理(AWS Management Console編)を参考にやってみてください。今回は電子メールの登録は必須ではありません。理由は後述します。
ユーザ | セキュリティグループ |
bob |
|
jane |
|
Identity ProviderとIAMロールの作成
他の記事の内容と重複する為、詳細な手順は割愛しますが、管理対象とする全てのAWSアカウントで下記リソースを作成しておく必要があります。
作成するリソース | 名称 | 備考 |
SAML Identity Provider | simplead.local | メタデータはADFSサーバからダウンロードしたものを利用 |
IAMロール | ADFS-Production | saml-provider/simplead.localをTrusted Entitiesに指定 |
ADFS設定
まずはActive Directory資産を活用したAWS Management ConsoleへのSSOの環境が整っていることが前提です。設定変更が必要な箇所のみ抜粋します。
RoleSessionName
AssumeRoleする際には任意のRoleSessionNameの指定が必要となります。前述の記事やEnabling Federation to AWS Using Windows Active Directory, ADFS, and SAML 2.0では、"E-Mail-Addresses"を指定していましたが、今回は"User-Principal-Name"を利用することにしました。
ちなみにログインに成功すると、このRoleSessionNameが画面右上に表示されます。
何故今回これを変更したかと言うと、EメールアドレスではRoleSessionNameの文字数制限である32文字まで、という制限に引っかかり正常に動作しないことがわかった(私自身のメールアドレスが偶然にも32文字以上だった為に発覚しました)からです。ちなみに32文字以上のRoleSessionNameを指定した場合、下記のようなエラーメッセージが表示されます。もちろん"ユーザログオン名(User-Principal-Name)"に変更したところで32文字以内であるという保証はありません。ただ、メールアドレスを変更することは難しいと思うので、Directory Service側の管理ルールとして許容出来る範囲ではないかと思うのですがいかがでしょうか?より適切なRoleSessionName指定があるかもしれません。
ロールマッピング
AD上で管理したいAWSアカウントの数だけロールマッピングの指定が必要です。見て取れる通り、AD上のセキュリティグループの文字列を正規表現でAWS上のIAMロールに置換処理をしているだけですので、本当はもう少し上手い管理方法があるかもしれません。
管理したいAWSアカウントの数だけ下記のようなカスタム要求規則を設定します。
- Roles-111111111111の例
c:[Type == "http://temp/variable", Value =~ "(?i)^111111111111-"] => issue(Type = "https://aws.amazon.com/SAML/Attributes/Role", Value = RegExReplace(c.Value, "111111111111-", "arn:aws:iam::111111111111:saml-provider/simplead.local,arn:aws:iam::111111111111:role/ADFS-"));
今回はAD上のセキュリティグループの先頭にマッピング対象のAWSアカウントIDを付与しておき、特定AWSアカウントのIAMロールとマッピングする方式としました。
動作確認
それではADユーザでログインしてみましょう。2つのAWSアカウント用セキュリティグループに同時に所属させたbobユーザでログインすると、どのような挙動になるでしょうか?
どちらのAWSアカウントにログインするかを選択することができました。
管理対象のAWSアカウントが増減した時に、ADFSサーバ設定の修正が必要となるところがいまいちですが、アカウント改廃は全てDirectory Service上のユーザ管理だけで対応できそうです。
AWSアカウントが増える度に要求ルールが増えてしまうという点について、AWSブログの方に解決方法が提示されていましたので以下に追記しておきます。
c:[Type == "http://temp/variable", Value =~ "(?i)^AWS-([^d]{12})"] => issue(Type = "https://aws.amazon.com/SAML/Attributes/Role", Value = RegExReplace(c.Value, "AWS-([^d]{12})-", "arn:aws:iam::$1:saml-provider/ADFS,arn:aws:iam::$1:role/"));
このような正規表現による置換を用いた要求ルールを書くことで、AWSアカウントごとに要求ルールを追加する必要は無さそうです。こちらの方が断然スマートですね。
まとめ
アカウントを管理できるDirectory ServiceとADFSサーバがあれば、AWSマネージメントコンソールへのアクセス管理を集約することができそうです。今回の構成だとADFSサーバがSPOFがなってしまう為、注意が必要です。また、前記事の課題となっていたアクセスキー利用ですが、この方式であれば"AssumeRoleWithSAML"が使えそうです。その辺りも近いうちに試してみたいと思っています。