Beispiel #1
0
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
}
Beispiel #2
0
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))
	}
}
Beispiel #4
0
// 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
}
Beispiel #5
0
// 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
}
Beispiel #6
0
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
}
Beispiel #7
0
// 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
}
Beispiel #8
0
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
}