LoginSignup
4

More than 1 year has passed since last update.

posted at

updated at

Organization

KeycloakとmidPointを連携させてみよう(connector-keycloak編)

はじめに

NRI OpenStandia Advent Calendar 2020の4日目は、OSSのIAM (Identity and Access Management) プラットフォームであるKeycloakとIDM (Identity Management) / IGA (Identity Governance and Administration) プラットフォームであるmidPointを連携させる方法について紹介します。

midPointについてより理解を深めるには、1日目で紹介されていますがmidPointの開発者Radovan氏が書き下ろしたPractical Identity Management with MidPointを読むと良いでしょう。バージョンがちょっと古いですが、NRI OpenStandiaで翻訳された日本語版もあります。また、昨年のAdvent CalendarであるmidPoint by OpenStandia Advent Calendar 2019も参考にしてください。

連携といっても以下のように色々な箇所での連携があります。

  • 認証連携(midPointのログインをKeycloak経由にする)
  • KeycloakのユーザーをmidPointで管理する(midPointからKeycloakに対してIDプロビジョニングする)
  • Keycloakのパスワード変更をmidPoint側に連携する

今回は上記の2つ目の、midPointからKeycloakに対してIDプロビジョニングする部分についてのお話です。これを行うことで、midPointでユーザーを登録することでKeycloakにログインできるようになります。Keycloakにログインできるようになるということは、Keycloakでセキュリティ保護している各アプリケーションにSSOできるということです。

また、IDプロビジョニングするにしても、LDAPを間に挟むという方式1もありますが、今回はLDAPなしでダイレクトにmidPointからKeycloakに対してKeycloakのAdmin REST APIを利用してプロビジョニングします。そのためのmidPoint用コネクターとして、Keycloak Connectorを使います。

前提

本記事ではDockerを使用して環境を構築するため、Dockerが使える環境を用意してください。また、Keycloak、midPoint、Keycloak Connectorはそれぞれ以下のバージョンを使用しています。

  • Keycloak: 11.0.3
  • midPoint: 4.2
  • Keycloak Connector: 1.0.1

Dockerネットワークの作成

最初に midPoint => Keycloakへの通信を行うため、Dockerネットワークを作成しておきます。

docker network create midpoint_keycloak

Keycloakの起動

さくっとDockerでKeycloakを起動します。環境変数 KEYCLOAK_USERKEYCLOAK_PASSWORD を設定して管理者アカウントも作成します。

docker run --rm --name keycloak -it -p 8080:8080 --net midpoint_keycloak -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin jboss/keycloak:11.0.3

http://localhost:8080/auth/admin にアクセスし、admin/admin で管理コンソールにログインできればOKです。

レルムの追加

動作確認用にレルムを1つ追加しておきます。ここでは test という名前で作成しています。

image.png

midPointの起動

コネクターのインストール用ディレクトリを作成して、Keycloak ConnectorのJARファイルをMavenリポジトリよりダウンロードします。

mkdir -p midpoint-kc/var/icf-connectors
cd midpoint-kc/var/icf-connectors
curl -LO "https://search.maven.org/remotecontent?filepath=jp/openstandia/connector/connector-keycloak/1.0.1/connector-keycloak-1.0.1.jar"
cd ../..

あとは作成したディレクトリをマウントしてmidPointコンテナを起動します。Keycloakと同一マシンで実行する場合はポートが8080で被らないように、今回は8081にマッピングしています。

docker run --rm --name midpoint -it -p 8081:8080 -v $(pwd)/var:/opt/midpoint/var --net midpoint_keycloak evolveum/midpoint:4.2

http://localhost:8081/ にアクセスし、 Administrator/5ecr3t2 でログインできればOKです。

また、管理コンソールの「リポジトリ・オブジェクト」にアクセスし、画面上のプルダウンメニューで「コネクター」を選択してインストールされているコネクター一覧を確認します。ここでKeycloakConnectorが存在していれば無事に追加したコネクターも認識されています。

