2022年6月20日月曜日

ポップアップLOVの一覧にツールチップを表示する

 ポップアップLOVの一覧にポインタを当てたときに、ツールチップを表示させたい、という要件がありました。以下のような感じです。


以前の記事「モーダル・ダイアログに重ねてモーダル・ダイアログを開く」の3つ目の例として、ポップアップLOVの表示を変更する方法について紹介しています。これから説明する方法も、ポップアップLOVのrecordTemplateを使ってカスタマイズを行います。

以下より、実装方法を紹介します。Always FreeのAutonomous DatabaseのAPEX 21.2を使用します。

準備として、サンプル・データセットのEMP/DEPTをインストールしておきます。LOVのソースとして、EMP/DEPTに含まれるビューEMP_DEPT_Vを使用します。

アプリケーション作成ウィザードを起動し、ホーム・ページだけを含むアプリケーションを作成します。


ポップアップLOVのソースとなるLOVを作成します。

共有コンポーネントのLOVを開きます。


作成済みのLOVの一覧が表示されます。作成をクリックします。


LOVの作成として最初からを選択します。

次へ進みます。


LOVの名前をEMPLOVとします。タイプはDynamicを選択します。

次へ進みます。


データ・ソースとして、ローカル・データベースを選択します。ソース・タイプはTable、表/ビューの名前としてEMP_DEPT_V(ビュー)を選択します。

次へ進みます。


デフォルトで戻り値はEMPNO、表示列はENAMEになります。

変更せず、次へ進みます。


LOVとしてEMPLOVが作成されます。追加表示列の設定を行うため、リンクをクリックして編集します。


追加表示列の列の選択をクリックします。


追加表示列としてDNAMEとLOCを追加し(シャトルの左から右へ移動する)、更新をクリックします。


追加表示列への列DNAMEとLOCの追加を確認し、変更の適用をクリックします。


以上で、共有コンポーネントのLOVが作成できました。

ページ・デザイナでホーム・ページを開き、静的コンテンツのリージョンポップアップLOVを作成し、そのリージョンにページ・アイテムを作成します。

識別の名前をP1_EMPNO、タイプはポップアップLOV、ラベルは従業員とします。LOVのタイプに共有コンポーネントを選択し、LOVとしてEMPLOVを選択します。追加値の表示はOFF、NULL値の表示はONとします。


この状態でアプリケーションを実行すると、ポップアップLOVは以下のように表示されます。


ポップアップLOVにカスタマイズしたrecordTemplateを設定します。ページ・アイテムP1_EMPNOの詳細のJavaScript初期化コードに以下を記述します。

recordTemplateで使用している置換文字列が~EMPNO.といった形式になっています。これは、$EMPNO.記述すると、JavaScript初期化コード自体で置き換えられてしまうためです。recordTemplateには置換文字列として~EMPNO.を使い、recordTemplateに設定した後に、~から$へ文字を置き換えています。


recordTemplateを適用すると、この記事の先頭の画像のように、ポップアップLOVの一覧でツールチップが表示されます。

以上で実装は完了です。

今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/popup-lov-and-tooltip.sql

Oracle APEXのアプリケーション作成の産駒になれば幸いです。

参考にした記事
Popup LOV custom template by Louis Moreaux, Oct 18, 2021
All the Things That Pop Up by John Snyders, Dec 23, 2019

完

2022年6月17日金曜日

Oracle IDCSを使ってAPEXアプリをSAMLで認証する

 Oracle Identity Cloud Serviceを使って、Oracle APEXのアプリケーションをSAMLで認証させてみました。

最初に無料で利用できる範囲を確認します。IDCSのドキュメントの以下のセクションを参照します。

About Oracle Identity Cloud Service Pricing Models

無償の範疇について、以下のように説明されています。


