k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/controller_policy.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package bootstrappolicy 18 19 import ( 20 "strings" 21 22 "k8s.io/klog/v2" 23 24 capi "k8s.io/api/certificates/v1beta1" 25 rbacv1 "k8s.io/api/rbac/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 genericfeatures "k8s.io/apiserver/pkg/features" 28 utilfeature "k8s.io/apiserver/pkg/util/feature" 29 rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1" 30 "k8s.io/kubernetes/pkg/controlplane/controller/legacytokentracking" 31 "k8s.io/kubernetes/pkg/features" 32 ) 33 34 const saRolePrefix = "system:controller:" 35 36 func addControllerRole(controllerRoles *[]rbacv1.ClusterRole, controllerRoleBindings *[]rbacv1.ClusterRoleBinding, role rbacv1.ClusterRole) { 37 if !strings.HasPrefix(role.Name, saRolePrefix) { 38 klog.Fatalf(`role %q must start with %q`, role.Name, saRolePrefix) 39 } 40 41 for _, existingRole := range *controllerRoles { 42 if role.Name == existingRole.Name { 43 klog.Fatalf("role %q was already registered", role.Name) 44 } 45 } 46 47 *controllerRoles = append(*controllerRoles, role) 48 addClusterRoleLabel(*controllerRoles) 49 50 *controllerRoleBindings = append(*controllerRoleBindings, 51 rbacv1helpers.NewClusterBinding(role.Name).SAs("kube-system", role.Name[len(saRolePrefix):]).BindingOrDie()) 52 addClusterRoleBindingLabel(*controllerRoleBindings) 53 } 54 55 func eventsRule() rbacv1.PolicyRule { 56 return rbacv1helpers.NewRule("create", "update", "patch").Groups(legacyGroup, eventsGroup).Resources("events").RuleOrDie() 57 } 58 59 func buildControllerRoles() ([]rbacv1.ClusterRole, []rbacv1.ClusterRoleBinding) { 60 // controllerRoles is a slice of roles used for controllers 61 controllerRoles := []rbacv1.ClusterRole{} 62 // controllerRoleBindings is a slice of roles used for controllers 63 controllerRoleBindings := []rbacv1.ClusterRoleBinding{} 64 65 addControllerRole(&controllerRoles, &controllerRoleBindings, func() rbacv1.ClusterRole { 66 role := rbacv1.ClusterRole{ 67 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "attachdetach-controller"}, 68 Rules: []rbacv1.PolicyRule{ 69 rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("persistentvolumes", "persistentvolumeclaims").RuleOrDie(), 70 rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), 71 rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), 72 rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(), 73 eventsRule(), 74 rbacv1helpers.NewRule("get", "create", "delete", "list", "watch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie(), 75 }, 76 } 77 78 role.Rules = append(role.Rules, rbacv1helpers.NewRule("get", "watch", "list").Groups("storage.k8s.io").Resources("csidrivers").RuleOrDie()) 79 role.Rules = append(role.Rules, rbacv1helpers.NewRule("get", "watch", "list").Groups("storage.k8s.io").Resources("csinodes").RuleOrDie()) 80 81 return role 82 }()) 83 84 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 85 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "clusterrole-aggregation-controller"}, 86 Rules: []rbacv1.PolicyRule{ 87 // this controller must have full permissions on clusterroles to allow it to mutate them in any way 88 rbacv1helpers.NewRule("escalate", "get", "list", "watch", "update", "patch").Groups(rbacGroup).Resources("clusterroles").RuleOrDie(), 89 }, 90 }) 91 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 92 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "cronjob-controller"}, 93 Rules: []rbacv1.PolicyRule{ 94 rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(batchGroup).Resources("cronjobs").RuleOrDie(), 95 rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "delete", "patch").Groups(batchGroup).Resources("jobs").RuleOrDie(), 96 rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("cronjobs/status").RuleOrDie(), 97 rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("cronjobs/finalizers").RuleOrDie(), 98 rbacv1helpers.NewRule("list", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), 99 eventsRule(), 100 }, 101 }) 102 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 103 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "daemon-set-controller"}, 104 Rules: []rbacv1.PolicyRule{ 105 rbacv1helpers.NewRule("get", "list", "watch").Groups(extensionsGroup, appsGroup).Resources("daemonsets").RuleOrDie(), 106 rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("daemonsets/status").RuleOrDie(), 107 rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("daemonsets/finalizers").RuleOrDie(), 108 rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), 109 rbacv1helpers.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), 110 rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("pods/binding").RuleOrDie(), 111 rbacv1helpers.NewRule("get", "list", "watch", "create", "delete", "update", "patch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(), 112 eventsRule(), 113 }, 114 }) 115 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 116 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "deployment-controller"}, 117 Rules: []rbacv1.PolicyRule{ 118 rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(extensionsGroup, appsGroup).Resources("deployments").RuleOrDie(), 119 rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("deployments/status").RuleOrDie(), 120 rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("deployments/finalizers").RuleOrDie(), 121 rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "patch", "delete").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), 122 // TODO: remove "update" once 123 // https://github.com/kubernetes/kubernetes/issues/36897 is resolved. 124 rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("pods").RuleOrDie(), 125 eventsRule(), 126 }, 127 }) 128 addControllerRole(&controllerRoles, &controllerRoleBindings, func() rbacv1.ClusterRole { 129 role := rbacv1.ClusterRole{ 130 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "disruption-controller"}, 131 Rules: []rbacv1.PolicyRule{ 132 rbacv1helpers.NewRule("get", "list", "watch").Groups(extensionsGroup, appsGroup).Resources("deployments").RuleOrDie(), 133 rbacv1helpers.NewRule("get", "list", "watch").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), 134 rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("replicationcontrollers").RuleOrDie(), 135 rbacv1helpers.NewRule("get", "list", "watch").Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(), 136 rbacv1helpers.NewRule("get", "list", "watch").Groups(appsGroup).Resources("statefulsets").RuleOrDie(), 137 rbacv1helpers.NewRule("update").Groups(policyGroup).Resources("poddisruptionbudgets/status").RuleOrDie(), 138 rbacv1helpers.NewRule("get").Groups("*").Resources("*/scale").RuleOrDie(), 139 eventsRule(), 140 }, 141 } 142 if utilfeature.DefaultFeatureGate.Enabled(features.PodDisruptionConditions) { 143 role.Rules = append(role.Rules, rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("pods/status").RuleOrDie()) 144 } 145 return role 146 }()) 147 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 148 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "endpoint-controller"}, 149 Rules: []rbacv1.PolicyRule{ 150 rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services", "pods").RuleOrDie(), 151 rbacv1helpers.NewRule("get", "list", "create", "update", "delete").Groups(legacyGroup).Resources("endpoints").RuleOrDie(), 152 rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("endpoints/restricted").RuleOrDie(), 153 eventsRule(), 154 }, 155 }) 156 157 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 158 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "endpointslice-controller"}, 159 Rules: []rbacv1.PolicyRule{ 160 rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services", "pods", "nodes").RuleOrDie(), 161 // The controller needs to be able to set a service's finalizers to be able to create an EndpointSlice 162 // resource that is owned by the service and sets blockOwnerDeletion=true in its ownerRef. 163 rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("services/finalizers").RuleOrDie(), 164 rbacv1helpers.NewRule("get", "list", "create", "update", "delete").Groups(discoveryGroup).Resources("endpointslices").RuleOrDie(), 165 eventsRule(), 166 }, 167 }) 168 169 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 170 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "endpointslicemirroring-controller"}, 171 Rules: []rbacv1.PolicyRule{ 172 rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), 173 // The controller needs to be able to set a service's finalizers to be able to create an EndpointSlice 174 // resource that is owned by the service and sets blockOwnerDeletion=true in its ownerRef. 175 rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("services/finalizers").RuleOrDie(), 176 // The controller needs to be able to set a service's finalizers to be able to create an EndpointSlice 177 // resource that is owned by the endpoint and sets blockOwnerDeletion=true in its ownerRef. 178 // see https://github.com/openshift/kubernetes/blob/8691466059314c3f7d6dcffcbb76d14596ca716c/pkg/controller/endpointslicemirroring/utils.go#L87-L88 179 rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("endpoints/finalizers").RuleOrDie(), 180 rbacv1helpers.NewRule("get", "list", "create", "update", "delete").Groups(discoveryGroup).Resources("endpointslices").RuleOrDie(), 181 eventsRule(), 182 }, 183 }) 184 185 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 186 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "expand-controller"}, 187 Rules: []rbacv1.PolicyRule{ 188 rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), 189 rbacv1helpers.NewRule("update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie(), 190 rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), 191 // glusterfs 192 rbacv1helpers.NewRule("get", "list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(), 193 rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(), 194 rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("secrets").RuleOrDie(), 195 eventsRule(), 196 }, 197 }) 198 199 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 200 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "ephemeral-volume-controller"}, 201 Rules: []rbacv1.PolicyRule{ 202 rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(), 203 rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("pods/finalizers").RuleOrDie(), 204 rbacv1helpers.NewRule("get", "list", "watch", "create").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), 205 eventsRule(), 206 }, 207 }) 208 209 if utilfeature.DefaultFeatureGate.Enabled(features.DynamicResourceAllocation) { 210 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 211 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "resource-claim-controller"}, 212 Rules: []rbacv1.PolicyRule{ 213 rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(), 214 rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("pods/finalizers").RuleOrDie(), 215 rbacv1helpers.NewRule("get", "list", "watch", "create", "delete").Groups(resourceGroup).Resources("resourceclaims").RuleOrDie(), 216 rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "patch").Groups(resourceGroup).Resources("podschedulingcontexts").RuleOrDie(), 217 rbacv1helpers.NewRule("update", "patch").Groups(resourceGroup).Resources("resourceclaims", "resourceclaims/status").RuleOrDie(), 218 rbacv1helpers.NewRule("update", "patch").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), 219 eventsRule(), 220 }, 221 }) 222 } 223 224 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 225 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "generic-garbage-collector"}, 226 Rules: []rbacv1.PolicyRule{ 227 // the GC controller needs to run list/watches, selective gets, and updates against any resource 228 rbacv1helpers.NewRule("get", "list", "watch", "patch", "update", "delete").Groups("*").Resources("*").RuleOrDie(), 229 eventsRule(), 230 }, 231 }) 232 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 233 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "horizontal-pod-autoscaler"}, 234 Rules: []rbacv1.PolicyRule{ 235 rbacv1helpers.NewRule("get", "list", "watch").Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), 236 rbacv1helpers.NewRule("update").Groups(autoscalingGroup).Resources("horizontalpodautoscalers/status").RuleOrDie(), 237 rbacv1helpers.NewRule("get", "update").Groups("*").Resources("*/scale").RuleOrDie(), 238 rbacv1helpers.NewRule("list").Groups(legacyGroup).Resources("pods").RuleOrDie(), 239 // allow listing resource, custom, and external metrics 240 rbacv1helpers.NewRule("list").Groups(resMetricsGroup).Resources("pods").RuleOrDie(), 241 rbacv1helpers.NewRule("get", "list").Groups(customMetricsGroup).Resources("*").RuleOrDie(), 242 rbacv1helpers.NewRule("get", "list").Groups(externalMetricsGroup).Resources("*").RuleOrDie(), 243 eventsRule(), 244 }, 245 }) 246 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 247 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "job-controller"}, 248 Rules: []rbacv1.PolicyRule{ 249 rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(batchGroup).Resources("jobs").RuleOrDie(), 250 rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("jobs/status").RuleOrDie(), 251 rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("jobs/finalizers").RuleOrDie(), 252 rbacv1helpers.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), 253 eventsRule(), 254 }, 255 }) 256 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 257 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "namespace-controller"}, 258 Rules: []rbacv1.PolicyRule{ 259 rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("namespaces").RuleOrDie(), 260 rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("namespaces/finalize", "namespaces/status").RuleOrDie(), 261 rbacv1helpers.NewRule("get", "list", "delete", "deletecollection").Groups("*").Resources("*").RuleOrDie(), 262 }, 263 }) 264 addControllerRole(&controllerRoles, &controllerRoleBindings, func() rbacv1.ClusterRole { 265 role := rbacv1.ClusterRole{ 266 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "node-controller"}, 267 Rules: []rbacv1.PolicyRule{ 268 rbacv1helpers.NewRule("get", "list", "update", "delete", "patch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), 269 rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), 270 // used for pod deletion 271 rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(), 272 rbacv1helpers.NewRule("list", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), 273 eventsRule(), 274 }, 275 } 276 if utilfeature.DefaultFeatureGate.Enabled(features.PodDisruptionConditions) { 277 role.Rules = append(role.Rules, rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("pods").RuleOrDie()) 278 } 279 return role 280 }()) 281 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 282 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "persistent-volume-binder"}, 283 Rules: []rbacv1.PolicyRule{ 284 rbacv1helpers.NewRule("get", "list", "watch", "update", "create", "delete").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), 285 rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("persistentvolumes/status").RuleOrDie(), 286 rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), 287 rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie(), 288 rbacv1helpers.NewRule("list", "watch", "get", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), 289 290 // glusterfs 291 rbacv1helpers.NewRule("get", "list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(), 292 rbacv1helpers.NewRule("get", "create", "update", "delete").Groups(legacyGroup).Resources("endpoints").RuleOrDie(), 293 rbacv1helpers.NewRule("get", "create", "delete").Groups(legacyGroup).Resources("services").RuleOrDie(), 294 rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("secrets").RuleOrDie(), 295 // openstack 296 rbacv1helpers.NewRule("get", "list").Groups(legacyGroup).Resources("nodes").RuleOrDie(), 297 298 // recyclerClient.WatchPod 299 rbacv1helpers.NewRule("watch").Groups(legacyGroup).Resources("events").RuleOrDie(), 300 301 eventsRule(), 302 }, 303 }) 304 addControllerRole(&controllerRoles, &controllerRoleBindings, func() rbacv1.ClusterRole { 305 role := rbacv1.ClusterRole{ 306 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pod-garbage-collector"}, 307 Rules: []rbacv1.PolicyRule{ 308 rbacv1helpers.NewRule("list", "watch", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), 309 rbacv1helpers.NewRule("get", "list").Groups(legacyGroup).Resources("nodes").RuleOrDie(), 310 }, 311 } 312 if utilfeature.DefaultFeatureGate.Enabled(features.PodDisruptionConditions) { 313 role.Rules = append(role.Rules, rbacv1helpers.NewRule("patch").Groups(legacyGroup).Resources("pods/status").RuleOrDie()) 314 } 315 return role 316 }()) 317 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 318 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "replicaset-controller"}, 319 Rules: []rbacv1.PolicyRule{ 320 rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(), 321 rbacv1helpers.NewRule("update").Groups(appsGroup, extensionsGroup).Resources("replicasets/status").RuleOrDie(), 322 rbacv1helpers.NewRule("update").Groups(appsGroup, extensionsGroup).Resources("replicasets/finalizers").RuleOrDie(), 323 rbacv1helpers.NewRule("list", "watch", "patch", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), 324 eventsRule(), 325 }, 326 }) 327 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 328 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "replication-controller"}, 329 Rules: []rbacv1.PolicyRule{ 330 // 1.0 controllers needed get, update, so without these old controllers break on new servers 331 rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("replicationcontrollers").RuleOrDie(), 332 rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("replicationcontrollers/status").RuleOrDie(), 333 rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("replicationcontrollers/finalizers").RuleOrDie(), 334 rbacv1helpers.NewRule("list", "watch", "patch", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(), 335 eventsRule(), 336 }, 337 }) 338 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 339 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "resourcequota-controller"}, 340 Rules: []rbacv1.PolicyRule{ 341 // quota can count quota on anything for reconciliation, so it needs full viewing powers 342 rbacv1helpers.NewRule("list", "watch").Groups("*").Resources("*").RuleOrDie(), 343 rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("resourcequotas/status").RuleOrDie(), 344 eventsRule(), 345 }, 346 }) 347 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 348 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "route-controller"}, 349 Rules: []rbacv1.PolicyRule{ 350 rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), 351 rbacv1helpers.NewRule("patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(), 352 eventsRule(), 353 }, 354 }) 355 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 356 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "service-account-controller"}, 357 Rules: []rbacv1.PolicyRule{ 358 rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(), 359 eventsRule(), 360 }, 361 }) 362 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 363 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "service-controller"}, 364 Rules: []rbacv1.PolicyRule{ 365 rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services").RuleOrDie(), 366 rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("services/status").RuleOrDie(), 367 rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), 368 eventsRule(), 369 }, 370 }) 371 if utilfeature.DefaultFeatureGate.Enabled(features.MultiCIDRServiceAllocator) { 372 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 373 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "service-cidrs-controller"}, 374 Rules: []rbacv1.PolicyRule{ 375 rbacv1helpers.NewRule("get", "list", "watch", "patch", "update").Groups(networkingGroup).Resources("servicecidrs").RuleOrDie(), 376 rbacv1helpers.NewRule("patch", "update").Groups(networkingGroup).Resources("servicecidrs/finalizers").RuleOrDie(), 377 rbacv1helpers.NewRule("patch", "update").Groups(networkingGroup).Resources("servicecidrs/status").RuleOrDie(), 378 rbacv1helpers.NewRule("get", "list", "watch").Groups(networkingGroup).Resources("ipaddresses").RuleOrDie(), 379 eventsRule(), 380 }, 381 }) 382 } 383 addControllerRole(&controllerRoles, &controllerRoleBindings, func() rbacv1.ClusterRole { 384 role := rbacv1.ClusterRole{ 385 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "statefulset-controller"}, 386 Rules: []rbacv1.PolicyRule{ 387 rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(), 388 rbacv1helpers.NewRule("get", "list", "watch").Groups(appsGroup).Resources("statefulsets").RuleOrDie(), 389 rbacv1helpers.NewRule("update").Groups(appsGroup).Resources("statefulsets/status").RuleOrDie(), 390 rbacv1helpers.NewRule("update").Groups(appsGroup).Resources("statefulsets/finalizers").RuleOrDie(), 391 rbacv1helpers.NewRule("get", "create", "delete", "update", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(), 392 rbacv1helpers.NewRule("get", "create", "delete", "update", "patch", "list", "watch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(), 393 rbacv1helpers.NewRule("get", "create").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), 394 eventsRule(), 395 }, 396 } 397 398 if utilfeature.DefaultFeatureGate.Enabled(features.StatefulSetAutoDeletePVC) { 399 role.Rules = append(role.Rules, rbacv1helpers.NewRule("update", "delete").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie()) 400 } 401 402 return role 403 }()) 404 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 405 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "ttl-controller"}, 406 Rules: []rbacv1.PolicyRule{ 407 rbacv1helpers.NewRule("update", "patch", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), 408 eventsRule(), 409 }, 410 }) 411 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 412 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "certificate-controller"}, 413 Rules: []rbacv1.PolicyRule{ 414 rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(), 415 rbacv1helpers.NewRule("update").Groups(certificatesGroup).Resources("certificatesigningrequests/status", "certificatesigningrequests/approval").RuleOrDie(), 416 rbacv1helpers.NewRule("approve").Groups(certificatesGroup).Resources("signers").Names(capi.KubeAPIServerClientKubeletSignerName).RuleOrDie(), 417 rbacv1helpers.NewRule("sign").Groups(certificatesGroup).Resources("signers").Names( 418 capi.LegacyUnknownSignerName, 419 capi.KubeAPIServerClientSignerName, 420 capi.KubeAPIServerClientKubeletSignerName, 421 capi.KubeletServingSignerName, 422 ).RuleOrDie(), 423 rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(), 424 eventsRule(), 425 }, 426 }) 427 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 428 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pvc-protection-controller"}, 429 Rules: []rbacv1.PolicyRule{ 430 rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(), 431 rbacv1helpers.NewRule("list", "watch", "get").Groups(legacyGroup).Resources("pods").RuleOrDie(), 432 eventsRule(), 433 }, 434 }) 435 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 436 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pv-protection-controller"}, 437 Rules: []rbacv1.PolicyRule{ 438 rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(), 439 eventsRule(), 440 }, 441 }) 442 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 443 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "ttl-after-finished-controller"}, 444 Rules: []rbacv1.PolicyRule{ 445 rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(batchGroup).Resources("jobs").RuleOrDie(), 446 eventsRule(), 447 }, 448 }) 449 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 450 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "root-ca-cert-publisher"}, 451 Rules: []rbacv1.PolicyRule{ 452 rbacv1helpers.NewRule("create", "update").Groups(legacyGroup).Resources("configmaps").RuleOrDie(), 453 eventsRule(), 454 }, 455 }) 456 if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.ValidatingAdmissionPolicy) { 457 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 458 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "validatingadmissionpolicy-status-controller"}, 459 Rules: []rbacv1.PolicyRule{ 460 rbacv1helpers.NewRule("get", "list", "watch").Groups(admissionRegistrationGroup). 461 Resources("validatingadmissionpolicies").RuleOrDie(), 462 rbacv1helpers.NewRule("get", "patch", "update").Groups(admissionRegistrationGroup). 463 Resources("validatingadmissionpolicies/status").RuleOrDie(), 464 eventsRule(), 465 }, 466 }) 467 } 468 if utilfeature.DefaultFeatureGate.Enabled(genericfeatures.StorageVersionAPI) && 469 utilfeature.DefaultFeatureGate.Enabled(genericfeatures.APIServerIdentity) { 470 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 471 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "storage-version-garbage-collector"}, 472 Rules: []rbacv1.PolicyRule{ 473 rbacv1helpers.NewRule("get", "list", "watch").Groups(coordinationGroup).Resources("leases").RuleOrDie(), 474 rbacv1helpers.NewRule("get", "list", "watch", "patch", "update", "delete").Groups(internalAPIServerGroup). 475 Resources("storageversions").RuleOrDie(), 476 rbacv1helpers.NewRule("get", "patch", "update").Groups(internalAPIServerGroup). 477 Resources("storageversions/status").RuleOrDie(), 478 }, 479 }) 480 } 481 482 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 483 ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "legacy-service-account-token-cleaner"}, 484 Rules: []rbacv1.PolicyRule{ 485 rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("configmaps").Names(legacytokentracking.ConfigMapName).RuleOrDie(), 486 rbacv1helpers.NewRule("patch", "delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(), 487 }, 488 }) 489 490 if utilfeature.DefaultFeatureGate.Enabled(features.StorageVersionMigrator) { 491 addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{ 492 ObjectMeta: metav1.ObjectMeta{ 493 Name: saRolePrefix + "storage-version-migrator-controller", 494 }, 495 Rules: []rbacv1.PolicyRule{ 496 rbacv1helpers.NewRule("list", "patch").Groups("*").Resources("*").RuleOrDie(), 497 rbacv1helpers.NewRule("update").Groups(storageVersionMigrationGroup).Resources("storageversionmigrations/status").RuleOrDie(), 498 }, 499 }) 500 } 501 502 return controllerRoles, controllerRoleBindings 503 } 504 505 // ControllerRoles returns the cluster roles used by controllers 506 func ControllerRoles() []rbacv1.ClusterRole { 507 controllerRoles, _ := buildControllerRoles() 508 return controllerRoles 509 } 510 511 // ControllerRoleBindings returns the role bindings used by controllers 512 func ControllerRoleBindings() []rbacv1.ClusterRoleBinding { 513 _, controllerRoleBindings := buildControllerRoles() 514 return controllerRoleBindings 515 }