Ponz Dev Log

ゆるくてマイペースな開発日記

KeycloakでLDAPをバックエンドにOIDC認証する

エンタープライズ向けシステムの世界にいるとユーザー管理・認証にLDAPサーバーを使っている場面に直面します。 LDAPサーバーはOSSOpenLDAPだったり、389 Directory Server (Red Hat)、Tivoli Directory Server (IBM)、あるいはMicrosoft Active Directoryかもしれません。

ユーザー認証というコンテキストであれば、2023年現在だとアプリケーションを新規開発するなら認証プロトコルにOIDCかSAMLを使うでしょう。素のLDAPプロトコルで認証するロジックを書くのは面倒です。OIDC/SAMLであればシングル・サインオン可能です。ただし、ユーザー管理のリポジトリとしてLDAPサーバーを (積極的/消極的どちらかの理由で) 有効活用したいケースがあります。

この記事では認証ソフトウェアのKeycloakを用いて、LDAPサーバーをバックエンドに据えて、LDAPユーザーでOIDC認証を実現する方法を残します。

環境情報

ソフトウェア

この記事ではLDAPサーバーにOpenLDAPを使用します。 OpenLDAPとKeycloakはどちらもDockerコンテナとして起動します。 以下のコンテナイメージを使用します。

コンポーネント コンテナイメージ
OpenLDAP docker.io/bitnami/openldap:2.6.5
Keycloak quay.io/keycloak/keycloak:22.0.1

LDAP

LDAPは次の設定でユーザー情報が投入されているとします。

  • ドメインDN: dc=example,dc=com
  • ユーザー組織単位 (OU): users
  • 匿名ユーザーによる操作: NG
  • ユーザー: 2つ登録済み
    • ID: hatenademo1, パスワード: H0ge_Fuga
    • ID: hatenademo2, パスワード: P1yo-piY0

環境セットアップ

コンテナをDocker Composeでまとめて起動します。

compose.yml の作成

まずはDocker Compose定義ファイル compose.yml を作成します。 compose.yml のサンプルを以下に示します。

内容としてはOpenLDAPに管理者ユーザー admin と、環境情報で定義したLDAP設定、2つのユーザー情報 hatenademo1 hatenademo2環境変数で投入しています。 Keycloakは開発モード start-dev で動かします。

version: "3"

services:
  openldap:
    container_name: openldap
    image: docker.io/bitnami/openldap:2.6.5
    ports:
      - "1389:1389"
    environment:
      LDAP_ADMIN_USERNAME: admin
      LDAP_ADMIN_PASSWORD: adminpassword
      LDAP_USERS: hatenademo1,hatenademo2
      LDAP_PASSWORDS: H0ge_Fuga,P1yo-piY0
      LDAP_ROOT: dc=example,dc=com
      LDAP_USER_DC: users  # ou=users
      LDAP_ALLOW_ANON_BINDING: no
  keycloak:
    container_name: keycloak
    image: quay.io/keycloak/keycloak:22.0.1
    command: ["start-dev"]
    ports:
      - "8080:8080"
    environment:
      KEYCLOAK_ADMIN: keycloakadmin
      KEYCLOAK_ADMIN_PASSWORD: Kc_Admin_Pass
      KC_HEALTH_ENABLED: true
    healthcheck:
      test: ["CMD", "curl", "--head", "-fsS", "http://localhost:8080/health/ready"]
      interval: 10s
      timeout: 3s
      retries: 3
      start_period: 30s

コンテナ起動

compose.yml をインプットに、docker compose コマンドでコンテナを起動します。

$ docker compose up -d

[+] Running 3/3
 ✔ Network hatenademo_default  Created
 ✔ Container openldap                 Started 
 ✔ Container keycloak                 Started 

OpenLDAPサーバーに ldapsearch コマンドを発行すると、2つのユーザーが登録されています。

$ ldapsearch -x -H "ldap://localhost:1389" -D "cn=admin,dc=example,dc=com" -W -b "ou=users,dc=example,dc=com" "objectClass=inetOrgPerson"

