はじめに
技術支援チームの中村です。
DMM社内で開発をちょっと便利にするようなツールを作成するチームに所属しています。
具体的には、2016年から運用されている社内用の認証・認可基盤の改善をプロジェクトの1つとして進めています。当プロジェクトではユーザーに関する情報をWindowsServerのActiveDirectoryで管理しており、そのデータをAzure Active Directory Connectを使いAzure Active Directoryと連携しています。
また当プロジェクトにおいて、ユーザーのアイデンティティのプロビジョニングをSCIMで行いましたので、連携時に気になったAzure Active Directoryの仕様やサービスプロバイダの実装・ライブラリの選定時に気にすべきことなどを紹介していきます。
連携のイメージ図は下記のような形になります。
SCIMで連携中に気になった Azure Active Directory 関連の仕様
では実際にAzure Active DirectoryとSCIMで連携している際に、気になった点について簡単に説明していきます。
1. Patchでactiveがbooleanではなく文字列で返却されてしまうのはどうする?
現時点で何も対応をしない場合は、PATCHメソッドによる更新の際に active
の値がboolean値ではなく文字列で返却されてしまい、RFCとずれてしまうため多くの実装で想定外の動きになります。この件に関してはMicrosoft社のドキュメント※1 にあるとおりに、アプリケーションのテナントURLにフラグを有効にするパラメータaadOptscim062020
を追加すると解決します。例示すると、https://hoge.example.com/scim/?aadOptscim062020
のような形になります。
レスポンスに含まれるJSONは下記のように変化します。
- フラグ追加ありのケース
{
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:PatchOp"
],
"Operations": [
{
"op": "Replace",
"path": "active",
"value": "True"
}
]
}
- フラグなしのケース
{"schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"],"Operations":[{"op":"replace", "path":"active","value":false}]}
{
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:PatchOp"
],
"Operations": [
{
"op": "replace",
"path": "active",
"value": false
}
]
}
2. SCIMのプロビジョニング間隔はどれくらい? 変更可能?
1つ目はSCIMのプロビジョニング間隔がどれくらいかということです。Microsoft社のドキュメント※2 を見ると仕様上は自動で動く周期は40分固定であるため、手動で動かさないかぎりは約40分ごとにまとめてSCIMのAPIが実行されます。
またオンプレミスのWindowsServerとAzure Active Directory Connectで連携する場合、Microsoft社のドキュメント※3 を見るとAzure Active Directory Connectの同期間隔は最短30分です。
そこでどちらも自動で動かしており手動対応しないというケースを想定すると、最悪の場合はオンプレミスのWindowsServerでのアカウント情報の変更から、約1時間10分後に反映されるというケースもありうるということになります。
ですが、どちらも必要があれば都度同期を実行も可能なので、緊急性を要するものも対応は可能です。
3. Azure Active Directory からのSCIMにIP制限をどうかけるべき?
SCIMのリクエストに対して、まずはAzure Active Directoryからのリクエストのみを許可しようと考える方は多いと思います。
Microsoft社のドキュメント※2 から遷移後にダウンロードできるJSONのAzureActiveDirectory
タグの約120個のIPアドレスのブロックがプロビジョニングに使われるようですので、これらが参考になると思います。
4. SCIMがどのタイミングでどのメソッドが実行される?
どの挙動に影響してどのSCIMメソッドが実行されるかということは事前に把握しておく必要があります。
例えば弊社の場合はオンプレミスのWindowsServerをAzure Active Directory ConnectでAzure Active Directoryと連携している状態です。この状態でAzureのポータル画面での変更・オンプレミス側のActive Directoryでいくつかの操作を試すと下記のような結果になりました。
どこでの操作か | どんな操作か | SCIMのHTTP Method | 備考 |
---|---|---|---|
Azureのポータル画面 | サインインのブロック | PATCH | active を false に変更 |
Azureのポータル画面 | すべてのユーザー より論理削除 | PATCH | active を false に変更 |
Azureのポータル画面 | 削除されたユーザー より物理削除 | DELETE | |
Azureのポータル画面 | アプリと関連づけたロールの削除 | PATCH | active を false に変更 |
オンプレミスAD | アカウントの無効化 | PATCH | active を false に変更 |
オンプレミスAD | アカウントのロック | - | 何もしない |
オンプレミスAD | アカウントの有効期限切れ | - | 何もしない |
オンプレミスAD | パスワードの有効期限切れ | - | 何もしない |
オンプレミスAD | アカウントの削除 | PATCH | active を false に変更 |
オンプレミスAD・Azureのポータル画面 | アカウントの作成 & ロール付け | POST |
また、Microsoft社のドキュメント※2 を見る限りでは、Azure Active Directoryでは、SCIMのPUTメソッドを叩くことは基本的にはないように見えます。
5. シークレットトークンが空の場合は何がとどく?
プロビジョニングの設定時に 管理者資格情報
の シークレットトークン
は空のまま設定を登録できます。
ではシークレットトークンを空にした場合にどうなるのか、なぜ駄目なのかという話ですが、Microsoft社のドキュメント※2 の中にある下記の記述を確認しましょう。
このフィールドを空白のままにすると、Azure AD では各要求に Azure AD を発行元とする OAuth ベアラー トークンを含めます。 ID プロバイダーとして Azure AD を使用するアプリは、この Azure AD によって発行されたトークンを検証できます。
このフィールドを空白のままにして、Azure AD によって生成されるトークンに依存することは推奨 "されません"。 このオプションは、主にテスト目的で使用できます。
このようなケースで実際に Authorization ヘッダーに含まれる値を確認すると、下記のようなJWT形式の値を確認できます。
Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Imwzc1EtNTBjQ0g0eEJWWkxIVEd3blNSNzY4MCIsImtpZCI6Imwzc1EtNTBjQ0g0eEJWWkxIVEd3blNSNzY4MCJ9.eyJhdWQiOiI4YWRmOGU2ZS02N2IyLTRjZjItYTI1OS1lM2RjNTQ3NmM2MjEiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9kMjc0M2Q4OC0zZDdhLTRlMzYtOWExMC04MjdkODQ5NzM1YzIvIiwiaWF0IjoxNjM0MTEzMjcyLCJuYmYiOjE2MzQxMTMyNzIsImV4cCI6MTYzNDE5OTk3MiwiYWlvIjoiRTJaZ1lKZ1ZmYkQvLzluRTFZcFRUNXRkbXZWclBnQT0iLCJhcHBpZCI6IjAwMDAwMDE0LTAwMDAtMDAwMC1jMDAwLTAwMDAwMDAwMDAwMCIsImFwcGlkYWNyIjoiMiIsImlkcCI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0L2QyNzQzZDg4LTNkN2EtNGUzNi05YTEwLTgyN2Q4NDk3MzVjMi8iLCJvaWQiOiJkOWY4YzAyYy01NmFlLTQ4NGUtYjE2ZC01NjQ1MzJmZGRkNjEiLCJyaCI6IjAuQVZVQWlEMTAwbm85Tms2YUVJSjloSmMxd2hRQUFBQUFBQUFBd0FBQUFBQUFBQUJWQUFBLiIsInN1YiI6ImQ5ZjhjMDJjLTU2YWUtNDg0ZS1iMTZkLTU2NDUzMmZkZGQ2MSIsInRpZCI6ImQyNzQzZDg4LTNkN2EtNGUzNi05YTEwLTgyN2Q4NDk3MzVjMiIsInV0aSI6InAwVDJ2b0h4VkVlLTI3bm9OTmt2QUEiLCJ2ZXIiOiIxLjAifQ.CJc9LntZsowWGYZTpdbk1aglx19Z8rE42vcDiWpH9kdmWhvDp8VR2x8u7Du4hfURnQBQjbLzTpnVcKFpIepdh4T_Xguq_GtRRsyDSplNnNcHDCeAH6W3RcJnHAhcAylFVtZXutJRQN4870leqi8kq5LAgPszoDY_K_mSZPiX_G60wyWU-UyUqoeVGBIo_1B6ue2-5xJBMfuESTjU8jJEtxFRIPCLb9HZXRy9CX8HA8RSf79mYjaCRR-h7GJ5IWChZTbJObOO-btSaDHk4omU-2WA6Fv7-OE8_LUXlw8hu1EaOv1ekYpKTFhkyPgMDFEhDcwHmyfp4H-YZk-YgRdAww
このJWTはJWSのようなので、OpenID Connect Discovery
の仕様に則った、エンドポイントに問い合わせて jwks_uri
を取得して、そこから ヘッダーに含まれる kid
の値と同じ鍵を見つけてくることで、署名の検証も可能です。
ですが Microsoft社のドキュメント※2 では、設定画面のシークレットトークンの欄を空白にすることで、AzureADによって生成されるシークレットトークンを用いることは推奨していません。ではなぜこのシークレットトークンを使ってはいけないかというと、簡単に記載すると下記の2点です。
-
SCIMクライアント側が発行したトークンを使うべきではないから
(※ サービスプロバイダ側の意思で無効にできないなど諸々問題がある) -
Azure Active Directoryがシークレットトークンを発行する動作はテスト用であり、今後変更や廃止される可能性が0ではないから
6. Postmanでテストする時に気をつけることは?
最後にPostmanについてですが、Microsoft社のドキュメント※2 には下記のような記述があります。
SCIM エンドポイントを構築したら、それをテストします。参照コードの一部として提供されている Postmanテストのコレクションを使用したり、上記の要求または応答のサンプルを通じて実行したりすることができます。
ではMicrosoft社のGithubリポジトリであるAzureAD/SCIMReferenceCode※4 を見てみましょう。
Postmanのリクエストでは Content-Type
は application/json
になっています。ですがAzure Active DirectoryからのリクエストではRFC7644※5 の記載どおり application/scim+json
です。このように差異のある可能性がありますので注意が必要です。
Content-Type | |
---|---|
Postman | application/json |
Azure Active Directory | application/scim+json; charset=utf-8 |
SCIMのサービスプロバイダ側の実装 or ライブラリの選定時で確認すべきこと
サービスプロバイダを実装する際に参考にするため、私はGithubで検索してでてきたいくつかのリポジトリを参考に開発しました。しかしSCIMはそこまで人気の高い技術ではないため、まだまだ開発途中のライブラリという印象のものが多くあります。
ゆえに自作する場合や既存のライブラリの採用時には、いくつかの確認が必要だと思ったのでその気になった点を簡単に共有します。
1. filter の演算子はどれを対応している?
Microsoft社のドキュメント※2 によると eq
と and
の対応が必要です。ですが実装によっては eq
の演算子にしか対応していないライブラリもあるようです。
これらの場合、正しくリクエストを処理できないということにつながりますので、SCIMのクライアントとサービスプロバイダはそれぞれどの演算子に対応しているかについて確認しておくと良いと思います。
2. 属性名などは case insensitiveか?
RFC7643※6 によると、Attributes
は case insensitive
なので大文字・小文字を区別しません。
ですが実装によっては case sensitive
に実装しているライブラリがありました。特定の処理の時だけ失敗するという問題が生まれかねないので、注意が必要です。
3. 不適切なリクエストをエラーにできているか?
例えば、RFC7644※5 にあるようにPatch のリクエストの場合はボディの schema 属性に、 urn:ietf:params:scim:api:messages:2.0:PatchOp
という値を持たせておく必要があります(MUST)。
これはかなりわかりやすい例ですが、これすらチェックしていないライブラリは存在します。共通した仕様に則るという良さを消してしまう可能性がありますので、ライブラリの一連の処理を確認しておくと良さそうです。
schema 属性に含まれている例はこちらです。
{
"schemas": [
"urn:ietf:params:scim:api:messages:2.0:PatchOp"
],
"Operations": [
{
"op": "replace",
"path": "active",
"value": false
}
}
4. 適切なレスポンスを返却できているか?
RFC7644※5 によると、実装者はHTTPレスポンスコードを返すことに加えてレスポンスのボディ内のエラーを、RFCに記載のある属性を用いてJSON形式で返さなければなりません(MUST)
ですがこれを忠実に実装しているライブラリばかりではなく、単一のエラーに多くのケースを丸め込んでいるものがありました。エラー時のわかりやすさのためにも、RFCどおりのエラークラスなどを自作すると良いと思います。
おわりに
今回は弊社でSCIMを採用したことで気になったSCIMに関連するシステムの仕様や、実装や選定時に注意すべきことについて簡単にまとめました。この記事がAzure Active DirectoryでSCIMを試そうとされてる方にとって、少しでも参考になれば幸いです。
参考・引用
※1. Microsoft. "Azure AD ユーザー プロビジョニング サービスの SCIM 2.0 プロトコルへのコンプライアンスに関する既知の問題と解決策". docs.microsoft.com.
https://docs.microsoft.com/ja-jp/azure/active-directory/app-provisioning/application-provisioning-config-problem-scim-compatibility
※2 Microsoft. "チュートリアル: Azure Active Directory の SCIM エンドポイントのプロビジョニングを開発および計画する". docs.microsoft.com.
https://docs.microsoft.com/ja-jp/azure/active-directory/app-provisioning/use-scim-to-provision-users-and-groups
※3 Azure Identity Support Japan. "Azure AD Connect に関する FAQ". Japan Azure Identity Support Blog.
https://jpazureid.github.io/blog/azure-active-directory-connect/azureadconnect_faq/
※4 Microsoft. "Test Your SCIM Endpoint". GitHub.
https://github.com/AzureAD/SCIMReferenceCode/wiki/Test-Your-SCIM-Endpoint.
※5 Internet Engineering Task Force (IETF). "System for Cross-domain Identity Management: Protocol". IETF Datatracker.
https://datatracker.ietf.org/doc/html/rfc7644
※6 Internet Engineering Task Force (IETF). "System for Cross-domain Identity Management: Core Schema". IETF Datatracker.
https://datatracker.ietf.org/doc/html/rfc7643