func TestClusterRoleLabel(t *testing.T) { roles := bootstrappolicy.ClusterRoles() for i := range roles { role := roles[i] accessor, err := meta.Accessor(&role) if err != nil { t.Fatalf("unexpected error: %v", err) } if got, want := accessor.GetLabels(), map[string]string{"kubernetes.io/bootstrapping": "rbac-defaults"}; !reflect.DeepEqual(got, want) { t.Errorf("ClusterRole: %s GetLabels() = %s, want %s", accessor.GetName(), got, want) } } rolebindings := bootstrappolicy.ClusterRoleBindings() for i := range rolebindings { rolebinding := rolebindings[i] accessor, err := meta.Accessor(&rolebinding) if err != nil { t.Fatalf("unexpected error: %v", err) } if got, want := accessor.GetLabels(), map[string]string{"kubernetes.io/bootstrapping": "rbac-defaults"}; !reflect.DeepEqual(got, want) { t.Errorf("ClusterRoleBinding: %s GetLabels() = %s, want %s", accessor.GetName(), got, want) } } }
func TestEditViewRelationship(t *testing.T) { readVerbs := sets.NewString(bootstrappolicy.Read...) semanticRoles := getSemanticRoles(bootstrappolicy.ClusterRoles()) // modify the edit role rules to make then read-only for comparison against view role rules for i := range semanticRoles.edit.Rules { rule := semanticRoles.edit.Rules[i] remainingVerbs := []string{} for _, verb := range rule.Verbs { if readVerbs.Has(verb) { remainingVerbs = append(remainingVerbs, verb) } } rule.Verbs = remainingVerbs semanticRoles.edit.Rules[i] = rule } // confirm that the view role doesn't already have extra powers for _, rule := range viewEscalatingNamespaceResources { if covers, _ := rbacvalidation.Covers(semanticRoles.view.Rules, []rbac.PolicyRule{rule}); covers { t.Errorf("view has extra powers: %#v", rule) } } semanticRoles.view.Rules = append(semanticRoles.view.Rules, viewEscalatingNamespaceResources...) // at this point, we should have a two way covers relationship if covers, miss := rbacvalidation.Covers(semanticRoles.edit.Rules, semanticRoles.view.Rules); !covers { t.Errorf("edit has lost rules for: %#v", miss) } if covers, miss := rbacvalidation.Covers(semanticRoles.view.Rules, semanticRoles.edit.Rules); !covers { t.Errorf("view is missing rules for: %#v\nIf these are escalating powers, add them to the list. Otherwise, add them to the view role.", miss) } }
func newPostStartHook(directClusterRoleAccess *clusterroleetcd.REST) genericapiserver.PostStartHookFunc { return func(genericapiserver.PostStartHookContext) error { ctx := api.NewContext() existingClusterRoles, err := directClusterRoleAccess.List(ctx, &api.ListOptions{}) if err != nil { utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) return nil } // if clusterroles already exist, then assume we don't have work to do because we've already // initialized or another API server has started this task if len(existingClusterRoles.(*rbac.ClusterRoleList).Items) > 0 { return nil } for _, clusterRole := range bootstrappolicy.ClusterRoles() { if _, err := directClusterRoleAccess.Create(ctx, &clusterRole); err != nil { // don't fail on failures, try to create as many as you can utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) continue } glog.Infof("Created clusterrole.%s/%s", rbac.GroupName, clusterRole.Name) } return nil } }
func PostStartHook(hookContext genericapiserver.PostStartHookContext) error { clientset, err := rbacclient.NewForConfig(hookContext.LoopbackClientConfig) if err != nil { utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) return nil } existingClusterRoles, err := clientset.ClusterRoles().List(api.ListOptions{}) if err != nil { utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) return nil } // if clusterroles already exist, then assume we don't have work to do because we've already // initialized or another API server has started this task if len(existingClusterRoles.Items) > 0 { return nil } for _, clusterRole := range append(bootstrappolicy.ClusterRoles(), bootstrappolicy.ControllerRoles()...) { if _, err := clientset.ClusterRoles().Create(&clusterRole); err != nil { // don't fail on failures, try to create as many as you can utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) continue } glog.Infof("Created clusterrole.%s/%s", rbac.GroupName, clusterRole.Name) } return nil }
func PostStartHook(hookContext genericapiserver.PostStartHookContext) error { // intializing roles is really important. On some e2e runs, we've seen cases where etcd is down when the server // starts, the roles don't initialize, and nothing works. err := wait.Poll(1*time.Second, 30*time.Second, func() (done bool, err error) { clientset, err := rbacclient.NewForConfig(hookContext.LoopbackClientConfig) if err != nil { utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) return false, nil } existingClusterRoles, err := clientset.ClusterRoles().List(api.ListOptions{}) if err != nil { utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) return false, nil } // only initialized on empty etcd if len(existingClusterRoles.Items) == 0 { for _, clusterRole := range append(bootstrappolicy.ClusterRoles(), bootstrappolicy.ControllerRoles()...) { if _, err := clientset.ClusterRoles().Create(&clusterRole); err != nil { // don't fail on failures, try to create as many as you can utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) continue } glog.Infof("Created clusterrole.%s/%s", rbac.GroupName, clusterRole.Name) } } existingClusterRoleBindings, err := clientset.ClusterRoleBindings().List(api.ListOptions{}) if err != nil { utilruntime.HandleError(fmt.Errorf("unable to initialize clusterrolebindings: %v", err)) return false, nil } // only initialized on empty etcd if len(existingClusterRoleBindings.Items) == 0 { for _, clusterRoleBinding := range append(bootstrappolicy.ClusterRoleBindings(), bootstrappolicy.ControllerRoleBindings()...) { if _, err := clientset.ClusterRoleBindings().Create(&clusterRoleBinding); err != nil { // don't fail on failures, try to create as many as you can utilruntime.HandleError(fmt.Errorf("unable to initialize clusterrolebindings: %v", err)) continue } glog.Infof("Created clusterrolebinding.%s/%s", rbac.GroupName, clusterRoleBinding.Name) } } return true, nil }) // if we're never able to make it through intialization, kill the API server if err != nil { return fmt.Errorf("unable to initialize roles: %v", err) } return nil }
// Some roles should always cover others func TestCovers(t *testing.T) { semanticRoles := getSemanticRoles(bootstrappolicy.ClusterRoles()) if covers, miss := rbacvalidation.Covers(semanticRoles.admin.Rules, semanticRoles.edit.Rules); !covers { t.Errorf("failed to cover: %#v", miss) } if covers, miss := rbacvalidation.Covers(semanticRoles.admin.Rules, semanticRoles.view.Rules); !covers { t.Errorf("failed to cover: %#v", miss) } if covers, miss := rbacvalidation.Covers(semanticRoles.edit.Rules, semanticRoles.view.Rules); !covers { t.Errorf("failed to cover: %#v", miss) } }
func TestBootstrapClusterRoles(t *testing.T) { list := &api.List{} names := sets.NewString() roles := map[string]runtime.Object{} bootstrapRoles := bootstrappolicy.ClusterRoles() for i := range bootstrapRoles { role := bootstrapRoles[i] names.Insert(role.Name) roles[role.Name] = &role } for _, name := range names.List() { list.Items = append(list.Items, roles[name]) } testObjects(t, list, "cluster-roles.yaml") }
func TestAdminEditRelationship(t *testing.T) { semanticRoles := getSemanticRoles(bootstrappolicy.ClusterRoles()) // confirm that the edit role doesn't already have extra powers for _, rule := range additionalAdminPowers { if covers, _ := rbacvalidation.Covers(semanticRoles.edit.Rules, []rbac.PolicyRule{rule}); covers { t.Errorf("edit has extra powers: %#v", rule) } } semanticRoles.edit.Rules = append(semanticRoles.edit.Rules, additionalAdminPowers...) // at this point, we should have a two way covers relationship if covers, miss := rbacvalidation.Covers(semanticRoles.admin.Rules, semanticRoles.edit.Rules); !covers { t.Errorf("admin has lost rules for: %#v", miss) } if covers, miss := rbacvalidation.Covers(semanticRoles.edit.Rules, semanticRoles.admin.Rules); !covers { t.Errorf("edit is missing rules for: %#v\nIf these should only be admin powers, add them to the list. Otherwise, add them to the edit role.", miss) } }