日本語訳から抜粋します。

  • Oracle Identity Cloud Service Foundation: Oracleは、Oracle Software-as-a-Service (SaaS)、Oracle Platform-as-a-Service (PaaS)およびOracle Cloud Infrastructureのみをサブスクライブするお客様に、この無料バージョンのOracle Identity Cloud Serviceを提供します。

    顧客は、このバージョンを使用して、ユーザー管理、グループ管理、パスワード管理、基本的なレポートなどの基本的なアイデンティティ管理機能を提供できます。 次の表に示すように、追加機能にはOracle Identity Cloud Service Standardのサブスクリプションが必要です。

    サードパーティのSaaS、PaaS、カスタムWebまたはモバイル・アプリケーション、プログラムによるクライアントまたはオンプレミス・アプリケーションがOracle Cloud Infrastructureでホストされている場合でも、これらのアプリケーションとの統合にこのバージョンを使用することはできません。 これらのユースケースでは、Oracle Identity Cloud Service Standardが必要です。

Oracle APEXではPaaSのAutonomous Databaseを利用している場合でも、SAML認証を使うにはORDSを別立てし独自ドメインを割り当てる必要があります。そのため、どのようにサードパーティの環境とOracle Cloudの環境を見分けるのか、正直なところ分かりません。クライアントはブラウザですから、ネットワークとしてもOracle Cloudの外にあります。

技術的にどのような方法で範囲を限定するのか分かりませんが、ドキュメントの記述に依るとOracle CloudでOracle APEXを動かしている限り、Oracle Identity Cloud Service Foundationの範疇のようです。他のクラウドやオンプレミスで稼働しているOracle APEXの環境も(Oracle APEXはサードパーティの製品ではないため)、無償利用の範疇に入るようにも読めます。後者については、公式なパスを通して確認する必要があるかもしれません。

とりあえず、今回はOracle Cloudで稼働しているOracle APEXのインスタンスを使用するため、無償利用の範囲と判断して作業を行います。

アップグレードしていないFree Tierアカウントで、Oracle Identity Cloud Serivce側の作業を行います。

OCIコンソールよりアイデンティティとセキュリティのフェデレーションを開きます。

Oracle Cloudのアカウントを作成すると、アイデンティティ・プロバイダとしてOracleIdentityCloudServiceがあらかじめ作成されます。

このリンクをクリックして開きます。

Oracle Identity Cloud Service Consoleのリンクをクリックし、Oracle Identity Cloud Serviceのコンソールを開きます。


Identity Cloud Serviceのコンソールが開きます。


コンソールが英語で表示される場合は、ナビゲーション・メニューのSettingsのDefault Settingsを開き、LocaleのLanguage SettingをJapaneseに変更します。また、Timezone Settingも(UTC+09:00) Tokyo - Japan Time (JT)に変更します。

設定を変更後、Saveをクリックします。変更を反映させるために、サインインをし直します。


Oracle APEXの環境をアプリケーションとして登録します。

ナビゲーション・メニューのアプリケーションを開きます。

追加をクリックします。


ダイアログが開くので、SAMLアプリケーションを選択します。


SAMLアプリケーションの追加を行う画面が表示されます。名前は任意ですが、今回はapexとします。

それ以外はデフォルトのまま、次に進みます。


アプリケーションapexが非アクティブの状態で追加されます。その後に開く画面にて、SAMLに関する構成を行います。

一般のエンティティIDおよびアサーション・コンシューマのURLは、双方ともAPEX側のSAMLコールバックURLを指定します。

以下のような形式のURLです。apex_authentication.saml_callbackの部分は、どのインスタンスでも同じです。ベースとなるURLはOracle APEXが稼働している環境に合わせて変更します。

https://test.mydomain.dev/ords/xepdb1/apex_authentication.saml_callback
https://test.mydomain.dev/ords/apex_authentication.saml_callback


NameID形式とNameID値はそれぞれデフォルトの、電子メール・アドレス、プライマリ電子メールのままとします。ここで指定された値をOracle APEX側で読み取るために、内部およびワークスペース・アプリケーション用のSAML: APEX属性の名前IDフォーマットとして、以下を指定します。NameID形式やNameID値をデフォルトから変更した場合、APEX属性の名前IDフォーマットも変更が必要です。

urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress

Autonomous DatabaseでのSAMLの設定には、名前IDフォーマットの指定がないため、この指定は不要です。

