Skip to content

Commit 0fd65db

Browse files
committed
Merge branch 'main' into cache-forceProtectionOff
2 parents 1e5dd58 + f8be7e4 commit 0fd65db

27 files changed

+359
-122
lines changed

.devcontainer/devcontainer.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
2+
{
3+
"name": "Zen Node.js",
4+
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
5+
"image": "mcr.microsoft.com/devcontainers/typescript-node:22",
6+
7+
// Features to add to the dev container. More info: https://containers.dev/features.
8+
"features": {
9+
"ghcr.io/devcontainers/features/docker-in-docker:2": {},
10+
"ghcr.io/devcontainers/features/rust:1": {}
11+
},
12+
13+
// Configure tool-specific properties.
14+
"customizations": {
15+
// Configure properties specific to VS Code.
16+
"vscode": {
17+
"settings": {},
18+
"extensions": [
19+
"ms-azuretools.vscode-docker",
20+
"dbaeumer.vscode-eslint",
21+
"esbenp.prettier-vscode",
22+
"YoavBls.pretty-ts-errors",
23+
"rust-lang.rust-analyzer"
24+
]
25+
}
26+
},
27+
28+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
29+
"forwardPorts": [3000, 4000],
30+
31+
// Use 'portsAttributes' to set default properties for specific forwarded ports.
32+
// More info: https://containers.dev/implementors/json_reference/#port-attributes
33+
"portsAttributes": {},
34+
35+
// Use 'postCreateCommand' to run commands after the container is created.
36+
"postCreateCommand": "./.devcontainer/postCreateCommand.sh"
37+
38+
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
39+
// "remoteUser": "root"
40+
}

.devcontainer/postCreateCommand.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/bash
2+
3+
# Update
4+
sudo apt update -y && sudo apt upgrade -y
5+
rustup update
6+
source /usr/local/share/nvm/nvm.sh
7+
nvm install --lts
8+
nvm use --lts
9+
npm update -g
10+
11+
# Install WASM pack
12+
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
13+
14+
# Install k6
15+
## k6 installation -- arm machines
16+
if [ "$(uname -m)" = "aarch64" ]; then
17+
K6_TAR_LINK=https://github.com/grafana/k6/releases/download/v0.58.0/k6-v0.58.0-linux-arm64.tar.gz
18+
curl -OL $K6_TAR_LINK
19+
tar -xzf k6-v0.58.0-linux-arm64.tar.gz
20+
sudo mv k6-v0.58.0-linux-arm64/k6 /usr/local/bin/k6
21+
rm -rf k6-v0.58.0-linux-arm64*
22+
else ## k6 installation -- other architectures
23+
sudo gpg -k
24+
sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
25+
echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
26+
sudo apt-get update -y
27+
sudo apt-get install k6 -y
28+
fi
29+
30+
# Install wrk, sqlite3
31+
sudo apt install wrk sqlite3 -y
32+
33+
# Install npm packages, build and run containers
34+
npm i
35+
npm run build
36+
npm run containers

benchmarks/hono-pg/benchmark.js

Lines changed: 51 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -4,53 +4,55 @@ const { promisify } = require("util");
44
const exec = promisify(require("child_process").exec);
55
const spawn = require("child_process").spawn;
66

