DMM.comの、一番深くておもしろいトコロ。

管理システムの改善でSCIMを採用した話

管理システムの改善でSCIMを採用した話

  • このエントリーをはてなブックマークに追加

はじめに

この記事は、DMMグループ Advent Calendar 2021の18日目の記事です。 技術支援チームの中村です。普段は社内全般で使うツールの開発・保守や社内用の認証・認可基盤に関する業務を行っています。

本記事は弊社の社内システムでSCIMを採用した話ですが、SCIMとはなにか・ユーザープロビジョニングのSCIM以外の選択肢の話・なぜSCIMを採用したのか という所をベースに簡単に説明いたします。

弊社システムでの連携後のイメージはこちらです。 f:id:dmmadcale2021:20211208184434p:plain

目次

SCIMとは

System for Cross-domain Identity Management (SCIM) とはリソースのプロビジョニングとデプロビジョニングに関する仕様です。2011年12月に1.0が発表され、2015年9月にSCIM2.0がRFC化 (RFC7642,RFC7643,RFC7644)しました。

この仕様は共通のユーザースキーマと拡張モデルを提供し、HTTP API (REST like) によるCRUD操作でスキーマのやりとりをJSON形式で行うなどの仕様により、ユーザ管理操作のコストと複雑さという問題の緩和を目指しています。

なぜこの仕様ができたかというと、ユーザー情報を記述して交換するための既存の標準は過去にもいくつも存在していましたが、これらの多くは実装が困難なものでした。

例えば下記のようなものです。

  • 形式がXML
  • 複雑な仕様
  • 拡張が難しい

その結果、各事業者がユーザーを管理するために標準化されていないプロトコルを実装することになりました。また、企業が複数の製品やサービスを利用する際に、各プロトコルの仕様に合わせて統合部の開発を行わなければならず、コストと複雑さが問題になっていました。それらの改善のために生まれた仕様がSCIMです。

SCIM自体の説明について詳しく知りたい方は、2017年のアドベントカレンダーの SCIMを知らない人向けSCIMの超基礎をご確認ください。

登場人物 (クライアントとサービスプロバイダについて)

SCIMを理解するために、まずは理解しておく必要がある2つの用語から説明します。SCIMの仕様ではクライアント(client)とサービスプロバイダー(Service Provider)を定義しています。クライアントは多くの場合はAzureADなどのアイデンティティプロバイダ(Identity Provider)で、多くのユーザー情報管理しているサービスです。

サービスプロバイダは多くの場合はSlackなどのSaaSであったり、AWSのSSOであったり、自作したアプリケーションなどのクライアントのアイデンティティの一部ないしは全体を必要とするシステムです。もちろん、アイデンティティプロバイダが他のアイデンティティプロバイダからデータを受け取るためにサービスプロバイダの役割も兼ねることも考えられます。また、単にSCIMサーバーと呼ばれることもあります。

SCIMでの振る舞いのイメージ

よくある動きとしては、クライアントのユーザーのアイデンティティ情報の作成・更新・削除にあわせてSCIMプロトコルに合わせたリクエストをSCIMサーバーに送るというケースです。リクエストによってSCIMサーバー側のデータを変更することにより、アイデンティティに関する情報を常に最新の情報に保つことができます。 f:id:dmmadcale2021:20211208184506p:plain

では次にリクエストのサンプルを見てみましょう。リクエストのボディにはJSON形式でユーザーのアイデンティティに関する情報が含まれています。

curl -i -X POST -H "Accept-Encoding:gzip" -H "Authorization:Bearer test-secret" -H "Content-Type:application/scim+json; charset=utf-8" -d '{
    "externalId": "test1",
    "UserName": "test2",
    "DisplayName": "test3",
    "Active": true,
    "schemas": [
        "urn:ietf:params:scim:schemas:core:2.0:User"
    ],
    "emails": [
        {
            "Primary": true,
            "type": "work",
            "value": "test4@example.com"
        }
    ]
}' 'http://localhost:3000/scim/Users'

また、先程のリクエストのレスポンスの例(Bodyのみ)を見てみると下記のようになります。