opensslを使用して、アップロードする署名証明書を生成します。手順はOktaの記事で紹介しています。実行するコマンドだけを以下に列記します。
openssl genrsa -out private.pem 2048
openssl req -new -key private.pem -out test.csr
openssl x509 -req -days 3650 -signkey private.pem -in test.csr -sha256 -extfile v3.ext -out cert-test.pem
X.509バージョン3の拡張を指定するファイルv3.extの内容は以下になります。

keyUsage = digitalSignature,keyEncipherment

% openssl genrsa -out private.pem 2048

Generating RSA private key, 2048 bit long modulus

............................................+++

......................................+++

e is 65537 (0x10001)

% 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 []:

% openssl x509 -req -days 3650 -signkey private.pem -in test.csr -sha256 -extfile v3.ext -out cert-test.pem

Signature ok

subject=/CN=test.apexugj.dev

Getting Private key

%


上記の手順で生成されたcert-test.pemを、署名証明書として選択します。

続いて、署名証明書のダウンロードとアイデンティティ・プロバイダ・メタデータのダウンロードを実行します。先ほどアップロードした署名証明書はサービス・プロバイダ(APEX側)のもので、こちらの署名証明書はアイデンティティ・プロバイダのものになります。

署名署名書はIDCSCertificate.pem、アイデンティティ・プロバイダ・メタデータはIDCSMetadata.xmlとしてダウンロードされます。


詳細設定を開きます。

署名付きSSOとして、アサーションおよびレスポンスを選択します。署名に署名証明書を含めるはチェックします。署名ハッシュ・アルゴリズムはSHA-256です。

シングル・ログアウトの有効化をチェックします。

ログアウト・バインドにPOSTを選択します。シングル・ログアウトURL、ログアウト・レスポンスURL共に、APEXのSAMLコールバックURLを設定します。

アサーションの暗号化はチェックしません。


現時点では、シングル・サインアウトの正常な動作は確認できていません。

属性構成を開いて、アサーションに含めるユーザー情報を指定します。

属性の+をクリックしてユーザー情報を追加します。形式は基本、タイプはユーザー属性とします。

名前をgroupsとして、グループ・メンバーシップを送信します。条件はすべてのグループです。サインインしたユーザーが所属しているグループがアサーションに含まれます。グループ情報は、APEX側の認可処理に使用できます。firstNameとして名、lastNameとして姓の情報も含めます。


認証と認可
の権限付与を認可として実施は、デフォルトでチェックが入っているのでそのままにします。必要な設定なのか、確認はできていません。

以上の設定を行い、終了をクリックします。


SAMLによるSSO構成が行われます。

アプリケーションをアクティブ化します。確認のダイアログがポップアップするので、OKをクリックします。


このアプリケーションでサインインできるユーザーを割り当てます。今回はユーザーを割り当てる代わりに、グループを割り当てます。グループタブを開き、+割り当てをクリックします。


OCI_Administratorsにチェックを入れ、OKをクリックします。


グループとしてOCI_Administratorsが割り当たります。少なくとも、現在Oracle CloudにサインインしてIdentity Cloud Serviceの設定を行なっているユーザーは、このアプリケーションapexにサインインできるようになりました。

以上で、Oracle Identity Cloud Serviceの準備は完了です。

Oracle APEX側の設定を行います。

Oracle APEXの管理サービスにサインインし、SAMLの構成画面を開きます。(ナビゲーション・パスはインスタンスの管理>セキュリティ>認証制御>SAMLです。スクリーンショットはOktaの記事を参照してください。)

内部およびワークスペース・アプリケーション用のSAML: APEX属性のアプリケーションのSAML有効化をONにします。名前IDフォーマットはOracle Identity Cloud Serviceの設定に合わせて、以下を設定します。Autonomous Databaseにこの指定はありません。

urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress

証明書と秘密キーは、opensslを使って生成したものを貼り付けます。

内部およびワークスペース・アプリケーション用のSAML: アイデンティティ・プロバイダ属性を設定します。