Enter LDAP Password: (adminユーザーのパスワード)

(...中略...)

# hatenademo1, users, example.com
dn: cn=hatenademo1,ou=users,dc=example,dc=com
cn: User1
cn: hatenademo1
sn: Bar1
objectClass: inetOrgPerson
uid: hatenademo1
(...その他の属性は省略...)

# hatenademo2, users, example.com
dn: cn=hatenademo2,ou=users,dc=example,dc=com
cn: User2
cn: hatenademo2
sn: Bar2
objectClass: inetOrgPerson
uid: hatenademo2
(...その他の属性は省略...)

Keycloak ユーザーフェデレーション設定

ここから本題です。KeycloakがLDAPサーバーをバックエンドのユーザーリポジトリとして扱う設定は、Keycloakの「ユーザーフェデレーション」という機能で扱います。フェデレーション設定をKeycloakのレルム ldap-demo に入れると仮定して後続に設定を進めます。

LDAPプロバイダーの設定

コンテナで立てたKeycloakの管理コンソールに http://localhost:8080 でアクセスし、Keycloak管理者ユーザーでログインします。 レルムが未作成の場合はログイン後にレルム ldap-demo を作成してください。

レルム選択後に左メニュー最下部に「User federation」メニューがあるので選択します。 フェデレーション設定するプロバイダーの選択画面が表示されるので「Add Ldap provider」を選択して設定入力画面に遷移します。

Keycloak フェデレーションプロバイダー選択

LDAP接続情報の設定

フェデレーション設定画面でLDAPサーバーの種類と接続情報を入力します。

General options > Vender (LDAPサーバーの種類) は Other を選択してください。 プルダウンにはADやTivoliといった選択肢が表示されますが、OpenLDAPの場合はOtherでよいです。

LDAPサーバー一般

また、Connection and authentication settings (接続情報) は必須属性を埋めます。必須属性以外はデフォルト値のままでOKです。 接続情報の入力例を次の表と図で示します。今回はコンテナで構築しているので、LDAP URLはKeycloakコンテナから見たOpenLDAPのホスト名・ポート番号を指定してください。ホスト名に localhost を指定しても接続できないことに注意です。

設定名 設定値
Connection URL ldap://openldap:1389
Bind type simple
Bind DN cn=admin,dc=example,dc=com
Bind credential adminpassword

LDAPサーバー接続情報

設定を埋めたら「Test connection」と「Test authentication」ボタンで疎通疎通確認します。 それぞれテストOKのポップアップが表示されたら疎通確認は完了です。

LDAPユーザー検索条件の設定

Keycloakが認証操作を実行するときにLDAPサーバーを検索する条件を設定します。 LDAP serching and updating の必須属性を埋めて保存します。入力例を次の表と図で示します。 今回はKeycloakからLDAPサーバーに属性変更操作を想定していないので、READ_ONLY を指定してください。

設定名 設定値
Edit mode READ_ONLY
Users DN ou=users,dc=example,dc=com
Username LDAP attribute uid
RDN LDAP attribute uid
UUID LDAP attribute uid
User object classes inetOrgPerson, organizationalPerson

LDAPユーザー検索条件

設定を全て埋めたら「Save」ボタンで設定を保存すれば完了です。

疎通確認

実際にLDAPユーザーで認証できるのか試します。 認証するOIDCクライアントアプリケーションとして、Keycloakが標準で用意しているアカウントコンソールを使用します。

アカウントコンソールのURL http://localhost:8080/realms/ldap-demo/account/ にアクセスしてアカウントコンソールを開きます。 Sign in ボタンを押下するとログインフォームが表示されるので、LDAPサーバーに登録済みのユーザーIDとパスワードを指定してログインできます。

ログインフォーム画面

ログインに成功すると、アカウントコンソール右上にはLDAPサーバーに登録してあるユーザーの姓名が表示されています。

アカウントコンソール ログイン後の画面

参考資料


以上。