# LDAP group を keycloak に読み込む方法 ## 参考 - https://extensions.xwiki.org/xwiki/bin/view/Extension/OpenID%20Connect/OpenID%20Connect%20Authenticator/OpenID%20Authentication%20with%20Keycloak/Keycloak%20Group-Mapping/ - https://www.janua.fr/mapping-ldap-group-and-roles-to-redhat-sso-keycloak/ ## 環境 keycloak: v21.1.1 ## 手順 1. Keycloak で LDAP の設定を済ませる 1. User federation から `Add new provider` をクリックし、LDAP を選択 2. 設定値を入力する 2. 作成した LDAP の User federation の詳細画面にいく 3. Mappers のタブを開く 4. `Add Mapper` をクリック 5. Name を適当に入力し、Mapper type に `group-ldap-mapper` を選択 6. 設定値を入力する - `LDAP Groups DN`: LDAP グループが所属するディレクトリの DN。 - `Group Name LDAP Attribute`: グループ object の RDN に使用されている attribute。 - `Group Object Classes`: グループ object の object class。複数ある場合は comma 区切り。 - `Membership LDAP Attribute`: グループ object の attribute のうち、所属メンバーを表すもの。 - `Membership Attribute Type`: `Membership LDAP Attribute` で指定した attribute の値の type。DN の場合は user object の DN が値として入っている想定。 - `User Groups Retrieve Strategy`: どのようにグループに所属しているユーザ情報を取得するか。LOAD_GROUPS_BY_MEMBER_ATTRIBUTE であれば、group object の Membership LDAP Attribute で指定した attribute 値を使って user を取得する。 7. 右上の Action から `Sync LDAP groups to keycloak` を選択 ## example 以下の内容で LDAP サーバデータがあるとする。 ``` # example.org dn: dc=example,dc=org objectClass: dcObject objectClass: organization dc: example o: example # users, example.org dn: ou=users,dc=example,dc=org objectClass: organizationalUnit ou: users # customuser, users, example.org dn: cn=customuser,ou=users,dc=example,dc=org cn: User1 cn: customuser sn: Bar1 objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount userPassword:: Y3VzdG9tcGFzc3dvcmQ= uid: customuser uidNumber: 1000 gidNumber: 1000 homeDirectory: /home/customuser # customuser2, users, example.org dn: cn=customuser2,ou=users,dc=example,dc=org cn: User2 cn: customuser2 sn: Bar2 objectClass: inetOrgPerson objectClass: posixAccount objectClass: shadowAccount userPassword:: Y3VzdG9tcGFzc3dvcmQ= uid: customuser2 uidNumber: 2000 gidNumber: 2000 homeDirectory: /home/customuser2 # groups, example.org dn: ou=groups,dc=example,dc=org ou: groups objectClass: organizationalUnit # parentGroup, groups, example.org dn: cn=parentGroup,ou=groups,dc=example,dc=org cn: parentGroup objectClass: groupOfNames member: cn=customuser,ou=users,dc=example,dc=org member: cn=childGroup,ou=groups,dc=example,dc=org # childGroup, groups, example.org dn: cn=childGroup,ou=groups,dc=example,dc=org cn: childGroup objectClass: groupOfNames member: cn=customuser2,ou=users,dc=example,dc=org ``` 以下の内容で新たに group-ldap-mapper を登録する。 ``` LDAP Groups DN: ou=groups,dc=example,dc=org Group Name LDAP Attribute: cn Group Object Classes: groupOfNames Preserve Group Inheritance: On Membership LDAP Attribute: member Membership Attribute Type: DN User Groups Retrieve Strategy: LOAD_GROUPS_BY_MEMBER_ATTRIBUTE ``` 以下のように Keycloak group が登録される。 - parentGroup - Child groups: childGroup - Members: user1 - childGroup - Members: user2 # Keycloak から group 情報を読み込む/LDAP との sync を発火する方法 ## 前提 - [Keycloak Admin REST API](https://www.keycloak.org/docs-api/21.1.1/rest-api/index.html) を使う。 - 使うためには、master realm の Clients にある admin-cli に対する OIDC access-token の取得が必要となる。 ``` # token_endpoint 確認 $ curl http://localhost:8080/realms/master/.well-known/openid-configuration | python3 -m json.tool # access_token 取得 $ curl --insecure -X POST {確認した token_endpoint} --user admin-cli: -H 'content-type: application/x-www-form-urlencoded' -d 'username={管理者ユーザ名}&password={管理者パスワード}&grant_type=password' | python3 -m json.tool $ access_token={取得した access_token} ``` - js でリクエストする場合は[ライブラリ](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client)がある ## group 構造取得 ``` $ curl -k -X GET http://localhost:8080/admin/realms/{realm 名}/groups -H "Content-Type: application/json" -H "Authorization: Bearer $access_token" | python3 -m json.tool # レスポンス例 [ { "id": "c54d5280-0f59-4cd3-920d-803b785f9f2e", "name": "parentGroup", "path": "/parentGroup", "subGroups": [ { "id": "e90232f7-cffc-493d-a061-b08f710608f9", "name": "childGroup", "path": "/parentGroup/childGroup", "subGroups": [] } ] } ] ``` ## member 情報取得 1 group 単位でリクエストする必要がある。 ``` $ curl -k -X GET http://localhost:8080/admin/realms/{realm 名}/groups/{group id}/members -H "Content-Type: application/json" -H "Authorization: Bearer $access_token" | python3 -m json.tool # レスポンス例 [ { "id": "b683abaa-5ac0-45b0-93d0-1fe7814f48fd", "createdTimestamp": 1683912761540, "username": "user1", "enabled": true, "totp": false, "emailVerified": false, "lastName": "Bar1", "federationLink": "cc03a070-5adc-413a-9ec1-e315bdf229ac", "attributes": { "LDAP_ENTRY_DN": [ "cn=customuser,ou=users,dc=example,dc=org" ], "LDAP_ID": [ "customuser" ] }, "disableableCredentialTypes": [], "requiredActions": [ "UPDATE_PASSWORD" ], "notBefore": 0 } ] ``` ## LDAP group との sync を発火する方法 ``` # 各 ID は詳細画面の URL、または GET /{realm}/components を叩くことで確認できる $ curl -k -X POST "http://localhost:8080/admin/realms/{realm 名}/user-storage/{LDAP user federation の ID}/mappers/{group mapper の ID}/sync?direction=fedToKeycloak" -H "Content-Type: application/json" -H "Authorization: Bearer $access_token" ``` ### 注意 - sync API は現在 [legacy module に含まれている](https://github.com/keycloak/keycloak/blob/main/docs/documentation/upgrading/topics/keycloak/changes-19_0_0.adoc#changes-in-the-module-structure)。 - API documentation には説明がなく、JS のライブラリにもリクエストするための実装は用意されていない。 - [storage の移行](https://www.keycloak.org/2022/07/storage-map.html)の過程で legacy となったようだが、リリースノートなどを読んでいるとまだ過渡期な雰囲気を感じるので、新しい storage 用に再実装されるのか[質問中](https://github.com/keycloak/keycloak/discussions/20338)