AWSからは署名バージョン4のリファレンスとして、以下のページが公開されています。英語ですし内容も難しいので、これを読んで署名処理を実装するのはかなり難しいと思います。
Signing AWS API requestsRequest signature examples
Troubleshoot signed requests for AWS APIs
日本語では、以下の説明がわかりやすかったです。
AWS の API を理解しよう !
中級編 ~ リクエストの署名や CLI/SDK の中身を覗いてみる
いちから署名処理を実装するのは大変なので、Amazon S3にアクセスするために書かれたパッケージより、署名処理の部分を流用することにしました。
plsql-aws-s3
パッケージAWS4_S3_PKGに、Amazon S3を操作するファンクションやプロシージャが実装されています。このパッケージを元に、署名生成に使われているプライベート・ファンクションを残したパッケージAWS4_REST_PKGを作成しました。これらのファンクションでS3に決め打ちになっている部分を、bedrockを呼び出せるように改変しています。
S3を操作するためのファンクションはすべて削除しています。その上で、署名バージョン4を生成し、HTTPのリクエスト・ヘッダーに設定するファンクションset_authorization_headersを新設しています。パッケージAWS4_REST_PKGのパブリックなファンクションはこれだけです。ファンクションset_authorization_headersではREST APIの呼び出しは行わず、apex_web_service.set_request_headersを呼び出して、署名バージョン4による署名を含んだAuthorizationヘッダーおよびその他いくつかの関連したヘッダーの設定だけを行います。
aws4_rest_pkg.set_authorization_headresを呼び出した後に、apex_web_service.make_rest_requestを呼び出すことによって、署名が付いたREST APIを発行します。
パッケージAWS4_REST_PKG本体のコードは記事の末尾に添付します。
パッケージAWS4_REST_PKGをインストールした後に実施した、動作確認の作業を記述します。以下の記事と同じ手順で、AWSのIAMユーザーとしてoracletestuserが作成済みで、アクセスキーとシークレットアクセスキーが作成済みとします。
Oracle Database 23c FreeにDBMS_CLOUDパッケージを入れてAmazon S3にアクセスする
AWSコンソールよりBedrockのページを開きます。今回はAgents APIを呼び出すことを想定しています。Agentsが使えるリージョンは限られているようなので、メニューにAgentsが表示されない場合は、リージョンを切り替える必要があります。以下の作業はバージニア北部(us-east-1)で実施しています。
Agentsから使える基盤モデルは、現時点ではAnthropicに限られているようです。
AnthropicのClaudeおよびClaude Instantについては、Access statusがUse case details requiredとなっています。今回はAgentsから実際に基盤モデルを呼び出すのは(お金もかかるので)やめて、署名バージョン4が正しく生成できていることだけを確認することにします。
Agentsのページを開き、新しくAgentを作成します。Create Agentをクリックします。
今回は署名が付与されたREST APIの認証が通ればよいので、Bedrock Agent自体の設定は最低限にします。BedrockのAgentsの詳細については、他の資料にあたっていただくようお願いします。
Nextをクリックします。
とりあえずClaude Instant V1を選択し、Instructions for the Agentとして「あなたは日本語を話す親切なエージェントです。丁寧な言葉遣いで回答し差別的な用語は使いません。」と記述して、Nextをクリックします。
Action groupsの追加画面が開きます。OpenAIでのFunction Callingと同等の機能と考えて良いかと思います。OpenAIのFunction Callingとは異なり、AgentはActionとして設定したLambdaファンクションの呼び出しまでを実施するようです。
Action groupsとして何も設定せず、Nextをクリックします。
Knowledge baseの追加画面が開きます。OpenAIでのRetrievalに当たる機能かと思います。Amazon S3に保存してあるドキュメントからベクトル埋め込み(embeddings)を生成しOpenSearchやPineconeに保存して、RAG(Retrieval-Augmented Generation)を実行する機能のようです。
Knowledge baseも何も設定せず、Nextをクリックします。
AgentとしてMyAgentが作成されます。これからポリシーを作成するにあたって、アカウントIDとAgent IDを使います。そのため、Agent ARNをコピーしておきます。
Identity and Access Management (IAM)のページのポリシーを開き、ポリシーの作成をクリックします。
ポリシーエディタとしてJSONを選択し、JSONでポリシーを記述します。作成されているAgentを一覧するListAgentsと、Agentを指定して情報を取得するGetAgentの呼び出し、および、Agentを指定してAliasをアップデートするUpdateAgentAliasとAgentに処理を依頼するInvokeAgentを許可します。
[アカウントID]の部分はアカウントIDである12桁の数値に置き換えます。[Agent ID]はAgentのIDに置き変えます。Agentとして未デプロイのWorking draftを指定するため、Agent AliasとしてTSTALIASIDを指定します。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "BedrockConsole",
"Effect": "Allow",
"Action": [
"bedrock:ListAgents",
"bedrock:GetAgent"
],
"Resource": "*"
},
{
"Sid": "AgentAliasSid",
"Effect": "Allow",
"Action": [
"bedrock:UpdateAgentAlias",
"bedrock:InvokeAgent"
],
"Resource": [
"arn:aws:bedrock:us-east-1:[アカウントID]:agent-alias/[Agent ID]/TSTALIASID"
]
}
]
}
次へ進みます。
ポリシーの作成をクリックすると、Bedrock Agentの呼び出しを許可するポリシーが作成されます。
確認画面で許可を追加をクリックします。
作成済みのユーザーoracletestuserを開き、許可タブより許可を追加を実行します。
許可を追加の画面でポリシーを直接アタッチするを選択します。アタッチするポリシーとして先ほど作成したポリシーOracleBedrockAgentPolicy_MyAgentを検索し、チェックを入れます。
次へ進みます。
Bedrock Agentの作成とアクセスの許可が完了しました。ユーザーoracletestuserのアクセスキーとシークレットアクセスキーは生成済みという前提なので、これでAWS側での準備は完了です。
これからOracle APEXのSQLコマンドからBedrock AgentのREST APIを呼び出してみます。
ListAgentsを呼び出してみます。以下のコードを実行します。
レスポンスとしてagentSummariesが返されました。REST APIに署名が正しく付けられているようです。
GetAgentを呼び出してみます。以下のコードを実行します。
InvokeAgentを呼び出してみます。
dependencyFailedExceptionが返されます。messageは"Access denied when calling Bedrock. Check your request permissions and retry the request."となっています。これはClaude Instance V1へのアクセスをリクエストしていないためだと思われます。
HTTPのステータス・コードは200が返されているため、署名は正しく生成されていると言えます。
印刷されたレスポンスを見ると、一筋縄では行かなそうなフォーマットでレスポンスが返されています。InvokeAgentのリファレンスのResponse SyntaxはJSONになっています。
Amazon Bedrock Agents APIを呼び出すための署名バージョン4の生成について、パッケージの作成とその動作確認については以上になります。
Oracle APEXのアプリケーション作成の参考になれば幸いです。
補足
パッケージDBMS_CLOUDにSEND_REQUESTというファンクション(およびプロシージャ)があります。開発元に確認してはいませんが、credentialScopeがs3に固定されているように見えます。credentialScopeを指定する引数はありませんし、s3以外のサービスを呼び出すとAuthentication Failedが返されます。
完