image.png

リソース定義の作成

コネクターがインストールできましたので、リソース定義を作成します。リソース定義は外部のリソース(源泉システムや連携先システムのこと)に対する接続定義で、接続情報や属性をどのようにマッピングするか、どのように同期制御を行うかといった設定を行うためのものです。

リソース定義の作成方法には、予め用意したXMLをインポートする方法とGUIで設定する方法の2つがあります。リソース定義のGUI設定は操作がかなり複雑なので、ここではXMLをインポートして設定する方法で解説します。

画面左メニューの 「オブジェクトのインポート」をクリックしてXMLインポートの画面を開きます。「オブジェクトインポート元」を「組み込みエディター」に変更し、以下のXMLを貼り付けて画面最下部の「オブジェクトのインポート」をクリックします。

image.png

XML設定例
<resource
  xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
  xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
  xmlns:icfs="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/resource-schema-3"
  xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3"
  xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
  xmlns:ri="http://midpoint.evolveum.com/xml/ns/public/resource/instance-3"
  xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3">
    <name>keycloak</name>
    <connectorRef relation="org:default" type="c:ConnectorType">
        <filter>
            <q:equal>
                <q:path>c:connectorType</q:path>
                <q:value>jp.openstandia.connector.keycloak.KeycloakConnector</q:value>
            </q:equal>
        </filter>
    </connectorRef>
    <connectorConfiguration xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3">
        <icfc:resultsHandlerConfiguration>
            <icfc:enableNormalizingResultsHandler>false</icfc:enableNormalizingResultsHandler>
            <icfc:enableFilteredResultsHandler>false</icfc:enableFilteredResultsHandler>
            <icfc:enableAttributesToGetSearchResultsHandler>false</icfc:enableAttributesToGetSearchResultsHandler>
        </icfc:resultsHandlerConfiguration>
        <icfc:configurationProperties xmlns:gen255="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/jp.openstandia.connector.connector-keycloak/jp.openstandia.connector.keycloak.KeycloakConnector">
            <gen255:serverUrl>http://keycloak:8080/auth</gen255:serverUrl>
            <gen255:username>admin</gen255:username>
            <gen255:password>admin</gen255:password>
            <gen255:clientId>admin-cli</gen255:clientId>
            <gen255:realmName>master</gen255:realmName>
            <gen255:targetRealmName>test</gen255:targetRealmName>
        </icfc:configurationProperties>
    </connectorConfiguration>
    <schemaHandling>
        <objectType>
            <kind>account</kind>
            <intent>default</intent>
            <displayName>User</displayName>
            <default>true</default>
            <objectClass>ri:user</objectClass>
            <attribute>
                <c:ref>ri:username</c:ref>
                <displayName>Username</displayName>
                <outbound>
                    <strength>strong</strength>
                    <source>
                        <c:path>$focus/name</c:path>
                    </source>
                </outbound>
            </attribute>
            <attribute>
                <c:ref>ri:email</c:ref>
                <displayName>Email</displayName>
                <matchingRule xmlns:mr="http://prism.evolveum.com/xml/ns/public/matching-rule-3">mr:stringIgnoreCase</matchingRule>
                <tolerant>false</tolerant>
                <outbound>
                    <strength>strong</strength>
                    <source>
                        <c:path>$focus/emailAddress</c:path>
                    </source>
                </outbound>
            </attribute>
            <attribute>
                <c:ref>ri:lastName</c:ref>
                <tolerant>false</tolerant>
                <outbound>
                    <strength>strong</strength>
                    <source>
                        <c:path>$focus/familyName</c:path>
                    </source>
                </outbound>
            </attribute>
            <attribute>
                <c:ref>ri:firstName</c:ref>
                <tolerant>false</tolerant>
                <outbound>
                    <strength>strong</strength>
                    <source>
                        <c:path>$focus/givenName</c:path>
                    </source>
                </outbound>
            </attribute>
            <activation>
                <administrativeStatus>
                    <outbound>
                        <strength>strong</strength>
                        <expression>
                            <asIs/>
                        </expression>
                    </outbound>
                </administrativeStatus>
            </activation>
            <credentials>
                <password>
                    <outbound>
                        <strength>strong</strength>
                        <expression>
                           <asIs/>
                        </expression>
                    </outbound>
                </password>
            </credentials>
        </objectType>
    </schemaHandling>
