mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Only show the UserManagement tab in the sidebar if the sub menus are allowed for that cluster (#2258)
- Optimize Cluster.isAllowedResource Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
c0dddc0f40
commit
47e5cb1732
@ -4,42 +4,54 @@ export type KubeResource =
|
|||||||
"namespaces" | "nodes" | "events" | "resourcequotas" | "services" | "limitranges" |
|
"namespaces" | "nodes" | "events" | "resourcequotas" | "services" | "limitranges" |
|
||||||
"secrets" | "configmaps" | "ingresses" | "networkpolicies" | "persistentvolumeclaims" | "persistentvolumes" | "storageclasses" |
|
"secrets" | "configmaps" | "ingresses" | "networkpolicies" | "persistentvolumeclaims" | "persistentvolumes" | "storageclasses" |
|
||||||
"pods" | "daemonsets" | "deployments" | "statefulsets" | "replicasets" | "jobs" | "cronjobs" |
|
"pods" | "daemonsets" | "deployments" | "statefulsets" | "replicasets" | "jobs" | "cronjobs" |
|
||||||
"endpoints" | "customresourcedefinitions" | "horizontalpodautoscalers" | "podsecuritypolicies" | "poddisruptionbudgets";
|
"endpoints" | "customresourcedefinitions" | "horizontalpodautoscalers" | "podsecuritypolicies" | "poddisruptionbudgets" |
|
||||||
|
"roles" | "clusterroles" | "rolebindings" | "clusterrolebindings" | "serviceaccounts";
|
||||||
|
|
||||||
export interface KubeApiResource {
|
export interface KubeApiResource extends KubeApiResourceData {
|
||||||
kind: string; // resource type (e.g. "Namespace")
|
|
||||||
apiName: KubeResource; // valid api resource name (e.g. "namespaces")
|
apiName: KubeResource; // valid api resource name (e.g. "namespaces")
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface KubeApiResourceData {
|
||||||
|
kind: string; // resource type (e.g. "Namespace")
|
||||||
group?: string; // api-group
|
group?: string; // api-group
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const apiResourceRecord: Record<KubeResource, KubeApiResourceData> = {
|
||||||
|
"clusterroles": { kind: "ClusterRole", group: "rbac.authorization.k8s.io" },
|
||||||
|
"clusterrolebindings": { kind: "ClusterRoleBinding", group: "rbac.authorization.k8s.io" },
|
||||||
|
"configmaps": { kind: "ConfigMap" },
|
||||||
|
"cronjobs": { kind: "CronJob", group: "batch" },
|
||||||
|
"customresourcedefinitions": { kind: "CustomResourceDefinition", group: "apiextensions.k8s.io" },
|
||||||
|
"daemonsets": { kind: "DaemonSet", group: "apps" },
|
||||||
|
"deployments": { kind: "Deployment", group: "apps" },
|
||||||
|
"endpoints": { kind: "Endpoint" },
|
||||||
|
"events": { kind: "Event" },
|
||||||
|
"horizontalpodautoscalers": { kind: "HorizontalPodAutoscaler" },
|
||||||
|
"ingresses": { kind: "Ingress", group: "networking.k8s.io" },
|
||||||
|
"jobs": { kind: "Job", group: "batch" },
|
||||||
|
"namespaces": { kind: "Namespace" },
|
||||||
|
"limitranges": { kind: "LimitRange" },
|
||||||
|
"networkpolicies": { kind: "NetworkPolicy", group: "networking.k8s.io" },
|
||||||
|
"nodes": { kind: "Node" },
|
||||||
|
"persistentvolumes": { kind: "PersistentVolume" },
|
||||||
|
"persistentvolumeclaims": { kind: "PersistentVolumeClaim" },
|
||||||
|
"pods": { kind: "Pod" },
|
||||||
|
"poddisruptionbudgets": { kind: "PodDisruptionBudget", group: "policy" },
|
||||||
|
"podsecuritypolicies": { kind: "PodSecurityPolicy" },
|
||||||
|
"resourcequotas": { kind: "ResourceQuota" },
|
||||||
|
"replicasets": { kind: "ReplicaSet", group: "apps" },
|
||||||
|
"roles": { kind: "Role", group: "rbac.authorization.k8s.io" },
|
||||||
|
"rolebindings": { kind: "RoleBinding", group: "rbac.authorization.k8s.io" },
|
||||||
|
"secrets": { kind: "Secret" },
|
||||||
|
"serviceaccounts": { kind: "ServiceAccount", group: "core" },
|
||||||
|
"services": { kind: "Service" },
|
||||||
|
"statefulsets": { kind: "StatefulSet", group: "apps" },
|
||||||
|
"storageclasses": { kind: "StorageClass", group: "storage.k8s.io" },
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: auto-populate all resources dynamically (see: kubectl api-resources -o=wide -v=7)
|
// TODO: auto-populate all resources dynamically (see: kubectl api-resources -o=wide -v=7)
|
||||||
export const apiResources: KubeApiResource[] = [
|
export const apiResources: KubeApiResource[] = Object.entries(apiResourceRecord)
|
||||||
{ kind: "ConfigMap", apiName: "configmaps" },
|
.map(([apiName, data]) => ({ apiName: apiName as KubeResource, ...data }));
|
||||||
{ kind: "CronJob", apiName: "cronjobs", group: "batch" },
|
|
||||||
{ kind: "CustomResourceDefinition", apiName: "customresourcedefinitions", group: "apiextensions.k8s.io" },
|
|
||||||
{ kind: "DaemonSet", apiName: "daemonsets", group: "apps" },
|
|
||||||
{ kind: "Deployment", apiName: "deployments", group: "apps" },
|
|
||||||
{ kind: "Endpoint", apiName: "endpoints" },
|
|
||||||
{ kind: "Event", apiName: "events" },
|
|
||||||
{ kind: "HorizontalPodAutoscaler", apiName: "horizontalpodautoscalers" },
|
|
||||||
{ kind: "Ingress", apiName: "ingresses", group: "networking.k8s.io" },
|
|
||||||
{ kind: "Job", apiName: "jobs", group: "batch" },
|
|
||||||
{ kind: "Namespace", apiName: "namespaces" },
|
|
||||||
{ kind: "LimitRange", apiName: "limitranges" },
|
|
||||||
{ kind: "NetworkPolicy", apiName: "networkpolicies", group: "networking.k8s.io" },
|
|
||||||
{ kind: "Node", apiName: "nodes" },
|
|
||||||
{ kind: "PersistentVolume", apiName: "persistentvolumes" },
|
|
||||||
{ kind: "PersistentVolumeClaim", apiName: "persistentvolumeclaims" },
|
|
||||||
{ kind: "Pod", apiName: "pods" },
|
|
||||||
{ kind: "PodDisruptionBudget", apiName: "poddisruptionbudgets", group: "policy" },
|
|
||||||
{ kind: "PodSecurityPolicy", apiName: "podsecuritypolicies" },
|
|
||||||
{ kind: "ResourceQuota", apiName: "resourcequotas" },
|
|
||||||
{ kind: "ReplicaSet", apiName: "replicasets", group: "apps" },
|
|
||||||
{ kind: "Secret", apiName: "secrets" },
|
|
||||||
{ kind: "Service", apiName: "services" },
|
|
||||||
{ kind: "StatefulSet", apiName: "statefulsets", group: "apps" },
|
|
||||||
{ kind: "StorageClass", apiName: "storageclasses", group: "storage.k8s.io" },
|
|
||||||
];
|
|
||||||
|
|
||||||
export function isAllowedResource(resources: KubeResource | KubeResource[]) {
|
export function isAllowedResource(resources: KubeResource | KubeResource[]) {
|
||||||
if (!Array.isArray(resources)) {
|
if (!Array.isArray(resources)) {
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import { AuthorizationV1Api, CoreV1Api, HttpError, KubeConfig, V1ResourceAttribu
|
|||||||
import { Kubectl } from "./kubectl";
|
import { Kubectl } from "./kubectl";
|
||||||
import { KubeconfigManager } from "./kubeconfig-manager";
|
import { KubeconfigManager } from "./kubeconfig-manager";
|
||||||
import { loadConfig, validateKubeConfig } from "../common/kube-helpers";
|
import { loadConfig, validateKubeConfig } from "../common/kube-helpers";
|
||||||
import { apiResources, KubeApiResource } from "../common/rbac";
|
import { apiResourceRecord, apiResources, KubeApiResource, KubeResource } from "../common/rbac";
|
||||||
import logger from "./logger";
|
import logger from "./logger";
|
||||||
import { VersionDetector } from "./cluster-detectors/version-detector";
|
import { VersionDetector } from "./cluster-detectors/version-detector";
|
||||||
import { detectorRegistry } from "./cluster-detectors/detector-registry";
|
import { detectorRegistry } from "./cluster-detectors/detector-registry";
|
||||||
@ -678,7 +678,11 @@ export class Cluster implements ClusterModel, ClusterState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isAllowedResource(kind: string): boolean {
|
isAllowedResource(kind: string): boolean {
|
||||||
const apiResource = apiResources.find(resource => resource.kind === kind || resource.apiName === kind);
|
if ((kind as KubeResource) in apiResourceRecord) {
|
||||||
|
return this.allowedResources.includes(kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
const apiResource = apiResources.find(resource => resource.kind === kind);
|
||||||
|
|
||||||
if (apiResource) {
|
if (apiResource) {
|
||||||
return this.allowedResources.includes(apiResource.apiName);
|
return this.allowedResources.includes(apiResource.apiName);
|
||||||
|
|||||||
@ -13,29 +13,37 @@ import { isAllowedResource } from "../../../common/rbac";
|
|||||||
@observer
|
@observer
|
||||||
export class UserManagement extends React.Component {
|
export class UserManagement extends React.Component {
|
||||||
static get tabRoutes() {
|
static get tabRoutes() {
|
||||||
const tabRoutes: TabLayoutRoute[] = [];
|
|
||||||
const query = namespaceUrlParam.toObjectParam();
|
const query = namespaceUrlParam.toObjectParam();
|
||||||
|
const tabRoutes: TabLayoutRoute[] = [];
|
||||||
|
|
||||||
tabRoutes.push(
|
if (isAllowedResource("serviceaccounts")) {
|
||||||
{
|
tabRoutes.push({
|
||||||
title: "Service Accounts",
|
title: "Service Accounts",
|
||||||
component: ServiceAccounts,
|
component: ServiceAccounts,
|
||||||
url: serviceAccountsURL({ query }),
|
url: serviceAccountsURL({ query }),
|
||||||
routePath: serviceAccountsRoute.path.toString(),
|
routePath: serviceAccountsRoute.path.toString(),
|
||||||
},
|
});
|
||||||
{
|
}
|
||||||
|
|
||||||
|
if (isAllowedResource("rolebindings") || isAllowedResource("clusterrolebindings")) {
|
||||||
|
// TODO: seperate out these two pages
|
||||||
|
tabRoutes.push({
|
||||||
title: "Role Bindings",
|
title: "Role Bindings",
|
||||||
component: RoleBindings,
|
component: RoleBindings,
|
||||||
url: roleBindingsURL({ query }),
|
url: roleBindingsURL({ query }),
|
||||||
routePath: roleBindingsRoute.path.toString(),
|
routePath: roleBindingsRoute.path.toString(),
|
||||||
},
|
});
|
||||||
{
|
}
|
||||||
|
|
||||||
|
if (isAllowedResource("roles") || isAllowedResource("clusterroles")) {
|
||||||
|
// TODO: seperate out these two pages
|
||||||
|
tabRoutes.push({
|
||||||
title: "Roles",
|
title: "Roles",
|
||||||
component: Roles,
|
component: Roles,
|
||||||
url: rolesURL({ query }),
|
url: rolesURL({ query }),
|
||||||
routePath: rolesRoute.path.toString(),
|
routePath: rolesRoute.path.toString(),
|
||||||
},
|
});
|
||||||
);
|
}
|
||||||
|
|
||||||
if (isAllowedResource("podsecuritypolicies")) {
|
if (isAllowedResource("podsecuritypolicies")) {
|
||||||
tabRoutes.push({
|
tabRoutes.push({
|
||||||
|
|||||||
@ -257,6 +257,7 @@ export class Sidebar extends React.Component<Props> {
|
|||||||
id="users"
|
id="users"
|
||||||
text="Access Control"
|
text="Access Control"
|
||||||
isActive={isActiveRoute(usersManagementRoute)}
|
isActive={isActiveRoute(usersManagementRoute)}
|
||||||
|
isHidden={UserManagement.tabRoutes.length === 0}
|
||||||
url={usersManagementURL({ query })}
|
url={usersManagementURL({ query })}
|
||||||
icon={<Icon material="security"/>}
|
icon={<Icon material="security"/>}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -26,4 +26,9 @@ export const ResourceNames: Record<KubeResource, string> = {
|
|||||||
"podsecuritypolicies": "Pod Security Policies",
|
"podsecuritypolicies": "Pod Security Policies",
|
||||||
"poddisruptionbudgets": "Pod Disruption Budgets",
|
"poddisruptionbudgets": "Pod Disruption Budgets",
|
||||||
"limitranges": "Limit Ranges",
|
"limitranges": "Limit Ranges",
|
||||||
|
"roles": "Roles",
|
||||||
|
"rolebindings": "Role Bindings",
|
||||||
|
"clusterrolebindings": "Cluster Role Bindings",
|
||||||
|
"clusterroles": "Cluster Roles",
|
||||||
|
"serviceaccounts": "Service Accounts"
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user