k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/pkg/registry/admissionregistration/validatingadmissionpolicybinding/authz_test.go (about) 1 /* 2 Copyright 2022 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 validatingadmissionpolicybinding 18 19 import ( 20 "context" 21 "testing" 22 23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 "k8s.io/apimachinery/pkg/runtime/schema" 25 "k8s.io/apiserver/pkg/authentication/user" 26 "k8s.io/apiserver/pkg/authorization/authorizer" 27 "k8s.io/apiserver/pkg/endpoints/request" 28 "k8s.io/kubernetes/pkg/apis/admissionregistration" 29 "k8s.io/kubernetes/pkg/registry/admissionregistration/resolver" 30 ) 31 32 func TestAuthorization(t *testing.T) { 33 for _, tc := range []struct { 34 name string 35 userInfo user.Info 36 auth AuthFunc 37 policyGetter PolicyGetterFunc 38 resourceResolver resolver.ResourceResolverFunc 39 expectErr bool 40 }{ 41 { 42 name: "superuser", 43 userInfo: &user.DefaultInfo{Groups: []string{user.SystemPrivilegedGroup}}, 44 expectErr: false, // success despite always-denying authorizer 45 auth: func(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) { 46 return authorizer.DecisionDeny, "", nil 47 }, 48 }, 49 { 50 name: "authorized", 51 userInfo: &user.DefaultInfo{Groups: []string{user.AllAuthenticated}}, 52 auth: func(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) { 53 if a.GetResource() == "configmaps" { 54 return authorizer.DecisionAllow, "", nil 55 } 56 return authorizer.DecisionDeny, "", nil 57 }, 58 policyGetter: func(ctx context.Context, name string) (*admissionregistration.ValidatingAdmissionPolicy, error) { 59 return &admissionregistration.ValidatingAdmissionPolicy{ 60 ObjectMeta: metav1.ObjectMeta{Name: "replicalimit-policy.example.com"}, 61 Spec: admissionregistration.ValidatingAdmissionPolicySpec{ 62 ParamKind: &admissionregistration.ParamKind{Kind: "ConfigMap", APIVersion: "v1"}, 63 }, 64 }, nil 65 }, 66 resourceResolver: func(gvk schema.GroupVersionKind) (schema.GroupVersionResource, error) { 67 return schema.GroupVersionResource{ 68 Group: "", 69 Version: "v1", 70 Resource: "configmaps", 71 }, nil 72 }, 73 expectErr: false, 74 }, 75 { 76 name: "denied", 77 userInfo: &user.DefaultInfo{Groups: []string{user.AllAuthenticated}}, 78 auth: func(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) { 79 if a.GetResource() == "configmaps" { 80 return authorizer.DecisionAllow, "", nil 81 } 82 return authorizer.DecisionDeny, "", nil 83 }, 84 policyGetter: func(ctx context.Context, name string) (*admissionregistration.ValidatingAdmissionPolicy, error) { 85 return &admissionregistration.ValidatingAdmissionPolicy{ 86 ObjectMeta: metav1.ObjectMeta{Name: "replicalimit-policy.example.com"}, 87 Spec: admissionregistration.ValidatingAdmissionPolicySpec{ 88 ParamKind: &admissionregistration.ParamKind{Kind: "Params", APIVersion: "foo.example.com/v1"}, 89 }, 90 }, nil 91 }, 92 resourceResolver: func(gvk schema.GroupVersionKind) (schema.GroupVersionResource, error) { 93 return schema.GroupVersionResource{ 94 Group: "foo.example.com", 95 Version: "v1", 96 Resource: "params", 97 }, nil 98 }, 99 expectErr: true, 100 }, 101 } { 102 t.Run(tc.name, func(t *testing.T) { 103 strategy := NewStrategy(tc.auth, tc.policyGetter, tc.resourceResolver) 104 t.Run("create", func(t *testing.T) { 105 ctx := request.WithUser(context.Background(), tc.userInfo) 106 for _, obj := range validPolicyBindings() { 107 errs := strategy.Validate(ctx, obj) 108 if len(errs) > 0 != tc.expectErr { 109 t.Errorf("expected error: %v but got error: %v", tc.expectErr, errs) 110 } 111 } 112 }) 113 t.Run("update", func(t *testing.T) { 114 ctx := request.WithUser(context.Background(), tc.userInfo) 115 for _, obj := range validPolicyBindings() { 116 objWithChangedParamRef := obj.DeepCopy() 117 if pr := objWithChangedParamRef.Spec.ParamRef; pr != nil { 118 if len(pr.Name) > 0 { 119 pr.Name = "changed" 120 } 121 122 if pr.Selector != nil { 123 pr.Selector = &metav1.LabelSelector{ 124 MatchLabels: map[string]string{ 125 "changed": "value", 126 }, 127 } 128 } 129 130 if len(pr.Namespace) > 0 { 131 pr.Namespace = "othernamespace" 132 } 133 134 if pr.ParameterNotFoundAction == nil || *pr.ParameterNotFoundAction == admissionregistration.AllowAction { 135 v := admissionregistration.DenyAction 136 pr.ParameterNotFoundAction = &v 137 } else { 138 v := admissionregistration.AllowAction 139 pr.ParameterNotFoundAction = &v 140 } 141 } 142 errs := strategy.ValidateUpdate(ctx, obj, objWithChangedParamRef) 143 if len(errs) > 0 != tc.expectErr { 144 t.Errorf("expected error: %v but got error: %v", tc.expectErr, errs) 145 } 146 } 147 }) 148 }) 149 } 150 } 151 152 type AuthFunc func(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) 153 154 func (f AuthFunc) Authorize(ctx context.Context, a authorizer.Attributes) (authorized authorizer.Decision, reason string, err error) { 155 return f(ctx, a) 156 } 157 158 type PolicyGetterFunc func(ctx context.Context, name string) (*admissionregistration.ValidatingAdmissionPolicy, error) 159 160 func (f PolicyGetterFunc) GetValidatingAdmissionPolicy(ctx context.Context, name string) (*admissionregistration.ValidatingAdmissionPolicy, error) { 161 return f(ctx, name) 162 }