[アップデート] Amazon Bedrock のモデル実行に Amazon Bedrock Guardrails の利用を強制する IAM 条件キーが登場しました

[アップデート] Amazon Bedrock のモデル実行に Amazon Bedrock Guardrails の利用を強制する IAM 条件キーが登場しました

Clock Icon2025.03.20

こんにちは!クラウド事業本部コンサルティング部のたかくに(@takakuni_)です。

Amazon Bedrock のモデル実行に Amazon Bedrock Guardrails の利用を強制する IAM 条件キーが登場しました。

https://aws.amazon.com/jp/about-aws/whats-new/2025/03/amazon-bedrock-guardrails-policy-based-enforcement-responsible-ai/

AWS Blog も投稿されていますね。

https://aws.amazon.com/blogs/machine-learning/amazon-bedrock-guardrails-announces-iam-policy-based-enforcement-to-deliver-safe-ai-interactions/

Amazon Bedrock Guardrails

Amazon Bedrock Guardrails は、 Amazon Bedrock の機能の 1つで、生成 AI アプリケーションの安全装置となる機能です。Amazon Bedrock Guardrails を利用することで、 LLM とのやりとりの中で、ふさわしくない話題/危険な内容/個人情報等が含まれるケースを制御(ブロックやマスク)するような仕組みが実装できます。

https://dev.classmethod.jp/articles/introduction-2024-amazon-bedrock-guardrails/

ここ最近では、ふさわしくない話題や個人情報のブロック/マスクに加えて、ハルシネーションなどのチェックもサポートされ始めました。

https://dev.classmethod.jp/articles/guardrails-for-amazon-bedrock-contextual-grounding-check/

https://dev.classmethod.jp/articles/amazon-bedrock-guardrails-automated-reasoning-checks-awsreinvent2024/

アップデート

今回のアップデートは「Amazon Bedrock を利用したモデル実行に Amazon Bedrock Guardrails の利用を強制する IAM 条件キーが登場しました。」というものです。今まではこの辺りの強制は難しかったため、選択肢が増えてとても良いアップデートだと思います。

対応する API は次の通りで、ひととおりの API がサポートされています。

  • Converse
  • ConverseStream
  • InvokeModel
  • InvokeModelWithResponseStream

https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails-permissions.html#guardrails-permissions-id

条件キーを眺めてみる

まずは条件キーを眺めてみましょう。新たに bedrock:GuardrailIdentifier キーが追加されていますね。

InvokeFoundationModelStatement1 で特定リージョンのモデル実行に、ガードレール(guardrail-id のバージョン 1)と一緒に使っていれば、許可を行い InvokeFoundationModelStatement2 で特定リージョンのモデル実行に、ガードレール(guardrail-id のバージョン 1)と一緒に使っていなければ拒否を行うよう定義されています。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "InvokeFoundationModelStatement1",
            "Effect": "Allow",
            "Action": [
                "bedrock:InvokeModel",
                "bedrock:InvokeModelWithResponseStream"
            ],
            "Resource": [
                "arn:aws:bedrock:region::foundation-model/*"
            ],
            "Condition": {
                "StringEquals": {
                    "bedrock:GuardrailIdentifier": [
                        "arn:aws:bedrock:region:account-id:guardrail/guardrail-id",
                        "arn:aws:bedrock:region:account-id:guardrail/guardrail-id:*"
                    ]
                }
            }
        },
        {
            "Sid": "InvokeFoundationModelStatement2",
            "Effect": "Deny",
            "Action": [
                "bedrock:InvokeModel",
                "bedrock:InvokeModelWithResponseStream"
            ],
            "Resource": [
                "arn:aws:bedrock:region::foundation-model/*"
            ],
            "Condition": {
                "StringNotEquals": {
                    "bedrock:GuardrailIdentifier": "arn:aws:bedrock:region:account-id:guardrail/guardrail-id:1"
                }
            }
        },
        {
            "Sid": "ApplyGuardrail",
            "Effect": "Allow",
            "Action": [
                "bedrock:ApplyGuardrail"
            ],
            "Resource": [
                "arn:aws:bedrock:region:account-id:guardrail/guardrail-id"
            ]
        }
    ]
}

バージョンの利用を許可する場合は、guardrail-id のみの、バージョン番号を付与しない形で許可を行うようです。

特定のガードレールとそのドラフトバージョンの使用を強制するポリシー

