Merge pull request #53722 from deads2k/rbac-01-allow-star

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

allow */subresource in rbac policy rules

xref #29698
xref #38756
xref #49504
xref #38810

Allow `*/subresource` format in RBAC policy rules to support polymorphic subresources like `*/scale` for HPA.

@DirectXMan12 fyi

```release-note
RBAC PolicyRules now allow resource=`*/<subresource>` to cover `any-resource/<subresource>`.   For example, `*/scale` covers `replicationcontroller/scale`.
```
pull/6/head
Kubernetes Submit Queue 2017-10-18 14:02:05 -07:00 committed by GitHub
commit 900c0761e3
26 changed files with 205 additions and 49 deletions

View File

@ -64461,7 +64461,7 @@
} }
}, },
"resources": { "resources": {
"description": "Resources is a list of resources this rule applies to. ResourceAll represents all resources. \"*\" means all.", "description": "Resources is a list of resources this rule applies to. \"*\" means all in the specified apiGroups.\n \"*/foo\" represents the subresource 'foo' for all resources in the specified apiGroups.",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
@ -64812,7 +64812,7 @@
} }
}, },
"resources": { "resources": {
"description": "Resources is a list of resources this rule applies to. ResourceAll represents all resources. \"*\" means all.", "description": "Resources is a list of resources this rule applies to. \"*\" means all in the specified apiGroups.\n \"*/foo\" represents the subresource 'foo' for all resources in the specified apiGroups.",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"
@ -73180,7 +73180,7 @@
} }
}, },
"resources": { "resources": {
"description": "Resources is a list of resources this rule applies to. ResourceAll represents all resources.", "description": "Resources is a list of resources this rule applies to. '*' represents all resources in the specified apiGroups. '*/foo' represents the subresource 'foo' for all resources in the specified apiGroups.",
"type": "array", "type": "array",
"items": { "items": {
"type": "string" "type": "string"

View File

@ -785,7 +785,7 @@
"items": { "items": {
"type": "string" "type": "string"
}, },
"description": "Resources is a list of resources this rule applies to. ResourceAll represents all resources. \"*\" means all." "description": "Resources is a list of resources this rule applies to. \"*\" means all in the specified apiGroups.\n \"*/foo\" represents the subresource 'foo' for all resources in the specified apiGroups."
}, },
"resourceNames": { "resourceNames": {
"type": "array", "type": "array",

View File

@ -785,7 +785,7 @@
"items": { "items": {
"type": "string" "type": "string"
}, },
"description": "Resources is a list of resources this rule applies to. ResourceAll represents all resources. \"*\" means all." "description": "Resources is a list of resources this rule applies to. \"*\" means all in the specified apiGroups.\n \"*/foo\" represents the subresource 'foo' for all resources in the specified apiGroups."
}, },
"resourceNames": { "resourceNames": {
"type": "array", "type": "array",

View File

@ -3818,7 +3818,7 @@
"items": { "items": {
"type": "string" "type": "string"
}, },
"description": "Resources is a list of resources this rule applies to. ResourceAll represents all resources." "description": "Resources is a list of resources this rule applies to. '*' represents all resources in the specified apiGroups. '*/foo' represents the subresource 'foo' for all resources in the specified apiGroups."
}, },
"resourceNames": { "resourceNames": {
"type": "array", "type": "array",

View File

@ -1432,7 +1432,8 @@ When an object is created, the system will populate this list with the current s
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">resources</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">resources</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Resources is a list of resources this rule applies to. ResourceAll represents all resources. "*" means all.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Resources is a list of resources this rule applies to. "<strong>" means all in the specified apiGroups.<br>
"</strong>/foo" represents the subresource <em>foo</em> for all resources in the specified apiGroups.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string array</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>

View File

@ -1452,7 +1452,8 @@ When an object is created, the system will populate this list with the current s
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">resources</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">resources</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Resources is a list of resources this rule applies to. ResourceAll represents all resources. "*" means all.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Resources is a list of resources this rule applies to. "<strong>" means all in the specified apiGroups.<br>
"</strong>/foo" represents the subresource <em>foo</em> for all resources in the specified apiGroups.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string array</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>

View File

@ -1682,7 +1682,7 @@ Examples:<br>
</tr> </tr>
<tr> <tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">resources</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">resources</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Resources is a list of resources this rule applies to. ResourceAll represents all resources.</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">Resources is a list of resources this rule applies to. <em><strong></em> represents all resources in the specified apiGroups. <em></strong>/foo</em> represents the subresource <em>foo</em> for all resources in the specified apiGroups.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string array</p></td> <td class="tableblock halign-left valign-top"><p class="tableblock">string array</p></td>
<td class="tableblock halign-left valign-top"></td> <td class="tableblock halign-left valign-top"></td>

View File

@ -205,7 +205,8 @@ type ResourceRule struct {
// APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of // APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of
// the enumerated resources in any API group will be allowed. "*" means all. // the enumerated resources in any API group will be allowed. "*" means all.
APIGroups []string APIGroups []string
// Resources is a list of resources this rule applies to. ResourceAll represents all resources. "*" means all. // Resources is a list of resources this rule applies to. "*" means all in the specified apiGroups.
// "*/foo" represents the subresource 'foo' for all resources in the specified apiGroups.
Resources []string Resources []string
// ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. "*" means all. // ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. "*" means all.
ResourceNames []string ResourceNames []string

View File

@ -55,14 +55,29 @@ func APIGroupMatches(rule *PolicyRule, requestedGroup string) bool {
return false return false
} }
func ResourceMatches(rule *PolicyRule, requestedResource string) bool { func ResourceMatches(rule *PolicyRule, combinedRequestedResource, requestedSubresource string) bool {
for _, ruleResource := range rule.Resources { for _, ruleResource := range rule.Resources {
// if everything is allowed, we match
if ruleResource == ResourceAll { if ruleResource == ResourceAll {
return true return true
} }
if ruleResource == requestedResource { // if we have an exact match, we match
if ruleResource == combinedRequestedResource {
return true return true
} }
// We can also match a */subresource.
// if there isn't a subresource, then continue
if len(requestedSubresource) == 0 {
continue
}
// if the rule isn't in the format */subresource, then we don't match, continue
if len(ruleResource) == len(requestedSubresource)+2 &&
strings.HasPrefix(ruleResource, "*/") &&
strings.HasSuffix(ruleResource, requestedSubresource) {
return true
}
} }
return false return false

View File

@ -70,3 +70,108 @@ func TestHelpersRoundTrip(t *testing.T) {
} }
} }
} }
func TestResourceMatches(t *testing.T) {
tests := []struct {
name string
ruleResources []string
combinedRequestedResource string
requestedSubresource string
expected bool
}{
{
name: "all matches 01",
ruleResources: []string{"*"},
combinedRequestedResource: "foo",
expected: true,
},
{
name: "checks all rules",
ruleResources: []string{"doesn't match", "*"},
combinedRequestedResource: "foo",
expected: true,
},
{
name: "matches exact rule",
ruleResources: []string{"foo/bar"},
combinedRequestedResource: "foo/bar",
requestedSubresource: "bar",
expected: true,
},
{
name: "matches exact rule 02",
ruleResources: []string{"foo/bar"},
combinedRequestedResource: "foo",
expected: false,
},
{
name: "matches subresource",
ruleResources: []string{"*/scale"},
combinedRequestedResource: "foo/scale",
requestedSubresource: "scale",
expected: true,
},
{
name: "doesn't match partial subresource hit",
ruleResources: []string{"foo/bar", "*/other"},
combinedRequestedResource: "foo/other/segment",
requestedSubresource: "other/segment",
expected: false,
},
{
name: "matches subresource with multiple slashes",
ruleResources: []string{"*/other/segment"},
combinedRequestedResource: "foo/other/segment",
requestedSubresource: "other/segment",
expected: true,
},
{
name: "doesn't fail on empty",
ruleResources: []string{""},
combinedRequestedResource: "foo/other/segment",
requestedSubresource: "other/segment",
expected: false,
},
{
name: "doesn't fail on slash",
ruleResources: []string{"/"},
combinedRequestedResource: "foo/other/segment",
requestedSubresource: "other/segment",
expected: false,
},
{
name: "doesn't fail on missing subresource",
ruleResources: []string{"*/"},
combinedRequestedResource: "foo/other/segment",
requestedSubresource: "other/segment",
expected: false,
},
{
name: "doesn't match on not star",
ruleResources: []string{"*something/other/segment"},
combinedRequestedResource: "foo/other/segment",
requestedSubresource: "other/segment",
expected: false,
},
{
name: "doesn't match on something else",
ruleResources: []string{"something/other/segment"},
combinedRequestedResource: "foo/other/segment",
requestedSubresource: "other/segment",
expected: false,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
rule := &rbac.PolicyRule{
Resources: tc.ruleResources,
}
actual := rbac.ResourceMatches(rule, tc.combinedRequestedResource, tc.requestedSubresource)
if tc.expected != actual {
t.Errorf("expected %v, got %v", tc.expected, actual)
}
})
}
}

