mirror of
https://gitee.com/rancher/rancher.git
synced 2025-12-06 07:49:17 +08:00
[RoleTemplate Aggregation] Use RoleBindings for Management Plane Rules (#52650)
* Change from using clusterrolebinding to rolebinding * Remove references to clusterrolebindings * Use CreateOrUpdate helper function instead of just create * Fix tests
This commit is contained in:
committed by
GitHub
parent
265cbbdc1b
commit
67b0d930cc
@@ -23,26 +23,26 @@ const (
|
||||
const (
|
||||
// Statuses
|
||||
clusterRoleTemplateBindingDelete = "ClusterRoleTemplateBindingDelete"
|
||||
removeClusterRoleBindings = "RemoveClusterRoleBindings"
|
||||
removeRoleBindings = "RemoveRoleBindings"
|
||||
reconcileSubject = "ReconcileSubject"
|
||||
reconcileMembershipBindings = "ReconcileMembershipBindings"
|
||||
reconcileBindings = "ReconcileBindings"
|
||||
// Reasons
|
||||
clusterRoleBindingDeleted = "ClusterRoleBindingDeleted"
|
||||
roleBindingDeleted = "roleBindingDeleted"
|
||||
bindingsExists = "BindingsExists"
|
||||
membershipBindingExists = "MembershipBindingExists"
|
||||
subjectExists = "SubjectExists"
|
||||
crtbHasNoSubject = "CRTBHasNoSubject"
|
||||
clusterMembershipBindingDeleted = "ClusterMembershipBindingDeleted"
|
||||
authv2ProvisioningBindingDeleted = "AuthV2ProvisioningBindingDeleted"
|
||||
failedToCreateClusterRoleBinding = "FailedToCreateClusterRoleBinding"
|
||||
failedToCreateRoleBinding = "FailedToCreateRoleBinding"
|
||||
failedToCreateOrUpdateMembershipBinding = "FailedToCreateOrUpdateMembershipBinding"
|
||||
failedToCreateUser = "FailedToCreateUser"
|
||||
failedToDeleteClusterRoleBinding = "FailedToDeleteClusterRoleBinding"
|
||||
failedToGetDesiredClusterRoleBindings = "FailedToGetDesiredClusterRoleBindings"
|
||||
failedToDeleteRoleBinding = "FailedToDeleteRoleBinding"
|
||||
failedToGetDesiredRoleBindings = "FailedToGetDesiredRoleBindings"
|
||||
failedToGetRoleTemplate = "FailedToGetRoleTemplate"
|
||||
failedToGetUser = "FailedToGetUser"
|
||||
failedToListExistingClusterRoleBindings = "FailedToGetExistingClusterRoleBindings"
|
||||
failedToListExistingRoleBindings = "FailedToGetExistingRoleBindings"
|
||||
)
|
||||
|
||||
// createOrUpdateClusterMembershipBinding ensures that the user specified by a CRTB or PRTB has membership to the cluster referenced by the CRTB or PRTB.
|
||||
@@ -174,7 +174,7 @@ func createOrUpdateProjectMembershipBinding(prtb *v3.ProjectRoleTemplateBinding,
|
||||
return err
|
||||
}
|
||||
|
||||
if !rbac.AreRoleBindingContentsSame(wantedRB, existingRB) {
|
||||
if ok, _ := rbac.AreRoleBindingContentsSame(wantedRB, existingRB); !ok {
|
||||
if err := rbController.Delete(wantedRB.Namespace, wantedRB.Name, &metav1.DeleteOptions{}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -132,40 +132,40 @@ func (c *crtbHandler) reconcileMembershipBindings(crtb *v3.ClusterRoleTemplateBi
|
||||
}
|
||||
|
||||
// reconcileBindings Ensures that all bindings required to provide access to the CRTB either exist or get created.
|
||||
// It deletes any of the existing CRBs that are not needed.
|
||||
// It deletes any existing role bindings with the CRTB owner label that are not needed.
|
||||
func (c *crtbHandler) reconcileBindings(crtb *v3.ClusterRoleTemplateBinding, localConditions *[]metav1.Condition) error {
|
||||
condition := metav1.Condition{Type: reconcileBindings}
|
||||
desiredCRBs, err := c.getDesiredClusterRoleBindings(crtb)
|
||||
desiredRBs, err := c.getDesiredRoleBindings(crtb)
|
||||
if err != nil {
|
||||
c.s.AddCondition(localConditions, condition, failedToGetDesiredClusterRoleBindings, err)
|
||||
c.s.AddCondition(localConditions, condition, failedToGetDesiredRoleBindings, err)
|
||||
return err
|
||||
}
|
||||
|
||||
currentCRBs, err := c.crbController.List(metav1.ListOptions{LabelSelector: rbac.GetCRTBOwnerLabel(crtb.Name)})
|
||||
currentRBs, err := c.rbController.List(crtb.Namespace, metav1.ListOptions{LabelSelector: rbac.GetCRTBOwnerLabel(crtb.Name)})
|
||||
if err != nil {
|
||||
c.s.AddCondition(localConditions, condition, failedToListExistingClusterRoleBindings, err)
|
||||
c.s.AddCondition(localConditions, condition, failedToListExistingRoleBindings, err)
|
||||
return err
|
||||
}
|
||||
|
||||
for _, currentCRB := range currentCRBs.Items {
|
||||
if crb, ok := desiredCRBs[currentCRB.Name]; ok {
|
||||
if rbac.AreClusterRoleBindingContentsSame(¤tCRB, crb) {
|
||||
// If the cluster role binding already exists with the right contents, we can skip creating it.
|
||||
delete(desiredCRBs, crb.Name)
|
||||
for _, currentRB := range currentRBs.Items {
|
||||
if rb, ok := desiredRBs[currentRB.Name]; ok {
|
||||
if ok, _ := rbac.AreRoleBindingContentsSame(¤tRB, rb); ok {
|
||||
// If the role binding already exists with the right contents, we can skip creating it.
|
||||
delete(desiredRBs, rb.Name)
|
||||
continue
|
||||
}
|
||||
}
|
||||
// If the CRB is not a member of the desired CRBs or has different contents, delete it.
|
||||
if err := c.crbController.Delete(currentCRB.Name, &metav1.DeleteOptions{}); err != nil {
|
||||
c.s.AddCondition(localConditions, condition, failedToDeleteClusterRoleBinding, err)
|
||||
// If the role binding is not a member of the desired role bindings or has different contents, delete it.
|
||||
if err := c.rbController.Delete(currentRB.Namespace, currentRB.Name, &metav1.DeleteOptions{}); err != nil {
|
||||
c.s.AddCondition(localConditions, condition, failedToDeleteRoleBinding, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// For any CRBs that don't exist, create them
|
||||
for _, crb := range desiredCRBs {
|
||||
if _, err := c.crbController.Create(crb); err != nil {
|
||||
c.s.AddCondition(localConditions, condition, failedToCreateClusterRoleBinding, err)
|
||||
// For any role bindings that don't exist, create them
|
||||
for _, rb := range desiredRBs {
|
||||
if err := rbac.CreateOrUpdateNamespacedResource(rb, c.rbController, rbac.AreRoleBindingContentsSame); err != nil {
|
||||
c.s.AddCondition(localConditions, condition, failedToCreateRoleBinding, err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -174,18 +174,18 @@ func (c *crtbHandler) reconcileBindings(crtb *v3.ClusterRoleTemplateBinding, loc
|
||||
return nil
|
||||
}
|
||||
|
||||
// getDesiredClusterRoleBindings checks for project and cluster management roles, and if they exist, builds and returns the needed ClusterRoleBindings
|
||||
func (c *crtbHandler) getDesiredClusterRoleBindings(crtb *v3.ClusterRoleTemplateBinding) (map[string]*rbacv1.ClusterRoleBinding, error) {
|
||||
desiredCRBs := map[string]*rbacv1.ClusterRoleBinding{}
|
||||
// getDesiredRoleBindings checks for project and cluster management roles, and if they exist, builds and returns the needed RoleBindings
|
||||
func (c *crtbHandler) getDesiredRoleBindings(crtb *v3.ClusterRoleTemplateBinding) (map[string]*rbacv1.RoleBinding, error) {
|
||||
desiredRBs := map[string]*rbacv1.RoleBinding{}
|
||||
// Check if there is a project management role to bind to
|
||||
projectManagementRoleName := rbac.ProjectManagementPlaneClusterRoleNameFor(crtb.RoleTemplateName)
|
||||
cr, err := c.crController.Get(rbac.AggregatedClusterRoleNameFor(projectManagementRoleName), metav1.GetOptions{})
|
||||
if err == nil && cr != nil {
|
||||
crb, err := rbac.BuildAggregatingClusterRoleBindingFromRTB(crtb, projectManagementRoleName)
|
||||
rb, err := rbac.BuildAggregatingRoleBindingFromRTB(crtb, projectManagementRoleName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
desiredCRBs[crb.Name] = crb
|
||||
desiredRBs[rb.Name] = rb
|
||||
} else if !apierrors.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
@@ -194,16 +194,16 @@ func (c *crtbHandler) getDesiredClusterRoleBindings(crtb *v3.ClusterRoleTemplate
|
||||
clusterManagementRoleName := rbac.ClusterManagementPlaneClusterRoleNameFor(crtb.RoleTemplateName)
|
||||
cr, err = c.crController.Get(rbac.AggregatedClusterRoleNameFor(clusterManagementRoleName), metav1.GetOptions{})
|
||||
if err == nil && cr != nil {
|
||||
crb, err := rbac.BuildAggregatingClusterRoleBindingFromRTB(crtb, clusterManagementRoleName)
|
||||
rb, err := rbac.BuildAggregatingRoleBindingFromRTB(crtb, clusterManagementRoleName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
desiredCRBs[crb.Name] = crb
|
||||
desiredRBs[rb.Name] = rb
|
||||
} else if !apierrors.IsNotFound(err) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return desiredCRBs, nil
|
||||
return desiredRBs, nil
|
||||
}
|
||||
|
||||
// OnRemove deletes Cluster Role Bindings that are owned by the CRTB and the membership binding if no other CRTBs give membership access.
|
||||
@@ -220,28 +220,28 @@ func (c *crtbHandler) OnRemove(_ string, crtb *v3.ClusterRoleTemplateBinding) (*
|
||||
err = removeAuthV2Permissions(crtb, c.rbController)
|
||||
c.s.AddCondition(&crtb.Status.LocalConditions, condition, authv2ProvisioningBindingDeleted, err)
|
||||
|
||||
return crtb, errors.Join(err, c.removeClusterRoleBindings(crtb))
|
||||
return crtb, errors.Join(err, c.removeRoleBindings(crtb))
|
||||
}
|
||||
|
||||
// removeClusterRoleBindings removes all bindings owned by the CRTB
|
||||
func (c *crtbHandler) removeClusterRoleBindings(crtb *v3.ClusterRoleTemplateBinding) error {
|
||||
condition := metav1.Condition{Type: removeClusterRoleBindings}
|
||||
currentCRBs, err := c.crbController.List(metav1.ListOptions{LabelSelector: rbac.GetCRTBOwnerLabel(crtb.Name)})
|
||||
func (c *crtbHandler) removeRoleBindings(crtb *v3.ClusterRoleTemplateBinding) error {
|
||||
condition := metav1.Condition{Type: removeRoleBindings}
|
||||
currentRBs, err := c.rbController.List(crtb.Namespace, metav1.ListOptions{LabelSelector: rbac.GetCRTBOwnerLabel(crtb.Name)})
|
||||
if err != nil {
|
||||
c.s.AddCondition(&crtb.Status.LocalConditions, condition, failedToListExistingClusterRoleBindings, err)
|
||||
c.s.AddCondition(&crtb.Status.LocalConditions, condition, failedToListExistingRoleBindings, err)
|
||||
return err
|
||||
}
|
||||
|
||||
var returnErr error
|
||||
for _, crb := range currentCRBs.Items {
|
||||
err = rbac.DeleteResource(crb.Name, c.crbController)
|
||||
for _, rb := range currentRBs.Items {
|
||||
err = rbac.DeleteNamespacedResource(crtb.Namespace, rb.Name, c.rbController)
|
||||
if err != nil {
|
||||
c.s.AddCondition(&crtb.Status.LocalConditions, condition, failedToDeleteClusterRoleBinding, err)
|
||||
c.s.AddCondition(&crtb.Status.LocalConditions, condition, failedToDeleteRoleBinding, err)
|
||||
returnErr = errors.Join(returnErr, err)
|
||||
}
|
||||
}
|
||||
|
||||
c.s.AddCondition(&crtb.Status.LocalConditions, condition, clusterRoleBindingDeleted, returnErr)
|
||||
c.s.AddCondition(&crtb.Status.LocalConditions, condition, roleBindingDeleted, returnErr)
|
||||
return returnErr
|
||||
}
|
||||
|
||||
|
||||
@@ -299,12 +299,12 @@ const (
|
||||
clusterMGMT = "test-rt-cluster-mgmt-aggregator"
|
||||
)
|
||||
|
||||
func Test_crtbHandler_getDesiredClusterRoleBindings(t *testing.T) {
|
||||
func Test_crtbHandler_getDesiredRoleBindings(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
crtb *v3.ClusterRoleTemplateBinding
|
||||
setupCRBController func(*fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRole, *rbacv1.ClusterRoleList])
|
||||
want map[string]*rbacv1.ClusterRoleBinding
|
||||
want map[string]*rbacv1.RoleBinding
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
@@ -331,7 +331,7 @@ func Test_crtbHandler_getDesiredClusterRoleBindings(t *testing.T) {
|
||||
m.EXPECT().Get(projectMGMT, metav1.GetOptions{}).Return(nil, errNotFound)
|
||||
m.EXPECT().Get(clusterMGMT, metav1.GetOptions{}).Return(nil, errNotFound)
|
||||
},
|
||||
want: map[string]*rbacv1.ClusterRoleBinding{},
|
||||
want: map[string]*rbacv1.RoleBinding{},
|
||||
},
|
||||
{
|
||||
name: "found project management plane role",
|
||||
@@ -340,18 +340,19 @@ func Test_crtbHandler_getDesiredClusterRoleBindings(t *testing.T) {
|
||||
m.EXPECT().Get(projectMGMT, metav1.GetOptions{}).Return(&rbacv1.ClusterRole{}, nil)
|
||||
m.EXPECT().Get(clusterMGMT, metav1.GetOptions{}).Return(nil, errNotFound)
|
||||
},
|
||||
want: map[string]*rbacv1.ClusterRoleBinding{
|
||||
"crb-5x2rfzlbvz": {
|
||||
want: map[string]*rbacv1.RoleBinding{
|
||||
"rb-visjzlqzqw": {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "crb-5x2rfzlbvz",
|
||||
Labels: map[string]string{"authz.cluster.cattle.io/crtb-owner-test-crtb": "true"},
|
||||
Name: "rb-visjzlqzqw",
|
||||
Namespace: "test-namespace",
|
||||
Labels: map[string]string{"authz.cluster.cattle.io/crtb-owner-test-crtb": "true"},
|
||||
},
|
||||
RoleRef: rbacv1.RoleRef{
|
||||
APIGroup: "rbac.authorization.k8s.io",
|
||||
Kind: "ClusterRole",
|
||||
Name: projectMGMT,
|
||||
},
|
||||
Subjects: defaultCRB.Subjects,
|
||||
Subjects: defaultRB.Subjects,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -362,18 +363,19 @@ func Test_crtbHandler_getDesiredClusterRoleBindings(t *testing.T) {
|
||||
m.EXPECT().Get(projectMGMT, metav1.GetOptions{}).Return(nil, errNotFound)
|
||||
m.EXPECT().Get(clusterMGMT, metav1.GetOptions{}).Return(&rbacv1.ClusterRole{}, nil)
|
||||
},
|
||||
want: map[string]*rbacv1.ClusterRoleBinding{
|
||||
"crb-meemnnklov": {
|
||||
want: map[string]*rbacv1.RoleBinding{
|
||||
"rb-lhchhtbxqn": {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "crb-meemnnklov",
|
||||
Labels: map[string]string{"authz.cluster.cattle.io/crtb-owner-test-crtb": "true"},
|
||||
Name: "rb-lhchhtbxqn",
|
||||
Namespace: "test-namespace",
|
||||
Labels: map[string]string{"authz.cluster.cattle.io/crtb-owner-test-crtb": "true"},
|
||||
},
|
||||
RoleRef: rbacv1.RoleRef{
|
||||
APIGroup: "rbac.authorization.k8s.io",
|
||||
Kind: "ClusterRole",
|
||||
Name: clusterMGMT,
|
||||
},
|
||||
Subjects: defaultCRB.Subjects,
|
||||
Subjects: defaultRB.Subjects,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -384,30 +386,32 @@ func Test_crtbHandler_getDesiredClusterRoleBindings(t *testing.T) {
|
||||
m.EXPECT().Get(projectMGMT, metav1.GetOptions{}).Return(&rbacv1.ClusterRole{}, nil)
|
||||
m.EXPECT().Get(clusterMGMT, metav1.GetOptions{}).Return(&rbacv1.ClusterRole{}, nil)
|
||||
},
|
||||
want: map[string]*rbacv1.ClusterRoleBinding{
|
||||
"crb-meemnnklov": {
|
||||
want: map[string]*rbacv1.RoleBinding{
|
||||
"rb-lhchhtbxqn": {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "crb-meemnnklov",
|
||||
Labels: map[string]string{"authz.cluster.cattle.io/crtb-owner-test-crtb": "true"},
|
||||
Name: "rb-lhchhtbxqn",
|
||||
Namespace: "test-namespace",
|
||||
Labels: map[string]string{"authz.cluster.cattle.io/crtb-owner-test-crtb": "true"},
|
||||
},
|
||||
RoleRef: rbacv1.RoleRef{
|
||||
APIGroup: "rbac.authorization.k8s.io",
|
||||
Kind: "ClusterRole",
|
||||
Name: clusterMGMT,
|
||||
},
|
||||
Subjects: defaultCRB.Subjects,
|
||||
Subjects: defaultRB.Subjects,
|
||||
},
|
||||
"crb-5x2rfzlbvz": {
|
||||
"rb-visjzlqzqw": {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "crb-5x2rfzlbvz",
|
||||
Labels: map[string]string{"authz.cluster.cattle.io/crtb-owner-test-crtb": "true"},
|
||||
Name: "rb-visjzlqzqw",
|
||||
Namespace: "test-namespace",
|
||||
Labels: map[string]string{"authz.cluster.cattle.io/crtb-owner-test-crtb": "true"},
|
||||
},
|
||||
RoleRef: rbacv1.RoleRef{
|
||||
APIGroup: "rbac.authorization.k8s.io",
|
||||
Kind: "ClusterRole",
|
||||
Name: projectMGMT,
|
||||
},
|
||||
Subjects: defaultCRB.Subjects,
|
||||
Subjects: defaultRB.Subjects,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -423,13 +427,13 @@ func Test_crtbHandler_getDesiredClusterRoleBindings(t *testing.T) {
|
||||
s: status.NewStatus(),
|
||||
crController: crController,
|
||||
}
|
||||
got, err := c.getDesiredClusterRoleBindings(tt.crtb)
|
||||
got, err := c.getDesiredRoleBindings(tt.crtb)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("crtbHandler.getDesiredClusterRoleBindings() error = %v, wantErr %v", err, tt.wantErr)
|
||||
t.Errorf("crtbHandler.getDesiredRoleBindings() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("crtbHandler.getDesiredClusterRoleBindings() = %v, want %v", got, tt.want)
|
||||
t.Errorf("crtbHandler.getDesiredRoleBindings() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"github.com/rancher/rancher/pkg/types/config"
|
||||
"github.com/rancher/rancher/pkg/user"
|
||||
crbacv1 "github.com/rancher/wrangler/v3/pkg/generated/controllers/rbac/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
@@ -67,13 +66,13 @@ func (p *prtbHandler) OnRemove(_ string, prtb *v3.ProjectRoleTemplateBinding) (*
|
||||
deleteProjectMembershipBinding(prtb, p.rbController),
|
||||
removeAuthV2Permissions(prtb, p.rbController))
|
||||
|
||||
currentCRBs, err := p.crbController.List(metav1.ListOptions{LabelSelector: rbac.GetPRTBOwnerLabel(prtb.Name)})
|
||||
currentRBs, err := p.rbController.List(prtb.Namespace, metav1.ListOptions{LabelSelector: rbac.GetPRTBOwnerLabel(prtb.Name)})
|
||||
if err != nil {
|
||||
return nil, errors.Join(returnErr, err)
|
||||
}
|
||||
|
||||
for _, crb := range currentCRBs.Items {
|
||||
returnErr = errors.Join(returnErr, rbac.DeleteResource(crb.Name, p.crbController))
|
||||
for _, rb := range currentRBs.Items {
|
||||
returnErr = errors.Join(returnErr, rbac.DeleteNamespacedResource(rb.Namespace, rb.Name, p.rbController))
|
||||
}
|
||||
|
||||
return prtb, returnErr
|
||||
@@ -126,10 +125,8 @@ func (p *prtbHandler) reconcileMembershipBindings(prtb *v3.ProjectRoleTemplateBi
|
||||
createOrUpdateProjectMembershipBinding(prtb, rt, p.rbController))
|
||||
}
|
||||
|
||||
// reconcileBindings ensures the right CRB exists for the project management plane role. It deletes any additional unwanted CRBs.
|
||||
// reconcileBindings ensures the right Role Binding exists for the project management plane role. It deletes any additional unwanted Role Bindings.
|
||||
func (p *prtbHandler) reconcileBindings(prtb *v3.ProjectRoleTemplateBinding) error {
|
||||
var crb *rbacv1.ClusterRoleBinding
|
||||
|
||||
projectManagementRoleName := rbac.ProjectManagementPlaneClusterRoleNameFor(prtb.RoleTemplateName)
|
||||
|
||||
// If there is no project management plane role, no need to create a binding for it
|
||||
@@ -141,29 +138,29 @@ func (p *prtbHandler) reconcileBindings(prtb *v3.ProjectRoleTemplateBinding) err
|
||||
return err
|
||||
}
|
||||
|
||||
crb, err = rbac.BuildAggregatingClusterRoleBindingFromRTB(prtb, projectManagementRoleName)
|
||||
rb, err := rbac.BuildAggregatingRoleBindingFromRTB(prtb, projectManagementRoleName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
currentCRBs, err := p.crbController.List(metav1.ListOptions{LabelSelector: rbac.GetPRTBOwnerLabel(prtb.Name)})
|
||||
currentRBs, err := p.rbController.List(prtb.Namespace, metav1.ListOptions{LabelSelector: rbac.GetPRTBOwnerLabel(prtb.Name)})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var prtbHasBinding bool
|
||||
for _, currentCRB := range currentCRBs.Items {
|
||||
if rbac.AreClusterRoleBindingContentsSame(¤tCRB, crb) {
|
||||
for _, currentRB := range currentRBs.Items {
|
||||
if ok, _ := rbac.AreRoleBindingContentsSame(¤tRB, rb); ok {
|
||||
prtbHasBinding = true
|
||||
continue
|
||||
}
|
||||
if err := rbac.DeleteResource(currentCRB.Name, p.crbController); err != nil {
|
||||
if err := rbac.DeleteNamespacedResource(currentRB.Namespace, currentRB.Name, p.rbController); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !prtbHasBinding {
|
||||
if _, err := p.crbController.Create(crb); err != nil {
|
||||
if err := rbac.CreateOrUpdateNamespacedResource(rb, p.rbController, rbac.AreRoleBindingContentsSame); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,10 +179,11 @@ func Test_reconcileSubject(t *testing.T) {
|
||||
|
||||
var (
|
||||
ownerLabel = "authz.cluster.cattle.io/prtb-owner-test-prtb"
|
||||
defaultCRB = rbacv1.ClusterRoleBinding{
|
||||
defaultRB = rbacv1.RoleBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "crb-5x2rfzlbvz",
|
||||
Labels: map[string]string{"authz.cluster.cattle.io/prtb-owner-test-prtb": "true"},
|
||||
Name: "rb-visjzlqzqw",
|
||||
Namespace: "test-namespace",
|
||||
Labels: map[string]string{"authz.cluster.cattle.io/prtb-owner-test-prtb": "true"},
|
||||
},
|
||||
RoleRef: rbacv1.RoleRef{
|
||||
Kind: "ClusterRole",
|
||||
@@ -198,16 +199,22 @@ var (
|
||||
},
|
||||
},
|
||||
}
|
||||
badRB = rbacv1.RoleBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "bad-crb",
|
||||
Namespace: "test-namespace",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func Test_reconcileBindings(t *testing.T) {
|
||||
t.Parallel()
|
||||
tests := []struct {
|
||||
name string
|
||||
setupCRController func(*fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRole, *rbacv1.ClusterRoleList])
|
||||
setupCRBController func(*fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRoleBinding, *rbacv1.ClusterRoleBindingList])
|
||||
prtb *v3.ProjectRoleTemplateBinding
|
||||
wantErr bool
|
||||
name string
|
||||
setupCRController func(*fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRole, *rbacv1.ClusterRoleList])
|
||||
setupRBController func(*fake.MockControllerInterface[*rbacv1.RoleBinding, *rbacv1.RoleBindingList])
|
||||
prtb *v3.ProjectRoleTemplateBinding
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "error getting cluster role",
|
||||
@@ -230,7 +237,7 @@ func Test_reconcileBindings(t *testing.T) {
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "error building clusterrolebinding",
|
||||
name: "error building rolebinding",
|
||||
setupCRController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRole, *rbacv1.ClusterRoleList]) {
|
||||
m.EXPECT().Get("test-rt-project-mgmt-aggregator", metav1.GetOptions{}).Return(nil, nil)
|
||||
},
|
||||
@@ -240,128 +247,107 @@ func Test_reconcileBindings(t *testing.T) {
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "error listing clusterrolebindings",
|
||||
name: "error listing rolebindings",
|
||||
setupCRController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRole, *rbacv1.ClusterRoleList]) {
|
||||
m.EXPECT().Get("test-rt-project-mgmt-aggregator", metav1.GetOptions{}).Return(nil, nil)
|
||||
},
|
||||
setupCRBController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRoleBinding, *rbacv1.ClusterRoleBindingList]) {
|
||||
m.EXPECT().List(metav1.ListOptions{LabelSelector: ownerLabel}).Return(nil, errDefault)
|
||||
},
|
||||
prtb: &v3.ProjectRoleTemplateBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-prtb"},
|
||||
UserName: "test-user",
|
||||
RoleTemplateName: "test-rt",
|
||||
setupRBController: func(m *fake.MockControllerInterface[*rbacv1.RoleBinding, *rbacv1.RoleBindingList]) {
|
||||
m.EXPECT().List("test-namespace", metav1.ListOptions{LabelSelector: ownerLabel}).Return(nil, errDefault)
|
||||
},
|
||||
prtb: defaultPRTB.DeepCopy(),
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "error listing clusterrolebindings",
|
||||
name: "error listing rolebindings",
|
||||
setupCRController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRole, *rbacv1.ClusterRoleList]) {
|
||||
m.EXPECT().Get("test-rt-project-mgmt-aggregator", metav1.GetOptions{}).Return(nil, nil)
|
||||
},
|
||||
setupCRBController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRoleBinding, *rbacv1.ClusterRoleBindingList]) {
|
||||
m.EXPECT().List(metav1.ListOptions{LabelSelector: ownerLabel}).Return(nil, errDefault)
|
||||
},
|
||||
prtb: &v3.ProjectRoleTemplateBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-prtb"},
|
||||
UserName: "test-user",
|
||||
RoleTemplateName: "test-rt",
|
||||
setupRBController: func(m *fake.MockControllerInterface[*rbacv1.RoleBinding, *rbacv1.RoleBindingList]) {
|
||||
m.EXPECT().List("test-namespace", metav1.ListOptions{LabelSelector: ownerLabel}).Return(nil, errDefault)
|
||||
},
|
||||
prtb: defaultPRTB.DeepCopy(),
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "error deleting unwanted clusterrolebindings",
|
||||
name: "error deleting unwanted rolebindings",
|
||||
setupCRController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRole, *rbacv1.ClusterRoleList]) {
|
||||
m.EXPECT().Get("test-rt-project-mgmt-aggregator", metav1.GetOptions{}).Return(nil, nil)
|
||||
},
|
||||
setupCRBController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRoleBinding, *rbacv1.ClusterRoleBindingList]) {
|
||||
m.EXPECT().List(metav1.ListOptions{LabelSelector: ownerLabel}).Return(&rbacv1.ClusterRoleBindingList{
|
||||
Items: []rbacv1.ClusterRoleBinding{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bad-crb"},
|
||||
},
|
||||
},
|
||||
setupRBController: func(m *fake.MockControllerInterface[*rbacv1.RoleBinding, *rbacv1.RoleBindingList]) {
|
||||
m.EXPECT().List("test-namespace", metav1.ListOptions{LabelSelector: ownerLabel}).Return(&rbacv1.RoleBindingList{
|
||||
Items: []rbacv1.RoleBinding{badRB},
|
||||
}, nil)
|
||||
m.EXPECT().Delete("bad-crb", &metav1.DeleteOptions{}).Return(errDefault)
|
||||
},
|
||||
prtb: &v3.ProjectRoleTemplateBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-prtb"},
|
||||
UserName: "test-user",
|
||||
RoleTemplateName: "test-rt",
|
||||
m.EXPECT().Delete("test-namespace", "bad-crb", &metav1.DeleteOptions{}).Return(errDefault)
|
||||
},
|
||||
prtb: defaultPRTB.DeepCopy(),
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "CRB already exists",
|
||||
name: "RB already exists",
|
||||
setupCRController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRole, *rbacv1.ClusterRoleList]) {
|
||||
m.EXPECT().Get("test-rt-project-mgmt-aggregator", metav1.GetOptions{}).Return(nil, nil)
|
||||
},
|
||||
setupCRBController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRoleBinding, *rbacv1.ClusterRoleBindingList]) {
|
||||
m.EXPECT().List(metav1.ListOptions{LabelSelector: ownerLabel}).Return(&rbacv1.ClusterRoleBindingList{
|
||||
Items: []rbacv1.ClusterRoleBinding{defaultCRB},
|
||||
setupRBController: func(m *fake.MockControllerInterface[*rbacv1.RoleBinding, *rbacv1.RoleBindingList]) {
|
||||
m.EXPECT().List("test-namespace", metav1.ListOptions{LabelSelector: ownerLabel}).Return(&rbacv1.RoleBindingList{
|
||||
Items: []rbacv1.RoleBinding{defaultRB},
|
||||
}, nil)
|
||||
},
|
||||
prtb: &v3.ProjectRoleTemplateBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-prtb"},
|
||||
UserName: "test-user",
|
||||
RoleTemplateName: "test-rt",
|
||||
},
|
||||
prtb: defaultPRTB.DeepCopy(),
|
||||
},
|
||||
{
|
||||
name: "CRB already exists with extra bad CRBs",
|
||||
name: "RB already exists with extra bad RBs",
|
||||
setupCRController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRole, *rbacv1.ClusterRoleList]) {
|
||||
m.EXPECT().Get("test-rt-project-mgmt-aggregator", metav1.GetOptions{}).Return(nil, nil)
|
||||
},
|
||||
setupCRBController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRoleBinding, *rbacv1.ClusterRoleBindingList]) {
|
||||
m.EXPECT().List(metav1.ListOptions{LabelSelector: ownerLabel}).Return(&rbacv1.ClusterRoleBindingList{
|
||||
Items: []rbacv1.ClusterRoleBinding{
|
||||
defaultCRB,
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bad-crb"},
|
||||
},
|
||||
},
|
||||
setupRBController: func(m *fake.MockControllerInterface[*rbacv1.RoleBinding, *rbacv1.RoleBindingList]) {
|
||||
m.EXPECT().List("test-namespace", metav1.ListOptions{LabelSelector: ownerLabel}).Return(&rbacv1.RoleBindingList{
|
||||
Items: []rbacv1.RoleBinding{defaultRB, badRB},
|
||||
}, nil)
|
||||
m.EXPECT().Delete("bad-crb", &metav1.DeleteOptions{}).Return(nil)
|
||||
},
|
||||
prtb: &v3.ProjectRoleTemplateBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-prtb"},
|
||||
UserName: "test-user",
|
||||
RoleTemplateName: "test-rt",
|
||||
m.EXPECT().Delete("test-namespace", "bad-crb", &metav1.DeleteOptions{}).Return(nil)
|
||||
},
|
||||
prtb: defaultPRTB.DeepCopy(),
|
||||
},
|
||||
{
|
||||
name: "CRB needs to be created",
|
||||
name: "RB needs to be created",
|
||||
setupCRController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRole, *rbacv1.ClusterRoleList]) {
|
||||
m.EXPECT().Get("test-rt-project-mgmt-aggregator", metav1.GetOptions{}).Return(nil, nil)
|
||||
},
|
||||
setupCRBController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRoleBinding, *rbacv1.ClusterRoleBindingList]) {
|
||||
m.EXPECT().List(metav1.ListOptions{LabelSelector: ownerLabel}).Return(&rbacv1.ClusterRoleBindingList{
|
||||
Items: []rbacv1.ClusterRoleBinding{},
|
||||
setupRBController: func(m *fake.MockControllerInterface[*rbacv1.RoleBinding, *rbacv1.RoleBindingList]) {
|
||||
m.EXPECT().List("test-namespace", metav1.ListOptions{LabelSelector: ownerLabel}).Return(&rbacv1.RoleBindingList{
|
||||
Items: []rbacv1.RoleBinding{},
|
||||
}, nil)
|
||||
m.EXPECT().Create(defaultCRB.DeepCopy()).Return(nil, nil)
|
||||
},
|
||||
prtb: &v3.ProjectRoleTemplateBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-prtb"},
|
||||
UserName: "test-user",
|
||||
RoleTemplateName: "test-rt",
|
||||
m.EXPECT().Get("test-namespace", defaultRB.Name, metav1.GetOptions{}).Return(nil, errNotFound)
|
||||
m.EXPECT().Create(defaultRB.DeepCopy()).Return(nil, nil)
|
||||
},
|
||||
prtb: defaultPRTB.DeepCopy(),
|
||||
},
|
||||
{
|
||||
name: "error creating CRB",
|
||||
name: "error creating RB",
|
||||
setupCRController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRole, *rbacv1.ClusterRoleList]) {
|
||||
m.EXPECT().Get("test-rt-project-mgmt-aggregator", metav1.GetOptions{}).Return(nil, nil)
|
||||
},
|
||||
setupCRBController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRoleBinding, *rbacv1.ClusterRoleBindingList]) {
|
||||
m.EXPECT().List(metav1.ListOptions{LabelSelector: ownerLabel}).Return(&rbacv1.ClusterRoleBindingList{
|
||||
Items: []rbacv1.ClusterRoleBinding{},
|
||||
setupRBController: func(m *fake.MockControllerInterface[*rbacv1.RoleBinding, *rbacv1.RoleBindingList]) {
|
||||
m.EXPECT().List("test-namespace", metav1.ListOptions{LabelSelector: ownerLabel}).Return(&rbacv1.RoleBindingList{
|
||||
Items: []rbacv1.RoleBinding{},
|
||||
}, nil)
|
||||
m.EXPECT().Create(defaultCRB.DeepCopy()).Return(nil, errDefault)
|
||||
m.EXPECT().Get("test-namespace", defaultRB.Name, metav1.GetOptions{}).Return(nil, errNotFound)
|
||||
m.EXPECT().Create(defaultRB.DeepCopy()).Return(nil, errDefault)
|
||||
},
|
||||
prtb: &v3.ProjectRoleTemplateBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test-prtb"},
|
||||
UserName: "test-user",
|
||||
RoleTemplateName: "test-rt",
|
||||
prtb: defaultPRTB.DeepCopy(),
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "error getting RB",
|
||||
setupCRController: func(m *fake.MockNonNamespacedControllerInterface[*rbacv1.ClusterRole, *rbacv1.ClusterRoleList]) {
|
||||
m.EXPECT().Get("test-rt-project-mgmt-aggregator", metav1.GetOptions{}).Return(nil, nil)
|
||||
},
|
||||
setupRBController: func(m *fake.MockControllerInterface[*rbacv1.RoleBinding, *rbacv1.RoleBindingList]) {
|
||||
m.EXPECT().List("test-namespace", metav1.ListOptions{LabelSelector: ownerLabel}).Return(&rbacv1.RoleBindingList{
|
||||
Items: []rbacv1.RoleBinding{},
|
||||
}, nil)
|
||||
m.EXPECT().Get("test-namespace", defaultRB.Name, metav1.GetOptions{}).Return(nil, errDefault)
|
||||
},
|
||||
prtb: defaultPRTB.DeepCopy(),
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
@@ -369,9 +355,9 @@ func Test_reconcileBindings(t *testing.T) {
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
crbController := fake.NewMockNonNamespacedControllerInterface[*rbacv1.ClusterRoleBinding, *rbacv1.ClusterRoleBindingList](ctrl)
|
||||
if tt.setupCRBController != nil {
|
||||
tt.setupCRBController(crbController)
|
||||
rbController := fake.NewMockControllerInterface[*rbacv1.RoleBinding, *rbacv1.RoleBindingList](ctrl)
|
||||
if tt.setupRBController != nil {
|
||||
tt.setupRBController(rbController)
|
||||
}
|
||||
crController := fake.NewMockNonNamespacedControllerInterface[*rbacv1.ClusterRole, *rbacv1.ClusterRoleList](ctrl)
|
||||
if tt.setupCRController != nil {
|
||||
@@ -379,8 +365,8 @@ func Test_reconcileBindings(t *testing.T) {
|
||||
}
|
||||
|
||||
p := &prtbHandler{
|
||||
crbController: crbController,
|
||||
crController: crController,
|
||||
crController: crController,
|
||||
rbController: rbController,
|
||||
}
|
||||
if err := p.reconcileBindings(tt.prtb); (err != nil) != tt.wantErr {
|
||||
t.Errorf("prtbHandler.reconcileBindings() error = %v, wantErr %v", err, tt.wantErr)
|
||||
|
||||
@@ -28,7 +28,6 @@ var (
|
||||
"etcdsnapshots": "rke.cattle.io",
|
||||
}
|
||||
projectManagementPlaneResources = map[string]string{
|
||||
"apps": "project.cattle.io",
|
||||
"projectroletemplatebindings": "management.cattle.io",
|
||||
"secrets": "",
|
||||
}
|
||||
|
||||
@@ -755,11 +755,6 @@ func Test_getManagementPlaneRules(t *testing.T) {
|
||||
},
|
||||
managementResources: projectManagementPlaneResources,
|
||||
want: []rbacv1.PolicyRule{
|
||||
{
|
||||
Resources: []string{"apps"},
|
||||
APIGroups: []string{"project.cattle.io"},
|
||||
Verbs: []string{"*"},
|
||||
},
|
||||
{
|
||||
Resources: []string{"projectroletemplatebindings"},
|
||||
APIGroups: []string{"management.cattle.io"},
|
||||
|
||||
@@ -95,8 +95,8 @@ func (n *namespaceHandler) OnChange(_ string, namespace *corev1.Namespace) (*cor
|
||||
for _, secret := range secrets {
|
||||
secretCopy := getNamespacedSecret(secret, namespace.Name)
|
||||
|
||||
s, err := rbac.CreateOrUpdateNamespacedResource(secretCopy, n.secretClient, areSecretsSame)
|
||||
desiredSecrets.Insert(client.ObjectKeyFromObject(s))
|
||||
err := rbac.CreateOrUpdateNamespacedResource(secretCopy, n.secretClient, areSecretsSame)
|
||||
desiredSecrets.Insert(client.ObjectKeyFromObject(secretCopy))
|
||||
errs = errors.Join(errs, err)
|
||||
}
|
||||
if errs != nil {
|
||||
|
||||
@@ -389,23 +389,25 @@ func CreateOrUpdateResource[T generic.RuntimeMetaObject, TList runtime.Object](o
|
||||
// - client is the Wrangler client to use to get/create/update resource.
|
||||
// - areResourcesTheSame is a func that compares two resources and returns (true, nil) if they are equal, and (false, T) when not the same.
|
||||
// T is an updated version of the resource.
|
||||
func CreateOrUpdateNamespacedResource[T generic.RuntimeMetaObject, TList runtime.Object](obj T, client generic.ClientInterface[T, TList], areResourcesTheSame func(T, T) (bool, T)) (T, error) {
|
||||
func CreateOrUpdateNamespacedResource[T generic.RuntimeMetaObject, TList runtime.Object](obj T, client generic.ClientInterface[T, TList], areResourcesTheSame func(T, T) (bool, T)) error {
|
||||
resource, err := client.Get(obj.GetNamespace(), obj.GetName(), metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return obj, err
|
||||
return err
|
||||
}
|
||||
// resource doesn't exist, create it
|
||||
logrus.Infof("%T %s being created in namespace %s", obj, obj.GetName(), obj.GetNamespace())
|
||||
return client.Create(obj)
|
||||
_, err := client.Create(obj)
|
||||
return err
|
||||
}
|
||||
|
||||
if same, updatedResource := areResourcesTheSame(resource, obj); !same {
|
||||
logrus.Infof("%T %s in namespace %s needs to be updated", obj, obj.GetName(), obj.GetNamespace())
|
||||
return client.Update(updatedResource)
|
||||
_, err := client.Update(updatedResource)
|
||||
return err
|
||||
|
||||
}
|
||||
return obj, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// AreClusterRolesSame returns true if the current ClusterRole has the same fields present in the desired ClusterRole.
|
||||
@@ -458,6 +460,16 @@ func DeleteResource[T generic.RuntimeMetaObject, TList runtime.Object](name stri
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteResource deletes a non namespaced resource
|
||||
func DeleteNamespacedResource[T generic.RuntimeMetaObject, TList runtime.Object](namespace, name string, client generic.ClientInterface[T, TList]) error {
|
||||
err := client.Delete(namespace, name, &metav1.DeleteOptions{})
|
||||
// If the resource is already gone, don't treat it as an error
|
||||
if apierrors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// BuildClusterRole creates a cluster role with an aggregation label
|
||||
// - name: name of the cluster role
|
||||
// - ownerName: name of the creator of this cluster role
|
||||
@@ -510,6 +522,45 @@ func BuildAggregatingClusterRole(rt *v3.RoleTemplate, nameTransformer func(strin
|
||||
}
|
||||
}
|
||||
|
||||
// BuildAggregatingRoleBindingFromRTB returns a RoleBinding for a RTB. It is bound to the Aggregating ClusterRole.
|
||||
func BuildAggregatingRoleBindingFromRTB(rtb metav1.Object, roleRefName string) (*rbacv1.RoleBinding, error) {
|
||||
return BuildRoleBindingFromRTB(rtb, AggregatedClusterRoleNameFor(roleRefName))
|
||||
}
|
||||
|
||||
// BuildRoleBindingFromRTB returns a RoleBinding for a RTB. It is bound to the ClusterRole specified by roleRefName.
|
||||
func BuildRoleBindingFromRTB(rtb metav1.Object, roleRefName string) (*rbacv1.RoleBinding, error) {
|
||||
roleRef := rbacv1.RoleRef{
|
||||
APIGroup: rbacv1.GroupName,
|
||||
Kind: "ClusterRole",
|
||||
Name: roleRefName,
|
||||
}
|
||||
|
||||
subject, err := BuildSubjectFromRTB(rtb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var ownerLabel string
|
||||
switch rtb.(type) {
|
||||
case *v3.ProjectRoleTemplateBinding:
|
||||
ownerLabel = GetPRTBOwnerLabel(rtb.GetName())
|
||||
case *v3.ClusterRoleTemplateBinding:
|
||||
ownerLabel = GetCRTBOwnerLabel(rtb.GetName())
|
||||
default:
|
||||
return nil, fmt.Errorf("unrecognized roleTemplateBinding type: %T", rtb)
|
||||
}
|
||||
|
||||
return &rbacv1.RoleBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: NameForRoleBinding(rtb.GetNamespace(), roleRef, subject),
|
||||
Namespace: rtb.GetNamespace(),
|
||||
Labels: map[string]string{ownerLabel: "true"},
|
||||
},
|
||||
RoleRef: roleRef,
|
||||
Subjects: []rbacv1.Subject{subject},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// BuildAggregatingClusterRoleBindingFromRTB returns the ClusterRoleBinding needed for a RTB. It is bound to the Aggregating ClusterRole.
|
||||
func BuildAggregatingClusterRoleBindingFromRTB(rtb metav1.Object, roleRefName string) (*rbacv1.ClusterRoleBinding, error) {
|
||||
return BuildClusterRoleBindingFromRTB(rtb, AggregatedClusterRoleNameFor(roleRefName))
|
||||
@@ -555,9 +606,9 @@ func AreClusterRoleBindingContentsSame(crb1, crb2 *rbacv1.ClusterRoleBinding) bo
|
||||
}
|
||||
|
||||
// AreRoleBindingsSame compares the Subjects and RoleRef fields of two Cluster Role Bindings.
|
||||
func AreRoleBindingContentsSame(rb1, rb2 *rbacv1.RoleBinding) bool {
|
||||
func AreRoleBindingContentsSame(rb1, rb2 *rbacv1.RoleBinding) (bool, *rbacv1.RoleBinding) {
|
||||
return equality.Semantic.DeepEqual(rb1.Subjects, rb2.Subjects) &&
|
||||
equality.Semantic.DeepEqual(rb1.RoleRef, rb2.RoleRef)
|
||||
equality.Semantic.DeepEqual(rb1.RoleRef, rb2.RoleRef), rb2
|
||||
}
|
||||
|
||||
// ClusterRoleNameFor returns safe version of a string to be used for a clusterRoleName
|
||||
|
||||
Reference in New Issue
Block a user