Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 117 additions & 68 deletions src/content/docs/ai-gateway/observability/logging/logpush.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ sidebar:
text: Beta
---

import { Render } from "~/components";
import { Render, Tabs, TabItem } from "~/components";

AI Gateway allows you to securely export logs to an external storage location, where you can decrypt and process them.
You can toggle Logpush on and off in the [Cloudflare dashboard](https://dash.cloudflare.com) settings.
Expand Down Expand Up @@ -37,7 +37,9 @@ To configure Logpush for AI Gateway, follow these steps:

## 1. Generate an RSA key pair locally

You need to generate a key pair to encrypt and decrypt the logs. This script will output your RSA privateKey and publicKey. Keep the private key secure, as it will be used to decrypt the logs. Below is a sample script to generate the keys using Node.js.
You need to generate a key pair to encrypt and decrypt the logs. This script will output your RSA privateKey and publicKey. Keep the private key secure, as it will be used to decrypt the logs. Below is a sample script to generate the keys using Node.js and OpenSSL.

<Tabs syncKey="JSPlusSSL"> <TabItem label="Javascript">

```js title="JavaScript"
const crypto = require("crypto");
Expand All @@ -64,6 +66,23 @@ Run the script by executing the below code on your terminal. Replace `file name`
node {file name}
```

</TabItem> <TabItem label="OpenSSL">

1. Generate private key:
Use the following command to generate a RSA private key:

```bash
openssl genpkey -algorithm RSA -out private_key.pem -pkeyopt rsa_keygen_bits:4096
```

2. Generate public key:
After generating the private key, you can extract the corresponding public key using:

```bash
openssl rsa -pubout -in private_key.pem -out public_key.pem
```

</TabItem> </Tabs>

## 2. Upload public key to gateway settings

Expand All @@ -79,6 +98,10 @@ After configuring Logpush, logs will be sent encrypted using the public key you

## 5. Decrypt logs

To decrypt the encrypted log bodies and metadata from AI Gateway, you can use the following Node.js script or OpenSSL:

<Tabs syncKey="JSPlusSSL"> <TabItem label="Javascript">

To decrypt the encrypted log bodies and metadata from AI Gateway, download the logs to a folder, in this case its named `my_log.log.gz`.

Then copy this javascript file into the same folder and place your private key in the top variable.
Expand All @@ -96,81 +119,81 @@ 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;
}
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);
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();
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("--");
});
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()
run();
```

Run the script by executing the below code on your terminal. Replace `file name` with the name of your JavaScript file.
Expand All @@ -179,7 +202,33 @@ Run the script by executing the below code on your terminal. Replace `file name`
node {file name}
```

## Script Explanation

The script reads the encrypted log file `(my_log.log.gz)`, decrypts the metadata, request body, and response body, and prints the decrypted data.
Ensure you replace the `privateKey` variable with your actual private RSA key that you generated in step 1.

</TabItem> <TabItem label="OpenSSL">

1. Decrypt the encrypted log file using the private key.

Assuming that the logs were encrypted with the public key (for example `public_key.pem`), you can use the private key (`private_key.pem`) to decrypt the log file.

For example, if the encrypted logs are in a file named `encrypted_logs.bin`, you can decrypt it like this:

```bash
openssl rsautl -decrypt -inkey private_key.pem -in encrypted_logs.bin -out decrypted_logs.txt
```

- `-decrypt` tells OpenSSL that we want to decrypt the file.
- `-inkey private_key.pem` specifies the private key that will be used to decrypt the logs.
- `-in encrypted_logs.bin` is the encrypted log file.
- `-out decrypted_logs.txt`decrypted logs will be saved into this file.

2. View the decrypted logs
Once decrypted, you can view the logs by simply running:

```bash
cat decrypted_logs.txt
```

This command will output the decrypted logs to the terminal.

</TabItem> </Tabs>
Loading