Metonymical Deflection

ゆるく日々のコト・たまにITインフラ

KeycloakによるSAML Idpの設定方法

Keycloakを使用したSAML Idpの設定方法を記載していきます。
ここでは動作確認用としてWordpressSAML SPとします。
Keycloakの認証バックエンドには、Windows2019のADを使用します。

1.構成

1-1.環境

全ての端末(仮想マシン)はVMWare上に構築しています。

VMWare : VMware(R) Workstation 15 Pro 15.5.1 build-15018445 

Keycloak用仮想マシン
OS : Ubuntu 22.04.2
Java : openjdk-17
Keycloak : 22.0.5
OpenSSL : 3.0.2

Wordpress仮想マシン
bitnami-wordpress-5.9.0
OVAからデプロイ

Active Directory仮想マシン
OS : Windows Server 2019

ClientPC用仮想マシン
OS : Windows10
1-2.全体の流れ
  • ドメイン登録
  • AD構築
  • 証明書発行
  • Keycloakインストール
  • Keycloak 各種設定
  • Wordpress インストール&各種設定
  • 動作確認
1-3.全体構成

fig.1

IPアドレスドメイン名は自身の環境に置き換えてください。
私の環境ではヘアピンNATができないためBBルータが2台あります。
BBルータAの方で、TCP8443でポートフォワードの設定をしています。*1

2.ドメイン登録

自身で独自ドメインを取得するか、以下のサイトなどで無料のドメイン登録を行ってください。
ddns.kuku.lu
ここでは上記サイトで、idp.f5.siのドメインを登録したものとして進めます。
登録したドメインを使用して、AレコードにGlobalIP-AのIPアドレスを設定しておいてください。

補足
KeycloakのHostname設定に、IPアドレスを設定していると、HTTPリダイレクトの際にうまく動作しなかったり、といったことを確認したため、ドメイン登録の項を記載しました。
仮に、閉じられた環境内で構築する場合であっても、別途DNSサーバを構築して、名前解決可能な環境にしておくことが必要だと考えています。*2

3.AD構築

以下のサイトなどを参考にADの構築を行ってください。
www.rem-system.com
上記サイトは、スクショ入りのStep by Stepで詳細に記載されており、特に躓くことなくADを構築できます。

ADはKeycloakの認証バックエンドとして利用しますので、AD上に任意のユーザを2-3つくらい作成しておいてください。
ここでは例として、user001@example.comといったユーザを作成したものとして進めます。*3
補足
AD上でユーザを作成する際、以下のように作成されていることを前提として進めます。

4.証明書発行

ここからは、Keycloak用仮想マシンでの作業となります。

4-1.openssl.cnfの設定

/etc/ssl/openssl.cnfファイルを編集します。
青文字箇所が変更した部分となります。

vi /etc/ssl/openssl.cnf
==== snip ====
[ CA_default ]

dir             = /etc/ssl/demoCA      # Where everything is kept  ./demoCAから絶対Pathに変更
certs           = $dir/certs            # Where the issued certs are kept

==== snip ====
[ req_distinguished_name ]
countryName                     = Country Name (2 letter code)
countryName_default             = JP
countryName_min                 = 2
countryName_max                 = 2

stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = Tokyo

localityName                    = Locality Name (eg, city)
localityName_default            = Chiyoda-ku

0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = f5.si

# we can do this but it is not needed normally :-)
#1.organizationName             = Second Organization Name (eg, company)
#1.organizationName_default     = World Wide Web Pty Ltd

organizationalUnitName          = Organizational Unit Name (eg, section)
#organizationalUnitName_default =

commonName                      = Common Name (e.g. server FQDN or YOUR name)
commonName_max                  = 64
==== snip ====
4-2.CAの構築

/usr/lib/ssl/misc/CA.plを使用して、CAを構築していきます。

cd /etc/ssl
/usr/lib/ssl/misc/CA.pl -newca

<出力例>

root@u222c96:/etc/ssl# /usr/lib/ssl/misc/CA.pl -newca
CA certificate filename (or enter to create) <ー空Enter

