Skip to content

Commit 8cce037

Browse files
committed
Handle MutatingAdmissionPolicyBinding
1 parent bb52435 commit 8cce037

File tree

9 files changed

+136
-22
lines changed

9 files changed

+136
-22
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ vapTestSuites:
114114
expect: <allow|deny|skip|error>
115115
mapTestSuites:
116116
- policy: <name> # MutatingAdmissionPolicy's name
117+
binding: <name> # Optional: MutatingAdmissionPolicyBinding's name
117118
tests:
118119
- object:
119120
group: <group> # Optional

internal/tester/loader.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,20 @@ import (
3737
)
3838

3939
type ResourceLoader struct {
40-
Vaps map[string]*v1.ValidatingAdmissionPolicy
41-
Maps map[string]*v1alpha1.MutatingAdmissionPolicy
42-
Resources map[NameWithGVK]*unstructured.Unstructured
43-
validator validator.Validator
40+
Vaps map[string]*v1.ValidatingAdmissionPolicy
41+
Maps map[string]*v1alpha1.MutatingAdmissionPolicy
42+
MapBindings map[string]*v1alpha1.MutatingAdmissionPolicyBinding
43+
Resources map[NameWithGVK]*unstructured.Unstructured
44+
validator validator.Validator
4445
}
4546

4647
func NewResourceLoader(validator validator.Validator) *ResourceLoader {
4748
return &ResourceLoader{
48-
Vaps: map[string]*v1.ValidatingAdmissionPolicy{},
49-
Maps: map[string]*v1alpha1.MutatingAdmissionPolicy{},
50-
Resources: map[NameWithGVK]*unstructured.Unstructured{},
51-
validator: validator,
49+
Vaps: map[string]*v1.ValidatingAdmissionPolicy{},
50+
Maps: map[string]*v1alpha1.MutatingAdmissionPolicy{},
51+
MapBindings: map[string]*v1alpha1.MutatingAdmissionPolicyBinding{},
52+
Resources: map[NameWithGVK]*unstructured.Unstructured{},
53+
validator: validator,
5254
}
5355
}
5456

@@ -111,6 +113,13 @@ func (r *ResourceLoader) LoadPolicies(paths []string) {
111113
// Ensure nil labelSelectors to be matching everything
112114
defaultingMAPPolicy(m)
113115
r.Maps[m.Name] = m
116+
case "MutatingAdmissionPolicyBinding":
117+
if gvk.Version != "v1alpha1" {
118+
slog.Warn("only v1alpha1 MutatingAdmissionPolicyBinding is supported", "version", gvk.Version)
119+
continue
120+
}
121+
mb := obj.(*v1alpha1.MutatingAdmissionPolicyBinding)
122+
r.MapBindings[mb.Name] = mb
114123
default:
115124
slog.Warn("unexpected manifest", "kind", gvk.Kind)
116125
}

internal/tester/manifest.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,9 @@ func (tc VAPTestCase) SummaryLine(pass bool, policy string, result string) strin
109109
}
110110

111111
type TestsForSingleMapPolicy struct {
112-
Policy string `yaml:"policy"`
113-
Tests []MAPTestCase `yaml:"tests"`
112+
Policy string `yaml:"policy"`
113+
Binding string `yaml:"binding,omitempty"`
114+
Tests []MAPTestCase `yaml:"tests"`
114115
}
115116

116117
type MAPTestCase struct {

internal/tester/result.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,26 @@ func (r *policyNotFoundResult) String(verbose bool) string {
154154
return fmt.Sprintf("FAIL: %s ==> POLICY NOT FOUND", r.Policy)
155155
}
156156

157+
type bindingNotFoundResult struct {
158+
Binding string
159+
}
160+
161+
var _ testResult = &bindingNotFoundResult{}
162+
163+
func newBindingNotFoundResult(binding string) *bindingNotFoundResult {
164+
return &bindingNotFoundResult{
165+
Binding: binding,
166+
}
167+
}
168+
169+
func (r *bindingNotFoundResult) Pass() bool {
170+
return false
171+
}
172+
173+
func (r *bindingNotFoundResult) String(verbose bool) string {
174+
return fmt.Sprintf("FAIL: %s ==> BINDING NOT FOUND", r.Binding)
175+
}
176+
157177
type setupErrorResult struct {
158178
Policy string
159179
TestCase TestCase

internal/tester/testdata/map-with-params.test/kaptest.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mapTestSuites:
1010
name: small
1111
namespace: foo
1212
param:
13+
namespace: hoge
1314
name: config1
1415
expect: mutate
1516
expectObject:
@@ -21,5 +22,21 @@ mapTestSuites:
2122
name: ok
2223
namespace: foo
2324
param:
25+
namespace: hoge
2426
name: config1
2527
expect: skip
28+
- policy: deployment-replicas
29+
binding: deployment-replicas-binding
30+
tests:
31+
- object:
32+
kind: Deployment
33+
name: small
34+
namespace: foo
35+
param:
36+
namespace: foo
37+
name: config1
38+
expect: mutate
39+
expectObject:
40+
kind: Deployment
41+
name: ok-large
42+
namespace: foo

internal/tester/testdata/map-with-params.test/resources.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,27 @@ spec:
2121
---
2222
apiVersion: apps/v1
2323
kind: Deployment
24+
metadata:
25+
name: ok-large
26+
namespace: foo
27+
labels:
28+
app: ok-deployment
29+
spec:
30+
replicas: 10
31+
selector:
32+
matchLabels:
33+
app: ok-deployment
34+
template:
35+
metadata:
36+
labels:
37+
app: ok-deployment
38+
spec:
39+
containers:
40+
- name: nginx
41+
image: nginx
42+
---
43+
apiVersion: apps/v1
44+
kind: Deployment
2445
metadata:
2546
name: small
2647
namespace: foo
@@ -47,3 +68,11 @@ metadata:
4768
namespace: hoge
4869
data:
4970
maxReplicas: "5"
71+
---
72+
apiVersion: v1
73+
kind: ConfigMap
74+
metadata:
75+
name: config1
76+
namespace: foo
77+
data:
78+
maxReplicas: "10"

internal/tester/testdata/map-with-params.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,13 @@ spec:
3232
replicas: variables.maxReplicas
3333
}
3434
}
35+
---
36+
apiVersion: admissionregistration.k8s.io/v1alpha1
37+
kind: MutatingAdmissionPolicyBinding
38+
metadata:
39+
name: deployment-replicas-binding
40+
spec:
41+
policyName: deployment-replicas
42+
paramRef:
43+
name: config1
44+
namespace: foo

