From 6e73e8514b9f2ae01d0f86ebabdd2191e8cb432f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Aug 2024 17:12:12 +0800 Subject: [PATCH 1/5] chore(deps): bump sigstore/cosign-installer from 3.5.0 to 3.6.0 (#10813) Bumps [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer) from 3.5.0 to 3.6.0. - [Release notes](https://github.com/sigstore/cosign-installer/releases) - [Commits](https://github.com/sigstore/cosign-installer/compare/59acb6260d9c0ba8f4a2f9d9b48431a222b68e20...4959ce089c160fddf62f7b42464195ba1a56d382) --- updated-dependencies: - dependency-name: sigstore/cosign-installer dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/conformance.yaml | 2 +- .github/workflows/helm-release.yaml | 2 +- .github/workflows/images-publish.yaml | 2 +- .github/workflows/release.yaml | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/conformance.yaml b/.github/workflows/conformance.yaml index 946da7f68fef..bbfdc7d5f024 100644 --- a/.github/workflows/conformance.yaml +++ b/.github/workflows/conformance.yaml @@ -642,7 +642,7 @@ jobs: - name: Install crane uses: imjasonh/setup-crane@31b88efe9de28ae0ffa220711af4b60be9435f6e - name: Install Cosign - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 + uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 - name: Install chainsaw uses: kyverno/action-install-chainsaw@82d8e747037f840e0ef9bdd97ecdc617f5535bdc # v0.2.8 # create cluster diff --git a/.github/workflows/helm-release.yaml b/.github/workflows/helm-release.yaml index 41b8c37245b8..8edfaa23dc56 100644 --- a/.github/workflows/helm-release.yaml +++ b/.github/workflows/helm-release.yaml @@ -70,7 +70,7 @@ jobs: version: v3.10.3 - name: Install Cosign - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 + uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0 - name: Set version run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV diff --git a/.github/workflows/images-publish.yaml b/.github/workflows/images-publish.yaml index 3bd54fd9be09..0a3671f7c71d 100644 --- a/.github/workflows/images-publish.yaml +++ b/.github/workflows/images-publish.yaml @@ -48,7 +48,7 @@ jobs: output: 'trivy-results.sarif' severity: 'CRITICAL,HIGH' - name: Install Cosign - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 + uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0 - name: Publish kyverno id: publish-kyverno uses: ./.github/actions/publish-image diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 72d487649df4..a81c461f133b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -43,7 +43,7 @@ jobs: output: 'trivy-results.sarif' severity: 'CRITICAL,HIGH' - name: Install Cosign - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 + uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0 - name: Publish kyverno id: release-kyverno uses: ./.github/actions/publish-image @@ -243,7 +243,7 @@ jobs: timeout-minutes: 30 - uses: creekorful/goreportcard-action@1f35ced8cdac2cba28c9a2f2288a16aacfd507f9 # v1.0 - name: Install Cosign - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 + uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0 - name: Make Release env: VERSION: ${{ github.ref_name }} @@ -282,7 +282,7 @@ jobs: with: version: 0.35.0 - name: Install Cosign - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 + uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3.6.0 - name: Build yaml manifest run: VERSION=${{ github.ref_name }} make codegen-manifest-release - name: Upload install manifest From 65a43d20590fbd5a4c84b15be8c38488d946816e Mon Sep 17 00:00:00 2001 From: Khaled Emara Date: Fri, 9 Aug 2024 14:12:20 +0300 Subject: [PATCH 2/5] feat(mutate): minimize unmarshals (#10702) * feat(mutate): minimize unmarshals Signed-off-by: Khaled Emara * test(mutate): test type assertion Signed-off-by: Khaled Emara * chore(codegen): remove unused import Signed-off-by: Khaled Emara --------- Signed-off-by: Khaled Emara --- api/kyverno/v1/common_types.go | 12 ++++--- api/kyverno/v1/zz_generated.deepcopy.go | 3 +- docs/user/crd/index.html | 4 +-- docs/user/crd/kyverno.v1.html | 2 +- go.mod | 1 + .../kyverno/v1/foreachmutation.go | 6 ++-- pkg/engine/handlers/mutation/common.go | 2 +- pkg/engine/mutate/mutation.go | 28 ++++++--------- pkg/engine/mutate/mutation_test.go | 34 +++++++++++++++++++ pkg/policy/mutate/validate.go | 2 +- 10 files changed, 60 insertions(+), 34 deletions(-) diff --git a/api/kyverno/v1/common_types.go b/api/kyverno/v1/common_types.go index 0204faafda17..209245e9a414 100644 --- a/api/kyverno/v1/common_types.go +++ b/api/kyverno/v1/common_types.go @@ -418,7 +418,9 @@ type ForEachMutation struct { // See https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/ // and https://kubectl.docs.kubernetes.io/references/kustomize/patchesstrategicmerge/. // +optional - RawPatchStrategicMerge *apiextv1.JSON `json:"patchStrategicMerge,omitempty" yaml:"patchStrategicMerge,omitempty"` + // +kubebuilder:validation:Schemaless + // +kubebuilder:pruning:PreserveUnknownFields + RawPatchStrategicMerge *kyverno.Any `json:"patchStrategicMerge,omitempty" yaml:"patchStrategicMerge,omitempty"` // PatchesJSON6902 is a list of RFC 6902 JSON Patch declarations used to modify resources. // See https://tools.ietf.org/html/rfc6902 and https://kubectl.docs.kubernetes.io/references/kustomize/patchesjson6902/. @@ -439,12 +441,12 @@ func (m *ForEachMutation) GetForEachMutation() []ForEachMutation { return m.ForEachMutation.Items } -func (m *ForEachMutation) GetPatchStrategicMerge() apiextensions.JSON { - return FromJSON(m.RawPatchStrategicMerge) +func (m *ForEachMutation) GetPatchStrategicMerge() any { + return kyverno.FromAny(m.RawPatchStrategicMerge) } -func (m *ForEachMutation) SetPatchStrategicMerge(in apiextensions.JSON) { - m.RawPatchStrategicMerge = ToJSON(in) +func (m *ForEachMutation) SetPatchStrategicMerge(in any) { + m.RawPatchStrategicMerge = kyverno.ToAny(in) } // Validation defines checks to be performed on matching resources. diff --git a/api/kyverno/v1/zz_generated.deepcopy.go b/api/kyverno/v1/zz_generated.deepcopy.go index 11e30252b59b..c6feffb85c66 100755 --- a/api/kyverno/v1/zz_generated.deepcopy.go +++ b/api/kyverno/v1/zz_generated.deepcopy.go @@ -559,8 +559,7 @@ func (in *ForEachMutation) DeepCopyInto(out *ForEachMutation) { } if in.RawPatchStrategicMerge != nil { in, out := &in.RawPatchStrategicMerge, &out.RawPatchStrategicMerge - *out = new(apiextensionsv1.JSON) - (*in).DeepCopyInto(*out) + *out = (*in).DeepCopy() } if in.ForEachMutation != nil { in, out := &in.ForEachMutation, &out.ForEachMutation diff --git a/docs/user/crd/index.html b/docs/user/crd/index.html index 17ff50804676..98908837edaf 100644 --- a/docs/user/crd/index.html +++ b/docs/user/crd/index.html @@ -1724,9 +1724,7 @@

ForEachMutation patchStrategicMerge
- -Kubernetes apiextensions/v1.JSON - +github.com/kyverno/kyverno/api/kyverno.Any diff --git a/docs/user/crd/kyverno.v1.html b/docs/user/crd/kyverno.v1.html index 1baa341e888f..433baef7a551 100644 --- a/docs/user/crd/kyverno.v1.html +++ b/docs/user/crd/kyverno.v1.html @@ -3540,7 +3540,7 @@

ForEachMutation - k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1.JSON + github.com/kyverno/kyverno/api/kyverno.Any diff --git a/go.mod b/go.mod index 67ed13869102..a3e98a9c8e7b 100644 --- a/go.mod +++ b/go.mod @@ -331,6 +331,7 @@ require ( github.com/spf13/viper v1.19.0 // indirect github.com/spiffe/go-spiffe/v2 v2.2.0 // indirect github.com/stoewer/go-strcase v1.3.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tchap/go-patricia/v2 v2.3.1 // indirect diff --git a/pkg/client/applyconfigurations/kyverno/v1/foreachmutation.go b/pkg/client/applyconfigurations/kyverno/v1/foreachmutation.go index d6f56a66968a..ae0747fc0290 100644 --- a/pkg/client/applyconfigurations/kyverno/v1/foreachmutation.go +++ b/pkg/client/applyconfigurations/kyverno/v1/foreachmutation.go @@ -19,8 +19,8 @@ limitations under the License. package v1 import ( + kyverno "github.com/kyverno/kyverno/api/kyverno" v1 "github.com/kyverno/kyverno/api/kyverno/v1" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" ) // ForEachMutationApplyConfiguration represents an declarative configuration of the ForEachMutation type for use @@ -30,7 +30,7 @@ type ForEachMutationApplyConfiguration struct { Order *v1.ForeachOrder `json:"order,omitempty"` Context []ContextEntryApplyConfiguration `json:"context,omitempty"` AnyAllConditions *AnyAllConditionsApplyConfiguration `json:"preconditions,omitempty"` - RawPatchStrategicMerge *apiextensionsv1.JSON `json:"patchStrategicMerge,omitempty"` + RawPatchStrategicMerge *kyverno.Any `json:"patchStrategicMerge,omitempty"` PatchesJSON6902 *string `json:"patchesJson6902,omitempty"` ForEachMutation *v1.ForEachMutationWrapper `json:"foreach,omitempty"` } @@ -81,7 +81,7 @@ func (b *ForEachMutationApplyConfiguration) WithAnyAllConditions(value *AnyAllCo // WithRawPatchStrategicMerge sets the RawPatchStrategicMerge field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the RawPatchStrategicMerge field is set to the value of the last call. -func (b *ForEachMutationApplyConfiguration) WithRawPatchStrategicMerge(value apiextensionsv1.JSON) *ForEachMutationApplyConfiguration { +func (b *ForEachMutationApplyConfiguration) WithRawPatchStrategicMerge(value kyverno.Any) *ForEachMutationApplyConfiguration { b.RawPatchStrategicMerge = &value return b } diff --git a/pkg/engine/handlers/mutation/common.go b/pkg/engine/handlers/mutation/common.go index 5ac473daca07..a6862f8e71fc 100644 --- a/pkg/engine/handlers/mutation/common.go +++ b/pkg/engine/handlers/mutation/common.go @@ -69,7 +69,7 @@ func (f *forEachMutator) mutateElements(ctx context.Context, foreach kyvernov1.F reverse := false // if it's a patch strategic merge, reverse by default - if foreach.RawPatchStrategicMerge != nil { + if foreach.GetPatchStrategicMerge() != nil { reverse = true } if foreach.Order != nil { diff --git a/pkg/engine/mutate/mutation.go b/pkg/engine/mutate/mutation.go index 2ca2c4421ddd..9f730430fe62 100644 --- a/pkg/engine/mutate/mutation.go +++ b/pkg/engine/mutate/mutation.go @@ -1,7 +1,6 @@ package mutate import ( - "encoding/json" "fmt" "strings" @@ -11,7 +10,6 @@ import ( "github.com/kyverno/kyverno/pkg/engine/context" "github.com/kyverno/kyverno/pkg/engine/mutate/patch" "github.com/kyverno/kyverno/pkg/engine/variables" - datautils "github.com/kyverno/kyverno/pkg/utils/data" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) @@ -77,7 +75,7 @@ func ForEach(name string, foreach kyvernov1.ForEachMutation, policyContext engin if err != nil { return NewErrorResponse("variable substitution failed", err) } - patcher := NewPatcher(fe.GetPatchStrategicMerge(), fe.PatchesJSON6902) + patcher := NewPatcher(fe["patchStrategicMerge"], fe["patchesJson6902"].(string)) if patcher == nil { return NewErrorResponse("empty mutate rule", nil) } @@ -101,28 +99,22 @@ func ForEach(name string, foreach kyvernov1.ForEachMutation, policyContext engin return NewResponse(engineapi.RuleStatusPass, *patchedResource, "resource patched") } -func substituteAllInForEach(fe kyvernov1.ForEachMutation, ctx context.Interface, logger logr.Logger) (*kyvernov1.ForEachMutation, error) { - jsonObj, err := datautils.ToMap(fe) - if err != nil { - return nil, err - } - - data, err := variables.SubstituteAll(logger, ctx, jsonObj) - if err != nil { - return nil, err - } +func substituteAllInForEach(fe kyvernov1.ForEachMutation, ctx context.Interface, logger logr.Logger) (map[string]interface{}, error) { + patchesMap := make(map[string]interface{}) + patchesMap["patchStrategicMerge"] = fe.GetPatchStrategicMerge() + patchesMap["patchesJson6902"] = fe.PatchesJSON6902 - bytes, err := json.Marshal(data) + subedPatchesMap, err := variables.SubstituteAll(logger, ctx, patchesMap) if err != nil { return nil, err } - var updatedForEach kyvernov1.ForEachMutation - if err := json.Unmarshal(bytes, &updatedForEach); err != nil { - return nil, err + typedMap, ok := subedPatchesMap.(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("failed to convert patched map to map[string]interface{}") } - return &updatedForEach, nil + return typedMap, nil } func NewPatcher(strategicMergePatch apiextensions.JSON, jsonPatch string) patch.Patcher { diff --git a/pkg/engine/mutate/mutation_test.go b/pkg/engine/mutate/mutation_test.go index ca4ef1c5d4d6..a12a21c5593e 100644 --- a/pkg/engine/mutate/mutation_test.go +++ b/pkg/engine/mutate/mutation_test.go @@ -7,10 +7,13 @@ import ( "github.com/go-logr/logr" types "github.com/kyverno/kyverno/api/kyverno/v1" + v1 "github.com/kyverno/kyverno/api/kyverno/v1" "github.com/kyverno/kyverno/pkg/config" engineapi "github.com/kyverno/kyverno/pkg/engine/api" "github.com/kyverno/kyverno/pkg/engine/context" "github.com/kyverno/kyverno/pkg/engine/jmespath" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -235,3 +238,34 @@ func TestProcessPatches_RemovePathDoesntExist_NotEmptyResult(t *testing.T) { unstructured.SetNestedField(resource.UnstructuredContent(), "label2Value", "metadata", "labels", "label2") require.Equal(t, resource, patched) } + +type MockContext struct { + context.Interface + mock.Mock +} + +func (m *MockContext) Query(query string) (interface{}, error) { + args := m.Called(query) + return args.Get(0), args.Error(1) +} + +func (m *MockContext) QueryOperation() string { + args := m.Called() + return args.Get(0).(string) +} + +func TestSubstituteAllInForEach_InvalidTypeConversion(t *testing.T) { + ctx := &MockContext{} + // Simulate a scenario where the substitution returns an unexpected type + ctx.On("Query", mock.Anything).Return(true, nil) + ctx.On("QueryOperation").Return("CREATE") + + foreach := v1.ForEachMutation{ + PatchesJSON6902: "string", + } + + fe, err := substituteAllInForEach(foreach, ctx, logr.Discard()) + + assert.NoError(t, err) + assert.IsType(t, "string", fe["patchesJson6902"]) +} diff --git a/pkg/policy/mutate/validate.go b/pkg/policy/mutate/validate.go index e5973bb2774b..88c311fe03e6 100644 --- a/pkg/policy/mutate/validate.go +++ b/pkg/policy/mutate/validate.go @@ -55,7 +55,7 @@ func (m *Mutate) validateForEach(tag string, foreach []kyvernov1.ForEachMutation tag = tag + fmt.Sprintf("foreach[%d]", i) fem := fe.GetForEachMutation() if len(fem) > 0 { - if fe.Context != nil || fe.AnyAllConditions != nil || fe.PatchesJSON6902 != "" || fe.RawPatchStrategicMerge != nil { + if fe.Context != nil || fe.AnyAllConditions != nil || fe.PatchesJSON6902 != "" || fe.GetPatchStrategicMerge() != nil { return tag, fmt.Errorf("a nested foreach cannot contain other declarations") } From bbb1d6103cb5350d94925e289dcc10778006976d Mon Sep 17 00:00:00 2001 From: Khaled Emara Date: Mon, 12 Aug 2024 17:59:27 +0300 Subject: [PATCH 3/5] 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 From b8a69a7eacc5da6ba5ce1c5f9e3538b3fa502a44 Mon Sep 17 00:00:00 2001 From: Khaled Emara Date: Mon, 12 Aug 2024 18:57:16 +0300 Subject: [PATCH 4/5] feat(audit): enable audit logs for kind (#10822) Signed-off-by: Khaled Emara --- scripts/config/kind/audit-config.yaml | 29 +++++++++++++++++++++++++++ scripts/config/kind/audit-policy.yaml | 7 +++++++ 2 files changed, 36 insertions(+) create mode 100644 scripts/config/kind/audit-config.yaml create mode 100644 scripts/config/kind/audit-policy.yaml diff --git a/scripts/config/kind/audit-config.yaml b/scripts/config/kind/audit-config.yaml new file mode 100644 index 000000000000..5b22c9b10412 --- /dev/null +++ b/scripts/config/kind/audit-config.yaml @@ -0,0 +1,29 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + kubeadmConfigPatches: + - | + kind: ClusterConfiguration + apiServer: + # enable auditing flags on the API server + extraArgs: + audit-log-path: /var/log/kubernetes/kube-apiserver-audit.log + audit-policy-file: /etc/kubernetes/policies/audit-policy.yaml + # mount new files / directories on the control plane + extraVolumes: + - name: audit-policies + hostPath: /etc/kubernetes/policies + mountPath: /etc/kubernetes/policies + readOnly: true + pathType: "DirectoryOrCreate" + - name: "audit-logs" + hostPath: "/var/log/kubernetes" + mountPath: "/var/log/kubernetes" + readOnly: false + pathType: DirectoryOrCreate + # mount the local file on the control plane + extraMounts: + - hostPath: ./scripts/config/kind/audit-policy.yaml + containerPath: /etc/kubernetes/policies/audit-policy.yaml + readOnly: true diff --git a/scripts/config/kind/audit-policy.yaml b/scripts/config/kind/audit-policy.yaml new file mode 100644 index 000000000000..0aa9818479d5 --- /dev/null +++ b/scripts/config/kind/audit-policy.yaml @@ -0,0 +1,7 @@ +apiVersion: audit.k8s.io/v1 +kind: Policy +rules: +- level: RequestResponse + resources: + - group: "kyverno.io" + resources: ["policies", "clusterpolicies"] From 3a69702b490cb7afe4cc026b34369932bf808ce7 Mon Sep 17 00:00:00 2001 From: Mariam Fahmy Date: Tue, 13 Aug 2024 12:25:29 +0300 Subject: [PATCH 5/5] fix: check permissions for validate.cel subrules only (#10829) Signed-off-by: Mariam Fahmy Co-authored-by: Jim Bugwadia --- pkg/validation/policy/actions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/validation/policy/actions.go b/pkg/validation/policy/actions.go index acbf33f2952a..1cbbe3b2ae35 100644 --- a/pkg/validation/policy/actions.go +++ b/pkg/validation/policy/actions.go @@ -55,7 +55,7 @@ func validateActions(idx int, rule *kyvernov1.Rule, client dclient.Interface, mo } // In case generateValidatingAdmissionPolicy flag is set to true, check the required permissions. - if toggle.FromContext(context.TODO()).GenerateValidatingAdmissionPolicy() { + if rule.HasValidateCEL() && toggle.FromContext(context.TODO()).GenerateValidatingAdmissionPolicy() { authCheck := authChecker.NewSelfChecker(client.GetKubeClient().AuthorizationV1().SelfSubjectAccessReviews()) // check if the controller has the required permissions to generate validating admission policies. if !validatingadmissionpolicy.HasValidatingAdmissionPolicyPermission(authCheck) {