{
    "Version": "2012-10-17",
    "Statement": [{
            "Sid": "InvokeFoundationModelStatement1",
            "Effect": "Allow",
            "Action": [
                "bedrock:InvokeModel",
                "bedrock:InvokeModelWithResponseStream"
            ],
            "Resource": [
                "arn:aws:bedrock:region::foundation-model/*"
            ],
            "Condition": {
                "StringEquals": {
                    "bedrock:GuardrailIdentifier": "arn:aws:bedrock:region:account-id:guardrail/guardrail-id"
                }
            }
        },
        {
            "Sid": "InvokeFoundationModelStatement2",
            "Effect": "Deny",
            "Action": [
                "bedrock:InvokeModel",
                "bedrock:InvokeModelWithResponseStream"
            ],
            "Resource": [
                "arn:aws:bedrock:region::foundation-model/*"
            ],
            "Condition": {
                "StringNotEquals": {
                    "bedrock:GuardrailIdentifier": "arn:aws:bedrock:region:account-id:guardrail/guardrail-id"
                }
            }
        },
        {
            "Sid": "ApplyGuardrail",
            "Effect": "Allow",
            "Action": [
                "bedrock:ApplyGuardrail"
            ],
            "Resource": [
                "arn:aws:bedrock:region:account-id:guardrail/guardrail-id"
            ]
        }
    ]
}

制約事項

今回の Condition には制約事項があります。

  • RetrieveAndGenerate や InvokeAgent などユーザーに変わって Bedrock のサービス側で推論 API を実行する場合は利用できない
    • AccessDenied エラーが発生する可能性がある
  • input タグを利用してガードレールのチェックを回避できる可能性がある
  • Amazon Bedrock Guardrails はリソースベースのポリシーをサポートしていないため、リクエストを行う IAM と同じ AWS アカウント内に存在する必要がある

やってみる

それでは、IAM 条件キーを追加した形で、 Bedrock 経由でモデルの呼び出しを行います。リージョンはオレゴンリージョンを利用しました。

ガードレールの作成

まずはユーザーに利用を強制させるガードレールを作成します。

今回は Word filters を利用して damenaword がやりとりに含まれていた場合に検知するよう設定しました。バージョンも 1 つだけ作っておきます。

2025-03-20 at 00.05.21-Amazon Bedrock  us-west-2-1.png

ガードレール作成後、事前にテストを実施したところ、うまく検出されていることがわかります。

2025-03-20 at 00.45.23-Amazon Bedrock  us-west-2.png

ガードレール ID は後ほど IAM ポリシーの定義で利用するため、控えておきます。

IAM の作成

今回は IAM ユーザーを作成し、次の IAM ポリシーを適用しました。

ドキュメントでいう、例1と例2の組み合わせとしました。(DRAFT およびバージョン1 のどちらかを強制させるポリシーです。)

Enforce the use of specific guardrails in model inference requests

{
    "Version": "2012-10-17",
    "Statement": [{
            "Sid": "InvokeFoundationModelStatement1",
            "Effect": "Allow",
            "Action": [
                "bedrock:InvokeModel",
                "bedrock:InvokeModelWithResponseStream"
            ],
            "Resource": [
                "arn:aws:bedrock:us-west-2::foundation-model/*"
            ],
            "Condition": {
                "StringEquals": {
                    "bedrock:GuardrailIdentifier": [
                        "arn:aws:bedrock:us-west-2:123456789012:guardrail/1t5wiavpc1ub",
                        "arn:aws:bedrock:us-west-2:123456789012:guardrail/1t5wiavpc1ub:1"
                    ]
                }
            }
        },
        {
            "Sid": "InvokeFoundationModelStatement2",
            "Effect": "Deny",
            "Action": [
                "bedrock:InvokeModel",
                "bedrock:InvokeModelWithResponseStream"
            ],
            "Resource": [
                "arn:aws:bedrock:us-west-2::foundation-model/*"
            ],
            "Condition": {
                "StringNotEquals": {
                    "bedrock:GuardrailIdentifier": [
                        "arn:aws:bedrock:us-west-2:123456789012:guardrail/1t5wiavpc1ub",
                        "arn:aws:bedrock:us-west-2:123456789012:guardrail/1t5wiavpc1ub:1"
                    ]
                }
            }
        },
        {
            "Sid": "ApplyGuardrail",
            "Effect": "Allow",
            "Action": [
                "bedrock:ApplyGuardrail"
            ],
            "Resource": [
                "arn:aws:bedrock:us-west-2:123456789012:guardrail/1t5wiavpc1ub"
            ]
        }
    ]
}

モデルの推論

作成した IAM ユーザーのアクセスキーを利用して、 boto3 からモデルの実行を行います。

ガードレールを適用しない推論

まずは、ガードレールを適用せずに Converse API を実行します。

main.py
import boto3

region_name = "us-west-2"
bedrock_runtime = boto3.client("bedrock-runtime", region_name=region_name)

system_prompt = "You are an excellent assistant."
input_message = "Why sky is blue?"
modelId = "anthropic.claude-3-5-sonnet-20240620-v1:0"

response = bedrock_runtime.converse(
    modelId=modelId,
    system=[{"text": system_prompt}],
    messages=[{
        "role": "user",
        "content": [{"text": input_message}]
    }]
)

print(response["output"]["message"]["content"][0]["text"])

明示的な Deny が働き、モデルの実行が拒否されていることがわかります。

