Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

AI Gateway と Zero Trust で AI エージェントラッパーを作成して保護する

最終更新 Markdown で表示Agent セットアップ

このチュートリアルでは、Cloudflare AI Gateway と Zero Trust を使い、AI エージェント向けの実用的で安全なウェブサイトラッパーを作成します。Cloudflare Zero Trust の管理者は、Cloudflare Access でラッパーへのアクセスを保護できます。加えて、Gateway ポリシー でユーザーと AI エージェントのやり取りを制御できます。たとえば Browser Isolation で隔離ブラウザー上で AI エージェントを実行する、Data Loss Prevention プロファイルで機密データの共有を防ぐ、社内ガイドラインに反する回答を避けるためのコンテンツスキャン、などです。特定の AI プロバイダー(ChatGPT Enterprise など)のエンタープライズプランがある場合、AI エージェントラッパーはテナント制御を適用する手段にもなります。

このチュートリアルでは、AI エージェントの例として ChatGPT を使います。

始める前に

次を用意してください。

1. AI gateway を作成する

まず、AI アプリを制御する AI gateway を作成します。

  1. Cloudflare ダッシュボードAI Gateway ページを開きます。

    AI Gateway を開く ↗
  2. Create Gateway を選択します。

  3. ゲートウェイに名前を付けます。

  4. Create を選択します。

  5. ゲートウェイの希望するオプションを設定します。

  6. AI プロバイダーを接続 し、AI gateway 経由で選んだ AI エージェントへクエリをプロキシします。

  7. (任意)Authenticated Gateway を有効にします。Authenticated Gateway は、リクエストヘッダー cf-aig-authorization のトークンを必須にし、AI gateway を安全に呼び出せるようにします。

    1. AI > AI Gateway を開きます。
    2. AI gateway を選び、Settings を開きます。
    3. Authenticated Gateway をオンにし、Confirm を選びます。
    4. Create authentication token を選び、Create an AI Gateway authentication token を選択します。
    5. トークンを設定し、トークン値をコピーします。Worker を作成するとき、AI gateway の呼び出しでこのトークンを渡します。

詳細は AI Gateway の始め方 を参照してください。

2.(任意)Guardrails で安全でないコンテンツや不適切なコンテンツをブロックする

Guardrails は AI Gateway の組み込みセキュリティ機能です。選んだカテゴリに基づき、プロンプトと応答の安全でないコンテンツや不適切なコンテンツを Cloudflare が識別します。

  1. Cloudflare ダッシュボードで AI Gateway ページを開きます。

    AI Gateway を開く ↗
  2. AI gateway を選びます。

  3. Guardrails を開きます。

  4. Guardrails をオンにします。

  5. Change を選び、プロンプトと応答の両方でフィルタするカテゴリを設定します。

3. ラッパーを提供する Worker を作る

1. Worker を作成する

Worker を作るには、Wrangler でローカルに作るか、ダッシュボード でリモートに作るかを選びます。

  1. ターミナルで Cloudflare アカウントにログインします。

    wrangler login
  2. プロジェクトをローカルで初期化します。

    mkdir ai-agent-wrapper
    cd ai-agent-wrapper
    wrangler init
  3. Wrangler 設定ファイルを作成します。

    name = "ai-agent-wrapper"
    main = "src/index.js"
    compatibility_date = "2023-10-30"
    
    [vars]
    # Add any environment variables here
  4. AI プロバイダーの API キーを シークレット として追加します。

    wrangler secret put <OPENAI_API_KEY>

これで、Wrangler が作成した index.js ファイルを使って Worker を作れます。

  1. Cloudflare ダッシュボードで Workers & Pages ページを開きます。

    Workers & Pages を開く ↗
  2. Create を選択します。

  3. WorkersHello world テンプレートを選びます。

  4. Worker に名前を付け、Deploy を選択します。

  5. Worker を選び、Settings タブを開きます。

  6. Variables and Secrets を開き、Add を選択します。

  7. 種類に Secret を選び、シークレット名(例: OPENAI_API_KEY)を付け、Value に AI プロバイダーの API キーを入力します。

