k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/apis/rbac/v1/evaluation_helpers.go (about) 1 /* 2 Copyright 2018 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package v1 18 19 import ( 20 "fmt" 21 "strings" 22 23 rbacv1 "k8s.io/api/rbac/v1" 24 ) 25 26 func VerbMatches(rule *rbacv1.PolicyRule, requestedVerb string) bool { 27 for _, ruleVerb := range rule.Verbs { 28 if ruleVerb == rbacv1.VerbAll { 29 return true 30 } 31 if ruleVerb == requestedVerb { 32 return true 33 } 34 } 35 36 return false 37 } 38 39 func APIGroupMatches(rule *rbacv1.PolicyRule, requestedGroup string) bool { 40 for _, ruleGroup := range rule.APIGroups { 41 if ruleGroup == rbacv1.APIGroupAll { 42 return true 43 } 44 if ruleGroup == requestedGroup { 45 return true 46 } 47 } 48 49 return false 50 } 51 52 func ResourceMatches(rule *rbacv1.PolicyRule, combinedRequestedResource, requestedSubresource string) bool { 53 for _, ruleResource := range rule.Resources { 54 // if everything is allowed, we match 55 if ruleResource == rbacv1.ResourceAll { 56 return true 57 } 58 // if we have an exact match, we match 59 if ruleResource == combinedRequestedResource { 60 return true 61 } 62 63 // We can also match a */subresource. 64 // if there isn't a subresource, then continue 65 if len(requestedSubresource) == 0 { 66 continue 67 } 68 // if the rule isn't in the format */subresource, then we don't match, continue 69 if len(ruleResource) == len(requestedSubresource)+2 && 70 strings.HasPrefix(ruleResource, "*/") && 71 strings.HasSuffix(ruleResource, requestedSubresource) { 72 return true 73 74 } 75 } 76 77 return false 78 } 79 80 func ResourceNameMatches(rule *rbacv1.PolicyRule, requestedName string) bool { 81 if len(rule.ResourceNames) == 0 { 82 return true 83 } 84 85 for _, ruleName := range rule.ResourceNames { 86 if ruleName == requestedName { 87 return true 88 } 89 } 90 91 return false 92 } 93 94 func NonResourceURLMatches(rule *rbacv1.PolicyRule, requestedURL string) bool { 95 for _, ruleURL := range rule.NonResourceURLs { 96 if ruleURL == rbacv1.NonResourceAll { 97 return true 98 } 99 if ruleURL == requestedURL { 100 return true 101 } 102 if strings.HasSuffix(ruleURL, "*") && strings.HasPrefix(requestedURL, strings.TrimRight(ruleURL, "*")) { 103 return true 104 } 105 } 106 107 return false 108 } 109 110 // CompactString exposes a compact string representation for use in escalation error messages 111 func CompactString(r rbacv1.PolicyRule) string { 112 formatStringParts := []string{} 113 formatArgs := []interface{}{} 114 if len(r.APIGroups) > 0 { 115 formatStringParts = append(formatStringParts, "APIGroups:%q") 116 formatArgs = append(formatArgs, r.APIGroups) 117 } 118 if len(r.Resources) > 0 { 119 formatStringParts = append(formatStringParts, "Resources:%q") 120 formatArgs = append(formatArgs, r.Resources) 121 } 122 if len(r.NonResourceURLs) > 0 { 123 formatStringParts = append(formatStringParts, "NonResourceURLs:%q") 124 formatArgs = append(formatArgs, r.NonResourceURLs) 125 } 126 if len(r.ResourceNames) > 0 { 127 formatStringParts = append(formatStringParts, "ResourceNames:%q") 128 formatArgs = append(formatArgs, r.ResourceNames) 129 } 130 if len(r.Verbs) > 0 { 131 formatStringParts = append(formatStringParts, "Verbs:%q") 132 formatArgs = append(formatArgs, r.Verbs) 133 } 134 formatString := "{" + strings.Join(formatStringParts, ", ") + "}" 135 return fmt.Sprintf(formatString, formatArgs...) 136 } 137 138 type SortableRuleSlice []rbacv1.PolicyRule 139 140 func (s SortableRuleSlice) Len() int { return len(s) } 141 func (s SortableRuleSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 142 func (s SortableRuleSlice) Less(i, j int) bool { 143 return strings.Compare(s[i].String(), s[j].String()) < 0 144 }