AI Gateway では、ログを外部ストレージへ安全にエクスポートできます。保存先で復号して処理します。 Workers Logpush のオン / オフは、Cloudflare ダッシュボード ↗ の設定で切り替えられます。この機能は Workers Paid プランで利用できます。料金は 料金 を参照してください。
このガイドでは、AI Gateway 向けに Workers Logpush を設定し、暗号化用の RSA 鍵ペアを生成し、受信したログを復号する手順を説明します。
ゲートウェイごとに最大 1,000 万件のログを保存できます。上限に達すると、新しいログは保存されず、Workers Logpush でもエクスポートされません。保存とエクスポートを続けるには、古いログを削除して空きを作ります。Workers Logpush の上限はジョブ 4 件、ログあたりの最大リクエストサイズは 1 MB です。
効率と安全性を両立するため、ハイブリッド暗号化を使います。まずログごとに AES キーを生成します。この AES キーがデータの本体を暗号化します。大量データを速く、安全に扱うために選んでいます。
この AES キーを安全に共有するため、RSA 暗号化を使います。AES キー自体は小さいですが、受信者へ安全に渡す必要があります。受信者の RSA 公開鍵でこのキーを暗号化します。RSA の鍵配布の強みを使い、対応する RSA 秘密鍵を持つ人だけが AES キーを復号して使えます。
暗号化後、AES で暗号化したデータと、RSA で暗号化した AES キーをまとめて送ります。受信側は RSA 秘密鍵で AES キーを復号します。AES キーが使えれば、本体データの復号は簡単です。
この方式は、データ暗号化の AES の効率と、RSA の安全な鍵交換を組み合わせます。データの完全性、機密性、性能を、ライフサイクル全体で維持します。
AI Gateway 向けに Workers Logpush を設定する手順は次のとおりです。
ログの暗号化と復号に使う鍵ペアを生成します。このスクリプトは RSA の privateKey と publicKey を出力します。秘密鍵はログの復号に使うため、安全に保管してください。以下は、Node.js と OpenSSL で鍵を生成するサンプルです。
const crypto = require("crypto");
const { privateKey, publicKey } = crypto.generateKeyPairSync("rsa", {
modulusLength: 4096,
publicKeyEncoding: {
type: "spki",
format: "pem",
},
privateKeyEncoding: {
type: "pkcs8",
format: "pem",
},
});
console.log(publicKey);
console.log(privateKey);ターミナルで次のコマンドを実行します。file name を JavaScript ファイル名に置き換えます。
node {file name}-
秘密鍵を生成します。 次のコマンドで RSA 秘密鍵を生成します。
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:4096 -
公開鍵を生成します。 秘密鍵を生成したあと、対応する公開鍵を次のコマンドで取り出します。
openssl rsa -pubout -in private_key.pem -out public_key.pem
鍵ペアを生成したら、公開鍵を AI Gateway の設定にアップロードします。この鍵でログを暗号化します。Workers Logpush を有効にするには、そのゲートウェイでログが有効になっている必要があります。
公開鍵をアップロードすると、そのゲートウェイで Workers Logpush が有効になります。ただし、送信先を指定した Logpush ジョブを作成して有効にするまで、ログはエクスポートされません。両方の手順が必要です。
Logpush ジョブを作成するには、送信先を選び、送信先を有効にする の手順に従います。たとえば Cloudflare R2 へエクスポートする場合は、Cloudflare R2 を有効にする を参照してください。ジョブの設定では、AI Gateway データセットを選びます。
Workers Logpush を設定すると、アップロードした公開鍵で暗号化されたログが送られます。データにアクセスするには、秘密鍵で復号します。ログは、選んだオブジェクトストレージへ送られます。
AI Gateway から届いた暗号化済みのログ本体とメタデータを復号するには、次の Node.js スクリプトまたは OpenSSL を使えます。
AI Gateway から届いた暗号化済みのログ本体とメタデータを復号するには、ログをフォルダーへダウンロードします。この例では my_log.log.gz という名前です。
同じフォルダーにこの JavaScript ファイルを置き、先頭の変数に秘密鍵を入れます。
const privateKeyStr = `-----BEGIN RSA PRIVATE KEY-----
....
-----END RSA PRIVATE KEY-----`;
const crypto = require("crypto");
const privateKey = crypto.createPrivateKey(privateKeyStr);
const fs = require("fs");
const zlib = require("zlib");
const readline = require("readline");
async function importAESGCMKey(keyBuffer) {
try {
// Ensure the key length is valid for AES
if ([128, 192, 256].includes(256)) {
return await crypto.webcrypto.subtle.importKey(
"raw",
keyBuffer,
{
name: "AES-GCM",
length: 256,
},
true, // Whether the key is extractable (true in this case to allow for export later if needed)
["encrypt", "decrypt"], // Use for encryption and decryption
);
} else {
throw new Error("Invalid AES key length. Must be 128, 12, or 256 bits.");
}
} catch (error) {
console.error("Failed to import key:", error);
throw error;
}
}
async function decryptData(encryptedData, aesKey, iv) {
const decryptedData = await crypto.subtle.decrypt(
{ name: "AES-GCM", iv: iv },
aesKey,
encryptedData,
);
return new TextDecoder().decode(decryptedData);
}
async function decryptBase64(privateKey, data) {
if (data.key === undefined) {
return data;
}
const aesKeyBuf = crypto.privateDecrypt(
{
key: privateKey,
oaepHash: "SHA256",
},
Buffer.from(data.key, "base64"),
);
const aesKey = await importAESGCMKey(aesKeyBuf);
const decryptedData = await decryptData(
Buffer.from(data.data, "base64"),
aesKey,
Buffer.from(data.iv, "base64"),
);
return decryptedData.toString();
}
async function run() {
let lineReader = readline.createInterface({
input: fs.createReadStream("my_log.log.gz").pipe(zlib.createGunzip()),
});
lineReader.on("line", async (line) => {
line = JSON.parse(line);
const { Metadata, RequestBody, ResponseBody, ...remaining } = line;
console.log({
...remaining,
Metadata: await decryptBase64(privateKey, Metadata),
RequestBody: await decryptBase64(privateKey, RequestBody),
ResponseBody: await decryptBase64(privateKey, ResponseBody),
});
console.log("--");
});
}
run();ターミナルで次のコマンドを実行します。file name を JavaScript ファイル名に置き換えます。
node {file name}スクリプトは暗号化されたログファイル (my_log.log.gz) を読み、メタデータ、リクエストボディ、レスポンスボディを復号して、復号後のデータを出力します。
privateKey 変数は、手順 1 で生成した実際の RSA 秘密鍵に置き換えてください。
- 秘密鍵を使って、暗号化されたログファイルを復号します。
ログが公開鍵(例: public_key.pem)で暗号化されている場合、秘密鍵(private_key.pem)でログファイルを復号できます。
たとえば、暗号化されたログが encrypted_logs.bin というファイルにある場合、次のように復号します。
openssl rsautl -decrypt -inkey private_key.pem -in encrypted_logs.bin -out decrypted_logs.txt-decryptは、ファイルを復号することを OpenSSL に指示します。-inkey private_key.pemは、ログの復号に使う秘密鍵を指定します。-in encrypted_logs.binは、暗号化されたログファイルです。-out decrypted_logs.txtは、復号したログの保存先です。
- 復号したログを表示します。 復号後、次のコマンドでログを表示できます。
cat decrypted_logs.txtこのコマンドは、復号したログをターミナルに出力します。