From 45b17ed776f9cd8ad6cd17205cdf35b9c859672f Mon Sep 17 00:00:00 2001 From: Micah Nagel Date: Thu, 29 Jan 2026 12:25:17 -0500 Subject: [PATCH 1/5] fix: ensure ambient mode is the default in all operator code --- .../operator/controllers/istio/ambient-waypoint.ts | 14 ++++---------- .../operator/controllers/istio/waypoint-utils.ts | 3 ++- .../controllers/network/authorizationPolicies.ts | 3 ++- .../operator/controllers/packages/package-store.ts | 3 ++- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/pepr/operator/controllers/istio/ambient-waypoint.ts b/src/pepr/operator/controllers/istio/ambient-waypoint.ts index a5964169cb..d75ceb3186 100644 --- a/src/pepr/operator/controllers/istio/ambient-waypoint.ts +++ b/src/pepr/operator/controllers/istio/ambient-waypoint.ts @@ -213,11 +213,8 @@ export async function reconcileService(svc: a.Service): Promise { } const pkg = PackageStore.getPackageByNamespace(namespace); - if ( - !pkg || - pkg.metadata?.deletionTimestamp || - pkg.spec?.network?.serviceMesh?.mode !== Mode.Ambient - ) { + const istioMode = pkg?.spec?.network?.serviceMesh?.mode || Mode.Ambient; + if (!pkg || pkg.metadata?.deletionTimestamp || istioMode !== Mode.Ambient) { return; } @@ -270,11 +267,8 @@ export async function reconcilePod(pod: a.Pod): Promise { } const pkg = PackageStore.getPackageByNamespace(namespace); - if ( - !pkg || - pkg.metadata?.deletionTimestamp || - pkg.spec?.network?.serviceMesh?.mode !== Mode.Ambient - ) { + const istioMode = pkg?.spec?.network?.serviceMesh?.mode || Mode.Ambient; + if (!pkg || pkg.metadata?.deletionTimestamp || istioMode !== Mode.Ambient) { return; } diff --git a/src/pepr/operator/controllers/istio/waypoint-utils.ts b/src/pepr/operator/controllers/istio/waypoint-utils.ts index a15f884512..d752c8180f 100644 --- a/src/pepr/operator/controllers/istio/waypoint-utils.ts +++ b/src/pepr/operator/controllers/istio/waypoint-utils.ts @@ -14,7 +14,8 @@ const WAYPOINT_SUFFIX = "-waypoint"; // Suffix for waypoint resource names * Determines if a package should use ambient waypoint networking */ export const shouldUseAmbientWaypoint = (pkg: UDSPackage): boolean => { - return pkg.spec?.network?.serviceMesh?.mode === Mode.Ambient && hasAuthserviceSSO(pkg); + const istioMode = pkg.spec?.network?.serviceMesh?.mode || Mode.Ambient; + return istioMode === Mode.Ambient && hasAuthserviceSSO(pkg); }; /** diff --git a/src/pepr/operator/controllers/network/authorizationPolicies.ts b/src/pepr/operator/controllers/network/authorizationPolicies.ts index 4dbfcfbbc2..ca18fc6e53 100644 --- a/src/pepr/operator/controllers/network/authorizationPolicies.ts +++ b/src/pepr/operator/controllers/network/authorizationPolicies.ts @@ -424,7 +424,8 @@ export function findMatchingSsoClient( pkg: UDSPackage, selector: Record | undefined, ) { - if (!selector || pkg.spec?.network?.serviceMesh?.mode !== Mode.Ambient) { + const istioMode = pkg.spec?.network?.serviceMesh?.mode || Mode.Ambient; + if (!selector || istioMode !== Mode.Ambient) { return undefined; } diff --git a/src/pepr/operator/controllers/packages/package-store.ts b/src/pepr/operator/controllers/packages/package-store.ts index a5f7a74f12..d1f8995d4a 100644 --- a/src/pepr/operator/controllers/packages/package-store.ts +++ b/src/pepr/operator/controllers/packages/package-store.ts @@ -182,7 +182,8 @@ function getAmbientPackages(): UDSPackage[] { const result: UDSPackage[] = []; for (const namespaceMap of packageNamespaceMap.values()) { for (const pkg of namespaceMap.values()) { - if (pkg.spec?.network?.serviceMesh?.mode === Mode.Ambient) { + const istioMode = pkg.spec?.network?.serviceMesh?.mode || Mode.Ambient; + if (istioMode === Mode.Ambient) { result.push(pkg); } } From cb117f69f5dcd7fa1a0dcd1afcaacdf8aa06db23 Mon Sep 17 00:00:00 2001 From: Micah Nagel Date: Thu, 29 Jan 2026 12:31:26 -0500 Subject: [PATCH 2/5] fix: unit tests --- .../operator/controllers/istio/waypoint-utils.spec.ts | 4 ++-- .../controllers/network/authorizationPolicies.spec.ts | 3 +++ .../operator/controllers/packages/package-store.spec.ts | 8 ++++---- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/pepr/operator/controllers/istio/waypoint-utils.spec.ts b/src/pepr/operator/controllers/istio/waypoint-utils.spec.ts index 1580e5b267..753a2755a6 100644 --- a/src/pepr/operator/controllers/istio/waypoint-utils.spec.ts +++ b/src/pepr/operator/controllers/istio/waypoint-utils.spec.ts @@ -93,7 +93,7 @@ describe("shouldUseAmbientWaypoint", () => { expected: false, }, { - name: "should return false when no serviceMesh config exists", + name: "should return true when no serviceMesh config exists (ambient default)", pkg: { metadata: { name: "test", namespace: "test" }, spec: { @@ -106,7 +106,7 @@ describe("shouldUseAmbientWaypoint", () => { ], }, } as UDSPackage, - expected: false, + expected: true, }, ]; diff --git a/src/pepr/operator/controllers/network/authorizationPolicies.spec.ts b/src/pepr/operator/controllers/network/authorizationPolicies.spec.ts index f31868f939..805d3f5bf4 100644 --- a/src/pepr/operator/controllers/network/authorizationPolicies.spec.ts +++ b/src/pepr/operator/controllers/network/authorizationPolicies.spec.ts @@ -273,6 +273,9 @@ describe("authorization policy generation", () => { }, ], network: { + serviceMesh: { + mode: Mode.Sidecar, + }, expose: [ { service: "httpbin", diff --git a/src/pepr/operator/controllers/packages/package-store.spec.ts b/src/pepr/operator/controllers/packages/package-store.spec.ts index 44e24edff1..64bd74aba6 100644 --- a/src/pepr/operator/controllers/packages/package-store.spec.ts +++ b/src/pepr/operator/controllers/packages/package-store.spec.ts @@ -224,16 +224,16 @@ describe("Package Store", () => { const ambientPkg2 = makeMockReq({ metadata: { namespace: "ns2", name: "ambient2" }, spec: { - network: { - serviceMesh: { mode: Mode.Ambient }, - }, + network: {}, }, }).Raw; const nonAmbientPkg = makeMockReq({ metadata: { namespace: "ns3", name: "non-ambient" }, spec: { - network: {}, + network: { + serviceMesh: { mode: Mode.Sidecar }, + }, }, }).Raw; From b33494a04a7939a61e7e07864afca0f1128fe6b6 Mon Sep 17 00:00:00 2001 From: Micah Nagel Date: Thu, 29 Jan 2026 12:34:05 -0500 Subject: [PATCH 3/5] chore: cover in e2e --- src/test/chart/templates/package.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/chart/templates/package.yaml b/src/test/chart/templates/package.yaml index 7fb5093063..e5dfab97ec 100644 --- a/src/test/chart/templates/package.yaml +++ b/src/test/chart/templates/package.yaml @@ -8,8 +8,9 @@ metadata: namespace: podinfo spec: network: - serviceMesh: - mode: ambient + # Relying on default mesh mode + # serviceMesh: + # mode: ambient expose: - service: podinfo selector: From c50e313aa0acc8d658f5b32b501b0af465e5177b Mon Sep 17 00:00:00 2001 From: Micah Nagel Date: Thu, 29 Jan 2026 13:03:58 -0500 Subject: [PATCH 4/5] chore: add test coverage --- .../istio/ambient-waypoint.spec.ts | 46 ++++++++++++++++--- .../network/authorizationPolicies.spec.ts | 13 ++++++ 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/pepr/operator/controllers/istio/ambient-waypoint.spec.ts b/src/pepr/operator/controllers/istio/ambient-waypoint.spec.ts index 1f19c3b47a..35db05db14 100644 --- a/src/pepr/operator/controllers/istio/ambient-waypoint.spec.ts +++ b/src/pepr/operator/controllers/istio/ambient-waypoint.spec.ts @@ -25,7 +25,7 @@ import { ambientEgressNamespace, sharedEgressPkgId } from "./istio-resources"; const createMockPackage = ( name: string, selector: Record = {}, - mode: "ambient" | "sidecar" = "ambient", + mode: "ambient" | "sidecar" | "unset" = "ambient", sso: Sso[] = [ { clientId: "test-client", @@ -40,11 +40,14 @@ const createMockPackage = ( uid: "test-uid", }, spec: { - network: { - serviceMesh: { - mode: mode === "ambient" ? Mode.Ambient : Mode.Sidecar, - }, - }, + network: + mode === "unset" + ? {} + : { + serviceMesh: { + mode: mode === "ambient" ? Mode.Ambient : Mode.Sidecar, + }, + }, sso, }, }); @@ -319,6 +322,37 @@ describe("reconcileService and reconcilePod", () => { } }, ); + + it.each(testCases)( + "$name - defaults to ambient mode when serviceMesh.mode is undefined", + async ({ createResource, expectedLabels, name }) => { + const resource = createResource(); + + const pkg = createMockPackage("test-pkg", { "app.kubernetes.io/name": "test-app" }, "unset", [ + { + clientId: "test-client", + name: "test-sso", + enableAuthserviceSelector: { "app.kubernetes.io/name": "test-app" }, + }, + ]); + + ( + PackageStore.getPackageByNamespace as MockedFunction< + typeof PackageStore.getPackageByNamespace + > + ).mockImplementation(namespace => { + return namespace === testNamespace ? pkg : undefined; + }); + + if (name === "service") { + await reconcileService(resource as a.Service); + } else { + await reconcilePod(resource as a.Pod); + } + + expect(resource.metadata?.labels).toMatchObject(expectedLabels); + }, + ); }); describe("setupAmbientWaypoint", () => { diff --git a/src/pepr/operator/controllers/network/authorizationPolicies.spec.ts b/src/pepr/operator/controllers/network/authorizationPolicies.spec.ts index 805d3f5bf4..53dc01896c 100644 --- a/src/pepr/operator/controllers/network/authorizationPolicies.spec.ts +++ b/src/pepr/operator/controllers/network/authorizationPolicies.spec.ts @@ -1145,6 +1145,19 @@ describe("findMatchingSsoClient", () => { expect(findMatchingSsoClient(pkg, { app: "a" })).toBeUndefined(); }); + test("defaults to ambient when serviceMesh.mode is undefined", () => { + const pkg: UDSPackage = { + metadata: { name: "app", namespace: "ns" }, + spec: { + // No serviceMesh block -> defaults to Ambient + sso: [{ clientId: "c1", name: "", enableAuthserviceSelector: { app: "a" } }], + network: {}, + }, + }; + + expect(findMatchingSsoClient(pkg, { app: "a" })).toMatchObject({ clientId: "c1" }); + }); + test("prefilters to enabled clients only (missing/null/undefined selector are ignored)", () => { const pkg: UDSPackage = { metadata: { name: "app", namespace: "ns" }, From 03487f13de9cb01e289ee76ea1e2e8a9083983d7 Mon Sep 17 00:00:00 2001 From: Micah Nagel Date: Thu, 29 Jan 2026 13:08:32 -0500 Subject: [PATCH 5/5] fix: explicit assert on status --- test/playwright/podinfo.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/playwright/podinfo.test.ts b/test/playwright/podinfo.test.ts index fd34eae69e..6e3231bf5f 100644 --- a/test/playwright/podinfo.test.ts +++ b/test/playwright/podinfo.test.ts @@ -45,6 +45,10 @@ test.describe("Podinfo Authservice protection and metrics behavior", () => { // Basic sanity check that podinfo content is rendered await expect(page).toHaveURL(podinfoUrl, { timeout: 10000 }); + + // Verify non-error response (indicates successful JWT validation) + const response = await page.reload(); + expect(response?.status()).toBeLessThan(400); } finally { await context.close(); }