発行者はIDCSMetadata.xmlよりentityIDを取り出して設定します。署名証明書はIdentity Cloud Serviceからダウンロードした証明書、IDCSCertificate.pemの内容を貼り付けます。サインインURLはXMLMetadata.xmlのSingleSignOnService要素のLocation属性の値を設定します。

<md:SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://idcs-********.identity.oraclecloud.com/fed/v1/idp/sso"/>


サインアウトURLとしてSingleLogoutService要素のLocation属性の値を設定します。(正常動作が確認できてから設定するのが望しいです。)

<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://idcs-***************.identity.oraclecloud.com/fed/v1/idp/slo"

 ResponseLocation="https://idcs-************.identity.oraclecloud.com/fed/v1/idp/slo"/>


Binding属性がHTTP-RedirectとHTTP-POSTのどちらでもLocationは同じようです。もし異なっている場合は、どちらか動く方を確認して選択します。

以上で変更の適用をします。


ORDSのCORS設定で、アクセスを許可するOriginはhttps://idcs-**********************.identity.oraclecloud.comでした。IDCSMetadata.xmlのentityIDやシングル・サインインURLのホスト部分になるので、それらの値から伏せ字の部分を補完してください。

ORDS 22.1では以下のコマンドを実行します。ordsコマンドのパスや構成ファイルの位置は、それぞれのインストールで異なります。

/usr/local/bin/ords --config /etc/ords/config config set security.externalSessionTrustedOrigins https://idcs-**********************.identity.oraclecloud.com

ORDS 21.xでは以下のコマンドを実行します。

java -jar ords.war set-property security.externalSessionTrustedOrigins https://idcs-**********************.identity.oraclecloud.com

変更を反映するには、ORDSの再起動が必要です。

以上でOracle APEX側の設定は完了です。

SAMLによるサインインを確認するために作成したアプリケーションにアクセスし、設定を確認します。

https://ホスト名/ords/PDB名/r/ワークスペース名/samltest/home

今回の例では、以下のURLにアクセスします。

https://test.mydomain.dev/ords/xepdb1/r/apexdev/samltest/home

Oracle Cloudのサインイン画面が表示されます。

ユーザー名とパスワードを入力し、サイン・インを実行します。


APEXアプリケーションの画面が開きます。

Oracle Identity Cloud ServiceのSAMLを構成するときに、属性構成としてアサーションに名前groupsとして、サインインしたユーザーが所属しているグループを渡すように設定しています。groupsという名称はOktaのときと同じ名前なので、こちらの記事で行ったダイナミック・グループの構成をそのままOracle Identity Cloud Serviceでも使用できます。

今回の作業では、ダイナミック・グループとしてOCI_Administratorsがサインインしたユーザーに割り当てられていることが確認できます。


シングル・サインアウトの動作を確認します。

アプリケーションからサインアウトすると、Oracle Cloudのサインイン画面に戻ります。


以下のようなエラーが発生する場合もあります。Autonomous Databaseでは、必ず発生します。

今回の検証作業はAlways Freeのインスタンスで行なっており、Customer Managed ORDSを使う要件であるプライベート・エンドポイントを使っていません。公式にはサポートされない構成での検証になります。


シングル・サインアウトが動いているAPEXのバージョンは22.1、Autonomous Databaseは21.2なので、その違いもあるかもしれません。近日中にADBも22.1へアップグレードされるので、その後に再度確認しようと思います。

すべての動作が確認できなかったのは残念ですが、以上で、Oracle Identity Cloud Serviceを使ってAPEXアプリをSAMLで認証するための作業は終了です。

完

Azure ADを使ってAPEXアプリをSAMLで認証する

  Azure ADを使って、Oracle APEXのアプリケーションをSAMLで認証させてみました。

Oracle APEX側の準備は、おおむねOktaを使ってSAML認証の設定を行ったときと同じです。そのため、Azure AD側での作業を主に記述します。

以下、作業手順になります。

https://portal.azure.comにアクセスし、ナビゲーション・メニューからAzure Active Directoryを開きます。


Microsoft EntraをTryしてみて、と通知が表示されているので、以降の作業はMicrosoft Entraで行ってみることにしました。


Microsoft Entra admin centerが開きます。

