人事データベースHRMOS Coreチームのdoyaaaaakenです。

最近はKotlinでサーバサイドをメインに開発しています。
なお、本日が最終出社日です!(新手の退職エントリですw)

今回、日本語・英語どちらの資料も少ない、珍しい規格を用いた開発を行ったので、それについて簡単に紹介します。

何をやったか

弊社では、現在HRMOS Coreと呼ばれる人事データベースを開発しています。

そこで、SlackやSalesforceなどメジャーなクラウドサービスも採用している SCIM(System for Cross-domain Identity Managementの略) と呼ばれる規格に準拠した、汎用的なユーザ情報連携のためのAPI群を開発しました。

開発した背景

HRMOS Coreは人事データベースであるという特性上、社員情報を一元管理し、入社、退社、人事異動などの社員情報のライフサイクルの管理も行ないます。

そして、クラウドサービス全盛の今、一元管理された社員情報をSlack、Salesforceなどの各種クラウドサービスとどの様に連携するかという課題があります。
これらをシステム的に処理するには、他のクラウドサービスが社員情報を取得できるようにするためのAPIや、社員情報の変更を他サービスにプッシュするユーザープロビジョニング/デプロビジョニング機能が必要です。

この一連の仕組みを汎用的に実現するためにSCIMの規格を検討、採用しました。

機能概要図

SCIMとは?

クラウドベースのアプリケーション間でアイデンティティ情報を連携するための仕様です。

ここでいうアイデンティティ情報とは、ユーザー情報と、ユーザーを包含するグループ情報を指しています。これらの情報はどの様なサービスでも必要になる情報だと思います。

SCIMでは、連携のための共通仕様を定義することで、他のサービスとの連携を簡易にすることを目標としています。1

SCIMが必要とされる背景

背景でも軽く触れましたが、エンタープライズ向けサービスにもクラウドが普及したことで以下の様な問題が生まれました。

ユーザアカウントの運用部門にとっての問題

クラウド製品の開発者にとっての問題

他サービスとのユーザ情報連携を実現する上で、サービスごとの固有仕様に沿って実装する必要があり、工数が増えてしまう

これはほんの一例ですが、こういった問題を解決するため、アイデンティティ情報連携のための共通仕様を策定しようという話がSCIMです。

SCIMの仕様

仕様概要

詳細に関しては公式のページを参照頂くとして、概要だけ紹介します。

SCIMは、ユーザ情報やそれを包括するグループ情報などのアイデンティティ情報を連携するためにJSON・HTTPを利用したプロトコルです。

REST APIベースで、以下のような仕様が定められています。

定義されているリソース

ユーザー情報を表すUserリソース、ユーザーを包含するグループを表すGroupリソースなどが RFC7643 として定義されています。
各リソースの属性は独自の項目を拡張することが可能です。

URLの命名パターン

リソースごとにURLのパターンが決まっており、Userであれば https://example.com/**/User といったURLになります。

エンドポイントのHTTPメソッドおよびその挙動

POSTは新規作成処理, PUTは置換処理, PATCHは部分更新処理として定義されています。

レスポンスのHTTPステータス

作成リクエストの場合は201、削除の場合は204など、リソースと操作毎に推奨されるステータスコードが定義されています。

リクエストパラメータ・リクエストボディー・レスポンスボディー

例えば、検索リクエストにおける検索条件は filter=title pr and userType eq “Employee” といった形式で条件を指定します。 PUT, POSTリクエストボディーについても、先程の RFC7643 である程度定められています。

連携方法

SCIMの処理を行う主体は、リクエストを送信する側であるクライアント、リクエストを受け付ける側であるサーバーいずれにもなりえます。

HRMOS Coreでは、クライアントとして他サービスへユーザ情報をプッシュ連携するUser Provisioning機能、サーバーとして他サービスからユーザ情報の参照・編集を受け付けるAPIをサポートしています。

SCIMに沿ったリクエストの例

具体的なリクエスト・レスポンスを見れば内容をより想像できると思うので、以下に掲載します。
各項目に入るべき値の意味、型、制約については、先程紹介した RFC7643 で定められています。

※ 例:「userNameは一意かつユーザフレンドリーな文字列」、「emailsは配列型でprimary=trueのものが必ず1つある」等

例1) ユーザ取得リクエスト

リクエスト

1
2
3
4
GET /v2/Users/2819c223-7f76-453a-919d-413861904646 HTTP/1.1
Host: example.com
Accept: application/scim+json
Authorization: Bearer h480djs93hd8

レスポンス

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
HTTP/1.1 200 OK
Content-Type: application/scim+json

