add namespaced role bindings

This commit is contained in:
deads2k 2017-02-28 11:11:32 -05:00
parent a849df9dff
commit e24b1c0c25
5 changed files with 100 additions and 0 deletions

View File

@ -282,6 +282,22 @@ func NewRoleBinding(roleName, namespace string) *RoleBindingBuilder {
}
}
func NewRoleBindingForClusterRole(roleName, namespace string) *RoleBindingBuilder {
return &RoleBindingBuilder{
RoleBinding: RoleBinding{
ObjectMeta: metav1.ObjectMeta{
Name: roleName,
Namespace: namespace,
},
RoleRef: RoleRef{
APIGroup: GroupName,
Kind: "ClusterRole",
Name: roleName,
},
},
}
}
// Groups adds the specified groups as the subjects of the RoleBinding.
func (r *RoleBindingBuilder) Groups(groups ...string) *RoleBindingBuilder {
for _, group := range groups {

View File

@ -233,6 +233,38 @@ func PostStartHook(hookContext genericapiserver.PostStartHookContext) error {
}
}
// ensure bootstrap namespaced rolebindings are created or reconciled
for namespace, roleBindings := range bootstrappolicy.NamespaceRoleBindings() {
for _, roleBinding := range roleBindings {
opts := reconciliation.ReconcileRoleBindingOptions{
RoleBinding: reconciliation.RoleBindingAdapter{RoleBinding: &roleBinding},
Client: reconciliation.RoleBindingClientAdapter{Client: clientset},
Confirm: true,
}
err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
result, err := opts.Run()
if err != nil {
return err
}
switch {
case result.Protected && result.Operation != reconciliation.ReconcileNone:
glog.Warningf("skipped reconcile-protected rolebinding.%s/%s in %v with missing subjects: %v", rbac.GroupName, roleBinding.Name, namespace, result.MissingSubjects)
case result.Operation == reconciliation.ReconcileUpdate:
glog.Infof("updated rolebinding.%s/%s in %v with additional subjects: %v", rbac.GroupName, roleBinding.Name, namespace, result.MissingSubjects)
case result.Operation == reconciliation.ReconcileCreate:
glog.Infof("created rolebinding.%s/%s in %v", rbac.GroupName, roleBinding.Name, namespace)
case result.Operation == reconciliation.ReconcileRecreate:
glog.Infof("recreated rolebinding.%s/%s in %v", rbac.GroupName, roleBinding.Name, namespace)
}
return nil
})
if err != nil {
// don't fail on failures, try to create as many as you can
utilruntime.HandleError(fmt.Errorf("unable to reconcile rolebinding.%s/%s in %v: %v", rbac.GroupName, roleBinding.Name, namespace, err))
}
}
}
return true, nil
})
// if we're never able to make it through intialization, kill the API server

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
@ -63,3 +84,8 @@ func init() {
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

@ -173,6 +173,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,4 @@
apiVersion: v1
items: null
kind: List
metadata: {}