1
16
17 package rbac
18
19 import (
20 rbacv1 "k8s.io/api/rbac/v1"
21 "k8s.io/apimachinery/pkg/util/sets"
22 "reflect"
23 "strings"
24 )
25
26 type simpleResource struct {
27 Group string
28 Resource string
29 ResourceNameExist bool
30 ResourceName string
31 }
32
33
34
35 func CompactRules(rules []rbacv1.PolicyRule) ([]rbacv1.PolicyRule, error) {
36 compacted := make([]rbacv1.PolicyRule, 0, len(rules))
37
38 simpleRules := map[simpleResource]*rbacv1.PolicyRule{}
39 for _, rule := range rules {
40 if resource, isSimple := isSimpleResourceRule(&rule); isSimple {
41 if existingRule, ok := simpleRules[resource]; ok {
42
43 if existingRule.Verbs == nil {
44 existingRule.Verbs = []string{}
45 }
46 existingVerbs := sets.NewString(existingRule.Verbs...)
47 for _, verb := range rule.Verbs {
48 if !existingVerbs.Has(verb) {
49 existingRule.Verbs = append(existingRule.Verbs, verb)
50 }
51 }
52
53 } else {
54
55 simpleRules[resource] = rule.DeepCopy()
56 }
57 } else {
58 compacted = append(compacted, rule)
59 }
60 }
61
62
63 for _, simpleRule := range simpleRules {
64 compacted = append(compacted, *simpleRule)
65 }
66
67 return compacted, nil
68 }
69
70
71 func isSimpleResourceRule(rule *rbacv1.PolicyRule) (simpleResource, bool) {
72 resource := simpleResource{}
73
74
75 if len(rule.ResourceNames) > 1 || len(rule.NonResourceURLs) > 0 {
76 return resource, false
77 }
78
79 if len(rule.APIGroups) != 1 || len(rule.Resources) != 1 {
80 return resource, false
81 }
82
83
84 simpleRule := &rbacv1.PolicyRule{APIGroups: rule.APIGroups, Resources: rule.Resources, Verbs: rule.Verbs, ResourceNames: rule.ResourceNames}
85 if !reflect.DeepEqual(simpleRule, rule) {
86 return resource, false
87 }
88
89 if len(rule.ResourceNames) == 0 {
90 resource = simpleResource{Group: rule.APIGroups[0], Resource: rule.Resources[0], ResourceNameExist: false}
91 } else {
92 resource = simpleResource{Group: rule.APIGroups[0], Resource: rule.Resources[0], ResourceNameExist: true, ResourceName: rule.ResourceNames[0]}
93 }
94
95 return resource, true
96 }
97
98
99
100 func BreakdownRule(rule rbacv1.PolicyRule) []rbacv1.PolicyRule {
101 subrules := []rbacv1.PolicyRule{}
102 for _, group := range rule.APIGroups {
103 for _, resource := range rule.Resources {
104 for _, verb := range rule.Verbs {
105 if len(rule.ResourceNames) > 0 {
106 for _, resourceName := range rule.ResourceNames {
107 subrules = append(subrules, rbacv1.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}, ResourceNames: []string{resourceName}})
108 }
109
110 } else {
111 subrules = append(subrules, rbacv1.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}})
112 }
113
114 }
115 }
116 }
117
118
119 for _, nonResourceURL := range rule.NonResourceURLs {
120 for _, verb := range rule.Verbs {
121 subrules = append(subrules, rbacv1.PolicyRule{NonResourceURLs: []string{nonResourceURL}, Verbs: []string{verb}})
122 }
123 }
124
125 return subrules
126 }
127
128
129 type SortableRuleSlice []rbacv1.PolicyRule
130
131 func (s SortableRuleSlice) Len() int { return len(s) }
132 func (s SortableRuleSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
133 func (s SortableRuleSlice) Less(i, j int) bool {
134 return strings.Compare(s[i].String(), s[j].String()) < 0
135 }
136
View as plain text