OktaでAWSコンソールにSAMLフェデレーションしたい
はじめに
こんにちは。コンサルティング部の津谷です。
前回のブログではOIDCを使った認証・認可の仕組みを検証しました。OIDCは、アプリケーションが外部IdPからアクセストークン・IDトークンを受け取るためのプロトコルでしたね。今回はSAMLプロトコルを使ったフェデレーション認証を検証して、基礎から深堀してみようと思います。
SAMLとは何か
SAMLは、SSO・ID連携を可能とするため、認証情報のやり取りを行うプロトコルになります。やり取りするファイルはXMLベースのマークアップ言語を使用しています。OIDCは、認証・認可両方を兼任するプロトコルですが、SAMLやkerberosといったプロトコルの役割は主に認証になります。この認証情報のやり取りを理解するには、「IDプロバイダー」と「サービスプロバイダー」という2つの概念を抑えておく必要があります。 以前書いたブログでは、auth0というOAuthプロトコルを利用した認可の仕組みを利用しています。基本的にOAuthプロトコルは認可を行うために、アプリケーション(アクセス許可の要求元)と認可用のサーバがアクセストークンをやり取りするために利用されました。OIDCは認可サーバが認証もできるように(IDトークンのやり取りをするため)に拡張されたプロトコルでしたね。
IDプロバイダー(IdP)とは
ユーザIDを管理するサービスになります。情報を保管するだけではなく、認証リクエストに応じてIDの検証を行い、承認を要求するサービス・アプリケーションにレスポンスを返すことができます。
サービスプロバイダー(SP)とは
アクセスしたいサービス・アプリケーションになります。IdPで承認されたユーザは、認証情報を受け取ったサービス・アプリケーションによってアクセスを許可されます。サービスへアクセスする際に、XMLベースの認証情報・ユーザ属性の情報をIdPがSPに連携します。認証されたユーザの情報をSPが受け取って初めてアクセス許可されるということですね。ここでSPが受け取る情報をSAMLアサーションと呼んでいます。
SAML認証の構成
基本的に認証情報のやり取りは、IdPとSPの間で行われます。認可のフローではないため、OIDCよりはシンプルかもしれません。このようなやり取りをシームレスに連携するには、IdPとSPが互いに信頼関係を構築する必要になります。互いに連携が取れていないと、認証情報のやりとりができません。
Okta(IdP)とAWSコンソール(SP)の構成
今回は、Oktaを外部IdPとして利用し、ユーザがAWSコンソールにアクセスできるかを検証してみます。AWS(コンソール)がSPの役割を担っています。認証のフローとしては、まずユーザがIdPドメインにブラウザからログインします。ログイン後、Oktaが認証を完了すると、認証情報や属性情報をXMLベースでAWS(コンソール)に渡します。一連のフローを整理してみました。今回は、Oktaからそのままコンソールへアクセスします。SP起点でIdPにリダイレクトする構成ではなく、IdP起点でユーザ認証・アサーション生成を行うフローになります。
①まずはユーザがOkta(IdP)にログインします。認証には、ID(メールアドレス)・パスワード・2段階認証を利用します。2段階認証の場合は、「Okta Verify」のモバイルアプリを入れて認証コードを取得します。

②認証が完了したら、OktaがユーザにSAMLアサーションとSPにアサーションを送るためのエンドポイントをレスポンスします。

③SAMLアサーションをSPに送ります。レスポンスとして受け取ったエンドポイントを使用して、SPにアクセスします。

④ユーザから送られてくるSAMLアサーション情報をSP側で検証します。

⑤アサーション情報が正当なものと判断した場合は、AWS内部でSTS(Session Token Service)にアクセスして一時セッションを取得します。内部では、AssumeRoleWithSAMLを実行するためのAPI呼び出しを行っております。セッション情報をユーザに返します。

⑥ロールをユーザが引き受けることで、ロールに付与された許可ポリシーの権限に基づきAWSリソースにアクセスできるという仕組みです。

