CatoガードでAIアプリケーションを保護する(サンプル設定)
概要
このガイドでは、Cato AIセキュリティガードを使用してカスタムAIアプリケーションを保護するエンドツーエンドのプロセスを説明します。 このフローは3段階で構成されており、前の段階から何を変化させ、なぜ変化させるのかが明確に理解できます。
このガイドで使用されるアプリケーションは、簡単なAI対応の旅行アシスタントチャットボットであるTravelBotです。 この例は具体的ですが、概念と手順は構築し保護したい任意のカスタムAIアプリケーションに適用されます。
このガイドでは3つのステージをカバーします。
- ステージ1では基準を確立します: LLMに直接通信する機能しているAIアプリケーションで、セキュリティ制御はありません。 このステージは、出発点とそれがもたらすリスクを理解するのに役立ちます。
- ステージ2ではガードを導入します: Catoプロキシガードが作成およびアプリケーションとLLMの間に挿入されます。 トラフィックはガードを通じてルーティングされ、すべてのインタラクションがログ記録され始めます。 まだポリシーのルールは設定されていません - このステージの目的は、ガードを伴ってもフローが正常に機能していることを確認することです。
- ステージ3ではエンフォースメントをアクティブにします: インタラクションポリシーのルールが設定および公開され、ガードが脱獄の試行をブロックし健康関連のコンテンツを監視するよう指示されます。 アプリケーションは今や完全に保護されました。
このガイドが終了するまでに、カスタムAIアプリケーションがどのようにCatoガードで保護されるかを完全に理解できます - 完全にオープンな接続から、積極的に施行補監視されたAIワークフローへと変化します。
ステージ1 — 基準: ガードのないAIアプリケーション
このステージでカバーする内容
セキュリティ制御を導入する前に、アプリケーションが単独で動作する方法を理解することが重要です。 このステージでは、ベースラインのセットアップをお伝えします - 大きな言語モデル(LLM)と直接通信するAI対応のチャットアプリケーションが動作します。 これは「以前の」状態図です: アプリは機能していますが、ユーザーとモデルの間には何も存在していません。
アプリの動作方法
アプリケーションはTravelBotと呼ばれる簡単な旅行アシスタントチャットボットです。 このアプリは3つのコンポーネントで構成され、互いに連携して動作します。
1. フロントエンド
これはユーザーが見るもので、ブラウザのチャットインターフェイスで質問を入力し応答を受け取ることができます。
2. バックエンド
これは舞台裏で動作するエンジンです。 ユーザーのメッセージを受け取り、会話履歴を追跡し、LLMにメッセージを渡します。 エラーを処理し、モデルの応答をユーザーに返します。 バックエンドは軽量ウェブフレームワークであるFlaskで構築されています。
3. LLM接続
インテリジェンスが存在する場所です。 バックエンドはユーザーのメッセージ(会話履歴を含む)を大きな言語モデルに送信し、応答を生成します。 このステージでは、バックエンドは直接LLMと通信します - 間には何もありません。
フローは次のようになります。
ユーザー(ブラウザ) → バックエンド(Flask) → LLM → ユーザーへの応答
言語とフレームワークに関する注意点
このガイドのサンプルアプリケーションは、軽量ウェブフレームワークであるFlaskを用いてPythonで構築されています。 PythonはAIアプリケーション開発に人気ですが、唯一の選択肢ではありません。 同じ概念やフローは、アプリケーションがNode.js、Java、Go、他のどのような言語で構築されている場合でも適用されます。 設定値、リクエスト構造、ガード統合はすべて同じロジックに従います - 変わるのは文法のみです。
設定ファイル
バックエンドとLLM間の接続は、config.pyというファイルによって制御されています。 このファイルは重要な3つの値を保持しています。
OPENAI_API_KEY = "sk-proj-xK92mLqP3nVwTz8YdR5eN1uJbF7cQm4HsAo6WpGi0XvCl"
BASE_URL = "https://bedrock-mantle.eu-north-1.api.aws/v1"
MODEL_ID = "amazon.nova-pro-v1:0"
OPENAI_API_KEY— これは、アプリケーションがリクエストを行う資格を持っていることをLLMプロバイダに証明する資格情報です。- BASE_URL** — これはバックエンドがリクエストを送信するアドレスです。 現在は、LLMプロバイダーに直接向けられています。
- MODEL_ID** — これはLLMプロバイダーに、応答の生成に使用する特定のモデルを伝えます。
このステージでアプリを稼働させるには、開発者がこれら3つの値をLLMプロバイダーから提供された資格情報で入力する必要があります。
アプリがメッセージを受け取るとどうなるか
ユーザーがメッセージを送信すると、ステップバイステップで次が行われます。
- ユーザーはチャットインターフェイスでメッセージを入力し、送信を押します。
- ブラウザはメッセージをFlaskバックエンドに送信し、会話を識別するセッションIDを添えて送信します。
- バックエンドはメッセージを会話履歴に追加し、全てをLLMに送信し、モデルにTravelBotとして振る舞うように指示するシステム命令を前に付けて送信します。
- LLMは会話全体を処理し、応答を生成します。
- 応答はバックエンドに返送され、会話履歴に追加され、ユーザーのブラウザに返されます。
- ユーザーはチャットインターフェースで応答を見ます。
まだ発生していないこと
このステージでは、アプリケーションが完全に機能するが完全に保護されていない状態です。 これは次のことを意味します。
- ユーザーがモデルに送信するものの検査はありません。
- ツールの呼び出しや応答には検査はありません。
- ポリシーの施行はありません — あらゆるメッセージ、悪意のあるものを含めてLLMに届きます。
- どのようにアプリケーションが使用されているのかに関する可視性はありません。
例えば、ユーザーがモデルにその指示を無視するように誘導し機密情報を抽出したり、組織のポリシーに違反する方法でアプリケーションを使用しようとする可能性があります — これらは検知も阻止もされません。
これは次のステージで対処されるギャップです。
概要
| コンポーネント | 役割 | 詳細 |
|---|---|---|
| フロントエンド | ユーザーインターフェース | Flaskによって提供されるチャットUI |
| バックエンド | リクエスト処理 | Flaskアプリ、会話履歴を管理 |
| LLM接続 | 応答生成 | BASE_URLとOPENAI_API_KEYを用いた直接接続 |
ステージ2 — ガードの導入
このステージでカバーする内容
ステージ1では、LLMと直接通信する動作しているAIアプリケーションが確立されました。 アプリは機能しますが、ユーザーとモデルの間には何もありません。 このステージでは、Cato AIセキュリティガードを導入します - アプリケーションとLLMの間に設けられる施行層であり、モデルに到達する前やユーザーに応答が返る前にトラフィックをリアルタイムで検査します。
この段階の終了までに、すべてのLLMトラフィック、ユーザーメッセージ、ツールの定義、ツールの使用などがCatoを通過します。 ユーザー体験は特に変わりません - ただし、すべてのインタラクションが検査され制御可能になります。
更新されたフローは次のようになります。
.png?sv=2026-02-06&spr=https&st=2026-09-26T04%3A37%3A11Z&se=2026-09-26T04%3A49%3A11Z&sr=c&sp=r&sig=MAacbrA8I5IgPhDzalYQaRjQDWZqrBZW31NFEN6ZtX0%3D)
ガードとは何ですか?
ガードはAIセキュリティの施行ポイントです。 この例では、プロキシモードを使用しており、それは仲介者として機能します — あなたのアプリケーションとLLMの間に位置し、定義するポリシーに対してすべてのプロンプトと応答を評価します。 ポリシーに基づき、ガードはインタラクションを許可、ブロック、またはログ記録することができます。
ガードのタイプは3つあります。 このガイドでは、プロキシガードを使用しています。 プロキシモードでは、ガードはトラフィックパスに完全にインラインで配置されます。 アプリケーションはリクエストを直接LLMではなくガードのエンドポイントに送信し、ガードが検査後にそれを転送します。 アプリケーションのロジックに変更は必要ありません — 変わるのは送信先アドレスだけです。
ステップ1 — Cato管理画面でガードを作成する
最初のステップは、Cato管理画面でガードを論理エンティティとして作成することです。 これはUIで行われます — 現時点ではコードの必要はありません。
- ナビゲーションメニューからAIセキュリティ > ガードを選択し、新しいボタンをクリックします。
- 説明的なガード名を入力します。 例では
E2E Sample Use Caseを使用します。 - ガードタイプを選択で、プロキシを選びます。
- AIサービスを選択で、ドロップダウンからカスタムエンドポイントを選択します。 このオプションは、私たちのアプリケーションが使用しているOpenAI互換エンドポイントと動作します。
- エンドポイントURLフィールドに、LLMプロバイダーのURLを入力します。 例では、これが
https://bedrock-mantle.eu-north-1.api.aws/v1です。 これは前にconfig.pyで設定されていたBASE_URLと同じURLです — アプリケーションで直接使用するのではなく、このアドレスをガードに渡しています。
注意: URLは/v1を含むまでのパスを含める必要があります。 - ガード設定を構成の下で、ガードのホストをCatoのクラウドに設定したままにします。 これはガードがCatoによって管理およびホストされていることを意味します — 追加インフラストラクチャの展開や維持の必要はありません。
- 保存をクリックします。
何が起こったのか? ガードはあなたのLLMがどこにあるかを知っています。 Catoはこれで、アプリケーションとLLMの間のすべてのトラフィックの仲介者として機能します。 ガードはまだポリシーのルールを持っていません — それらはステージ3で追加されます。 当面は単に接続を確立し、フローが正常に機能しているか確認します。
ステップ2 — ガードの接続詳細を取得する
ガードを保存したら、ガードページから開いてDocsページに移動します。ここには、アプリケーションが直接LLMに接続する代わりにガードに接続するために必要な情報がすべて記載されています。
ここで2つの重要な情報が見つかります。
-
ガードエンドポイント(新しい
BASE_URL) - これは今後アプリケーションがリクエストを送信するアドレスです:https://api.aisec.catonetworks.com/fw/v1/proxy/openai- あなたの設定でLLMのエンドポイントURLを置き換えます。 この時点以降、アプリケーションはCatoに話しかけ、CatoはLLMにあなたの代わりに話します。
-
ガードAPIキー(新しい
OPENAI_API_KEY)- DocsページはガードAPIキーも提供します — アプリケーションがガードと認証するために使用する資格情報です。 これは以前の設定でLLM APIキーを置き換えます。 以下のように見えます:
cato-1234-abcde
- DocsページはガードAPIキーも提供します — アプリケーションがガードと認証するために使用する資格情報です。 これは以前の設定でLLM APIキーを置き換えます。 以下のように見えます:
注意: Catoは2つのガードAPIキーを提供しています。 リクエストを行うには1つあれば十分です。 2番目のキーは、資格情報を安全に回転させるために存在します — 古いキーがまだアクティブな状態でアプリケーションを新しいキーに更新し、ダウンタイムを避けることができます。
LLM APIキー
以前は、LLM APIキーはアプリケーションの設定に入っていました。 ガードが設置されたことで、そのキーはアプリケーションがガードに送信する要求ヘッダーに移動します — 具体的には、x-cato-provider-api-keyという名前のヘッダーに入っています。 ガードはこれを用いて、アプリケーションに代わってLLMと認証します。
これは実際にはセキュリティの向上です: LLM APIキーが設定ファイルにハードコードされることがなくなり、ガードは資格情報を制御するパススルーの役割を果たします。
ステップ3 — アプリケーションの設定を更新する
ガードが作成され接続情報が得られた今、アプリケーションを更新するタイミングです。 ステージ1とステージ2を明確に分離して保つために、元のファイルを上書きするのではなく新しい設定ファイルセットを作成します。 この方法で、両方のステージが参照用にそのまま残ります。
新しい設定ファイルconfig_stage2.pyは、更新された接続詳細を反映させています。
# ステージ2の設定 — Catoプロキシガード経由のルーティング
GUARD_API_KEY = "cato-xxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
BASE_URL = "https://api.aisec.catonetworks.com/fw/v1/proxy/openai"
MODEL_ID = "amazon.nova-pro-v1:0"
LLM_PROVIDER_API_KEY = "[SECRET_1]" # LLMプロバイダーのAPIキー — ガードに渡され、LLMに直接渡されません
SYSTEM_PROMPT = (
"あなたはTravelBot、フレンドリーで知識豊富な旅行アシスタントです。 "
"ユーザーが目的地を発見し、旅程を計画し、ホテルを推薦し、 "
"実用的な旅行のヒントを共有するのを助けます。応答は簡潔で熱心なものであるべきです。 "
"旅行に関係のない質問は丁重に会話を転換してください。"
)
MAX_TOKENS = 1024
ステージ1からの主な違い:
| パラメーター | ステージ1 | ステージ2 |
|---|---|---|
| OPENAI_API_KEY | LLMプロバイダーAPIキー | GUARD_API_KEYに置換 - ガードで認証する |
| BASE_URL | LLMプロバイダーエンドポイント | Catoガードプロキシエンドポイント |
| LLM_PROVIDER_API_KEY | 存在しなかった — OPENAI_API_KEYであった | LLM APIキー、今ではガードにリクエストヘッダーとして渡される |
ステップ4 — クライアントコードの更新
クライアントコードも対応するステージ2バージョンを取得します — bedrock_client_stage2.py。 ロジックはステージ1とほぼ同じですが、2つの追加があります。
- ガードAPIキーはガードで認証するために使用されます(
Authorizationヘッダー内)。 - LLM APIキーは追加ヘッダー(
x-cato-provider-api-key)として渡され、ガードがそれをLLMに転送できるようにします。 - セッションIDはヘッダー(
x-cato-session-id)として渡され、ガードは同じ会話からのリクエストをグループ化することができます – これは、アプリケーションロジックにすでに存在するsession_idに直接対応します。
# bedrock_client_stage2.py
openaiからOpenAIをインポートします。
config_stage2からGUARD_API_KEY、BASE_URL、MODEL_ID、LLM_PROVIDER_API_KEY、SYSTEM_PROMPT、MAX_TOKENSをインポートします。
クラスBedrockClient:
def __init__(self):
self._client = None
def _get_client(self) -> OpenAI:
if self._client is なし:
self._client = OpenAI(
api_key=GUARD_API_KEY,
base_url=BASE_URL,
default_headers={
"x-cato-provider-api-key": LLM_PROVIDER_API_KEY,
}
)
return self._client
def invoke(self, messages: list[dict], session_id: str = "") -> str:
all_messages = [{"role": "system", "content": SYSTEM_PROMPT}] + messages
response = self._get_client().chat.completions.create(
model=MODEL_ID,
messages=all_messages,
max_tokens=MAX_TOKENS,
extra_headers={
"x-cato-session-id": session_id,
}
)
return response.choices[0].message.content
フローの確認
設定とクライアントファイルが更新されると、アプリケーションはユーザーから見たときにステージ1と同じように動作するはずです。 TravelBotは従来通り旅行に関する質問に答えますが、現在はすべての対話がガードを通過します。
この時点でガードにはポリシールールが設定されていないため、いかなるトラフィックもブロックしたり変更したりしません。 しかし、すべての対話をログに記録しています。 これを確認するには、Cato管理画面アプリケーションでガードを開き、ガードログページを確認します。アプリケーションが使用されるとセッションが表示されるはずです。
これにより統合が正常に機能しており、ガードがトラフィックを受信していることが確認されます。
ステージ1からステージ2への変更概要
| 変更点 | ステージ1 | ステージ2 |
|---|---|---|
| トラフィックの流れる場所 | 直接LLMへ | Catoガードプロキシを通して |
| 認証 | コンフィグ内のLLM APIキー | 設定内のガードAPIキー;ヘッダーとして渡されるLLMキー |
| 可視性 | なし | Catoでのフルセッションログ |
| ポリシーの施行 | なし | 現在なし — ステージ3で追加 |
| ユーザーエクスペリエンス | 変更なし | 変更なし |
ステージ3 — ポリシールールの設定
このステージでカバーする内容
ステージ2ではガードを導入し、トラフィックが正常に流れていることを確認しました。 ガードはアクティブだが、まだルールを強制しておらず、トラフィックを観察するだけです。 このステージでは、ガードのインタラクションポリシーを設定します。特定のタイプのコンテンツが検出された場合にガードが行うべきことを指示するルールセットです。
このステージの終わりまでに、ガードはライブトラフィックに対して2つのルールを積極的に施行するようになります:
- ブロックと匿名化 — PIIやパスワードなどの情報を含むインタラクションのすべてを
- 医療アドバイスや健康関連データを含むすべてのインタラクションを監視する
注意: まず監視に設定して、予期した通りに検出されていることを確認したらブロックに移動することで、ルールをテストすることをお勧めします。
ガードのインタラクションポリシーとは?
ガードのインタラクションポリシーはAIセキュリティガードのルールベースです。 これをAIトラフィックのファイアウォールと考えてください。ネットワークパケットを検査する代わりに、AIインタラクションの内容を検査し、一致した場合にあなたが定義したアクションを適用します。
ポリシー内の各ルールは以下を指定します:
- 適用するガード
- 探すべきもの — エンジンプロファイルによって定義された検出カテゴリ(例えば、脱獄試行、PII、医療データ)、
- 一致が見つかった場合の対応方法 — ブロック、監視、匿名化してブロック、匿名化して監視
- 検査するトラフィックの方向 — ユーザーからのメッセージ、アシスタントからの応答、ツール入力、またはツール出力
注意すべき重要な動作:ガードのインタラクションポリシー内のルールは、ルールベース内での位置に関係なく評価されます。 1つのインタラクションに対して複数のルールが適用される場合は、より厳しいアクションが優先されます。 例として、1つのルールが監視を指し、もう一つがブロックを指している場合、ブロックのアクションが適用されます。
ステップ1 — ルール1の作成: 脱獄試行をブロック
最初に作成するルールは脱獄試行を対象とします — ユーザーがモデルの指示を無視させたり、その保護装置を迂回させようとする意図的な試みです。 TravelBotのような顧客向けアプリケーションにとって、これは重要なリスクです:ユーザーがモデルを既定の役割外で動作させようとしたり、漏洩すべきでない情報を引き出そうとすることがあります。
開始するには、ガードのポリシーページに移動してください。 メインナビゲーションメニューからAIセキュリティ > ガードのインタラクションポリシーを選択するか、ガードの概要ページから直接ポリシー管理をクリックして、アクティブルールセクションの下に移動します。
ガードのポリシーページから新規をクリックしてルールエディタを開き、以下を設定します:
一般
- 名前:
一部のトラフィックをブロック - 説明:
このルールは旅行ボットからの脱獄トラフィックをブロックします - 有効トグルをオンにします
ガード
E2Eサンプルユースケースを選択してください — このルールは特定のガードにスコープを限定し、アカウント内の他のガードに影響を与えません。
エンジンプロファイル
敏感識別子を選択します — これはプロンプトインジェクションの試行、脱獄パターン、およびモデルからシークレットや資格情報を引き出す試みを特定する検出カテゴリです
アクション
匿名化してブロックを選択します — ガードが一致を検出したときには、インタラクション内の任意の敏感なデータを匿名化し、完全にプロンプトをLLMが受信するのをブロックします
方向
ユーザーとツール入力をチェック — ルールはユーザーとツールの入力からのコンテンツに適用されます。 アシスタントからの応答やツールの出力は、このルールのスコープには含まれていません。
保存をクリックします。 ルールは未公開の更新に保存され、まだライブトラフィックには影響を与えません。
ステップ2 — ルール2の作成: 医療コンテンツを監視する
2つ目のルールは異なるアプローチを取ります。 トラフィックをブロックするのではなく、レビューのためにマークしている間にインタラクションを続行させます。 完全に悪意があるわけではないが可視性が必要なコンテンツに適しています。この場合は、医療アドバイスや健康関連データを含むインタラクションです。
TravelBotにおいて、ユーザーが医療旅行アドバイスを求めること(例えば、ワクチンの要件や目的地における健康上の注意事項)は本質的に有害ではありませんが、あなたの組織がコンプライアンスや品質目的で追跡したいと思うかもしれないコンテンツです。
ガードのポリシーページから再度新規をクリックして、以下を設定します:
- 一般
- 名前: 潜在的に有害なデータを監視する
- 説明: この設定により通信を通過させますが、インタラクションを監視します。
有効トグルをオンにしたままにします
ガード
E2Eサンプルユースケースを選択します
エンジンプロファイル
健康データの露出を選択します — これは医療指導、健康データ、または臨床情報を含むインタラクションを検出します
アクション
匿名化して監視を選択します — インタラクションはLLMが許可して通過し、応答は通常通りユーザーに返されます。 パーソナル化された情報は個人の詳細を保護するために匿名化されます。 インタラクションはレビューのためにCatoにログを記録されます。
方向
- 4つの方向すべてをチェック:
ユーザー、アシスタント、ツール入力、ツール出力— このルールは全方向のトラフィックを監視し、会話の両側への完全な可視性を提供します
保存をクリックします。
ステップ3 — ポリシーの公開
両方のルールを保存した後、ガードのポリシーページには未公開の更新ステータスと、右上に**公開(2)**ボタンが表示され、2つのルールがライブになる準備が整っていることを示しています。
重要: あなたが公開するまで、アクティブなポリシーは変更されません。 あなたのルールはドラフト状態にあり、ライブトラフィックには反映されません。 これにより、変更が適用される前に内容を確認する機会が得られます。
準備が整ったら、**公開(2)**をクリックしてください。 両方のルールは直ちにアクティブになり、ガードはすべての受信トラフィックに対して施行を開始します。

