2023年5月20日土曜日

ORDSのコネクション・プールの監視

Oracle REST Data Servicesのコネクション・プールを監視する用途に、ORDS Instance APIを使用できます。ORDS Instance APIについて、以下の2件の記事が公開されています。

1件目はORDSを開発しているKris Riceさんによる記事です。
Monitoring ORDS Connection Pools
2件目はORDSのプロダクト・マネージャのPeter O'Brienさんによる記事です。
ORDS Pool Usage Chart with APEX

コネクション・プールの状態を表示するアプリケーションは、最初の記事では静的なHTMLにJavaScriptを記述したもの、後の記事ではAPEXアプリケーションを作成しています。

後の記事で作成しているAPEXアプリケーションについては、記事中で詳しく説明されています。また、アプリケーションのエクスポートも添付されています。

1件目の記事は書かれた時期がORDS 20.4の頃で、最新のORDSでは構成するためのコマンドも構成ファイルも大幅に変更されています。そのため、本記事ではORDS Instance APIを有効にする新しい手順を紹介します。また、静的なHTMLファイルをほぼそのままAPEXのアプリケーションに変える、という少し変わった実装も紹介します。

以下のように動作するアプリケーションを作成します。



事前作業



ORDS Instance APIを有効にする前に、DNSへのホスト名の登録およびCA(今回はLet's Encrypt)からサーバー証明書を取得する必要があります。ORDS Instance APIをHTTPで呼び出す場合はこれらの作業は不要ですが、HTTPSの場合はパブリック認証局によって署名されたサーバー証明書が必要です。

サーバー証明書を取得するにあたって、ORDSが稼働しているコンピュート・インスタンスのホスト名とパブリックIPアドレスをDNSに登録しておきます。登録手順はDNSのサービスに依存します。

hostコマンドを実行し、DNSに登録したパブリックIPアドレスが返されることを確認します。

host ホスト名

[root@apex2 ~]# host ホスト名

apex2.apexugj.dev has address 150.***.***.177

[root@apex2 ~]# 


Certbotを使って、Let's Encryptからサーバー証明書を取得します。Oracle Linux 8で使用できるCertbotは、EPELリポジトリに含まれています。EPELリポジトリを構成した上で、Certbotをインストールすることもできますが、今回はdnfコマンドにリポジトリを指定して、Certbotをインストールします。

dnf --repofrompath ol8_developer_EPEL,http://yum.oracle.com/repo/OracleLinux/OL8/developer/EPEL/x86_64 -y install certbot

[root@apex2 ~]# dnf --repofrompath ol8_developer_EPEL,http://yum.oracle.com/repo/OracleLinux/OL8/developer/EPEL/x86_64 -y install certbot

Failed to set locale, defaulting to C.UTF-8

Added ol8_developer_EPEL repo from http://yum.oracle.com/repo/OracleLinux/OL8/developer/EPEL/x86_64

ol8_developer_EPEL                               51 MB/s |  46 MB     00:00    

Last metadata expiration check: 0:00:11 ago on Sat May 20 16:50:29 2023.

Dependencies resolved.

================================================================================

 Package                   Arch   Version              Repository          Size

================================================================================

Installing:

 certbot                   noarch 1.22.0-1.el8         ol8_developer_EPEL  55 k

Installing dependencies:

 python3-acme              noarch 1.22.0-4.el8         ol8_developer_EPEL  97 k

 python3-certbot           noarch 1.22.0-1.el8         ol8_developer_EPEL 427 k

 python3-chardet           noarch 3.0.4-7.el8          ol8_baseos_latest  195 k

 python3-configargparse    noarch 0.14.0-6.el8         ol8_developer_EPEL  37 k

 python3-configobj         noarch 5.0.6-11.el8         ol8_baseos_latest   68 k

 python3-distro            noarch 1.4.0-2.module+el8.3.0+7694+550a8252

                                                       ol8_appstream       37 k


[中略]


  python3-urllib3-1.24.2-5.0.1.el8.noarch                                       

  python3-zope-component-4.3.0-8.el8.noarch                                     

  python3-zope-event-4.2.0-12.el8.noarch                                        

  python3-zope-interface-4.6.0-1.el8.x86_64                                     

  python36-3.6.8-38.module+el8.5.0+20329+5c5719bc.x86_64                        


Complete!

[root@apex2 ~]# 


certbotを実行すると、サーバー証明書の要求元を検証するために、HTTP-01チャレンジという操作が行われます。この処理は、TCP 80番ポートで通信します。

firewalldにて、TCP 80番ポートの通信を8080番ポートに転送する設定がされている場合、この設定を削除します。

firewall-cmd --remove-forward-port=port=80:proto=tcp:toport=8080
firewall-cmd --runtime-to-permanent
firewall-cmd --list-all

[root@apex2 ~]# firewall-cmd --remove-forward-port=port=80:proto=tcp:toport=8080 

success

[root@apex2 ~]# firewall-cmd --runtime-to-permanent

success

[root@apex2 ~]# firewall-cmd --list-all

public (active)

  target: default

  icmp-block-inversion: no

  interfaces: ens3

  sources: 

  services: cockpit dhcpv6-client http https ssh

  ports: 

  protocols: 

  forward: no

  masquerade: no

  forward-ports: 

port=443:proto=tcp:toport=8443:toaddr=

  source-ports: 

  icmp-blocks: 

  rich rules: 

[root@apex2 ~]# 


Certbotを実行してLet's Encryptからサーバー証明書を取得する準備ができました。

これからの作業は、以下の記事に沿って作業を行います。

Customer Managed ORDSの構成(2) - Let's Encryptを使ったSSL化
Let's Encryptからの証明書取得
ORDSの構成変更

作業の最後に、手元のPCからブラウザでAPEXに接続し、正しく設定されたことを確認します。

https://ホスト名/ords/apex_admin


ORDS Instance APIの有効化



ORDS Instance APIを有効にします。ORDS全体またはコネクション・プールごとに有効化できます。今回はORDS全体で有効にします。

ORDSのプロパティinstance.api.enabledtrueにします。

ORDSをインストールしたユーザーoracleで、ORDSの構成コマンドを実行します。

ords --config /etc/ords/config config set --global instance.api.enabled true

[oracle@apex2 ~]$ ords --config /etc/ords/config config set --global instance.api.enabled true


ORDS: Release 23.1 Production on Sat May 20 08:40:13 2023


Copyright (c) 2010, 2023, Oracle.


Configuration:

  /etc/ords/config/


The setting named: instance.api.enabled is not a recognized configuration setting. Run: ords config info to get a list of known configuration settings

The global setting named: instance.api.enabled was set to: true

[oracle@apex2 ~]$ 


instance.api.enabled is not a recognized configurationといったメッセージが出力されますが、instance.api.enabledの名前に間違いがなければ、無視できます。

ORDS Instance APIを呼び出すことのできるユーザーを作成します。

ユーザー名はsysadmin、ロールとしてSystem Administratorを与えます。

ords --config /etc/ords/config config user add sysadmin 'System Administrator'

コマンドの実行中にパスワードの入力を求められます。同じ文字列を2回、入力します。

[oracle@apex2 ~]$ ords --config /etc/ords/config config user add sysadmin 'System Administrator'


ORDS: Release 23.1 Production on Sat May 20 08:23:37 2023


Copyright (c) 2010, 2023, Oracle.


Configuration:

  /etc/ords/config/


Enter the password for sysadmin: ********

Confirm password: ********

Created user sysadmin in file /etc/ords/config/global/credentials

[oracle@apex2 ~]$ 


ORDSの設定変更およびユーザー追加を有効にするには、ORDSを再起動する必要があります。ユーザーrootに戻り、ORDSを再起動します。

exit
systemctl restart ords

[oracle@apex2 ~]$ exit

logout

[root@apex2 ~]# systemctl restart ords

[root@apex2 ~]# 


curlコマンドによる動作確認の例です。

curl --user sysadmin:パスワード https://ホスト名/ords/_/instance-api/stable/status

% curl --user sysadmin:********* https://ホスト名/ords/_/instance-api/stable/status 

{

  "invalid_pools_count" : 0,

  "valid_pools_count" : 1,

  "links" : [ {

    "rel" : "self",

    "href" : "https://***.*****.***/ords/_/instance-api/stable/status"

  }, {

    "rel" : "describedby",

    "href" : "https://***.*****.***/ords/_/instance-api/stable/metadata-catalog/"

  }, {

    "rel" : "related",

    "href" : "https://***.*****.***/ords/_/instance-api/stable/database-pools-cache/"

  } ]

}%                                                                              % 




アプリケーションPool Monitorの作成



アプリケーション作成ウィザードを起動し、空のアプリケーションを作成します。アプリケーションの名前Pool Monitorとします。


アプリケーションが作成されます。

アプリケーション定義置換を開き、ORDS Instance APIの呼び出しに使うホスト名、ユーザー名、パスワードをそれぞれG_HOSTG_USERNAMEG_PASSWORDとして設定します。


ページ・デザイナホーム・ページを開きます。

ページ・プロパティCSSファイルURLとして、以下を指定します。

https://cdn.jsdelivr.net/npm/hack-font@3/build/web/hack-subset.css


Kris Riceさんの記事にある<script>から</script>の間のコードを、JavaScriptファンクションおよびグローバル変数の宣言に記述します。コードには以下の変更を加えます。

ホスト名は&G_HOST.に置き換える。
ユーザー名は&G_USERNAME.に置き換える。
パスワードは&G_PASSWORD.に置き換える。
一番最後のpoolListing();は記述しない。


ページ・プロパティのJavaScriptページ・ロード時に実行に以下を記述します。

poolListing();


静的コンテンツのリージョンを作成し、<body>から</body>の間のHTMLをソースHTMLコードに転記します。

外観テンプレートとして、修飾のないBlank with Attributes (No Grid)を選択します。


以上でアプリケーションは完成です。

アプリケーションを実行すると、記事の先頭の動画のように動作します。

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

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

2023年5月19日金曜日

リージョン・タイプURLを使ってみる

 Oracle APEXで使用できるリージョンのタイプにURLというものがあります。これは外部のURLを参照して、リージョンの内容として表示するというものです。組入れモードとして、IFrameInline(no escaping)Inline(escape special characters)の3種類を選べます。

参照される側として、以下のアプリケーションを作成します。

サンプル・データセットEMP/DEPTに含まれる表EMPをソースとしたクラシック・レポートを画面左に配置し、表DEPTのクラシック・レポートを画面右に配置します。

参照される側のアプリケーションは、APEXアプリケーションではないことが一般的です。クリックジャッキングといった脆弱性の元になるため、APEXアプリケーションはデフォルトでiFrameへの埋め込みを禁止しています

アプリケーション名はSource Appとしています。アプリケーションのエクスポートは以下になります。
https://github.com/ujnak/apexapps/blob/master/exports/source-app.zip


このアプリケーション全体をiFrameに取り込むアプリケーションを作成します。

アプリケーション名はiFrame Appとしています。アプリケーションのエクスポートは以下になります。
https://github.com/ujnak/apexapps/blob/master/exports/iframe-app.zip



EMPのレポートとDEPTのレポートをそれぞれリージョンにInlineで読み込み、配置を変えて表示するアプリケーションを作成します。

アプリケーション名はInline Appとしています。アプリケーションのエクスポートは以下になります。
https://github.com/ujnak/apexapps/blob/master/exports/inline-app.zip


3つのアプリケーションともに、ホーム・ページのみに機能を実装しています。

参照される側のSource Appには、表EMPをソースとしたクラシック・レポートを作成しています。

Inlineでの組込みの範囲を指定するため、ヘッダーおよびフッターヘッダー・テキストとして<!-- start:report-emp -->フッター・テキストとして<!-- end:report-emp -->を設定しています。コメントであるため、画面には表示されません。


同様に表DEPTをソースとしたクラシック・レポートでは、ヘッダー・テキストとして<!-- start:report-dept -->フッター・テキストとして<!-- end:report-dept -->を設定しています。


アプリケーション定義セキュリティブラウザ・セキュリティセクションに含まれるフレームへの埋込みを、デフォルトの拒否から同じ起点から許可に変更します。これはX-Frame-Optionsヘッダーに指定する値です。

組込む方法が異なるため、この設定はInlineでの組込みに影響を与えません。


iFrame AppSource Appが同じワークスペースに作成されている場合、認証スキームセッション共有で同じCookie名に設定にしていると、iFrame AppSource Appでセッションを共有できます。つまり、iFrame AppSource Appを呼び出す際に、Source Appのログイン処理をスキップできます。


Source Appを埋め込むiFrame Appには、識別タイプURLであるリージョンだけが作成されています。


URLリージョンの高さは自動調整されないためテンプレート・オプションを使って、Body Heightとして640pxを設定しています。


プロパティ・エディタでリージョンの属性を開きます。

設定URLSource Appホーム・ページを指すURLを入力します。session=&APP_SESSION.としてセッションIDを渡すことによりセッションが引き継がれ、ログイン処理がスキップされます。

https://ホスト名/ords/r/apexdev/source-app/home?session=&APP_SESSION.

組入れモードIFrameIFrame属性としてwidth=100% height=100%を設定しています。


IFrame(インラインフレーム要素)そのものが実装されていると考えてよいでしょう。

Inline Appでは、URLリージョンの組入れモードInline (no escaping)にしています。

DEPTを表示するリージョンでは、設定HTML破棄の終了として<!-- start:report-dept -->(この文字列が現れるまでは、HTMLテキストを破棄する - つまりここからが表示を開始する)、HTML破棄の開始として<!-- end:report-dept -->(ここからのHTMLテキストは破棄する - つまりここで表示を終了する)を設定しています。


EMPを表示するリージョンのHTML破棄の終了<!-- start:report-emp -->HTML破棄の開始<!-- end:report-emp -->です。


組入れモードIFrameの場合は、設定されたURLはブラウザがアクセスします。Inlineの場合は、バックエンドのデータベースがアクセスします。これは動的コンテンツのリージョンで、以下のコードを実行しているのと同様です。


データベース・サーバーによってHTTPリクエストが発行されているため、ソースとなっているAPEXアプリケーションは認証なし(またはパブリック・ページ)になっている必要があります。

リージョン・タイプURLの紹介は以上になります。

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

Autonomous DatabaseのStripe Viewにアクセスする

 Autonomous Databaseでは、Stripeに登録された顧客や製品などを一覧するビューが提供されています。

https://docs.oracle.com/en/cloud/paas/autonomous-database/adbsa/stripe-autonomous-database.html

以前にStripeを使う記事を書いたことがありStripeのアカウントが作成済みだったため、動作を確認してみました。

Stripeには以下の2つの商品が登録されています。


商品を一覧するビューSTRIPE_PRODUCTSを、対話モード・レポートで表示してみました。Stripeに登録されている商品がリストされています。


以下より、実施した作業について紹介します。

Oracle APEXのワークスペース・スキーマはWKSP_APEXDEVとします。ワークスペース・スキーマが異なる場合は、使用しているワークスペース・スキーマの名前に置き換えてください。

マニュアルの手順に従って作業を行います。

最初にAPEXのワークスペース・スキーマにネットワークACLを追加して、Stripeへのアクセスを許可します。principal_nameにワークスペース・スキーマWKSP_APEXDEVを指定します。
BEGIN
  DBMS_NETWORK_ACL_ADMIN.APPEND_HOST_ACE(
         host => 'stripe.com',
         ace  => xs$ace_type(privilege_list => xs$name_list('http'),
                             principal_name => 'WKSP_APEXDEV',
                             principal_type => xs_acl.ptype_db)
   );
END;
/
管理者ユーザーADMINでデータベース・アクションに接続し、SQLワークシートより実行します。


今回の例ではビューSTRIPE_PRODUCTSにアクセスします。APEXのワークスペース・スキーマに、ビューSTRIPE_PRODUCTSへの読み込み権限を与えます。

GRANT READ on STRIPE_PRODUCTS to WKSP_APEXDEV;


Autonomous Databaseでは、STRIPE_ACCOUNTSSTRIPE_COUPONSSTRIPE_CUSTOMERSSTRIPE_INVOICESSTRIPE_PLANSSTRIPE_PRODUCTSSTRIPE_SUBSCRIPTIONSといったビューが提供されています。READ権限は、これらのビューそれぞれに付与する必要があります。

管理者ユーザーADMINでの作業は完了です。

アプリケーション作成ウィザードを起動し、空のアプリケーションを作成します。名前Stripe Productsとします。


アプリケーションが作成されたら、ページ・デザイナホーム・ページを開きます。

対話モード・レポートのリージョンを作成します。

ソースの表名として、STRIPE_PRODUCTSを設定します。


以上でアプケーションを実行します。

クリデンシャルにアクセスができない、といったエラーが発生します。

ORA-20004: Credential "ORDS_PLSQL_GATEWAY"."STRIPE$CRED" does not exist


マニュアルによると、credential_nameSTRIPE$CREDであれば、デフォルトのクリデンシャルとして使用されると記述されています。これは、管理者ユーザーADMINに限定されているようです。ワークスペース・スキーマのデフォルト・クリデンシャルの指定ではスキーマ名による修飾が必須です。

ワークスペース・スキーマWKSP_APEXDEVに、Stripeへのアクセスで使用するクリデンシャルMY_STRIPE_CREDを作成します。

引数usernameStripeのユーザ名(通常メールアドレス)、passwordには、シークレットキーを指定します。


BEGIN
    DBMS_CLOUD.CREATE_CREDENTIAL(
        credential_name => 'MY_STRIPE_CRED',
        username        => 'Stripeのユーザー名',
        password        => 'シークレットキー' );
END;
/

作成されたクリデンシャルを、ビューUSER_CREDENTIALSより確認します。

select * from user_credentials where credential_name = 'MY_STRIPE_CRED';


クリデンシャルMY_STRIPE_CREDを、APEXアプリケーションが参照するようにします。

アプリケーション定義セキュリティデータベース・セッション初期化PL/SQLコードに以下を記述します。
begin
    execute immediate 'alter session set default_credential = ''WKSP_APEXDEV.MY_STRIPE_CRED''';
end;


以上で記事の先頭にあるように、対話モード・レポートにStripeに登録されている商品が一覧されます。

簡単なアプリケーションですが、今回作成したアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/stripe-products.zip

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