From e771896541f472401d2baf239b782485235a419e Mon Sep 17 00:00:00 2001 From: Mohd Kamaal <102820439+Mohdcode@users.noreply.github.com> Date: Mon, 16 Dec 2024 10:36:34 +0530 Subject: [PATCH] distributed labels in group, version, and resource so it doesn't exceed (#11620) * change label to hash if exceed 63 limit char Signed-off-by: Mohd Kamaal * Distribute GVR labels into 'group', 'version', and 'resource' to avoid exceeding character limits Signed-off-by: Mohd Kamaal --------- Signed-off-by: Mohd Kamaal Co-authored-by: Kamaal Co-authored-by: Vishal Choudhary --- pkg/utils/report/metadata.go | 31 ++++++++++++--- .../reports/admission/label/README.md | 20 ++++++++++ .../admission/label/chainsaw-test.yaml | 30 ++++++++++++++ .../admission/label/crd-definition.yaml | 25 ++++++++++++ .../admission/label/crd-permission.yaml | 22 +++++++++++ .../admission/label/ephemeral-report.yaml | 39 +++++++++++++++++++ .../reports/admission/label/policy.yaml | 19 +++++++++ .../reports/admission/label/resource.yaml | 8 ++++ 8 files changed, 188 insertions(+), 6 deletions(-) create mode 100644 test/conformance/chainsaw/reports/admission/label/README.md create mode 100644 test/conformance/chainsaw/reports/admission/label/chainsaw-test.yaml create mode 100644 test/conformance/chainsaw/reports/admission/label/crd-definition.yaml create mode 100644 test/conformance/chainsaw/reports/admission/label/crd-permission.yaml create mode 100644 test/conformance/chainsaw/reports/admission/label/ephemeral-report.yaml create mode 100644 test/conformance/chainsaw/reports/admission/label/policy.yaml create mode 100644 test/conformance/chainsaw/reports/admission/label/resource.yaml diff --git a/pkg/utils/report/metadata.go b/pkg/utils/report/metadata.go index a6006c8e78..d75ecd09a8 100644 --- a/pkg/utils/report/metadata.go +++ b/pkg/utils/report/metadata.go @@ -115,7 +115,13 @@ func SetResourceUid(report reportsv1.ReportInterface, uid types.UID) { } func SetResourceGVR(report reportsv1.ReportInterface, gvr schema.GroupVersionResource) { - if gvr.Group != "" { + gvrString := gvr.Resource + "." + gvr.Version + "." + gvr.Group + + if len(gvrString) > 63 { + controllerutils.SetLabel(report, LabelResourceGroup, gvr.Group) + controllerutils.SetLabel(report, LabelResourceVersion, gvr.Version) + controllerutils.SetLabel(report, AnnotationResourceName, gvr.Resource) + } else if gvr.Group != "" { controllerutils.SetLabel(report, LabelResourceGVR, gvr.Resource+"."+gvr.Version+"."+gvr.Group) } else { controllerutils.SetLabel(report, LabelResourceGVR, gvr.Resource+"."+gvr.Version) @@ -181,16 +187,29 @@ func GetResourceUid(report metav1.Object) types.UID { } func GetResourceGVR(report metav1.Object) schema.GroupVersionResource { - arg := controllerutils.GetLabel(report, LabelResourceGVR) - dots := strings.Count(arg, ".") + group := controllerutils.GetLabel(report, LabelResourceGroup) + version := controllerutils.GetLabel(report, LabelResourceVersion) + resource := controllerutils.GetLabel(report, AnnotationResourceName) + GVRstring := group + version + resource + + // If all three parts exist, return the GVR + if group != "" && version != "" && resource != "" { + if len(GVRstring) > 63 { + return schema.GroupVersionResource{Group: group, Version: version, Resource: resource} + } + } + + // Fallback to the old combined label + combinedGVR := controllerutils.GetLabel(report, LabelResourceGVR) + dots := strings.Count(combinedGVR, ".") if dots >= 2 { - s := strings.SplitN(arg, ".", 3) + s := strings.SplitN(combinedGVR, ".", 3) return schema.GroupVersionResource{Group: s[2], Version: s[1], Resource: s[0]} } else if dots == 1 { - s := strings.SplitN(arg, ".", 2) + s := strings.SplitN(combinedGVR, ".", 2) return schema.GroupVersionResource{Version: s[1], Resource: s[0]} } - return schema.GroupVersionResource{Resource: arg} + return schema.GroupVersionResource{Resource: combinedGVR} } func GetResourceNamespaceAndName(report metav1.Object) (string, string) { diff --git a/test/conformance/chainsaw/reports/admission/label/README.md b/test/conformance/chainsaw/reports/admission/label/README.md new file mode 100644 index 0000000000..7d95bfd277 --- /dev/null +++ b/test/conformance/chainsaw/reports/admission/label/README.md @@ -0,0 +1,20 @@ +## Description + +This test ensures that the EphemeralReport is generated successfully at admission, even when long GVR (Group, Version, Resource) labels are used. Kyverno handles this by distributing the GVR components (group, version, resource) into separate labels, ensuring they fit within Kubernetes' 63-character limit. + +Kubernetes enforces the 63-character label limit during resource creation, and Kyverno ensures that the GVR components are split appropriately into distinct labels to avoid exceeding this limit. + +## Why It's Important + +If the combined length of GVR identifiers exceeds the 63-character limit, Kubernetes won't create the EphemeralReport at admission. Kyverno addresses this by: +Splitting the GVR components into separate labels, ensuring no label exceeds the size limit. +This approach enables the successful creation of EphemeralReport at admission. + +## Expected Behavior + +- Kyverno splits the GVR components (group, version, resource) into separate labels. +- The creation of EphemeralReport at admission will proceed successfully with the labels preserved within size limits. + +## Reference Issue(s) + +- Kyverno Issue #11547 diff --git a/test/conformance/chainsaw/reports/admission/label/chainsaw-test.yaml b/test/conformance/chainsaw/reports/admission/label/chainsaw-test.yaml new file mode 100644 index 0000000000..f1c13d6bf3 --- /dev/null +++ b/test/conformance/chainsaw/reports/admission/label/chainsaw-test.yaml @@ -0,0 +1,30 @@ +apiVersion: chainsaw.kyverno.io/v1alpha1 +kind: Test +metadata: + name: test-long-resource-labels +spec: + steps: + - name: create crd + try: + - apply: + file: crd-definition.yaml + + - name: create permission + try: + - apply: + file: crd-permission.yaml + + - name: apply policy + try: + - apply: + file: policy.yaml + + - name: create resource + try: + - apply: + file: resource.yaml + + - name: check report + try: + - assert: + file: ephemeral-report.yaml diff --git a/test/conformance/chainsaw/reports/admission/label/crd-definition.yaml b/test/conformance/chainsaw/reports/admission/label/crd-definition.yaml new file mode 100644 index 0000000000..82369638ce --- /dev/null +++ b/test/conformance/chainsaw/reports/admission/label/crd-definition.yaml @@ -0,0 +1,25 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: verylongresources.verylonggggggggggggggggggggggggggggggggggggggggroup.example.com +spec: + group: verylonggggggggggggggggggggggggggggggggggggggggroup.example.com + names: + kind: VeryLongResource + listKind: VeryLongResourceList + plural: verylongresources + singular: verylongresource + scope: Namespaced + versions: + - name: verylongversion + served: true + storage: true + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + exampleField: + type: string diff --git a/test/conformance/chainsaw/reports/admission/label/crd-permission.yaml b/test/conformance/chainsaw/reports/admission/label/crd-permission.yaml new file mode 100644 index 0000000000..ba098586d5 --- /dev/null +++ b/test/conformance/chainsaw/reports/admission/label/crd-permission.yaml @@ -0,0 +1,22 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: kyverno-reports-controller +rules: + - apiGroups: ["verylonggggggggggggggggggggggggggggggggggggggggroup.example.com"] + resources: ["verylongresources"] + verbs: ["get", "list", "watch"] + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: kyverno-reports-controller-rolebinding +subjects: + - kind: ServiceAccount + name: kyverno-reports-controller + namespace: kyverno +roleRef: + kind: ClusterRole + name: kyverno-reports-controller + apiGroup: rbac.authorization.k8s.io diff --git a/test/conformance/chainsaw/reports/admission/label/ephemeral-report.yaml b/test/conformance/chainsaw/reports/admission/label/ephemeral-report.yaml new file mode 100644 index 0000000000..df44804fd8 --- /dev/null +++ b/test/conformance/chainsaw/reports/admission/label/ephemeral-report.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +items: +- apiVersion: reports.kyverno.io/v1 + kind: EphemeralReport + metadata: + annotations: + audit.kyverno.io/resource.name: very-long-resource-name-testing-label-length + generation: 1 + labels: + app.kubernetes.io/managed-by: kyverno + audit.kyverno.io/resource.group: verylonggggggggggggggggggggggggggggggggggggggggroup.example.com + audit.kyverno.io/resource.name: verylongresources + audit.kyverno.io/resource.kind: VeryLongResource + audit.kyverno.io/resource.version: verylongversion + audit.kyverno.io/source: admission + ownerReferences: + - apiVersion: verylonggggggggggggggggggggggggggggggggggggggggroup.example.com/verylongversion + kind: VeryLongResource + name: very-long-resource-name-testing-label-length + spec: + owner: + apiVersion: "" + kind: "" + name: "" + uid: "" + results: + - message: 'validation error: Resource must have valid labels. rule check-label-length + failed at path /metadata/labels/team/' + policy: validate-long-resource-labels + result: fail + rule: check-label-length + scored: true + source: kyverno + summary: + error: 0 + fail: 1 + pass: 0 + skip: 0 + warn: 0 diff --git a/test/conformance/chainsaw/reports/admission/label/policy.yaml b/test/conformance/chainsaw/reports/admission/label/policy.yaml new file mode 100644 index 0000000000..a8939fc7aa --- /dev/null +++ b/test/conformance/chainsaw/reports/admission/label/policy.yaml @@ -0,0 +1,19 @@ +apiVersion: kyverno.io/v1 +kind: ClusterPolicy +metadata: + name: validate-long-resource-labels +spec: + rules: + - name: check-label-length + match: + resources: + kinds: + - VeryLongResource + validate: + message: "Resource must have valid labels." + pattern: + metadata: + labels: + env: "?*" + team: "?*" + failureAction: Audit diff --git a/test/conformance/chainsaw/reports/admission/label/resource.yaml b/test/conformance/chainsaw/reports/admission/label/resource.yaml new file mode 100644 index 0000000000..609c925820 --- /dev/null +++ b/test/conformance/chainsaw/reports/admission/label/resource.yaml @@ -0,0 +1,8 @@ +apiVersion: verylonggggggggggggggggggggggggggggggggggggggggroup.example.com/verylongversion +kind: VeryLongResource +metadata: + name: very-long-resource-name-testing-label-length + labels: + env: "test-environment" +spec: + exampleField: "exampleValue"