ナビゲーション・メニューのApplicationsのエンタープライズアプリケーションを開きます。

開いた画面で+新しいアプリケーションをクリックします。


Oracle APEXは事前に連携がされているアプリケーションではないため、+独自のアプリケーションの作成をクリックします。


右側にドロワーが開きます。お使いのアプリの名前は何ですか?という問い合わせにapexと入力します。Azure AD側ではアプリと言っていますが、Oracle APEXの場合は個々のアプリではなく、インスタンス全体をここでいうアプリとして登録します。そのため、ここではAPEXが動いているインスタンス名のような名前を指定することになるでしょう。

名前にapexと入力すると、エントリと一致する可能性がある次のアプリケーションが見つかりました、と候補が表示されます。選択できる候補は無いので、ギャラリーに見つからないその他のアプリケーションを統合します(ギャラリー以外)を選択します。

作成をクリックします。


エンタープライズアプリケーションとしてapexが作成されます。

SAMLの設定は、2。シングルサインオンの設定に含まれています。今回の作業は、この他に1。ユーザーとグループの割り当てだけです。

2。シングルサインオンの設定の作業の開始のリンクをクリックします。


シングルサインオン方式の選択として、SAMLを選択します。


SAMLによるシングルサインオンのセットアップとして、実施する手順が1から5まで順番に提示されます。

最初の基本的なSAML構成から実施します。編集をクリックします。

画面右にドロワーが開きます。

識別子(エンティティID)、応答URL(Assertion Consumer Service URL)、サインオンURL(省略可能)の3つすべてに、Oracle APEX側で定義されているSAMLコールバックURLを設定します。

以下のような形式のURLです。apex_authentication.saml_callbackの部分は、どのインスタンスでも同じです。ベースとなるURLはOracle APEXが稼働している環境に合わせて変更します。

https://test.mydomain.dev/ords/xepdb1/apex_authentication.saml_callback

https://test.mydomain.dev/ords/apex_authentication.saml_callback

以上の設定を保存します。

2の属性とクレームは、デフォルトのままにしておきます。

3のSAML署名証明書の編集をクリックします。

署名オプションをSAML応答とアサーションへの署名に変更します。署名アルゴリズムはSHA-256のまま変更しません。

以上の変更を実施し、保存します。


アクティブな証明書の操作メニューを開き、PEM証明書のダウンロードを実行します。アプリケーション名.pem、今回の例ではapex.pemというファイル名で、PEM形式の証明書がダウンロードされます。

以上の作業を行い、ドロワーを閉じます。

Azure AD側のSAMLの設定は以上になります。

これからOracle APEX側の設定を行います。

Azure ADの5のapexのセットアップ(apexの部分はアプリケーション名で、作業によって変わります)の記述を参照します。


Oracle APEXの管理サービスにサインインし、SAMLの構成画面を開きます。(ナビゲーション・パスはインスタンスの管理>セキュリティ>認証制御>SAMLです。スクリーンショットはOktaの記事を参照してください。)

内部およびワークスペース・アプリケーション用のSAML: APEX属性のアプリケーションのSAML有効化をONにします。証明書と秘密キーは、Oktaのときと同様にopensslを使って秘密キーと自己署名証明書を生成したものを貼り付けます。Oracle APEXの設定で必須なので指定しますが、SAML認証には使用されません。

内部およびワークスペース・アプリケーション用のSAML: アイデンティティ・プロバイダ属性を設定します。

発行者としてAzure AD識別子、署名証明書はAzure ADからダウンロードした証明書(今回であればapex.pemの内容)、サインインURLとしてログインURL、サインアウトURLとしてログアウトURLを設定します。

以上で変更の適用をします。


ORDSのCORS設定で、アクセスを許可するOriginはhttps://login.microsoftonline.comでした。

ORDS 22.1では以下のコマンドを実行します。ordsコマンドのパスや構成ファイルの位置は、それぞれのインストールで異なります。

/usr/local/bin/ords --config /etc/ords/config config set security.externalSessionTrustedOrigins https://login.microsoftonline.com

