Oracle APEXのアプリケーションよりGoogle Indexing APIを呼び出す方法を調べてみました。
ポーランドのPretius社が公開している以下のブログ記事を参考にしています。
https://pretius.com/blog/google-workspace-integration-oracle-database-apex/#integration-service-account
Pretius社はOracle APEX界隈ではとても知名度の高い会社です。昨年(2022年)は、ポーランドのソフトウェアの業界団体(SoDA - Software Development Association Poland )より、“An IT project that supported Ukraine”というカテゴリにて、Oracle APEXを使って作成したアプリケーションにより表彰されています。
https://pretius.com/blog/why-low-code-how-apex-helped-refugees/
Googleが提供しているAPIの認証を通す方法はいくつかあります。Indexing APIは一番設定が簡単な(すなわち安全性が一番低い)APIキーによる認証はできません。
そのため、サービス・アカウントを使ってGoogle Indexing APIを呼び出すことにしました。
Google側の準備
Google Cloudのコンソールは使用経験がほとんど無いため、以下の記載は参考程度と考えてください。
最初にGoogle Cloudのコンソール を開きます。
プロジェクトの選択 をクリックし、開いたダイアログ上の新しいプロジェクト をクリックします。
プロジェクト名は任意ですが、ここでは
my first api project としました。
作成 をクリックします。
プロジェクトが作成されます。先ほどのプロジェクトの選択 のダイアログより、作成されたプロジェクトを開きます。
クイックアクセス (または左上のハンバーガー・メニューを開いて)よりAPIとサービス を開きます。
APIとサービスの画面の、+APIとサービスの有効化 をクリックします。
プロジェクト作成直後で15ほど利用可能なAPIとサービスが有効化されていました。使用する予定は無いため、すべて無効化しています。
今回使用する予定のindexing api を検索します。
検索された結果より、Indexing API を選択します。
Indexing APIを
有効 にします。
Indexing APIが有効になります。ウィザード形式で認証情報を作成するためのボタン認証情報を作成 がありますが、認証情報はサービス・アカウントとキーを使うことに決めているので、ウィザードは使用しません。
左のメニューより認証情報 を開きます。
認証情報の画面より+認証情報を作成 をクリックし、サービスアカウント を選択します。
サービスアカウント名 、サービスアカウントID 、サービスアカウントの説明 を設定します。任意の値を設定します。
これからの作業で使用するのは、サービスアカウントIDのメールアドレス です。クリップボードにコピーして、保存しておきます。
完了 をクリックします。
サービスアカウントが作成されます。鉛筆アイコン (またはサービスアカウント名 )をクリック し、編集を開始します。
キー ・タブを開き、
鍵を追加 より
新しい鍵の作成 を実行します。
キーのタイプ としてP12 (PKCS#12形式)を選択し、作成を実行します。この鍵はPL/SQLのパッケージDBMS_CRYPTOで使用するため、PKCS#1またはPKCS#8形式に変更します。JSONが推奨となっていますが、opensslコマンドを使用するため扱いやすいP12を選択しています。
作成 をクリックします。
秘密鍵が手元のPCにダウンロードされます。opensslで形式変換する際に、秘密鍵のパスワードを聞かれるため、表示されている
秘密鍵のパスワード をクリップボードに
コピー し、保存しておきます。
閉じる をクリックします。
ダウンロードされたPKCS#12形式のファイルをPKCS#8形式に変換します。openssl pkcs12コマンドを使用します。
openssl pkcs12 -in ダウンロードされたファイル -nocerts -nodes -out 出力ファイル
Enter Import Password: には秘密鍵のパスワード を入力します。
以下の例では、秘密鍵をmy-api.key というファイルに出力しています。
% openssl pkcs12 -in my-first-api-project-*******.p12 -nocerts -nodes -out my-api.key
Enter Import Password: 秘密鍵のパスワード
MAC verified OK
%
Google Cloudのコンソールでの作業は、以上で終了です。
Google Search Consoleを開き、設定 からユーザーと権限 を開きます。
ユーザーを追加 を実行します。
メールアドレス として、作成済みのサービスアカウントのメールアドレス を指定します。権限 はオーナー を割り当てます。
追加 をクリックします。
ユーザーの追加が確認されたら、Google Search Consoleでの作業は完了です。
Autonomous Databaseでの作業に移ります。
Oracle Database 19cより追加されたDBMS_CRYPTO.SIGNを使用します。Autonomous Databaseでは利用可能です。
JSON Web Tokenを作成するファンクションと作成したJWTを使ってトークンを取得するために使用するパッケージUTIL_GOOGLE_API を作成します。
コードは以下になります。データベースで実行します。
SQLコマンド よりGoogle Indexing APIを発行し、動作を確認します。秘密鍵やサービスアカウントのメールアドレスの部分は置き換えます。
This file contains hidden or 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_jwt varchar2(32767);
C_RSA_KEY constant varchar2(32767) := q'~
-----BEGIN PRIVATE KEY-----
opensslで生成した秘密鍵ファイルの内容をそのまま
貼り付ける。
-----END PRIVATE KEY-----
~';
l_token_url varchar2(4000);
l_token_clob clob;
l_token_json json_object_t;
l_token varchar2(32767);
l_request clob;
l_result clob;
begin
/* JWTの生成 */
l_jwt := util_google_api.generate_jwt(
p_secret => C_RSA_KEY
,p_iss => 'サービスアカウントのメールアドレス'
,p_scope => 'https://www.googleapis.com/auth/indexing' -- Indexing APIのscope
,p_aud => 'https://oauth2.googleapis.com/token'
);
-- dbms_output.put_line(l_jwt);
/* トークンの取得 */
l_token := util_google_api.get_token(l_jwt);
-- dbms_output.put_line(l_token);
/* Indexing APIの呼び出し */
l_request := q'~{"url":"索引の作成を要求するURL","type":"URL_UPDATED"}~';
apex_web_service.clear_request_headers;
apex_web_service.set_request_headers('Content-Type','application/json',p_reset => false);
apex_web_service.set_request_headers('Authorization', l_token,p_reset => false);
l_result := apex_web_service.make_rest_request(
p_url => 'https://indexing.googleapis.com/v3/urlNotifications:publish'
,p_http_method => 'POST'
,p_body => l_request
);
dbms_output.put_line(l_result);
end;
JSONのレスポンスが正常に返されていれば、すべての作業は完了です。
以上で動作確認も完了です。
実際には、データベースのどこかに秘密鍵を安全に保存する必要もあり、また、生成したJWTや取得したトークンをキャッシュしておくといった実装も必要になるかと思います。
本記事は以上になります。
完