{
  "schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],
  "id":"2819c223-7f76-453a-919d-413861904646",
  "externalId":"doyaaaaaken",
  "meta":{
    "resourceType":"User",
    "created":"2011-08-01T21:32:44.882Z",
    "lastModified":"2011-08-01T21:32:44.882Z",
    "location": "https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646",
    "version":"W\/\"e180ee84f0671b1\""
  },
  "userName":"doyaaaaaken",
  "userType": "Employee",
  "name":{
    "familyName":"Tanaka",
    "givenName":"Taro"
  },
  "phoneNumbers":[
    {
      "value":"555-555-8377",
      "type":"work"
    }
  ],
  "emails":[
    {
      "value":"taro.tanaka@example.com",
      "type":"work",
      "primary": true
    }
  ],
  "addresses": [
    {
      "type": "work",
      "streetAddress": "100 Universal City Plaza",
      "locality": "Hollywood",
      "region": "CA",
      "postalCode": "91608",
      "country": "USA",
      "formatted": "100 Universal City Plaza\nHollywood, CA 91608 USA",
      "primary": true
    }
  ],
  "urn:ietf:params:scim:schemas:extension:enterprise:2.0:User": {
    "employeeNumber": "701984",
    "costCenter": "4130",
    "organization": "Universal Studios",
    "division": "Theme Park",
    "department": "Tour Operations",
    "manager": {
      "value": "26118915-6090-4610-87e4-49d8ca9f808d",
      "$ref": "../Users/26118915-6090-4610-87e4-49d8ca9f808d",
      "displayName": "John Smith"
    }
  }
}

例2) ユーザ作成リクエスト

リクエスト

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
POST /v2/Users  HTTP/1.1
Accept: application/json
Authorization: Bearer h480djs93hd8
Host: example.com
Content-Length: ...
Content-Type: application/json

{
  "schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],
  "externalId":"doyaaaaaken",
  "userName":"doyaaaaaken",
  "name":{
    "familyName":"Taro",
    "givenName":"Tanaka"
  }
}

レスポンス

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
HTTP/1.1 201 Created
Content-Type: application/scim+json
Location: https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646
ETag: W/"e180ee84f0671b1"

{
  "schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],
  "id":"2819c223-7f76-453a-919d-413861904646",
  "externalId":"doyaaaaaken",
  "meta":{
    "resourceType":"User",
    "created":"2011-08-01T21:32:44.882Z",
    "lastModified":"2011-08-01T21:32:44.882Z",
    "location": "https://example.com/v2/Users/2819c223-7f76-453a-919d-413861904646",
    "version":"W\/\"e180ee84f0671b1\""
  },
  "name":{
    "familyName":"Taro",
    "givenName":"Tanaka"
  },
  "userName":"doyaaaaaken"
}

普及度合いについて

採用するかどうか検討する上で、実際に普及しているかどうかは気になると思います。

利用しているサービス

GSuite、Slack、Salesforce、 Azure Active Directory、 Trelloなどで利用されています。
他にも公式ページに対応しているサービス例が掲載されています。

RFCのステータス

SCIMの最新バージョンである2.0の内容は、2015年9月に RFC7642, RFC7643, RFC7644 に定義されています。

このうちStandard Track(標準化過程)に分類され、具体的な仕様について定義されているのはRFC7643, RFC7644ですが、これらのステータスはProposed Standard(標準化への提唱)の段階にあります。

この段階は、仕様として成熟しきってはいないが(将来仕様が変化する可能性がある)、インターネットコミュニティにおいて十分検討され、設計上の方針が確定しており、安定している段階だと定義されています。2 3

これらのことからSCIMの採用を検討しても良い段階に来ているのがわかると思います。

まとめ

エンタープライズの分野においてもクラウドサービスが増えてきたことで、サービス間の連携機能の重要性は増してきています。

まだまだ事例、資料等は少ないのですが、REST APIベースで簡単に理解できる仕様ではあるので、皆さんのサービスでもSCIMの採用を検討してみてはいかがでしょうか?

それでは良いIdentity Provisioning Lifeを!

参考

ビズリーチでは、新しい仲間を募集しています。

お客様にとって価値あるモノをつくり、働く環境の変革に挑戦する仲間を募集しています。
募集中のポジションやプロダクト組織の詳細は、ぜひキャリア採用サイトをご覧ください。

ビズリーチ採用サイト
小山健太(doyaaaaaken)
小山健太(doyaaaaaken)

ずっと新規事業開発畑のサーバサイドがメインのエンジニア。KotlinやScalaを使っているがJavaを使ったことがなくたまに話しについていけないのが悩み。