Making CA certificate ...
openssl req  -new -keyout ./demoCA/private/cakey.pem -out ./demoCA/careq.pem
..+......+....+..+.......+.....+.......+.....+....+.....+.+......+........+....+...+.................+.+..+...+....+...+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.....+...+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..+.+.....+...+.+..+...+......+.........+....+...................................+..........+......+..+.......+............+......+.................+.......+...+......+.....+.....................+......+.......+.....+......+....+..+...+............+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
..+.+..............+.+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.....+.+...+.....+.+.....+....+..+.........+..........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.....+.....+......+...+....+......+..+.........+...+.+......+......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Enter PEM pass phrase: <ーパスフレーズを入力
Verifying - Enter PEM pass phrase: <ーパスフレーズを入力
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [JP]: <ー空Enter
State or Province Name (full name) [Tokyo]: <ー空Enter
Locality Name (eg, city) [Chiyoda-ku]: <ー空Enter
Organization Name (eg, company) [f5.si]: <ー空Enter
Organizational Unit Name (eg, section) : <ー空Enter
Common Name (e.g. server FQDN or YOUR name) :CA.f5.si <ーCAのCommon Nameを手入力。任意の名前でOK
Email Address : <ー空Enter

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password : <ー空Enter
An optional company name []: <ー空Enter
==> 0
openssl ca  -create_serial -out ./demoCA/cacert.pem -days 1095 -batch -keyfile ./demoCA/private/cakey.pem -selfsign -extensions v3_ca -infiles ./demoCA/careq.pem
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem: <ー最初に入力した(cakeyの)パスフレーズを再度入力
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:
            6e:fa:be:0b:64:8b:ea:4c:c2:ee:c2:7b:62:b3:64:5f:52:40:59:2b
        Validity
            Not Before: Nov 23 00:12:36 2023 GMT
            Not After : Nov 22 00:12:36 2026 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = f5.si
            commonName                = CA.f5.si
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                3B:BE:09:A3:AF:51:5A:6A:D5:3F:DD:C1:D2:60:4A:88:E9:F8:79:BF
            X509v3 Authority Key Identifier:
                3B:BE:09:A3:AF:51:5A:6A:D5:3F:DD:C1:D2:60:4A:88:E9:F8:79:BF
            X509v3 Basic Constraints: critical
                CA:TRUE
Certificate is to be certified until Nov 22 00:12:36 2026 GMT (1095 days)

Write out database with 1 new entries
Data Base Updated
==> 0
CA certificate is in ./demoCA/cacert.pem

これにより、/etc/ssl配下に、demoCAというディレクトリが作成されます。
/etc/ssl/demoCA配下に、CAのルート証明書が格納されています。
/etc/ssl/demoCA/private配下に、CAのキーファイルが格納されています。

4-3.Idpで利用する証明書を発行

/etc/ssl/demoCA配下でIdpの証明書を発行します。
初めに、SAN(Subject Altanative Name)設定ファイルを作成します。

cat > /etc/ssl/demoCA/subjectnames.txt <<EOF
subjectAltName = DNS:idp.f5.si
EOF
cd /etc/ssl/demoCA
openssl genrsa -out idp.key 2048
openssl req -utf8 -new -key idp.key -out idp.csr
openssl ca -in idp.csr -out idp.pem -extfile subjectnames.txt

<出力例>

root@u222c96:/etc/ssl/demoCA# cd /etc/ssl/demoCA
root@u222c96:/etc/ssl/demoCA# openssl genrsa -out idp.key 2048
root@u222c96:/etc/ssl/demoCA# openssl req -utf8 -new -key idp.key -out idp.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [JP]: <ー空Enter
State or Province Name (full name) [Tokyo]: <ー空Enter
Locality Name (eg, city) [Chiyoda-ku]: <ー空Enter
Organization Name (eg, company) [f5.si]: <ー空Enter
Organizational Unit Name (eg, section) : <ー空Enter
Common Name (e.g. server FQDN or YOUR name) :idp.f5.si <ーidp.f5.siと入力
Email Address :

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password : <ー空Enter
An optional company name []: <ー空Enter

root@u222c96:/etc/ssl/demoCA# openssl ca -in idp.csr -out idp.pem -extfile subjectnames.txt
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for /etc/ssl/demoCA/private/cakey.pem: <ーcakeyのパスフレーズを再度入力
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:
            6e:fa:be:0b:64:8b:ea:4c:c2:ee:c2:7b:62:b3:64:5f:52:40:59:2c
        Validity
            Not Before: Nov 23 06:24:02 2023 GMT
            Not After : Nov 22 06:24:02 2024 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = f5.si
            commonName                = idp.f5.si
        X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:idp.f5.si
Certificate is to be certified until Nov 22 06:24:02 2024 GMT (365 days)
Sign the certificate? [y/n]:y <ーyを入力しEnter


