Make load test script more self-documenting
This adds a script to package.json that will guide the user on e.g. what env vars to set when they aren't set. It also allows you to pass in a plain email address and have the performance test send breach notifications for that specific email address, without having to manually calculate a hash.
This commit is contained in:
Родитель
45c1a2b8b2
Коммит
7667ecbd51
11
README.md
11
README.md
|
@ -219,9 +219,18 @@ To test the HIBP breach alerts endpoint, use:
|
|||
```sh
|
||||
export SERVER_URL=...
|
||||
export HIBP_NOTIFY_TOKEN=...
|
||||
k6 -u 10 src/scripts/loadtest/hibp.js # Run with 10 virtual users
|
||||
npm run loadtest:hbibp-webhook
|
||||
```
|
||||
|
||||
You can customise the number of requests to send in parallel ("virtual users") by setting the
|
||||
[`K6_VUS`](https://grafana.com/docs/k6/latest/using-k6/k6-options/reference/#vus) environment
|
||||
variable (default 1000), and for how long to send those requests by setting the
|
||||
[`K6_DURATION`](https://grafana.com/docs/k6/latest/using-k6/k6-options/reference/#duration)
|
||||
environment variable (default 30s).
|
||||
|
||||
You can also enforce the alert being sent for a specific email address via the
|
||||
`LOADTEST_BREACHED_EMAIL` environment variable.
|
||||
|
||||
See https://grafana.com/docs/k6/latest/get-started/running-k6/ for more information.
|
||||
|
||||
## Localization
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
"build-glean-docs": "npm run build-glean-frontend-docs && npm run build-glean-backend-docs",
|
||||
"build-glean-frontend-docs": "glean translate src/telemetry/metrics.yaml --format markdown --output docs/telemetry/frontent",
|
||||
"build-glean-backend-docs": "glean translate src/telemetry/backend-metrics.yaml --format markdown --output docs/telemetry/backend",
|
||||
"loadtest:hbibp-webhook": "echo 'Ensure k6 is installed; see:\n\thttps://grafana.com/docs/k6/latest/set-up/install-k6/\n' && k6 run src/scripts/loadtest/hibp.js",
|
||||
"validate-nimbus": "sh src/scripts/build/validate-nimbus-file.sh"
|
||||
},
|
||||
"repository": {
|
||||
|
|
|
@ -14,6 +14,12 @@ const projectId = process.env.GCP_PUBSUB_PROJECT_ID;
|
|||
const topicName = process.env.GCP_PUBSUB_TOPIC_NAME;
|
||||
const subscriptionName = process.env.GCP_PUBSUB_SUBSCRIPTION_NAME;
|
||||
|
||||
export type PostHibpNotificationRequestBody = {
|
||||
breachName: string;
|
||||
hashPrefix: string;
|
||||
hashSuffixes: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Whenever a breach is detected on the HIBP side, HIBP sends a request to this endpoint.
|
||||
* The payload is checked for validity, and immediately queued if it is valid.
|
||||
|
@ -21,8 +27,8 @@ const subscriptionName = process.env.GCP_PUBSUB_SUBSCRIPTION_NAME;
|
|||
* @param req
|
||||
*/
|
||||
export async function POST(req: NextRequest) {
|
||||
let pubsub;
|
||||
let json;
|
||||
let pubsub: PubSub;
|
||||
let json: PostHibpNotificationRequestBody;
|
||||
|
||||
try {
|
||||
if (!projectId) {
|
||||
|
@ -37,7 +43,7 @@ export async function POST(req: NextRequest) {
|
|||
return NextResponse.json({ success: false }, { status: 401 });
|
||||
}
|
||||
|
||||
json = await req.json();
|
||||
json = (await req.json()) as PostHibpNotificationRequestBody;
|
||||
|
||||
if (!(json.breachName && json.hashPrefix && json.hashSuffixes)) {
|
||||
logger.error(
|
||||
|
|
|
@ -11,33 +11,57 @@
|
|||
* @see https://grafana.com/docs/k6/latest/get-started/running-k6
|
||||
*/
|
||||
|
||||
/* eslint-disable import/no-unresolved */
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
import { post } from "k6/http";
|
||||
import crypto from "k6/crypto";
|
||||
|
||||
const url = `${__ENV.SERVER_URL}/api/v1/hibp/notify`;
|
||||
// k6 exposes environment variables via the __ENV variable:
|
||||
// https://grafana.com/docs/k6/latest/using-k6/environment-variables/
|
||||
/** @type {typeof process.env} */
|
||||
const envVars = __ENV;
|
||||
|
||||
// eslint-disable-next-line import/no-anonymous-default-export
|
||||
export default function () {
|
||||
const HIBP_NOTIFY_TOKEN = envVars.HIBP_NOTIFY_TOKEN;
|
||||
if (typeof HIBP_NOTIFY_TOKEN !== "string") {
|
||||
throw new Error(
|
||||
"Make sure to set the following environment variable: HIBP_NOTIFY_TOKEN",
|
||||
);
|
||||
}
|
||||
|
||||
const VIRTUAL_USERS =
|
||||
typeof envVars.K6_VIRTUAL_USERS === "string"
|
||||
? parseInt(envVars.K6_VIRTUAL_USERS, 10)
|
||||
: typeof envVars.K6_VUS === "string"
|
||||
? parseInt(envVars.K6_VUS, 10)
|
||||
: 1000;
|
||||
const DURATION =
|
||||
typeof envVars.K6_DURATION === "string" ? envVars.K6_DURATION : "30s";
|
||||
|
||||
export const options = {
|
||||
vus: VIRTUAL_USERS,
|
||||
duration: DURATION,
|
||||
};
|
||||
|
||||
const url = `${envVars.SERVER_URL ?? "https://stage.firefoxmonitor.nonprod.cloudops.mozgcp.net"}/api/v1/hibp/notify`;
|
||||
const mockedBreachedEmailHash =
|
||||
typeof envVars.LOADTEST_BREACHED_EMAIL === "string"
|
||||
? crypto.sha1(envVars.LOADTEST_BREACHED_EMAIL, "hex")
|
||||
: "1c48923da9f6f17165711712d11bc104087444cc";
|
||||
|
||||
export const run = () => {
|
||||
/** @type {import("../../app/api/v1/hibp/notify/route").PostHibpNotificationRequestBody} */
|
||||
let data = {
|
||||
breachName: "ApexSMS",
|
||||
// NOTE: modify this hash range if you want to receive email to specific test account(s).
|
||||
// This example should only email an address that is a sha1 hash for 1c48923da9f6f17165711712d11bc104087444cc.
|
||||
// See https://www.troyhunt.com/understanding-have-i-been-pwneds-use-of-sha-1-and-k-anonymity/ for more information.
|
||||
hashPrefix: "1c4892",
|
||||
hashSuffixes: [
|
||||
"3da9f6f17165711712d11bc104087444cc",
|
||||
"3da9f6fffff5711712d11bc104087444cc",
|
||||
],
|
||||
hashPrefix: mockedBreachedEmailHash.substring(0, 6),
|
||||
hashSuffixes: [mockedBreachedEmailHash.substring(6)],
|
||||
};
|
||||
|
||||
// Using a JSON string as body
|
||||
let res = post(url, JSON.stringify(data), {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
// eslint-disable-next-line no-undef
|
||||
Authorization: `Bearer ${__ENV.HIBP_NOTIFY_TOKEN}`,
|
||||
Authorization: `Bearer ${HIBP_NOTIFY_TOKEN}`,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -49,4 +73,5 @@ export default function () {
|
|||
} catch (ex) {
|
||||
throw new Error(`Failed to parse result: ${res.status}, ${res.text}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
export default run;
|
||||
|
|
Загрузка…
Ссылка в новой задаче