...

Source file src/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_compact.go

Documentation: k8s.io/kubernetes/pkg/registry/rbac/validation

     1  /*
     2  Copyright 2017 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 validation
    18  
    19  import (
    20  	"reflect"
    21  
    22  	rbacv1 "k8s.io/api/rbac/v1"
    23  )
    24  
    25  type simpleResource struct {
    26  	Group             string
    27  	Resource          string
    28  	ResourceNameExist bool
    29  	ResourceName      string
    30  }
    31  
    32  // CompactRules combines rules that contain a single APIGroup/Resource, differ only by verb, and contain no other attributes.
    33  // this is a fast check, and works well with the decomposed "missing rules" list from a Covers check.
    34  func CompactRules(rules []rbacv1.PolicyRule) ([]rbacv1.PolicyRule, error) {
    35  	compacted := make([]rbacv1.PolicyRule, 0, len(rules))
    36  
    37  	simpleRules := map[simpleResource]*rbacv1.PolicyRule{}
    38  	for _, rule := range rules {
    39  		if resource, isSimple := isSimpleResourceRule(&rule); isSimple {
    40  			if existingRule, ok := simpleRules[resource]; ok {
    41  				// Add the new verbs to the existing simple resource rule
    42  				if existingRule.Verbs == nil {
    43  					existingRule.Verbs = []string{}
    44  				}
    45  				existingRule.Verbs = append(existingRule.Verbs, rule.Verbs...)
    46  			} else {
    47  				// Copy the rule to accumulate matching simple resource rules into
    48  				simpleRules[resource] = rule.DeepCopy()
    49  			}
    50  		} else {
    51  			compacted = append(compacted, rule)
    52  		}
    53  	}
    54  
    55  	// Once we've consolidated the simple resource rules, add them to the compacted list
    56  	for _, simpleRule := range simpleRules {
    57  		compacted = append(compacted, *simpleRule)
    58  	}
    59  
    60  	return compacted, nil
    61  }
    62  
    63  // isSimpleResourceRule returns true if the given rule contains verbs, a single resource, a single API group, at most one Resource Name, and no other values
    64  func isSimpleResourceRule(rule *rbacv1.PolicyRule) (simpleResource, bool) {
    65  	resource := simpleResource{}
    66  
    67  	// If we have "complex" rule attributes, return early without allocations or expensive comparisons
    68  	if len(rule.ResourceNames) > 1 || len(rule.NonResourceURLs) > 0 {
    69  		return resource, false
    70  	}
    71  	// If we have multiple api groups or resources, return early
    72  	if len(rule.APIGroups) != 1 || len(rule.Resources) != 1 {
    73  		return resource, false
    74  	}
    75  
    76  	// Test if this rule only contains APIGroups/Resources/Verbs/ResourceNames
    77  	simpleRule := &rbacv1.PolicyRule{APIGroups: rule.APIGroups, Resources: rule.Resources, Verbs: rule.Verbs, ResourceNames: rule.ResourceNames}
    78  	if !reflect.DeepEqual(simpleRule, rule) {
    79  		return resource, false
    80  	}
    81  
    82  	if len(rule.ResourceNames) == 0 {
    83  		resource = simpleResource{Group: rule.APIGroups[0], Resource: rule.Resources[0], ResourceNameExist: false}
    84  	} else {
    85  		resource = simpleResource{Group: rule.APIGroups[0], Resource: rule.Resources[0], ResourceNameExist: true, ResourceName: rule.ResourceNames[0]}
    86  	}
    87  
    88  	return resource, true
    89  }
    90  

View as plain text