1 out of 1 certificate requests certified, commit? [y/n]y <ーyを入力しEnter
Write out database with 1 new entries
Data Base Updated
4-4.発行した証明書の確認

以下ファイルのうち、cacert.pem, idp.pem, idp.keyは後ほど使用しますので、ClientPC内などに保存しておきます。

root@u222c96:/etc/ssl/demoCA# ls
cacert.pem  crl        idp.key    index.txt.attr      newcerts  serial.old
careq.pem   crlnumber  idp.pem    index.txt.attr.old  private   subjectnames.txt
certs       idp.csr    index.txt  index.txt.old       serial

5.Keycloakインストール

5-1.OpenJDK17インストール
apt update && \
apt -y install openjdk-17-jdk
5-2.KeycloakソースDL
mkdir /root/tmp && \
cd /root/tmp && \
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
5-3.Keycloak初期起動

ローカルホスト名に任意のホスト名を追記します。
これを実施しないと、Keycloak起動時にエラーで起動できない場合があるためです。
idp.f5.siのようにFQDNで記載しないでください。

vi /etc/hosts

127.0.0.1 localhost idp <ー ローカルホスト名にidpを追記

続いて、管理者アカウントの設定を行います。
ここでは例として、ユーザ名:admin、パスワード:Password!とします。
環境変数に設定後、echoコマンドで確認します。

KEYCLOAK_ADMIN=admin && \
export KEYCLOAK_ADMIN && \
KEYCLOAK_ADMIN_PASSWORD=Password! && \
export KEYCLOAK_ADMIN_PASSWORD

echo $KEYCLOAK_ADMIN
echo $KEYCLOAK_ADMIN_PASSWORD

<出力例>
以下のように出力されればOKです。

root@u222c93:~/tmp# echo $KEYCLOAK_ADMIN
admin
root@u222c93:~/tmp# echo $KEYCLOAK_ADMIN_PASSWORD
Password!

それでは、Keycloakを起動します。

cd /root/tmp/keycloak-22.0.5/bin/
./kc.sh start-dev

<出力例>

root@u222c93:~/tmp/keycloak-22.0.5/bin# ./kc.sh start-dev
Updating the configuration and installing your custom providers, if any. Please wait.
2023-11-23 16:14:12,828 INFO  [io.quarkus.deployment.QuarkusAugmentor] (main) Quarkus augmentation completed in 5769ms
2023-11-23 16:14:14,012 INFO  [org.keycloak.quarkus.runtime.hostname.DefaultHostnameProvider] (main) Hostname settings: Base URL: , Hostname: , Strict HTTPS: false, Path: , Strict BackChannel: false, Admin URL: , Admin: , Port: -1, Proxied: false
2023-11-23 16:14:14,961 WARN  [io.quarkus.agroal.runtime.DataSources] (main) Datasource  enables XA but transaction recovery is not enabled. Please enable transaction recovery by setting quarkus.transaction-manager.enable-recovery=true, otherwise data may be lost if the application is terminated abruptly
2023-11-23 16:14:15,348 WARN  [org.infinispan.PERSISTENCE] (keycloak-cache-init) ISPN000554: jboss-marshalling is deprecated and planned for removal
2023-11-23 16:14:15,421 WARN  [org.infinispan.CONFIG] (keycloak-cache-init) ISPN000569: Unable to persist Infinispan internal caches as no global state enabled
2023-11-23 16:14:15,499 INFO  [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000556: Starting user marshaller 'org.infinispan.jboss.marshalling.core.JBossUserMarshaller'
2023-11-23 16:14:16,050 INFO  [org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory] (main) Node name: node_127375, Site name: null
2023-11-23 16:14:16,055 INFO  [org.keycloak.broker.provider.AbstractIdentityProviderMapper] (main) Registering class org.keycloak.broker.provider.mappersync.ConfigSyncEventListener
2023-11-23 16:14:18,460 INFO  [org.keycloak.quarkus.runtime.storage.legacy.liquibase.QuarkusJpaUpdaterProvider] (main) Initializing database schema. Using changelog META-INF/jpa-changelog-master.xml

UPDATE SUMMARY
Run:                        115
Previously run:               0
Filtered out:                 0
-------------------------------
Total change sets:          115

2023-11-23 16:14:21,812 INFO  [org.keycloak.services] (main) KC-SERVICES0050: Initializing master realm
2023-11-23 16:14:23,400 INFO  [io.quarkus] (main) Keycloak 22.0.5 on JVM (powered by Quarkus 3.2.7.Final) started in 10.483s. Listening on: http://0.0.0.0:8080
2023-11-23 16:14:23,401 INFO  [io.quarkus] (main) Profile dev activated.
2023-11-23 16:14:23,401 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]
2023-11-23 16:14:23,521 INFO  [org.keycloak.services] (main) KC-SERVICES0009: Added user 'admin' to realm 'master'
2023-11-23 16:14:23,522 WARN  [org.keycloak.quarkus.runtime.KeycloakMain] (main) Running the server in development mode. DO NOT use this configuration in production.