7-
async function startServer(firewallEnabled) {
8-
console.log("Spawning server. Firewall enabled:", firewallEnabled);
7+
async function runBenchmarks() {
8+
console.log("Spawning servers...");
99

1010
let env = { ...process.env, AIKIDO_CI: "true" };
11-
if (firewallEnabled) {
12-
env = {
11+
12+
const serverWithFirewall = spawn("node", ["server.js", "4000"], {
13+
env: {
1314
...env,
1415
AIKIDO_BLOCKING: "true",
1516
NODE_OPTIONS: "-r @aikidosec/firewall",
16-
};
17-
}
17+
},
18+
cwd: join(__dirname, "app"),
19+
});
1820

19-
const server = spawn("node", ["server.js", "4000"], {
20-
env,
21+
const serverWithoutFirewall = spawn("node", ["server.js", "4001"], {
22+
env: {
23+
...env,
24+
},
2125
cwd: join(__dirname, "app"),
2226
});
2327

2428
try {
25-
server.on("error", (err) => {
26-
throw err;
27-
});
28-
29-
server.on("close", () => {
30-
console.log("Closing test server...");
31-
});
32-
33-
server.stderr.on("data", (data) => {
34-
throw new Error(data.toString());
35-
});
29+
for (const server of [serverWithFirewall, serverWithoutFirewall]) {
30+
server.on("error", (err) => {
31+
throw err;
32+
});
33+
34+
server.stderr.on("data", (data) => {
35+
throw new Error(data.toString());
36+
});
37+
}
3638

37-
console.log("Waiting for server to start...");
38-
await new Promise((resolve) => setTimeout(resolve, 2500));
39+
console.log("Waiting for servers to start...");
40+
await new Promise((resolve) => setTimeout(resolve, 3000));
3941

4042
console.log("Running k6...");
4143
const result = await exec("k6 run requests.mjs");
4244
if (result.stderr) {
4345
throw new Error(result.stderr);
4446
}
4547

46-
server.kill();
47-
// Wait for the server to close
48-
await new Promise((resolve) => server.on("close", resolve));
48+
serverWithFirewall.kill();
49+
serverWithoutFirewall.kill();
4950
} catch (error) {
5051
console.error(error);
5152
return false;
5253
} finally {
53-
server.kill();
54+
serverWithFirewall.kill();
55+
serverWithoutFirewall.kill();
5456
return true;
5557
}
5658
}
@@ -74,69 +76,52 @@ async function getResult() {
7476
process.exit(1);
7577
}
7678

77-
// Start with firewall enabled
78-
if (!(await startServer(true))) {
79-
process.exit(1);
80-
}
81-
82-
const resultWithFirewall = await getResult();
83-
84-
// Start with firewall disabled
85-
if (!(await startServer(false))) {
79+
if (!(await runBenchmarks())) {
8680
process.exit(1);
8781
}
8882

89-
const resultWithoutFirewall = await getResult();
83+
const results = await getResult();
9084

9185
console.log("====================================");
92-
console.log("Results with firewall enabled:");
93-
const customGetFirewall =
94-
resultWithFirewall.metrics.custom_get_duration.values;
86+
console.log("Results with Zen enabled:");
87+
const getResultsWithZen = results.metrics.get_with_zen.values;
9588
console.log(
96-
`GET duration: avg=${customGetFirewall.avg}ms, min=${customGetFirewall.min}ms, max=${customGetFirewall.max}ms`
89+
`GET duration: avg=${getResultsWithZen.avg}ms, min=${getResultsWithZen.min}ms, max=${getResultsWithZen.max}ms`
9790
);
98-
const customPostFirewall =
99-
resultWithFirewall.metrics.custom_post_duration.values;
91+
const postResultsWithZen = results.metrics.post_with_zen.values;
10092
console.log(
101-
`POST duration: avg=${customPostFirewall.avg}ms, min=${customPostFirewall.min}ms, max=${customPostFirewall.max}ms`
102-
);
103-
console.log(
104-
`Total requests: ${resultWithFirewall.metrics.http_reqs.values.count}`
93+
`POST duration: avg=${postResultsWithZen.avg}ms, min=${postResultsWithZen.min}ms, max=${postResultsWithZen.max}ms`
10594
);
10695

10796
console.log("------------------------------------");
108-
console.log("Results with firewall disabled:");
109-
const customGetNoFirewall =
110-
resultWithoutFirewall.metrics.custom_get_duration.values;
111-
console.log(
112-
`GET duration: avg=${customGetNoFirewall.avg}ms, min=${customGetNoFirewall.min}ms, max=${customGetNoFirewall.max}ms`
113-
);
114-
const customPostNoFirewall =
115-
resultWithoutFirewall.metrics.custom_post_duration.values;
97+
console.log("Results with Zen disabled:");
98+
const getResultsWithoutZen = results.metrics.get_without_zen.values;
11699
console.log(
117-
`POST duration: avg=${customPostNoFirewall.avg}ms, min=${customPostNoFirewall.min}ms, max=${customPostNoFirewall.max}ms`
100+
`GET duration: avg=${getResultsWithoutZen.avg}ms, min=${getResultsWithoutZen.min}ms, max=${getResultsWithoutZen.max}ms`
118101
);
102+
const postResultsWithoutZen = results.metrics.post_without_zen.values;
119103
console.log(
120-
`Total requests: ${resultWithoutFirewall.metrics.http_reqs.values.count}`
104+
`POST duration: avg=${postResultsWithoutZen.avg}ms, min=${postResultsWithoutZen.min}ms, max=${postResultsWithoutZen.max}ms`
121105
);
122106

123-
const getMedDiff = customGetFirewall.med - customGetNoFirewall.med;
124-
const postMedDiff = customPostFirewall.med - customPostNoFirewall.med;
125-
const getDiffPercent = (getMedDiff / customGetNoFirewall.med) * 100;
126-
const postDiffPercent = (postMedDiff / customPostNoFirewall.med) * 100;
107+
const getDiff = results.metrics.get_delta.values.avg;
108+
const postDiff = results.metrics.post_delta.values.avg;
109+
110+
const getDiffPercent = (getDiff / getResultsWithoutZen.avg) * 100;
111+
const postDiffPercent = (postDiff / postResultsWithoutZen.avg) * 100;
127112

128113
console.log("------------------------------------");
129-
console.log("Firewall performance impact:");
130-
console.log(`GET med diff: ${getMedDiff}ms (${getDiffPercent.toFixed(2)}%)`);
114+
console.log("Zen performance impact:");
131115
console.log(
132-
`POST med diff: ${postMedDiff}ms (${postDiffPercent.toFixed(2)}%)`
116+
`GET avg diff: ${getDiff.toFixed(3)}ms (${getDiffPercent.toFixed(2)}%)`
117+
);
118+
console.log(
119+
`POST avg diff: ${postDiff.toFixed(3)}ms (${postDiffPercent.toFixed(2)}%)`
133120
);
134121

135122
// Check if difference is larger than 3ms
136-
if (getMedDiff > 3 || postMedDiff > 3) {
137-
console.log(
138-
"Firewall is causing a performance impact thats larger than 3ms"
139-
);
123+
if (getDiff > 3 || postDiff > 3) {
124+
console.log("Zen is causing a performance impact thats larger than 3ms");
140125
process.exit(1);
141126
}
142127

benchmarks/hono-pg/requests.mjs

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import http from "k6/http";
22
import { Trend } from "k6/metrics";
33

44
export const options = {
5-
vus: 1,
6-
duration: "30s",
5+
vus: 2,
6+
duration: "60s",
77
};
88

99
http.setResponseCallback(http.expectedStatuses({ min: 200, max: 204 }));
@@ -52,7 +52,6 @@ const headers = {
5252
"Accept-Language": "en-US,en;q=0.9",
5353
Dnt: "1",
5454
Priority: "u=0, i",
55-
"Content-Type": "application/json",
5655
"Sec-Ch-Ua":
5756
'"Not)A;Brand";v="99", "Google Chrome";v="127", "Chromium";v="127"',
5857
"Sec-Ch-Ua-Arch": '"arm"',
@@ -74,25 +73,57 @@ const headers = {
7473
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
7574
};
7675

77-
const GET_TREND = new Trend("custom_get_duration");
78-
const POST_TREND = new Trend("custom_post_duration");
76+
function buildTestTrends(prefix) {
77+
return {
78+
delta: new Trend(`${prefix}_delta`),
79+
with_zen: new Trend(`${prefix}_with_zen`),
80+
without_zen: new Trend(`${prefix}_without_zen`),
81+
};
82+
}
83+
84+
const getTrends = buildTestTrends("get");
85+
const postTrends = buildTestTrends("post");
7986

8087
export default function () {
81-
const getRes = http.get("http://localhost:4000/api/posts", {
88+
const getWithZen = http.get("http://localhost:4000/api/posts", {
89+
headers: headers,
90+
});
91+
const getWithoutZen = http.get("http://localhost:4001/api/posts", {
8292
headers: headers,
8393
});
8494

85-
GET_TREND.add(getRes.timings.waiting);
95+
getTrends.with_zen.add(getWithZen.timings.waiting);
96+
getTrends.without_zen.add(getWithoutZen.timings.waiting);
97+
getTrends.delta.add(
98+
getWithZen.timings.waiting - getWithoutZen.timings.waiting
99+
);
86100

87-
const postRes = http.post(
101+
const postWithZen = http.post(
88102
"http://localhost:4000/api/posts",
89103
JSON.stringify(payload),
90104
{
91-
headers: headers,
105+
headers: {
106+
...headers,
107+
"Content-Type": "application/json",
108+
},
109+
}
110+
);
111+
const postWithoutZen = http.post(
112+
"http://localhost:4001/api/posts",
113+
JSON.stringify(payload),
114+
{
115+
headers: {
116+
...headers,
117+
"Content-Type": "application/json",
118+
},
92119
}
93120
);
94121

95-
POST_TREND.add(postRes.timings.waiting);
122+
postTrends.with_zen.add(postWithZen.timings.waiting);
123+
postTrends.without_zen.add(postWithoutZen.timings.waiting);
124+
postTrends.delta.add(
125+
postWithZen.timings.waiting - postWithoutZen.timings.waiting
126+
);
96127
}
97128

98129
export function handleSummary(data) {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const t = require("tap");
2+
const { execSync } = require("child_process");
3+
const { resolve } = require("path");
4+
5+
const pathToApp = resolve(
6+
__dirname,
7+
"../../sample-apps/lambda-mark-unsafe",
8+
"app.js"
9+
);
10+
11+
t.test(
12+
"it does not crash if markUnsafe is used in lambda wrapper",
13+
async (t) => {
14+
execSync(`node ${pathToApp}`, {
15+
env: { ...process.env, AIKIDO_DEBUG: "true", AIKIDO_BLOCKING: "true" },
16+
});
17+
}
18+
);

library/agent/Agent.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,10 @@ export class Agent {
216216
agent: this.getAgentInfo(),
217217
};
218218

219+
this.getInspectionStatistics().onDetectedAttack({
220+
blocked,
221+
});
222+
219223
this.attackLogger.log(attack);
220224

221225
if (this.token) {

0 commit comments

Comments
 (0)