</resource>

正常にインポートできた場合は、緑色の成功メッセージが表示されます。

image.png

続いて、画面左メニューの 「リソース」>「すべてのリソース」をクリックしてリソース一覧のページを開きます。インポートした「keycloak」リソースがあるはずなので、クリックします。
keycloakリソースの画面で「接続テスト」をクリックし、接続確認を行います。問題なければオールグリーンの結果が返ります。

image.png

これで追加したリソースを使える状態になりました。

XML内容の補足

インポートしたXMLで設定している内容について少し補足しておきます。

接続先設定

以下のように接続先であるKeycloakのサーバURL、レルム名、認証情報などを設定しています。もし、異なる値を使っている場合は適宜変更してください。

本記事では、簡略化のため admin-cli クライアントと管理者アカウント・クレデンシャルを使ってKeycloakのAdmin REST APIを呼び出す設定にしています。実際の運用では、レルム管理の権限を付与した専用のクライアント (サービスアカウント) を作成して接続する方が望ましいです。

        <icfc:configurationProperties xmlns:gen255="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/bundle/jp.openstandia.connector.connector-keycloak/jp.openstandia.connector.keycloak.KeycloakConnector">
            <gen255:serverUrl>http://keycloak:8080/auth</gen255:serverUrl>
            <gen255:username>admin</gen255:username>
            <gen255:password>admin</gen255:password>
            <gen255:clientId>admin-cli</gen255:clientId>
            <gen255:realmName>master</gen255:realmName>
            <gen255:targetRealmName>test</gen255:targetRealmName>
        </icfc:configurationProperties>

ResultsHandlerの無効化

以下のように3つのResultsHandlerを無効化します。これをしておかないと正常に動作しません。

なぜこれをわざわざ無効化する必要があるかは、midPointのドキュメント「What are ConnId result handlers? 」に書かれていますが、midPointが内部で使用しているコネクターフレームワーク(midPointと独立しており、他のIDMプロダクトでも利用している)の歴史的な経緯により、デフォルトで有効化となっています。コネクター種類によっては明示的に無効化する必要があり、Keycloak Connectorもその1つです。

    <connectorConfiguration xmlns:icfc="http://midpoint.evolveum.com/xml/ns/public/connector/icf-1/connector-schema-3">
        <icfc:resultsHandlerConfiguration>
            <icfc:enableNormalizingResultsHandler>false</icfc:enableNormalizingResultsHandler>
            <icfc:enableFilteredResultsHandler>false</icfc:enableFilteredResultsHandler>
            <icfc:enableAttributesToGetSearchResultsHandler>false</icfc:enableAttributesToGetSearchResultsHandler>
        </icfc:resultsHandlerConfiguration>

マッピング設定

今回のXMLでは以下の outbound のマッピングを設定しています。

midPoint Keycloak
name => username
emailAddress => email
givenName => firstName
familyName => lastName

また、アカウント有効/無効の連携のために <activation>...</activation> を、パスワードの連携のため <credentials>...</credentials> を設定しています。

ユーザーの追加

では実際にユーザーをプロビジョニングさせてみましょう。画面左メニューの 「ユーザー」>「新規ユーザー」をクリックして新規ユーザー作成画面を開きます。ここでは、以下の項目を入力します。

  • 名前
  • Eメール
  • パスワード > 値

image.png