<補足1>
Ctrl+c でKeycloakを停止することが可能です。

<補足2>
もし、起動時にエラーが出力される場合は、以下3つのいずれかをそれぞれ試してください。

./kc.sh start-dev --db-pool-initial-size=100
./kc.sh start-dev --db-pool-max-size=100
./kc.sh start-dev --db-pool-min-size=100

私が試した結果、基本的には最初に記載した/etc/hostsファイルのローカルホストに任意のホスト名(FQDNはNG)を記載するだけで問題なく起動するはずです。

5-4.Keycloak管理コンソールログイン

管理コンソールにログインします。
ここではログインテストとして、ローカルのNWセグメント(192.168.240.0/24 or 192.168.33.0/24)から、http://192.168.240.93:8080/ もしくはhttp://192.168.33.93:8080/にログインしてください。

http://192.168.240.93:8080/にアクセス
Administration Consoleをクリック

ユーザ名とパスワードを入力して、Sign Inをクリック

Keycloakのメイン画面が表示されます。

ここではログインテストとして、http://192.168.240.93:8080/にアクセスしましたが、実際はClientPCがInternet経由でIdpにアクセスします。(fig.1参照)
このため、この後の項では、登録したドメイン名でのアクセスやSSL化するための設定を実施していきます。
fig.1

6.Keycloak各種設定

既に起動してあるKeycloakは、Ctrl+cで一旦停止しておいてください。

6-1.証明書ファイルのコピー

idp.pem, idp.keyをコピーしておきます。

cp /etc/ssl/demoCA/idp.pem /root/tmp/keycloak-22.0.5/conf/
cp /etc/ssl/demoCA/idp.key /root/tmp/keycloak-22.0.5/conf/
6-2.keycloak.conf設定

SSL化設定やKeycloakのホスト名設定を実施します。

vi /root/tmp/keycloak-22.0.5/conf/keycloak.conf

=====snip=====
# The file path to a server certificate or certificate chain in PEM format.
#https-certificate-file=${kc.home.dir}conf/server.crt.pem
https-certificate-file=/root/tmp/keycloak-22.0.5/conf/idp.pem

# The file path to a private key in PEM format.
#https-certificate-key-file=${kc.home.dir}conf/server.key.pem
https-certificate-key-file=/root/tmp/keycloak-22.0.5/conf/idp.key

=====snip=====

# Hostname for the Keycloak server.
#hostname=myhostname
hostname=idp.f5.si
6-3.keycloak起動

それでは、改めてKeycloakを起動します。*4

cd /root/tmp/keycloak-22.0.5/bin/
./kc.sh start-dev

<出力例>
初回起動と大きく異なる点は、https://0.0.0.0:8443が追加された点です。

root@u222c93:~/tmp/keycloak-22.0.5/bin# ./kc.sh start-dev
2023-11-23 16:56:54,173 INFO  [org.keycloak.quarkus.runtime.hostname.DefaultHostnameProvider] (main) Hostname settings: Base URL: , Hostname: idp.f5.si, Strict HTTPS: false, Path: , Strict BackChannel: false, Admin URL: , Admin: , Port: -1, Proxied: false
2023-11-23 16:56:55,317 WARN  [io.quarkus.agroal.runtime.DataSources] (main) Datasource  enables XA but transaction recovery is not enabled. Please enable transaction recovery by setting quarkus.transaction-manager.enable-recovery=true, otherwise data may be lost if the application is terminated abruptly
2023-11-23 16:56:55,654 WARN  [org.infinispan.PERSISTENCE] (keycloak-cache-init) ISPN000554: jboss-marshalling is deprecated and planned for removal
2023-11-23 16:56:55,705 WARN  [org.infinispan.CONFIG] (keycloak-cache-init) ISPN000569: Unable to persist Infinispan internal caches as no global state enabled
2023-11-23 16:56:55,749 INFO  [org.infinispan.CONTAINER] (keycloak-cache-init) ISPN000556: Starting user marshaller 'org.infinispan.jboss.marshalling.core.JBossUserMarshaller'
2023-11-23 16:56:56,584 INFO  [org.keycloak.connections.infinispan.DefaultInfinispanConnectionProviderFactory] (main) Node name: node_752132, Site name: null
2023-11-23 16:56:56,589 INFO  [org.keycloak.broker.provider.AbstractIdentityProviderMapper] (main) Registering class org.keycloak.broker.provider.mappersync.ConfigSyncEventListener
2023-11-23 16:56:57,637 INFO  [io.quarkus] (main) Keycloak 22.0.5 on JVM (powered by Quarkus 3.2.7.Final) started in 4.471s. Listening on: http://0.0.0.0:8080 and https://0.0.0.0:8443
2023-11-23 16:56:57,637 INFO  [io.quarkus] (main) Profile dev activated.
2023-11-23 16:56:57,637 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]
2023-11-23 16:56:57,641 WARN  [org.keycloak.quarkus.runtime.KeycloakMain] (main) Running the server in development mode. DO NOT use this configuration in production.
6-4.Keycloak管理コンソールログイン