(enforce-guardrails-py3.12) takakuni@ enforce-guardrails % python main.py
Traceback (most recent call last):
  File "/Users/takakuni/Documents/genai-blog/enforce-guardrails/main.py", line 10, in <module>
    response = bedrock_runtime.converse(
               ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/takakuni/Documents/genai-blog/enforce-guardrails/.venv/lib/python3.12/site-packages/botocore/client.py", line 570, in _api_call
    return self._make_api_call(operation_name, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/takakuni/Documents/genai-blog/enforce-guardrails/.venv/lib/python3.12/site-packages/botocore/context.py", line 124, in wrapper
    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/takakuni/Documents/genai-blog/enforce-guardrails/.venv/lib/python3.12/site-packages/botocore/client.py", line 1031, in _make_api_call
    raise error_class(parsed_response, operation_name)
botocore.errorfactory.AccessDeniedException: An error occurred (AccessDeniedException) when calling the Converse operation: User: arn:aws:iam::123456789012:user/enforce-guardrail is not authorized to perform: bedrock:InvokeModel on resource: arn:aws:bedrock:us-west-2::foundation-model/anthropic.claude-3-5-sonnet-20240620-v1:0 with an explicit deny in an identity-based policy

ガードレールを適用した Invoke Model

続いて、ガードレールを適用した形で InvokeModel API を実行します。

app.py
import boto3

region_name = "us-west-2"
bedrock_runtime = boto3.client("bedrock-runtime", region_name=region_name)

system_prompt = "You are an excellent assistant."
input_message = "Why sky is blue?"
modelId = "anthropic.claude-3-5-sonnet-20240620-v1:0"

+ guardrail_id = "1t5wiavpc1ub"
+ guardrail_version = "1"
+ guardrail_config = {
+     "guardrailIdentifier": guardrail_id,
+     "guardrailVersion": guardrail_version,
+     "trace": "enabled"
+ }

response = bedrock_runtime.converse(
    modelId=modelId,
    system=[{"text": system_prompt}],
    messages=[{
        "role": "user",
+        "content": [{"guardContent": {"text": {"text": input_message}}}]
+    }],
+    guardrailConfig=guardrail_config
-        "content": [{"text": input_message}]
-    }]
)

print(response["output"]["message"]["content"][0]["text"])

うまく、生成されました!

(enforce-guardrails-py3.12) takakuni@ enforce-guardrails % python main.py
The sky appears blue to us due to a phenomenon called Rayleigh scattering. Here's a simplified explanation:

1. Sunlight contains all colors of the visible spectrum.

2. As sunlight enters Earth's atmosphere, it collides with gas molecules and other particles.

3. These collisions cause the light to scatter in all directions.

4. Blue light has a shorter wavelength and higher frequency than other colors in the visible spectrum, so it scatters more easily than other colors.

5. This scattered blue light reaches our eyes from all directions, making the sky appear blue.

6. Other colors, like red and yellow, have longer wavelengths and pass through the atmosphere more directly, which is why we see them more prominently during sunrise and sunset when sunlight travels through more of the atmosphere to reach our eyes.

This is why on a clear day, the sky appears blue to us. However, factors like pollution, humidity, and cloud cover can affect the sky's appearance, sometimes making it look gray or white.

ガードレールを適用した Invoke Model (NG ワード入り)

最後にガードレールが機能するかチェックしましょう。

NG ワードで設定した damenaword を input_message に入力します。

app.py
import boto3

region_name = "us-west-2"
bedrock_runtime = boto3.client("bedrock-runtime", region_name=region_name)

system_prompt = "You are an excellent assistant."
+ input_message = "Why sky is blue? damenaword"
- input_message = "Why sky is blue?"
modelId = "anthropic.claude-3-5-sonnet-20240620-v1:0"

guardrail_id = "1t5wiavpc1ub"
guardrail_version = "1"
guardrail_config = {
    "guardrailIdentifier": guardrail_id,
    "guardrailVersion": guardrail_version,
    "trace": "enabled"
}

response = bedrock_runtime.converse(
    modelId=modelId,
    system=[{"text": system_prompt}],
    messages=[{
        "role": "user",
        "content": [{"guardContent": {"text": {"text": input_message}}}]
    }],
    guardrailConfig=guardrail_config
)

print(response["output"]["message"]["content"][0]["text"])

正しく機能していますね。

(enforce-guardrails-py3.12) takakuni@ enforce-guardrails % python main.py
申し訳ありませんが、モデルはこの質問に回答できません。

まとめ

以上、「Amazon Bedrock のモデル実行に Amazon Bedrock Guardrails の利用を強制する IAM 条件キーが登場しました。」でした。

今まで利用が任意 or アプリケーションの作りに依存していた部分から、さらにガバナンスを効かせられることができるようになって、嬉しいですね。

このブログがどなたかの参考になれば幸いです。クラウド事業本部コンサルティング部のたかくに(@takakuni_)でした!

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.