k8s.io/kubernetes@v1.29.3/pkg/registry/rbac/role/policybased/storage.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 policybased implements a standard storage for Role that prevents privilege escalation. 18 package policybased 19 20 import ( 21 "context" 22 23 "k8s.io/apimachinery/pkg/api/errors" 24 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 "k8s.io/apimachinery/pkg/runtime" 26 "k8s.io/apiserver/pkg/authorization/authorizer" 27 "k8s.io/apiserver/pkg/registry/rest" 28 kapihelper "k8s.io/kubernetes/pkg/apis/core/helper" 29 "k8s.io/kubernetes/pkg/apis/rbac" 30 rbacregistry "k8s.io/kubernetes/pkg/registry/rbac" 31 rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation" 32 ) 33 34 var groupResource = rbac.Resource("roles") 35 36 type Storage struct { 37 rest.StandardStorage 38 39 authorizer authorizer.Authorizer 40 41 ruleResolver rbacregistryvalidation.AuthorizationRuleResolver 42 } 43 44 func NewStorage(s rest.StandardStorage, authorizer authorizer.Authorizer, ruleResolver rbacregistryvalidation.AuthorizationRuleResolver) *Storage { 45 return &Storage{s, authorizer, ruleResolver} 46 } 47 48 // Destroy cleans up resources on shutdown. 49 func (r *Storage) Destroy() { 50 r.StandardStorage.Destroy() 51 } 52 53 func (r *Storage) NamespaceScoped() bool { 54 return true 55 } 56 57 func (r *Storage) StorageVersion() runtime.GroupVersioner { 58 svp, ok := r.StandardStorage.(rest.StorageVersionProvider) 59 if !ok { 60 return nil 61 } 62 return svp.StorageVersion() 63 } 64 65 var _ rest.StorageVersionProvider = &Storage{} 66 67 func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) { 68 if rbacregistry.EscalationAllowed(ctx) || rbacregistry.RoleEscalationAuthorized(ctx, s.authorizer) { 69 return s.StandardStorage.Create(ctx, obj, createValidation, options) 70 } 71 72 role := obj.(*rbac.Role) 73 rules := role.Rules 74 if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil { 75 return nil, errors.NewForbidden(groupResource, role.Name, err) 76 } 77 return s.StandardStorage.Create(ctx, obj, createValidation, options) 78 } 79 80 func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) { 81 if rbacregistry.EscalationAllowed(ctx) || rbacregistry.RoleEscalationAuthorized(ctx, s.authorizer) { 82 return s.StandardStorage.Update(ctx, name, obj, createValidation, updateValidation, forceAllowCreate, options) 83 } 84 85 nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx context.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) { 86 role := obj.(*rbac.Role) 87 88 // if we're only mutating fields needed for the GC to eventually delete this obj, return 89 if rbacregistry.IsOnlyMutatingGCFields(obj, oldObj, kapihelper.Semantic) { 90 return obj, nil 91 } 92 93 rules := role.Rules 94 if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil { 95 return nil, errors.NewForbidden(groupResource, role.Name, err) 96 } 97 return obj, nil 98 }) 99 100 return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation, forceAllowCreate, options) 101 } 102 103 var _ rest.SingularNameProvider = &Storage{} 104 105 func (s *Storage) GetSingularName() string { 106 snp, ok := s.StandardStorage.(rest.SingularNameProvider) 107 if !ok { 108 return "" 109 } 110 return snp.GetSingularName() 111 }