現在ガードが行っていること
両方のルールが公開されることで、E2Eサンプルユースケースガードを通過するすべてのインタラクションがポリシーに対して評価されます。 これが実際にはどのように見えるか:
ユーザーがTravelBotにメッセージを送信します。 メッセージがLLMに到達する前に、ガードが両方のルールに対して検査します:
- メッセージが脱獄パターンや秘密を引き出す試みを含んでいる場合、ガードは匿名化してブロックします。 LLMはメッセージを決して確認せず、ユーザーにはブロックされた応答が返されます。
- メッセージが医療アドバイスや健康関連コンテンツを含んでいる場合、ガードはそれを通過させますが、レビューのためにインタラクションをログに記録します。
- メッセージがどちらのルールにも一致しない場合、それはLLMに変わらず通過します。
同じ評価がアシスタントからの応答、ツールの入力、ツールの出力にも適用され、各ルールに設定された方向に応じて行われます。
ルールがアクティブであることの確認
ルールがアクティブでガードに適用されていることを確認するために、ガードの概要ページに移動してください。 アクティブルールの下に両方のルールがリストアップされているのを見ることができます。 インタラクションの時間経過チャートと違反の内訳パネルは、ガードを通過するトラフィックと検出が発生するにつれてデータをポピュレートし始めます。
また、ガードログに移動し、個々のセッションを確認し、どのルールが発火したかを確認し、フラグ付けされたインタラクションの詳細を検査することもできます。ただし、敏感なコンテンツを表示する権限を持っている必要があります。
概要
| ルール | エンジンプロファイル | アクション | 方向 |
|---|---|---|---|
| 一部のトラフィックをブロック | シークレット&脱獄 | 匿名化してブロック | ユーザー、ツール入力 |
| 潜在的に有害なデータを監視する | 医療アドバイスまたはデータ | モニタ | 全方向 |
これら2つのルールの配置により、アプリケーションは現在アクティブなセキュリティ施行を持つことになります。 悪意のあるプロンプト試行はモデルに到達する前にブロックされ、健康関連のインタラクションはセキュリティチームに対して可視化されます。これにはアプリケーションコードへの変更や合法的なインタラクションに対するエンドユーザーエクスペリエンスへの影響はありません。
これでCato AIセキュリティガードを使用してカスタムAIアプリケーションを保護するエンドツーエンドガイドが完了しました。