/ test / vitest / falco.spec.ts
falco.spec.ts
 1  /**
 2   * Copyright 2025 Defense Unicorns
 3   * SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-Defense-Unicorns-Commercial
 4   */
 5  
 6  import { afterAll, beforeAll, describe, expect, test } from "vitest";
 7  import { getAllLogsByLabelSelector, execAndWait, withTempPod } from "./helpers/k8s";
 8  import { pollUntilSuccess } from "./helpers/polling";
 9  
10  describe("Falco e2e Tests", () => {
11    beforeAll(async () => {});
12  
13    afterAll(async () => {});
14  
15    /*
16     * Test Falco detection of rule Search Private Keys or Passwords: see default rules: https://falco.org/docs/reference/rules/default-rules/
17     * This test creates a temporary pod in kube-system and runs a command that simulates searching for private keys with a unique identifier
18     * Then it checks the falcosidekick logs for an alert containing that unique identifier
19     * This tests the full e2e pipeline from Falco detection to falcosidekick alerting
20     * Note: this requires falcosidekick to be configured in debug mode (or have a registered output) to ensure the alert is logged
21     */
22    test("Falco detects 'Search Private Keys or Passwords' event and sends to Falco Sidekick", async () => {
23      // Generate a random string to identify this test run
24      const randomString = Math.random().toString(36).substring(2, 10); // 8-character alphanumeric string
25  
26      // Use a temporary pod in kube-system to trigger the Falco event
27      await withTempPod(
28        {
29          name: `falco-test-${randomString}`,
30          namespace: "kube-system", // Use kube-system to get around zarf mutations
31          image: "alpine:latest",
32          command: ["sleep", "3600"],
33        },
34        async podName => {
35          await execAndWait(
36            "kube-system",
37            podName,
38            ["find", `/tmp/test-${randomString}`, "-name", "id_rsa"],
39            "main",
40          );
41  
42          // Poll for the Falco event in falcosidekick logs until success or timeout
43          const falcoSidekickEvent = await pollUntilSuccess(
44            async () => {
45              const falcoSidekickLogs = await getAllLogsByLabelSelector(
46                "falco",
47                "app.kubernetes.io/name=falcosidekick",
48              );
49              return falcoSidekickLogs.find(
50                log =>
51                  log.includes("Grep private keys or passwords activities found") &&
52                  log.includes(`test-${randomString}`),
53              );
54            },
55            result => result !== undefined,
56            `Falco event with identifier "test-${randomString}" in falcosidekick logs`,
57            60000, // 1 minute timeout
58            15000, // 15 seconds interval
59          );
60  
61          expect(falcoSidekickEvent).toBeDefined();
62        },
63      );
64    }, 70000); // Set test timeout to 70 seconds
65  });