From bbb1d6103cb5350d94925e289dcc10778006976d Mon Sep 17 00:00:00 2001 From: Khaled Emara Date: Mon, 12 Aug 2024 17:59:27 +0300 Subject: [PATCH] feat(mutate): don't eagerly process img-ver (#10703) * feat(mutate): don't eagerly process img-ver Signed-off-by: Khaled Emara * test(mutate): add mutate with img-ver test Signed-off-by: Khaled Emara --------- Signed-off-by: Khaled Emara Co-authored-by: Vishal Choudhary Co-authored-by: shuting --- pkg/webhooks/resource/handlers.go | 54 +++++++++---------- .../standard/with-mutation/README.md | 11 ++++ .../standard/with-mutation/chainsaw-test.yaml | 27 ++++++++++ .../with-mutation/img-cpol-assert.yaml | 9 ++++ .../standard/with-mutation/img-cpol.yaml | 30 +++++++++++ .../with-mutation/mut-cpol-assert.yaml | 9 ++++ .../standard/with-mutation/mut-cpol.yaml | 22 ++++++++ .../standard/with-mutation/ns.yaml | 4 ++ .../with-mutation/test-pod-assert.yaml | 5 ++ .../standard/with-mutation/test-pod.yaml | 9 ++++ 10 files changed, 153 insertions(+), 27 deletions(-) create mode 100644 test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/README.md create mode 100755 test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/chainsaw-test.yaml create mode 100755 test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/img-cpol-assert.yaml create mode 100755 test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/img-cpol.yaml create mode 100755 test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/mut-cpol-assert.yaml create mode 100755 test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/mut-cpol.yaml create mode 100755 test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/ns.yaml create mode 100755 test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/test-pod-assert.yaml create mode 100755 test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/test-pod.yaml diff --git a/pkg/webhooks/resource/handlers.go b/pkg/webhooks/resource/handlers.go index b41612f6f048..827be222fead 100644 --- a/pkg/webhooks/resource/handlers.go +++ b/pkg/webhooks/resource/handlers.go @@ -198,38 +198,38 @@ func (h *resourceHandlers) Mutate(ctx context.Context, logger logr.Logger, reque return admissionutils.Response(request.UID, err) } mh := mutation.NewMutationHandler(logger, h.engine, h.eventGen, h.nsLister, h.metricsConfig) - mutatePatches, mutateWarnings, err := mh.HandleMutation(ctx, request.AdmissionRequest, mutatePolicies, policyContext, startTime) + patches, warnings, err := mh.HandleMutation(ctx, request.AdmissionRequest, mutatePolicies, policyContext, startTime) if err != nil { logger.Error(err, "mutation failed") return admissionutils.Response(request.UID, err) } - newRequest := patchRequest(mutatePatches, request.AdmissionRequest, logger) - // rebuild context to process images updated via mutate policies - policyContext, err = h.pcBuilder.Build(newRequest, request.Roles, request.ClusterRoles, request.GroupVersionKind) - if err != nil { - logger.Error(err, "failed to build policy context") - return admissionutils.Response(request.UID, err) - } - ivh := imageverification.NewImageVerificationHandler( - logger, - h.kyvernoClient, - h.engine, - h.eventGen, - h.admissionReports, - h.configuration, - h.nsLister, - h.reportsBreaker, - ) - imagePatches, imageVerifyWarnings, err := ivh.Handle(ctx, newRequest, verifyImagesPolicies, policyContext) - if err != nil { - logger.Error(err, "image verification failed") - return admissionutils.Response(request.UID, err) + if len(verifyImagesPolicies) != 0 { + newRequest := patchRequest(patches, request.AdmissionRequest, logger) + // rebuild context to process images updated via mutate policies + policyContext, err = h.pcBuilder.Build(newRequest, request.Roles, request.ClusterRoles, request.GroupVersionKind) + if err != nil { + logger.Error(err, "failed to build policy context") + return admissionutils.Response(request.UID, err) + } + ivh := imageverification.NewImageVerificationHandler( + logger, + h.kyvernoClient, + h.engine, + h.eventGen, + h.admissionReports, + h.configuration, + h.nsLister, + h.reportsBreaker, + ) + imagePatches, imageVerifyWarnings, err := ivh.Handle(ctx, newRequest, verifyImagesPolicies, policyContext) + if err != nil { + logger.Error(err, "image verification failed") + return admissionutils.Response(request.UID, err) + } + patches = jsonutils.JoinPatches(patches, imagePatches) + warnings = append(warnings, imageVerifyWarnings...) } - patch := jsonutils.JoinPatches(mutatePatches, imagePatches) - var warnings []string - warnings = append(warnings, mutateWarnings...) - warnings = append(warnings, imageVerifyWarnings...) - return admissionutils.MutationResponse(request.UID, patch, warnings...) + return admissionutils.MutationResponse(request.UID, patches, warnings...) } func (h *resourceHandlers) retrieveAndCategorizePolicies( diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/README.md b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/README.md new file mode 100644 index 000000000000..e7e7aed1ee16 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/README.md @@ -0,0 +1,11 @@ +## Description + +This test performs a simple verification of an image using a public key specified directly in the policy as well as mutate the image before the verification. + +## Expected Behavior + +Pod creation should pass as the mutated image has been signed by the public key specified in the policy. + +## Reference Issue(s) + +N/A \ No newline at end of file diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/chainsaw-test.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/chainsaw-test.yaml new file mode 100755 index 000000000000..3f9b2904e739 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/chainsaw-test.yaml @@ -0,0 +1,27 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + creationTimestamp: null + name: with-mutation +spec: + timeouts: + delete: 2m + steps: + - name: step-01 + try: + - apply: + file: ns.yaml + - apply: + file: mut-cpol.yaml + - assert: + file: mut-cpol-assert.yaml + - apply: + file: img-cpol.yaml + - assert: + file: img-cpol-assert.yaml + - name: step-02 + try: + - apply: + file: test-pod.yaml + - assert: + file: test-pod-assert.yaml diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/img-cpol-assert.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/img-cpol-assert.yaml new file mode 100755 index 000000000000..a1e604427d78 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/img-cpol-assert.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: with-mutation-img +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/img-cpol.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/img-cpol.yaml new file mode 100755 index 000000000000..f4822b3bbb37 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/img-cpol.yaml @@ -0,0 +1,30 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: with-mutation-img +spec: + background: false + failurePolicy: Fail + rules: + - match: + any: + - resources: + kinds: + - Pod + name: with-mutation-rule + verifyImages: + - attestors: + - entries: + - keys: + publicKeys: |- + -----BEGIN PUBLIC KEY----- + MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE8nXRh950IZbRj8Ra/N9sbqOPZrfM + 5/KAQN0/KjHcorm/J5yctVd7iEcnessRQjU917hmKO6JWVGHpDguIyakZA== + -----END PUBLIC KEY----- + rekor: + ignoreTlog: true + url: https://rekor.sigstore.dev + imageReferences: + - ghcr.io/kyverno/test-verify-image:* + validationFailureAction: Enforce + webhookTimeoutSeconds: 30 diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/mut-cpol-assert.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/mut-cpol-assert.yaml new file mode 100755 index 000000000000..8498e5fe2eda --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/mut-cpol-assert.yaml @@ -0,0 +1,9 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: with-mutation-mut +status: + conditions: + - reason: Succeeded + status: "True" + type: Ready diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/mut-cpol.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/mut-cpol.yaml new file mode 100755 index 000000000000..676f7a073157 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/mut-cpol.yaml @@ -0,0 +1,22 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: with-mutation-mut +spec: + background: false + failurePolicy: Fail + rules: + - match: + any: + - resources: + kinds: + - Pod + name: with-mutation-rule + mutate: + patchStrategicMerge: + spec: + containers: + - (name): test-secret + image: "ghcr.io/kyverno/test-verify-image:signed" + validationFailureAction: Enforce + webhookTimeoutSeconds: 30 diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/ns.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/ns.yaml new file mode 100755 index 000000000000..54c1efb587b1 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/ns.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: test-verify-images diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/test-pod-assert.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/test-pod-assert.yaml new file mode 100755 index 000000000000..1926808612a0 --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/test-pod-assert.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-with-mutation + namespace: test-verify-images diff --git a/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/test-pod.yaml b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/test-pod.yaml new file mode 100755 index 000000000000..5922e5a0a3cf --- /dev/null +++ b/test/conformance/chainsaw/verifyImages/clusterpolicy/standard/with-mutation/test-pod.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Pod +metadata: + name: test-with-mutation + namespace: test-verify-images +spec: + containers: + - image: ghcr.io/kyverno/test-verify-image:unsigned + name: test-secret