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) { allowedResourceTypes := authorizationapi.ExpandResources(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.Object != nil { switch rule.AttributeRestrictions.Object.(type) { case (*authorizationapi.IsPersonalSubjectAccessReview): return IsPersonalAccessReview(a) default: return false, fmt.Errorf("unable to interpret: %#v", rule.AttributeRestrictions.Object) } } return true, nil } } } return false, nil }
func GetBootstrapOpenshiftRoles(openshiftNamespace string) []authorizationapi.Role { roles := []authorizationapi.Role{ { ObjectMeta: kapi.ObjectMeta{ Name: 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.ExpandResources(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.ExpandResources(util.NewStringSet(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.ExpandResources(ownerRule.Resources) verbMatches := ownerRule.Verbs.Has("*") || ownerRule.Verbs.HasAll(subrule.Verbs.List()...) resourceMatches := ownerRule.Resources.Has("*") || 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 }
// 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.ExpandResources(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 breadownRuleForGroup(group string, rule authorizationapi.PolicyRule) []authorizationapi.PolicyRule { subrules := []authorizationapi.PolicyRule{} for resource := range authorizationapi.ExpandResources(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 }
// breadownRule takes a rule and builds an equivalent list of rules that each have at most one verb, one // resource, and one resource name func breakdownRule(rule authorizationapi.PolicyRule) []authorizationapi.PolicyRule { subrules := []authorizationapi.PolicyRule{} for resource := range authorizationapi.ExpandResources(rule.Resources) { for verb := range rule.Verbs { if len(rule.ResourceNames) > 0 { for _, resourceName := range rule.ResourceNames.List() { subrules = append(subrules, authorizationapi.PolicyRule{Resources: util.NewStringSet(resource), Verbs: util.NewStringSet(verb), ResourceNames: util.NewStringSet(resourceName)}) } } else { subrules = append(subrules, authorizationapi.PolicyRule{Resources: util.NewStringSet(resource), Verbs: util.NewStringSet(verb)}) } } } return subrules }
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"), }, }, }, { 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: BuildControllerRoleName, }, Rules: []authorizationapi.PolicyRule{ // BuildControllerFactory.buildLW // BuildControllerFactory.buildDeleteLW { Verbs: sets.NewString("get", "list", "watch"), Resources: sets.NewString("builds"), }, // BuildController.BuildUpdater (OSClientBuildClient) { Verbs: sets.NewString("update"), Resources: sets.NewString("builds"), }, // BuildController.ImageStreamClient (ControllerClient) { Verbs: sets.NewString("get"), Resources: sets.NewString("imagestreams"), }, // BuildController.PodManager (ControllerClient) // BuildDeleteController.PodManager (ControllerClient) // BuildControllerFactory.buildDeleteLW { Verbs: sets.NewString("get", "list", "create", "delete"), Resources: sets.NewString("pods"), }, // BuildController.Recorder (EventBroadcaster) { Verbs: sets.NewString("create", "update", "patch"), Resources: sets.NewString("events"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: DeploymentControllerRoleName, }, Rules: []authorizationapi.PolicyRule{ // DeploymentControllerFactory.deploymentLW { Verbs: sets.NewString("list", "watch"), Resources: sets.NewString("replicationcontrollers"), }, // DeploymentControllerFactory.deploymentClient { Verbs: sets.NewString("get", "update"), Resources: sets.NewString("replicationcontrollers"), }, // DeploymentController.podClient { Verbs: sets.NewString("get", "list", "create", "delete", "update"), Resources: sets.NewString("pods"), }, // DeploymentController.recorder (EventBroadcaster) { Verbs: sets.NewString("create", "update", "patch"), Resources: sets.NewString("events"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: ReplicationControllerRoleName, }, Rules: []authorizationapi.PolicyRule{ // ReplicationManager.rcController.ListWatch { Verbs: sets.NewString("list", "watch"), Resources: sets.NewString("replicationcontrollers"), }, // ReplicationManager.syncReplicationController() -> updateReplicaCount() { // TODO: audit/remove those, 1.0 controllers needed get, update Verbs: sets.NewString("get", "update"), Resources: sets.NewString("replicationcontrollers"), }, // ReplicationManager.syncReplicationController() -> updateReplicaCount() { Verbs: sets.NewString("update"), Resources: sets.NewString("replicationcontrollers/status"), }, // ReplicationManager.podController.ListWatch { Verbs: sets.NewString("list", "watch"), Resources: sets.NewString("pods"), }, // ReplicationManager.podControl (RealPodControl) { Verbs: sets.NewString("create", "delete"), Resources: sets.NewString("pods"), }, // ReplicationManager.podControl.recorder { Verbs: sets.NewString("create", "update", "patch"), Resources: sets.NewString("events"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: JobControllerRoleName, }, Rules: []authorizationapi.PolicyRule{ // JobController.jobController.ListWatch { APIGroups: []string{authorizationapi.APIGroupExtensions}, Verbs: sets.NewString("list", "watch"), Resources: sets.NewString("jobs"), }, // JobController.syncJob() -> updateJobStatus() { APIGroups: []string{authorizationapi.APIGroupExtensions}, Verbs: sets.NewString("update"), Resources: sets.NewString("jobs/status"), }, // JobController.podController.ListWatch { Verbs: sets.NewString("list", "watch"), Resources: sets.NewString("pods"), }, // JobController.podControl (RealPodControl) { Verbs: sets.NewString("create", "delete"), Resources: sets.NewString("pods"), }, // JobController.podControl.recorder { Verbs: sets.NewString("create", "update", "patch"), Resources: sets.NewString("events"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: PersistentVolumeControllerRoleName, }, Rules: []authorizationapi.PolicyRule{ // PersistentVolumeBinder.volumeController.ListWatch { Verbs: sets.NewString("list", "watch"), Resources: sets.NewString("persistentvolumes"), }, // PersistentVolumeBinder.syncVolume() { Verbs: sets.NewString("get", "update", "create", "delete"), Resources: sets.NewString("persistentvolumes"), }, // PersistentVolumeBinder.syncVolume() { Verbs: sets.NewString("update"), Resources: sets.NewString("persistentvolumes/status"), }, // PersistentVolumeBinder.claimController.ListWatch { Verbs: sets.NewString("list", "watch"), Resources: sets.NewString("persistentvolumeclaims"), }, // PersistentVolumeBinder.syncClaim() { Verbs: sets.NewString("get", "update"), Resources: sets.NewString("persistentvolumeclaims"), }, // PersistentVolumeBinder.syncClaim() { Verbs: sets.NewString("update"), Resources: sets.NewString("persistentvolumeclaims/status"), }, // PersistentVolumeRecycler.reclaimVolume() -> handleRecycle() { Verbs: sets.NewString("list", "watch"), Resources: sets.NewString("pods"), }, // PersistentVolumeRecycler.reclaimVolume() -> handleRecycle() { Verbs: sets.NewString("get", "create", "delete"), Resources: sets.NewString("pods"), }, // PersistentVolumeRecycler.reclaimVolume() -> handleRecycle() { Verbs: sets.NewString("create", "update", "patch"), Resources: sets.NewString("events"), }, }, }, { ObjectMeta: kapi.ObjectMeta{ Name: HPAControllerRoleName, }, Rules: []authorizationapi.PolicyRule{ // HPA Controller { APIGroups: []string{authorizationapi.APIGroupExtensions}, Verbs: sets.NewString("get", "list"), Resources: sets.NewString("horizontalpodautoscalers"), }, { APIGroups: []string{authorizationapi.APIGroupExtensions}, Verbs: sets.NewString("update"), Resources: sets.NewString("horizontalpodautoscalers/status"), }, { APIGroups: []string{authorizationapi.APIGroupExtensions}, Verbs: sets.NewString("get", "update"), Resources: sets.NewString("replicationcontrollers/scale"), }, { Verbs: sets.NewString("get", "update"), Resources: sets.NewString("deploymentconfigs/scale"), }, { Verbs: sets.NewString("create", "update", "patch"), Resources: sets.NewString("events"), }, // Heapster MetricsClient { Verbs: sets.NewString("list"), Resources: sets.NewString("pods"), }, { // TODO: fix MetricsClient to no longer require root proxy access // TODO: restrict this to the appropriate namespace Verbs: sets.NewString("proxy"), Resources: sets.NewString("services"), ResourceNames: sets.NewString("https:heapster:"), }, }, }, { 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"), }, }, }, } // 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.ExpandResources(roles[i].Rules[j].Resources) } } return roles }