ORDS 21.xでは以下のコマンドを実行します。

java -jar ords.war set-property security.externalSessionTrustedOrigins https://login.microsoftonline.com

変更を反映するには、ORDSの再起動が必要です。

以上でOracle APEX側の設定は完了です。

Azure AD側で1。ユーザーとグループの割り当てを行います。


+ユーザーまたはグループの追加をクリックします。


ユーザーを選択します。現在Microsoft Entra admin centerを開いているユーザーは作成済みなので、そのユーザーを割り当てます。

選択されていませんのリンクをクリックします。


ENTERPRISE MOBILITY + SECURITY E5もしくはAZURE AD PREMIUM P2のサブスクリプションを購入するとグループの割り当てもできるとのことです。無料試用版も提供されています。今回の検証ではグループは使いません。

サインインを許可するユーザーをクリックして選択したアイテムに移動させた後、選択をクリックします。


選択したユーザーで、割り当てを実行します。


以上でAzure ADとOracle APEXの双方の設定は完了です。

SAMLによるサインインを確認するために作成したアプリケーションにアクセスし、設定を確認します。

https://ホスト名/ords/PDB名/r/ワークスペース名/samltest/home

今回の例では、以下のURLにアクセスします。

https://test.mydomain.dev/ords/xepdb1/r/apexdev/samltest/home

Microsoftのサインイン画面が表示されます。Microsoftとの契約状況(私はMIcrosoft 365の契約があります)やユーザーの設定状況によって、サインイン画面は違うのではないかと思います。


アカウントを選択すると、(私の場合は)通知の送信を行う画面が開きました。


Microsoft Authenticatorによる承認待ちになります。


サインインの状態を維持しますか?と確認されます。はいかいいえのどちらかを選択します。


APEXのアプリケーションの画面が開きます。APP_USERの値が非常に長くなっています。


この値は、Azure AD側の属性とクレームとして設定されている一意のユーザーIDになります。


APEXのアプリケーションのAPP_USERもシステムで一意でなければならない値なので、Azure AD側で一意性が保証されている値を設定する必要があります。

そのため、対応としてはAPP_USER自体を変更するのではなく、アプリケーション側でAPP_USERを表示に使用している部分を、人が見てわかる表示(姓名など)に変更します。

Azure ADのデフォルト設定では、SAML 2.0 Assertionに表示名(AttributeのName属性がhttp://schemas.microsoft.com/identity/claims/displayname)と電子メール・アドレス(AttributeのName属性がhttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress)が含まれています。これを認証スキームの認証後のプロシージャで取り出し、アプリケーション・アイテムG_DISPLAY_NAME、G_EMAILADDRESSに設定します。

共有コンポーネントのアプリケーション・アイテムとして、G_DISPLAY_NAME、G_EMAILADDRESSを作成します。


表示名と電子メール・アドレスの取り出しコードは、以下になります。

このPL/SQLコードを認証スキームSAMLサインインのソースのPL/SQLコードに記述し、ログイン・プロセスの認証後のプロシージャ名としてget_user_profilesを設定します。



ナビゲーション・バーの表示を変更するため、共有コンポーネントのナビゲーション・バー・リストを開きます。


ナビゲーション・バーを開きます。


名前が&APP_USER.となっているリスト・エントリの鉛筆アイコンをクリックします。編集画面が開きます。


リスト・エントリ・ラベルを&APP_USER.から&G_DISPLAY_NAME.に変更します。

変更の適用をクリックすると、ナビゲーション・メニューの変更は完了です。


ユーザー名が小文字のみで表示されないようにするには、同じページのユーザー定義属性のList Item CSS Classesとして設定されているhas-usernameを削除します。


以上の変更を行い、再度、SAML認証の確認アプリケーションにアクセスします。


以上で、Azure ADを使ってAPEXアプリをSAMLで認証するための作業は終了です。

サブスクリプションの関係で、Azure ADでは認証後のプロシージャにてダイナミック・グループの割り当ては行っていません。おそらくAzure ADでもAssertionにグループ情報が含まれることになるので、Oktaの処理とおおむね同じコードで対応できると思います。

完