改めて管理コンソールにログインします。
https://idp.f5.si:8443/にアクセス

以降は、ClientPC側から、https://idp.f5.si:8443/にアクセスしながら設定を進めて行きます。
当然、Internetに晒されているため、SrcIPをGlobalIP-Bだけに絞るなど、BBルータA上で各種セキュリティ設定を行っておいてください。*5

https://idp.f5.si:8443/にアクセスした際、ブラウザ上に証明書の警告が表示されますので、/etc/ssl/demoCA/cacert.pemをクライアントPCの信頼されたルート証明機関にインストールしておいてください。

6-5.レルムの作成

KeycloaK上にレルムを作成します。*6

masterのプルダウンメニューから、Create Realmをクリック

Realm nameに任意の名前を入力して、Createをクリック*7
ここでは例として、KC_Idpとします。

KC_Idpレルムが作成されました。このレルム上で各種設定を行っていきます。

6-6.ADとの連携設定

サイドメニューの一番下にあるUser federationをクリック

User federation画面にて、Add Ldap providersをクリック

設定が必要な項目のみピックアップします。

項目 設定値 備考
UI display name ADDC 任意の名前でOKです。
Connection URL ldap://192.168.240.92
BindDN CN=Administrator,CN=Users,DC=example,DC=com DC=example,DC=comの部分は自身の環境に合わせて変更
BindCredentials Administratorのパスワードを入力
Edit mode READ_Only
UsersDN CN=Users,DC=example,DC=com BindDNと同様に自身の環境に合わせて変更
Import users Off 一旦Offにしておきます。
Sync Registrations Off READ_Onlyの場合は使用しないため無効にします
User LDAP filter (&(objectClass=person)(userPrincipalName=*))

以下のように設定してSaveをクリック

Periodic full syncの項目が消えていますが、DefaultのOffから変更していません。

登録が完了すると以下の画面が表示されます。
続けて、Mappers設定を行うため、ADDCをクリック

6-7.Mappers設定

ADDCから取得した各種のLDAP属性をKeycloakで利用可能な属性にマッピングします。

初期状態は以下のようになっています。
ここでは、group, sAMAccountNameを追加し、usernameを編集していきます。

都度、Add mapperをクリックして、Mapper typeを選択すると、必要な設定項目が表示されます。

6-7-1.Group Mappers設定

設定が必要な項目のみピックアップします。

項目 設定値 備考
Name group
Mapper type group-ldap-mapper プルダウンメニューから選択すると設定項目が表示
LDAP Groups DN CN=Users,DC=example,DC=com 自身の環境に合わせて変更
Preserve Group Inheritance Off Directory同期時にエラーとなるためOff
Ignore Missing Groups Off 注意:もしDirectory同期時にエラーとなる場合はOn

以下のように設定してSaveをクリック

6-7-2.sAMAccountName Mappers設定

設定が必要な項目のみピックアップします。

項目 設定値 備考
Name sAMAccountName
Mapper type user-attribute-ldap-mapper プルダウンメニューから選択すると設定項目が表示
User Model Attribute sAMAccountName
LDAP Attribute cn
Always Read Value From LDAP Off 作成時はこの項目自体が存在しないため無視してください

以下のように設定してSaveをクリック

6-7-3.username Mappers設定

既存のusernameをクリックして編集します。
設定が必要な項目のみピックアップします。

