From 8f7c0f1c82ef2a36a8342bddcd2ffcb8308070ea Mon Sep 17 00:00:00 2001 From: vpnachev Date: Fri, 18 Oct 2024 14:11:15 +0300 Subject: [PATCH] Fix lakom permissions when extension is using scope=Cluster --- pkg/controller/lifecycle/actuator.go | 63 ++++++++++++++--------- pkg/controller/lifecycle/actuator_test.go | 44 +++++++++++----- 2 files changed, 72 insertions(+), 35 deletions(-) diff --git a/pkg/controller/lifecycle/actuator.go b/pkg/controller/lifecycle/actuator.go index 919aad75..9cb90130 100644 --- a/pkg/controller/lifecycle/actuator.go +++ b/pkg/controller/lifecycle/actuator.go @@ -672,11 +672,10 @@ func getShootResources(webhookCaBundle []byte, extensionNamespace, shootAccessSe ObjectSelector: &objectSelector, }}, }, - &rbacv1.Role{ + &rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{ - Name: constants.LakomResourceReader, - Namespace: metav1.NamespaceSystem, - Labels: getLabels(), + Name: constants.LakomResourceReader, + Labels: getLabels(), }, Rules: []rbacv1.PolicyRule{ { @@ -686,25 +685,7 @@ func getShootResources(webhookCaBundle []byte, extensionNamespace, shootAccessSe }, }, }, - &rbacv1.RoleBinding{ - ObjectMeta: metav1.ObjectMeta{ - Name: constants.LakomResourceReader, - Namespace: metav1.NamespaceSystem, - Labels: getLabels(), - }, - RoleRef: rbacv1.RoleRef{ - APIGroup: "rbac.authorization.k8s.io", - Kind: "Role", - Name: constants.LakomResourceReader, - }, - Subjects: []rbacv1.Subject{ - { - Kind: rbacv1.ServiceAccountKind, - Name: shootAccessServiceAccountName, - Namespace: metav1.NamespaceSystem, - }, - }, - }, + getRoleBinding(scope, shootAccessServiceAccountName), ) if err != nil { @@ -713,3 +694,39 @@ func getShootResources(webhookCaBundle []byte, extensionNamespace, shootAccessSe return shootResources, nil } + +func getRoleBinding(scope lakom.ScopeType, shootAccessServiceAccountName string) client.Object { + roleRef := rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "ClusterRole", + Name: constants.LakomResourceReader, + } + subjects := []rbacv1.Subject{ + { + Kind: rbacv1.ServiceAccountKind, + Name: shootAccessServiceAccountName, + Namespace: metav1.NamespaceSystem, + }, + } + + if scope == lakom.Cluster { + return &rbacv1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: constants.LakomResourceReader, + Labels: getLabels(), + }, + RoleRef: roleRef, + Subjects: subjects, + } + } + + return &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: constants.LakomResourceReader, + Namespace: metav1.NamespaceSystem, + Labels: getLabels(), + }, + RoleRef: roleRef, + Subjects: subjects, + } +} diff --git a/pkg/controller/lifecycle/actuator_test.go b/pkg/controller/lifecycle/actuator_test.go index 409463ba..fba22ae5 100644 --- a/pkg/controller/lifecycle/actuator_test.go +++ b/pkg/controller/lifecycle/actuator_test.go @@ -84,8 +84,8 @@ var _ = Describe("Actuator", func() { Expect(manifests).To(ConsistOf( expectedSeedValidatingWebhook(caBundle, extensionNamespace, managedByGardenerObjectSelector, kubeSystemNamespaceSelector), expectedShootMutatingWebhook(caBundle, extensionNamespace, managedByGardenerObjectSelector, kubeSystemNamespaceSelector), - expectedShootRole(), - expectedShootRoleBinding(shootAccessServiceAccountName), + expectedShootClusterRole(), + expectedShootRoleBinding(shootAccessServiceAccountName, scope), )) }) @@ -132,16 +132,17 @@ var _ = Describe("Actuator", func() { ) DescribeTable("Should ensure the rolebinding is correctly set", - func(saName string) { - resources, err := getShootResources(caBundle, extensionNamespace, saName, scope) + func(saName string, lakomScope lakom.ScopeType) { + resources, err := getShootResources(caBundle, extensionNamespace, saName, lakomScope) Expect(err).ToNot(HaveOccurred()) manifests, err := test.ExtractManifestsFromManagedResourceData(resources) Expect(err).ToNot(HaveOccurred()) - Expect(manifests).To(ContainElement(expectedShootRoleBinding(saName))) + Expect(manifests).To(ContainElement(expectedShootRoleBinding(saName, lakomScope))) }, - Entry("ServiceAccount name: test", "test"), - Entry("ServiceAccount name: foo-bar", "foo-bar"), + Entry("ServiceAccount name: test, scope: KubeSystemManagedByGardener", "test", lakom.KubeSystemManagedByGardener), + Entry("ServiceAccount name: foo-bar, scope: KubeSystem", "foo-bar", lakom.KubeSystem), + Entry("ServiceAccount name: foo-bar, scope: Cluster", "foo-bar", lakom.Cluster), ) DescribeTable("Should return the correct object and namespace selectors based on scope", @@ -326,16 +327,15 @@ webhooks: ` } -func expectedShootRole() string { +func expectedShootClusterRole() string { return `apiVersion: rbac.authorization.k8s.io/v1 -kind: Role +kind: ClusterRole metadata: creationTimestamp: null labels: app.kubernetes.io/name: lakom app.kubernetes.io/part-of: shoot-lakom-service name: gardener-extension-shoot-lakom-service-resource-reader - namespace: kube-system rules: - apiGroups: - "" @@ -346,7 +346,27 @@ rules: ` } -func expectedShootRoleBinding(saName string) string { +func expectedShootRoleBinding(saName string, lakomScope lakom.ScopeType) string { + if lakomScope == lakom.Cluster { + return `apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + creationTimestamp: null + labels: + app.kubernetes.io/name: lakom + app.kubernetes.io/part-of: shoot-lakom-service + name: gardener-extension-shoot-lakom-service-resource-reader +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: gardener-extension-shoot-lakom-service-resource-reader +subjects: +- kind: ServiceAccount + name: ` + saName + ` + namespace: kube-system +` + } + return `apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: @@ -358,7 +378,7 @@ metadata: namespace: kube-system roleRef: apiGroup: rbac.authorization.k8s.io - kind: Role + kind: ClusterRole name: gardener-extension-shoot-lakom-service-resource-reader subjects: - kind: ServiceAccount