Apple Mシリーズ上でコンテナ・イメージから作成した、ローカルのAPEX環境でORDS Database APIを有効にしてみました。その際の作業ログを残しておきます。
環境を作成した直後はワークスペースが作成されていません。APEXの管理サービスに接続し、ワークスペースを作成します。
管理者ユーザーとパスワードは@apxchpwdを実行したときに設定しています。管理者ユーザー名のデフォルトはADMINです。
ワークスペースが未作成であるため、Oracle APEXへようこその画面が開きます。ワークスペースの作成をクリックしても同じ作業になりますが、今回はワークスペースを2つ作る予定なのでワークペースの管理を開きます。
ワークスペースの管理画面が開きます。最初に既存のワースペースを確認し、その後にワークスペースの作成を実施します。
Oracle APEXをインストールするとINTERNALというワークスペースが作成されます。Oracle APEXの管理ツールや開発ツールは、このINTERNALワークスペースに作成されているAPEXアプリケーションになります。
ワークスペースの管理画面に戻り、ワークスペースの作成をクリックします。
ワークスペース名を指定します。今回は
apexdevとしています。
ワークスペースIDは開発環境を作成するときに指定します(
こちらの記事で説明しています)。今回は指定しません。
次へ進みます。
既存スキーマの再利用にいいえを選択し、ワークスペースに紐づくスキーマを新規作成します。スキーマ名はapexdevとします。領域割当て制限(MB)は10000を選択します。Oracle Database 23c Freeが持てるユーザー・データの上限が12GBなので、ほぼ上限いっぱいまでこのスキーマはデータが持てることになります。
スキーマのパスワードは必須項目なので設定しますが、APEXはこのパスワードを使いません。他のツールよりデータベースに接続する際に使用します。
次へ進みます。
ワークスペースの管理者のユーザー名と管理者のパスワードを設定します。電子メールも必須項目なので合わせて設定します。
Autonomous Databaseと異なりオンプレミスの環境では、管理者ユーザーや開発者ユーザーはデータベースのアカウントではなく、Oracle APEXで管理します。
次へ進みます。
確認画面が開きます。ワークスペースの作成を実行します。
ワークスペースが作成されました。完了します。
同じ作業を繰り返し、ワークスペースapexdev2を作成します。紐づけるスキーマはapexdev2として作成します。
既存のワークスペースを開き、INTERNAL、APEXDEV、APEXDEV2の3つのワークスペースが作成されていることを確認します。
作成したワークスペースAPEXDEV2(2の方です)にサインインし、検証に使用する設定を行ないます。
初回接続時は管理者のパスワードの変更を求められます。パスワードの変更を実施し、ワークスペースへサインインします。
ワークスペースに含まれるアプリケーション一覧を取得するORDS Database APIを呼び出したときに、結果が返されるようにアプリケーションを作成します。空のアプリケーションで十分です。
アプリケーション・ビルダーを開きます。
作成をクリックします。
作成するアプリケーションの名前は確認用アプリとします。
アプリケーションの作成をクリックします。
アプリケーションが作成されました。ワークスペースAPEXDEV2での作業は終了です。
これからワークスペースAPEXDEVを対象としてORDS Database APIを発行し、ワークスペースAPEXDEV2に作成されているアプリケーション一覧を取得するために必要な設定を行ないます。
ワークスペースAPEXDEV2からサインアウトし、ワークスペースAPEXDEVにサインインします。APEXDEV2のときと同様に、初回はパスワードの変更を求められます。
ワークスペースAPEXDEVに管理者ユーザーでサインインしました。SQLワークショップからRESTfulサービスを呼び出し、ワークスペースに紐づいているスキーマAPEXDEVをORDSに登録します(ORDSの用語ではREST有効化という作業になります)。
ORDSにスキーマを登録をクリックします。
ORDSスキーマ属性を保存します。RESTfulアクセスの有効化をオン、スキーマ別名はapexdev(通常ワークスペース名と同じ名前にします)、(RESTfulサービスの呼び出しの確認に使用するため)サンプル・サービスのインストールをオンにします。
スキーマ属性の保存をクリックします。
RESTfulサービスの画面が開きます。
左ペインよりサンプル・サービスとしてインストールされたモジュールoracle.example.hrのテンプレートversionのメソッドGETを選択します。
このメソッドの完全なURLを確認します。
http://localhost:8181/ords/apexdev/hr/version/
手元のPCからcurlコマンドを実行し、REST APIを呼び出してみます。
curl http://localhost:8181/ords/apexdev/hr/version/
レスポンスとして
{ "version": "23.1" } が返されます。
% curl http://localhost:8181/ords/apexdev/hr/version/
{"version": "23.1"}
%
作成したローカルの環境でREST APIを受け付けることが確認できました。
続いてSQLワークショップのSQLコマンドから、このREST APIを呼び出します。
Oracle APEXをインストールした直後は、ネットワークACLの設定がされていません。Oracle APEXはバージョンごとにスキーマを作成し、そのスキーマにデータベース・オブジェクトを作成します。Oracle APEX 23.2であれば、インストール先のスキーマはAPEX_230200になります。
以下のSELECT文によりスキーマAPEX_230200に設定されているネットワークACLを確認します。
select host, acl,
decode(dbms_network_acl_admin.check_privilege_aclid(aclid, 'APEX_230200','connect'), 1, 'GRANTED', 0, 'DENIED', NULL) privilege
from dba_network_acls;
PRIVILEGEがnullです。
(Oracle SQL Developer Extension for VS Codeの画面です)
以下のスクリプトを実行し、すべての宛先を対象としてconnectとresolveの権限を与えます。
begin
dbms_network_acl_admin.append_host_ace(
host => '*',
ace => xs$ace_type(
privilege_list => xs$name_list('connect','resolve'),
principal_name => 'APEX_230200',
principal_type => xs_acl.ptype_db
)
);
commit;
end;
/
先ほどのSELECT文を再実行し、PRIVILEGEの再確認を行ないます。connectについてPRIVILEGEがGRANTEDになっています。resolveの確認は割愛しますが、同様にGRANTEDになっています。
SQLワークショップのSQLコマンドより、REST APIであるversionを呼び出します。手元のPCからORDSのコンテナordsへはlocalhostで接続できますが、データベースのコンテナapexdbからはlocalhostではなく、ORDSのコンテナに割り当てられたIPアドレスを宛先とする必要があります。
コンテナordsに割り当てられたIPアドレスを確認します。
docker inspect --format='{{.NetworkSettings.IPAddress}}' ords
172.17.0.3と確認できました。
% docker inspect --format='{{.NetworkSettings.IPAddress}}' ords
172.17.0.3
ynakakoshi@Ns-MacBook ~ %
コンテナordsの起動時にIPアドレスが変わると面倒なので、コンテナapexdbと同様に、作成時に--ipオプションを指定して、あらかじめIPアドレスを割り当てておくとよいでしょう。
docker run -d --name ords --ip=172.17.0.3 -v `pwd`/ords_config/:/etc/ords/config/ -p 8181:8181 container-registry.oracle.com/database/ords:latest
SQLコマンドより以下のスクリプトを実行します。
declare
l_response clob;
begin
apex_web_service.clear_request_headers();
l_response := apex_web_service.make_rest_request(
p_url => 'http://172.17.0.3:8181/ords/apexdev/hr/version/'
,p_http_method => 'GET'
);
dbms_output.put_line(l_response);
end;
結果に{ "version": "23.1" }が印刷されます。
データベースからREST APIを呼び出せることが確認できました。
OAuthクライアントを作成します。SQL Developer Webに接続します。
詳細を開きパスにapexdev(ORDSスキーマ属性のスキーマ別名として保存した値です)を設定します。ユーザー名とパスワードは、APEXのワークスペースの管理者ユーザー(今回はadmin)とそのパスワードを入力します。
SQL Developer WebにスキーマAPEXDEVの権限でサインインします。
REST を開きます。
クライアントを開きます。
OAuthクライアントの作成をクリックします。
クライアント定義のタブを開きます。
付与タイプはCLIENT_CREDです。OAuthクライアントの名前はrestuser、説明は必須項目なのでRest Userとしました。サポート電子メールも必須項目です。
ロールのタブを開きます。
ロールとしてSQL DeveloperとRESTful Servicesを選択します。ORDS Database APIを呼び出しために必要なロールはSQL Developerだけです。RESTful Servicesはサンプルとしてインストールしたoracle.example.hrを使って、OAuthによる保護を確認するために割り当てます。
作成をクリックするとOAuthクライアントが作成されますが、その前にコードの表示をオンにしてみます。
ORDSの管理作業はPL/SQLのスクリプトを呼び出して実施することが一般的です。そのため、大体の画面操作で、同等の作業を行なうコードを確認できます。
OAuthクライアントを作成します。
OAuthクライアントが作成されました。
REST APIの認証にクライアントIDとクライアント・シークレットを使用するため、これらの値をコピーして安全に保存します。
これらの値を使って、Bearerトークンを取得してみます。
手元のPCより以下のトークンURLに対して、curlコマンドを実行してトークンをリクエストします。ワークスペースのベースURLに/oauth/tokenが続きます。
http://localhost:8181/ords/apexdev/oauth/token
curl http://localhost:8181/ords/apexdev/oauth/token \
-X POST \
-u <クライアントID>:<クライアント・シークレット> \
-d "grant_type=client_credentials"
レスポンスとしてaccess_tokenが返されます。
% curl http://localhost:8181/ords/apexdev/oauth/token \
-X POST \
-u <クライアントID>:<クライアント・シークレット> \
-d "grant_type=client_credentials"
{"access_token":"j2-PVvvomRNWPYclDLsmlw","token_type":"bearer","expires_in":3600}% ynakakoshi@Ns-MacBook ~ %
APEXのワークスペース
APEXDEVにサインインし、
ワークショップ・ユーティリティの
Web資格証明を開きます。OAuthクライアントの
クライアントIDと
クライアント・シークレットを
Web資格証明として保存します。
作成をクリックします。
作成するWeb資格証明の名前と静的IDをCRED_OAUTH_REST_USERとします。認証タイプにOAuth2クライアント資格証明フローを選択し、クライアントIDまたはユーザー名に先ほどコピーしたOAuthクライアントのクライアントID、クライアント・シークレットまたはパスワードにクライアント・シークレットを設定します。
以上でWeb資格証明を作成します。
Web資格証明CRED_OAUTH_REST_USERが作成されました。
Web資格証明が正しく作成されたかどうか確認するため、サンプルとして作成されたRESTfulサービスを保護します。
RESTfulサービスを開き、左ペインで権限を選択し権限の作成を実行します。
作成する権限の名前とタイトルをoracle.example.hrとします。ロールにRESTful Services、モジュールにoracle.example.hrを選択します。
以上の設定で権限の作成を実行します。
権限
oracle.example.hrが作成されます。
SQLコマンドよりREST APIのversionを呼び出すコードを実行します。実行するコードは同じです。
結果としてUnauthorizedが返されます。
APEX_WEB_SERVICE.MAKE_REST_REQUESTを呼び出す際の引数としてp_credential_static_idにCRED_OAUTH_REST_USER、p_token_urlにhttp://172.17.0.3:8181/ords/apexdev/oauth/tokenを追加します。
declare
l_response clob;
begin
apex_web_service.clear_request_headers();
l_response := apex_web_service.make_rest_request(
p_url => 'http://172.17.0.3:8181/ords/apexdev/hr/version/'
,p_http_method => 'GET'
,p_credential_static_id => 'CRED_OAUTH_REST_USER'
,p_token_url => 'http://172.17.0.3:8181/ords/apexdev/oauth/token'
);
dbms_output.put_line(l_response);
end;
今度は認証に成功し、レスポンスとして{"version": "23.1"}が返されます。
Web資格証明CRED_OAUTH_REST_USERが有効であることが確認できました。
これからORDS Database APIの呼び出しを行ないます。
ORDS Database APIはデフォルトでは有効になっていないため、最初にORDS Database APIを有効にします。通常は以下のコマンドでORDS Database APIを有効にします。
ords config set database.api.enabled true
今回の環境ではコンテナ
ordsで実行するため、以下のコマンドを実行します。
docker exec -it ords ords config set database.api.enabled true
% docker exec -it ords ords config set database.api.enabled true
2024-03-07T10:25:03Z INFO ORDS has not detected the option '--config' and this will be set up to the default directory.
ORDS: Release 23.4 Production on Thu Mar 07 10:25:14 2024
Copyright (c) 2010, 2024, Oracle.
Configuration:
/etc/ords/config/
No updates required to setting named database.api.enabled in global configuration because the values are the same.
%
ワークスペースAPEXDEV2に含まれるアプリケーションの一覧を取得してみます。以下のURLを呼び出します。
http://172.17.0.3:8181/ords/apexdev/_/db-api/stable/apex/workspaces/apexdev2/applications/
declare
l_response clob;
begin
apex_web_service.clear_request_headers();
l_response := apex_web_service.make_rest_request(
p_url => 'http://172.17.0.3:8181/ords/apexdev/_/db-api/stable/apex/workspaces/apexdev2/applications/'
,p_http_method => 'GET'
,p_credential_static_id => 'CRED_OAUTH_REST_USER'
,p_token_url => 'http://172.17.0.3:8181/ords/apexdev/oauth/token'
);
dbms_output.put_line(l_response);
end;
レスポンス自体は正常に受け取れますが、ワークスペースAPEXDEV2に作成されているはずのアプリケーション確認用アプリが返ってきません。
このORDS Database APIはスキーマAPEXDEVの権限で実行されています。異なるAPEXワークスペースの情報を参照するには、スキーマはAPEX_ADMINISTRATOR_ROLEを持つ必要があります。
スキーマAPEXDEVにロールAPEX_ADMINISTRATOR_ROLEを割り当てます。ユーザSYSによる接続から実行します。
grant APEX_ADMINISTRATOR_ROLE to apexdev;
再度、ORDS Database APIを呼び出します。今度は確認用アプリが返ってきました。
以上でローカル環境にインストールしたAPEXでORDS Database APIを有効にし、その呼び出しを確認することができました。
完