項目 設定値 備考
Name username グレーアウトのため変更不要
Mapper type user-attribute-ldap-mapper グレーアウトのため変更不要
User Model Attribute username 変更不要
LDAP Attribute userPrincipalName cnからuserPrincipalName
Always Read Value From LDAP Off 作成時はこの項目自体が存在しないため無視してください

以下のように設定してSaveをクリック

6-7-4.ユーザのインポート

前項でMapperが以下のように設定されていればOKです。

ユーザをインポートするため、一旦Settingsタブに切り替えます。
Synchronization settingsまでスクロールダウンして、Import usersをOnに変更しSaveします。

再び、Mappersタブに切り替えて、Actionプルダウンメニューから、Sync all usersをクリックします。
すると、以下のメッセージが表示されインポートが完了します。

補足1
ここでは8usersになっていますが、作成したユーザ数によって変化します。
補足2
インポートしたユーザはサイドメニューのUsersから参照できます。
何も表示されない場合がありますが、検索フォームにuserなどと入力して検索すると表示されます。*8

6-8.Idp証明書のインポートと設定

4-4.発行した証明書の確認でClientPCに保存したidp.pemとidp.keyをKeycloakにインポートしていきます。

6-8-1.既存の自己署名証明書の削除

Realm settings>Keysタブ>Providersタブをクリック
rsa-generatedの右側にある「・・・」をクリックすると、Deleteが表示されますのでクリックします。

以下の画面が表示されるので、さらにDeleteをクリック

rsa-generatedが削除されました。

6-8-2.idp.pemの編集

OpenSSLで発行したidp.pemには、余分な行が含まれているため、インポート時にエラーとなります。
このため、ClientPCに保存しているidp.pemをテキストエディタなどで開き、-----BEGIN CERTIFICATE-----より、上の行を削除します。
以下の例では、赤文字部分を削除して、青文字部分だけ残します。

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            3c:f3:fd:5b:4b:0d:4c:3f:3c:70:8f:64:74:0b:67:65:56:b3:fa:65
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C=JP, ST=Tokyo, O=f5.si, CN=CA.f5.si
        Validity
            Not Before: Nov 23 07:03:39 2023 GMT
            Not After : Nov 22 07:03:39 2024 GMT
        Subject: C=JP, ST=Tokyo, O=f5.si, CN=idp.f5.si
        Subject Public Key Info:
=====snip=====
        65:5e:9f:df:e0:ea:52:05:52:61:8e:96:55:ea:32:12:3f:a7:
        e9:89:9c:d6:72:93:41:83:af:37:03:04:10:ed:45:bf:b5:2a:
        b9:76:57:e2:2b:5b:fa:35:de:31:9a:68:c7:e1:48:c4:6f:13:
        b5:6a:9c:39:c7:18:ac:23:92:1a:96:4b:67:09:84:8a:f0:a7:
        aa:25:67:4c:69:ee:d0:91:51:1e:87:15:47:6f:5a:a4:76:bf:
        5d:43:03:dc:a3:7d:ff:61:1d:e7:49:4f:19:dd:10:46:6e:4a:
        32:c8:c6:ba:95:e2:39:21:65:11:22:b7:ed:73:66:3b:b6:f8:
        c0:50:04:39:ce:ae:7c:cc:c1:62:a9:9e:33:bf:4e:88:38:4b:
        6a:aa:7c:8f:18:98:53:09:81:d7:c1:67:19:50:70:16:4c:34:
        c1:70:b4:7f:06:d3:2f:96:0b:fa:3b:b2:3d:ef:ac:37:05:d9:
        bf:7b:de:f4
-----BEGIN CERTIFICATE-----
MIIDZzCCAk+gAwIBAgIUPPP9W0sNTD88cI9kdAtnZVaz+mUwDQYJKoZIhvcNAQEL
BQAwQDELMAkGA1UEBhMCSlAxDjAMBgNVBAgMBVRva3lvMQ4wDAYDVQQKDAVmNS5z
aTERMA8GA1UEAwwIQ0EuZjUuc2kwHhcNMjMxMTIzMDcwMzM5WhcNMjQxMTIyMDcw
=====snip=====
BBDtRb+1Krl2V+IrW/o13jGaaMfhSMRvE7VqnDnHGKwjkhqWS2cJhIrwp6olZ0xp
7tCRUR6HFUdvWqR2v11DA9yjff9hHedJTxndEEZuSjLIxrqV4jkhZREit+1zZju2
MBQBDnOrnzMwWKpnjO/Tog4S2qqfI8YmFMJgdfBZxlQcBZMNMFwtH8G0y+WC/o7
sj3vrDcF2b973vQ=
-----END CERTIFICATE-----
6-8-3.idp.pemとidp.keyのインポート

