podinfo.test.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 { expect, test } from "@playwright/test"; 7 import { domain } from "./uds.config"; 8 9 const podinfoUrl = `https://podinfo.${domain}`; 10 const ssoBaseUrl = `https://sso.${domain}`; 11 12 // These tests validate the end-user behavior for the podinfo app: 13 // - podinfo.uds.dev is protected by Authservice and requires a login 14 // - the /metrics endpoint is not directly accessible to browsers/unauthenticated callers 15 // 16 // Note: Prometheus -> podinfo scraping is validated separately by the Prometheus Vitest 17 // e2e in test/vitest/prometheus.spec.ts, which asserts that all configured Prometheus 18 // targets (including podinfo monitors) are "up". 19 20 test.describe("Podinfo Authservice protection and metrics behavior", () => { 21 test("podinfo is protected and login flow works", async ({ browser }) => { 22 const context = await browser.newContext({ storageState: undefined }); 23 const page = await context.newPage(); 24 25 try { 26 // Navigate to podinfo without any existing auth state; should redirect to SSO 27 await page.goto(podinfoUrl); 28 await page.waitForLoadState("networkidle"); 29 30 const redirectedUrl = page.url(); 31 expect( 32 redirectedUrl.startsWith(`${ssoBaseUrl}/realms/uds/protocol/openid-connect/auth`), 33 ).toBe(true); 34 35 // Complete the Keycloak login flow 36 await page.getByLabel("Username or email").fill("doug"); 37 await page.getByLabel("Password").fill("unicorn123!@#UN"); 38 await page.getByRole("button", { name: "Sign In" }).click(); 39 40 // After successful login we should be redirected back to podinfo 41 await page.waitForLoadState("networkidle"); 42 await page.waitForURL(new RegExp(`^${podinfoUrl.replace(".", "\\.")}`), { 43 timeout: 30000, 44 }); 45 46 // Basic sanity check that podinfo content is rendered 47 await expect(page).toHaveURL(podinfoUrl, { timeout: 10000 }); 48 } finally { 49 await context.close(); 50 } 51 }); 52 53 test("unauthenticated access to podinfo metrics is RBAC denied", async ({ browser }) => { 54 const context = await browser.newContext({ storageState: undefined }); 55 const page = await context.newPage(); 56 57 try { 58 const metricsUrl = `${podinfoUrl}/metrics`; 59 60 // Direct unauthenticated request to the metrics endpoint should be denied by Envoy RBAC 61 const response = await page.goto(metricsUrl, { waitUntil: "networkidle" }); 62 expect(response).not.toBeNull(); 63 expect(response?.status()).toBe(403); 64 } finally { 65 await context.close(); 66 } 67 }); 68 });