🚨

[Bedrock] APIキーとIAMポリシーでLLMをセキュアに呼び出す方法

に公開

こんにちは!AWS Bedrock で生成AIライフを楽しんでいますか?
そんなBedrockについて、コンソールからポチポチとモデルを有効化できた、あの「モデルアクセス」機能が廃止されてしまいました。

以前は「どのモデルを使うか」をGUIで管理できて便利でしたが、これからは APIキー(実態はIAMユーザー)とIAMポリシー を使って、より厳格にアクセスを管理する方式がスタンダードになりました。

本番環境で意図しないモデル(特に高価なモデル)を呼び出されない設定や、キーが漏洩したときのリスクを考えると、最小権限の原則を守って利用したいです。

この記事では、「モデルアクセス」なき後で、特定のLLM(例: Claude 3.5 Haiku)と特定のEmbeddingモデル(例: Titan Embeddings)だけを呼び出せる方法を紹介します。

今回のゴール

Claude 3.5 HaikuTitan Embedding V2のみ使用可能にし、それ以外のモデル(例: Claude 3 Opus)は絶対に呼び出せないようにする。

全体の流れは以下の通りです。

  1. APIキーと紐づくIAMユーザーの作成
  2. IAMポリシーの設定
  3. 動作確認(Docker & AWS CLI)

APIキーとIAMユーザーの作成

まずは、BedrockのコンソールからAPIキーを作成します。これがBedrockへのアクセス専用のIAMユーザーを生成します。

  1. AWS Bedrockのページにアクセスし、サイドメニューからAPIキーを選択。
  2. APIキーを生成をクリック。
  3. キーのオプションを任意の値で設定し、APIキーを生成
  4. 一覧に戻り、作成したAPIキーを選択し、アクション > IAMコンソールで管理 をクリック。
  5. ここからはIAMコンソールの画面で、セキュリティ認証情報タブに移動。
  6. 「アクセスキー」のセクションでアクセスキーを作成をクリック。
  7. ユースケース(例: コマンドラインインターフェイス (CLI))を選択し、作成。

それぞれ、生成時にアクセスキーなど、その時しか表示されない値があるため、個別にメモを取る必要がありますが、後からアクセスキーなどを作り直すことが可能です。

IAMポリシーの設定

IAMユーザー(APIキー)が作成できましたが、標準的にBedrockへのアクセスが許可された状態になっています。そのため、「どのモデルにアクセスできるか」をIAMポリシーで明示的に定義します。

  1. IAMユーザーの詳細ページで、許可タブに移動。
  2. 既存の許可ポリシー(AmazonBedrockFullAccess など)がアタッチされていたら、すべて削除
  3. 許可を追加 > インラインポリシーを作成を選択。
  4. JSONタブを選び、以下のJSONを貼り付けます。
policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowSpecificBedrockModels",
            "Effect": "Allow",
            "Action": [
                "bedrock:InvokeModel",
                "bedrock:InvokeModelWithResponseStream",
                "bedrock:CallWithBearerToken"
            ],
            "Resource": [
                "arn:aws:bedrock:us-west-2::foundation-model/anthropic.claude-3-5-haiku-20241022-v1:0",
                "arn:aws:bedrock:us-west-2::foundation-model/amazon.titan-embed-text-v2:0"
            ]
        }
    ]
}

ポリシーの内容は、必要に応じて、リージョンやモデルIDを変更して使用してください。モデルIDは、Bedrockのサイドメニュー「モデルカタログ」から、使いたいモデルを選び、詳細画面で確認できます。

動作確認(Docker & AWS CLI)

設定が完璧だと思っていても、動かしてみると想定と異なっていた場合もあるため、ローカルで検証します。通常、AWS CLIをインストールしなければなりませんが、環境によっては面倒だったり、ローカル環境を汚してしまうこともあるため、Dockerコンテナ内でAWS CLIを使ってテストします(Dockerすてき)。

準備 (Dockerコンテナ起動)

まずは、Amazon公式のAWS CLIが使えるイメージでコンテナを起動します。

$ docker run -it --rm --entrypoint /bin/bash amazon/aws-cli

以降は、起動したコンテナ内で作業します。

認証情報の設定

コンテナを起動したら、aws configureコマンドで、IAMユーザーで作成した「アクセスキーID」と「シークレットアクセスキー」を設定します。

$ aws configure

対話形式で以下のように入力します。

AWS Access Key ID [None]: (アクセスキーIDを入力)
AWS Secret Access Key [None]: (シークレットアクセスキーを入力)
Default region name [None]: (ポリシーで設定したリージョン)
Default output format [None]: json

認証情報の確認

設定が正しくできたか、自分の情報を確認します。

# コンテナ内で実行
$ aws sts get-caller-identity

以下のように、設定したユーザーのARNが表示されれば設定が適切にできています。

{
    "UserId": "AIDACKCEVS45EXAMPLE",
    "Account": "123456789012",
    "Arn": "arn:aws:iam::123456789012:user/YourUserName" 
}

LLMへのアクセス

設定ができたので、ローカルからクラウドのモデルに接続します。
converse API(会話形式)でテストするため、リクエスト内容をファイルに保存します。

$ echo '{
    "messages": [
        {"role": "user", "content": [{"text": "Hello, Bedrock!"}]}
    ]
}' > request.json

ポリシーで設定した許可しているモデルIDと任意のリージョンを設定してコマンドを実行します。

# コンテナ内で実行
$ aws bedrock-runtime converse \
    --model-id anthropic.claude-3-5-haiku-20241022-v1:0 \
    --cli-input-json file://request.json \
    --region us-west-2

問題なく実行できると、以下のようにAIからの返答が返ってきます。

"content": [
    {
        "text": "I want to be direct with you. I'm Claude, an AI created by Anthropic. I aim to be helpful, honest, and harmless. How can I assist you today?"
    }
]

Embeddingへのアクセス

次に、もう一つ許可した Embedding モデルもテストします。
リクエストファイルを上書きします。

# コンテナ内で実行
$ echo '{
    "inputText": "AWS Bedrockはフルマネージド型の生成AIサービスです。"
}' > request.json

invoke-modelAPIで実行します(同様にモデルIDやリージョンは任意のものに変更する)。

# コンテナ内で実行
$ aws bedrock-runtime invoke-model \
    --model-id amazon.titan-embed-text-v2:0 \
    --body fileb://request.json \
    --region us-west-2 \
    --accept "application/json" \
    --content-type "application/json" \
    output.json

An error occurred... といったエラーが出力されず、カレントディレクトリに output.json が生成され、中身に embedding というキーで大量の数字(ベクトル)が入っていれば成功です。
また、LLMへのアクセスとは異なり、bodyでは、fileb://を使用してバイナリで送信を行うため、注意が必要です。

許可していないモデルへのアクセス

IAMポリシーが正しく機能しているか、わざとエラーを起こして確認します。
ポリシーで許可していないモデル(例: anthropic.claude-3-sonnet-20240229-v1:0)を model-id に指定してみます。

$ aws bedrock-runtime converse \
    --model-id anthropic.claude-3-sonnet-20240229-v1:0 \
    --cli-input-json file://request.json \
    --region us-west-2

結果として、該当のモデルへのアクセス権がない旨、エラーとして表示されます。

まとめ

クラウドサービスの機能の統廃合は気づけば起きてしまうため後追いになることが大変ですが、APIキーとIAMポリシーを組み合わせることで、よりセキュアで柔軟なアクセス管理が可能になりました。

株式会社メンバーズ AIフォーオールカンパニー

Discussion