{
    "schemas": [
        "urn:ietf:params:scim:schemas:core:2.0:User"
    ],
    "id": "efcf33c01683482a8e2bf0a61718856d",
    "externalId": "test1",
    "meta": {
        "resourceType": "User",
        "created": "2021-10-13T11:00:00.000Z",
        "lastModified": "2021-10-13T11:00:00.000Z"
    },
    "userName": "test2",
    "displayName": "test3",
    "active": true,
    "emails": [
        {
            "type": "work",
            "value": "test4@example.com"
        }
    ]
}

このようにリクエストもレスポンスもREST likeなAPIを作っている人にとっては、比較的理解しやすい形です。

ユーザーのアイデンティティ情報の連携方法の検討

最初にSCIMとはなにかを説明しました。ここからは「なぜSCIMを社内のシステムに採用したのか」ということについて順にお話していきます。まずはユーザーのアイデンティティ情報の連携方法についてですが勿論SCIMのようなAPIによる連携方法だけではありません。方法は多々あると思いますが、例えば下記のようなものが考えられます。

  1. マスターデータに合わせて手作業でデータ管理

  2. ユーザーを管理しているシステムで認証成功し連携許可時にデータを作成・更新 (ジャストインタイムプロビジョニングなど)

  3. RDBやLDAPなどのDBに一定間隔でポーリング

  4. IDを管理するシステム側でリソースの状況に応じたAPIの実行

それぞれのケースと各種方法を採用する時の検討材料の例と合わせて、簡単に表として比較すると下記のようになります。

No 作成・更新・削除への対応 反映の即時性 対応漏れの少なさ 備考
1. 手作業 - 対応するデータ量によっては対応に人的コストがかかる。
- 即時反映できない時があり、退職時などで情報の漏洩のリスクに繋がる。
- 人為的ミスが発生しうる。
2. 認証時同期 - 複数のアカウントで連携するグループウェアでは、連携先のアカウントが認証成功後でないとアカウントが見つからない。
- 削除方法の検討が必要。ログインはできないが、アカウントが残っているケースは予期せぬ情報漏洩のリスクに繋がる。
3. ポーリング - IDを管理するシステムに直接アクセスするため十分にセキュアで冗長構成な経路が必要。
- ポーリングによって、不要なアクセスを行うため負荷の増大。
4. API - 独自仕様のAPIが出来上がり、再利用のしづらさ・仕様の複雑化による技術負債化 ⇒ SCIMで軽減できる。

その中から弊社は4の IDを管理するシステム側でリソースの状況に応じたAPIの実行 およびそのプロトコルとしてSCIMを採用したのですが、まず4のAPIでの連携を選定した理由2点について説明します。

1. 十分に要件に合致

1つ目は要件への合致です。 当プロジェクトではざっくり下記のような要件がありました。

  • ユーザーを管理しているシステム(WindowsServer)での変更に合わせて反映が速やかに行われること
  • データの反映は作成・更新だけでなく、削除も含まれること
  • 自動化し作業の漏れが発生しないこと

作業漏れや人的リスクをできる限り回避したいということと、自動化し作業の漏れが発生しないようにするという要件でまず1番の手作業という選択肢が外れました。

また ユーザーを管理しているシステムで認証成功し連携許可時にデータを作成・更新する という2番の選択肢は、デプロビジョニング(ユーザーの削除)はどうするかという問題を含んでおり、デプロビジョニングが必要であったために、2番の選択肢のみの採用はなくなりました。

その結果、下記のどちらかを検討することになりました。

  • 2番(認証時同期) + 3番(ポーリング) or 4番(API)
  • 3番(ポーリング) or 4番(API)

2. 当プロジェクトの環境とポーリング形式の相性の悪さ

次に3番(ポーリング) or 4番(API) の選択肢からどちらを選ぶかという話ですが、我々は4番(API)を選ぶことにしました。理由の1つが弊社の環境がポーリング形式と相性が悪かったという理由になります。

ポーリング形式ではIDを管理するシステムに直接アクセスするため十分にセキュアで冗長構成な経路が必要です。そこでAPI(SCIM)との判断材料で気になったのが下記の2点です。

  • ポーリングの処理自体がユーザーを管理しているシステムに対して負荷をかけてしまう可能性
  • 十分にセキュアで冗長・セキュアな経路の維持にかかるコスト・複雑性
    • 管理コストの増加
    • 経路確保のための費用
    • システムの複雑性の増加

ポーリングの処理自体がユーザーを管理しているシステムに対して負荷をかけてしまう可能性は、十分な負荷試験と処理するデータの取得件数の制限・取得タイミングの制限などで影響がないことを保証できそうでした。