Worker ページで Edit code を選び、オンラインコードエディターで Worker を作れます。

2. Worker を実装する

次は、AI Gateway 配下の AI プロバイダーとやり取りできる簡単なフロントエンドを提供する、スターター Worker の例です。この例では AI プロバイダーとして OpenAI を使います。

export default {
	async fetch(request, env) {
		if (request.url.endsWith("/api/chat")) {
			if (request.method === "POST") {
				try {
					const { messages } = await request.json();

					const response = await fetch(
						"https://gateway.ai.cloudflare.com/v1/$ACCOUNT_ID/$GATEWAY_ID/openai/chat/completions",
						{
							method: "POST",
							headers: {
								"Content-Type": "application/json",
								Authorization: `Bearer ${env.OPENAI_API_KEY}`,
							},
							body: JSON.stringify({
								model: "gpt-4o-mini",
								messages: messages,
							}),
						},
					);

					if (!response.ok) {
						throw new Error(`AI Gateway Error: ${response.status}`);
					}

					const result = await response.json();
					return new Response(
						JSON.stringify({
							response: result.choices[0].message.content,
						}),
						{
							headers: { "Content-Type": "application/json" },
						},
					);
				} catch (error) {
					return new Response(JSON.stringify({ error: error.message }), {
						status: 500,
						headers: { "Content-Type": "application/json" },
					});
				}
			}
			return new Response("Method not allowed", { status: 405 });
		}

		return new Response(HTML, {
			headers: { "Content-Type": "text/html" },
		});
	},
};

const HTML = `<!DOCTYPE html>
  <html lang="en" data-theme="dark">
  <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>ChatGPT Wrapper</title>
      <style>
          :root {
              --background-color: #1a1a1a;
              --chat-background: #2d2d2d;
              --text-color: #ffffff;
              --input-border: #404040;
              --message-ai-background: #404040;
              --message-ai-text: #ffffff;
          }

          body {
              font-family: system-ui, sans-serif;
              margin: 0;
              padding: 20px;
              background: var(--background-color);
              display: flex;
              flex-direction: column;
              align-items: center;
              gap: 20px;
              color: var(--text-color);
          }

          .chat-container {
              width: 100%;
              max-width: 800px;
              background: var(--chat-background);
              border-radius: 10px;
              box-shadow: 0 2px 10px rgba(0,0,0,0.1);
              height: 80vh;
              display: flex;
              flex-direction: column;
          }

          .chat-header {
              padding: 15px 20px;
              border-bottom: 1px solid var(--input-border);
              background: var(--chat-background);
              border-radius: 10px 10px 0 0;
              text-align: center;
          }

          .chat-messages {
              flex-grow: 1;
              overflow-y: auto;
              padding: 20px;
          }

          .message {
              margin-bottom: 20px;
              padding: 10px 15px;
              border-radius: 10px;
              max-width: 80%;
          }

          .user-message {
              background: #007AFF;
              color: white;
              margin-left: auto;
          }

          .ai-message {
              background: var(--message-ai-background);
              color: var(--message-ai-text);
          }

          .input-container {
              padding: 20px;
              border-top: 1px solid var(--input-border);
              display: flex;
              gap: 10px;
          }

          input {
              flex-grow: 1;
              padding: 10px;
              border: 1px solid var(--input-border);
              border-radius: 5px;
              font-size: 16px;
              background: var(--chat-background);
              color: var(--text-color);
          }

          button {
              padding: 10px 20px;
              background: #007AFF;
              color: white;
              border: none;
              border-radius: 5px;
              cursor: pointer;
              font-size: 16px;
          }

          button:disabled {
              background: #ccc;
          }

          .error {
              color: red;
              padding: 10px;
              text-align: center;
          }
      </style>
  </head>
  <body>
      <div class="chat-container">
          <div class="chat-header">
              <h2>AI Assistant</h2>
          </div>
          <div class="chat-messages" id="messages"></div>
          <div class="input-container">
              <input type="text" id="userInput" placeholder="Type your message..." />
              <button onclick="sendMessage()" id="sendButton">Send</button>
          </div>
      </div>

      <script>
          let messages = [];
          const messagesDiv = document.getElementById('messages');
          const userInput = document.getElementById('userInput');
          const sendButton = document.getElementById('sendButton');

          userInput.addEventListener('keypress', (e) => {
              if (e.key === 'Enter') sendMessage();
          });

          async function sendMessage() {
              const content = userInput.value.trim();
              if (!content) return;

              userInput.disabled = true;
              sendButton.disabled = true;

              messages.push({ role: 'user', content });
              appendMessage('user', content);
              userInput.value = '';

              try {
                  const response = await fetch('/api/chat', {
                      method: 'POST',
                      headers: { 'Content-Type': 'application/json' },
                      body: JSON.stringify({
                          messages
                      })
                  });

                  if (!response.ok) {
                      throw new Error('API request failed');
                  }

                  const result = await response.json();
                  const aiMessage = result.response;

                  messages.push({ role: 'assistant', content: aiMessage });
                  appendMessage('ai', aiMessage);
              } catch (error) {
                  appendMessage('ai', 'Sorry, there was an error processing your request.');
                  console.error('Error:', error);
              }

              userInput.disabled = false;
              sendButton.disabled = false;
              userInput.focus();
          }

          function appendMessage(role, content) {
              const messageDiv = document.createElement('div');
              messageDiv.className = 'message ' + role + '-message';
              messageDiv.textContent = content;
              messagesDiv.appendChild(messageDiv);
              messagesDiv.scrollTop = messagesDiv.scrollHeight;
          }
      </script>
  </body>
  </html>`;

