Skip to content

Commit fa333ae

Browse files
committed
Introduce topology rbac e2e tests
Signed-off-by: Dominika Zemanovicova <[email protected]>
1 parent 71f8350 commit fa333ae

File tree

9 files changed

+258
-109
lines changed

9 files changed

+258
-109
lines changed

.ibm/pipelines/resources/config_map/app-config-rhdh-rbac.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ permission:
129129
- catalog
130130
- permission
131131
- scaffolder
132+
- kubernetes
132133
admin:
133134
users:
134135
- name: user:default/rhdh-qe

.ibm/pipelines/value_files/values_showcase-rbac.yaml

+2-4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ global:
4242
disabled: false
4343
- package: ./dynamic-plugins/dist/backstage-community-plugin-tekton
4444
disabled: false
45+
- package: ./dynamic-plugins/dist/backstage-community-plugin-topology
46+
disabled: false
4547
- package: ./dynamic-plugins/dist/backstage-plugin-kubernetes
4648
disabled: false
4749
- package: ./dynamic-plugins/dist/backstage-plugin-kubernetes-backend-dynamic
@@ -70,10 +72,6 @@ global:
7072
- apiVersion: 'v1'
7173
group: 'route.openshift.io'
7274
plural: 'routes'
73-
# Add to view topology code decorators
74-
- group: 'org.eclipse.che'
75-
apiVersion: 'v2'
76-
plural: 'checlusters'
7775
serviceLocatorMethod:
7876
type: multiTenant
7977
# Enable OCM plugins.

e2e-tests/playwright/e2e/plugins/rbac/rbac.spec.ts

+24-39
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ import {
88
} from "../../../support/pageObjects/page-obj";
99
import { Common, setupBrowser } from "../../../utils/common";
1010
import { UIhelper } from "../../../utils/ui-helper";
11-
import fs from "fs/promises";
1211
import { RbacPo } from "../../../support/pageObjects/rbac-po";
1312
import { RhdhAuthApiHack } from "../../../support/api/rhdh-auth-api-hack";
1413
import RhdhRbacApi from "../../../support/api/rbac-api";
1514
import { RbacConstants } from "../../../data/rbac-constants";
1615
import { Policy } from "../../../support/api/rbac-api-structures";
1716
import { CatalogImport } from "../../../support/pages/catalog-import";
17+
import { downloadAndReadFile } from "../../../utils/helper";
1818

