1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Port #7282 to master (#7289)

* fix requestNamespaceListPermissionsForInjectable



* more tests



* fix test descriptions



* fake -> stub



* fake-namespace -> irrelevant-namespace



---------

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
This commit is contained in:
Jari Kolehmainen 2023-03-06 17:00:59 +02:00 committed by GitHub
parent e5f5151b3c
commit f88555a1d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 340 additions and 10 deletions

View File

@ -47,9 +47,9 @@ const requestNamespaceListPermissionsForInjectable = getInjectable({
const { resourceRules } = status;
return (resource) => {
const resourceRule = resourceRules.find(({
apiGroups = [],
resources = [],
const rules = resourceRules.filter(({
apiGroups = ["*"],
resources = ["*"],
}) => {
const isAboutRelevantApiGroup = apiGroups.includes("*") || apiGroups.includes(resource.group);
const isAboutResource = resources.includes("*") || resources.includes(resource.apiName);
@ -57,13 +57,7 @@ const requestNamespaceListPermissionsForInjectable = getInjectable({
return isAboutRelevantApiGroup && isAboutResource;
});
if (!resourceRule) {
return false;
}
const { verbs } = resourceRule;
return verbs.includes("*") || verbs.includes("list");
return rules.some(({ verbs }) => verbs.includes("*") || verbs.includes("list"));
};
} catch (error) {
logger.error(`[AUTHORIZATION-NAMESPACE-REVIEW]: failed to create subject rules review`, { namespace, error });

View File

@ -0,0 +1,336 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { V1SubjectRulesReviewStatus } from "@kubernetes/client-node";
import type { DiContainer } from "@ogre-tools/injectable";
import { getDiForUnitTesting } from "../../main/getDiForUnitTesting";
import type { RequestNamespaceListPermissionsFor } from "./request-namespace-list-permissions.injectable";
import requestNamespaceListPermissionsForInjectable from "./request-namespace-list-permissions.injectable";
const createStubProxyConfig = (statusResponse: Promise<{ body: { status: V1SubjectRulesReviewStatus }}>) => ({
makeApiClient: () => ({
createSelfSubjectRulesReview: (): Promise<{ body: { status: V1SubjectRulesReviewStatus }}> => statusResponse,
}),
});
describe("requestNamespaceListPermissions", () => {
let di: DiContainer;
let requestNamespaceListPermissions: RequestNamespaceListPermissionsFor;
beforeEach(() => {
di = getDiForUnitTesting({ doGeneralOverrides: true });
requestNamespaceListPermissions = di.inject(requestNamespaceListPermissionsForInjectable);
});
describe("when api returns incomplete data", () => {
it("returns truthy function", async () => {
const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
new Promise((resolve) => resolve({
body: {
status: {
incomplete: true,
resourceRules: [],
nonResourceRules: [],
},
},
})),
) as any);
const permissionCheck = await requestPermissions("irrelevant-namespace");
expect(permissionCheck({
apiName: "pods",
group: "",
kind: "Pod",
namespaced: true,
})).toBeTruthy();
});
});
describe("when api rejects", () => {
it("returns truthy function", async () => {
const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
new Promise((resolve, reject) => reject("unknown error")),
) as any);
const permissionCheck = await requestPermissions("irrelevant-namespace");
expect(permissionCheck({
apiName: "pods",
group: "",
kind: "Pod",
namespaced: true,
})).toBeTruthy();
});
});
describe("when first resourceRule has all permissions for everything", () => {
it("return truthy function", async () => {
const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
new Promise((resolve) => resolve({
body: {
status: {
incomplete: false,
resourceRules: [
{
apiGroups: ["*"],
verbs: ["*"],
},
{
apiGroups: ["*"],
verbs: ["get"],
},
],
nonResourceRules: [],
},
},
})),
) as any);
const permissionCheck = await requestPermissions("irrelevant-namespace");
expect(permissionCheck({
apiName: "pods",
group: "",
kind: "Pod",
namespaced: true,
})).toBeTruthy();
});
});
describe("when first resourceRule has list permissions for everything", () => {
it("return truthy function", async () => {
const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
new Promise((resolve) => resolve({
body: {
status: {
incomplete: false,
resourceRules: [
{
apiGroups: ["*"],
verbs: ["list"],
},
{
apiGroups: ["*"],
verbs: ["get"],
},
],
nonResourceRules: [],
},
},
})),
) as any);
const permissionCheck = await requestPermissions("irrelevant-namespace");
expect(permissionCheck({
apiName: "pods",
group: "",
kind: "Pod",
namespaced: true,
})).toBeTruthy();
});
});
describe("when first resourceRule has list permissions for asked resource", () => {
it("return truthy function", async () => {
const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
new Promise((resolve) => resolve({
body: {
status: {
incomplete: false,
resourceRules: [
{
apiGroups: [""],
resources: ["pods"],
verbs: ["list"],
},
{
apiGroups: ["*"],
verbs: ["get"],
},
],
nonResourceRules: [],
},
},
})),
) as any);
const permissionCheck = await requestPermissions("irrelevant-namespace");
expect(permissionCheck({
apiName: "pods",
group: "",
kind: "Pod",
namespaced: true,
})).toBeTruthy();
});
});
describe("when last resourceRule has all permissions for everything", () => {
it("return truthy function", async () => {
const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
new Promise((resolve) => resolve({
body: {
status: {
incomplete: false,
resourceRules: [
{
apiGroups: ["*"],
verbs: ["get"],
},
{
apiGroups: ["*"],
verbs: ["*"],
},
],
nonResourceRules: [],
},
},
})),
) as any);
const permissionCheck = await requestPermissions("irrelevant-namespace");
expect(permissionCheck({
apiName: "pods",
group: "",
kind: "Pod",
namespaced: true,
})).toBeTruthy();
});
});
describe("when last resourceRule has list permissions for everything", () => {
it("return truthy function", async () => {
const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
new Promise((resolve) => resolve({
body: {
status: {
incomplete: false,
resourceRules: [
{
apiGroups: ["*"],
verbs: ["get"],
},
{
apiGroups: ["*"],
verbs: ["list"],
},
],
nonResourceRules: [],
},
},
})),
) as any);
const permissionCheck = await requestPermissions("irrelevant-namespace");
expect(permissionCheck({
apiName: "pods",
group: "",
kind: "Pod",
namespaced: true,
})).toBeTruthy();
});
});
describe("when last resourceRule has list permissions for asked resource", () => {
it("return truthy function", async () => {
const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
new Promise((resolve) => resolve({
body: {
status: {
incomplete: false,
resourceRules: [
{
apiGroups: ["*"],
verbs: ["get"],
},
{
apiGroups: [""],
resources: ["pods"],
verbs: ["list"],
},
],
nonResourceRules: [],
},
},
})),
) as any);
const permissionCheck = await requestPermissions("irrelevant-namespace");
expect(permissionCheck({
apiName: "pods",
group: "",
kind: "Pod",
namespaced: true,
})).toBeTruthy();
});
});
describe("when resourceRules has matching resource without list verb", () => {
it("return falsy function", async () => {
const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
new Promise((resolve) => resolve({
body: {
status: {
incomplete: false,
resourceRules: [
{
apiGroups: [""],
resources: ["pods"],
verbs: ["get"],
},
],
nonResourceRules: [],
},
},
})),
) as any);
const permissionCheck = await requestPermissions("irrelevant-namespace");
expect(permissionCheck({
apiName: "pods",
group: "",
kind: "Pod",
namespaced: true,
})).toBeFalsy();
});
});
describe("when resourceRules has no matching resource with list verb", () => {
it("return falsy function", async () => {
const requestPermissions = requestNamespaceListPermissions(createStubProxyConfig(
new Promise((resolve) => resolve({
body: {
status: {
incomplete: false,
resourceRules: [
{
apiGroups: [""],
resources: ["services"],
verbs: ["list"],
},
],
nonResourceRules: [],
},
},
})),
) as any);
const permissionCheck = await requestPermissions("irrelevant-namespace");
expect(permissionCheck({
apiName: "pods",
group: "",
kind: "Pod",
namespaced: true,
})).toBeFalsy();
});
});
});