k8s.io/apiserver@v0.31.1/pkg/authorization/union/union.go (about)

     1  /*
     2  Copyright 2014 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 union implements an authorizer that combines multiple subauthorizer.
    18  // The union authorizer iterates over each subauthorizer and returns the first
    19  // decision that is either an Allow decision or a Deny decision. If a
    20  // subauthorizer returns a NoOpinion, then the union authorizer moves onto the
    21  // next authorizer or, if the subauthorizer was the last authorizer, returns
    22  // NoOpinion as the aggregate decision. I.e. union authorizer creates an
    23  // aggregate decision and supports short-circuit allows and denies from
    24  // subauthorizers.
    25  package union
    26  
    27  import (
    28  	"context"
    29  	"strings"
    30  
    31  	utilerrors "k8s.io/apimachinery/pkg/util/errors"
    32  	"k8s.io/apiserver/pkg/authentication/user"
    33  	"k8s.io/apiserver/pkg/authorization/authorizer"
    34  )
    35  
    36  // unionAuthzHandler authorizer against a chain of authorizer.Authorizer
    37  type unionAuthzHandler []authorizer.Authorizer
    38  
    39  // New returns an authorizer that authorizes against a chain of authorizer.Authorizer objects
    40  func New(authorizationHandlers ...authorizer.Authorizer) authorizer.Authorizer {
    41  	return unionAuthzHandler(authorizationHandlers)
    42  }
    43  
    44  // Authorizes against a chain of authorizer.Authorizer objects and returns nil if successful and returns error if unsuccessful
    45  func (authzHandler unionAuthzHandler) Authorize(ctx context.Context, a authorizer.Attributes) (authorizer.Decision, string, error) {
    46  	var (
    47  		errlist    []error
    48  		reasonlist []string
    49  	)
    50  
    51  	for _, currAuthzHandler := range authzHandler {
    52  		decision, reason, err := currAuthzHandler.Authorize(ctx, a)
    53  
    54  		if err != nil {
    55  			errlist = append(errlist, err)
    56  		}
    57  		if len(reason) != 0 {
    58  			reasonlist = append(reasonlist, reason)
    59  		}
    60  		switch decision {
    61  		case authorizer.DecisionAllow, authorizer.DecisionDeny:
    62  			return decision, reason, err
    63  		case authorizer.DecisionNoOpinion:
    64  			// continue to the next authorizer
    65  		}
    66  	}
    67  
    68  	return authorizer.DecisionNoOpinion, strings.Join(reasonlist, "\n"), utilerrors.NewAggregate(errlist)
    69  }
    70  
    71  // unionAuthzRulesHandler authorizer against a chain of authorizer.RuleResolver
    72  type unionAuthzRulesHandler []authorizer.RuleResolver
    73  
    74  // NewRuleResolvers returns an authorizer that authorizes against a chain of authorizer.Authorizer objects
    75  func NewRuleResolvers(authorizationHandlers ...authorizer.RuleResolver) authorizer.RuleResolver {
    76  	return unionAuthzRulesHandler(authorizationHandlers)
    77  }
    78  
    79  // RulesFor against a chain of authorizer.RuleResolver objects and returns nil if successful and returns error if unsuccessful
    80  func (authzHandler unionAuthzRulesHandler) RulesFor(user user.Info, namespace string) ([]authorizer.ResourceRuleInfo, []authorizer.NonResourceRuleInfo, bool, error) {
    81  	var (
    82  		errList              []error
    83  		resourceRulesList    []authorizer.ResourceRuleInfo
    84  		nonResourceRulesList []authorizer.NonResourceRuleInfo
    85  	)
    86  	incompleteStatus := false
    87  
    88  	for _, currAuthzHandler := range authzHandler {
    89  		resourceRules, nonResourceRules, incomplete, err := currAuthzHandler.RulesFor(user, namespace)
    90  
    91  		if incomplete {
    92  			incompleteStatus = true
    93  		}
    94  		if err != nil {
    95  			errList = append(errList, err)
    96  		}
    97  		if len(resourceRules) > 0 {
    98  			resourceRulesList = append(resourceRulesList, resourceRules...)
    99  		}
   100  		if len(nonResourceRules) > 0 {
   101  			nonResourceRulesList = append(nonResourceRulesList, nonResourceRules...)
   102  		}
   103  	}
   104  
   105  	return resourceRulesList, nonResourceRulesList, incompleteStatus, utilerrors.NewAggregate(errList)
   106  }