Realm settings>Keysタブ>Providersタブ>Add providerをクリック
以下の画面で、rsaをクリック

以下の画面で、idp.pemとidp.keyをインポートします。
Nameには、任意の名前(ここでは、idp.f5.si)を入力します。
Private RSA KeyのBrowse...をクリックして、idp.keyを選択します。
X509 CertificateのBrowse...をクリックして、idp.pemを選択します。

最後にSaveをクリックすると、以下のように登録されます。

idp.f5.siの左のアイコン(・・・が6つあるアイコン)をドラッグすると優先順位を上げられるため、一番上に移動させておきます。

6-9.Idpのmetadataのエクスポート

Realm settings>Generalタブをクリック
SAML 2.0 Identity Provider Metadataをクリック

ブラウザ上に新しいタブが作成され、以下の画面が表示されます。

このmetadetaをテキストエディタなどにコピペして、任意のファイル名(idp.xmlなど)で保存しておきます。
idp.xmlは、後ほどSAML SPであるWordpress側にインポートして利用します。

7.Wordpressインストール&各種設定

7-1.Wordpressインストール

以下のサイトからWordpressOVAファイルをDLします。
bitnami.com
OVAファイルをVMWare上にデプロイしてください。

7-2.Wordpress初期設定

構成図に基づき、ssh接続やIPアドレス設定を記載しています。
Defaultでは、DHCP設定にてIPアドレスを自動取得しますが、自動取得が特に気にならない方は、7-2-3までスキップしてください。*9

7-2-1.OSコンソールへのログインとssh設定

以下のクレデンシャルでログインしてください。

ユーザ名:bitnami
パスワード:bitnami

sshのパスワード接続を許可したいので、PasswordAuthenticationのコメントアウトを外します。

sudo vi /etc/ssh/sshd_config

PasswordAuthentication yes

その後、以下のコマンドでsshサーバを起動します。

sudo rm -f /etc/ssh/sshd_not_to_be_run
sudo systemctl enable ssh
sudo systemctl start ssh
7-2-2.IPアドレス設定

ssh接続後、IPアドレスを変更します。*10

sudo vi /etc/systemd/network/25-wired.network

[Match]
Name=ens*

[Network]
Address=192.168.11.94/24
Gateway=192.168.11.1
DNS=192.168.11.1

設定が完了したら、一旦再起動します。

7-2-3.Wordpressコンソールへのログイン

再起動後、VMWareのコンソール上に以下のような画面が表示されます。

ClientPCから以下のURLにアクセスしてください。
補足:パスワードはWordpressをデプロイするたびに自動生成されるため都度変更されます。

http://192.168.11.94/admin/
ユーザ名:user
パスワード:vfwUWFiS25BR

以下のような画面で上記クレデンシャルを入力しログインします。

ログインすると以下の画面が表示されます。
Please update nowをクリックして、最新Verにアップデートしておきます。

初回ログイン時は、WordpressのローカルDBを使用しました。
ここから、WordpressSAML SPとして設定することにより、Keycloak IdpによるSAML認証ができるように設定をしていきます。

7-3.WordpressSAML SP設定
7-3-1.SAML Plug-inのインストール

Plugins>Add New Pluginをクリック

画面右上Keywordの右側にsamlと入力すると検索候補が表示されます。
SAML Single Sign On - SSO LoginのInstall Nowをクリックします。*11

インストールが完了すると以下の表示に切り替わるので、Activateをクリック

以下の画面が表示されるので、Configure Your IDP Nowをクリック*12

7-3-2.SAML Idp(Keycloak) Metadataのインポート

画面中央のUpload IDP Metadataタブをクリックします。
Identity Provider Nameには、任意の名前を入力(ここでは例として、KC_Idpと入力)
ファイル選択をクリックし、6-9.Idpのmetadataのエクスポートで保存したidp.xmlを選択
そして、Uploadをクリック

idp.xmlファイルのアップロードが成功すると、以下の画面が表示。
画面を下スクロールしてSaveをクリック

7-3-3.SAML SP(Wordpress) Metadataのエクスポート

画面上部のService Provider Metadataタブをクリックし、Downloadをクリック
任意のファイル名(ここでは例として、sp.xml)でClientPCに保存

7-3-4.Keycloak SP Metadataのインポート

