Skip to content

Commit b81b982

Browse files
committed
use cluster role aggregation for admin, edit, and view
1 parent ff839e6 commit b81b982

File tree

7 files changed

+221
-881
lines changed

7 files changed

+221
-881
lines changed

pkg/cmd/server/bootstrappolicy/policy.go

Lines changed: 30 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -266,35 +266,12 @@ func GetOpenshiftBootstrapClusterRoles() []rbac.ClusterRole {
266266
},
267267
},
268268
{
269-
ObjectMeta: metav1.ObjectMeta{
270-
Name: AdminRoleName,
271-
Annotations: map[string]string{
272-
oapi.OpenShiftDescription: "A user that has edit rights within the project and can change the project's membership.",
273-
},
274-
},
269+
// a role for a namespace level admin. It is `edit` plus the power to grant permissions to other users.
270+
ObjectMeta: metav1.ObjectMeta{Name: "system:openshift:aggregate-to-admin", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-admin": "true"}},
275271
Rules: []rbac.PolicyRule{
276-
rbac.NewRule(readWrite...).Groups(kapiGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(),
277-
rbac.NewRule(readWrite...).Groups(kapiGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts",
278-
"services", "services/proxy", "endpoints", "persistentvolumeclaims", "configmaps", "secrets").RuleOrDie(),
279-
rbac.NewRule(read...).Groups(kapiGroup).Resources("limitranges", "resourcequotas", "bindings", "events",
280-
"namespaces", "pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(),
281-
rbac.NewRule("impersonate").Groups(kapiGroup).Resources("serviceaccounts").RuleOrDie(),
282-
283-
rbac.NewRule(readWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(),
284-
285-
rbac.NewRule(readWrite...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(),
286-
287-
rbac.NewRule(readWrite...).Groups(appsGroup, extensionsGroup).Resources("replicationcontrollers/scale",
288-
"replicasets", "replicasets/scale", "deployments", "deployments/scale", "deployments/rollback").RuleOrDie(),
289-
rbac.NewRule(read...).Groups(appsGroup, extensionsGroup).Resources("daemonsets").RuleOrDie(),
290-
291-
rbac.NewRule(readWrite...).Groups(appsGroup).Resources("statefulsets", "deployments", "deployments/scale", "deployments/status").RuleOrDie(),
292-
293272
rbac.NewRule(readWrite...).Groups(authzGroup, legacyAuthzGroup).Resources("roles", "rolebindings").RuleOrDie(),
294-
rbac.NewRule(readWrite...).Groups(rbacGroup).Resources("roles", "rolebindings").RuleOrDie(),
295273
rbac.NewRule("create").Groups(authzGroup, legacyAuthzGroup).Resources("localresourceaccessreviews", "localsubjectaccessreviews", "subjectrulesreviews").RuleOrDie(),
296274
rbac.NewRule("create").Groups(securityGroup, legacySecurityGroup).Resources("podsecuritypolicysubjectreviews", "podsecuritypolicyselfsubjectreviews", "podsecuritypolicyreviews").RuleOrDie(),
297-
rbac.NewRule("create").Groups(kAuthzGroup).Resources("localsubjectaccessreviews").RuleOrDie(),
298275

299276
rbac.NewRule(read...).Groups(authzGroup, legacyAuthzGroup).Resources("rolebindingrestrictions").RuleOrDie(),
300277

@@ -328,7 +305,7 @@ func GetOpenshiftBootstrapClusterRoles() []rbac.ClusterRole {
328305

329306
rbac.NewRule(readWrite...).Groups(templateGroup, legacyTemplateGroup).Resources("templates", "templateconfigs", "processedtemplates", "templateinstances").RuleOrDie(),
330307

331-
rbac.NewRule(readWrite...).Groups(extensionsGroup, networkingGroup).Resources("networkpolicies").RuleOrDie(),
308+
rbac.NewRule(readWrite...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(),
332309

333310
// backwards compatibility
334311
rbac.NewRule(readWrite...).Groups(buildGroup, legacyBuildGroup).Resources("buildlogs").RuleOrDie(),
@@ -337,30 +314,11 @@ func GetOpenshiftBootstrapClusterRoles() []rbac.ClusterRole {
337314
},
338315
},
339316
{
340-
ObjectMeta: metav1.ObjectMeta{
341-
Name: EditRoleName,
342-
Annotations: map[string]string{
343-
oapi.OpenShiftDescription: "A user that can create and edit most objects in a project, but can not update the project's membership.",
344-
},
345-
},
317+
// a role for a namespace level editor. It grants access to all user level actions in a namespace.
318+
// It does not grant powers for "privileged" resources which are domain of the system: `/status`
319+
// subresources or `quota`/`limits` which are used to control namespaces
320+
ObjectMeta: metav1.ObjectMeta{Name: "system:openshift:aggregate-to-edit", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-edit": "true"}},
346321
Rules: []rbac.PolicyRule{
347-
rbac.NewRule(readWrite...).Groups(kapiGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(),
348-
rbac.NewRule(readWrite...).Groups(kapiGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts",
349-
"services", "services/proxy", "endpoints", "persistentvolumeclaims", "configmaps", "secrets").RuleOrDie(),
350-
rbac.NewRule(read...).Groups(kapiGroup).Resources("limitranges", "resourcequotas", "bindings", "events",
351-
"namespaces", "pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(),
352-
rbac.NewRule("impersonate").Groups(kapiGroup).Resources("serviceaccounts").RuleOrDie(),
353-
354-
rbac.NewRule(readWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(),
355-
356-
rbac.NewRule(readWrite...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(),
357-
358-
rbac.NewRule(readWrite...).Groups(appsGroup, extensionsGroup).Resources("replicationcontrollers/scale",
359-
"replicasets", "replicasets/scale", "deployments", "deployments/scale", "deployments/rollback").RuleOrDie(),
360-
rbac.NewRule(read...).Groups(appsGroup, extensionsGroup).Resources("daemonsets").RuleOrDie(),
361-
362-
rbac.NewRule(readWrite...).Groups(appsGroup).Resources("statefulsets", "deployments", "deployments/scale", "deployments/status").RuleOrDie(),
363-
364322
rbac.NewRule(readWrite...).Groups(buildGroup, legacyBuildGroup).Resources("builds", "buildconfigs", "buildconfigs/webhooks").RuleOrDie(),
365323
rbac.NewRule(read...).Groups(buildGroup, legacyBuildGroup).Resources("builds/log").RuleOrDie(),
366324
rbac.NewRule("create").Groups(buildGroup, legacyBuildGroup).Resources("buildconfigs/instantiate", "buildconfigs/instantiatebinary", "builds/clone").RuleOrDie(),
@@ -389,36 +347,18 @@ func GetOpenshiftBootstrapClusterRoles() []rbac.ClusterRole {
389347

390348
rbac.NewRule(readWrite...).Groups(templateGroup, legacyTemplateGroup).Resources("templates", "templateconfigs", "processedtemplates", "templateinstances").RuleOrDie(),
391349

392-
rbac.NewRule(readWrite...).Groups(extensionsGroup, networkingGroup).Resources("networkpolicies").RuleOrDie(),
350+
rbac.NewRule(readWrite...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(),
393351

394352
// backwards compatibility
395353
rbac.NewRule(readWrite...).Groups(buildGroup, legacyBuildGroup).Resources("buildlogs").RuleOrDie(),
396354
rbac.NewRule(read...).Groups(kapiGroup).Resources("resourcequotausages").RuleOrDie(),
397355
},
398356
},
399357
{
400-
ObjectMeta: metav1.ObjectMeta{
401-
Name: ViewRoleName,
402-
Annotations: map[string]string{
403-
oapi.OpenShiftDescription: "A user who can view but not edit any resources within the project. They can not view secrets or membership.",
404-
},
405-
},
358+
// a role for namespace level viewing. It grants Read-only access to non-escalating resources in
359+
// a namespace.
360+
ObjectMeta: metav1.ObjectMeta{Name: "system:openshift:aggregate-to-view", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-view": "true"}},
406361
Rules: []rbac.PolicyRule{
407-
// TODO add "replicationcontrollers/scale" here
408-
rbac.NewRule(read...).Groups(kapiGroup).Resources("pods", "replicationcontrollers", "serviceaccounts",
409-
"services", "endpoints", "persistentvolumeclaims", "configmaps").RuleOrDie(),
410-
rbac.NewRule(read...).Groups(kapiGroup).Resources("limitranges", "resourcequotas", "bindings", "events",
411-
"namespaces", "pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(),
412-
413-
rbac.NewRule(read...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(),
414-
415-
rbac.NewRule(read...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(),
416-
417-
rbac.NewRule(read...).Groups(appsGroup, extensionsGroup).Resources("deployments", "deployments/scale", "replicasets", "replicasets/scale").RuleOrDie(),
418-
rbac.NewRule(read...).Groups(appsGroup, extensionsGroup).Resources("daemonsets").RuleOrDie(),
419-
420-
rbac.NewRule(read...).Groups(appsGroup).Resources("statefulsets", "deployments", "deployments/scale").RuleOrDie(),
421-
422362
rbac.NewRule(read...).Groups(buildGroup, legacyBuildGroup).Resources("builds", "buildconfigs", "buildconfigs/webhooks").RuleOrDie(),
423363
rbac.NewRule(read...).Groups(buildGroup, legacyBuildGroup).Resources("builds/log").RuleOrDie(),
424364
// access to jenkins
@@ -896,6 +836,25 @@ func GetBootstrapClusterRoles() []rbac.ClusterRole {
896836
}
897837
role.Annotations[roleSystemOnly] = roleIsSystemOnly
898838
}
839+
840+
// add a couple selected descriptions
841+
switch role.Name {
842+
case "admin":
843+
if role.Annotations == nil {
844+
role.Annotations = map[string]string{}
845+
}
846+
role.Annotations[oapi.OpenShiftDescription] = "A user that has edit rights within the project and can change the project's membership."
847+
case "edit":
848+
if role.Annotations == nil {
849+
role.Annotations = map[string]string{}
850+
}
851+
role.Annotations[oapi.OpenShiftDescription] = "A user that can create and edit most objects in a project, but can not update the project's membership."
852+
case "view":
853+
if role.Annotations == nil {
854+
role.Annotations = map[string]string{}
855+
}
856+
role.Annotations[oapi.OpenShiftDescription] = "A user who can view but not edit any resources within the project. They can not view secrets or membership."
857+
}
899858
}
900859

901860
return finalClusterRoles
@@ -1045,11 +1004,6 @@ func GetBootstrapClusterRoleBindings() []rbac.ClusterRoleBinding {
10451004
// clusterRoleConflicts lists the roles which are known to conflict with upstream and which we have manually
10461005
// deconflicted with our own.
10471006
var clusterRoleConflicts = sets.NewString(
1048-
// these require special treatment to handle origin resources
1049-
"admin",
1050-
"edit",
1051-
"view",
1052-
10531007
// TODO this should probably be re-swizzled to be the delta on top of the kube role
10541008
"system:discovery",
10551009

pkg/cmd/server/bootstrappolicy/policy_test.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ func testObjects(t *testing.T, list *api.List, fixtureFilename string) {
142142
// Some roles should always cover others
143143
func TestCovers(t *testing.T) {
144144
allRoles := bootstrappolicy.GetBootstrapClusterRoles()
145-
var admin *rbac.ClusterRole
146-
var editor *rbac.ClusterRole
147-
var viewer *rbac.ClusterRole
145+
var admin []rbac.PolicyRule
146+
var editor []rbac.PolicyRule
147+
var viewer []rbac.PolicyRule
148148
var registryAdmin *rbac.ClusterRole
149149
var registryEditor *rbac.ClusterRole
150150
var registryViewer *rbac.ClusterRole
@@ -158,12 +158,12 @@ func TestCovers(t *testing.T) {
158158
for i := range allRoles {
159159
role := allRoles[i]
160160
switch role.Name {
161-
case bootstrappolicy.AdminRoleName:
162-
admin = &role
163-
case bootstrappolicy.EditRoleName:
164-
editor = &role
165-
case bootstrappolicy.ViewRoleName:
166-
viewer = &role
161+
case "system:openshift:aggregate-to-admin", "system:aggregate-to-admin":
162+
admin = append(admin, role.Rules...)
163+
case "system:openshift:aggregate-to-edit", "system:aggregate-to-edit":
164+
editor = append(editor, role.Rules...)
165+
case "system:openshift:aggregate-to-view", "system:aggregate-to-view":
166+
viewer = append(viewer, role.Rules...)
167167
case bootstrappolicy.RegistryAdminRoleName:
168168
registryAdmin = &role
169169
case bootstrappolicy.RegistryEditorRoleName:
@@ -185,16 +185,16 @@ func TestCovers(t *testing.T) {
185185
}
186186
}
187187

188-
if covers, miss := rulevalidation.Covers(admin.Rules, editor.Rules); !covers {
188+
if covers, miss := rulevalidation.Covers(admin, editor); !covers {
189189
t.Errorf("failed to cover: %#v", miss)
190190
}
191-
if covers, miss := rulevalidation.Covers(admin.Rules, editor.Rules); !covers {
191+
if covers, miss := rulevalidation.Covers(admin, editor); !covers {
192192
t.Errorf("failed to cover: %#v", miss)
193193
}
194-
if covers, miss := rulevalidation.Covers(admin.Rules, viewer.Rules); !covers {
194+
if covers, miss := rulevalidation.Covers(admin, viewer); !covers {
195195
t.Errorf("failed to cover: %#v", miss)
196196
}
197-
if covers, miss := rulevalidation.Covers(admin.Rules, registryAdmin.Rules); !covers {
197+
if covers, miss := rulevalidation.Covers(admin, registryAdmin.Rules); !covers {
198198
t.Errorf("failed to cover: %#v", miss)
199199
}
200200
if covers, miss := rulevalidation.Covers(clusterAdmin.Rules, storageAdmin.Rules); !covers {
@@ -208,10 +208,10 @@ func TestCovers(t *testing.T) {
208208
}
209209

210210
// admin and editor should cover imagebuilder
211-
if covers, miss := rulevalidation.Covers(admin.Rules, imageBuilder.Rules); !covers {
211+
if covers, miss := rulevalidation.Covers(admin, imageBuilder.Rules); !covers {
212212
t.Errorf("failed to cover: %#v", miss)
213213
}
214-
if covers, miss := rulevalidation.Covers(editor.Rules, imageBuilder.Rules); !covers {
214+
if covers, miss := rulevalidation.Covers(editor, imageBuilder.Rules); !covers {
215215
t.Errorf("failed to cover: %#v", miss)
216216
}
217217

pkg/cmd/server/bootstrappolicy/web_console_role_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ var rolesToHide = sets.NewString(
6060
"system:aggregate-to-edit",
6161
"system:aggregate-to-view",
6262
"system:aws-cloud-provider",
63+
"system:openshift:aggregate-to-admin",
64+
"system:openshift:aggregate-to-edit",
65+
"system:openshift:aggregate-to-view",
6366
)
6467

6568
func TestSystemOnlyRoles(t *testing.T) {

test/integration/ingressip_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func TestIngressIPAllocation(t *testing.T) {
3232
defer testserver.CleanupMasterEtcd(t, masterConfig)
3333
masterConfig.NetworkConfig.ExternalIPNetworkCIDRs = []string{"172.16.0.0/24"}
3434
masterConfig.NetworkConfig.IngressIPNetworkCIDR = "172.16.1.0/24"
35-
clusterAdminKubeConfig, err := testserver.StartConfiguredMasterWithOptions(masterConfig, testserver.TestOptions{})
35+
clusterAdminKubeConfig, err := testserver.StartConfiguredMasterWithOptions(masterConfig)
3636
if err != nil {
3737
t.Fatalf("Unexpected error: %v", err)
3838
}

0 commit comments

Comments
 (0)