1919
/*
2020
Note that:
@@ -226,7 +226,10 @@ test.describe.serial("Test RBAC", () => {
226226

227227
test("Should download the user list", async ({ page }) => {
228228
await page.locator('a:has-text("Download User List")').click();
229-
const fileContent = await downloadAndReadFile(page);
229+
const fileContent = await downloadAndReadFile(
230+
page,
231+
'a:has-text("Download User List")',
232+
);
230233
const lines = fileContent.trim().split("\n");
231234

232235
const header = "userEntityRef,displayName,email,lastAuthTime";
@@ -243,25 +246,6 @@ test.describe.serial("Test RBAC", () => {
243246
}
244247
});
245248

246-
async function downloadAndReadFile(
247-
page: Page,
248-
): Promise<string | undefined> {
249-
const [download] = await Promise.all([
250-
page.waitForEvent("download"),
251-
page.locator('a:has-text("Download User List")').click(),
252-
]);
253-
254-
const filePath = await download.path();
255-
256-
if (filePath) {
257-
const fileContent = await fs.readFile(filePath, "utf-8");
258-
return fileContent;
259-
} else {
260-
console.error("Download failed or path is not available");
261-
return undefined;
262-
}
263-
}
264-
265249
test("View details of a role", async ({ page }) => {
266250
const uiHelper = new UIhelper(page);
267251
await uiHelper.clickLink("role:default/rbac_admin");
@@ -293,7 +277,6 @@ test.describe.serial("Test RBAC", () => {
293277
test("Create and edit a role from the roles list page", async ({
294278
page,
295279
}) => {
296-
const rolesHelper = new Roles(page);
297280
const uiHelper = new UIhelper(page);
298281

299282
await uiHelper.clickButton("Create");
@@ -325,11 +308,12 @@ test.describe.serial("Test RBAC", () => {
325308

326309
const rbacPo = new RbacPo(page);
327310
const testUser = "Jonathon Page";
328-
await rbacPo.createRole("test-role", [
329-
RbacPo.rbacTestUsers.guest,
330-
RbacPo.rbacTestUsers.tara,
331-
RbacPo.rbacTestUsers.backstage,
332-
]);
311+
await rbacPo.createRole(
312+
"test-role",
313+
[RbacPo.rbacTestUsers.guest, RbacPo.rbacTestUsers.tara],
314+
[RbacPo.rbacTestUsers.backstage],
315+
[{ permission: "catalog.entity.delete" }],
316+
);
333317
await page.click(
334318
ROLES_PAGE_COMPONENTS.editRole("role:default/test-role"),
335319
);
@@ -361,20 +345,20 @@ test.describe.serial("Test RBAC", () => {
361345
await usersAndGroupsLocator.waitFor();
362346
await expect(usersAndGroupsLocator).toBeVisible();
363347

364-
await rolesHelper.deleteRole("role:default/test-role");
348+
await rbacPo.deleteRole("role:default/test-role");
365349
});
366350

367351
test("Edit users and groups and update policies of a role from the overview page", async ({
368352
page,
369353
}) => {
370-
const rolesHelper = new Roles(page);
371354
const uiHelper = new UIhelper(page);
372355
const rbacPo = new RbacPo(page);
373-
await rbacPo.createRole("test-role1", [
374-
RbacPo.rbacTestUsers.guest,
375-
RbacPo.rbacTestUsers.tara,
376-
RbacPo.rbacTestUsers.backstage,
377-
]);
356+
await rbacPo.createRole(
357+
"test-role1",
358+
[RbacPo.rbacTestUsers.guest, RbacPo.rbacTestUsers.tara],
359+
[RbacPo.rbacTestUsers.backstage],
360+
[{ permission: "catalog.entity.delete" }],
361+
);
378362

379363
await uiHelper.searchInputAriaLabel("test-role1");
380364

@@ -423,17 +407,18 @@ test.describe.serial("Test RBAC", () => {
423407
);
424408
await uiHelper.verifyHeading("Permission Policies (2)");
425409

426-
await rolesHelper.deleteRole("role:default/test-role1");
410+
await rbacPo.deleteRole("role:default/test-role1");
427411
});
428412

429413
test("Create a role with a permission policy per resource type and verify that the only authorized users can access specific resources.", async ({
430414
page,
431415
}) => {
432-
const rolesHelper = new Roles(page);
433416
const uiHelper = new UIhelper(page);
434-
await new RbacPo(page).createRole(
417+
const rbacPo = new RbacPo(page);
418+
await rbacPo.createConditionalRole(
435419
"test-role1",
436-
["Guest User", "rhdh-qe", "Backstage"],
420+
["Guest User", "rhdh-qe"],
421+
["Backstage"],
437422
"anyOf",
438423
);
439424

@@ -444,7 +429,7 @@ test.describe.serial("Test RBAC", () => {
444429
.locator(SEARCH_OBJECTS_COMPONENTS.ariaLabelSearch)
445430
.fill("test-role1");
446431
await uiHelper.verifyHeading("All roles (1)");
447-
await rolesHelper.deleteRole("role:default/test-role1");
432+
await rbacPo.deleteRole("role:default/test-role1");
448433
});
449434
});
450435

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { test } from "@playwright/test";
2+
import { Common } from "../../../utils/common";
3+
import { UIhelper } from "../../../utils/ui-helper";
4+
import { Catalog } from "../../../support/pages/catalog";
5+
import { Topology } from "../../../support/pages/topology";
6+
7+
test.describe("Test Topology Plugin with RBAC", () => {
8+
let common: Common;
9+
let uiHelper: UIhelper;
10+
let catalog: Catalog;
11+
let topology: Topology;
12+
13+
test.beforeEach(async ({ page }, testInfo) => {
14+
if (testInfo.retry > 0) {
15+
// progressively increase test timeout for retries
16+
test.setTimeout(testInfo.timeout + testInfo.timeout * 0.25);
17+
}
18+
common = new Common(page);
19+
uiHelper = new UIhelper(page);
20+
catalog = new Catalog(page);
21+
topology = new Topology(page);
22+
});
23+
24+
test.describe("Verify a user without permissions is not able to access parts of the Topology plugin", () => {
25+
// User is able to read from the catalog
26+
// User is missing 'kubernetes.clusters.read', 'kubernetes.resources.read', 'kubernetes.proxy' permissions
27+
test("Verify pods are not visible in the Topology tab", async () => {
28+
await common.loginAsKeycloakUser(
29+
process.env.QE_USER6_ID,
30+
process.env.QE_USER6_PASS,
31+
);
32+
33+
await catalog.goToBackstageJanusProject();
34+
await uiHelper.clickTab("Topology");
35+
await topology.verifyMissingTopologyPermission();
36+
});
37+
38+
// User is able to read from the catalog
39+
// User has 'kubernetes.clusters.read' and 'kubernetes.resources.read' permissions
40+
// User is missing 'kubernetes.proxy' permission (needed for pod logs)
41+
test("Verify pod logs are not visible in the Topology tab", async () => {
42+
await common.loginAsKeycloakUser(
43+
process.env.QE_USER5_ID,
44+
process.env.QE_USER5_PASS,
45+
);
46+
await catalog.goToBackstageJanusProject();
47+
await uiHelper.clickTab("Topology");
48+
49+
await topology.verifyDeployment("topology-test");
50+
await topology.verifyPodLogs(false);
51+
});
52+
});
53+
54+
// User is able to read from the catalog
55+
// User has 'kubernetes.clusters.read', 'kubernetes.resources.read', 'kubernetes.proxy' permissions
56+
test.describe("Verify a user with permissions is able to access the Topology plugin", () => {
57+
test.beforeEach(async () => {
58+
await common.loginAsKeycloakUser();
59+
60+
await catalog.goToBackstageJanusProject();
61+
await uiHelper.clickTab("Topology");
62+
});
63+
64+
test("Verify pods visibility in the Topology tab", async () => {
65+
await topology.verifyDeployment("topology-test");
66+
});
67+
68+
test("Verify pod logs visibility in the Topology tab", async () => {
69+
await topology.verifyDeployment("topology-test");
70+
await topology.verifyPodLogs(true);
71+
});
72+
});
73+
});

e2e-tests/playwright/e2e/plugins/topology/topology.spec.ts

+4-7
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@ import { test, expect } from "@playwright/test";
22
import { Common } from "../../../utils/common";
33
import { UIhelper } from "../../../utils/ui-helper";
44
import { Catalog } from "../../../support/pages/catalog";
5-
// import { Topology } from "../../../support/pages/topology";
5+
import { Topology } from "../../../support/pages/topology";
66

77
test.describe("Test Topology Plugin", () => {
88
test.skip(() => process.env.JOB_NAME.includes("operator"));
99
let common: Common;
1010
let uiHelper: UIhelper;
1111
let catalog: Catalog;
12-
// let topology: Topology;
12+
let topology: Topology;
1313

1414
test.beforeEach(async ({ page }) => {
1515
common = new Common(page);
1616
uiHelper = new UIhelper(page);
1717
catalog = new Catalog(page);
18-
// topology = new Topology(page);
18+
topology = new Topology(page);
1919
await common.loginAsGuest();
2020
});
2121

@@ -28,13 +28,10 @@ test.describe("Test Topology Plugin", () => {
2828
await uiHelper.clickTab("Topology");
2929
await uiHelper.verifyText("backstage-janus");
3030
await page.getByRole("button", { name: "Fit to Screen" }).click();
31-
await uiHelper.verifyText("topology-test");
31+
await topology.verifyDeployment("topology-test");
3232
await uiHelper.verifyButtonURL("Open URL", "topology-test-route", {
3333
locator: `[data-test-id="topology-test"]`,
3434
});
35-
await page.locator("[data-test-id=topology-test] image").first().click();
36-
await page.getByLabel("Pod").click();
37-
await page.getByLabel("Pod").getByText("1", { exact: true }).click();
3835
await uiHelper.clickTab("Details");
3936
await uiHelper.verifyText("Status");
4037
await uiHelper.verifyText("Active");

0 commit comments

Comments
 (0)