Runner in the High

技術のことをかくこころみ

SCIMなどの外部連携インターフェイスがアプリケーションの仕様を侵食する件

今回はちょっとエンタープライズなハナシ。

そもそもSCIMってなに

このQiitaの記事が詳しい。
要はマスターデータを連携するためのWebAPIのインターフェイスの規格的なもの。 qiita.com

SCIMインターフェイスはつらい

B2Bのプロダクトだとマスターデータの連携を行う目的でSCIMインターフェイスの口を提供するケースがあるが、SCIMはビジネスルールを侵食する

まずSCIMにはスキーマとして次の仕様があるが、SCIMインターフェイスを実装するアプリケーションは基本的にスキーマごとの仕様を実装することがほぼ必須になる。

  • Groupスキーマの仕様
    • Groupの階層化(あるGroupが子となるGroupを複数持つことができる)
    • Userの所属(Groupに複数のUserが所属できる)
  • Userスキーマの仕様
    • 物理/論理削除

「必須になる」と書いているのは、アプリケーションはスキーマ単位で取捨選択はできるが、スキーマにおける仕様を取捨選択することはできないからである。たとえばGroupスキーマをサポートしながら、Userの所属のみを採用し、Groupの階層化をサポートしない、というのはほぼ不可能*1になる。

実際のAzureADでのケースを挙げると、AzureDAサイドでグループの階層化が行われている場合には、SCIMのグループ更新のリクエストに階層化されたグループの情報が乗ってくる。アプリケーション側は階層情報をどこかで必ず保持しなければいけない。リクエストを読み捨ててしまうと、続いて不定期でやってくるAzureADからの永続化チェックのレスポンスを作れないからである。AzureAD側が満足するレスポンスを返せないと、永遠にリクエストが飛んでくることになるし、永続化に失敗しているとみなされればAzureADの場合には「検疫モード」に移行し、連携処理がしばらく止められてしまい顧客に迷惑をかける。

これは、SCIMインターフェイスがアプリケーションから「〇〇の機能は提供していない」みたいなリクエストを受け取る選択肢を提供していないためだ。したがって、SCIMを使うからには常にSCIMのルールに乗らなければいけない。これが「プロダクトのドメインSCIMの仕様に侵食される」と述べた理由である。

たとえばグループ削除のポリシーについて

もっと踏み込んだ話をする。 たとえば、SCIMではグループの削除がインターフェイスとして存在しているため、SCIMをカバーする場合には我々サイドのアプリケーションもグループの削除をサポートせねばならない。

また、SCIMのグループは階層化もサポートしているため、階層化されているグループの削除のポリシーも考えることになる。 簡単に考えても、階層化されているグループを削除する場合には次の4パターンがある。

  1. 親グループが消えたら子グループも消える
  2. 親グループが消えても子は残るがもとの親の親に紐づく(この仕様は子が親をひとつしか持たない場合のみ有効)
  3. 親グループが消えた場合には子は親を持たないグループになる
  4. 子グループを持つ親は削除できないようにする

さて、この4つの選択肢を出したとしてもSCIMでAzureADをサポートする場合にはc以外の選択肢を持つことができない。なぜならAzureADがcだからである! 我々が違う選択をしてくても、SCIMを使っている限りはSCIMに寄り添う以外不可能。そういうことなのである。

もちろんAzureADに対応しないという選択もできるが、シェアを考えると現実的ではない。

どうすればいいのか

自前のWebAPIのみを提供するという選択肢がある。これであれば自分たちで仕様を決められるのでSCIMに引きずられることはない。

しかし自前のWebAPIとなると、今度は顧客側に対応の工数を求めることになり、B2Bサービスなどは受注や導入開始などのリードタイムを長くする可能性がある。 B2Bアプリケーションにおいて「導入の容易さ」は大きな武器であり、ここを犠牲にするのは確実におすすめできない。

SCIMの利点はマスタデータを提供する多くのサービス(Okta, GSuite, AzureAD, etc)が大抵の場合すでにインターフェイスを実装しているため、使う側からすると導入コストがゼロに等しくなるというアドバンテージがある。 ビジネスの観点からするとここには勝てない。

顧客との力関係やその他もろもろの都合が合うのであれば「SCIMなどの外部連携インターフェイスを使わない」という選択肢も検討できるだろうが、本当にそれができるかはまた別問題である。

余談

AzureADとのSCIM対応は仕様を知ったり実装をする点でも実は結構大変... なのだが、それはまた別記事で書こうと思う。

*1:もちろん、バックエンド側でSCIMとの連携情報保持でしか使わないテーブルを用意するだけに留めるというのは可能。しかし、逆に言うと最低限それは絶対にやらなければならない。なにもしないは不可。