k8s.io/kubernetes@v1.29.3/pkg/registry/rbac/escalation_check.go (about) 1 /* 2 Copyright 2016 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 rbac 18 19 import ( 20 "context" 21 "fmt" 22 23 "k8s.io/apimachinery/pkg/runtime/schema" 24 utilruntime "k8s.io/apimachinery/pkg/util/runtime" 25 "k8s.io/apiserver/pkg/authentication/user" 26 "k8s.io/apiserver/pkg/authorization/authorizer" 27 genericapirequest "k8s.io/apiserver/pkg/endpoints/request" 28 "k8s.io/kubernetes/pkg/apis/rbac" 29 ) 30 31 // EscalationAllowed checks if the user associated with the context is a superuser 32 func EscalationAllowed(ctx context.Context) bool { 33 u, ok := genericapirequest.UserFrom(ctx) 34 if !ok { 35 return false 36 } 37 38 // system:masters is special because the API server uses it for privileged loopback connections 39 // therefore we know that a member of system:masters can always do anything 40 for _, group := range u.GetGroups() { 41 if group == user.SystemPrivilegedGroup { 42 return true 43 } 44 } 45 46 return false 47 } 48 49 var roleResources = map[schema.GroupResource]bool{ 50 rbac.SchemeGroupVersion.WithResource("clusterroles").GroupResource(): true, 51 rbac.SchemeGroupVersion.WithResource("roles").GroupResource(): true, 52 } 53 54 // RoleEscalationAuthorized checks if the user associated with the context is explicitly authorized to escalate the role resource associated with the context 55 func RoleEscalationAuthorized(ctx context.Context, a authorizer.Authorizer) bool { 56 if a == nil { 57 return false 58 } 59 60 user, ok := genericapirequest.UserFrom(ctx) 61 if !ok { 62 return false 63 } 64 65 requestInfo, ok := genericapirequest.RequestInfoFrom(ctx) 66 if !ok { 67 return false 68 } 69 70 if !requestInfo.IsResourceRequest { 71 return false 72 } 73 74 requestResource := schema.GroupResource{Group: requestInfo.APIGroup, Resource: requestInfo.Resource} 75 if !roleResources[requestResource] { 76 return false 77 } 78 79 attrs := authorizer.AttributesRecord{ 80 User: user, 81 Verb: "escalate", 82 APIGroup: requestInfo.APIGroup, 83 APIVersion: "*", 84 Resource: requestInfo.Resource, 85 Name: requestInfo.Name, 86 Namespace: requestInfo.Namespace, 87 ResourceRequest: true, 88 } 89 90 decision, _, err := a.Authorize(ctx, attrs) 91 if err != nil { 92 utilruntime.HandleError(fmt.Errorf( 93 "error authorizing user %#v to escalate %#v named %q in namespace %q: %v", 94 user, requestResource, requestInfo.Name, requestInfo.Namespace, err, 95 )) 96 } 97 return decision == authorizer.DecisionAllow 98 } 99 100 // BindingAuthorized returns true if the user associated with the context is explicitly authorized to bind the specified roleRef 101 func BindingAuthorized(ctx context.Context, roleRef rbac.RoleRef, bindingNamespace string, a authorizer.Authorizer) bool { 102 if a == nil { 103 return false 104 } 105 106 user, ok := genericapirequest.UserFrom(ctx) 107 if !ok { 108 return false 109 } 110 111 attrs := authorizer.AttributesRecord{ 112 User: user, 113 Verb: "bind", 114 // check against the namespace where the binding is being created (or the empty namespace for clusterrolebindings). 115 // this allows delegation to bind particular clusterroles in rolebindings within particular namespaces, 116 // and to authorize binding a clusterrole across all namespaces in a clusterrolebinding. 117 Namespace: bindingNamespace, 118 ResourceRequest: true, 119 } 120 121 // This occurs after defaulting and conversion, so values pulled from the roleRef won't change 122 // Invalid APIGroup or Name values will fail validation 123 switch roleRef.Kind { 124 case "ClusterRole": 125 attrs.APIGroup = roleRef.APIGroup 126 attrs.APIVersion = "*" 127 attrs.Resource = "clusterroles" 128 attrs.Name = roleRef.Name 129 case "Role": 130 attrs.APIGroup = roleRef.APIGroup 131 attrs.APIVersion = "*" 132 attrs.Resource = "roles" 133 attrs.Name = roleRef.Name 134 default: 135 return false 136 } 137 138 decision, _, err := a.Authorize(ctx, attrs) 139 if err != nil { 140 utilruntime.HandleError(fmt.Errorf( 141 "error authorizing user %#v to bind %#v in namespace %s: %v", 142 user, roleRef, bindingNamespace, err, 143 )) 144 } 145 return decision == authorizer.DecisionAllow 146 }