1
16
17
18 package policybased
19
20 import (
21 "context"
22
23 rbacv1 "k8s.io/api/rbac/v1"
24 "k8s.io/apimachinery/pkg/api/errors"
25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26 "k8s.io/apimachinery/pkg/runtime"
27 "k8s.io/apiserver/pkg/authorization/authorizer"
28 "k8s.io/apiserver/pkg/registry/rest"
29 kapihelper "k8s.io/kubernetes/pkg/apis/core/helper"
30 "k8s.io/kubernetes/pkg/apis/rbac"
31 rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
32 rbacregistry "k8s.io/kubernetes/pkg/registry/rbac"
33 rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
34 )
35
36 var groupResource = rbac.Resource("clusterrolebindings")
37
38 type Storage struct {
39 rest.StandardStorage
40
41 authorizer authorizer.Authorizer
42
43 ruleResolver rbacregistryvalidation.AuthorizationRuleResolver
44 }
45
46 func NewStorage(s rest.StandardStorage, authorizer authorizer.Authorizer, ruleResolver rbacregistryvalidation.AuthorizationRuleResolver) *Storage {
47 return &Storage{s, authorizer, ruleResolver}
48 }
49
50
51 func (r *Storage) Destroy() {
52 r.StandardStorage.Destroy()
53 }
54
55 func (r *Storage) NamespaceScoped() bool {
56 return false
57 }
58
59 func (r *Storage) StorageVersion() runtime.GroupVersioner {
60 svp, ok := r.StandardStorage.(rest.StorageVersionProvider)
61 if !ok {
62 return nil
63 }
64 return svp.StorageVersion()
65 }
66
67 var _ rest.StorageVersionProvider = &Storage{}
68
69 func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
70 if rbacregistry.EscalationAllowed(ctx) {
71 return s.StandardStorage.Create(ctx, obj, createValidation, options)
72 }
73
74 clusterRoleBinding := obj.(*rbac.ClusterRoleBinding)
75 if rbacregistry.BindingAuthorized(ctx, clusterRoleBinding.RoleRef, metav1.NamespaceNone, s.authorizer) {
76 return s.StandardStorage.Create(ctx, obj, createValidation, options)
77 }
78
79 v1RoleRef := rbacv1.RoleRef{}
80 err := rbacv1helpers.Convert_rbac_RoleRef_To_v1_RoleRef(&clusterRoleBinding.RoleRef, &v1RoleRef, nil)
81 if err != nil {
82 return nil, err
83 }
84 rules, err := s.ruleResolver.GetRoleReferenceRules(v1RoleRef, metav1.NamespaceNone)
85 if err != nil {
86 return nil, err
87 }
88 if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
89 return nil, errors.NewForbidden(groupResource, clusterRoleBinding.Name, err)
90 }
91 return s.StandardStorage.Create(ctx, obj, createValidation, options)
92 }
93
94 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) {
95 if rbacregistry.EscalationAllowed(ctx) {
96 return s.StandardStorage.Update(ctx, name, obj, createValidation, updateValidation, forceAllowCreate, options)
97 }
98
99 nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx context.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) {
100 clusterRoleBinding := obj.(*rbac.ClusterRoleBinding)
101
102
103 if rbacregistry.IsOnlyMutatingGCFields(obj, oldObj, kapihelper.Semantic) {
104 return obj, nil
105 }
106
107
108 if rbacregistry.BindingAuthorized(ctx, clusterRoleBinding.RoleRef, metav1.NamespaceNone, s.authorizer) {
109 return obj, nil
110 }
111
112
113 v1RoleRef := rbacv1.RoleRef{}
114 err := rbacv1helpers.Convert_rbac_RoleRef_To_v1_RoleRef(&clusterRoleBinding.RoleRef, &v1RoleRef, nil)
115 if err != nil {
116 return nil, err
117 }
118 rules, err := s.ruleResolver.GetRoleReferenceRules(v1RoleRef, metav1.NamespaceNone)
119 if err != nil {
120 return nil, err
121 }
122 if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
123 return nil, errors.NewForbidden(groupResource, clusterRoleBinding.Name, err)
124 }
125 return obj, nil
126 })
127
128 return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation, forceAllowCreate, options)
129 }
130
131 var _ rest.SingularNameProvider = &Storage{}
132
133 func (s *Storage) GetSingularName() string {
134 snp, ok := s.StandardStorage.(rest.SingularNameProvider)
135 if !ok {
136 return ""
137 }
138 return snp.GetSingularName()
139 }
140
View as plain text