ですが、検討材料として気になったのは 十分にセキュアで冗長・セキュアな経路の維持にかかるコスト・複雑性 です。「このプロジェクトでのみの専用の経路を準備するコスト・および管理コストがかかること」「システム全体で見た時の複雑性が少し増加してしまうこと」「経路確保のために少し余分な費用がかかること」などを踏まえて4番のAPIの実行という形式を我々は選択することになりました。

なぜSCIM?

ここまでで、IDを管理するシステム側でリソースの状況に応じてAPIを叩いてもらうという方針は決まりました。ではなぜ、その方法をSCIMにしたかというと下記の2点です。

1. Azure Active Directory がSCIMのクライアントとして対応

当プロジェクトでは当初オンプレミスのWindowsServerと連携していたのですが、オンプレミスのWindowsServerにはSCIMのクライアントとしての機能がありませんでした。ゆえにAPIでの連携する場合は連動してAPIを叩いてもらうための仕組みを用意する必要があります。

しかし、主に下記の理由もありオリジナルなAPIを作成して連携するのも悩ましく、ポーリング形式でユーザーをプロビジョニング・デプロビジョニングを行っていました。

  • データの更新に合わせてAPIを叩いてくれるようにWindowsServer側などでバッチ処理を行う必要があり、少し手間がかかる。
  • 作成したオリジナルなAPIを再利用する場がほぼない + 再利用しづらい

しかし、プロジェクトの途中で弊社のユーザー管理関連のシステムにおいてAzure Active Directoryと連携できるようになり、これはSCIMクライアントとして機能します。これによりSCIMに合わせてAPIを作るだけで上記2つの問題も解決し、比較的シンプルな構成でユーザープロビジョニング・デプロビジョニングの仕組みを実装できるので、その良さを活かそうと思ったのが1つ目の理由です。

2. 共通仕様の採用で、他のSCIMのクライアントとの連携しやすさなど今後の拡張性

もう1つの理由として、オリジナルなAPIで連携する場合は、ある程度の軽減はできますが再利用しづらいものになってしまうことが多々あります。これをできる限り再利用しやすいAPIにしたかったという点です。

もしSCIMプロトコルに準拠していなかった場合、連携先が増えるごとに再実装・結合した検証が必要になり、複雑さとコストが重くなってしまう可能性が考えられます。しかし、SCIMに準拠しておくことで、現在はAzureADと連携していますが他のSCIMに準拠したシステムとも連携しやすくなると考えています。

SCIMを採用してみた結果(所感)

では最後にSCIMを採用してみた所感について簡単に共有します。

良かった点

  • ライフサイクルが自動化することにより手作業を挟まないので運用が比較的に楽

  • 自動的にすみやかにデプロビジョニング(削除・非アクティブ化)されるのでセキュリティリスクの軽減

    • 他のSSOなどのシステムだけだと独自セッションなどをシステムがもつ場合、実装次第では独自のセッションが切れずにアクセスし続けることができるケースも考えられ、削除されるまでのタイムラグが怖い。
  • 仕様に合わせて実装するだけなので、オリジナルのAPIを作るよりはAPIの作成に関して検討することが比較的少ない

    • とはいえAPIの認証方法などについてはSCIMでは決まっていないので別途検討が必要である
  • HTTPのAPIベースの連携のため監視が比較的容易である

検討が必要な点

調査していくにあたって、気になったのは下記の点です。これらに関しては関連記事の方で説明していますので、こちらもご確認ください。参考: Azure Active DirectoryとSCIMでプロビジョニングする時のTIPS

  • SCIMの同期(プロビジョニング)の間隔は連携するIdPなどのSCIMクライアントの仕様により前後するため、SCIMの調査前は即時同期されるイメージだったが実際に調査していくとタイミングに制約がある

  • どのタイミングでSCIMのCRUDが実行されるかということについて、連携するIdPなどのSCIMクライアントの仕様によるため調査が必要である

  • 言語によっては十分な実装のライブラリが見つからず、自作する必要がある

あとがき

この記事は SCIMとはなにかなぜSCIMを採用したのかSCIMを採用してみた結果(所管) などを簡単に説明しました。読者の方がユーザープロビジョニングの方法を検討する際にこの記事が少しでも参考になれば幸いです。