Skip to content

Commit 8f92581

Browse files
matskivopenshift-cherrypick-robot
authored andcommitted
Bug 1855088: generate unique role and binding names When same permission rules are defined for different ServiceAccounts, OLM would generate same name for (Cluster)Role and (Cluster)RoleBinding related to this rules. This change should ensure that unique names are generated, taking into account ServiceAccount name and CSV Name and CSV namespace (for ClusterRole)
1 parent feb756f commit 8f92581

File tree

2 files changed

+43
-11
lines changed

2 files changed

+43
-11
lines changed

pkg/controller/registry/resolver/rbac.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func RBACForClusterServiceVersion(csv *v1alpha1.ClusterServiceVersion) (map[stri
9393
// Create Role
9494
role := &rbacv1.Role{
9595
ObjectMeta: metav1.ObjectMeta{
96-
Name: generateName(csv.GetName(), permission.Rules),
96+
Name: generateName(fmt.Sprintf("%s-%s", csv.GetName(), permission.ServiceAccountName), []interface{}{csv.GetName(), permission}),
9797
Namespace: csv.GetNamespace(),
9898
OwnerReferences: []metav1.OwnerReference{ownerutil.NonBlockingOwner(csv)},
9999
Labels: ownerutil.OwnerLabel(csv, v1alpha1.ClusterServiceVersionKind),
@@ -105,7 +105,7 @@ func RBACForClusterServiceVersion(csv *v1alpha1.ClusterServiceVersion) (map[stri
105105
// Create RoleBinding
106106
roleBinding := &rbacv1.RoleBinding{
107107
ObjectMeta: metav1.ObjectMeta{
108-
Name: generateName(role.GetName(), permission),
108+
Name: role.GetName(),
109109
Namespace: csv.GetNamespace(),
110110
OwnerReferences: []metav1.OwnerReference{ownerutil.NonBlockingOwner(csv)},
111111
Labels: ownerutil.OwnerLabel(csv, v1alpha1.ClusterServiceVersionKind),
@@ -137,7 +137,7 @@ func RBACForClusterServiceVersion(csv *v1alpha1.ClusterServiceVersion) (map[stri
137137
// Create ClusterRole
138138
role := &rbacv1.ClusterRole{
139139
ObjectMeta: metav1.ObjectMeta{
140-
Name: generateName(csv.GetName(), permission.Rules),
140+
Name: generateName(csv.GetName(), []interface{}{csv.GetName(), csv.GetNamespace(), permission}),
141141
Labels: ownerutil.OwnerLabel(csv, v1alpha1.ClusterServiceVersionKind),
142142
},
143143
Rules: permission.Rules,
@@ -147,7 +147,7 @@ func RBACForClusterServiceVersion(csv *v1alpha1.ClusterServiceVersion) (map[stri
147147
// Create ClusterRoleBinding
148148
roleBinding := &rbacv1.ClusterRoleBinding{
149149
ObjectMeta: metav1.ObjectMeta{
150-
Name: generateName(role.GetName(), permission),
150+
Name: role.GetName(),
151151
Namespace: csv.GetNamespace(),
152152
Labels: ownerutil.OwnerLabel(csv, v1alpha1.ClusterServiceVersionKind),
153153
},

pkg/controller/registry/resolver/rbac_test.go

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,10 @@ func TestGeneratesWithinRange(t *testing.T) {
7070
require.NoError(t, quick.Check(f, nil))
7171
}
7272

73-
func TestRBACBindings(t *testing.T) {
73+
func TestRBACForClusterServiceVersion(t *testing.T) {
7474
serviceAccount1 := "test-service-account"
75-
serviceAccount2 := "second-account"
75+
serviceAccount2 := "second-service-account"
76+
csvName := "test-csv.v1.1.0"
7677

7778
rules := []rbacv1.PolicyRule{
7879
{
@@ -82,16 +83,20 @@ func TestRBACBindings(t *testing.T) {
8283
},
8384
}
8485

86+
// Note: two CSVs have same name and permissions for a cluster role, this is chosen intentionally,
87+
// to verify that ClusterRole and ClusterRoleBinding have different names when the same CSV is installed
88+
// twice in the same cluster, but in different namespaces.
8589
tests := []struct {
8690
name string
8791
csv v1alpha1.ClusterServiceVersion
8892
want map[string]*OperatorPermissions
8993
}{
9094
{
91-
name: "RoleBinding",
95+
name: "RoleBindings and one ClusterRoleBinding",
9296
csv: v1alpha1.ClusterServiceVersion{
9397
ObjectMeta: metav1.ObjectMeta{
94-
Name: "test-csv-1.1.0",
98+
Name: csvName,
99+
Namespace: "test-namespace",
95100
},
96101
Spec: v1alpha1.ClusterServiceVersionSpec{
97102
InstallStrategy: v1alpha1.NamedInstallStrategy{
@@ -117,13 +122,20 @@ func TestRBACBindings(t *testing.T) {
117122
Rules: rules,
118123
},
119124
},
125+
ClusterPermissions: []v1alpha1.StrategyDeploymentPermissions{
126+
{
127+
ServiceAccountName: serviceAccount1,
128+
Rules: rules,
129+
},
130+
},
120131
},
121132
},
122133
},
123134
},
124135
want: map[string]*OperatorPermissions{
125136
serviceAccount1: {
126-
RoleBindings: []*rbacv1.RoleBinding{{}, {}},
137+
RoleBindings: []*rbacv1.RoleBinding{{}, {}},
138+
ClusterRoleBindings: []*rbacv1.ClusterRoleBinding{{}},
127139
},
128140
serviceAccount2: {
129141
RoleBindings: []*rbacv1.RoleBinding{{}},
@@ -134,7 +146,8 @@ func TestRBACBindings(t *testing.T) {
134146
name: "ClusterRoleBinding",
135147
csv: v1alpha1.ClusterServiceVersion{
136148
ObjectMeta: metav1.ObjectMeta{
137-
Name: "second-csv-1.1.0",
149+
Name: csvName,
150+
Namespace: "second-namespace",
138151
},
139152
Spec: v1alpha1.ClusterServiceVersionSpec{
140153
InstallStrategy: v1alpha1.NamedInstallStrategy{
@@ -164,13 +177,18 @@ func TestRBACBindings(t *testing.T) {
164177
},
165178
},
166179
}
180+
181+
// declared here to verify that names are unique when same csv is install in different namespaces
182+
clusterRoleBindingNames := map[string]bool{}
183+
clusterRolesNames := map[string]bool{}
184+
167185
for _, tt := range tests {
168186
t.Run(tt.name, func(t *testing.T) {
169187
result, err := RBACForClusterServiceVersion(&tt.csv)
170188
require.NoError(t, err)
171189

172190
roleBindingNames := map[string]bool{}
173-
clusterRoleBindingNames := map[string]bool{}
191+
rolesNames := map[string]bool{}
174192
for serviceAccount, permissions := range tt.want {
175193
// Check that correct number of bindings is created
176194
require.Equal(t, len(permissions.RoleBindings), len(result[serviceAccount].RoleBindings))
@@ -197,6 +215,20 @@ func TestRBACBindings(t *testing.T) {
197215
require.False(t, crbWithNameExists, "ClusterRoleBinding with the same name already generated")
198216
clusterRoleBindingNames[clusterRoleBinding.Name] = true
199217
}
218+
219+
// Check that Roles are created with unique names
220+
for _, role := range result[serviceAccount].Roles {
221+
_, roleWithNameExists := rolesNames[role.Name]
222+
require.False(t, roleWithNameExists, "Role with the same name already generated")
223+
rolesNames[role.Name] = true
224+
}
225+
226+
// Check that ClusterRoles are created with unique names
227+
for _, clusterRole := range result[serviceAccount].ClusterRoles {
228+
_, crWithNameExists := clusterRolesNames[clusterRole.Name]
229+
require.False(t, crWithNameExists, "ClusterRole with the same name already generated")
230+
clusterRolesNames[clusterRole.Name] = true
231+
}
200232
}
201233
})
202234
}

0 commit comments

Comments
 (0)