...

Source file src/k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy/controller_policy.go

Documentation: k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy

     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  }
   516  

View as plain text