Oracle Cloud Infrastructureの環境では、暗号化キーといったセンシティブな情報の保存先として、ボールト(Vault)のサービスを使用できます。
ボールトのサービスを呼び出すPL/SQL SDKが提供されているので、これを使ってシークレットとして暗号キーを保存と取り出しを実装してみます。
ボールトが作成済みであることが前提条件です。
ボールトの作成手順については、日本オラクルから公開されている以下のチュートリアルが参考になります。
OCIチュートリアル - Oracle Cloud Infrastructureを使ってみよう
プライベート認証局と証明書の発行
https://oracle-japan.github.io/ocitutorials/intermediates/certificate/
シークレットの作成、更新、削除を行うAPIを呼び出す際に使用するクリデンシャルは、以下の手順に沿って作成します。
作成されるクリデンシャルはMY_OCI_CREDになります。
APEXにて以下のテスト用アプリケーションを作成します。以下の操作を行なっています。
APEXにて以下のテスト用アプリケーションを作成します。以下の操作を行なっています。
- Generate Keyをクリックし暗号化キーを生成する。暗号化キーはGenerated Keyに返される。
- Secret Nameを指定する。CreateをクリックしてGenerated Keyに表示されている暗号化キーをシークレットとして保存する。Secret IDとCurrent Version Numberが返される。
- Generate Keyをクリックし、暗号化キーを更新する。
- Updateをクリックし、Secret IDのシークレットを新たに生成されたGenerated Keyの値で更新する。Current Version Numberが返される。
- Getをクリックし、シークレットとして保存されている暗号化キーをKeyに返す。Generated Keyと同じ値になる。
- Time Of Deletionを設定し、Deleteをクリックする。Secret IDのシークレットの削除がスケジュールされる。
OCIコンソールより、一連の操作を行なったシークレットを確認します。
バージョンが2つあり、すでに削除がスケジュールされていることが確認できます。
以下より、実施した作業を紹介します。
マスター暗号化キーの作成
シークレットを作成する際に指定する暗号化キーを作成します。
OCIのコンソールよりボールトの詳細ページを開きます。
ボールトのOCIDはAPI呼び出しの際に使用するため、あらかじめコピーしておきます。
リソースのマスター暗号化キーを選択し、キーの作成をクリックします。
画面右よりドロワーが開きます。
保護モードとしてソフトウェアが使えます。名前は任意ですがSFM_MASTER_KEYとしました。キーのシェイプ: アルゴリズムはAES、キーの長さは選択できる最長の長さである256ビットを選択します。
以上で作成をクリックします。
少し時間がかかりますが、マスター暗号化キーが作成されます。
マスター暗号化キーのOCIDもAPIの呼び出しに使用するため、コピーをとっておきます。
ポリシーの作成
クリデンシャルMY_OCI_CREDの元となるユーザーがシークレットを操作できるように、ポリシーを作成します。
OCIコンソールよりアイデンティティのポリシーを開きます。
ポリシーの作成をクリックします。
作成するポリシーの名前はSecretAdminPolicyとしています。コンパートメントにはルートを選んでいます。ポリシー・ユースケースとしてキーおよびシークレット管理を選択し、共通ポリシー・テンプレートとしてセキュリティ管理者がボールト、キーおよびシークレットを管理できるようにしますを選択します。
ポリシーを適用するグループとしてAPEXObjectManagersを選択し、場所としてルートを指定しています。クリデンシャルMY_OCI_CREDを作成する手順にグループAPEXObjectManagersの作成も含まれています。
以上で作成をクリックします。
ポリシーSecretAdminPolicyが作成されます。
テナンシのOCIDの取得
シークレットを操作するAPIの呼び出しには、ボールト、マスター暗号化キーの他にコンパートメントのOCIDが必要です。
OCIコンソールよりコンパートメントを開き、使用するコンパートメントのOCIDをコピーしておきます。
PL/SQL SDKの実行権限の付与
シークレットを操作するPL/SQL SDKのパッケージの実行権限を、APEXのワークスペース・スキーマに与えます。以下の例ではワークスペース・スキーマをwksp_apexdevとしています。環境に合わせてワークスペース・スキーマ名を置き換えます。
データベース・アクションの開発のSQLより実行します。
パッケージSFM_SECRET_UTILの作成
パッケージSFM_SECRET_UTILを作成します。
create_secret、update_secret、get_key_from_secret、delete_secretの4つのファンクションまたはプロシージャが実装されています。
SQLワークショップのSQLスクリプトを使って実行します。
検証用アプリケーションの作成
アプリケーション作成ウィザードを起動し、空のアプリケーションを作成します。アプリケーションの名前はシークレットの操作としました。
アプリケーションの作成を実行します。
アプリケーションが作成されます。
アプリケーション定義の置換を開き、置換文字列としてG_COMPARTMENT_OCID、G_MASTER_KEY_OCID、G_VAULT_OCID、G_REGION、G_CREDENTIALを設定します。
ページ・デザイナでホーム・ページを開きます。
ボタンおよびページを作成し、以下のように配置します。
ページ・アイテムP1_TIME_OF_DELETIONのみタイプが日付ピッカーです。それ以外はテキスト・フィールド、ボタンもデフォルトの設定です。
ボタンGENERATE_KEYのクリックに対応したプロセスを作成します。
識別の名前は暗号キーの作成、タイプはコードの実行を選択します。PL/SQLコードには以下を記述します。暗号化キーがGenerated Keyに設定されます。
:P1_GENERATED_KEY := rawtohex(dbms_crypto.randombytes(32));
識別の名前はシークレットの作成、タイプはAPIの呼び出しを選択します。パッケージSFM_SECRET_UTILに含まれるファンクションCREATE_SECRETを呼び出します。
ファンクションの結果として作成されたシークレットのOCIDが返されます。ページ・アイテムP1_SECRET_IDに設定します。
シークレットに保存する暗号化キーであるp_keyとして、以下のPL/SQL式を指定します。
hextoraw(:P1_GENERATED_KEY)
パラメータp_secret_nameはシークレット名です。ユーザーがページ・アイテムP1_SECRET_NAMEに入力します。すでに同名のシークレットが存在する場合、エラーが発生します。
出力パラメータのp_current_version_numberは、ページ・アイテムP1_CURRENT_VERSION_NUMGBERに設定します。シークレットの作成時は1が返されます。
引数p_compartment_ocid、p_master_key_ocid、p_vault_ocid、p_region、p_credentialについては、置換文字列のG_COMPARTMENT_OCID、G_MASTER_KEY_OCID、G_VAULT_OCID、G_REGION、G_CREDENTIALをアイテムとして設定します。
ボタンUPDATEのクリックに対応したプロセスを作成します。
識別の名前はシークレットのアップデート、タイプはAPIの呼び出しを選択します。パッケージSFM_SECRET_UTILに含まれるファンクションUPDATE_SECRETを呼び出します。
ファンクションの結果としてバージョン番号が返されます。アイテムP1_CURRENT_VERSION_NUMBERに設定します。通常、現在のバージョン番号より1つ大きい値になります。
パラメータp_keyの設定はCREATEと同じです。
パラメータp_secret_idとしてページ・アイテムP1_SECRET_IDの値が渡されます。ボタンCREATEを押したときに、ページ・アイテムP1_SECRET_IDには、作成されたシークレットのOCIDが設定されています。
ボタンGETのクリックに対応したプロセスを作成します。
識別の名前は暗号キーの取り出し、タイプはAPIの呼び出しを選択します。パッケージSFM_SECRET_UTILに含まれるファンクションGET_KEY_FROM_SECRETを呼び出します。
ファンクションの結果として暗号化キーがRAW型で返されます。パラメータのデータ型にVARCHAR2を選択しているため、暗黙でファンクションrawtohexが実行されてページ・アイテムP1_KEYに値が設定されます。
そのためP1_GENERATED_KEYとP1_KEYは同じ表示になります。
パラメータp_secret_nameにはP1_SECRET_NAMEが渡されます。
パラメータp_secret_idおよびp_version_numberは出力パラメータで、それぞれページ・アイテムP1_SECRET_ID、P1_CURRENT_VERSION_NUMBERに設定されます。
ボタンDELETEのクリックに対応したプロセスを作成します。
識別の名前はシークレットの削除、タイプはAPIの呼び出しを選択します。パッケージSFM_SECRET_UTILに含まれるファンクションDELETE_SECRETを呼び出します。
パラメータp_secret_idには、ページ・アイテムP1_SECRET_IDの値が渡されます。
パラメータP1_TIME_OF_DELETIONはシークレットが実際に削除される日付を指定します。シークレットは即時で削除することはできません。ページ・アイテムP1_TIME_OF_DELETIONも最低でも1日以上立ってから削除されるよう、日付ピッカーにて削除日時を選択します。
以上でアプリケーションは完成です。実行すると、記事の先頭のGIF動画のように、パッケージのコードの動作確認ができます。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/oci-secret-plsql-sdk.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完