internal/tester/tester.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,18 @@ func runEach(cfg TesterCmdConfig, manifestPath string) testResultSummary {
200200
continue
201201
}
202202

203-
mutator, err := kaptest.NewMutator(policy)
203+
var mutator *kaptest.Mutator
204+
var err error
205+
if tt.Binding != "" {
206+
binding, ok := loader.MapBindings[tt.Binding]
207+
if !ok {
208+
results = append(results, newBindingNotFoundResult(tt.Binding))
209+
continue
210+
}
211+
mutator, err = kaptest.NewMutatorWithBinding(policy, binding)
212+
} else {
213+
mutator, err = kaptest.NewMutator(policy)
214+
}
204215
if err != nil {
205216
panic(err)
206217
}

mutation.go

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type MutatorInterface interface {
5454

5555
type Mutator struct {
5656
policy *v1alpha1.MutatingAdmissionPolicy
57+
binding *v1alpha1.MutatingAdmissionPolicyBinding
5758
evaluator mutating.PolicyEvaluator
5859
}
5960

@@ -107,6 +108,15 @@ func NewMutator(policy *v1alpha1.MutatingAdmissionPolicy) (*Mutator, error) {
107108
}, nil
108109
}
109110

111+
func NewMutatorWithBinding(policy *v1alpha1.MutatingAdmissionPolicy, binding *v1alpha1.MutatingAdmissionPolicyBinding) (*Mutator, error) {
112+
m, err := NewMutator(policy)
113+
if err != nil {
114+
return nil, err
115+
}
116+
m.binding = binding
117+
return m, nil
118+
}
119+
110120
type mutatorContext struct {
111121
tcm patch.TypeConverterManager
112122
auth authorizer.Authorizer
@@ -280,21 +290,25 @@ func (m *Mutator) dispatchImpl(p MutationParams, dispatcherFactory func(mCtx *mu
280290
return nil, fmt.Errorf("failed to initialize mutatorContext: %w", err)
281291
}
282292

283-
binding := &v1alpha1.MutatingAdmissionPolicyBinding{
284-
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
285-
ParamRef: &v1alpha1.ParamRef{},
286-
MatchResources: &v1alpha1.MatchResources{
287-
MatchPolicy: ptr.To(v1alpha1.Equivalent),
288-
ObjectSelector: &metav1.LabelSelector{},
289-
NamespaceSelector: &metav1.LabelSelector{},
293+
bindingGenerated := false
294+
if m.binding == nil {
295+
m.binding = &v1alpha1.MutatingAdmissionPolicyBinding{
296+
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
297+
ParamRef: &v1alpha1.ParamRef{},
298+
MatchResources: &v1alpha1.MatchResources{
299+
MatchPolicy: ptr.To(v1alpha1.Equivalent),
300+
ObjectSelector: &metav1.LabelSelector{},
301+
NamespaceSelector: &metav1.LabelSelector{},
302+
},
290303
},
291-
},
304+
}
305+
bindingGenerated = true
292306
}
293307

294308
hook := mutating.PolicyHook{
295309
Policy: m.policy,
296310
Evaluator: m.evaluator,
297-
Bindings: []*mutating.PolicyBinding{binding},
311+
Bindings: []*mutating.PolicyBinding{m.binding},
298312
}
299313

300314
if m.policy.Spec.ParamKind != nil {
@@ -322,8 +336,10 @@ func (m *Mutator) dispatchImpl(p MutationParams, dispatcherFactory func(mCtx *mu
322336
if err != nil {
323337
return nil, fmt.Errorf("failed to access paramObj: %w", err)
324338
}
325-
binding.Spec.ParamRef.Name = metaAcc.GetName()
326-
binding.Spec.ParamRef.Namespace = metaAcc.GetNamespace()
339+
if bindingGenerated {
340+
m.binding.Spec.ParamRef.Name = metaAcc.GetName()
341+
m.binding.Spec.ParamRef.Namespace = metaAcc.GetNamespace()
342+
}
327343
}
328344

329345
// Start informers

0 commit comments

Comments
 (0)