検証してみた
事前準備
実際に検証しながら、確認してみます。今回は、Oktaの無料トライアルでやってみます。トライアル期間は30日です。下記のURLから試してみましょう。
名前とメールアドレス、国を選択して、無料トライアルを始めるとパスワードの設定も必要にありますので済ませておきましょう。
MFAの設定もしておきました。「Okta Verify」をアプリインストールして、コード認証できるようにしておきます。

設定が完了したら、ダッシュボードに遷移します。ここまで出来たら事前準備は終了です。
構築
Okta側の設定から始めていきます。

管理コンソール(Admin Console)を開き、左タブから「アプリケーション」を押下します。「アプリカタログを参照」を押下し、サービスプロバイダー(AWSアカウント)との統合作業を進めていきます。

検索窓で、「AWSアカウントフェデレーション」と検索すると上記の画面が出てきます。
このアカウントフェデレーションは、アカウント単位でのフェデレーション認証をサポートしています。単一のアカウントに割り当てられたロールにスイッチしてSSOすることが可能です。複数のAWSアカウントに設定が必要な場合は個別に設定する必要があります。
「統合を追加」を押下して、設定に進みましょう。

一般設定から行っていきます。ここでは、AWSのログインURLを設定しています。アクセス先のアカウントIDだけ追記しておきます。フェデレーション認証後に遷移するコンソール画面になります。ここはデフォルトの設定のままで問題ありません。

次にサインオンオプションの設定に移ります。今回は「SAML2.0」を選択しましょう。先ほども触れましたが、SAML認証をする場合、IdPとSPでは信頼関係を構築する必要があります。メタデータを登録することでSP側は、信頼関係を結ぶIdPを認識するようになります。後ほど、AWS側でメタデータの登録を行いますので、メタデータURLから、確認してみましょう。メタデータはIdPの設定情報と考えると腑に落ちました。IdPを識別するIDや、アサーションをSPが復号する際の公開鍵情報などが入っています。

XML形式で、ブラウザに出力されます。こちらは右クリックなどで「名前を付けて保存」をすればXMLファイルとしてローカルに保存することができます。もちろん、テキストをそのままコピーして保存するでも構いません。
ここまで、設定ができたらAWS側で設定していきます。

IAMコンソールの左タブ「IDプロバイダー」を押下し、「プロバイダーを追加」します。

プロバイダのタイプは「SAML」を選択します。
プロバイダ名は「okta-test」としました。
先ほど、XML形式で保存したメタデータをアップロードします。
また、Okta側の設定に戻ります。先ほど登録したIdプロバイダーのArn情報を設定します。
「高度なサインオン設定」で指定しましょう。

また、AWS側の設定に戻ります。
Oktaユーザが、引き受けるIAMロールを作成していきます。

信頼されたエンティティは「SAML2.0 フェデレーション」を選択します。
プロバイダーは先ほど作成した「okta-test」を選択します。今回はコンソールへのアクセスを許可するので、「プログラムとAWSマネジメントコンソールへのアクセスを許可する」にチェックを入れます。

権限は、「AdministratorAccess」にしておきます。制限するリソースに応じて権限は最小にしておくことが推奨されますが、今回は検証なので管理者権限にしています。

ロール名は、「okta-test-role」にしています。
作成後信頼ポリシーが以下のようになっていることを確認します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<アカウントID>:saml-provider/okta-test"
},
"Action": "sts:AssumeRoleWithSAML",
"Condition": {
"StringEquals": {
"SAML:aud": "https://signin.aws.amazon.com/saml"
}
}
}
]
}
作成したロールにフェデレートする設定が入っているか、信頼ポリシーから確認しましょう。ロールを引き受けるとSTSに「AssumeRoleWithSAML」を実行するAPIを呼び出します。呼び出し元の条件として、Oktaから引き受けたアサーション用のエンドポイントを経由しているかで制限しています。(自動生成されるのであまり意識はしないかもしれませんが、、、)Okta側では、基本的にAWSアカウントフェデレーションを行う際にSAMLアサーションを上記のURL宛てに送信しています。
ここまで完了したら、今度はOkta側がAWS統合でIAMロールをリスト化して表示するためのIAMユーザの作成とポリシー付与を行います。基本的にプログラム経由での権限行使になるのでアクセスキーとシークレットアクセスキーの払い出しが必要になります。
まずは、Oktaの管理コンソール上でIAMロールをリスト表示するためのポリシーを作成します。ポリシーの名前は「oktasso-test-policy」にします。インラインで以下のJSONを記載しましょう。リストに必要な最小権限を付与しております。
JSONもコピーして使えるように以下に記載します。

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:ListRoles",
"iam:ListAccountAliases"
],
"Resource": "*"
}
]
}
IAMユーザを作成します。