続いて「アサイン」タブをクリックしてアサイン画面を開きます。アサインアイコンをクリックすると、アサイン先を選ぶポップアップウィンドウが開きます。ここで「リソース」タブをクリックすると、先程作成した「keycloak」リソースが見えます。これを選択して、「パラメータ種類」を「アカウント」、「用途」を「default」に設定して「追加」をクリックします。

今回はユーザーに対して直接リソースをアサインして動作確認していますが、実運用ではロールやアーキタイプを使ったロールベース・プロビジョニングを使う方が望ましいです。詳しくはこちらの記事などを参考にしてください。

image.png

これで保存する準備ができました。最後に保存の前に、「変更のプレビュー」をクリックするとどのような変更、プロビジョニングが行われるか確認することができます。二次変更というところに、Keycloakへのプロビジョニング内容が表示されます。

image.png

プレビューでエラーも発生せず、プロビジョニングされるデータも想定どおりであれば「保存」をクリックしてユーザー登録を完了します。

Keycloak側の確認

Keycloak側を確認してみます。管理者コンソールのユーザー一覧を参照すると、登録されていることを確認できます。

image.png

ログイン確認

実際にプロビジョニングされたアカウントでログイン確認してみます。今回、シングルサインオンのアプリケーションは用意していないですが、Keycloakが提供するエンドユーザー向けのアカウント管理画面を使ってログイン確認することができます。

http://localhost:8080/auth/realms/test/account にアクセスします。プロビジョニングしたアカウント(user1/password)でログインしてみます。

image.png

無事に認証が成功すれば、アカウント管理画面が表示されるはずです。

image.png

変更の確認

midPointからユーザー属性を変更した際に、Keycloak側にも反映されるかどうか確認してみます。
画面左メニューの 「ユーザー」>「すべてのユーザー」をクリックしてユーザー一覧を表示します。先程作成したユーザーをクリックして、詳細画面を開きます。ここで、姓を「Bar」=>「Hoge」に変更して「変更のプレビュー」をクリックします。

image.png

二次変更に変更内容が表示されていれば大丈夫そうですので、「保存」をクリックします。

image.png

先程ログインしたアカウント管理画面をリロードさせてみて、姓 (Last name) が変更されていることを確認します。

image.png

アカウント無効の確認

次はアカウントを無効化してみます。midPointのユーザー詳細画面から、「アクティベーション」>「管理ステータス」を「無効」に設定します。

image.png

「変更のプレビュー」をクリックしてまた変更内容を確認してみます。二次変更に管理ステータスが ENABLED => DISABLED と出ていれば大丈夫そうですので、「保存」をクリックします。

image.png

これでKeycloakのユーザー詳細画面を開くと、「User Enabled」が「OFF」になっているはずです。

image.png

実際にログインしようとしてみると、アカウント無効というエラーメッセージが表示されます。

image.png

削除の確認

最後に、アカウントの削除を確認してみます。midPointのユーザー一覧画面から、該当のアカウントを削除します。右側にあるアクションメニューから「削除」をクリックします。

image.png

確認のポップアップが表示されるので、「はい」をクリックします。

image.png

Keycloak側のユーザー一覧で「View all users」をクリックしても、表示されないことを確認します。

image.png

おわりに

KeycloakとmidPointの間で、Keycloak Connectorを使って直接アカウントを連携する方法を紹介しました。今回は、基本的なプロビジョニング動作としてユーザー情報の連携のみを紹介していますが、Keycloak側のカスタム・ユーザー属性への連携や、midPointの組織やロールをKeycloakのグループとして連携し、ユーザーに対してグループ所属情報を連携するといったもうちょっと高度な使い方もできます。


  1. Keycloakは標準でLDAPをユーザーストレージとして使うこともでき、midPointも標準でLDAPに対してプロビジョニングするコネクターを備えていますので、LDAPを中心に置いてKeycloakとmidPointを連携することができます。 

  2. お決まりのmidPointの初期システムアカウントのIDとパスワードです。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
4