func GetBootstrapOpenshiftRoles(openshiftNamespace string) []authorizationapi.Role { roles := []authorizationapi.Role{ { ObjectMeta: kapi.ObjectMeta{ Name: OpenshiftSharedResourceViewRoleName, Namespace: openshiftNamespace, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule(read...).Groups(templateGroup).Resources("templates").RuleOrDie(), authorizationapi.NewRule(read...).Groups(imageGroup).Resources("imagestreams", "imagestreamtags", "imagestreamimages").RuleOrDie(), // so anyone can pull from openshift/* image streams authorizationapi.NewRule("get").Groups(imageGroup).Resources("imagestreams/layers").RuleOrDie(), }, }, } // we don't want to expose the resourcegroups externally because it makes it very difficult for customers to learn from // our default roles and hard for them to reason about what power they are granting their users for i := range roles { for j := range roles[i].Rules { roles[i].Rules[j].Resources = authorizationapi.NormalizeResources(roles[i].Rules[j].Resources) } } return roles }
func (a DefaultAuthorizationAttributes) RuleMatches(rule authorizationapi.PolicyRule) (bool, error) { if a.IsNonResourceURL() { if a.nonResourceMatches(rule) { if a.verbMatches(rule.Verbs) { return true, nil } } return false, nil } if a.verbMatches(rule.Verbs) { if a.apiGroupMatches(rule.APIGroups) { allowedResourceTypes := authorizationapi.NormalizeResources(rule.Resources) if a.resourceMatches(allowedResourceTypes) { if a.nameMatches(rule.ResourceNames) { // this rule matches the request, so we should check the additional restrictions to be sure that it's allowed if rule.AttributeRestrictions != nil { switch rule.AttributeRestrictions.(type) { case (*authorizationapi.IsPersonalSubjectAccessReview): return IsPersonalAccessReview(a) default: return false, fmt.Errorf("unable to interpret: %#v", rule.AttributeRestrictions) } } return true, nil } } } } return false, nil }
func oldGetBootstrapOpenshiftRoles(openshiftNamespace string) []authorizationapi.Role { roles := []authorizationapi.Role{ { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.OpenshiftSharedResourceViewRoleName, Namespace: openshiftNamespace, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "list"), Resources: sets.NewString("templates", authorizationapi.ImageGroupName), }, { // so anyone can pull from openshift/* image streams Verbs: sets.NewString("get"), Resources: sets.NewString("imagestreams/layers"), }, }, }, } // we don't want to expose the resourcegroups externally because it makes it very difficult for customers to learn from // our default roles and hard for them to reason about what power they are granting their users for i := range roles { for j := range roles[i].Rules { roles[i].Rules[j].Resources = authorizationapi.NormalizeResources(roles[i].Rules[j].Resources) } } return roles }
// TestAllOpenShiftResourceCoverage checks to make sure that the openshift all group actually contains all openshift resources func TestAllOpenShiftResourceCoverage(t *testing.T) { allOpenshift := authorizationapi.NormalizeResources(sets.NewString(authorizationapi.GroupsToResources[authorizationapi.OpenshiftAllGroupName]...)) config := fakeMasterConfig() storageMap := config.GetRestStorage() for key := range storageMap { if allOpenshift.Has(strings.ToLower(key)) { continue } t.Errorf("authorizationapi.GroupsToResources[authorizationapi.OpenshiftAllGroupName] is missing %v. Check pkg/authorization/api/types.go.", strings.ToLower(key)) } }
// ruleCovers determines whether the ownerRule (which may have multiple verbs, resources, and resourceNames) covers // the subrule (which may only contain at most one verb, resource, and resourceName) func ruleCovers(ownerRule, subrule authorizationapi.PolicyRule) bool { allResources := authorizationapi.NormalizeResources(ownerRule.Resources) ownerGroups := sets.NewString(ownerRule.APIGroups...) groupMatches := ownerGroups.Has(authorizationapi.APIGroupAll) || ownerGroups.HasAll(subrule.APIGroups...) || (len(ownerRule.APIGroups) == 0 && len(subrule.APIGroups) == 0) verbMatches := ownerRule.Verbs.Has(authorizationapi.VerbAll) || ownerRule.Verbs.HasAll(subrule.Verbs.List()...) resourceMatches := ownerRule.Resources.Has(authorizationapi.ResourceAll) || allResources.HasAll(subrule.Resources.List()...) resourceNameMatches := false if len(subrule.ResourceNames) == 0 { resourceNameMatches = (len(ownerRule.ResourceNames) == 0) } else { resourceNameMatches = (len(ownerRule.ResourceNames) == 0) || ownerRule.ResourceNames.HasAll(subrule.ResourceNames.List()...) } return verbMatches && resourceMatches && resourceNameMatches && groupMatches }
func breakdownRuleForGroup(group string, rule authorizationapi.PolicyRule) []authorizationapi.PolicyRule { subrules := []authorizationapi.PolicyRule{} for resource := range authorizationapi.NormalizeResources(rule.Resources) { for verb := range rule.Verbs { if len(rule.ResourceNames) > 0 { for _, resourceName := range rule.ResourceNames.List() { subrules = append(subrules, authorizationapi.PolicyRule{APIGroups: []string{group}, Resources: sets.NewString(resource), Verbs: sets.NewString(verb), ResourceNames: sets.NewString(resourceName)}) } } else { subrules = append(subrules, authorizationapi.PolicyRule{APIGroups: []string{group}, Resources: sets.NewString(resource), Verbs: sets.NewString(verb)}) } } } return subrules }
func GetBootstrapClusterRoles() []authorizationapi.ClusterRole { // four resource can be a single line // up to ten-ish resources per line otherwise roles := []authorizationapi.ClusterRole{ { ObjectMeta: kapi.ObjectMeta{ Name: ClusterAdminRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("*").Groups("*").Resources("*").RuleOrDie(), { Verbs: sets.NewString(authorizationapi.VerbAll), NonResourceURLs: sets.NewString(authorizationapi.NonResourceAll), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: SudoerRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("impersonate").Groups(kapiGroup).Resources(authorizationapi.SystemUserResource).Names(SystemAdminUsername).RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: ClusterReaderRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("bindings", "componentstatuses", "configmaps", "egressnetworkpolicies", "endpoints", "events", "limitranges", "namespaces", "namespaces/status", "nodes", "nodes/status", "persistentvolumeclaims", "persistentvolumeclaims/status", "persistentvolumes", "persistentvolumes/status", "pods", "pods/binding", "pods/eviction", "pods/log", "pods/status", "podtemplates", "replicationcontrollers", "replicationcontrollers/scale", "replicationcontrollers/status", "resourcequotas", "resourcequotas/status", "securitycontextconstraints", "serviceaccounts", "services", "services/status").RuleOrDie(), authorizationapi.NewRule(read...).Groups(appsGroup).Resources("petsets", "petsets/status").RuleOrDie(), authorizationapi.NewRule(read...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers", "horizontalpodautoscalers/status").RuleOrDie(), authorizationapi.NewRule(read...).Groups(batchGroup).Resources("jobs", "jobs/status", "scheduledjobs", "scheduledjobs/status").RuleOrDie(), authorizationapi.NewRule(read...).Groups(extensionsGroup).Resources("daemonsets", "daemonsets/status", "deployments", "deployments/scale", "deployments/status", "horizontalpodautoscalers", "horizontalpodautoscalers/status", "ingresses", "ingresses/status", "jobs", "jobs/status", "networkpolicies", "podsecuritypolicies", "replicasets", "replicasets/scale", "replicasets/status", "replicationcontrollers", "replicationcontrollers/scale", "storageclasses", "thirdpartyresources").RuleOrDie(), authorizationapi.NewRule(read...).Groups(policyGroup).Resources("poddisruptionbudgets", "poddisruptionbudgets/status").RuleOrDie(), authorizationapi.NewRule(read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(), authorizationapi.NewRule(read...).Groups(certificatesGroup).Resources("certificatesigningrequests", "certificatesigningrequests/approval", "certificatesigningrequests/status").RuleOrDie(), authorizationapi.NewRule(read...).Groups(authzGroup).Resources("clusterpolicies", "clusterpolicybindings", "clusterroles", "clusterrolebindings", "policies", "policybindings", "roles", "rolebindings").RuleOrDie(), authorizationapi.NewRule(read...).Groups(buildGroup).Resources("builds", "builds/details", "buildconfigs", "buildconfigs/webhooks", "builds/log").RuleOrDie(), authorizationapi.NewRule(read...).Groups(deployGroup).Resources("deploymentconfigs", "deploymentconfigs/scale", "deploymentconfigs/log", "deploymentconfigs/status").RuleOrDie(), authorizationapi.NewRule(read...).Groups(imageGroup).Resources("images", "imagesignatures", "imagestreams", "imagestreamtags", "imagestreamimages", "imagestreams/status").RuleOrDie(), // pull images authorizationapi.NewRule("get").Groups(imageGroup).Resources("imagestreams/layers").RuleOrDie(), authorizationapi.NewRule(read...).Groups(oauthGroup).Resources("oauthclientauthorizations").RuleOrDie(), authorizationapi.NewRule(read...).Groups(projectGroup).Resources("projectrequests", "projects").RuleOrDie(), authorizationapi.NewRule(read...).Groups(quotaGroup).Resources("appliedclusterresourcequotas", "clusterresourcequotas", "clusterresourcequotas/status").RuleOrDie(), authorizationapi.NewRule(read...).Groups(routeGroup).Resources("routes", "routes/status").RuleOrDie(), authorizationapi.NewRule(read...).Groups(sdnGroup).Resources("clusternetworks", "hostsubnets", "netnamespaces").RuleOrDie(), authorizationapi.NewRule(read...).Groups(templateGroup).Resources("templates", "templateconfigs", "processedtemplates").RuleOrDie(), authorizationapi.NewRule(read...).Groups(userGroup).Resources("groups", "identities", "useridentitymappings", "users").RuleOrDie(), // permissions to check access. These creates are non-mutating authorizationapi.NewRule("create").Groups(authzGroup).Resources("localresourceaccessreviews", "localsubjectaccessreviews", "resourceaccessreviews", "selfsubjectrulesreviews", "subjectrulesreviews", "subjectaccessreviews").RuleOrDie(), authorizationapi.NewRule("create").Groups("authentication.k8s.io").Resources("tokenreviews").RuleOrDie(), // permissions to check PSP, these creates are non-mutating authorizationapi.NewRule("create").Groups(securityGroup).Resources("podsecuritypolicysubjectreviews", "podsecuritypolicyselfsubjectreviews", "podsecuritypolicyreviews").RuleOrDie(), // Allow read access to node metrics authorizationapi.NewRule("get").Groups(kapiGroup).Resources(authorizationapi.NodeMetricsResource, authorizationapi.NodeSpecResource).RuleOrDie(), // Allow read access to stats // Node stats requests are submitted as POSTs. These creates are non-mutating authorizationapi.NewRule("get", "create").Groups(kapiGroup).Resources(authorizationapi.NodeStatsResource).RuleOrDie(), { Verbs: sets.NewString("get"), NonResourceURLs: sets.NewString(authorizationapi.NonResourceAll), }, // backwards compatibility authorizationapi.NewRule(read...).Groups(buildGroup).Resources("buildlogs").RuleOrDie(), authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("resourcequotausages").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: BuildStrategyDockerRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("create").Groups(buildGroup).Resources(authorizationapi.DockerBuildResource).RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: BuildStrategyCustomRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("create").Groups(buildGroup).Resources(authorizationapi.CustomBuildResource).RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: BuildStrategySourceRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("create").Groups(buildGroup).Resources(authorizationapi.SourceBuildResource).RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: BuildStrategyJenkinsPipelineRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("create").Groups(buildGroup).Resources(authorizationapi.JenkinsPipelineBuildResource).RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: AdminRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule(readWrite...).Groups(kapiGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(kapiGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts", "services", "services/proxy", "endpoints", "persistentvolumeclaims", "configmaps", "secrets").RuleOrDie(), authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("limitranges", "resourcequotas", "bindings", "events", "namespaces", "pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(), authorizationapi.NewRule("impersonate").Groups(kapiGroup).Resources("serviceaccounts").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(batchGroup).Resources("jobs", "scheduledjobs").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(extensionsGroup).Resources("jobs", "horizontalpodautoscalers", "replicationcontrollers/scale", "replicasets", "replicasets/scale", "deployments", "deployments/scale").RuleOrDie(), authorizationapi.NewRule(read...).Groups(extensionsGroup).Resources("daemonsets").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(appsGroup).Resources("petsets").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(authzGroup).Resources("roles", "rolebindings").RuleOrDie(), authorizationapi.NewRule("create").Groups(authzGroup).Resources("localresourceaccessreviews", "localsubjectaccessreviews", "subjectrulesreviews").RuleOrDie(), authorizationapi.NewRule("create").Groups(securityGroup).Resources("podsecuritypolicysubjectreviews", "podsecuritypolicyselfsubjectreviews", "podsecuritypolicyreviews").RuleOrDie(), authorizationapi.NewRule(read...).Groups(authzGroup).Resources("policies", "policybindings").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(buildGroup).Resources("builds", "buildconfigs", "buildconfigs/webhooks").RuleOrDie(), authorizationapi.NewRule(read...).Groups(buildGroup).Resources("builds/log").RuleOrDie(), authorizationapi.NewRule("create").Groups(buildGroup).Resources("buildconfigs/instantiate", "buildconfigs/instantiatebinary", "builds/clone").RuleOrDie(), // access to jenkins. multiple values to ensure that covers relationships authorizationapi.NewRule("admin", "edit", "view").Groups(buildapi.FutureGroupName).Resources("jenkins").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(deployGroup).Resources("deploymentconfigs", "generatedeploymentconfigs", "deploymentconfigs/scale").RuleOrDie(), authorizationapi.NewRule("create").Groups(deployGroup).Resources("deploymentconfigrollbacks", "deploymentconfigs/rollback", "deploymentconfigs/instantiate").RuleOrDie(), authorizationapi.NewRule(read...).Groups(deployGroup).Resources("deploymentconfigs/log", "deploymentconfigs/status").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(imageGroup).Resources("imagestreams", "imagestreammappings", "imagestreamtags", "imagestreamimages", "imagestreams/secrets").RuleOrDie(), authorizationapi.NewRule(read...).Groups(imageGroup).Resources("imagestreams/status").RuleOrDie(), // push and pull images authorizationapi.NewRule("get", "update").Groups(imageGroup).Resources("imagestreams/layers").RuleOrDie(), authorizationapi.NewRule("create").Groups(imageGroup).Resources("imagestreamimports").RuleOrDie(), authorizationapi.NewRule("get", "patch", "update", "delete").Groups(projectGroup).Resources("projects").RuleOrDie(), authorizationapi.NewRule(read...).Groups(quotaGroup).Resources("appliedclusterresourcequotas").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(routeGroup).Resources("routes").RuleOrDie(), authorizationapi.NewRule(read...).Groups(routeGroup).Resources("routes/status").RuleOrDie(), // an admin can run routers that write back conditions to the route authorizationapi.NewRule("update").Groups(routeGroup).Resources("routes/status").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(templateGroup).Resources("templates", "templateconfigs", "processedtemplates").RuleOrDie(), // backwards compatibility authorizationapi.NewRule(readWrite...).Groups(buildGroup).Resources("buildlogs").RuleOrDie(), authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("resourcequotausages").RuleOrDie(), authorizationapi.NewRule("create").Groups(authzGroup).Resources("resourceaccessreviews", "subjectaccessreviews").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: EditRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule(readWrite...).Groups(kapiGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(kapiGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts", "services", "services/proxy", "endpoints", "persistentvolumeclaims", "configmaps", "secrets").RuleOrDie(), authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("limitranges", "resourcequotas", "bindings", "events", "namespaces", "pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(), authorizationapi.NewRule("impersonate").Groups(kapiGroup).Resources("serviceaccounts").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(batchGroup).Resources("jobs", "scheduledjobs").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(extensionsGroup).Resources("jobs", "horizontalpodautoscalers", "replicationcontrollers/scale", "replicasets", "replicasets/scale", "deployments", "deployments/scale").RuleOrDie(), authorizationapi.NewRule(read...).Groups(extensionsGroup).Resources("daemonsets").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(appsGroup).Resources("petsets").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(buildGroup).Resources("builds", "buildconfigs", "buildconfigs/webhooks").RuleOrDie(), authorizationapi.NewRule(read...).Groups(buildGroup).Resources("builds/log").RuleOrDie(), authorizationapi.NewRule("create").Groups(buildGroup).Resources("buildconfigs/instantiate", "buildconfigs/instantiatebinary", "builds/clone").RuleOrDie(), // access to jenkins. multiple values to ensure that covers relationships authorizationapi.NewRule("edit", "view").Groups(buildapi.FutureGroupName).Resources("jenkins").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(deployGroup).Resources("deploymentconfigs", "generatedeploymentconfigs", "deploymentconfigs/scale").RuleOrDie(), authorizationapi.NewRule("create").Groups(deployGroup).Resources("deploymentconfigrollbacks", "deploymentconfigs/rollback", "deploymentconfigs/instantiate").RuleOrDie(), authorizationapi.NewRule(read...).Groups(deployGroup).Resources("deploymentconfigs/log", "deploymentconfigs/status").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(imageGroup).Resources("imagestreams", "imagestreammappings", "imagestreamtags", "imagestreamimages", "imagestreams/secrets").RuleOrDie(), authorizationapi.NewRule(read...).Groups(imageGroup).Resources("imagestreams/status").RuleOrDie(), // push and pull images authorizationapi.NewRule("get", "update").Groups(imageGroup).Resources("imagestreams/layers").RuleOrDie(), authorizationapi.NewRule("create").Groups(imageGroup).Resources("imagestreamimports").RuleOrDie(), authorizationapi.NewRule("get").Groups(projectGroup).Resources("projects").RuleOrDie(), authorizationapi.NewRule(read...).Groups(quotaGroup).Resources("appliedclusterresourcequotas").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(routeGroup).Resources("routes").RuleOrDie(), authorizationapi.NewRule(read...).Groups(routeGroup).Resources("routes/status").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(templateGroup).Resources("templates", "templateconfigs", "processedtemplates").RuleOrDie(), // backwards compatibility authorizationapi.NewRule(readWrite...).Groups(buildGroup).Resources("buildlogs").RuleOrDie(), authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("resourcequotausages").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: ViewRoleName, }, Rules: []authorizationapi.PolicyRule{ // TODO add "replicationcontrollers/scale" here authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("pods", "replicationcontrollers", "serviceaccounts", "services", "endpoints", "persistentvolumeclaims", "configmaps").RuleOrDie(), authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("limitranges", "resourcequotas", "bindings", "events", "namespaces", "pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(), authorizationapi.NewRule(read...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), authorizationapi.NewRule(read...).Groups(batchGroup).Resources("jobs", "scheduledjobs").RuleOrDie(), authorizationapi.NewRule(read...).Groups(extensionsGroup).Resources("jobs", "horizontalpodautoscalers", "replicasets", "replicasets/scale", "deployments", "deployments/scale").RuleOrDie(), authorizationapi.NewRule(read...).Groups(extensionsGroup).Resources("daemonsets").RuleOrDie(), authorizationapi.NewRule(read...).Groups(appsGroup).Resources("petsets").RuleOrDie(), authorizationapi.NewRule(read...).Groups(buildGroup).Resources("builds", "buildconfigs", "buildconfigs/webhooks").RuleOrDie(), authorizationapi.NewRule(read...).Groups(buildGroup).Resources("builds/log").RuleOrDie(), // access to jenkins authorizationapi.NewRule("view").Groups(buildapi.FutureGroupName).Resources("jenkins").RuleOrDie(), authorizationapi.NewRule(read...).Groups(deployGroup).Resources("deploymentconfigs", "deploymentconfigs/scale").RuleOrDie(), authorizationapi.NewRule(read...).Groups(deployGroup).Resources("deploymentconfigs/log", "deploymentconfigs/status").RuleOrDie(), authorizationapi.NewRule(read...).Groups(imageGroup).Resources("imagestreams", "imagestreammappings", "imagestreamtags", "imagestreamimages").RuleOrDie(), authorizationapi.NewRule(read...).Groups(imageGroup).Resources("imagestreams/status").RuleOrDie(), // TODO let them pull images? // pull images // authorizationapi.NewRule("get").Groups(imageGroup).Resources("imagestreams/layers").RuleOrDie(), authorizationapi.NewRule("get").Groups(projectGroup).Resources("projects").RuleOrDie(), authorizationapi.NewRule(read...).Groups(quotaGroup).Resources("appliedclusterresourcequotas").RuleOrDie(), authorizationapi.NewRule(read...).Groups(routeGroup).Resources("routes").RuleOrDie(), authorizationapi.NewRule(read...).Groups(routeGroup).Resources("routes/status").RuleOrDie(), authorizationapi.NewRule(read...).Groups(templateGroup).Resources("templates", "templateconfigs", "processedtemplates").RuleOrDie(), // backwards compatibility authorizationapi.NewRule(read...).Groups(buildGroup).Resources("buildlogs").RuleOrDie(), authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("resourcequotausages").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: BasicUserRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("get").Groups(userGroup).Resources("users").Names("~").RuleOrDie(), authorizationapi.NewRule("list").Groups(projectGroup).Resources("projectrequests").RuleOrDie(), authorizationapi.NewRule("get", "list").Groups(authzGroup).Resources("clusterroles").RuleOrDie(), authorizationapi.NewRule("list", "watch").Groups(projectGroup).Resources("projects").RuleOrDie(), authorizationapi.NewRule("create").Groups(authzGroup).Resources("selfsubjectrulesreviews").RuleOrDie(), {Verbs: sets.NewString("create"), APIGroups: []string{authzGroup}, Resources: sets.NewString("subjectaccessreviews", "localsubjectaccessreviews"), AttributeRestrictions: &authorizationapi.IsPersonalSubjectAccessReview{}}, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: SelfAccessReviewerRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("create").Groups(authzGroup).Resources("selfsubjectrulesreviews").RuleOrDie(), {Verbs: sets.NewString("create"), APIGroups: []string{authzGroup}, Resources: sets.NewString("subjectaccessreviews", "localsubjectaccessreviews"), AttributeRestrictions: &authorizationapi.IsPersonalSubjectAccessReview{}}, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: SelfProvisionerRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("create").Groups(projectGroup).Resources("projectrequests").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: StatusCheckerRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get"), NonResourceURLs: sets.NewString( // Health "/healthz", "/healthz/*", ), }, authorizationapi.DiscoveryRule, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: ImageAuditorRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("get", "list", "watch", "patch", "update").Groups(imageGroup).Resources("images").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: ImagePullerRoleName, }, Rules: []authorizationapi.PolicyRule{ // pull images authorizationapi.NewRule("get").Groups(imageGroup).Resources("imagestreams/layers").RuleOrDie(), }, }, { // This role looks like a duplicate of ImageBuilderRole, but the ImageBuilder role is specifically for our builder service accounts // if we found another permission needed by them, we'd add it there so the intent is different if you used the ImageBuilderRole // you could end up accidentally granting more permissions than you intended. This is intended to only grant enough powers to // push an image to our registry ObjectMeta: kapi.ObjectMeta{ Name: ImagePusherRoleName, }, Rules: []authorizationapi.PolicyRule{ // push and pull images authorizationapi.NewRule("get", "update").Groups(imageGroup).Resources("imagestreams/layers").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: ImageBuilderRoleName, }, Rules: []authorizationapi.PolicyRule{ // push and pull images authorizationapi.NewRule("get", "update").Groups(imageGroup).Resources("imagestreams/layers").RuleOrDie(), // allow auto-provisioning when pushing an image that doesn't have an imagestream yet authorizationapi.NewRule("create").Groups(imageGroup).Resources("imagestreams").RuleOrDie(), authorizationapi.NewRule("update").Groups(buildGroup).Resources("builds/details").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: ImagePrunerRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("get", "list").Groups(kapiGroup).Resources("pods", "replicationcontrollers").RuleOrDie(), authorizationapi.NewRule("list").Groups(kapiGroup).Resources("limitranges").RuleOrDie(), authorizationapi.NewRule("get", "list").Groups(buildGroup).Resources("buildconfigs", "builds").RuleOrDie(), authorizationapi.NewRule("get", "list").Groups(deployGroup).Resources("deploymentconfigs").RuleOrDie(), authorizationapi.NewRule("delete").Groups(imageGroup).Resources("images").RuleOrDie(), authorizationapi.NewRule("get", "list").Groups(imageGroup).Resources("images", "imagestreams").RuleOrDie(), authorizationapi.NewRule("update").Groups(imageGroup).Resources("imagestreams/status").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: ImageSignerRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("get").Groups(imageGroup).Resources("images", "imagestreams/layers").RuleOrDie(), authorizationapi.NewRule("create", "delete").Groups(imageGroup).Resources("imagesignatures").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: DeployerRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("get", "list", "watch", "update").Groups(kapiGroup).Resources("replicationcontrollers").RuleOrDie(), authorizationapi.NewRule("get", "list", "watch", "create").Groups(kapiGroup).Resources("pods").RuleOrDie(), authorizationapi.NewRule("get").Groups(kapiGroup).Resources("pods/log").RuleOrDie(), authorizationapi.NewRule("create", "list").Groups(kapiGroup).Resources("events").RuleOrDie(), authorizationapi.NewRule("update").Groups(imageGroup).Resources("imagestreamtags").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: MasterRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("*").Groups("*").Resources("*").RuleOrDie(), { Verbs: sets.NewString(authorizationapi.VerbAll), NonResourceURLs: sets.NewString(authorizationapi.NonResourceAll), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: OAuthTokenDeleterRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("delete").Groups(oauthGroup).Resources("oauthaccesstokens", "oauthauthorizetokens").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: RouterRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("list", "watch").Groups(kapiGroup).Resources("endpoints").RuleOrDie(), authorizationapi.NewRule("list", "watch").Groups(kapiGroup).Resources("services").RuleOrDie(), authorizationapi.NewRule("list", "watch").Groups(kapiGroup).Resources("nodes").RuleOrDie(), authorizationapi.NewRule("list", "watch").Groups(routeGroup).Resources("routes").RuleOrDie(), authorizationapi.NewRule("update").Groups(routeGroup).Resources("routes/status").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: RegistryRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("list").Groups(kapiGroup).Resources("limitranges", "resourcequotas").RuleOrDie(), authorizationapi.NewRule("get", "delete").Groups(imageGroup).Resources("images", "imagestreamtags").RuleOrDie(), authorizationapi.NewRule("get").Groups(imageGroup).Resources("imagestreamimages", "imagestreams/secrets").RuleOrDie(), authorizationapi.NewRule("get", "update").Groups(imageGroup).Resources("imagestreams").RuleOrDie(), authorizationapi.NewRule("create").Groups(imageGroup).Resources("imagestreammappings").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: NodeProxierRoleName, }, Rules: []authorizationapi.PolicyRule{ // Used to build serviceLister authorizationapi.NewRule("list", "watch").Groups(kapiGroup).Resources("services", "endpoints").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: NodeAdminRoleName, }, Rules: []authorizationapi.PolicyRule{ // Allow read-only access to the API objects authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("nodes").RuleOrDie(), // Allow all API calls to the nodes authorizationapi.NewRule("proxy").Groups(kapiGroup).Resources("nodes").RuleOrDie(), authorizationapi.NewRule("*").Groups(kapiGroup).Resources("nodes/proxy", authorizationapi.NodeMetricsResource, authorizationapi.NodeSpecResource, authorizationapi.NodeStatsResource, authorizationapi.NodeLogResource).RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: NodeReaderRoleName, }, Rules: []authorizationapi.PolicyRule{ // Allow read-only access to the API objects authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("nodes").RuleOrDie(), // Allow read access to node metrics authorizationapi.NewRule("get").Groups(kapiGroup).Resources(authorizationapi.NodeMetricsResource, authorizationapi.NodeSpecResource).RuleOrDie(), // Allow read access to stats // Node stats requests are submitted as POSTs. These creates are non-mutating authorizationapi.NewRule("get", "create").Groups(kapiGroup).Resources(authorizationapi.NodeStatsResource).RuleOrDie(), // TODO: expose other things like /healthz on the node once we figure out non-resource URL policy across systems }, }, { ObjectMeta: kapi.ObjectMeta{ Name: NodeRoleName, }, Rules: []authorizationapi.PolicyRule{ // Needed to check API access. These creates are non-mutating authorizationapi.NewRule("create").Groups("authentication.k8s.io").Resources("tokenreviews").RuleOrDie(), authorizationapi.NewRule("create").Groups(authzGroup).Resources("subjectaccessreviews", "localsubjectaccessreviews").RuleOrDie(), // Needed to build serviceLister, to populate env vars for services authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("services").RuleOrDie(), // Nodes can register themselves // TODO: restrict to creating a node with the same name they announce authorizationapi.NewRule("create", "get", "list", "watch").Groups(kapiGroup).Resources("nodes").RuleOrDie(), // TODO: restrict to the bound node once supported authorizationapi.NewRule("update").Groups(kapiGroup).Resources("nodes/status").RuleOrDie(), // TODO: restrict to the bound node as creator once supported authorizationapi.NewRule("create", "update", "patch").Groups(kapiGroup).Resources("events").RuleOrDie(), // TODO: restrict to pods scheduled on the bound node once supported authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("pods").RuleOrDie(), // TODO: remove once mirror pods are removed // TODO: restrict deletion to mirror pods created by the bound node once supported // Needed for the node to create/delete mirror pods authorizationapi.NewRule("get", "create", "delete").Groups(kapiGroup).Resources("pods").RuleOrDie(), // TODO: restrict to pods scheduled on the bound node once supported authorizationapi.NewRule("update").Groups(kapiGroup).Resources("pods/status").RuleOrDie(), // TODO: restrict to secrets and configmaps used by pods scheduled on bound node once supported // Needed for imagepullsecrets, rbd/ceph and secret volumes, and secrets in envs // Needed for configmap volume and envs authorizationapi.NewRule("get").Groups(kapiGroup).Resources("secrets", "configmaps").RuleOrDie(), // TODO: restrict to claims/volumes used by pods scheduled on bound node once supported // Needed for persistent volumes authorizationapi.NewRule("get").Groups(kapiGroup).Resources("persistentvolumeclaims", "persistentvolumes").RuleOrDie(), // TODO: restrict to namespaces of pods scheduled on bound node once supported // TODO: change glusterfs to use DNS lookup so this isn't needed? // Needed for glusterfs volumes authorizationapi.NewRule("get").Groups(kapiGroup).Resources("endpoints").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: SDNReaderRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule(read...).Groups(sdnGroup).Resources("hostsubnets", "netnamespaces").RuleOrDie(), authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("nodes", "namespaces").RuleOrDie(), authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("egressnetworkpolicies").RuleOrDie(), authorizationapi.NewRule("get").Groups(sdnGroup).Resources("clusternetworks").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: SDNManagerRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("get", "list", "watch", "create", "delete").Groups(sdnGroup).Resources("hostsubnets", "netnamespaces").RuleOrDie(), authorizationapi.NewRule("get", "create").Groups(sdnGroup).Resources("clusternetworks").RuleOrDie(), authorizationapi.NewRule(read...).Groups(kapiGroup).Resources("nodes").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: WebHooksRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule("get", "create").Groups(buildGroup).Resources("buildconfigs/webhooks").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: DiscoveryRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.DiscoveryRule, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: RegistryAdminRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule(readWrite...).Groups(kapiGroup).Resources("serviceaccounts", "secrets").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(imageGroup).Resources("imagestreamimages", "imagestreammappings", "imagestreams", "imagestreams/secrets", "imagestreamtags").RuleOrDie(), authorizationapi.NewRule("create").Groups(imageGroup).Resources("imagestreamimports").RuleOrDie(), authorizationapi.NewRule("get", "update").Groups(imageGroup).Resources("imagestreams/layers").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(authzGroup).Resources("rolebindings", "roles").RuleOrDie(), authorizationapi.NewRule("create").Groups(authzGroup).Resources("localresourceaccessreviews", "localsubjectaccessreviews", "subjectrulesreviews").RuleOrDie(), authorizationapi.NewRule(read...).Groups(authzGroup).Resources("policies", "policybindings").RuleOrDie(), authorizationapi.NewRule("get").Groups(kapiGroup).Resources("namespaces").RuleOrDie(), authorizationapi.NewRule("get", "delete").Groups(projectGroup).Resources("projects").RuleOrDie(), // backwards compatibility authorizationapi.NewRule("create").Groups(authzGroup).Resources("resourceaccessreviews", "subjectaccessreviews").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: RegistryEditorRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule(readWrite...).Groups(kapiGroup).Resources("serviceaccounts", "secrets").RuleOrDie(), authorizationapi.NewRule(readWrite...).Groups(imageGroup).Resources("imagestreamimages", "imagestreammappings", "imagestreams", "imagestreams/secrets", "imagestreamtags").RuleOrDie(), authorizationapi.NewRule("create").Groups(imageGroup).Resources("imagestreamimports").RuleOrDie(), authorizationapi.NewRule("get", "update").Groups(imageGroup).Resources("imagestreams/layers").RuleOrDie(), authorizationapi.NewRule("get").Groups(kapiGroup).Resources("namespaces").RuleOrDie(), authorizationapi.NewRule("get").Groups(projectGroup).Resources("projects").RuleOrDie(), }, }, { ObjectMeta: kapi.ObjectMeta{ Name: RegistryViewerRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.NewRule(read...).Groups(imageGroup).Resources("imagestreamimages", "imagestreammappings", "imagestreams", "imagestreamtags").RuleOrDie(), authorizationapi.NewRule("get").Groups(imageGroup).Resources("imagestreams/layers").RuleOrDie(), authorizationapi.NewRule("get").Groups(kapiGroup).Resources("namespaces").RuleOrDie(), authorizationapi.NewRule("get").Groups(projectGroup).Resources("projects").RuleOrDie(), }, }, } saRoles := InfraSAs.AllRoles() for _, saRole := range saRoles { for _, existingRole := range roles { if existingRole.Name == saRole.Name { panic(fmt.Sprintf("clusterrole/%s is already registered", existingRole.Name)) } } } // TODO roundtrip roles to pick up defaulting for API groups. Without this, the covers check in reconcile-cluster-roles will fail. // we can remove this again once everything gets group qualified and we have unit tests enforcing that. other pulls are in // progress to do that. // we only want to roundtrip the sa roles now. We'll remove this once we convert the SA roles versionedRoles := []authorizationapiv1.ClusterRole{} for i := range saRoles { newRole := &authorizationapiv1.ClusterRole{} if err := kapi.Scheme.Convert(&saRoles[i], newRole, nil); err != nil { panic(err) } versionedRoles = append(versionedRoles, *newRole) } roundtrippedRoles := []authorizationapi.ClusterRole{} for i := range versionedRoles { newRole := &authorizationapi.ClusterRole{} if err := kapi.Scheme.Convert(&versionedRoles[i], newRole, nil); err != nil { panic(err) } roundtrippedRoles = append(roundtrippedRoles, *newRole) } roles = append(roles, roundtrippedRoles...) // we don't want to expose the resourcegroups externally because it makes it very difficult for customers to learn from // our default roles and hard for them to reason about what power they are granting their users for i := range roles { for j := range roles[i].Rules { roles[i].Rules[j].Resources = authorizationapi.NormalizeResources(roles[i].Rules[j].Resources) } } return roles }
func GetBootstrapClusterRoles() []authorizationapi.ClusterRole { roles := []authorizationapi.ClusterRole{ { ObjectMeta: kapi.ObjectMeta{ Name: ClusterAdminRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString(authorizationapi.VerbAll), Resources: sets.NewString(authorizationapi.ResourceAll), APIGroups: []string{authorizationapi.APIGroupAll}, }, { Verbs: sets.NewString(authorizationapi.VerbAll), NonResourceURLs: sets.NewString(authorizationapi.NonResourceAll), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: ClusterReaderRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString(authorizationapi.NonEscalatingResourcesGroupName), }, { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("jobs", "horizontalpodautoscalers", "replicationcontrollers/scale"), APIGroups: []string{authorizationapi.APIGroupExtensions}, }, { // permissions to check access. These creates are non-mutating Verbs: sets.NewString("create"), Resources: sets.NewString("resourceaccessreviews", "subjectaccessreviews"), }, // Allow read access to node metrics { Verbs: sets.NewString("get"), Resources: sets.NewString(authorizationapi.NodeMetricsResource), }, // Allow read access to stats // Node stats requests are submitted as POSTs. These creates are non-mutating { Verbs: sets.NewString("get", "create"), Resources: sets.NewString(authorizationapi.NodeStatsResource), }, { Verbs: sets.NewString("get"), NonResourceURLs: sets.NewString(authorizationapi.NonResourceAll), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: AdminRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "list", "watch", "create", "update", "patch", "delete"), Resources: sets.NewString(authorizationapi.OpenshiftExposedGroupName, authorizationapi.PermissionGrantingGroupName, authorizationapi.KubeExposedGroupName, "projects", "secrets", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward", authorizationapi.DockerBuildResource, authorizationapi.SourceBuildResource, authorizationapi.CustomBuildResource, "deploymentconfigs/scale"), }, { APIGroups: []string{authorizationapi.APIGroupExtensions}, Verbs: sets.NewString("get", "list", "watch", "create", "update", "patch", "delete"), Resources: sets.NewString("jobs", "horizontalpodautoscalers", "replicationcontrollers/scale"), }, { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString(authorizationapi.PolicyOwnerGroupName, authorizationapi.KubeAllGroupName, authorizationapi.OpenshiftStatusGroupName, authorizationapi.KubeStatusGroupName), }, { Verbs: sets.NewString("get", "update"), // this is used by verifyImageStreamAccess in pkg/dockerregistry/server/auth.go Resources: sets.NewString("imagestreams/layers"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: EditRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "list", "watch", "create", "update", "patch", "delete"), Resources: sets.NewString(authorizationapi.OpenshiftExposedGroupName, authorizationapi.KubeExposedGroupName, "secrets", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward", authorizationapi.DockerBuildResource, authorizationapi.SourceBuildResource, authorizationapi.CustomBuildResource, "deploymentconfigs/scale"), }, { APIGroups: []string{authorizationapi.APIGroupExtensions}, Verbs: sets.NewString("get", "list", "watch", "create", "update", "patch", "delete"), Resources: sets.NewString("jobs", "horizontalpodautoscalers", "replicationcontrollers/scale"), }, { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString(authorizationapi.KubeAllGroupName, authorizationapi.OpenshiftStatusGroupName, authorizationapi.KubeStatusGroupName, "projects"), }, { Verbs: sets.NewString("get", "update"), // this is used by verifyImageStreamAccess in pkg/dockerregistry/server/auth.go Resources: sets.NewString("imagestreams/layers"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: ViewRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString(authorizationapi.OpenshiftExposedGroupName, authorizationapi.KubeAllGroupName, authorizationapi.OpenshiftStatusGroupName, authorizationapi.KubeStatusGroupName, "projects"), }, { APIGroups: []string{authorizationapi.APIGroupExtensions}, Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("jobs", "horizontalpodautoscalers"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: BasicUserRoleName, }, Rules: []authorizationapi.PolicyRule{ {Verbs: sets.NewString("get"), Resources: sets.NewString("users"), ResourceNames: sets.NewString("~")}, {Verbs: sets.NewString("list"), Resources: sets.NewString("projectrequests")}, {Verbs: sets.NewString("list", "get"), Resources: sets.NewString("clusterroles")}, {Verbs: sets.NewString("list"), Resources: sets.NewString("projects")}, {Verbs: sets.NewString("create"), Resources: sets.NewString("subjectaccessreviews", "localsubjectaccessreviews"), AttributeRestrictions: runtime.EmbeddedObject{Object: &authorizationapi.IsPersonalSubjectAccessReview{}}}, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: SelfProvisionerRoleName, }, Rules: []authorizationapi.PolicyRule{ {Verbs: sets.NewString("create"), Resources: sets.NewString("projectrequests")}, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: StatusCheckerRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get"), NonResourceURLs: sets.NewString( "/healthz", "/healthz/*", "/version", "/api", "/api/", "/api/v1", "/api/v1/", "/apis", "/apis/", "/apis/extensions", "/apis/extensions/", "/apis/extensions/v1beta1", "/apis/extensions/v1beta1/", "/osapi", "/osapi/", // these cannot be removed until we can drop support for pre 3.1 clients "/oapi/", "/oapi", "/oapi/v1", "/oapi/v1/", ), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: ImagePullerRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get"), // this is used by verifyImageStreamAccess in pkg/dockerregistry/server/auth.go Resources: sets.NewString("imagestreams/layers"), }, }, }, { // This role looks like a duplicate of ImageBuilderRole, but the ImageBuilder role is specifically for our builder service accounts // if we found another permission needed by them, we'd add it there so the intent is different if you used the ImageBuilderRole // you could end up accidentally granting more permissions than you intended. This is intended to only grant enough powers to // push an image to our registry ObjectMeta: kapi.ObjectMeta{ Name: ImagePusherRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "update"), // this is used by verifyImageStreamAccess in pkg/dockerregistry/server/auth.go Resources: sets.NewString("imagestreams/layers"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: ImageBuilderRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "update"), // this is used by verifyImageStreamAccess in pkg/dockerregistry/server/auth.go Resources: sets.NewString("imagestreams/layers"), }, { Verbs: sets.NewString("update"), Resources: sets.NewString("builds/details"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: ImagePrunerRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("delete"), Resources: sets.NewString("images"), }, { Verbs: sets.NewString("get", "list"), Resources: sets.NewString("images", "imagestreams", "pods", "replicationcontrollers", "buildconfigs", "builds", "deploymentconfigs"), }, { Verbs: sets.NewString("update"), Resources: sets.NewString("imagestreams/status"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: DeployerRoleName, }, Rules: []authorizationapi.PolicyRule{ { // replicationControllerGetter Verbs: sets.NewString("get", "list"), Resources: sets.NewString("replicationcontrollers"), }, { // RecreateDeploymentStrategy.replicationControllerClient // RollingDeploymentStrategy.updaterClient Verbs: sets.NewString("get", "update"), Resources: sets.NewString("replicationcontrollers"), }, { // RecreateDeploymentStrategy.hookExecutor // RollingDeploymentStrategy.hookExecutor Verbs: sets.NewString("get", "list", "watch", "create"), Resources: sets.NewString("pods"), }, { // RecreateDeploymentStrategy.hookExecutor // RollingDeploymentStrategy.hookExecutor Verbs: sets.NewString("get"), Resources: sets.NewString("pods/log"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: MasterRoleName, }, Rules: []authorizationapi.PolicyRule{ { APIGroups: []string{authorizationapi.APIGroupAll}, Verbs: sets.NewString(authorizationapi.VerbAll), Resources: sets.NewString(authorizationapi.ResourceAll), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: OAuthTokenDeleterRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("delete"), Resources: sets.NewString("oauthaccesstokens", "oauthauthorizetokens"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: RouterRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("list", "watch"), Resources: sets.NewString("routes", "endpoints"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: RegistryRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "delete"), Resources: sets.NewString("images"), }, { Verbs: sets.NewString("get"), Resources: sets.NewString("imagestreamimages", "imagestreamtags", "imagestreams"), }, { Verbs: sets.NewString("update"), Resources: sets.NewString("imagestreams"), }, { Verbs: sets.NewString("create"), Resources: sets.NewString("imagestreammappings"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: NodeProxierRoleName, }, Rules: []authorizationapi.PolicyRule{ { // Used to build serviceLister Verbs: sets.NewString("list", "watch"), Resources: sets.NewString("services", "endpoints"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: NodeAdminRoleName, }, Rules: []authorizationapi.PolicyRule{ // Allow read-only access to the API objects { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("nodes"), }, // Allow all API calls to the nodes { Verbs: sets.NewString("proxy"), Resources: sets.NewString("nodes"), }, { Verbs: sets.NewString(authorizationapi.VerbAll), Resources: sets.NewString(authorizationapi.NodeMetricsResource, authorizationapi.NodeStatsResource, authorizationapi.NodeLogResource), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: NodeReaderRoleName, }, Rules: []authorizationapi.PolicyRule{ // Allow read-only access to the API objects { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("nodes"), }, // Allow read access to node metrics { Verbs: sets.NewString("get"), Resources: sets.NewString(authorizationapi.NodeMetricsResource), }, // Allow read access to stats // Node stats requests are submitted as POSTs. These creates are non-mutating { Verbs: sets.NewString("get", "create"), Resources: sets.NewString(authorizationapi.NodeStatsResource), }, // TODO: expose other things like /healthz on the node once we figure out non-resource URL policy across systems }, }, { ObjectMeta: kapi.ObjectMeta{ Name: NodeRoleName, }, Rules: []authorizationapi.PolicyRule{ { // Needed to check API access. These creates are non-mutating Verbs: sets.NewString("create"), Resources: sets.NewString("subjectaccessreviews", "localsubjectaccessreviews"), }, { // Needed to build serviceLister, to populate env vars for services Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("services"), }, { // Nodes can register themselves // TODO: restrict to creating a node with the same name they announce Verbs: sets.NewString("create", "get", "list", "watch"), Resources: sets.NewString("nodes"), }, { // TODO: restrict to the bound node once supported Verbs: sets.NewString("update"), Resources: sets.NewString("nodes/status"), }, { // TODO: restrict to the bound node as creator once supported Verbs: sets.NewString("create", "update", "patch"), Resources: sets.NewString("events"), }, { // TODO: restrict to pods scheduled on the bound node once supported Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("pods"), }, { // TODO: remove once mirror pods are removed // TODO: restrict deletion to mirror pods created by the bound node once supported // Needed for the node to create/delete mirror pods Verbs: sets.NewString("get", "create", "delete"), Resources: sets.NewString("pods"), }, { // TODO: restrict to pods scheduled on the bound node once supported Verbs: sets.NewString("update"), Resources: sets.NewString("pods/status"), }, { // TODO: restrict to secrets used by pods scheduled on bound node once supported // Needed for imagepullsecrets, rbd/ceph and secret volumes Verbs: sets.NewString("get"), Resources: sets.NewString("secrets"), }, { // TODO: restrict to claims/volumes used by pods scheduled on bound node once supported // Needed for persistent volumes Verbs: sets.NewString("get"), Resources: sets.NewString("persistentvolumeclaims", "persistentvolumes"), }, { // TODO: restrict to namespaces of pods scheduled on bound node once supported // TODO: change glusterfs to use DNS lookup so this isn't needed? // Needed for glusterfs volumes Verbs: sets.NewString("get"), Resources: sets.NewString("endpoints"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: SDNReaderRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("hostsubnets"), }, { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("netnamespaces"), }, { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("nodes"), }, { Verbs: sets.NewString("get"), Resources: sets.NewString("clusternetworks"), }, { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("namespaces"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: SDNManagerRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "list", "watch", "create", "delete"), Resources: sets.NewString("hostsubnets"), }, { Verbs: sets.NewString("get", "list", "watch", "create", "delete"), Resources: sets.NewString("netnamespaces"), }, { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("nodes"), }, { Verbs: sets.NewString("get", "create"), Resources: sets.NewString("clusternetworks"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: WebHooksRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "create"), Resources: sets.NewString("buildconfigs/webhooks"), }, }, }, } saRoles := InfraSAs.AllRoles() for _, saRole := range saRoles { for _, existingRole := range roles { if existingRole.Name == saRole.Name { panic(fmt.Sprintf("clusterrole/%s is already registered", existingRole.Name)) } } } roles = append(roles, saRoles...) // we don't want to expose the resourcegroups externally because it makes it very difficult for customers to learn from // our default roles and hard for them to reason about what power they are granting their users for i := range roles { for j := range roles[i].Rules { roles[i].Rules[j].Resources = authorizationapi.NormalizeResources(roles[i].Rules[j].Resources) } } return roles }
func oldGetBootstrapClusterRoles() []authorizationapi.ClusterRole { roles := []authorizationapi.ClusterRole{ { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.ClusterAdminRoleName, }, Rules: []authorizationapi.PolicyRule{ { APIGroups: []string{authorizationapi.APIGroupAll}, Verbs: sets.NewString(authorizationapi.VerbAll), Resources: sets.NewString(authorizationapi.ResourceAll), }, { Verbs: sets.NewString(authorizationapi.VerbAll), NonResourceURLs: sets.NewString(authorizationapi.NonResourceAll), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.SudoerRoleName, }, Rules: []authorizationapi.PolicyRule{ { APIGroups: []string{kapi.GroupName}, Verbs: sets.NewString("impersonate"), Resources: sets.NewString(authorizationapi.SystemUserResource), ResourceNames: sets.NewString(bootstrappolicy.SystemAdminUsername), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.ClusterReaderRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString(authorizationapi.NonEscalatingResourcesGroupName), }, { APIGroups: []string{autoscaling.GroupName}, Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("horizontalpodautoscalers"), }, { APIGroups: []string{batch.GroupName}, Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("jobs"), }, { APIGroups: []string{extensions.GroupName}, Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("daemonsets", "jobs", "horizontalpodautoscalers", "replicationcontrollers/scale"), }, { // permissions to check access. These creates are non-mutating Verbs: sets.NewString("create"), Resources: sets.NewString("resourceaccessreviews", "subjectaccessreviews"), }, // Allow read access to node metrics { Verbs: sets.NewString("get"), Resources: sets.NewString(authorizationapi.NodeMetricsResource), }, // Allow read access to stats // Node stats requests are submitted as POSTs. These creates are non-mutating { Verbs: sets.NewString("get", "create"), Resources: sets.NewString(authorizationapi.NodeStatsResource), }, { Verbs: sets.NewString("get"), NonResourceURLs: sets.NewString(authorizationapi.NonResourceAll), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.BuildStrategyDockerRoleName, }, Rules: []authorizationapi.PolicyRule{ { APIGroups: []string{api.GroupName}, Verbs: sets.NewString("create"), Resources: sets.NewString(authorizationapi.DockerBuildResource), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.BuildStrategyCustomRoleName, }, Rules: []authorizationapi.PolicyRule{ { APIGroups: []string{api.GroupName}, Verbs: sets.NewString("create"), Resources: sets.NewString(authorizationapi.CustomBuildResource), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.BuildStrategySourceRoleName, }, Rules: []authorizationapi.PolicyRule{ { APIGroups: []string{api.GroupName}, Verbs: sets.NewString("create"), Resources: sets.NewString(authorizationapi.SourceBuildResource), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.BuildStrategyJenkinsPipelineRoleName, }, Rules: []authorizationapi.PolicyRule{ { APIGroups: []string{api.GroupName}, Verbs: sets.NewString("create"), Resources: sets.NewString(authorizationapi.JenkinsPipelineBuildResource), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.AdminRoleName, }, Rules: []authorizationapi.PolicyRule{ { APIGroups: []string{kapi.GroupName}, Verbs: sets.NewString("get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"), Resources: sets.NewString( authorizationapi.KubeExposedGroupName, "secrets", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward", "services/proxy", "replicationcontrollers/scale", ), }, { APIGroups: []string{kapi.GroupName}, Verbs: sets.NewString("impersonate"), Resources: sets.NewString("serviceaccounts"), }, { APIGroups: []string{api.GroupName}, Verbs: sets.NewString("get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"), Resources: sets.NewString( authorizationapi.OpenshiftExposedGroupName, authorizationapi.PermissionGrantingGroupName, "projects", "deploymentconfigs/scale", "imagestreams/secrets", ), }, { APIGroups: []string{autoscaling.GroupName}, Verbs: sets.NewString("get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"), Resources: sets.NewString("horizontalpodautoscalers"), }, { APIGroups: []string{batch.GroupName}, Verbs: sets.NewString("get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"), Resources: sets.NewString("jobs"), }, { APIGroups: []string{extensions.GroupName}, Verbs: sets.NewString("get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"), Resources: sets.NewString("jobs", "horizontalpodautoscalers", "replicationcontrollers/scale"), }, { APIGroups: []string{extensions.GroupName}, Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("daemonsets"), }, { APIGroups: []string{api.GroupName}, Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString(authorizationapi.PolicyOwnerGroupName, authorizationapi.KubeAllGroupName, authorizationapi.OpenshiftStatusGroupName, authorizationapi.KubeStatusGroupName), }, { APIGroups: []string{imageapi.GroupName}, Verbs: sets.NewString("get", "update"), // this is used by verifyImageStreamAccess in pkg/dockerregistry/server/auth.go Resources: sets.NewString("imagestreams/layers"), }, // an admin can run routers that write back conditions to the route { APIGroups: []string{routeapi.GroupName}, Verbs: sets.NewString("update"), Resources: sets.NewString("routes/status"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.EditRoleName, }, Rules: []authorizationapi.PolicyRule{ { APIGroups: []string{kapi.GroupName}, Verbs: sets.NewString("get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"), Resources: sets.NewString( authorizationapi.KubeExposedGroupName, "secrets", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward", "services/proxy", "replicationcontrollers/scale", ), }, { APIGroups: []string{kapi.GroupName}, Verbs: sets.NewString("impersonate"), Resources: sets.NewString("serviceaccounts"), }, { APIGroups: []string{api.GroupName}, Verbs: sets.NewString("get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"), Resources: sets.NewString( authorizationapi.OpenshiftExposedGroupName, "deploymentconfigs/scale", "imagestreams/secrets", ), }, { APIGroups: []string{autoscaling.GroupName}, Verbs: sets.NewString("get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"), Resources: sets.NewString("horizontalpodautoscalers"), }, { APIGroups: []string{batch.GroupName}, Verbs: sets.NewString("get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"), Resources: sets.NewString("jobs"), }, { APIGroups: []string{extensions.GroupName}, Verbs: sets.NewString("get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"), Resources: sets.NewString("jobs", "horizontalpodautoscalers", "replicationcontrollers/scale"), }, { APIGroups: []string{extensions.GroupName}, Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("daemonsets"), }, { APIGroups: []string{api.GroupName}, Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString(authorizationapi.KubeAllGroupName, authorizationapi.OpenshiftStatusGroupName, authorizationapi.KubeStatusGroupName, "projects"), }, { APIGroups: []string{imageapi.GroupName}, Verbs: sets.NewString("get", "update"), // this is used by verifyImageStreamAccess in pkg/dockerregistry/server/auth.go Resources: sets.NewString("imagestreams/layers"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.ViewRoleName, }, Rules: []authorizationapi.PolicyRule{ { APIGroups: []string{api.GroupName}, Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString(authorizationapi.OpenshiftExposedGroupName, authorizationapi.KubeAllGroupName, authorizationapi.OpenshiftStatusGroupName, authorizationapi.KubeStatusGroupName, "projects"), }, { APIGroups: []string{autoscaling.GroupName}, Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("horizontalpodautoscalers"), }, { APIGroups: []string{batch.GroupName}, Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("jobs"), }, { APIGroups: []string{extensions.GroupName}, Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("daemonsets", "jobs", "horizontalpodautoscalers"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.BasicUserRoleName, }, Rules: []authorizationapi.PolicyRule{ {Verbs: sets.NewString("get"), Resources: sets.NewString("users"), ResourceNames: sets.NewString("~")}, {Verbs: sets.NewString("list"), Resources: sets.NewString("projectrequests")}, {Verbs: sets.NewString("list", "get"), Resources: sets.NewString("clusterroles")}, {Verbs: sets.NewString("list", "watch"), Resources: sets.NewString("projects")}, {Verbs: sets.NewString("create"), Resources: sets.NewString("subjectaccessreviews", "localsubjectaccessreviews"), AttributeRestrictions: &authorizationapi.IsPersonalSubjectAccessReview{}}, {Verbs: sets.NewString("create"), Resources: sets.NewString("selfsubjectrulesreviews")}, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.SelfProvisionerRoleName, }, Rules: []authorizationapi.PolicyRule{ {Verbs: sets.NewString("create"), Resources: sets.NewString("projectrequests")}, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.StatusCheckerRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get"), NonResourceURLs: sets.NewString( // Health "/healthz", "/healthz/*", ), }, authorizationapi.DiscoveryRule, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.ImageAuditorRoleName, }, Rules: []authorizationapi.PolicyRule{ { APIGroups: []string{imageapi.GroupName}, Verbs: sets.NewString("get", "list", "watch", "patch", "update"), Resources: sets.NewString("images"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.ImagePullerRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get"), // this is used by verifyImageStreamAccess in pkg/dockerregistry/server/auth.go Resources: sets.NewString("imagestreams/layers"), }, }, }, { // This role looks like a duplicate of ImageBuilderRole, but the ImageBuilder role is specifically for our builder service accounts // if we found another permission needed by them, we'd add it there so the intent is different if you used the ImageBuilderRole // you could end up accidentally granting more permissions than you intended. This is intended to only grant enough powers to // push an image to our registry ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.ImagePusherRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "update"), // this is used by verifyImageStreamAccess in pkg/dockerregistry/server/auth.go Resources: sets.NewString("imagestreams/layers"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.ImageBuilderRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "update"), // this is used by verifyImageStreamAccess in pkg/dockerregistry/server/auth.go Resources: sets.NewString("imagestreams/layers"), }, { Verbs: sets.NewString("update"), Resources: sets.NewString("builds/details"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.ImagePrunerRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("delete"), Resources: sets.NewString("images"), }, { Verbs: sets.NewString("get", "list"), Resources: sets.NewString("images", "imagestreams", "pods", "replicationcontrollers", "buildconfigs", "builds", "deploymentconfigs"), }, { Verbs: sets.NewString("update"), Resources: sets.NewString("imagestreams/status"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.DeployerRoleName, }, Rules: []authorizationapi.PolicyRule{ { // replicationControllerGetter Verbs: sets.NewString("get", "list"), Resources: sets.NewString("replicationcontrollers"), }, { // RecreateDeploymentStrategy.replicationControllerClient // RollingDeploymentStrategy.updaterClient Verbs: sets.NewString("get", "update"), Resources: sets.NewString("replicationcontrollers"), }, { // RecreateDeploymentStrategy.hookExecutor // RollingDeploymentStrategy.hookExecutor Verbs: sets.NewString("get", "list", "watch", "create"), Resources: sets.NewString("pods"), }, { // RecreateDeploymentStrategy.hookExecutor // RollingDeploymentStrategy.hookExecutor Verbs: sets.NewString("get"), Resources: sets.NewString("pods/log"), }, { // Deployer.After.TagImages Verbs: sets.NewString("update"), Resources: sets.NewString("imagestreamtags"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.MasterRoleName, }, Rules: []authorizationapi.PolicyRule{ { APIGroups: []string{authorizationapi.APIGroupAll}, Verbs: sets.NewString(authorizationapi.VerbAll), Resources: sets.NewString(authorizationapi.ResourceAll), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.OAuthTokenDeleterRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("delete"), Resources: sets.NewString("oauthaccesstokens", "oauthauthorizetokens"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.RouterRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("list", "watch"), Resources: sets.NewString("routes", "endpoints"), }, // routers write back conditions to the route { Verbs: sets.NewString("update"), Resources: sets.NewString("routes/status"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.RegistryRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "delete"), Resources: sets.NewString("images"), }, { Verbs: sets.NewString("get"), Resources: sets.NewString("imagestreamimages", "imagestreamtags", "imagestreams", "imagestreams/secrets"), }, { Verbs: sets.NewString("update"), Resources: sets.NewString("imagestreams"), }, { Verbs: sets.NewString("create"), Resources: sets.NewString("imagestreammappings"), }, { Verbs: sets.NewString("list"), Resources: sets.NewString("resourcequotas"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.NodeProxierRoleName, }, Rules: []authorizationapi.PolicyRule{ { // Used to build serviceLister Verbs: sets.NewString("list", "watch"), Resources: sets.NewString("services", "endpoints"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.NodeAdminRoleName, }, Rules: []authorizationapi.PolicyRule{ // Allow read-only access to the API objects { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("nodes"), }, // Allow all API calls to the nodes { Verbs: sets.NewString("proxy"), Resources: sets.NewString("nodes"), }, { Verbs: sets.NewString(authorizationapi.VerbAll), Resources: sets.NewString("nodes/proxy", authorizationapi.NodeMetricsResource, authorizationapi.NodeStatsResource, authorizationapi.NodeLogResource), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.NodeReaderRoleName, }, Rules: []authorizationapi.PolicyRule{ // Allow read-only access to the API objects { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("nodes"), }, // Allow read access to node metrics { Verbs: sets.NewString("get"), Resources: sets.NewString(authorizationapi.NodeMetricsResource), }, // Allow read access to stats // Node stats requests are submitted as POSTs. These creates are non-mutating { Verbs: sets.NewString("get", "create"), Resources: sets.NewString(authorizationapi.NodeStatsResource), }, // TODO: expose other things like /healthz on the node once we figure out non-resource URL policy across systems }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.NodeRoleName, }, Rules: []authorizationapi.PolicyRule{ { // Needed to check API access. These creates are non-mutating Verbs: sets.NewString("create"), Resources: sets.NewString("subjectaccessreviews", "localsubjectaccessreviews"), }, { // Needed to build serviceLister, to populate env vars for services Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("services"), }, { // Nodes can register themselves // TODO: restrict to creating a node with the same name they announce Verbs: sets.NewString("create", "get", "list", "watch"), Resources: sets.NewString("nodes"), }, { // TODO: restrict to the bound node once supported Verbs: sets.NewString("update"), Resources: sets.NewString("nodes/status"), }, { // TODO: restrict to the bound node as creator once supported Verbs: sets.NewString("create", "update", "patch"), Resources: sets.NewString("events"), }, { // TODO: restrict to pods scheduled on the bound node once supported Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("pods"), }, { // TODO: remove once mirror pods are removed // TODO: restrict deletion to mirror pods created by the bound node once supported // Needed for the node to create/delete mirror pods Verbs: sets.NewString("get", "create", "delete"), Resources: sets.NewString("pods"), }, { // TODO: restrict to pods scheduled on the bound node once supported Verbs: sets.NewString("update"), Resources: sets.NewString("pods/status"), }, { // TODO: restrict to secrets and configmaps used by pods scheduled on bound node once supported // Needed for imagepullsecrets, rbd/ceph and secret volumes, and secrets in envs // Needed for configmap volume and envs Verbs: sets.NewString("get"), Resources: sets.NewString("secrets", "configmaps"), }, { // TODO: restrict to claims/volumes used by pods scheduled on bound node once supported // Needed for persistent volumes Verbs: sets.NewString("get"), Resources: sets.NewString("persistentvolumeclaims", "persistentvolumes"), }, { // TODO: restrict to namespaces of pods scheduled on bound node once supported // TODO: change glusterfs to use DNS lookup so this isn't needed? // Needed for glusterfs volumes Verbs: sets.NewString("get"), Resources: sets.NewString("endpoints"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.SDNReaderRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("hostsubnets"), }, { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("netnamespaces"), }, { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("nodes"), }, { Verbs: sets.NewString("get"), Resources: sets.NewString("clusternetworks"), }, { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("namespaces"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.SDNManagerRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "list", "watch", "create", "delete"), Resources: sets.NewString("hostsubnets"), }, { Verbs: sets.NewString("get", "list", "watch", "create", "delete"), Resources: sets.NewString("netnamespaces"), }, { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("nodes"), }, { Verbs: sets.NewString("get", "create"), Resources: sets.NewString("clusternetworks"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.WebHooksRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "create"), Resources: sets.NewString("buildconfigs/webhooks"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.DiscoveryRoleName, }, Rules: []authorizationapi.PolicyRule{ authorizationapi.DiscoveryRule, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.RegistryAdminRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"), APIGroups: []string{imageapi.GroupName}, Resources: sets.NewString("imagestreamimages", "imagestreamimports", "imagestreammappings", "imagestreams", "imagestreams/secrets", "imagestreamtags"), }, { Verbs: sets.NewString("get", "update"), APIGroups: []string{imageapi.GroupName}, Resources: sets.NewString("imagestreams/layers"), }, { Verbs: sets.NewString("create"), APIGroups: []string{authorizationapi.GroupName}, Resources: sets.NewString("localresourceaccessreviews", "localsubjectaccessreviews", "resourceaccessreviews", "subjectaccessreviews"), }, { Verbs: sets.NewString("create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"), APIGroups: []string{authorizationapi.GroupName}, Resources: sets.NewString("rolebindings", "roles"), }, { Verbs: sets.NewString("get", "list", "watch"), APIGroups: []string{authorizationapi.GroupName}, Resources: sets.NewString("policies", "policybindings"), }, { Verbs: sets.NewString("get"), APIGroups: []string{kapi.GroupName}, Resources: sets.NewString("namespaces"), }, { Verbs: sets.NewString("get", "delete"), APIGroups: []string{projectapi.GroupName}, Resources: sets.NewString("projects"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.RegistryEditorRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("create", "delete", "deletecollection", "get", "list", "patch", "update", "watch"), APIGroups: []string{imageapi.GroupName}, Resources: sets.NewString("imagestreamimages", "imagestreamimports", "imagestreammappings", "imagestreams", "imagestreams/secrets", "imagestreamtags"), }, { Verbs: sets.NewString("get", "update"), APIGroups: []string{imageapi.GroupName}, Resources: sets.NewString("imagestreams/layers"), }, { Verbs: sets.NewString("get"), APIGroups: []string{kapi.GroupName}, Resources: sets.NewString("namespaces"), }, { Verbs: sets.NewString("get"), APIGroups: []string{projectapi.GroupName}, Resources: sets.NewString("projects"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: bootstrappolicy.RegistryViewerRoleName, }, Rules: []authorizationapi.PolicyRule{ { Verbs: sets.NewString("get", "list", "watch"), APIGroups: []string{imageapi.GroupName}, Resources: sets.NewString("imagestreamimages", "imagestreamimports", "imagestreammappings", "imagestreams", "imagestreamtags"), }, { Verbs: sets.NewString("get"), APIGroups: []string{imageapi.GroupName}, Resources: sets.NewString("imagestreams/layers"), }, { Verbs: sets.NewString("get"), APIGroups: []string{kapi.GroupName}, Resources: sets.NewString("namespaces"), }, { Verbs: sets.NewString("get"), APIGroups: []string{projectapi.GroupName}, Resources: sets.NewString("projects"), }, }, }, } // we don't want to expose the resourcegroups externally because it makes it very difficult for customers to learn from // our default roles and hard for them to reason about what power they are granting their users for i := range roles { for j := range roles[i].Rules { roles[i].Rules[j].Resources = authorizationapi.NormalizeResources(roles[i].Rules[j].Resources) } } versionedRoles := []authorizationapiv1.ClusterRole{} for i := range roles { newRole := &authorizationapiv1.ClusterRole{} kapi.Scheme.Convert(&roles[i], newRole) versionedRoles = append(versionedRoles, *newRole) } roundtrippedRoles := []authorizationapi.ClusterRole{} for i := range versionedRoles { newRole := &authorizationapi.ClusterRole{} kapi.Scheme.Convert(&versionedRoles[i], newRole) roundtrippedRoles = append(roundtrippedRoles, *newRole) } return roundtrippedRoles }