Merge pull request #42259 from deads2k/rbac-07-reconcile-binding

Automatic merge from submit-queue

Add RBAC roles for bootstrap controllers

Supercedes https://github.com/kubernetes/kubernetes/pull/42221

When locking down controllers to individual RBAC roles we need to make sure that the bootstrap controllers have the right permissions.

This adds the roles and bindings at the correct namespace scopes for the bootstrap-signer and token-cleaner controllers.

@liggitt ptal
@jbeda @luxas you got a good way to test this?  It must not be covered in normal e2e or we'd've seen the issue before.
This commit is contained in:
Kubernetes Submit Queue
2017-03-01 16:57:51 -08:00
committed by GitHub
15 changed files with 635 additions and 106 deletions

View File

@@ -28,6 +28,9 @@ import (
var (
// namespaceRoles is a map of namespace to slice of roles to create
namespaceRoles = map[string][]rbac.Role{}
// namespaceRoleBindings is a map of namespace to slice of roleBindings to create
namespaceRoleBindings = map[string][]rbac.RoleBinding{}
)
func addNamespaceRole(namespace string, role rbac.Role) {
@@ -48,6 +51,24 @@ func addNamespaceRole(namespace string, role rbac.Role) {
namespaceRoles[namespace] = existingRoles
}
func addNamespaceRoleBinding(namespace string, roleBinding rbac.RoleBinding) {
if !strings.HasPrefix(namespace, "kube-") {
glog.Fatalf(`roles can only be bootstrapped into reserved namespaces starting with "kube-", not %q`, namespace)
}
existingRoleBindings := namespaceRoleBindings[namespace]
for _, existingRoleBinding := range existingRoleBindings {
if roleBinding.Name == existingRoleBinding.Name {
glog.Fatalf("rolebinding %q was already registered in %q", roleBinding.Name, namespace)
}
}
roleBinding.Namespace = namespace
addDefaultMetadata(&roleBinding)
existingRoleBindings = append(existingRoleBindings, roleBinding)
namespaceRoleBindings[namespace] = existingRoleBindings
}
func init() {
addNamespaceRole(metav1.NamespaceSystem, rbac.Role{
// role for finding authentication config info for starting a server
@@ -57,9 +78,46 @@ func init() {
rbac.NewRule("get").Groups(legacyGroup).Resources("configmaps").Names("extension-apiserver-authentication").RuleOrDie(),
},
})
addNamespaceRole(metav1.NamespaceSystem, rbac.Role{
// role for the bootstrap signer to be able to inspect kube-system secrets
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "bootstrap-signer"},
Rules: []rbac.PolicyRule{
rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("secrets").RuleOrDie(),
},
})
addNamespaceRole(metav1.NamespaceSystem, rbac.Role{
// role for the token-cleaner to be able to remove secrets, but only in kube-system
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "token-cleaner"},
Rules: []rbac.PolicyRule{
rbac.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(),
eventsRule(),
},
})
addNamespaceRoleBinding(metav1.NamespaceSystem,
rbac.NewRoleBinding(saRolePrefix+"bootstrap-signer", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "bootstrap-signer").BindingOrDie())
addNamespaceRoleBinding(metav1.NamespaceSystem,
rbac.NewRoleBinding(saRolePrefix+"token-cleaner", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "token-cleaner").BindingOrDie())
addNamespaceRole(metav1.NamespacePublic, rbac.Role{
// role for the bootstrap signer to be able to write its configmap
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "bootstrap-signer"},
Rules: []rbac.PolicyRule{
rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(),
rbac.NewRule("update").Groups(legacyGroup).Resources("configmaps").Names("cluster-info").RuleOrDie(),
eventsRule(),
},
})
addNamespaceRoleBinding(metav1.NamespacePublic,
rbac.NewRoleBinding(saRolePrefix+"bootstrap-signer", metav1.NamespacePublic).SAs(metav1.NamespaceSystem, "bootstrap-signer").BindingOrDie())
}
// NamespaceRoles returns a map of namespace to slice of roles to create
func NamespaceRoles() map[string][]rbac.Role {
return namespaceRoles
}
// NamespaceRoleBindings returns a map of namespace to slice of roles to create
func NamespaceRoleBindings() map[string][]rbac.RoleBinding {
return namespaceRoleBindings
}

View File

@@ -187,6 +187,28 @@ func TestBootstrapNamespaceRoles(t *testing.T) {
testObjects(t, list, "namespace-roles.yaml")
}
func TestBootstrapNamespaceRoleBindings(t *testing.T) {
list := &api.List{}
names := sets.NewString()
roleBindings := map[string]runtime.Object{}
namespaceRoleBindings := bootstrappolicy.NamespaceRoleBindings()
for _, namespace := range sets.StringKeySet(namespaceRoleBindings).List() {
bootstrapRoleBindings := namespaceRoleBindings[namespace]
for i := range bootstrapRoleBindings {
roleBinding := bootstrapRoleBindings[i]
names.Insert(roleBinding.Name)
roleBindings[roleBinding.Name] = &roleBinding
}
for _, name := range names.List() {
list.Items = append(list.Items, roleBindings[name])
}
}
testObjects(t, list, "namespace-role-bindings.yaml")
}
func TestBootstrapClusterRoles(t *testing.T) {
list := &api.List{}
names := sets.NewString()

View File

@@ -0,0 +1,58 @@
apiVersion: v1
items:
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:controller:bootstrap-signer
namespace: kube-public
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: system:controller:bootstrap-signer
subjects:
- kind: ServiceAccount
name: bootstrap-signer
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:controller:bootstrap-signer
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: system:controller:bootstrap-signer
subjects:
- kind: ServiceAccount
name: bootstrap-signer
namespace: kube-system
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:controller:token-cleaner
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: system:controller:token-cleaner
subjects:
- kind: ServiceAccount
name: token-cleaner
namespace: kube-system
kind: List
metadata: {}

View File

@@ -1,5 +1,40 @@
apiVersion: v1
items:
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:controller:bootstrap-signer
namespace: kube-public
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
- apiGroups:
- ""
resourceNames:
- cluster-info
resources:
- configmaps
verbs:
- update
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- update
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
@@ -19,5 +54,52 @@ items:
- configmaps
verbs:
- get
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:controller:bootstrap-signer
namespace: kube-system
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- watch
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:controller:token-cleaner
namespace: kube-system
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- delete
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- update
kind: List
metadata: {}