// ChangedClusterRoles returns the roles that must be created and/or updated to // match the recommended bootstrap policy func (o *ReconcileClusterRolesOptions) ChangedClusterRoles() ([]*authorizationapi.ClusterRole, error) { changedRoles := []*authorizationapi.ClusterRole{} bootstrapClusterRoles := bootstrappolicy.GetBootstrapClusterRoles() for i := range bootstrapClusterRoles { expectedClusterRole := &bootstrapClusterRoles[i] actualClusterRole, err := o.RoleClient.Get(expectedClusterRole.Name) if kapierrors.IsNotFound(err) { changedRoles = append(changedRoles, expectedClusterRole) continue } if err != nil { return nil, err } if !kapi.Semantic.DeepEqual(expectedClusterRole.Rules, actualClusterRole.Rules) { if o.Union { _, missingRules := rulevalidation.Covers(expectedClusterRole.Rules, actualClusterRole.Rules) expectedClusterRole.Rules = append(expectedClusterRole.Rules, missingRules...) } changedRoles = append(changedRoles, expectedClusterRole) } } return changedRoles, nil }
// ChangedClusterRoles returns the roles that must be created and/or updated to // match the recommended bootstrap policy func (o *ReconcileClusterRolesOptions) ChangedClusterRoles() ([]*authorizationapi.ClusterRole, error) { changedRoles := []*authorizationapi.ClusterRole{} bootstrapClusterRoles := bootstrappolicy.GetBootstrapClusterRoles() for i := range bootstrapClusterRoles { expectedClusterRole := &bootstrapClusterRoles[i] actualClusterRole, err := o.RoleClient.Get(expectedClusterRole.Name) if kapierrors.IsNotFound(err) { changedRoles = append(changedRoles, expectedClusterRole) continue } if err != nil { return nil, err } // Copy any existing labels/annotations, so the displayed update is correct // This assumes bootstrap roles will not set any labels/annotations // These aren't actually used during update; the latest labels/annotations are pulled from the existing object again expectedClusterRole.Labels = actualClusterRole.Labels expectedClusterRole.Annotations = actualClusterRole.Annotations if !kapi.Semantic.DeepEqual(expectedClusterRole.Rules, actualClusterRole.Rules) { if o.Union { _, missingRules := rulevalidation.Covers(expectedClusterRole.Rules, actualClusterRole.Rules) expectedClusterRole.Rules = append(expectedClusterRole.Rules, missingRules...) } changedRoles = append(changedRoles, expectedClusterRole) } } return changedRoles, nil }
func TestBootstrapClusterRoles(t *testing.T) { roles := bootstrappolicy.GetBootstrapClusterRoles() list := &api.List{} for i := range roles { list.Items = append(list.Items, &roles[i]) } testObjects(t, list, "bootstrap_cluster_roles.yaml") }
func (o CreateBootstrapPolicyFileOptions) CreateBootstrapPolicyFile() error { if err := os.MkdirAll(path.Dir(o.File), os.FileMode(0755)); err != nil { return err } policyTemplate := &api.Template{} clusterRoles := bootstrappolicy.GetBootstrapClusterRoles() for i := range clusterRoles { versionedObject, err := kapi.Scheme.ConvertToVersion(&clusterRoles[i], latest.Version.String()) if err != nil { return err } policyTemplate.Objects = append(policyTemplate.Objects, versionedObject) } clusterRoleBindings := bootstrappolicy.GetBootstrapClusterRoleBindings() for i := range clusterRoleBindings { versionedObject, err := kapi.Scheme.ConvertToVersion(&clusterRoleBindings[i], latest.Version.String()) if err != nil { return err } policyTemplate.Objects = append(policyTemplate.Objects, versionedObject) } openshiftRoles := bootstrappolicy.GetBootstrapOpenshiftRoles(o.OpenShiftSharedResourcesNamespace) for i := range openshiftRoles { versionedObject, err := kapi.Scheme.ConvertToVersion(&openshiftRoles[i], latest.Version.String()) if err != nil { return err } policyTemplate.Objects = append(policyTemplate.Objects, versionedObject) } openshiftRoleBindings := bootstrappolicy.GetBootstrapOpenshiftRoleBindings(o.OpenShiftSharedResourcesNamespace) for i := range openshiftRoleBindings { versionedObject, err := kapi.Scheme.ConvertToVersion(&openshiftRoleBindings[i], latest.Version.String()) if err != nil { return err } policyTemplate.Objects = append(policyTemplate.Objects, versionedObject) } versionedPolicyTemplate, err := kapi.Scheme.ConvertToVersion(policyTemplate, latest.Version.String()) if err != nil { return err } buffer := &bytes.Buffer{} (&kubectl.JSONPrinter{}).PrintObj(versionedPolicyTemplate, buffer) if err := ioutil.WriteFile(o.File, buffer.Bytes(), 0644); err != nil { return err } return nil }
// ChangedClusterRoles returns the roles that must be created and/or updated to // match the recommended bootstrap policy func (o *ReconcileClusterRolesOptions) ChangedClusterRoles() ([]*authorizationapi.ClusterRole, []*authorizationapi.ClusterRole, error) { changedRoles := []*authorizationapi.ClusterRole{} skippedRoles := []*authorizationapi.ClusterRole{} rolesToReconcile := sets.NewString(o.RolesToReconcile...) rolesNotFound := sets.NewString(o.RolesToReconcile...) bootstrapClusterRoles := bootstrappolicy.GetBootstrapClusterRoles() for i := range bootstrapClusterRoles { expectedClusterRole := &bootstrapClusterRoles[i] if (len(rolesToReconcile) > 0) && !rolesToReconcile.Has(expectedClusterRole.Name) { continue } rolesNotFound.Delete(expectedClusterRole.Name) actualClusterRole, err := o.RoleClient.Get(expectedClusterRole.Name) if kapierrors.IsNotFound(err) { changedRoles = append(changedRoles, expectedClusterRole) continue } if err != nil { return nil, nil, err } // Copy any existing labels/annotations, so the displayed update is correct // This assumes bootstrap roles will not set any labels/annotations // These aren't actually used during update; the latest labels/annotations are pulled from the existing object again expectedClusterRole.Labels = actualClusterRole.Labels expectedClusterRole.Annotations = actualClusterRole.Annotations _, extraRules := rulevalidation.Covers(expectedClusterRole.Rules, actualClusterRole.Rules) _, missingRules := rulevalidation.Covers(actualClusterRole.Rules, expectedClusterRole.Rules) // We need to reconcile: // 1. if we're missing rules // 2. if there are extra rules we need to remove if (len(missingRules) > 0) || (!o.Union && len(extraRules) > 0) { if o.Union { expectedClusterRole.Rules = append(expectedClusterRole.Rules, extraRules...) } if actualClusterRole.Annotations[ReconcileProtectAnnotation] == "true" { skippedRoles = append(skippedRoles, expectedClusterRole) } else { changedRoles = append(changedRoles, expectedClusterRole) } } } if len(rolesNotFound) != 0 { // return the known changes and the error so that a caller can decide if he wants a partial update return changedRoles, skippedRoles, fmt.Errorf("did not find requested cluster role %s", rolesNotFound.List()) } return changedRoles, skippedRoles, nil }
// Some roles should always cover others func TestCovers(t *testing.T) { allRoles := bootstrappolicy.GetBootstrapClusterRoles() var admin *authorizationapi.ClusterRole var editor *authorizationapi.ClusterRole var viewer *authorizationapi.ClusterRole var registryAdmin *authorizationapi.ClusterRole var registryEditor *authorizationapi.ClusterRole var registryViewer *authorizationapi.ClusterRole for i := range allRoles { role := allRoles[i] switch role.Name { case bootstrappolicy.AdminRoleName: admin = &role case bootstrappolicy.EditRoleName: editor = &role case bootstrappolicy.ViewRoleName: viewer = &role case bootstrappolicy.RegistryAdminRoleName: registryAdmin = &role case bootstrappolicy.RegistryEditorRoleName: registryEditor = &role case bootstrappolicy.RegistryViewerRoleName: registryViewer = &role } } if covers, _ := rulevalidation.Covers(admin.Rules, editor.Rules); !covers { t.Errorf("failed to cover") } if covers, _ := rulevalidation.Covers(admin.Rules, editor.Rules); !covers { t.Errorf("failed to cover") } if covers, _ := rulevalidation.Covers(admin.Rules, viewer.Rules); !covers { t.Errorf("failed to cover") } if covers, _ := rulevalidation.Covers(admin.Rules, registryAdmin.Rules); !covers { t.Errorf("failed to cover") } if covers, _ := rulevalidation.Covers(registryAdmin.Rules, registryEditor.Rules); !covers { t.Errorf("failed to cover") } if covers, _ := rulevalidation.Covers(registryAdmin.Rules, registryViewer.Rules); !covers { t.Errorf("failed to cover") } }
func GetBootstrapPolicy() *authorizationapi.ClusterPolicy { policy := &authorizationapi.ClusterPolicy{ ObjectMeta: kapi.ObjectMeta{ Name: authorizationapi.PolicyName, CreationTimestamp: unversioned.Now(), UID: util.NewUUID(), }, LastModified: unversioned.Now(), Roles: make(map[string]*authorizationapi.ClusterRole), } roles := bootstrappolicy.GetBootstrapClusterRoles() for i := range roles { policy.Roles[roles[i].Name] = &roles[i] } return policy }
// leave this in place so I can use when converting the SAs func DisableTestClusterRoles(t *testing.T) { currentRoles := bootstrappolicy.GetBootstrapClusterRoles() oldRoles := oldGetBootstrapClusterRoles() // old roles don't have the SAs appended, so run through them. The SAs haven't been converted yet for i := range oldRoles { oldRole := oldRoles[i] newRole := currentRoles[i] if oldRole.Name != newRole.Name { t.Fatalf("%v vs %v", oldRole.Name, newRole.Name) } // @liggitt don't whine about a temporary test fataling if covers, missing := rulevalidation.Covers(oldRole.Rules, newRole.Rules); !covers { t.Fatalf("%v/%v: %#v", oldRole.Name, newRole.Name, missing) } if covers, missing := rulevalidation.Covers(newRole.Rules, oldRole.Rules); !covers { t.Fatalf("%v/%v: %#v", oldRole.Name, newRole.Name, missing) } } }
// Some roles should always cover others func TestCovers(t *testing.T) { allRoles := bootstrappolicy.GetBootstrapClusterRoles() var admin *authorizationapi.ClusterRole var editor *authorizationapi.ClusterRole var viewer *authorizationapi.ClusterRole var registryAdmin *authorizationapi.ClusterRole var registryEditor *authorizationapi.ClusterRole var registryViewer *authorizationapi.ClusterRole var systemMaster *authorizationapi.ClusterRole var systemDiscovery *authorizationapi.ClusterRole var clusterAdmin *authorizationapi.ClusterRole var storageAdmin *authorizationapi.ClusterRole for i := range allRoles { role := allRoles[i] switch role.Name { case bootstrappolicy.AdminRoleName: admin = &role case bootstrappolicy.EditRoleName: editor = &role case bootstrappolicy.ViewRoleName: viewer = &role case bootstrappolicy.RegistryAdminRoleName: registryAdmin = &role case bootstrappolicy.RegistryEditorRoleName: registryEditor = &role case bootstrappolicy.RegistryViewerRoleName: registryViewer = &role case bootstrappolicy.MasterRoleName: systemMaster = &role case bootstrappolicy.DiscoveryRoleName: systemDiscovery = &role case bootstrappolicy.ClusterAdminRoleName: clusterAdmin = &role case bootstrappolicy.StorageAdminRoleName: storageAdmin = &role } } if covers, miss := rulevalidation.Covers(admin.Rules, editor.Rules); !covers { t.Errorf("failed to cover: %#v", miss) } if covers, miss := rulevalidation.Covers(admin.Rules, editor.Rules); !covers { t.Errorf("failed to cover: %#v", miss) } if covers, miss := rulevalidation.Covers(admin.Rules, viewer.Rules); !covers { t.Errorf("failed to cover: %#v", miss) } if covers, miss := rulevalidation.Covers(admin.Rules, registryAdmin.Rules); !covers { t.Errorf("failed to cover: %#v", miss) } if covers, miss := rulevalidation.Covers(clusterAdmin.Rules, storageAdmin.Rules); !covers { t.Errorf("failed to cover: %#v", miss) } if covers, miss := rulevalidation.Covers(registryAdmin.Rules, registryEditor.Rules); !covers { t.Errorf("failed to cover: %#v", miss) } if covers, miss := rulevalidation.Covers(registryAdmin.Rules, registryViewer.Rules); !covers { t.Errorf("failed to cover: %#v", miss) } // Make sure we can auto-reconcile discovery if covers, miss := rulevalidation.Covers(systemMaster.Rules, systemDiscovery.Rules); !covers { t.Errorf("failed to cover: %#v", miss) } // Make sure the master has full permissions if covers, miss := rulevalidation.Covers(systemMaster.Rules, clusterAdmin.Rules); !covers { t.Errorf("failed to cover: %#v", miss) } }