View File

@ -48,7 +48,8 @@ type PolicyRule struct {
// APIGroups is the name of the APIGroup that contains the resources. // APIGroups is the name of the APIGroup that contains the resources.
// If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. // If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed.
APIGroups []string APIGroups []string
// Resources is a list of resources this rule applies to. ResourceAll represents all resources. // Resources is a list of resources this rule applies to. '*' represents all resources in the specified apiGroups.
// '*/foo' represents the subresource 'foo' for all resources in the specified apiGroups.
Resources []string Resources []string
// ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. // ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed.
ResourceNames []string ResourceNames []string

View File

@ -105,6 +105,31 @@ func hasAll(set, contains []string) bool {
return true return true
} }
func resourceCoversAll(setResources, coversResources []string) bool {
// if we have a star or an exact match on all resources, then we match
if has(setResources, rbac.ResourceAll) || hasAll(setResources, coversResources) {
return true
}
for _, path := range coversResources {
// if we have an exact match, then we match.
if has(setResources, path) {
continue
}
// if we're not a subresource, then we definitely don't match. fail.
if !strings.Contains(path, "/") {
return false
}
tokens := strings.SplitN(path, "/", 2)
resourceToCheck := "*/" + tokens[1]
if !has(setResources, resourceToCheck) {
return false
}
}
return true
}
func nonResourceURLsCoversAll(set, covers []string) bool { func nonResourceURLsCoversAll(set, covers []string) bool {
for _, path := range covers { for _, path := range covers {
covered := false covered := false
@ -133,7 +158,7 @@ func nonResourceURLCovers(ownerPath, subPath string) bool {
func ruleCovers(ownerRule, subRule rbac.PolicyRule) bool { func ruleCovers(ownerRule, subRule rbac.PolicyRule) bool {
verbMatches := has(ownerRule.Verbs, rbac.VerbAll) || hasAll(ownerRule.Verbs, subRule.Verbs) verbMatches := has(ownerRule.Verbs, rbac.VerbAll) || hasAll(ownerRule.Verbs, subRule.Verbs)
groupMatches := has(ownerRule.APIGroups, rbac.APIGroupAll) || hasAll(ownerRule.APIGroups, subRule.APIGroups) groupMatches := has(ownerRule.APIGroups, rbac.APIGroupAll) || hasAll(ownerRule.APIGroups, subRule.APIGroups)
resourceMatches := has(ownerRule.Resources, rbac.ResourceAll) || hasAll(ownerRule.Resources, subRule.Resources) resourceMatches := resourceCoversAll(ownerRule.Resources, subRule.Resources)
nonResourceURLMatches := nonResourceURLsCoversAll(ownerRule.NonResourceURLs, subRule.NonResourceURLs) nonResourceURLMatches := nonResourceURLsCoversAll(ownerRule.NonResourceURLs, subRule.NonResourceURLs)
resourceNameMatches := false resourceNameMatches := false

View File

@ -45,6 +45,20 @@ func TestCoversExactMatch(t *testing.T) {
}.test(t) }.test(t)
} }
func TestCoversSubresourceWildcard(t *testing.T) {
escalationTest{
ownerRules: []rbac.PolicyRule{
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*/scale"}},
},
servantRules: []rbac.PolicyRule{
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"foo/scale"}},
},
expectedCovered: true,
expectedUncoveredRules: []rbac.PolicyRule{},
}.test(t)
}
func TestCoversMultipleRulesCoveringSingleRule(t *testing.T) { func TestCoversMultipleRulesCoveringSingleRule(t *testing.T) {
escalationTest{ escalationTest{
ownerRules: []rbac.PolicyRule{ ownerRules: []rbac.PolicyRule{

View File

@ -156,10 +156,7 @@ func buildControllerRoles() ([]rbac.ClusterRole, []rbac.ClusterRoleBinding) {
Rules: []rbac.PolicyRule{ Rules: []rbac.PolicyRule{
rbac.NewRule("get", "list", "watch").Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(), rbac.NewRule("get", "list", "watch").Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(),
rbac.NewRule("update").Groups(autoscalingGroup).Resources("horizontalpodautoscalers/status").RuleOrDie(), rbac.NewRule("update").Groups(autoscalingGroup).Resources("horizontalpodautoscalers/status").RuleOrDie(),
rbac.NewRule("get", "update").Groups(legacyGroup).Resources("replicationcontrollers/scale").RuleOrDie(), rbac.NewRule("get", "update").Groups("*").Resources("*/scale").RuleOrDie(),
// TODO this should be removable when the HPA contoller is fixed
rbac.NewRule("get", "update").Groups(extensionsGroup).Resources("replicationcontrollers/scale").RuleOrDie(),
rbac.NewRule("get", "update").Groups(extensionsGroup, appsGroup).Resources("deployments/scale", "replicasets/scale").RuleOrDie(),
rbac.NewRule("list").Groups(legacyGroup).Resources("pods").RuleOrDie(), rbac.NewRule("list").Groups(legacyGroup).Resources("pods").RuleOrDie(),
// TODO: restrict this to the appropriate namespace // TODO: restrict this to the appropriate namespace
rbac.NewRule("get").Groups(legacyGroup).Resources("services/proxy").Names("https:heapster:", "http:heapster:").RuleOrDie(), rbac.NewRule("get").Groups(legacyGroup).Resources("services/proxy").Names("https:heapster:", "http:heapster:").RuleOrDie(),

View File

@ -445,25 +445,9 @@ items:
verbs: verbs:
- update - update
- apiGroups: - apiGroups:
- "" - '*'
resources: resources:
- replicationcontrollers/scale - '*/scale'
verbs:
- get
- update
- apiGroups:
- extensions
resources:
- replicationcontrollers/scale
verbs:
- get
- update
- apiGroups:
- apps
- extensions
resources:
- deployments/scale
- replicasets/scale
verbs: verbs:
- get - get
- update - update

View File

@ -174,14 +174,14 @@ func RulesAllow(requestAttributes authorizer.Attributes, rules ...rbac.PolicyRul
func RuleAllows(requestAttributes authorizer.Attributes, rule *rbac.PolicyRule) bool { func RuleAllows(requestAttributes authorizer.Attributes, rule *rbac.PolicyRule) bool {
if requestAttributes.IsResourceRequest() { if requestAttributes.IsResourceRequest() {
resource := requestAttributes.GetResource() combinedResource := requestAttributes.GetResource()
if len(requestAttributes.GetSubresource()) > 0 { if len(requestAttributes.GetSubresource()) > 0 {
resource = requestAttributes.GetResource() + "/" + requestAttributes.GetSubresource() combinedResource = requestAttributes.GetResource() + "/" + requestAttributes.GetSubresource()
} }
return rbac.VerbMatches(rule, requestAttributes.GetVerb()) && return rbac.VerbMatches(rule, requestAttributes.GetVerb()) &&
rbac.APIGroupMatches(rule, requestAttributes.GetAPIGroup()) && rbac.APIGroupMatches(rule, requestAttributes.GetAPIGroup()) &&
rbac.ResourceMatches(rule, resource) && rbac.ResourceMatches(rule, combinedResource, requestAttributes.GetSubresource()) &&
rbac.ResourceNameMatches(rule, requestAttributes.GetName()) rbac.ResourceNameMatches(rule, requestAttributes.GetName())
} }

View File

@ -224,13 +224,19 @@ func TestAuthorizer(t *testing.T) {
{ {
// test subresource resolution // test subresource resolution
clusterRoles: []*rbac.ClusterRole{ clusterRoles: []*rbac.ClusterRole{
newClusterRole("admin", newRule("*", "*", "pods/status", "*")), newClusterRole("admin",
newRule("*", "*", "pods/status", "*"),
newRule("*", "*", "*/scale", "*"),
),
}, },
roleBindings: []*rbac.RoleBinding{ roleBindings: []*rbac.RoleBinding{
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"), newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
}, },
shouldPass: []authorizer.Attributes{ shouldPass: []authorizer.Attributes{
&defaultAttributes{"admin", "", "get", "pods", "status", "ns1", ""}, &defaultAttributes{"admin", "", "get", "pods", "status", "ns1", ""},
&defaultAttributes{"admin", "", "get", "pods", "scale", "ns1", ""},
&defaultAttributes{"admin", "", "get", "deployments", "scale", "ns1", ""},
&defaultAttributes{"admin", "", "get", "anything", "scale", "ns1", ""},
}, },
shouldFail: []authorizer.Attributes{ shouldFail: []authorizer.Attributes{
&defaultAttributes{"admin", "", "get", "pods", "", "ns1", ""}, &defaultAttributes{"admin", "", "get", "pods", "", "ns1", ""},

View File

@ -121,7 +121,8 @@ message ResourceRule {
// +optional // +optional
repeated string apiGroups = 2; repeated string apiGroups = 2;
// Resources is a list of resources this rule applies to. ResourceAll represents all resources. "*" means all. // Resources is a list of resources this rule applies to. "*" means all in the specified apiGroups.
// "*/foo" represents the subresource 'foo' for all resources in the specified apiGroups.
// +optional // +optional
repeated string resources = 3; repeated string resources = 3;

View File

@ -241,7 +241,8 @@ type ResourceRule struct {
// the enumerated resources in any API group will be allowed. "*" means all. // the enumerated resources in any API group will be allowed. "*" means all.
// +optional // +optional
APIGroups []string `json:"apiGroups,omitempty" protobuf:"bytes,2,rep,name=apiGroups"` APIGroups []string `json:"apiGroups,omitempty" protobuf:"bytes,2,rep,name=apiGroups"`
// Resources is a list of resources this rule applies to. ResourceAll represents all resources. "*" means all. // Resources is a list of resources this rule applies to. "*" means all in the specified apiGroups.
// "*/foo" represents the subresource 'foo' for all resources in the specified apiGroups.
// +optional // +optional
Resources []string `json:"resources,omitempty" protobuf:"bytes,3,rep,name=resources"` Resources []string `json:"resources,omitempty" protobuf:"bytes,3,rep,name=resources"`
// ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. "*" means all. // ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. "*" means all.

View File

@ -76,7 +76,7 @@ var map_ResourceRule = map[string]string{
"": "ResourceRule is the list of actions the subject is allowed to perform on resources. The list ordering isn't significant, may contain duplicates, and possibly be incomplete.", "": "ResourceRule is the list of actions the subject is allowed to perform on resources. The list ordering isn't significant, may contain duplicates, and possibly be incomplete.",
"verbs": "Verb is a list of kubernetes resource API verbs, like: get, list, watch, create, update, delete, proxy. \"*\" means all.", "verbs": "Verb is a list of kubernetes resource API verbs, like: get, list, watch, create, update, delete, proxy. \"*\" means all.",
"apiGroups": "APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. \"*\" means all.", "apiGroups": "APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. \"*\" means all.",
"resources": "Resources is a list of resources this rule applies to. ResourceAll represents all resources. \"*\" means all.", "resources": "Resources is a list of resources this rule applies to. \"*\" means all in the specified apiGroups.\n \"*/foo\" represents the subresource 'foo' for all resources in the specified apiGroups.",
"resourceNames": "ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. \"*\" means all.", "resourceNames": "ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. \"*\" means all.",
} }

View File

@ -121,7 +121,8 @@ message ResourceRule {
// +optional // +optional
repeated string apiGroups = 2; repeated string apiGroups = 2;
// Resources is a list of resources this rule applies to. ResourceAll represents all resources. "*" means all. // Resources is a list of resources this rule applies to. "*" means all in the specified apiGroups.
// "*/foo" represents the subresource 'foo' for all resources in the specified apiGroups.
// +optional // +optional
repeated string resources = 3; repeated string resources = 3;

View File

@ -241,7 +241,8 @@ type ResourceRule struct {
// the enumerated resources in any API group will be allowed. "*" means all. // the enumerated resources in any API group will be allowed. "*" means all.
// +optional // +optional
APIGroups []string `json:"apiGroups,omitempty" protobuf:"bytes,2,rep,name=apiGroups"` APIGroups []string `json:"apiGroups,omitempty" protobuf:"bytes,2,rep,name=apiGroups"`
// Resources is a list of resources this rule applies to. ResourceAll represents all resources. "*" means all. // Resources is a list of resources this rule applies to. "*" means all in the specified apiGroups.
// "*/foo" represents the subresource 'foo' for all resources in the specified apiGroups.
// +optional // +optional
Resources []string `json:"resources,omitempty" protobuf:"bytes,3,rep,name=resources"` Resources []string `json:"resources,omitempty" protobuf:"bytes,3,rep,name=resources"`
// ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. "*" means all. // ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. "*" means all.

View File

@ -76,7 +76,7 @@ var map_ResourceRule = map[string]string{
"": "ResourceRule is the list of actions the subject is allowed to perform on resources. The list ordering isn't significant, may contain duplicates, and possibly be incomplete.", "": "ResourceRule is the list of actions the subject is allowed to perform on resources. The list ordering isn't significant, may contain duplicates, and possibly be incomplete.",
"verbs": "Verb is a list of kubernetes resource API verbs, like: get, list, watch, create, update, delete, proxy. \"*\" means all.", "verbs": "Verb is a list of kubernetes resource API verbs, like: get, list, watch, create, update, delete, proxy. \"*\" means all.",
"apiGroups": "APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. \"*\" means all.", "apiGroups": "APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed. \"*\" means all.",
"resources": "Resources is a list of resources this rule applies to. ResourceAll represents all resources. \"*\" means all.", "resources": "Resources is a list of resources this rule applies to. \"*\" means all in the specified apiGroups.\n \"*/foo\" represents the subresource 'foo' for all resources in the specified apiGroups.",
"resourceNames": "ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. \"*\" means all.", "resourceNames": "ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. \"*\" means all.",
} }

View File

@ -85,7 +85,8 @@ message PolicyRule {
// +optional // +optional
repeated string apiGroups = 2; repeated string apiGroups = 2;
// Resources is a list of resources this rule applies to. ResourceAll represents all resources. // Resources is a list of resources this rule applies to. '*' represents all resources in the specified apiGroups.
// '*/foo' represents the subresource 'foo' for all resources in the specified apiGroups.
// +optional // +optional
repeated string resources = 3; repeated string resources = 3;

View File

@ -54,7 +54,8 @@ type PolicyRule struct {
// the enumerated resources in any API group will be allowed. // the enumerated resources in any API group will be allowed.
// +optional // +optional
APIGroups []string `json:"apiGroups,omitempty" protobuf:"bytes,2,rep,name=apiGroups"` APIGroups []string `json:"apiGroups,omitempty" protobuf:"bytes,2,rep,name=apiGroups"`
// Resources is a list of resources this rule applies to. ResourceAll represents all resources. // Resources is a list of resources this rule applies to. '*' represents all resources in the specified apiGroups.
// '*/foo' represents the subresource 'foo' for all resources in the specified apiGroups.
// +optional // +optional
Resources []string `json:"resources,omitempty" protobuf:"bytes,3,rep,name=resources"` Resources []string `json:"resources,omitempty" protobuf:"bytes,3,rep,name=resources"`
// ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed. // ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed.

View File

@ -72,7 +72,7 @@ var map_PolicyRule = map[string]string{
"": "PolicyRule holds information that describes a policy rule, but does not contain information about who the rule applies to or which namespace the rule applies to.", "": "PolicyRule holds information that describes a policy rule, but does not contain information about who the rule applies to or which namespace the rule applies to.",
"verbs": "Verbs is a list of Verbs that apply to ALL the ResourceKinds and AttributeRestrictions contained in this rule. VerbAll represents all kinds.", "verbs": "Verbs is a list of Verbs that apply to ALL the ResourceKinds and AttributeRestrictions contained in this rule. VerbAll represents all kinds.",
"apiGroups": "APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed.", "apiGroups": "APIGroups is the name of the APIGroup that contains the resources. If multiple API groups are specified, any action requested against one of the enumerated resources in any API group will be allowed.",
"resources": "Resources is a list of resources this rule applies to. ResourceAll represents all resources.", "resources": "Resources is a list of resources this rule applies to. '*' represents all resources in the specified apiGroups. '*/foo' represents the subresource 'foo' for all resources in the specified apiGroups.",
"resourceNames": "ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed.", "resourceNames": "ResourceNames is an optional white list of names that the rule applies to. An empty set means that everything is allowed.",
"nonResourceURLs": "NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding. Rules can either apply to API resources (such as \"pods\" or \"secrets\") or non-resource URL paths (such as \"/api\"), but not both.", "nonResourceURLs": "NonResourceURLs is a set of partial urls that a user should have access to. *s are allowed, but only as the full, final step in the path Since non-resource URLs are not namespaced, this field is only applicable for ClusterRoles referenced from a ClusterRoleBinding. Rules can either apply to API resources (such as \"pods\" or \"secrets\") or non-resource URL paths (such as \"/api\"), but not both.",
} }