Keycloakを認証サーバーとして使用して、Oracle APEXのアプリケーションをSAMLにて認証させてみました。現時点で、以下の3つの問題が見つかっています。
- Keycloakが生成する公開鍵証明書をOracle APEXに登録できない。
- X509v3の公開鍵証明書を再生成する。
- Oracle APEXのSAMLコールバックを呼び出す際にOriginヘッダーがnullになる。
- ORDS側でOriginヘッダーがnullでも接続を許可する。
- APEXのSAMLコールバックに含まれる電子署名が無効とされる。
- 現状、対処方法がありません。
最後の問題があるため、現在のところKeycloakによるSAML認証は利用できません。
実施した検証作業を以下に記述します。
以下の環境を想定しています。
- Keycloak 18.0.0
- ホスト名はidp.mydomain.devとします。環境に合わせて読み替えます。
- Oracle CloudのAmpere A1インスタンス - Always Freeに実装。
- 検証は開発モードで実施。
- 記事 - Ampere A1インスタンスにKeycloakをインストールする
- Oracle APEX 22.1
- ホスト名はtest.mydomain.devとします。環境に合わせて読み替えます。
- Oracle CloudのVM.Standard.E4.Flex 1 OCPU、4GBに実装(課金されます)。
- Oracle DatabaseはExpress Edition 21.3を使用。
- ADB(APEX 21.2) + Customer Managed ORDSでも実装可能(課金されません)。
- ORDSは22.1.1を使用。ADB+Customer Managed ORDSでは21.4.3。
- 記事 - APEXを実装したVirutalBoxの仮想マシンをOracle Cloudにインポートする
- 記事 - ORDSの暗号化にLet's Encryptを使用する
- 記事 - TomcatとCertbotを使う実装にしています。
レルムの作成
[keycloak@idp ~]$ kc.sh export --dir $HOME --realm apex
2022-06-10 06:57:19,372 INFO [org.keycloak.quarkus.runtime.hostname.DefaultHostnameProvider] (main) Hostname settings: FrontEnd: idp.apexugj.dev, Strict HTTPS: false, Path: <request>, Strict BackChannel: false, Admin: <request>, Port: -1, Proxied: false
2022-06-10 06:57:19,891 INFO
[中略]
2022-06-10 06:57:22,167 INFO [io.quarkus] (main) Profile import_export activated.
2022-06-10 06:57:22,167 INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-h2, jdbc-mariadb, jdbc-mssql, jdbc-mysql, jdbc-oracle, jdbc-postgresql, keycloak, narayana-jta, reactive-routes, resteasy, resteasy-jackson, smallrye-context-propagation, smallrye-health, smallrye-metrics, vault, vertx]
2022-06-10 06:57:22,320 INFO [io.quarkus] (main) Keycloak stopped in 0.150s
[keycloak@idp ~]$
[keycloak@idp ~]$ sh format-pem.sh private.pem p1
Paste one line PEM
ここでクリップボードの内容をペーストする。
MIIEowIBAAKCAQEA1kzQCcX0SRCe10iTp3rJYX8sjjAjQ4RWmGN/b0yrc2NgYEwyZsQfFPY7GjDChfnXd2J+7o27h6q6s1kTL4RdEhToxk8GB+S0OrMvL0f6yCqQbdxNcTQW51LkC6udxpRw+15e8ooqgNxBs7MgEiRcyvSpRUgblgq+q2hlWm+OMfEOQnaDkKcNLDRhLJK+9CRe5BaL7Z+/kIsMen84knQPpvgwlhBNMjQzRTp
[中略]
0a:47:25:d9:6b:f9:77:cc:5d:83:34:63:3a:9a:a6:
fe:7f:fd:5a:f2:63:7c:36:67:94:02:fd:13:3c:e3:
15:58:e3:6e:d0:e1:fb:eb
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEA1kzQCcX0SRCe10iTp3rJYX8sjjAjQ4RWmGN/b0yrc2NgYEwy
ZsQfFPY7GjDChfnXd2J+7o27h6q6s1kTL4RdEhToxk8GB+S0OrMvL0f6yCqQbdxN
cTQW51LkC6udxpRw+15e8ooqgNxBs7MgEiRcyvSpRUgblgq+q2hlWm+OMfEOQnaD
[中略]
aBy0ugEJVopg7y4OH7/L1BCCT5HVAYCc+q5+f1axqiMFOdR/hH7Pugit7sUZRUzM
8DaGSNElIlQOBh2nO2ZhREmSNEaA4YzoPHeyy7yaSRCWVbC0hvprhxNV1TpPmU+6
A4VJDQKBgD5zgz39ZNAhvvbGmNdO1VDmZ3J7XKspdbRAp4HtXMkqj2q+MYJj5N7g
SFJH1VSUVrDO7/fCMrRM65I08i0YVYdEbWgc267ylwqAeta+cy1bv0OyqyEb/bVt
HgpHJdlr+XfMXYM0Yzqapv5//VryY3w2Z5QC/RM84xVY427Q4fvr
-----END RSA PRIVATE KEY-----
[keycloak@idp ~]$
[keycloak@idp ~]$ openssl req -new -key private.pem -out apex.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) [XX]:.
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:.
Organization Name (eg, company) [Default Company Ltd]:.
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:apex
Email Address []:.
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[keycloak@idp ~]$
[keycloak@idp ~]$ openssl x509 -req -days 3650 -signkey private.pem -in apex.csr -sha256 -extfile v3.ext -out cert-apex.pem
Signature ok
subject=CN = apex
Getting Private key
[keycloak@idp ~]$
[keycloak@idp ~]$ tr -d '\n\r' < cert-apex.pem
-----BEGIN CERTIFICATE-----MIIC/DCCAeSgAwIBAgIUR3t1+jiW0qANoL0CO+vp6N6L/zkwDQYJKo
ZIhvcNAQELBQAwDzENMAsGA1UEAwwEYXBleDAeFw0yMjA2MTAwNzMzMjVaFw0zMjA2MDcwNzMzMjVaMA8
xDTALBgNVBAMMBGFwZXgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWTNAJxfRJEJ7XSJOn
eslhfyyOMCNDhFaYY39vTKtzY2BgTDJmxB8U9jsaMMKF+dd3Yn7ujbuHqrqzWRMvhF0SFOjGTwYH5LQ6s
y8vR/rIKpBt3E1xNBbnUuQLq53GlHD7Xl7yiiqA3EGzsyASJFzK9KlFSBuWCr6raGVab44x8Q5CdoOQpw************************************* 省略****************************************
E1xNBbnUuQLq53K2EYez8YCk9cmkm/H6/r6aFSteeRMr0/xYX0WjAeZHgDsKpB/LDzKyp9Kc3oAc0XqLY
Rz1x6YnAacpCSsryhfrXh7wlWlgNdDzQlnrO3VFg9fahs56aRSxuNmaJVpiowos+yt+yJJID9LvbxkN0Q
wiF3uwcBIsJAVmC3wbGl0ihKUdD5gmqObQKUa8bIR1rdcFhCdMoicsFFlP6Qu123ZXp+vrpnOXY1BK9--
---END CERTIFICATE-----[keycloak@idp ~]$
[keycloak@idp ~]$ kc.sh import --file $HOME/apex-realm.json
2022-06-10 07:52:59,350 INFO [org.keycloak.quarkus.runtime.hostname.DefaultHostnameProvider] (main) Hostname settings: FrontEnd: idp.apexugj.dev, Strict HTTPS: false, Path: <request>, Strict BackChannel: false, Admin: <request>, Port: -1, Proxied: false
2022-06-10 07:52:59,978 INFO [org.infinispan.server.core.transport.EPollAvailable] (keycloak-cache-init) ISPN005028: Native Epoll transport not available, using NIO instead: java.lang.UnsatisfiedLinkError: could not load a native library: netty_transport_native_epoll_aarch_64
2022-06-10 07:53:00,130 WARN [org.infinispan.CONFIG] (keycloak-cache-init) ISPN000569: Unable to persist Infinispan internal caches as no global state enabled
[中略]
2022-06-10 07:53:03,458 INFO [io.quarkus] (main) Profile import_export activated.
2022-06-10 07:53:03,458 INFO [io.quarkus] (main) Installed features: [agroal, cdi, hibernate-orm, jdbc-h2, jdbc-mariadb, jdbc-mssql, jdbc-mysql, jdbc-oracle, jdbc-postgresql, keycloak, narayana-jta, reactive-routes, resteasy, resteasy-jackson, smallrye-context-propagation, smallrye-health, smallrye-metrics, vault, vertx]
2022-06-10 07:53:03,604 INFO [io.quarkus] (main) Keycloak stopped in 0.142s
[keycloak@idp ~]$
クライアントの作成
https://test.mydomain.dev/ords/xepdb1/apex_authentication.saml_callback
Client Protocolとしてsamlを選択し、Saveを実行します。
openssl pkcs12 -in keystore.p12 -nodes
% openssl pkcs12 -in keystore.p12 -nodes
Enter Import Password: パスワードを入力する
MAC verified OK
Bag Attributes
localKeyID: 10 69 9B E0 32 C5 F7 AB C6 16 5C A7 83 B2 39 DC CF 6A 82 02
friendlyName: https://test.mydomain.dev/ords/xepdb1/apex_authentication.saml_callback
Key Attributes: <No Attributes>
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDJa+xnQa33FNKW
mHlGs+iF+1XCWbfzr0nmCHvcWg4L6NTF39B3UcgqXfSW6jtaxI09876MAkWyRzO6
wC4NUJTzMNenetJx0kC9GmFm/W02KpUuQjPyDAHBe+9UQx+yulq/K1E6Nv3MxyGG
[ BEGIN PRIVATE KEYからEND PRIVATE KEYまでをファイルpkey.pemに取り出す]
CJ2lJqVYxH61FXXzgSHOT6kmw11O4w59K2cVEkECgYBrt45iQaM4QUZXwJcMfqtR
onDJkN+YsxRo87Y61lHwVDXcNToHe7DtAaVs6C3P6FBxzR2/lfd9f9v7pMvo/P5B
1qD4dtndzPPBn55qLR/vNzShmrdDVmSd7ZduXZDAkcea3Jxao4IX8R0AfJtL3Ie6
pRxKu/Y5Ye/VYlotiIzXsQ==
-----END PRIVATE KEY-----
Bag Attributes
localKeyID: 10 69 9B E0 32 C5 F7 AB C6 16 5C A7 83 B2 39 DC CF 6A 82 02
friendlyName: https://test.apexugj.dev/ords/xepdb1/apex_authentication.saml_callback
subject=/CN=https://test.mydomain.dev/ords/xepdb1/apex_authentication.saml_callback
issuer=/CN=https://test.mydomain.dev/ords/xepdb1/apex_authentication.saml_callback
-----BEGIN CERTIFICATE-----
MIIDGzCCAgMCBgGBTLqtvzANBgkqhkiG9w0BAQsFADBRMU8wTQYDVQQDDEZodHRw
czovL3Rlc3QuYXBleHVnai5kZXYvb3Jkcy94ZXBkYjEvYXBleF9hdXRoZW50aWNh
dGlvbi5zYW1sX2NhbGxiYWNrMB4XDTIyMDYxMDA4MjY1MVoXDTMyMDYxMDA4Mjgz
MVowUTFPME0GA1UEAwxGaHR0cHM6Ly90ZXN0LmFwZXh1Z2ouZGV2L29yZHMveGVw
ZGIxL2FwZXhfYXV0aGVudGljYXRpb24uc2FtbF9jYWxsYmFjazCCASIwDQYJKoZI
[ これは置き換え対象の証明書なので不要 ]
Suai+a9htVNrUyFWWoNvu5SivLmOx+2d9SZNaZo43n6vAAcx9lEIN/XTlDyXsXb7
80YFHXNEze++wCwTvrscYdn5GEdhG5cUvTwPerB/gwxtiGZk7Y3YHpnfE1xK5/id
GdmIIo44D3p4HMqBwrv/x9E++bDBxPrGcBUdLAJ0v6ACr0VMEldt3MjNjxld22Mf
LorCSlFHUyL1aXk47VHjLJUaXj70JLxvktrtci31cQ==
-----END CERTIFICATE-----
Bag Attributes
friendlyName: apex
subject=/CN=apex
issuer=/CN=apex
-----BEGIN CERTIFICATE-----
MIIC/DCCAeSgAwIBAgIUR3t1+jiW0qANoL0CO+vp6N6L/zkwDQYJKoZIhvcNAQEL
BQAwDzENMAsGA1UEAwwEYXBleDAeFw0yMjA2MTAwNzMzMjVaFw0zMjA2MDcwNzMz
MjVaMA8xDTALBgNVBAMMBGFwZXgwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQDWTNAJxfRJEJ7XSJOneslhfyyOMCNDhFaYY39vTKtzY2BgTDJmxB8U9jsa
MMKF+dd3Yn7ujbuHqrqzWRMvhF0SFOjGTwYH5LQ6sy8vR/rIKpBt3E1xNBbnUuQL
[ レルムの公開鍵証明書 - cert-apex.pemとして取り出す。 ]
AkHmVpsBkfKFji9TWpFbfuOJuQtTCK2EYez8YCk9cmkm/H6/r6aFSteeRMr0/xYX
0WjAeZHgDsKpB/LDzKyp9Kc3oAc0XqLYRz1x6YnAacpCSsryhfrXh7wlWlgNdDzQ
lnrO3VFg9fahs56aRSxuNmaJVpiowos+yt+yJJID9LvbxkN0QwiF3uwcBIsJAVmC
3wbGl0ihKUdD5gmqObQKUa8bIR1rdcFhCdMoicsFFlP6Qu123ZXp+vrpnOXY1BK9
-----END CERTIFICATE-----
%
% openssl req -new -key private.pem -out test.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) []:
State or Province Name (full name) []:
Locality Name (eg, city) []:
Organization Name (eg, company) []:
Organizational Unit Name (eg, section) []:
Common Name (eg, fully qualified host name) []:test.mydomain.dev
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
ynakakoshi@NsM1MacBookPro k %
% openssl x509 -req -days 3650 -signkey private.pem -in test.csr -sha256 -extfile v3.ext -out cert-test.pem
Signature ok
subject=/CN=test.mydomain.dev
Getting Private key
%
% cat pkey.pem cert-test.pem cert-apex.pem > keystore.pem
% openssl pkcs12 -export -in keystore.pem -name test -caname apex -out import.p12
Enter Export Password:*********
Verifying - Enter Export Password:********
%
Keycloakの管理画面に戻り、Keysタブの画面よりImportを実行します。
Keycloakでの最低限の設定
APEXでのSAML認証スキームの設定
確認に使用するAPEXアプリケーションの作成
Oracle REST Data ServicesのCORS設定
ORDS 22.1以降では、以下のコマンドで設定します。ordsコマンドの位置や構成ディレクトリの位置は、それぞれのインストールによって変わります。
[oracle@apex ~]$ /usr/local/bin/ords --config /etc/ords/config config set security.externalSessionTrustedOrigins null
ORDS: Release 22.1 Production on Fri Jun 10 11:03:48 2022
Copyright (c) 2010, 2022, Oracle.
Configuration:
/etc/ords/config/
The global setting named: security.externalSessionTrustedOrigins was set to: null
[oracle@apex ~]$