ここからはKeycloakの管理コンソール画面に切り替えます。
サイドメニューより、Clients>Clients listタブ>Import clientをクリック

画面右上のBrowse...をクリックし、前項でエクスポートしたsp.xmlを選択
Nameには、任意の名前を入力(ここでは例として、wordpressと入力)

最後にSaveをクリックすると、以下の画面が表示されます。

7-3-5.Keycloak Mapper設定

前項画面からの続きで、Client scopesタブをクリック*13
続いて、http://192.168.11.94/wp-content/~をクリック

以下の画面で、Add predefined mapperをクリック

以下の画面で、X500~を全てチェックし、Addをクリック

登録が完了すると、以下の画面が表示されます。

以上で設定は完了です。
ここからは動作確認をしていきます。

8.動作確認

動作確認前に、ここでもう一度構成を確認しておきましょう。

  1. ClientPCー>WordPress SPにアクセスし、SAML認証を選択
  2. ClientPCー>Keycloak Idpにリダイレクトされ、クレデンシャルを入力
  3. ClientPCー>WordPress SPにリダイレクトされ、ログイン完了後の画面が表示

fig.1

ClientPCから以下URLにアクセス
http://192.168.11.94/admin/
Login with KC_Idpをクリック

Keycloakの方にリダイレクトされるので、クレデンシャルを入力して、Sign Inをクリック

以下の警告画面が表示されますが、そのまま送信するをクリック*14

ログイン完了後、以下の画面が表示されます。

以上です。

9.最後に

以下のサイトを参考にさせて頂きました。
Guides - Keycloak
Keycloak22.0.1のセットアップ #Java - Qiita
https://qiita.com/s-takino/items/ee3be5bcf6f318bc5d40

次回以降のKeycloak関連記事では、以下のようなトピックを取り上げられたらいいなと考えています。

  • Nginxによるリバースプロキシ
  • PostgresSQLの利用
  • LetsEncryptによる証明書発行

*1:Keycloakのデフォルト待ち受けポートはTCP8443となります

*2:もう少し掘り下げて検証すれば、Hostname=IPアドレスでも、うまく動作する可能性はあります。しかし、IPアドレスのままでKeycloakを動作させることが目的ではないため、私は素直にドメイン登録をしました。

*3:このユーザ名は一番最後の動作確認時に利用します。

*4:初回は環境変数でユーザ名とパスワードを設定しましたが、2回目以降の起動では設定不要です。

*5:本来であれば、リバプロやWAFの導入といった作業をした方が良いです。また、keycloak.conf上で、hostname-urlやhostname-admin-urlといった設定も可能なのですが今回は割愛しています。

*6:レルムとはKeycloak上の管理ドメインです。初期設定ではmasterレルムが存在していますが、名前の通りmasterなので、これとは別にIdpとして利用するためのレルムを別途作成します。

*7:名前は任意で構いませんが、URI上にこの名前が登場するためスペースを入れたりすることは控えてください。

*8:なぜ表示されないかは謎です。。またユーザが重複して表示される場合もありますがSAML認証には影響しないため気にしないでください。

*9:Wordpressの最新Ver6.4.1の場合、この方法でIPアドレス設定ができませんでした。Wordpressのマニュアルを読む限り、VMWare上の設定が必要とのことで、VMWare関連ドキュメントへのリンクが大量に掲載されたページしか表示されなかったため、Ver5.9.0を使用しています。ここは頑張りどころではないため古いVer5.9.0でスルーしましたが、WordpressはDebian11で動作しているため、Debian11のネットワーク設定を少しいじればサクッと設定できるかもしれません。

*10:DefaultではDHCP設定となっているため固定IP設定とします。Internetに出られれば良いので、DHCP設定のままでも構いません。

*11:似たような候補でLogin using WordPress Users(WP asSAML IDP)が表示されますが無視してください。

*12:画面に表示されているKeycloakをクリックすると、Keycloakの設定マニュアルが表示されます。

*13:サイドメニューにも"Client scopes"がありますが、これはクリックしないでください。もしクリックしてしまった場合、Clients>Clients listタブ>http://192.168.11.94/wp-content/~>Client scopesタブをクリックします。

*14:ClientPCからWordpressにクレデンシャルが平文で送信されます。一般的に、SAML IdpとSP間で直接通信することはなく、必ずClientPCを経由して通信します。今回の構成では、SAML SPであるWordpressSSL化されていなくても、ClientPCとWordpress間はローカルNW内の通信となり、クレデンシャルがInternetに晒されることはないので特に問題ありません。