前の記事で作成したAPEXアプリケーションに、シークレットの内容を操作する機能を付加します。
APEXのWeb資格証明をシークレットとして保存します。シークレットとして保存したWeb資格証明の確認や更新をできるようにします。
RESTデータ・ソースの作成
Vault Secret Retrieval APIを呼び出すRESTデータ・ソースを作成します。
作成済みのシークレットのIdを取得します。Vault Secret Retrieval APIを呼び出す際の引数として与えます。
対話モード・レポートの鉛筆アイコンに対して、リンクのアドレスをコピーを実行し、p3_idとして渡されている値をコピーします。
javascript:apex.theme42.dialog('\u002Fords\u002Fr\u002Fapexdev\u002Fmanage-secrets\u002Fsecrets?p3_id=ocid1.vaultsecret.oc1.iad.ama****************************************************************354w6q\u0026p3_compartment_id=ocid1.tenancy.oc1..
共有コンポーネントのRESTデータ・ソースを開き、作成を開始します。手順の最初の方は、Vault Secret ManagementのRESTデータ・ソースを作成したときと同じです。
ソース・タイプとしてOracle Cloud Infrastructure(OCI)を選択し、名前はVault Secret Retrievalとします。
URLエンドポイントとして、以下を指定します。https://secrets.vaults.us-ashburn-1.oci.oraclecloud.com/20190301/secretbundles/シークレットのOCID
次へ進みます。
リモート・サーバーとしてOCI Vault Secret Retrieval Endpoint(前の記事で作成済み)が選択されていることを確認します。
次へ進みます。
認証が必要ですをオンにし、資格証明としてOCI API Accessを選択します。
検出をクリックします。
RESTデータ・ソースの作成をクリックします。
RESTデータ・ソースVault Secret Retrievalが作成されます。
編集画面を開きます。
最初にURLパス接頭辞よりsecretbundles以降の直書きされたsecretIdを削除します。
変更の適用をクリックします。
以上の変更を行い、変更の適用をクリックします。
パラメータのタイプとしてURLパターンを選択し、名前はsecretIdとします。詳細の必須をオンにします。
操作の行のフェッチの編集画面を開きます。鉛筆アイコンをクリックします。
操作のURLパターンを/{secretId}とします。
パラメータの追加をクリックします。
パラメータの追加をクリックします。
変更の適用をクリックします。
再度、パラメータの追加を開き、パラメータのタイプとしてデータ・プロファイル列を選択します。
選択できるデータ・プロファイル列を追加します。ただし、実際に使用する列はCONTENTのみです。
以上でRESTデータ・ソースVault Secret Retrievalは出来上がりです。
変更の適用をクリックします。
操作のデータベース・アクションが行のフェッチのURLパターンに、/{secretId}が設定されていることを再度確認してください。
シークレットを操作するパッケージの作成
APEXのWeb資格証明を作る情報からOCI Vaultのシークレットとして保存するデータを生成したり、その逆を行うファンクションを実装したパッケージUTL_APEX_WEB_CREDENTIAL_MANAGERを作成します。取り出したシークレットを元にAPEXのWeb資格証明を作成するプロシージャも含みます。
PL/SQLのコードは記事の末尾に添付します。
コードの実行には、SQLワークショップのSQLスクリプトが使えます。
Web資格証明の扱いを追加
フォーム・リージョンのページ・アイテムP3_CONTENTは、ボールトに保存されるシークレットにそのまま対応しています。このシークレットにAPEXのWeb資格証明の情報を含めます。
ページ・アイテムP3_CONTENTを直接扱うことは無くなるため、タイプを非表示に変更します。
Web資格証明の情報を入力するページ・アイテムを作成します。
タイプは特に指定が無ければテキスト・フィールド、ラベルはページ・アイテム名からページ番号を外し、読みやすいように変えます。セッション・ステートのストレージはすべてリクエストごと(メモリーのみ)を設定します。
ページ・アイテムP3_CREDENTIAL_NAME、P3_CREDENTIAL_STATIC_ID、P3_AUTHENTICATION_TYPEを作成します。P3_AUTHENTICATION_TYPEのLOVのタイプに静的値を選択します。
追加値の表示はオフ、NULL値の表示はオン、NULL表示値として-- Select Authentication Type --を設定します。
LOVの静的値として、以下の設定を行います。
表示値としてBasic、HTTP Header、Query Parameter、OAuth2、OCI、Secret Dataを設定し、それらの戻り値としてBASIC、HTTP_HEADER、HTTP_QUERY_STRING、OAUTH2_CLIENT_CREDENTIALS、OCI、SECRET_DATAを設定します。
実行時にソートはオフにします。
選択したWeb資格証明ごとに入力可能なページ・アイテムの表示を切り替えるために、上記の選択肢に対応した静的コンテンツのリージョンを作成します。
リージョンのタイトルはLOVの表示値、外観のテンプレートはBlank with Attributesを選択します。静的IDとしてLOVの戻り値を設定します。
リージョンとしてBasic、HTTP Header、Query Parameter、OAuth2、OCI、Secret Dataを作成します。
リージョンHTTP Headerにページ・アイテムP3_HEADER_NAME、P3_HEADER_VALUEを作成します。
リージョンQuery Parameterにページ・アイテムP3_PARAMETER_NAME、P3_PARAMETER_VALUEを作成します。
リージョンOAuth2にページ・アイテムP3_CLIENT_ID、P3_CLIENT_SECRET、P3_SCOPEを作成します。
リージョンOCIにページ・アイテムP3_USER_ID、P3_PRIVATE_KEY、P3_TENANCY_ID、P3_FINGERPRINTを作成します。
リージョンSecret Dataにページ・アイテムP3_SECRET_DATAを作成します。
このうち、P3_PRIVATE_KEYとP3_SECRET_DATAのタイプはテキスト領域にします。
続けてP3_ALLOWED_URLS、P3_PROMPT_ON_INSTALL、P3_CREDENTIAL_COMMENTを作成します。P3_ALLOWED_URLSとP3_CREDENTIAL_COMMENTのタイプはテキスト領域、P3_PROMPT_ON_INSTALLのタイプは切替えとします。
ページ・アイテムP3_AUTHENTICATION_TYPEの選択により、表示するページ・アイテムを切り替えるためにP3_AUTHENTICATION_TYPEに動的アクションを作成します。
識別の名前はonChange show / hideとします。タイミングのイベントはページ・アイテムのデフォルトである変更です。
TRUEアクションとしてJavaScriptコードの実行を選択し、設定のコードに以下を記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 選択したリージョンのみを表示する。 | |
*/ | |
const v = $v(this.triggeringElement); | |
["BASIC","HTTP_HEADER","HTTP_QUERY_STRING","OAUTH2_CLIENT_CREDENTIALS","OCI","SECRET_DATA"].forEach( | |
(e) => { | |
if ( e == v ) { | |
$x_Show(document.getElementById(e)); | |
} | |
else | |
{ | |
$x_Hide(document.getElementById(e)); | |
} | |
} | |
); | |
/* | |
* APEXのWeb資格証明のパラメータは、SECRET_DATAのときは表示しない。 | |
*/ | |
if ( v == "SECRET_DATA" ) { | |
apex.items.P3_CREDENTIAL_NAME.hide(); | |
apex.items.P3_CREDENTIAL_STATIC_ID.hide(); | |
apex.items.P3_ALLOWED_URLS.hide(); | |
apex.items.P3_PROMPT_ON_INSTALL.hide(); | |
apex.items.P3_CREDENTIAL_COMMENT.hide(); | |
} | |
else | |
{ | |
apex.items.P3_CREDENTIAL_NAME.show(); | |
apex.items.P3_CREDENTIAL_STATIC_ID.show(); | |
apex.items.P3_ALLOWED_URLS.show(); | |
apex.items.P3_PROMPT_ON_INSTALL.show(); | |
apex.items.P3_CREDENTIAL_COMMENT.show(); | |
} |
初期化時に実行はオンにします。
ページ・アイテムP3_KEY_ID、P3_VAULT_ID、P3_COMPARTMENT_IDは、常にアプリケーション定義の置換文字列に設定した値にするので、これらはページ・アイテムとして非表示にします。
Vault Secret Retrieval APIを呼び出して、シークレットを取得します。
ヘッダーの前にプロセスを作成し、初期化フォームSecret Detailの下に配置します。
識別の名前はGet Secret、タイプはAPIの呼び出しを選択します。設定のタイプはRESTソース、RESTソースとしてVault Secret Retrieval、操作としてGET - /{secretId}を選択します。
サーバー側の条件のタイプとしてアイテムはNULLではないを選択し、アイテムとしてP3_IDを指定します。
パラメータCONTENTを選択し、パラメータの出力を無視をオフに変更します。値のアイテムとしてP3_CONTENTを指定します。
以上で、ページ・アイテムP3_IDの値をsecretIdとしてVault Secret Retrieval APIが呼び出され、CONTENTとして返されたシークレットの値がページ・アイテムP3_CONTENTに設定されます。
それ以外の出力パラメータは不要なので、出力を無視をオンのままにしておきます。
取得したシークレットからWeb資格証明の値を取り出します。
ヘッダーの前にプロセスを作成し、シークレットの取り出しの下に配置します。
識別の名前はExtract Credential From Secret、タイプはAPIの呼出しを選択します。設定のタイプはPL/SQLパッケージ、パッケージとしてUTL_APEX_WEB_CREDENTIAL_MANAGERを選択します。プロシージャまたはファンクションとしてEXTRACT_CREDENTIAL_FROM_SECRETを選択します。
サーバー側の条件のタイプとしてアイテムはNULLではない、アイテムとしてP3_CONTENTを指定します。P3_CONTENTにデータが設定されている場合に限り、その値よりWeb資格証明のデータを取り出します。
記述ミスなどもあり得るため、パラメータの設定は確認することを勧めます。
シークレットからWeb資格証明の値を取り出しが実装されました。反対にWeb資格証明の値よりシークレットを作成する処理を実装します。
プロセス・ビューを表示し、Web資格証明からシークレットを生成するプロセスを作成します。プロセスプロセス・フォームSecret Detailの上に配置します。
識別の名前はCreate Secret from Credential、タイプはAPIの呼出しを選択します。設定のタイプはPL/SQLパッケージ、パッケージとしてUTL_APEX_WEB_CREDENTIAL_MANAGERを選択します。プロシージャまたはファンクションとしてCREATE_SECRET_FROM_CREDENTIALを選択します。
サーバー側の条件のタイプとしてリクエストは値に含まれるを選択し、値にCREATE SAVEを指定します。ボタン作成または変更の適用を押したときに、このプロセスを実行します。
パラメータのファンクションの結果の値のアイテムにP3_CONTENTを指定します。
以上で、OCI VaultのシークレットとしてWeb資格証明を保存すること、およびシークレットからWeb資格証明のデータを取り出すことができるようになりました。
対話モード・レポートにシークレットをAPEXのWeb資格証明としてインストールするボタンを作成します。
対話モード・レポートのローカル後処理のタイプをSQL問合せに変更し、SQL問合せにインストールボタンとなる列INSTALLを追加します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
select ID, | |
KEY_ID, | |
VAULT_ID, | |
SECRET_NAME, | |
CREATED_BY, | |
CREATED_ON, | |
DESCRIPTION, | |
TIME_CREATED, | |
COMPARTMENT_ID, | |
LIFECYCLE_STATE, | |
ROTATION_CONFIG, | |
TIME_OF_DELETION, | |
LIFECYCLE_DETAILS, | |
IS_AUTO_GENERATION_ENABLED, | |
SECRET_GENERATION_CONTEXT, | |
TIME_OF_CURRENT_VERSION_EXPIRY, | |
'INSTALL' as INSTALL | |
from #APEX$SOURCE_DATA# | |
where KEY_ID = :G_KEY_ID | |
and VAULT_ID = :G_VAULT_ID | |
and COMPARTMENT_ID = :G_COMPARTMENT_ID |
追加された列INSTALLの列の書式のHTML式に以下を記述します。このボタンをクリックしたときに、列のID(その列のシークレットのOCID)を引数にしてAPEXアクションinstall-web-credentialを呼び出します。
<button type="button" class="t-Button" data-action="install-web-credential?secretId=#ID#">Install</button>
列KEY_ID、VAULT_IDおよびCOMPARTMENT_IDといったOCIDは、あまり表示したくないため、タイプを非表示に変更します。
シークレットのOCIDを引数にしてOCI Vaultよりシークレットを取り出し、取り出したシークレットからAPEXのWeb資格証明を作成するプロセスを、Ajaxコールバックとして作成します。
識別の名前はINSTALL_WEB_CREDENTIAL、タイプはコードの実行です。ソースのPL/SQLコードとして以下を記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
l_key_id varchar2(255); | |
l_params apex_exec.t_parameters; | |
l_secret varchar2(4000); | |
begin | |
apex_exec.add_parameter( l_params, 'secretId', apex_application.g_x01 ); | |
apex_exec.execute_rest_source( | |
p_static_id => 'vault_secret_retrieval', | |
p_operation => 'GET', | |
p_parameters => l_params ); | |
l_secret := apex_exec.get_parameter_varchar2( l_params, 'CONTENT'); | |
-- apex_debug.info('secret %s', l_secret); | |
utl_apex_web_credential_manager.create_credential_from_secret( | |
p_secret => l_secret | |
); | |
htp.p('{ "success": true }'); | |
exception | |
when others then | |
htp.p('{ "success": false }'); | |
end; |
ページ・プロパティのJavaScriptのページ・ロード時に実行に、APEXアクションのinstall-web-credentialを定義します。以下のコードを記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
apex.actions.add([ | |
{ | |
name: "install-web-credential", | |
action: function( event, element, args) { | |
/* 確認のためのダイアログを表示する */ | |
apex.message.confirm( | |
"Are you sure?", function( okPressed ) { | |
/* OCI VaultのシークレットからWeb資格証明を作成/更新する。 */ | |
apex.server.process( | |
"INSTALL_WEB_CREDENTIAL", | |
{ | |
x01: args.secretId | |
} | |
,{ | |
success: function( data ) { | |
if (data.success) { | |
/* 成功メッセージの表示 */ | |
apex.message.showPageSuccess( "Web Credential Created or Updated!" ); | |
} | |
else | |
{ | |
/* 失敗メッセージの表示 */ | |
apex.message.showErrors([ | |
{ | |
type: "error", | |
location: "page", | |
message: "Web Credential Creation or Update Failed!", | |
unsafe: false | |
} | |
]); | |
} | |
} | |
} | |
); | |
} | |
); | |
} | |
} | |
]); |
Web資格証明をAPEXアプリケーションから作成するには、アプリケーション定義のセキュリティの詳細にある、ランタイムAPIの使用状況に含まれるワークスペース・リポジトリを変更にチェックを入れる必要があります。
以上でアプリケーションは完成です。
動作の確認を行います。
対話モード・レポートのページから作成をクリックします。
以下ではSecret Name、Credential Name、Credential Static IdはTEST_CRED01、Description、Credential CommentはテストでWeb資格証明を保存する。、Authentication TypeはBasic、Usernameはscott、Passwordはtigerとしています。
作成をクリックすると、シークレットが作成されます。
レポートに作成したシークレットが表示されます。
作成したシークレットの鉛筆アイコンをクリックし、編集ダイアログを開きます。
Username、Passwordをぞれぞれscott4、tiger4に変更し、変更の適用をクリックします。
Installを実行します。
Web資格証明の作成または更新が成功すると、成功メッセージが表示されます。
以上で、作成したAPEXアプリケーションの動作確認ができました。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/manage-secrets.zip
次の記事で最後になりますが、RESTデータ・ソースを扱うアプリケーションを作成するにあたって、考慮すべき点について説明します。
続く
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
create or replace package utl_apex_web_credential_manager | |
as | |
/** | |
* APEXのWeb資格証明に必要なデータを、OCI Vaultのシークレットに保存できる | |
* Base64エンコーディングされたJSONの文字列として返す。 | |
*/ | |
function create_secret_from_credential( | |
p_authentication_type in varchar2 | |
,p_credential_static_id in varchar2 | |
,p_credential_name in varchar2 | |
,p_allowed_urls in varchar2 | |
,p_prompt_on_install in boolean | |
,p_credential_comment in varchar2 | |
/* Basic */ | |
,p_username in varchar2 | |
,p_password in varchar2 | |
/* HTTP Header */ | |
,p_header_name in varchar2 | |
,p_header_value in varchar2 | |
/* Query Parameter */ | |
,p_parameter_name in varchar2 | |
,p_parameter_value in varchar2 | |
/* OAuth2 */ | |
,p_client_id in varchar2 | |
,p_client_secret in varchar2 | |
,p_scope in varchar2 | |
/* OCI */ | |
,p_user_id in varchar2 | |
,p_private_key in varchar2 | |
,p_tenancy_id in varchar2 | |
,p_fingerprint in varchar2 | |
/* Secret Data */ | |
,p_secret_data in varchar2 | |
) return clob; | |
/** | |
* シークレットとして保存されていたBase64でエンコードされたJSONドキュメントより、 | |
* Web資格証明の作成に必要なデータを取り出す。 | |
*/ | |
procedure extract_credential_from_secret( | |
p_secret in clob | |
,p_credential_name out varchar2 | |
,p_credential_static_id out varchar2 | |
,p_authentication_type out varchar2 | |
,p_allowed_urls out varchar2 | |
,p_prompt_on_install out boolean | |
,p_credential_comment out varchar2 | |
/* Basic */ | |
,p_username out varchar2 | |
,p_password out varchar2 | |
/* HTTP Header */ | |
,p_header_name out varchar2 | |
,p_header_value out varchar2 | |
/* Query Parameter */ | |
,p_parameter_name out varchar2 | |
,p_parameter_value out varchar2 | |
/* OAuth2 */ | |
,p_client_id out varchar2 | |
,p_client_secret out varchar2 | |
,p_scope out varchar2 | |
/* OCI */ | |
,p_user_id out varchar2 | |
,p_private_key out varchar2 | |
,p_tenancy_id out varchar2 | |
,p_fingerprint out varchar2 | |
/* Raw Secret Data */ | |
,p_secret_data out varchar2 | |
); | |
/** | |
* OCI Vaultのシークレットとして保存した文字列より、APEXのWeb資格証明を作成する。 | |
* | |
* APEX_CREDENTIAL.CREATE_CREDENTIALの呼び出し時に与える | |
* p_credential_name, p_credential_static_id, その他の引数の値を | |
* 設定できるのは、Web資格証明の作成時に限られる。そのため、これらの値を変更するには | |
* Web資格証明を作り直す必要がある。 | |
* | |
* OCI Vaultのシークレットとして保存しているalllowed URLs、prompt on installや | |
* credential commentといった値はシークレットとしては変更できるが、その値を変更して | |
* APEX側に保存されている既存のWeb資格証明をアップデートしても、更新されるのは | |
* set_persistent_credentialで更新可能な値に限られる。 | |
*/ | |
procedure create_credential_from_secret( | |
p_secret in clob | |
,p_force_update in boolean default false | |
,p_workspace in varchar2 default null | |
); | |
end utl_apex_web_credential_manager; | |
/ | |
create or replace package body utl_apex_web_credential_manager | |
as | |
/** | |
* Web資格証明に共通しているパラメータを、シークレットになるJSONに書き込む。 | |
* | |
* APEX_CREDENTIAL.CREATE_CREDENTIALの引数に準ずる。 | |
* Ref: https://docs.oracle.com/en/database/oracle/apex/23.2/aeapi/CREATE_CREDENTIAL-Procedure.html | |
*/ | |
procedure set_common_attributes( | |
p_credential in out json_object_t | |
,p_credential_static_id in varchar2 | |
,p_credential_name in varchar2 default null /* static_id if null */ | |
,p_authentication_type in varchar2 | |
,p_scope in varchar2 default null | |
,p_allowed_urls in varchar2 default null | |
,p_prompt_on_install in boolean default false | |
,p_credential_comment in varchar2 default null | |
) | |
as | |
begin | |
/* p_credentialの指定がなければ、オブジェクトを生成する。 */ | |
if p_credential is null then | |
p_credential := json_object_t(); | |
end if; | |
/* credential nameの指定がなければ静的IDを名前にする。 */ | |
if p_credential_name is not null then | |
p_credential.put('credential_name', p_credential_name); | |
else | |
p_credential.put('credential_name', p_credential_static_id); | |
end if; | |
/* 必須パラメータ */ | |
p_credential.put('credential_static_id', p_credential_static_id); | |
p_credential.put('authentication_type', p_authentication_type); | |
/* 任意パラメータ */ | |
if p_scope is not null then | |
p_credential.put('scope', p_scope); | |
end if; | |
if p_allowed_urls is not null then | |
p_credential.put('allowed_urls', p_allowed_urls); | |
end if; | |
if p_prompt_on_install is not null then | |
p_credential.put('prompt_on_install', p_prompt_on_install); | |
end if; | |
if p_credential_comment is not null then | |
p_credential.put('credential_comment', p_credential_comment); | |
end if; | |
end set_common_attributes; | |
/** | |
* 基本認証よりシークレットを生成する。 | |
*/ | |
function create_secret_from_basic_cred( | |
p_credential_static_id in varchar2 | |
,p_credential_name in varchar2 default null | |
,p_username in varchar2 | |
,p_password in varchar2 | |
,p_allowed_urls in varchar2 default null | |
,p_prompt_on_install in boolean default false | |
,p_credential_comment in varchar2 default null | |
) return clob | |
as | |
l_credential json_object_t := json_object_t(); | |
begin | |
set_common_attributes( | |
p_credential => l_credential | |
,p_credential_name => p_credential_name | |
,p_credential_static_id => p_credential_static_id | |
,p_authentication_type => apex_credential.C_TYPE_BASIC | |
,p_allowed_urls => p_allowed_urls | |
,p_prompt_on_install => p_prompt_on_install | |
,p_credential_comment => p_credential_comment | |
); | |
l_credential.put('username', p_username); | |
l_credential.put('password', p_password); | |
return apex_web_service.blob2clobbase64(l_credential.to_blob()); | |
end create_secret_from_basic_cred; | |
/** | |
* HTTPヘッダーよりシークレットを生成する。 | |
*/ | |
function create_secret_from_http_header_cred( | |
p_credential_static_id in varchar2 | |
,p_credential_name in varchar2 default null | |
,p_header_name in varchar2 | |
,p_header_value in varchar2 | |
,p_allowed_urls in varchar2 default null | |
,p_prompt_on_install in boolean default false | |
,p_credential_comment in varchar2 default null | |
) return clob | |
as | |
l_credential json_object_t := json_object_t(); | |
begin | |
set_common_attributes( | |
p_credential => l_credential | |
,p_credential_name => p_credential_name | |
,p_credential_static_id => p_credential_static_id | |
,p_authentication_type => apex_credential.C_TYPE_HTTP_HEADER | |
,p_allowed_urls => p_allowed_urls | |
,p_prompt_on_install => p_prompt_on_install | |
,p_credential_comment => p_credential_comment | |
); | |
l_credential.put('header_name', p_header_name); | |
l_credential.put('header_value', p_header_value); | |
return apex_web_service.blob2clobbase64(l_credential.to_blob()); | |
end create_secret_from_http_header_cred; | |
/** | |
* 問合せパラメータよりシークレットを生成する。 | |
*/ | |
function create_secret_from_query_parameter_cred( | |
p_credential_static_id in varchar2 | |
,p_credential_name in varchar2 default null | |
,p_parameter_name in varchar2 | |
,p_parameter_value in varchar2 | |
,p_allowed_urls in varchar2 default null | |
,p_prompt_on_install in boolean default false | |
,p_credential_comment in varchar2 default null | |
) return clob | |
as | |
l_credential json_object_t := json_object_t(); | |
begin | |
set_common_attributes( | |
p_credential => l_credential | |
,p_credential_name => p_credential_name | |
,p_credential_static_id => p_credential_static_id | |
,p_authentication_type => apex_credential.C_TYPE_HTTP_QUERY_STRING | |
,p_allowed_urls => p_allowed_urls | |
,p_prompt_on_install => p_prompt_on_install | |
,p_credential_comment => p_credential_comment | |
); | |
l_credential.put('parameter_name', p_parameter_name); | |
l_credential.put('parameter_value', p_parameter_value); | |
return apex_web_service.blob2clobbase64(l_credential.to_blob()); | |
end create_secret_from_query_parameter_cred; | |
/** | |
* OAuth2よりシークレットを生成する。 | |
*/ | |
function create_secret_from_oauth2_cred( | |
p_credential_static_id in varchar2 | |
,p_credential_name in varchar2 default null | |
,p_client_id in varchar2 | |
,p_client_secret in varchar2 | |
,p_scope in varchar2 default null | |
,p_allowed_urls in varchar2 default null | |
,p_prompt_on_install in boolean default false | |
,p_credential_comment in varchar2 default null | |
) return clob | |
as | |
l_credential json_object_t := json_object_t(); | |
begin | |
set_common_attributes( | |
p_credential => l_credential | |
,p_credential_name => p_credential_name | |
,p_credential_static_id => p_credential_static_id | |
,p_authentication_type => apex_credential.C_TYPE_HTTP_QUERY_STRING | |
,p_scope => p_scope | |
,p_allowed_urls => p_allowed_urls | |
,p_prompt_on_install => p_prompt_on_install | |
,p_credential_comment => p_credential_comment | |
); | |
l_credential.put('client_id', p_client_id); | |
l_credential.put('client_secret', p_client_secret); | |
return apex_web_service.blob2clobbase64(l_credential.to_blob()); | |
end create_secret_from_oauth2_cred; | |
/** | |
* OCIよりシークレットを生成する。 | |
*/ | |
function create_secret_from_oci_cred( | |
p_credential_static_id in varchar2 | |
,p_credential_name in varchar2 default null | |
,p_user_id in varchar2 | |
,p_private_key in varchar2 | |
,p_tenancy_id in varchar2 | |
,p_fingerprint in varchar2 | |
,p_allowed_urls in varchar2 default null | |
,p_prompt_on_install in boolean default false | |
,p_credential_comment in varchar2 default null | |
) return clob | |
as | |
l_credential json_object_t := json_object_t(); | |
begin | |
set_common_attributes( | |
p_credential => l_credential | |
,p_credential_name => p_credential_name | |
,p_credential_static_id => p_credential_static_id | |
,p_authentication_type => apex_credential.C_TYPE_HTTP_QUERY_STRING | |
,p_allowed_urls => p_allowed_urls | |
,p_prompt_on_install => p_prompt_on_install | |
,p_credential_comment => p_credential_comment | |
); | |
l_credential.put('user_id', p_user_id); | |
l_credential.put('private_key', p_private_key); | |
l_credential.put('tenancy_id', p_tenancy_id); | |
l_credential.put('finterprint', p_fingerprint); | |
return apex_web_service.blob2clobbase64(l_credential.to_blob()); | |
end create_secret_from_oci_cred; | |
/** | |
* 生のシークレットであるデータよりシークレットを生成する。 | |
* これはAPEXのWeb資格証明にはならない。 | |
*/ | |
function create_secret_from_secret_data( | |
p_secret_data in varchar2 | |
) return clob | |
as | |
l_credential json_object_t := json_object_t(); | |
begin | |
l_credential.put('credential_type', 'SECRET_DATA'); | |
l_credential.put('secret_data', p_secret_data); | |
return apex_web_service.blob2clobbase64(l_credential.to_blob()); | |
end create_secret_from_secret_data; | |
/** | |
* APEXのWeb資格証明に必要なデータを、OCI Vaultのシークレットに保存できる | |
* Base64エンコーディングされたJSONの文字列として返す。 | |
*/ | |
function create_secret_from_credential( | |
p_authentication_type in varchar2 | |
,p_credential_static_id in varchar2 | |
,p_credential_name in varchar2 | |
,p_allowed_urls in varchar2 | |
,p_prompt_on_install in boolean | |
,p_credential_comment in varchar2 | |
/* Basic */ | |
,p_username in varchar2 | |
,p_password in varchar2 | |
/* HTTP Header */ | |
,p_header_name in varchar2 | |
,p_header_value in varchar2 | |
/* Query Parameter */ | |
,p_parameter_name in varchar2 | |
,p_parameter_value in varchar2 | |
/* OAuth2 */ | |
,p_client_id in varchar2 | |
,p_client_secret in varchar2 | |
,p_scope in varchar2 | |
/* OCI */ | |
,p_user_id in varchar2 | |
,p_private_key in varchar2 | |
,p_tenancy_id in varchar2 | |
,p_fingerprint in varchar2 | |
/* Secret Data */ | |
,p_secret_data in varchar2 | |
) return clob | |
as | |
l_secret clob; | |
e_invalid_authentication_type exception; | |
begin | |
if p_authentication_type = apex_credential.C_TYPE_BASIC then | |
l_secret := utl_apex_web_credential_manager.create_secret_from_basic_cred( | |
p_credential_static_id => p_credential_static_id | |
,p_credential_name => p_credential_name | |
,p_username => p_username | |
,p_password => p_password | |
,p_allowed_urls => p_allowed_urls | |
,p_prompt_on_install => p_prompt_on_install | |
,p_credential_comment => p_credential_comment | |
); | |
elsif p_authentication_type = apex_credential.C_TYPE_HTTP_HEADER then | |
l_secret := utl_apex_web_credential_manager.create_secret_from_http_header_cred( | |
p_credential_static_id => p_credential_static_id | |
,p_credential_name => p_credential_name | |
,p_header_name => p_header_name | |
,p_header_value => p_header_value | |
,p_allowed_urls => p_allowed_urls | |
,p_prompt_on_install => p_prompt_on_install | |
,p_credential_comment => p_credential_comment | |
); | |
elsif p_authentication_type = apex_credential.C_TYPE_HTTP_QUERY_STRING then | |
l_secret := utl_apex_web_credential_manager.create_secret_from_query_parameter_cred( | |
p_credential_static_id => p_credential_static_id | |
,p_credential_name => p_credential_name | |
,p_parameter_name => p_parameter_name | |
,p_parameter_value => p_parameter_value | |
,p_allowed_urls => p_allowed_urls | |
,p_prompt_on_install => p_prompt_on_install | |
,p_credential_comment => p_credential_comment | |
); | |
elsif p_authentication_type = apex_credential.C_TYPE_OAUTH_CLIENT_CRED then | |
l_secret := utl_apex_web_credential_manager.create_secret_from_oauth2_cred( | |
p_credential_static_id => p_credential_static_id | |
,p_credential_name => p_credential_name | |
,p_client_id => p_client_id | |
,p_client_secret => p_client_secret | |
,p_scope => p_scope | |
,p_allowed_urls => p_allowed_urls | |
,p_prompt_on_install => p_prompt_on_install | |
,p_credential_comment => p_credential_comment | |
); | |
elsif p_authentication_type = apex_credential.C_TYPE_OCI then | |
l_secret := utl_apex_web_credential_manager.create_secret_from_oci_cred( | |
p_credential_static_id => p_credential_static_id | |
,p_credential_name => p_credential_name | |
,p_user_id => p_user_id | |
,p_private_key => p_private_key | |
,p_tenancy_id => p_tenancy_id | |
,p_fingerprint => p_fingerprint | |
,p_allowed_urls => p_allowed_urls | |
,p_prompt_on_install => p_prompt_on_install | |
,p_credential_comment => p_credential_comment | |
); | |
elsif p_authentication_type = 'SECRET_DATA' then | |
l_secret := utl_apex_web_credential_manager.create_secret_from_secret_data( | |
p_secret_data => p_secret_data | |
); | |
else | |
raise e_invalid_authentication_type; | |
end if; | |
return l_secret; | |
end create_secret_from_credential; | |
/** | |
* シークレットとして保存されていたBase64でエンコードされたJSONドキュメントより、 | |
* Web資格証明の作成に必要なデータを取り出す。 | |
*/ | |
procedure extract_credential_from_secret( | |
p_secret in clob | |
,p_credential_name out varchar2 | |
,p_credential_static_id out varchar2 | |
,p_authentication_type out varchar2 | |
,p_allowed_urls out varchar2 | |
,p_prompt_on_install out boolean | |
,p_credential_comment out varchar2 | |
/* Basic */ | |
,p_username out varchar2 | |
,p_password out varchar2 | |
/* HTTP Header */ | |
,p_header_name out varchar2 | |
,p_header_value out varchar2 | |
/* Query Parameter */ | |
,p_parameter_name out varchar2 | |
,p_parameter_value out varchar2 | |
/* OAuth2 */ | |
,p_client_id out varchar2 | |
,p_client_secret out varchar2 | |
,p_scope out varchar2 | |
/* OCI */ | |
,p_user_id out varchar2 | |
,p_private_key out varchar2 | |
,p_tenancy_id out varchar2 | |
,p_fingerprint out varchar2 | |
/* Raw - Secret Data */ | |
,p_secret_data out varchar2 | |
) | |
as | |
l_blob blob; | |
l_credential json_object_t; | |
begin | |
l_blob := apex_web_service.clobbase642blob( | |
p_clob => p_secret | |
); | |
l_credential := json_object_t.parse(l_blob); | |
/* 共通の属性を取り出す。 */ | |
p_credential_name := l_credential.get_string('credential_name'); | |
p_credential_static_id := l_credential.get_string('credential_static_id'); | |
p_authentication_type := l_credential.get_string('authentication_type'); | |
p_allowed_urls := l_credential.get_string('allowed_urls'); | |
p_prompt_on_install := l_credential.get_boolean('prompt_on_install'); | |
p_credential_comment := l_credential.get_string('credential_comment'); | |
case p_authentication_type | |
when apex_credential.C_TYPE_BASIC then | |
p_username := l_credential.get_string('username'); | |
p_password := l_credential.get_string('password'); | |
when apex_credential.C_TYPE_HTTP_HEADER then | |
p_header_name := l_credential.get_string('header_name'); | |
p_header_value := l_credential.get_string('header_value'); | |
when apex_credential.C_TYPE_HTTP_QUERY_STRING then | |
p_parameter_name := l_credential.get_string('parameter_name'); | |
p_parameter_value := l_credential.get_string('parameter_value'); | |
when apex_credential.C_TYPE_OAUTH_CLIENT_CRED then | |
p_client_id := l_credential.get_string('client_id'); | |
p_client_secret := l_credential.get_string('client_secret'); | |
p_scope := l_credential.get_string('scope'); | |
when apex_credential.C_TYPE_OCI then | |
p_user_id := l_credential.get_string('user_id'); | |
p_private_key := l_credential.get_string('private_key'); | |
p_tenancy_id := l_credential.get_string('tenancy_id'); | |
p_fingerprint := l_credential.get_string('fingerprint'); | |
else | |
p_secret_data := l_credential.get_string('secret_data'); | |
end case; | |
end extract_credential_from_secret; | |
/** | |
* OCI Vaultのシークレットとして保存した文字列より、APEXのWeb資格証明を作成する。 | |
*/ | |
procedure create_credential_from_secret( | |
p_secret in clob | |
,p_force_update in boolean | |
,p_workspace in varchar2 | |
) | |
as | |
l_blob blob; | |
l_credential json_object_t; | |
l_credential_name varchar2(400); | |
l_credential_static_id varchar2(400); | |
l_authentication_type varchar2(20); | |
l_allowed_urls varchar2(4000); | |
l_prompt_on_install boolean; | |
l_credential_comment varchar2(4000); | |
l_scope varchar2(4000); | |
l_credential_code_type apex_workspace_credentials.credential_type_code%type; | |
l_count number; | |
is_new boolean; | |
e_authenticantication_type_is_changed exception; | |
begin | |
/* | |
* 引数にワークスペース名が設定されていれば設定する。 | |
* プロシージャーがSQLclなどから呼び出されたときの対応だが、 | |
* ワークスペースを指定したときの動作は未確認。 | |
*/ | |
if p_workspace is not null then | |
apex_util.set_workspace( p_workspace => p_workspace ); | |
end if; | |
/* | |
* Base64でエンコードされたシークレットをデコードしてJSONとして扱えるように変換する。 | |
*/ | |
l_blob := apex_web_service.clobbase642blob( | |
p_clob => p_secret | |
); | |
l_credential := json_object_t.parse(l_blob); | |
/* | |
* Web資格証明の有無を確認する。 | |
*/ | |
l_credential_static_id := l_credential.get_string('credential_static_id'); | |
l_authentication_type := l_credential.get_string('authentication_type'); | |
is_new := false; | |
begin | |
select credential_type_code into l_credential_code_type from apex_workspace_credentials | |
where static_id = l_credential_static_id; | |
exception | |
when no_data_found then | |
/* 新規作成 */ | |
is_new := true; | |
end; | |
/* | |
* Web資格証明がすでに作成済みのときの対応。 | |
*/ | |
if not is_new then | |
if p_force_update then | |
/* 再作成の指定があれば、作成済みのWeb資格証明を削除する。 */ | |
apex_credential.drop_credential( p_credential_static_id => l_credential_static_id ); | |
elsif l_credential_code_type <> l_authentication_type then | |
/* Web資格証明のタイプの変更は許さない。 */ | |
raise e_authenticantication_type_is_changed; | |
end if; | |
end if; | |
/* | |
* Web資格証明を新規作成する。 | |
*/ | |
if is_new then | |
/* 共通の属性を取り出す。 */ | |
l_credential_name := l_credential.get_string('credential_name'); | |
l_allowed_urls := l_credential.get_string('allowd_urls'); | |
l_prompt_on_install := l_credential.get_boolean('prompt_on_install'); | |
l_credential_comment := l_credential.get_string('credential_comment'); | |
l_scope := l_credential.get_string('scope'); | |
/* Web資格証明を作成する。 */ | |
apex_credential.create_credential( | |
p_credential_name => l_credential_name | |
,p_credential_static_id => l_credential_static_id | |
,p_authentication_type => l_authentication_type | |
,p_scope => l_scope | |
,p_allowed_urls => apex_string.split(l_allowed_urls,',') | |
,p_prompt_on_install => l_prompt_on_install | |
,p_credential_comment => l_credential_comment | |
); | |
end if; | |
/* Web資格証明を更新する。 */ | |
case l_authentication_type | |
when apex_credential.C_TYPE_BASIC then | |
apex_credential.set_persistent_credentials( | |
p_credential_static_id => l_credential_static_id | |
,p_username => l_credential.get_string('username') | |
,p_password => l_credential.get_string('password') | |
); | |
when apex_credential.C_TYPE_HTTP_HEADER then | |
apex_credential.set_persistent_credentials( | |
p_credential_static_id =>l_credential_static_id | |
,p_username => l_credential.get_string('header_name') | |
,p_password => l_credential.get_string('header_value') | |
); | |
when apex_credential.C_TYPE_HTTP_QUERY_STRING then | |
apex_credential.set_persistent_credentials( | |
p_credential_static_id => l_credential_static_id | |
,p_username => l_credential.get_string('parameter_name') | |
,p_password => l_credential.get_string('parameter_value') | |
); | |
when apex_credential.C_TYPE_OAUTH_CLIENT_CRED then | |
apex_credential.set_persistent_credentials( | |
p_credential_static_id => l_credential_static_id | |
,p_username => l_credential.get_string('client_id') | |
,p_password => l_credential.get_string('client_secret') | |
); | |
when apex_credential.C_TYPE_OCI then | |
apex_credential.set_persistent_credentials( | |
p_credential_static_id => l_credential_static_id | |
,p_client_id => l_credential.get_string('user_id') | |
,p_client_secret => l_credential.get_string('private_key') | |
,p_namespace => l_credential.get_string('tenancy_id') | |
,p_fingerprint => l_credential.get_string('finterprint') | |
); | |
end case; | |
end create_credential_from_secret; | |
end utl_apex_web_credential_manager; | |
/ |