From 6909de75a05df50b316e88405f684b0fc1c0c084 Mon Sep 17 00:00:00 2001 From: Derek Brown <6845676+DerekTBrown@users.noreply.github.com> Date: Thu, 26 Jun 2025 10:57:19 -0600 Subject: [PATCH] [fixes #56772] Fix validation for images without prefix --- extensions/v1alpha1/wasm.pb.go | 2 +- extensions/v1alpha1/wasm.proto | 2 +- kubernetes/customresourcedefinitions.gen.yaml | 8 +- tests/testdata/wasm-valid.yaml | 79 +++++++++++++++++-- 4 files changed, 77 insertions(+), 14 deletions(-) diff --git a/extensions/v1alpha1/wasm.pb.go b/extensions/v1alpha1/wasm.pb.go index 61d7aac774a..1e3e4e59bc3 100644 --- a/extensions/v1alpha1/wasm.pb.go +++ b/extensions/v1alpha1/wasm.pb.go @@ -587,7 +587,7 @@ type WasmPlugin struct { // within the proxy container, and `http[s]://` for `.wasm` module files // hosted remotely. // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:XValidation:message="url must have schema one of [http, https, file, oci]",rule="isURL(self) ? (url(self).getScheme() in [”, 'http', 'https', 'oci', 'file']) : (isURL('http://' + self) && url('http://' +self).getScheme() in [”, 'http', 'https', 'oci', 'file'])" + // +kubebuilder:validation:XValidation:message="url must have schema one of [http, https, file, oci] or be a valid OCI image reference",rule="(isURL(self) && url(self).getScheme() in ['http','https','file','oci']) || matches(self,'^([A-Za-z0-9.-]+(?::[0-9]+)?)?(/[A-Za-z0-9][A-Za-z0-9._-]*)*(?::[\\w][\\w.-]{0,127})?$')" Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` // SHA256 checksum that will be used to verify Wasm module or OCI container. // If the `url` field already references a SHA256 (using the `@sha256:` diff --git a/extensions/v1alpha1/wasm.proto b/extensions/v1alpha1/wasm.proto index 0c2e22468de..e507be91ed8 100644 --- a/extensions/v1alpha1/wasm.proto +++ b/extensions/v1alpha1/wasm.proto @@ -279,7 +279,7 @@ message WasmPlugin { // within the proxy container, and `http[s]://` for `.wasm` module files // hosted remotely. // +kubebuilder:validation:MinLength=1 - // +kubebuilder:validation:XValidation:message="url must have schema one of [http, https, file, oci]",rule="isURL(self) ? (url(self).getScheme() in ['', 'http', 'https', 'oci', 'file']) : (isURL('http://' + self) && url('http://' +self).getScheme() in ['', 'http', 'https', 'oci', 'file'])" + // +kubebuilder:validation:XValidation:message="url must have schema one of [http, https, file, oci] or be a valid OCI image reference",rule="(isURL(self) && url(self).getScheme() in ['http','https','file','oci']) || matches(self,'^([A-Za-z0-9.-]+(?::[0-9]+)?)?(/[A-Za-z0-9][A-Za-z0-9._-]*)*(?::[\\w][\\w.-]{0,127})?$')" string url = 2 [(google.api.field_behavior) = REQUIRED]; // SHA256 checksum that will be used to verify Wasm module or OCI container. diff --git a/kubernetes/customresourcedefinitions.gen.yaml b/kubernetes/customresourcedefinitions.gen.yaml index d76ca2be832..210bc67e2c2 100644 --- a/kubernetes/customresourcedefinitions.gen.yaml +++ b/kubernetes/customresourcedefinitions.gen.yaml @@ -225,10 +225,10 @@ spec: minLength: 1 type: string x-kubernetes-validations: - - message: url must have schema one of [http, https, file, oci] - rule: |- - isURL(self) ? (url(self).getScheme() in ["", "http", "https", "oci", "file"]) : (isURL("http://" + self) && - url("http://" + self).getScheme() in ["", "http", "https", "oci", "file"]) + - message: url must have schema one of [http, https, file, oci] or + be a valid OCI image reference + rule: isURL(self) && url(self).getScheme() in ["http", "https", + "file", "oci"] || matches(self, "^([A-Za-z0-9.-]+(?::[0-9]+)?)?(/[A-Za-z0-9][A-Za-z0-9._-]*)*(?::[\\w][\\w.-]{0,127})?$") verificationKey: type: string vmConfig: diff --git a/tests/testdata/wasm-valid.yaml b/tests/testdata/wasm-valid.yaml index 92cd9637d3d..92e68c6fbe9 100644 --- a/tests/testdata/wasm-valid.yaml +++ b/tests/testdata/wasm-valid.yaml @@ -22,13 +22,6 @@ spec: --- apiVersion: extensions.istio.io/v1alpha1 kind: WasmPlugin -metadata: - name: url-without-schema -spec: - url: "test" ---- -apiVersion: extensions.istio.io/v1alpha1 -kind: WasmPlugin metadata: name: env spec: @@ -41,4 +34,74 @@ spec: valueFrom: INLINE value: "test" - name: "test3" - value: "test" \ No newline at end of file + value: "test" +--- +apiVersion: extensions.istio.io/v1alpha1 +kind: WasmPlugin +metadata: + name: noprefix-image-default-lib-and-tag +spec: + url: "bar" +--- +apiVersion: extensions.istio.io/v1alpha1 +kind: WasmPlugin +metadata: + name: noprefix-image-default-lib-with-tag +spec: + url: "bar:latest" +--- +apiVersion: extensions.istio.io/v1alpha1 +kind: WasmPlugin +metadata: + name: noprefix-image-explicit-lib-default-tag +spec: + url: "library/bar" +--- +apiVersion: extensions.istio.io/v1alpha1 +kind: WasmPlugin +metadata: + name: noprefix-image-explicit-lib-and-tag +spec: + url: "library/bar:latest" +--- +apiVersion: extensions.istio.io/v1alpha1 +kind: WasmPlugin +metadata: + name: noprefix-image-with-explicit-repo-and-tag +spec: + url: "foo.bar/foo/bar:1.21.4" +--- +apiVersion: extensions.istio.io/v1alpha1 +kind: WasmPlugin +metadata: + name: noprefix-image-with-explicit-repo-and-tag-and-port +spec: + url: "foo.bar:5000/client_id_matches_cert:latest" +--- +apiVersion: extensions.istio.io/v1alpha1 +kind: WasmPlugin +metadata: + name: oci-image-explicit-lib-default-tag +spec: + url: "oci://library/bar" +--- +apiVersion: extensions.istio.io/v1alpha1 +kind: WasmPlugin +metadata: + name: oci-image-explicit-lib-and-tag +spec: + url: "oci://library/bar:latest" +--- +apiVersion: extensions.istio.io/v1alpha1 +kind: WasmPlugin +metadata: + name: oci-image-with-explicit-repo-and-tag +spec: + url: "oci://foo.bar/foo/bar:1.21.4" +--- +apiVersion: extensions.istio.io/v1alpha1 +kind: WasmPlugin +metadata: + name: oci-image-with-explicit-repo-and-tag-and-port +spec: + url: "oci://foo.bar:5000/client_id_matches_cert:latest"