mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-11-24 22:28:43 +00:00
Switch to pointer to policy rule, visit and short circuit during authorization
This commit is contained in:
@@ -24,6 +24,7 @@ import (
|
||||
|
||||
"bytes"
|
||||
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
@@ -36,15 +37,41 @@ type RequestToRuleMapper interface {
|
||||
// supplied, you do not have to fail the request. If you cannot, you should indicate the error along
|
||||
// with your denial.
|
||||
RulesFor(subject user.Info, namespace string) ([]rbac.PolicyRule, error)
|
||||
|
||||
// VisitRulesFor invokes visitor() with each rule that applies to a given user in a given namespace,
|
||||
// and each error encountered resolving those rules. Rule may be nil if err is non-nil.
|
||||
// If visitor() returns false, visiting is short-circuited.
|
||||
VisitRulesFor(user user.Info, namespace string, visitor func(rule *rbac.PolicyRule, err error) bool)
|
||||
}
|
||||
|
||||
type RBACAuthorizer struct {
|
||||
authorizationRuleResolver RequestToRuleMapper
|
||||
}
|
||||
|
||||
// authorizingVisitor short-circuits once allowed, and collects any resolution errors encountered
|
||||
type authorizingVisitor struct {
|
||||
requestAttributes authorizer.Attributes
|
||||
|
||||
allowed bool
|
||||
errors []error
|
||||
}
|
||||
|
||||
func (v *authorizingVisitor) visit(rule *rbac.PolicyRule, err error) bool {
|
||||
if rule != nil && RuleAllows(v.requestAttributes, rule) {
|
||||
v.allowed = true
|
||||
return false
|
||||
}
|
||||
if err != nil {
|
||||
v.errors = append(v.errors, err)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *RBACAuthorizer) Authorize(requestAttributes authorizer.Attributes) (bool, string, error) {
|
||||
rules, ruleResolutionError := r.authorizationRuleResolver.RulesFor(requestAttributes.GetUser(), requestAttributes.GetNamespace())
|
||||
if RulesAllow(requestAttributes, rules...) {
|
||||
ruleCheckingVisitor := &authorizingVisitor{requestAttributes: requestAttributes}
|
||||
|
||||
r.authorizationRuleResolver.VisitRulesFor(requestAttributes.GetUser(), requestAttributes.GetNamespace(), ruleCheckingVisitor.visit)
|
||||
if ruleCheckingVisitor.allowed {
|
||||
return true, "", nil
|
||||
}
|
||||
|
||||
@@ -88,8 +115,8 @@ func (r *RBACAuthorizer) Authorize(requestAttributes authorizer.Attributes) (boo
|
||||
}
|
||||
|
||||
reason := ""
|
||||
if ruleResolutionError != nil {
|
||||
reason = fmt.Sprintf("%v", ruleResolutionError)
|
||||
if len(ruleCheckingVisitor.errors) > 0 {
|
||||
reason = fmt.Sprintf("%v", utilerrors.NewAggregate(ruleCheckingVisitor.errors))
|
||||
}
|
||||
return false, reason, nil
|
||||
}
|
||||
@@ -104,8 +131,8 @@ func New(roles rbacregistryvalidation.RoleGetter, roleBindings rbacregistryvalid
|
||||
}
|
||||
|
||||
func RulesAllow(requestAttributes authorizer.Attributes, rules ...rbac.PolicyRule) bool {
|
||||
for _, rule := range rules {
|
||||
if RuleAllows(requestAttributes, rule) {
|
||||
for i := range rules {
|
||||
if RuleAllows(requestAttributes, &rules[i]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -113,7 +140,7 @@ func RulesAllow(requestAttributes authorizer.Attributes, rules ...rbac.PolicyRul
|
||||
return false
|
||||
}
|
||||
|
||||
func RuleAllows(requestAttributes authorizer.Attributes, rule rbac.PolicyRule) bool {
|
||||
func RuleAllows(requestAttributes authorizer.Attributes, rule *rbac.PolicyRule) bool {
|
||||
if requestAttributes.IsResourceRequest() {
|
||||
resource := requestAttributes.GetResource()
|
||||
if len(requestAttributes.GetSubresource()) > 0 {
|
||||
|
||||
Reference in New Issue
Block a user