名前は「oktasso-test-user」にしました。コンソールへのアクセスは必要ないのでチェックはいれなくて問題ないです。

先ほど作成したカスタムポリシーを直接付与しておきます。
IAMユーザ作成後、アクセスキーとシークレットアクセスキーの払い出しておきます。

「セキュリティ認証情報」のタブから、アクセスキーを作成しましょう。
作成されたら、csvファイルで保管するか、コピーしてローカルに控えておきます。
ここまででAWS側の設定が完了しました。
- 信頼関係を結ぶOktaプロバイダーとメタデータを連携
- フェデレーション先のIAMロールの作成
- 管理コンソール上でアサーション情報(属性情報)に含むロールをリストするためのIAMユーザ・ポリシーの作成
最後にOkta側で残りの設定を済ませていきましょう。
まずは、アカウントフェデレーションをプロビジョニングできるようにします。統合はできても、機能を有効化しないと使えません。「プロビジョニング」-「統合」から、「API統合を構成」を押下しましょう。

ここで、Oktaユーザに割り当てるロールを指定するための設定を行います。まずは、ロール情報をアカウントからリストするためのアクセスキー・シークレットキーを入力しましょう。

「プロビジョニング」-「アプリへ」からロールを引き受けるOktaユーザに資格情報を割り当てる必要があります。フェデレーション時に引き渡すアサーション情報をこの設定で更新することになります。
「ユーザーを作成」「ユーザー属性を更新」いずれも有効化しましょう。

「割り当て」から「ユーザーに割り当て」を選択します。


こちらはSAMLアサーションに含まれる情報になります。基本デフォルトでよいですが、下にロールのマッピングが表示されています。SAML Users Rolesが出力されていますね。先ほど別途IAMユーザを作ったのは、Oktaのプログラム上からIAMのリストを出力する(指定する)ためだったんですね。ここではもちろん「okta-test-role」を指定します。
ここまでで設定が完了しました。
動作確認
実際にOktaからAWSコンソールにアクセスできるか試してみましょう。
Oktaにログイン後、ダッシュボードから、「AWS Account Federation」を押下します。

ログイン画面に遷移しますので、「okta-test-role」を選択して、「サインイン」を押下します。

ロールをAssumeして、コンソールにログインできていることが確認できました。

参照リンク
検証をする上で、以下に助けられました。本当にありがとうございます。
【Okta公式】
【構築ブログ】
最後に
外部IdPの情報を使ってAWSアカウントにSAMLフェデレーションする仕組みはよく利用されるかと思います。今までは内部でIdPとSPがどのようなやり取りをしているのかあまり意識することはなかったのですが、SAMLを基礎から学ぶことでなぜそれを設定する必要があるのか、解像度が上がってきましたね。
今回は、1つのIdPを利用してSAML認証してみましたが、下記の例ではどうでしょうか。
複数のIdPを使ってアクセスしたい。けど、SAMLフェデレートの設定をアカウントごと、IdPごとに設定するのは骨が折れる...といった運用面での困難があるかと思います。Identity Centerを使えば複数アカウントへのアクセスを1度の設定で取りまとめることが可能ですが、1つのIdPしか連携できないといった制約もございます。そんな時はどうすればいいのかといった内容も今後検証してみたいと思っております。お読みいただきありがとうございました。






