- 記事一覧 >
- ブログ記事

Ubuntu 22にKeycloak 22をインストールして、Identity providers=Azure ADでSAML
はじめに
この記事に「SSO とは」「SAML とは」「Keycloak とは」等々、用語の説明はありません。
Ubuntu 22.04.3 LTS に Keycloak 22.0.5(Quarkus 版) をインストールして、SAML による SSO(シングルサインオン/Single Sign On)環境を作成しました。
さらに作業を進めて、Identity providers に Azure AD(Azure Active Directory/Microsoft Entra ID)を追加して、Azure AD のアカウントで認証することに成功しました。
アプリ - Keycloak - Azure AD の場合、Keycloak は、仲介サービス(Identity Broker)として機能します。
Azure AD(Azure Active Directory)は、Microsoft Entra ID に名称が変わりましたが、この記事では、Azure AD 表記のままでいきます。
今回作成したのは、以下の2パターンです。
●基本パターン
・SP(Service Provider): Apache & mod_auth_mellon & php
・IdP(Identity Provider): Keycloak
・User federation: Keycloak の DB(PostgreSQL14)
●Azure AD利用パターン
・SP(Service Provider): Apache & mod_auth_mellon & php
・Identity Broker: Keycloak
・IdP(Identity Provider): Azure AD
・User federation: Azure AD
Identity Broker(Keycloak)は、mod_auth_mellon から見ると、IdP で、Azure AD から見ると、SP でもあります。
この2パターンの環境構築について、Keycloak インストールから全手順を紹介していきます。
Keycloak に関しては、Docker, Podman, Kubernetes 等コンテナでデプロイではなく、ソースコードを Ubuntu の /opt/keycloak にビルドしてデプロイします。
Keycloak は、v17 までアプリケーションサーバーとして、Wildfly を使っていたのですが、v17 から Quarkus を利用するようになったようです。今回、Wildfly ではなく、Quarkus 前提の手順です。
Quarkus(カーカス)は、Red Hat 社が開発しているオープンソースの Java フレームワークです。
コンテナ化・サーバレス化した開発環境に最適化されており、アプリケーションの起動時間や応答時間を速くし、省メモリで実行することができます。
Quarkus の主な機能は次のとおりです。
・柔軟な開発モデル
・省メモリ
・高速起動
・繰り返しタスクの自動化
【検証環境】
●Keycloak
・Ubuntu 22.04.3 LTS
・Keycloak 22.0.5
・PostgreSQL 14.9
●Apache & mod_auth_mellon & php
・Debian Bullseye with Raspberry Pi Desktop 2022-07-01(Debian version: 11)
・Apache 2.4.56
・libapache2-mod-auth-mellon 0.17.0-1+deb11u1
・PHP 7.4.33
● クラウド:Azure AD(Azure Active Directory/Microsoft Entra ID)
この記事では、とにかく動作するまでの最低限の設定しか行いません。ログアウトのことは考えません。
本記事情報の設定不足、誤りにより何らかの問題が生じても、一切責任を負いません。
IdP:Keycloak インストール
OS(Ubuntu 22.04.3 LTS)を標準のインストール方法でインストールした直後とします。
全て root 権限で実行しています。そのため、sudo は省略しています。
hosts 登録しないといけないとか当たり前のことは省略しています。
Keycloak 22.0.5 をインストールします。
apt を最新化します。
# apt update -y && apt upgrade -y必要パッケージと時刻合わせに使う chrony をインストールします。
SAML 認証では、IdP(Identity Provider)と SP(Service Provider)の間で時刻が大きくずれていると問題が生じることがあります。
これは、SAML アサーション(認証情報)には有効期限が含まれており、その有効期限が IdP と SP で異なる解釈をされる可能性があるからです。
# apt install software-properties-common ca-certificates chrony -y
# vi /etc/chrony/chrony.conf
# systemctl restart chrony.serviceここで、chrony.conf は、以下のように NTP サーバーを設定して、時刻がずれないようにします。
#pool ntp.ubuntu.com iburst maxsources 4
#pool 0.ubuntu.pool.ntp.org iburst maxsources 1
#pool 1.ubuntu.pool.ntp.org iburst maxsources 1
#pool 2.ubuntu.pool.ntp.org iburst maxsources 2
pool ntp.nict.jp iburstJava ランタイム環境と開発環境をインストールします。
# apt install openjdk-17-jre-headless openjdk-17-jdk-headless -ykeycloak-22.0.5.tar.gz をダウンロードして、展開し、/opt/keycloak に配置します。
# wget https://github.com/keycloak/keycloak/releases/download/22.0.5/keycloak-22.0.5.tar.gz
# tar zxvf keycloak-22.0.5.tar.gz
# mv keycloak-22.0.5 keycloak
# mv keycloak /opt/PostgreSQL 14 をインストールして、DB=keycloak、 User=keycloak, Password=PASSWORD を作成します。
# apt install postgresql -y
# su - postgres
$ psql -V
psql (PostgreSQL) 14.9 (Ubuntu 14.9-0ubuntu0.22.04.1)
$ psql -d postgres
CREATE USER keycloak WITH PASSWORD 'PASSWORD' CREATEDB;
CREATE DATABASE keycloak OWNER keycloak;
\q
$ exitkeycloak.conf にデータベースの種類、データベース名、データベースユーザー名等設定します。
# vi /opt/keycloak/conf/keycloak.conf# データベースの種類=PostgreSQL
db=postgres
# データベースへの接続に使用するユーザー名=keycloak
db-username=keycloak
# データベースへの接続に使用するパスワード=PASSWORD
db-password=PASSWORD
# データベースへの接続URL
db-url=jdbc:postgresql://localhost/keycloak
# ヘルスチェック(サービスの健康状態を確認する機能)有効
health-enabled=true
# メトリクス(サービスのパフォーマンスを測定するデータ)有効
metrics-enabled=truekeycloak ユーザーと keycloak グループを作成します。(最後に /opt/keycloak の Owner:Group のパーミッションを keycloak:keycloak とします。)
# groupadd -r keycloak
# useradd -m -d /var/lib/keycloak -s /sbin/nologin -r -g keycloak keycloakhttps:// で Keycloak の管理コンソールにアクセスするため、自己署名証明書を作成します。
今回、Keycloak の URL は、https://kctest.contoso.com とします。
Keycloak の管理コンソール とは、GUIの Keycloak 設定画面のことです。
# openssl req -newkey rsa:2048 -nodes -keyout server.key.pem -x509 -days 3650 -out server.crt.pem
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Aichi
Locality Name (eg, city) []:Toyota
Organization Name (eg, company) [Internet Widgits Pty Ltd]:ITC
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:kctest.contoso.com
Email Address []:
# mv server.crt.pem /opt/keycloak/conf/
# mv server.key.pem /opt/keycloak/conf/keycloak.conf に先ほどのホスト名、証明書、秘密鍵を設定します。
# vi /opt/keycloak/conf/keycloak.conf# 注意:confの前に / の追加が必要。(コメントを外すだけでは、NG)
https-certificate-file=${kc.home.dir}/conf/server.crt.pem
# 注意:confの前に / の追加が必要。(コメントを外すだけでは、NG)
https-certificate-key-file=${kc.home.dir}/conf/server.key.pem
hostname=kctest.contoso.com
# 443ポートを使用する設定を追加します。※デフォルトは、8443です。
https-port=443keycloak.conf の
https-certificate-fileとhttps-certificate-key-fileについて、上記コメントにもありますが、初期状態でコメントアウトされている
${kc.home.dir}confのままの場合、
/opt/keycloakconfを参照しようとしてエラーになりました。
ビルドして、手動起動します。
ビルドする際に、Keycloak 管理コンソールの管理者ユーザー名とパスワードを設定します。
管理者ユーザー名: admin
管理者パスワード: KYC_PASS
# cd /opt/keycloak/bin/
# export KEYCLOAK_ADMIN=admin
# export KEYCLOAK_ADMIN_PASSWORD=KYC_PASS
# ./kc.sh --verbose build
# ./kc.sh --verbose starthttps://kctest.contoso.com/ にアクセスして、
管理者ユーザー名: admin
管理者パスワード: KYC_PASS
でログインできたら、ひとまずは、成功です。
ヨシ!
IdP:Keycloak サービス追加
./kc.sh --verbose start で問題無いことが確認できたため、CTRL + C で止めます。
systemctl で keycloak を起動する設定を追加します。
# vi /etc/systemd/system/keycloak.service# 汎用オプション
[Unit]
# サービスの説明書き
Description=Keycloak Application Server
# ネットワークとsyslogサービスが起動して実行された後にこのサービスを開始
After=syslog.target network.target
# 固有のオプション
[Service]
# 実行したタイミングで起動完了と判断
Type=simple
# 停止完了までに待機する時間
TimeoutStopSec=0
# systemctl stopコマンドでSIGTERMシグナルを送る
KillSignal=SIGTERM
# サービスが停止されたときにメインプロセスのみが強制終了
KillMode=process
# 成功とみなされる終了ステータス=143
SuccessExitStatus=143
# 最大ロックメモリアドレス空間
LimitMEMLOCK=infinity
# systemd がサービスを停止した後、残りのプロセスにSIGKILLシグナルを送信しない
SendSIGKILL=no
# 作業ディレクトリ
WorkingDirectory=/opt/keycloak/
# 実行に使用されるユーザーとグループ
User=keycloak
Group=keycloak
# オープンファイル記述子の最大数
LimitNOFILE=102642
# ログをコンソールとファイルに出力するオプションを指定して起動
# ログの出力先は、/opt/keycloak/data/log/keycloak.log
ExecStart=/opt/keycloak/bin/kc.sh start --log=console,file
# インストールに関する情報
[Install]
# システムがマルチユーザーモードで起動するときに自動的に起動する
WantedBy=multi-user.target# chown keycloak: -R /opt/keycloak
# systemctl enable keycloak.service
# systemctl start keycloak.service
(しばらくしてから確認)
# systemctl status keycloak.service
× keycloak.service - Keycloak Application Server
Loaded: loaded (/etc/systemd/system/keycloak.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Sat 2023-11-25 17:18:55 JST; 43s ago
Process: 1774 ExecStart=/opt/keycloak/bin/kc.sh start --log=console,file (code=exited, status=1/FAILURE)
Main PID: 1774 (code=exited, status=1/FAILURE)
CPU: 16.515s
11月 25 17:18:54 ubuntu-22043 kc.sh[1774]: 2023-11-25 17:18:54,266 INFO [org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory] (main) Node name: ubuntu-22043-6245, S>
11月 25 17:18:55 ubuntu-22043 kc.sh[1774]: 2023-11-25 17:18:55,119 INFO [org.infinispan.CLUSTER] (main) ISPN000080: Disconnecting JGroups channel `ISPN`
11月 25 17:18:55 ubuntu-22043 kc.sh[1774]: 2023-11-25 17:18:55,162 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Failed to start server in (production) mode
11月 25 17:18:55 ubuntu-22043 kc.sh[1774]: 2023-11-25 17:18:55,163 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Unable to start HTTP server
11月 25 17:18:55 ubuntu-22043 kc.sh[1774]: 2023-11-25 17:18:55,163 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: io.quarkus.runtime.QuarkusBindException: Por>
11月 25 17:18:55 ubuntu-22043 kc.sh[1774]: 2023-11-25 17:18:55,163 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) ERROR: Port(s) already bound: 443: 許可がありません
11月 25 17:18:55 ubuntu-22043 kc.sh[1774]: 2023-11-25 17:18:55,164 ERROR [org.keycloak.quarkus.runtime.cli.ExecutionExceptionHandler] (main) For more details run the same command passing the '>
11月 25 17:18:55 ubuntu-22043 systemd[1]: keycloak.service: Main process exited, code=exited, status=1/FAILURE
11月 25 17:18:55 ubuntu-22043 systemd[1]: keycloak.service: Failed with result 'exit-code'.
11月 25 17:18:55 ubuntu-22043 systemd[1]: keycloak.service: Consumed 16.515s CPU time.systemctl start keycloak.service ですんなり起動して、ヨシ!っと思ったら、エラー停止しました。
エラー:ERROR: Port(s) already bound: 443: 許可がありません.
非特権(非 root)ユーザ(keycloak)で起動していて、ウェルノウンポート(1024 未満のポート)にバインドできないため、エラーです。
# sysctl net.ipv4.ip_unprivileged_port_start
net.ipv4.ip_unprivileged_port_start = 10241024 以上しか非特権ユーザーのアクセスが許されていません。
# sysctl -w net.ipv4.ip_unprivileged_port_start=443で 443 未満に変更します。
さらに、この設定を恒久化します。
# vi /etc/sysctl.d/99-sysctl.confnet.ipv4.ip_unprivileged_port_start=443反映して、再スタートします。
# sysctl --system
# systemctl start keycloak
# systemctl status keycloak
● keycloak.service - Keycloak Application Server
Loaded: loaded (/etc/systemd/system/keycloak.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2023-11-25 17:31:25 JST; 10s ago
Main PID: 1928 (java)
Tasks: 52 (limit: 9387)
Memory: 291.1M
CPU: 14.350s
CGroup: /system.slice/keycloak.service
mq1928 java -Dkc.config.built=true -Xms64m -Xmx512m -XX:MetaspaceSize=96M -XX:MaxMetaspaceSize=256m -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.err.encoding=UTF-8 -Dstdout.encoding=UTF-8 -Dstderr.encoding=UTF-8 -XX:+ExitOnOutOfMemoryError -Djava.security.egd=file:/dev/urandom -XX:+UseParallelGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED -Dkc.home.dir=/opt/keycloak/bin/.. -Djboss.ser>
11月 25 17:31:29 ubuntu-22043 kc.sh[1928]: 2023-11-25 17:31:29,829 INFO [org.infinispan.LIFECYCLE] (jgroups-7,ubuntu-22043-12067) [Context=offlineSessions] ISPN100002: Starting rebalance with members [ubuntu-22043-46092, ubuntu-22043-12067], phase READ_OLD_WRITE_ALL, topology id 12
11月 25 17:31:29 ubuntu-22043 kc.sh[1928]: 2023-11-25 17:31:29,831 INFO [org.infinispan.LIFECYCLE] (jgroups-7,ubuntu-22043-12067) [Context=offlineSessions] ISPN100010: Finished rebalance with members [ubuntu-22043-46092, ubuntu-22043-12067], topology id 12
11月 25 17:31:29 ubuntu-22043 kc.sh[1928]: 2023-11-25 17:31:29,848 INFO [org.infinispan.LIFECYCLE] (jgroups-10,ubuntu-22043-12067) [Context=sessions] ISPN100002: Starting rebalance with members [ubuntu-22043-46092, ubuntu-22043-12067], phase READ_OLD_WRITE_ALL, topology id 12
11月 25 17:31:29 ubuntu-22043 kc.sh[1928]: 2023-11-25 17:31:29,850 INFO [org.infinispan.LIFECYCLE] (jgroups-10,ubuntu-22043-12067) [Context=sessions] ISPN100010: Finished rebalance with members [ubuntu-22043-46092, ubuntu-22043-12067], topology id 12
11月 25 17:31:29 ubuntu-22043 kc.sh[1928]: 2023-11-25 17:31:29,862 INFO [org.infinispan.LIFECYCLE] (jgroups-10,ubuntu-22043-12067) [Context=work] ISPN100002: Starting rebalance with members [ubuntu-22043-46092, ubuntu-22043-12067], phase READ_OLD_WRITE_ALL, topology id 12
11月 25 17:31:29 ubuntu-22043 kc.sh[1928]: 2023-11-25 17:31:29,864 INFO [org.infinispan.LIFECYCLE] (non-blocking-thread--p2-t5) [Context=work] ISPN100010: Finished rebalance with members [ubuntu-22043-46092, ubuntu-22043-12067], topology id 12
11月 25 17:31:30 ubuntu-22043 kc.sh[1928]: 2023-11-25 17:31:30,035 INFO [org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory] (main) Node name: ubuntu-22043-12067, Site name: null
11月 25 17:31:30 ubuntu-22043 kc.sh[1928]: 2023-11-25 17:31:30,784 INFO [io.quarkus] (main) Keycloak 22.0.5 on JVM (powered by Quarkus 3.2.7.Final) started in 4.791s. Listening on: https://0.0.0.0:443
11月 25 17:31:30 ubuntu-22043 kc.sh[1928]: 2023-11-25 17:31:30,786 INFO [io.quarkus] (main) Profile prod activated.
11月 25 17:31:30 ubuntu-22043 kc.sh[1928]: 2023-11-25 17:31:30,786 INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-h2, jdbc-mariadb, jdbc-mssql, jdbc-mysql, jdbc-oracle, jdbc-postgresql, keycloak, logging-gelf, micrometer, narayana-jta, reactive-routes, resteasy, resteasy-jackson, smallrye-context-propagation, smallrye-health, vertx]https://kctest.contoso.com/ にアクセスして、起動確認します。
ヨシ!
IdP:Keycloak レルム作成
まず、テスト用にレルムを作成します。
「レルム(Realm)」は、以下のように各種設定をまとめた入れ物のようなイメージで良いと思います。master レルムが最初からあります。
管理コンソールの "master" と表示されているところをクリックして、Create Realm をクリックします。
Realm name に作成するレルムの名前を入力して、Create をクリックします。
ここでは、TestRealm とします。
IdP:Keycloak 一般ユーザー作成
レルム:TestRealm を選択して、Keycloak の DB(PostgreSQL)にユーザーを作成します。
ここで作成するユーザーは、レルム:TestRealm 内に作成された Keycloak 独自管理下のユーザーです。
Users をクリックして、Add user をクリックします。
Username に作成するユーザー名を入力します。
ここでは、testuser とします。
確認メール不要としたいため、Email verified は、Yes とします。
Create をクリックします。
Credentials タブをクリックして、パスワードを設定します。
Set password をクリックします。
設定したいパスワードを入力します。
ここで、Temporary を On にすると、初回ログイン時にパスワードの変更を求められますので、Off にしておきます。
Save をクリックします。
テストユーザーの準備完了です。
SP:アプリ環境作成
・Debian Bullseye with Raspberry Pi Desktop 2022-07-01(Debian version: 11)
の OS インストール直後からスタートして、
・Apache 2.4.56
・PHP 7.4.33
・libapache2-mod-auth-mellon 0.17.0-1+deb11u1
をインストールします。
OS インストール方法は、別記事「Raspberry Pi OS を VMware-workstation-16.1.1 にインストール」を参考にしてください。※バージョンが少し古いですが、手順は同じです。
ここで、SAML クライアント、つまり、アプリ(SP)側の URL は、https://kcapp.example.com/ であるという前提として進めます。
https://kcapp.example.com/
で Apache のデフォルト画面(index.html)https://kcapp.example.com/info.php
で phpinfo() の画面を表示する Web サーバーを構築し、それを「アプリ」とします。
全て root 権限で実行しています。そのため、sudo は省略しています。
hosts 登録しないといけないとか当たり前のことは省略しています。
# apt -y update
# apt -y install apache2
# apt -y install libapache2-mod-auth-mellon
# a2enmod auth_mellon
# a2enmod ssl
# a2ensite default-ssl
# openssl genrsa -aes128 2048 > server.key
# openssl req -new -key server.key > server.csr
# openssl x509 -in server.csr -days 365 -req -signkey server.key > server.crt
# openssl rsa -in server.key -out server.key
# cp -p server.crt /etc/ssl/certs/server.crt
# cp -p server.key /etc/ssl/private/server.key
# chmod 400 /etc/ssl/private/server.key
# vi /etc/apache2/sites-available/default-ssl.conf
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
を以下に変更
↓
SSLCertificateFile /etc/ssl/certs/server.crt
SSLCertificateKeyFile /etc/ssl/private/server.key
# apt -y install php-common libapache2-mod-php php-cli
# systemctl restart apache2
# vi /var/www/html/info.php<?php
phpinfo();ここまで実施して、動作確認します。 なお、この時点では、mod_auth_mellon の設定をしていないため、SSO 認証無しです。
https://kcapp.example.com/
https://kcapp.example.com/info.php
OK!
SP:mod auth_mellon 設定
Apache の conf に mod_auth_mellon の設定を追加します。
ここでは、簡略化のため、既に最初から存在する defult-ssl.conf に VirtualHost の設定を追加します。
設定に指定されている各ファイルは、この後作成します。
# vi /etc/apache2/sites-available/default-ssl.conf<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin webadmin@kcapp.example.com
ServerName kcapp.example.com
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateKeyFile /etc/apache2/saml/https_kcapp.example.com.key
SSLCertificateFile /etc/apache2/saml/https_kcapp.example.com.cert
<Location />
# SAML認証に関するエンドポイントのパス
# エンドポイント=IdPとSPがSAML認証の要求や応答をやり取りするためのURL
MellonEndpointPath "/mellon"
# IdPのメタデータファイルのパス
# メタデータ=IdPやSPの設定や機能を記述したXMLファイル
MellonIdPMetadataFile /etc/apache2/saml/idp_metadata.xml
# SPの秘密鍵ファイルのパス
# 秘密鍵=SAML認証の通信を暗号化するための鍵
MellonSPPrivateKeyFile /etc/apache2/saml/https_kcapp.example.com.key
# SPの証明書ファイルのパス
# 証明書=SPの秘密鍵に対応する公開鍵を含むファイル
MellonSPCertFile /etc/apache2/saml/https_kcapp.example.com.cert
# SPのメタデータファイルのパス
MellonSPMetadataFile /etc/apache2/saml/https_kcapp.example.com.xml
# SAML認証を使用する
AuthType "Mellon"
Require valid-user
# SAML認証を有効にする
MellonEnable "auth"
</Location>
</VirtualHost>
...(既存設定)SP:SAML 認証メタデータ作成
秘密鍵、証明書、SAML の詳細な設定を行うメタデータ(XML ファイル)の配置が必要になるのですが、mellon_create_metadata.sh を使って、一気に終わらせます。
そのため、メタデータの内容に関する説明は省略します。
# mkdir /etc/apache2/saml
# cd /etc/apache2/saml
# ENTITY_ID=https://kcapp.example.com
# BASE_URL=https://kcapp.example.com/mellon
# curl -O https://raw.githubusercontent.com/latchset/mod_auth_mellon/main/mellon_create_metadata.sh
# chmod 755 mellon_create_metadata.sh
# ./mellon_create_metadata.sh ${ENTITY_ID} ${BASE_URL}
Output files:
Private key: https_kcapp.example.com.key
Certificate: https_kcapp.example.com.cert
Metadata: https_kcapp.example.com.xml
Host: kcapp.example.com
Endpoints:
SingleLogoutService: https://kcapp.example.com/mellon/logout
AssertionConsumerService: https://kcapp.example.com/mellon/postResponse
# ls
https_kcapp.example.com.cert https_kcapp.example.com.key https_kcapp.example.com.xml mellon_create_metadata.sh【ENTITY_ID】
SAMLのEntity IDは、アプリケーション(SP)を一意に識別するためのものです。SAML 認証では、IdP と SP はそれぞれのメタデータを交換します。メタデータとは、IdP や SP の設定や機能を記述した XML ファイルです。メタデータには、ENTITY_ID が含まれており、IdP と SP が互いに認識するために使用されます。
URL形式であることが推奨されますが、URL形式であることは必須ではありません。
Keycloak で設定する Client ID と同一にします。(今回この後自動的に同一になります。)
【BASE_URL】
BASE_URL は、SP のエンドポイントのベースとなる URL です。エンドポイントとは、IdP と SP が SAML 認証の要求や応答をやり取りするための URL です。エンドポイントには、以下のような種類があります。
SingleLogoutService:ログアウト処理を行うエンドポイント
AssertionConsumerService:認証応答を受け取るエンドポイント
SingleSignOnService:認証要求を送るエンドポイント
BASE_URL は、アプリケーションで使用しない URL パスを指定する必要があります。
カレントディレクトリに
https_kcapp.example.com.cert
https_kcapp.example.com.key
https_kcapp.example.com.xml
が作成されます。
idp_metadata.xml がまだありません。Keycloak から取得します。
取得先は、https://kctest.contoso.com/realms/[Realm名(今回は、TestRealm)]/protocol/saml/descriptor です。
# curl -k -o /etc/apache2/saml/idp_metadata.xml \
https://kctest.contoso.com/realms/TestRealm/protocol/saml/descriptor設定を反映します。
# systemctl reload apache2IdP:Keycloak SAML 設定
Keycloak 管理コンソールにて、SAML クライアントの設定を行います。
ここまで、SAML クライアント、つまり、アプリ(SP)側の URL は、https://kcapp.example.com/ であるという前提として進めてきました。
SAML クライアント(mod_auth_mellon のサーバー)は既に構築済みのため、mod_auth_mellon のサーバーからクライアントメタデータをダウンロードして、それを Keycloak へインポートして登録します。
これにより、本来、Keycloak 管理コンソールで設定が必要な URL の設定や Signing keys config の登録など、省略することになります。
https://kcapp.example.com/mellon/metadata から SP のメタデータをダウンロードします。
Keycloak 管理コンソールから TestRealm に移動して、 Clients をクリックして、Import client をクリックします。
Browse... クリックし、先ほどダウンロードしたファイルを選択します。
インポートされるため、ひとまず、何も変更せずに、Save をクリックします。
Keycloak に SAML クライアントが登録されました。
その他、設定は全てデフォルトとします。
Valid redirect URIs は、認可後リダイレクトされる URI を入力します。デフォルトは、* です。
パスだけ設定する場合は、Root URL からの相対パスとなります。
今回、認可後リダイレクトされる URI は、https://kcapp.example.com/mellon/postResponse になるため、https://kcapp.example.com/mellon/postResponse が自動的に設定されています。
SAML 認証動作確認
testuser でログインしてみます。
今回、単一アプリの認証が通ることだけ確認して、SSO の確認は行いません。
https://kcapp.example.com/ へアクセスします。
↓(そのまま URL を書き換えて)
https://kcapp.example.com/info.php へアクセスします。
OK!
今回の場合、SAML クライアントのメタデータをインポートしたため、特に問題無かったですが、手動でクライアントを登録する場合、以下の問題が発生するかもしれません。
/opt/keycloak/data/log/keycloak.log に以下のログが出力されている場合、Keycloak 側設定 Client ID と mod_auth_mellon で作成したメタデータの ENTITY_ID がずれている可能性があります。
2023-11-25 17:14:22,540 WARN [org.keycloak.events] (executor-thread-82) type=LOGIN_ERROR, realmId=167b42ad-a626-4475-9d32-3a8c97e8f6b3, clientId=null, userId=null, ipAddress=192.168.11.5, error=client_not_found, reason=Cannot_match_source_hash
以下の場合は、Signing keys config の Certificate が間違っている可能性があります。
2023-11-25 18:55:27,139 WARN [org.keycloak.events] (executor-thread-72) type=LOGIN_ERROR, realmId=be563de8-bb3d-49af-9073-1dfe8e859dfd, clientId=null, userId=null, ipAddress=192.168.11.5, error=invalid_signature
その他、SP、IdP の時刻が大幅にずれていないか確認が必要です。
IdP:Keycloak SAML 同意画面
Keycloak の設定によって、同意画面(Consent)を表示することもできます。
Clients → https://kcapp.example.com → Consent required を On に設定して、Save をクリックします。
アプリにログインしてみます。
同意画面が追加されました!
同意した事実は、Keycloak 管理コンソールから TestRealm に移動して、
Users → testuser → Consents タブにて、確認できて、取り消すこともできます。(取り消すと、もう一度同意画面が出てきます。)
今回は、内部 DB にユーザー情報を登録していますが、Kerberos(Active Directory)や LDAP にもできます。
OpenLDAP を利用した例は、過去記事「Keycloak PostgreSQL OpenLDAP mod_auth_openidc で SSO 全手順」にあります。
IdP:Azure AD
Identity providers に Azure AD(Azure Active Directory/Microsoft Entra ID)を追加して、Azure AD のアカウントで認証するように変更していきます。
まず、Azure AD 側の設定を行います。
Azure ポータルから、Microsoft Entra ID に移動して、エンタープライズ アプリケーション をクリックします。
+新しいアプリケーション をクリックします。
+独自のアプリケーション作成 をクリックします。
お使いのアプリの名前は何ですか?
のところを KeycloakTEST とします。ギャラリーに見つからないその他のアプリケーションを統合します (ギャラリー以外) にチェックが入った状態とし、作成 をクリックします。
シングル サインオンの設定 のところの 作業の開始 をクリックします。
SAML をクリックします。
編集 をクリックします。
識別子 (エンティティ ID):https://kctest.contoso.com/realms/TestRealm
応答 URL (Assertion Consumer Service URL):https://kctest.contoso.com/realms/TestRealm/broker/saml/endpoint
とし、保存 をクリックします。
識別子 (エンティティ ID)は、mod_auth_mellon で出てきた ENTITY_ID と考え方は同じで、一意の識別子です。何でも良いですが、この後 Keycloak の設定画面で初期設定された状態で表示されるのがこの URL です。
応答 URL (Assertion Consumer Service URL) もこの後 Keycloak の設定画面で固定のエンドポイント URL が表示されるからこの URL です。ここでは、両方分かっているものとします。
ここで、アプリのフェデレーション メタデータ URL をコピーして、メモっておきます。※後でも見に来れます。
ユーザーとグループ をクリックし、+ユーザーまたはグループの追加 をクリックします。
しばらく待つか、一旦初期画面に戻って、KeycloakTEST を選択しなおさないといけないかもしれません。
続けて操作していた時、割り当てられず、エラーになりました。
割り当ての追加 画面に切り替わり、選択されていません をクリックします。
SAML 認証を使うユーザー/グループを選択し、選択 をクリックします。
今回は、すべてのユーザー にします。
割り当て をクリックします。
これで Azure AD 側は、準備完了です。
IdP/SP:Keycloak Identity providers 追加
Azure AD と紐づけて、IdP とします。
Keycloak を アプリにとっての IdP、Azure AD にとっての SP とします。
Keycloak 管理コンソールから TestRealm に移動して、
Identity providers をクリックして、SAML v2.0 をクリックします。
SAML entity descriptor の設定のところに、先ほど Azure AD に表示されていてコピーした アプリのフェデレーション メタデータ URL をペーストします。
ここで、Keycloak → https://login.microsoftonline.com/... とサーバーサイドでアクセスが行きます。
Keycloak がインターネットに出られない場合、プロキシ経由で出る必要があります。
No valid metadata was found at thie URL:'Network response was not OK.'
となった場合、そういうことです。
↓
ここでは、プロキシ経由でインターネットへ出る設定を行います。
緑色のチェックマークが付いた場合、必要のない作業ですので、読み飛ばしてください。
# vi /etc/systemd/system/keycloak.service以下のように書き換え(http://192.168.0.158:3128 は、プロキシサーバーのこと)
ExecStart=/opt/keycloak/bin/kc.sh start --log=console,file
↓
ExecStart=/opt/keycloak/bin/kc.sh start --log=console,file --spi-connections-http-client-default-proxy-mappings="'.*\\\.microsoftonline\\\.com;http://192.168.0.158:3128'"余談ですが、マニュアルの Configuring outgoing HTTP requests(2023 年 11 月時点)に
bin/kc.[sh|bat] start --spi-connections-http-client-default-<configurationoption>=<value>と説明があるのですが、
proxy-mappingsの具体的な記述例の
...-proxy-mappings="'の直後にドットが無く、これをベースに設定しても効きませんでした。ドットが必要でした。
# systemctl daemon-reload
# systemctl restart keycloak.serviceでプロキシが有効になり、緑色のチェックマークが付くはずです。
他の方法としては、keycloak.service の
[Service]セクションに
Environment="HTTP_PROXY=http://192.168.0.158:3128"
Environment="HTTPS_PROXY=http://192.168.0.158:3128"
Environment="NO_PROXY=.example.com,.contoso.com"と記述してもプロキシ有効になりました。
※この場合、
kc.sh startのオプションは変更不要です。
ここからは、プロキシうんぬん関係なく、共通の手順に戻ります。
↓
SAML entity descriptor の URL が認識されたら、Add をクリックします。
いろいろ自動登録されますので、ひとまず、Save をクリックします。
SAML Azure AD 認証動作確認1
https://kcapp.example.com/ へアクセスすると、
Or sing in with
saml
が追加されていますので、saml をクリックします。
saml の表記は、Keycloak の Identity providers → saml → General settings - Alias 設定の文字列になります。
Azure AD でおなじみのサインイン画面が表示されるようになります。
ヨシ!っといきたいところですが、
Keycloak の Identity providers → saml → Advanced settings - First login flow
の設定が first broker login となっているため、最初に Username, Email, First name, Last name の登録を迫られます。
今回は、ここで止まって欲しくないので、First login flow の設定を変更します。
First login flow は、ユーザーが初めて外部 IdP からログインした後に使用されるワークフローを選択します。
デフォルトでは、この設定は
first broker loginを指していますが、独自のフローを作成して設定することも可能です。
IdP/SP:Keycloak Flow 追加
First login flow に簡略化されたフローを指定したいため、オリジナルのフローを作成します。
※フローについての細かい説明は省略します。
Keycloak 管理コンソールから TestRealm に移動して、 Authentication をクリックして、Create flow をクリックします。
Name に None を入力して、Create をクリックします。
Add execution をクリックします。
Create User If Unique にチェックを入れて、Add をクリックします。
Create User if Unique ステップは、Keycloak アカウント(今回は、
testuser一人)と email が一致した場合、そのユーザーと特定し、それ以外の場合は、新規に Keycloak アカウント 作成という意味です。
Requirement を Alternative と変更します。(変更した時点でシステムに反映されます。)
再び、
Identity providers → saml → Advanced settings - First login flow
に戻ると、None が選択可能になっているため、None を選択して、Save をクリックします。
SAML Azure AD 認証動作確認2
https://kcapp.example.com/ へアクセスし、saml をクリックします。
Azure AD のサインイン画面が表示され、サインインします。
↓(そのまま URL を書き換えて)
https://kcapp.example.com/info.php へアクセスします。
アプリが表示されました!
ヨシ!
しかし、実は、Keycloak の Users を見ると、Azure AD が決めた ID で強引に登録されています。誰が誰だか分かりません。
・・・あとは頑張ればなんとかなりそうだし、ヨシ!

その他、宣伝、誹謗中傷等、当方が不適切と判断した書き込みは、理由の如何を問わず、投稿者に断りなく削除します。
書き込み内容について、一切の責任を負いません。
このコメント機能は、予告無く廃止する可能性があります。ご了承ください。
コメントの削除をご依頼の場合はTwitterのDM等でご連絡ください。




































