AI Gateway エンドポイントのアカウント ID とゲートウェイ ID は置き換えてください。Workers の 環境変数 または シークレット として追加できます。AI gateway 作成時に Authenticated Gateway を使った場合は、トークンもシークレットとして追加し、cf-aig-authorization ヘッダーで AI gateway に渡してください。

3. Worker を公開する

Worker のコードが完成したら、Cloudflare Access で制御できるホスト名で Worker に到達できるようにします。

Wrangler 設定ファイルを編集し、カスタムホスト名だけで Worker にアクセスできるように次の情報を追加します。

name = "ai-agent-wrapper"
main = "src/index.js"
compatibility_date = "2023-10-30"
workers_dev = false

+# Replace with your custom domain
+routes = [
+  { pattern = "<YOUR_CUSTOM_DOMAIN>", custom_domain = true }
+]

[vars]
# Add any environment variables here

Worker を公開するには wrangler deploy を実行します。

Cloudflare ダッシュボードの コードエディター でリモート作成した場合は、Deploy を選んでデプロイできます。

カスタムホスト名からのみ Worker にアクセスできるようにするには:

  1. Cloudflare ダッシュボードで Workers & Pages ページを開きます。

    Workers & Pages を開く ↗
  2. Worker を選びます。

  3. Settings を開きます。

  4. Domains & RoutesAdd を選択します。

  5. Custom domain を選びます。

  6. 希望するカスタムドメイン名を入力します。

  7. Add domain を選択します。

これで Worker は到達可能なパブリックホスト名の背後にあります。workers.devPreview URLs の両方をオフにし、カスタムドメインだけでアクセスできるようにしてください。

4. Access でラッパーを保護する

信頼できるユーザーだけが AI エージェントラッパーにアクセスできるようにするには:

  1. Cloudflare ダッシュボードZero Trust > Access controls > Applications を開きます。
  2. Create new application を選択します。
  3. Self-hosted and private を選択します。
  4. Add public hostname を選び、Worker に設定したカスタムドメインを入力します。
  5. Worker 向けに Access アプリケーションを設定 します。
  6. アプリケーションに接続できるユーザーを制御する Access ポリシー を追加します。

これで、Access ポリシーに一致したユーザーだけが AI ラッパーにアクセスできます。

5. Gateway で公開 AI エージェントへのアクセスをブロックする

許可していない公開 AI エージェントへのアクセスは、Gateway の HTTP ポリシー でブロックできます。

  1. Cloudflare ダッシュボードZero Trust > Traffic policies > Firewall policies > HTTP を開きます。

  2. Add a policy を選択します。

  3. 次のポリシーを追加します。

    Selector Operator Value Action
    Content Categories in Artificial Intelligence Block
  4. Create policy を選択します。

これで、管理対象エンドポイントから公開 AI エージェントへアクセスできなくなります。

あるいは、カスタムブロックメッセージリダイレクト、または AI エージェントラッパーへ誘導する ユーザー通知 を表示して、公開 AI エージェントの利用を防げます。

6. Data Loss Prevention と Clientless Browser Isolation を適用する

AI エージェントラッパーへのアクセスを制御できるようになったので、Data Loss Prevention(DLP)や Clientless Web Isolation などの追加のセキュリティ手段で、AI エージェントと共有するデータを保護・制御できます。

Data Loss Prevention プロファイルを適用する

Data Loss Prevention(DLP) を使い、ユーザーが AI エージェントへ機密データを送らないようにできます。

  1. Cloudflare ダッシュボードZero Trust > Data loss prevention > Profiles を開きます。

  2. 適用したい DLP プロファイル が正しく設定されていることを確認します。

  3. ラッパーのホスト名に DLP プロファイルを適用する HTTP ポリシーを追加します。例:

    Selector Operator Value Logic Action
    Host is ai-wrapper.example.com And Block
    DLP Profile in AI DLP profile
  4. Create policy を選択します。

DLP ポリシーの作成について詳しくは、HTTP トラフィックをスキャンする を参照してください。

クライアントレスの隔離ブラウザーで実行する

ラッパーをセルフホスト Access アプリケーションとして公開したので、Access ポリシー を作成してアプリケーションに設定し、ユーザー向けの 隔離セッション で実行できます。

  1. Cloudflare OneBrowser isolation > Browser isolation settings を開きます。
  2. Allow users to open a remote browser without the device client をオンにします。
  1. Access controls > Policies を開きます。
  2. Add a policy を選択します。
  3. ActionAllow にします。
  4. Add rules で、アプリケーションを隔離する対象を定義する ID ルールを追加します。
  5. Additional settings (optional)Isolate application をオンにします。

Access ポリシーを作成したら、ラッパーに紐づけます。

  1. Access controls > Applications を開きます。
  2. ラッパーアプリケーションを選び、Configure を選択します。
  3. PoliciesSelect existing policies を選択します。
  4. 先に作成した Access ポリシーを選びます。
  5. Confirm を選び、Save を選択します。

Clientless Web Isolation のトラフィックには Gateway HTTP ポリシーが適用されるため、設定した DLP プロファイルは隔離セッションにも適用されます。

Access アプリケーションの隔離について詳しくは、セルフホストアプリケーションを隔離する を参照してください。

追加の利点

AI エージェントへのアクセス保護に Cloudflare を採用すると、可視性と設定の柔軟さが向上します。

可視性

Zero Trust はすべての Access イベントDLP 検出 を記録します。加えて、AI Gateway はユーザープロンプト、モデル応答、トークン使用量、コストの 可視性 を提供します。

ログは Logpush で外部プロバイダーへエクスポートできます。

設定の柔軟さ

ラッパーを 別の AI プロバイダー に切り替えたり、複数の AI プロバイダーから選べるようにしたりできます。Workers AI で Cloudflare のグローバルネットワーク上で直接動く AI モデルも含められます。これにより、ユーザー体験や既存のアクセス制御に影響を与えずに、AI 利用コストを管理したり、新しいモデルを採用したりできます。

役に立ちましたか?