From 9fea512aca8ba3d3348ef340636c2c376d0df287 Mon Sep 17 00:00:00 2001 From: xphyr Date: Fri, 5 Jun 2026 12:31:18 -0400 Subject: [PATCH 01/11] Adding new "insecureSkipVerify" option for http datasources This option allows a user to explicitly override TLS for self-signed certificates on specific data sources This option uses existing framework for overriding TLS settings in storageio importer for consistency All existing go tests have been updated to use the default setting "false" to maintain the existing tests Signed-off-by: xphyr --- api/openapi-spec/swagger.json | 4 ++ cmd/cdi-importer/importer.go | 2 +- pkg/apis/core/v1beta1/openapi_generated.go | 7 +++ pkg/controller/common/util.go | 3 ++ pkg/controller/import-controller.go | 4 +- pkg/importer/http-datasource.go | 11 ++-- pkg/importer/http-datasource_test.go | 52 +++++++++---------- pkg/operator/resources/crds_generated.go | 12 +++++ .../pkg/apis/core/v1beta1/types.go | 3 ++ .../core/v1beta1/types_swagger_generated.go | 1 + .../core/v1beta1/zz_generated.deepcopy.go | 5 ++ 11 files changed, 69 insertions(+), 35 deletions(-) diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 7087c0d783..92c711a0a1 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -4794,6 +4794,10 @@ "default": "" } }, + "insecureSkipVerify": { + "description": "InsecureSkipVerify is a flag to skip certificate verification for the HTTP endpoint", + "type": "boolean" + }, "secretExtraHeaders": { "description": "SecretExtraHeaders is a list of Secret references, each containing an extra HTTP header that may include sensitive information", "type": "array", diff --git a/cmd/cdi-importer/importer.go b/cmd/cdi-importer/importer.go index cc767b1446..0e95e6cf36 100644 --- a/cmd/cdi-importer/importer.go +++ b/cmd/cdi-importer/importer.go @@ -291,7 +291,7 @@ func newDataSource(source string, contentType string, volumeMode v1.PersistentVo switch source { case cc.SourceHTTP: - ds, err := importer.NewHTTPDataSource(getHTTPEp(ep), acc, sec, certDir, cdiv1.DataVolumeContentType(contentType), checksum) + ds, err := importer.NewHTTPDataSource(getHTTPEp(ep), acc, sec, certDir, cdiv1.DataVolumeContentType(contentType), checksum, insecureTLS) if err != nil { errorCannotConnectDataSource(err, "http") } diff --git a/pkg/apis/core/v1beta1/openapi_generated.go b/pkg/apis/core/v1beta1/openapi_generated.go index 7b28adafb6..06f01656ec 100644 --- a/pkg/apis/core/v1beta1/openapi_generated.go +++ b/pkg/apis/core/v1beta1/openapi_generated.go @@ -18165,6 +18165,13 @@ func schema_pkg_apis_core_v1beta1_DataVolumeSourceHTTP(ref common.ReferenceCallb Format: "", }, }, + "insecureSkipVerify": { + SchemaProps: spec.SchemaProps{ + Description: "InsecureSkipVerify is a flag to skip certificate verification for the HTTP endpoint", + Type: []string{"boolean"}, + Format: "", + }, + }, }, Required: []string{"url"}, }, diff --git a/pkg/controller/common/util.go b/pkg/controller/common/util.go index 02df0fb87a..656eb06ea8 100644 --- a/pkg/controller/common/util.go +++ b/pkg/controller/common/util.go @@ -1753,6 +1753,9 @@ func UpdateHTTPAnnotations(annotations map[string]string, http *cdiv1.DataVolume if http.Checksum != "" { annotations[AnnChecksum] = http.Checksum } + if http.InsecureSkipVerify != nil && *http.InsecureSkipVerify { + annotations[AnnInsecureSkipVerify] = "true" + } for index, header := range http.ExtraHeaders { annotations[fmt.Sprintf("%s.%d", AnnExtraHeaders, index)] = header } diff --git a/pkg/controller/import-controller.go b/pkg/controller/import-controller.go index 543e7865b6..52ec268073 100644 --- a/pkg/controller/import-controller.go +++ b/pkg/controller/import-controller.go @@ -713,9 +713,9 @@ func (r *ImportReconciler) createImportEnvVar(pvc *corev1.PersistentVolumeClaim) } func (r *ImportReconciler) isInsecureTLS(pvc *corev1.PersistentVolumeClaim, cdiConfig *cdiv1.CDIConfig) (bool, error) { - // Check if insecureSkipVerify annotation is set (only applicable for ImageIO sources) + // Check if insecureSkipVerify annotation is set (only applicable for ImageIO sources and HTTP sources) source, sourceOk := pvc.Annotations[cc.AnnSource] - if sourceOk && source == cc.SourceImageio { + if sourceOk && (source == cc.SourceImageio || source == cc.SourceHTTP) { if insecureSkipVerify, ok := pvc.Annotations[cc.AnnInsecureSkipVerify]; ok && insecureSkipVerify == "true" { return true, nil } diff --git a/pkg/importer/http-datasource.go b/pkg/importer/http-datasource.go index 73bc619543..511f93123b 100644 --- a/pkg/importer/http-datasource.go +++ b/pkg/importer/http-datasource.go @@ -84,14 +84,13 @@ type HTTPDataSource struct { contentLength uint64 // checksumValidator validates the checksum of downloaded data checksumValidator *ChecksumValidator - - n image.NbdkitOperation + n image.NbdkitOperation } var createNbdkitCurl = image.NewNbdkitCurl // NewHTTPDataSource creates a new instance of the http data provider. -func NewHTTPDataSource(endpoint, accessKey, secKey, certDir string, contentType cdiv1.DataVolumeContentType, checksum string) (*HTTPDataSource, error) { +func NewHTTPDataSource(endpoint, accessKey, secKey, certDir string, contentType cdiv1.DataVolumeContentType, checksum string, insecureSkipVerify bool) (*HTTPDataSource, error) { ep, err := ParseEndpoint(endpoint) if err != nil { return nil, errors.Wrapf(err, "unable to parse endpoint %q", endpoint) @@ -104,7 +103,7 @@ func NewHTTPDataSource(endpoint, accessKey, secKey, certDir string, contentType return nil, errors.Wrap(err, "Error getting extra headers for HTTP client") } - httpReader, contentLength, brokenForQemuImg, err := createHTTPReader(ctx, ep, accessKey, secKey, certDir, extraHeaders, secretExtraHeaders, contentType) + httpReader, contentLength, brokenForQemuImg, err := createHTTPReader(ctx, ep, accessKey, secKey, certDir, extraHeaders, secretExtraHeaders, contentType, insecureSkipVerify) if err != nil { cancel() return nil, err @@ -365,9 +364,9 @@ func addExtraheaders(req *http.Request, extraHeaders []string) { req.Header.Add("User-Agent", defaultUserAgent) } -func createHTTPReader(ctx context.Context, ep *url.URL, accessKey, secKey, certDir string, extraHeaders, secretExtraHeaders []string, contentType cdiv1.DataVolumeContentType) (io.ReadCloser, uint64, bool, error) { +func createHTTPReader(ctx context.Context, ep *url.URL, accessKey, secKey, certDir string, extraHeaders, secretExtraHeaders []string, contentType cdiv1.DataVolumeContentType, insecureSkipVerify bool) (io.ReadCloser, uint64, bool, error) { var brokenForQemuImg bool - client, err := createHTTPClient(certDir, false) + client, err := createHTTPClient(certDir, insecureSkipVerify) if err != nil { return nil, uint64(0), false, errors.Wrap(err, "Error creating http client") } diff --git a/pkg/importer/http-datasource_test.go b/pkg/importer/http-datasource_test.go index eed1d43271..6d2237a339 100644 --- a/pkg/importer/http-datasource_test.go +++ b/pkg/importer/http-datasource_test.go @@ -76,14 +76,14 @@ var _ = Describe("Http data source", func() { }) It("NewHTTPDataSource should fail when called with an invalid endpoint", func() { - _, err = NewHTTPDataSource("httpd://!@#$%^&*()dgsdd&3r53/invalid", "", "", "", cdiv1.DataVolumeKubeVirt, "") + _, err = NewHTTPDataSource("httpd://!@#$%^&*()dgsdd&3r53/invalid", "", "", "", cdiv1.DataVolumeKubeVirt, "", false) Expect(err).To(HaveOccurred()) Expect(strings.Contains(err.Error(), "unable to parse endpoint")).To(BeTrue()) }) It("NewHTTPDataSource should fail when called with an invalid certdir", func() { image := ts.URL + "/" + cirrosFileName - _, err = NewHTTPDataSource(image, "", "", "/invaliddir", cdiv1.DataVolumeKubeVirt, "") + _, err = NewHTTPDataSource(image, "", "", "/invaliddir", cdiv1.DataVolumeKubeVirt, "", false) Expect(err).To(HaveOccurred()) }) @@ -92,7 +92,7 @@ var _ = Describe("Http data source", func() { if image != "" { image = ts.URL + "/" + image } - dp, err = NewHTTPDataSource(image, "", "", "", contentType, "") + dp, err = NewHTTPDataSource(image, "", "", "", contentType, "", false) dp.brokenForQemuImg = brokenForQemuImg Expect(err).NotTo(HaveOccurred()) newPhase, err := dp.Info() @@ -117,7 +117,7 @@ var _ = Describe("Http data source", func() { if image != "" { image = ts.URL + "/" + image } - dp, err = NewHTTPDataSource(image, "", "", "", contentType, "") + dp, err = NewHTTPDataSource(image, "", "", "", contentType, "", false) Expect(err).NotTo(HaveOccurred()) _, err := dp.Info() Expect(err).NotTo(HaveOccurred()) @@ -152,7 +152,7 @@ var _ = Describe("Http data source", func() { ) DescribeTable("should succeed when writing to a valid file with phase", func(expectedPhase ProcessingPhase, brokenForQemuImg bool, imageType string) { - dp, err = NewHTTPDataSource(ts.URL+"/"+imageType, "", "", "", cdiv1.DataVolumeKubeVirt, "") + dp, err = NewHTTPDataSource(ts.URL+"/"+imageType, "", "", "", cdiv1.DataVolumeKubeVirt, "", false) dp.brokenForQemuImg = brokenForQemuImg Expect(err).NotTo(HaveOccurred()) result, err := dp.Info() @@ -182,7 +182,7 @@ var _ = Describe("Http data source", func() { w.WriteHeader(http.StatusInternalServerError) } })) - dp, err = NewHTTPDataSource(ts2.URL+"/"+tinyCoreGz, "", "", "", cdiv1.DataVolumeKubeVirt, "") + dp, err = NewHTTPDataSource(ts2.URL+"/"+tinyCoreGz, "", "", "", cdiv1.DataVolumeKubeVirt, "", false) Expect(err).NotTo(HaveOccurred()) _, err := dp.Info() Expect(err).NotTo(HaveOccurred()) @@ -215,7 +215,7 @@ var _ = Describe("Http data source", func() { It("should fail when created with invalid checksum format", func() { image := ts.URL + "/" + cirrosFileName // Invalid format: missing colon - _, err := NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeKubeVirt, "sha256abc123") + _, err := NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeKubeVirt, "sha256abc123", false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("invalid checksum")) }) @@ -223,7 +223,7 @@ var _ = Describe("Http data source", func() { It("should fail when created with unsupported checksum algorithm", func() { image := ts.URL + "/" + cirrosFileName // Unsupported algorithm - _, err := NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeKubeVirt, "crc32:12345678") + _, err := NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeKubeVirt, "crc32:12345678", false) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("invalid checksum")) }) @@ -231,7 +231,7 @@ var _ = Describe("Http data source", func() { It("should succeed with valid checksum during transfer", func() { image := ts.URL + "/" + cirrosFileName checksum := "sha256:" + testDataSHA256 - dp, err = NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeKubeVirt, checksum) + dp, err = NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeKubeVirt, checksum, false) Expect(err).NotTo(HaveOccurred()) _, err := dp.Info() @@ -257,7 +257,7 @@ var _ = Describe("Http data source", func() { image := ts.URL + "/" + cirrosFileName // Use an incorrect checksum (all zeros) incorrectChecksum := "sha256:0000000000000000000000000000000000000000000000000000000000000000" - dp, err = NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeKubeVirt, incorrectChecksum) + dp, err = NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeKubeVirt, incorrectChecksum, false) Expect(err).NotTo(HaveOccurred()) _, err := dp.Info() @@ -277,7 +277,7 @@ var _ = Describe("Http data source", func() { archiveChecksum := "sha256:" + archiveDataSHA256 image := ts.URL + "/" + diskimageTarFileName - dp, err = NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeArchive, archiveChecksum) + dp, err = NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeArchive, archiveChecksum, false) Expect(err).NotTo(HaveOccurred()) _, err := dp.Info() @@ -292,7 +292,7 @@ var _ = Describe("Http data source", func() { image := ts.URL + "/" + diskimageTarFileName // Use an incorrect checksum incorrectChecksum := "sha256:1111111111111111111111111111111111111111111111111111111111111111" - dp, err = NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeArchive, incorrectChecksum) + dp, err = NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeArchive, incorrectChecksum, false) Expect(err).NotTo(HaveOccurred()) _, err := dp.Info() @@ -307,7 +307,7 @@ var _ = Describe("Http data source", func() { It("should succeed with valid checksum during TransferFile", func() { image := ts.URL + "/" + cirrosFileName checksum := "sha256:" + testDataSHA256 - dp, err = NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeKubeVirt, checksum) + dp, err = NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeKubeVirt, checksum, false) dp.brokenForQemuImg = true // Force TransferFile path Expect(err).NotTo(HaveOccurred()) @@ -332,7 +332,7 @@ var _ = Describe("Http data source", func() { image := ts.URL + "/" + cirrosFileName // Use an incorrect checksum incorrectChecksum := "sha256:2222222222222222222222222222222222222222222222222222222222222222" - dp, err = NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeKubeVirt, incorrectChecksum) + dp, err = NewHTTPDataSource(image, "", "", "", cdiv1.DataVolumeKubeVirt, incorrectChecksum, false) dp.brokenForQemuImg = true // Force TransferFile path Expect(err).NotTo(HaveOccurred()) @@ -353,7 +353,7 @@ var _ = Describe("Http data source", func() { Expect(os.Unsetenv(common.ImporterPullMethod)).To(Succeed()) }) - dp, err = NewHTTPDataSource(ts.URL+"/"+tinyCoreGz, "", "", "", cdiv1.DataVolumeKubeVirt, "") + dp, err = NewHTTPDataSource(ts.URL+"/"+tinyCoreGz, "", "", "", cdiv1.DataVolumeKubeVirt, "", false) Expect(err).NotTo(HaveOccurred()) termMsg := dp.GetTerminationMessage() @@ -368,7 +368,7 @@ var _ = Describe("Http data source", func() { ts2 := createTestServer(imageDir, emptyEnv) - dp, err = NewHTTPDataSource(ts2.URL+"/"+tinyCoreGz, "", "", "", cdiv1.DataVolumeKubeVirt, "") + dp, err = NewHTTPDataSource(ts2.URL+"/"+tinyCoreGz, "", "", "", cdiv1.DataVolumeKubeVirt, "", false) Expect(err).NotTo(HaveOccurred()) termMsg := dp.GetTerminationMessage() @@ -390,7 +390,7 @@ var _ = Describe("Http data source", func() { "INSTANCETYPE_KUBEVIRT_IO_DEFAULT_PREFERENCE=fedora", }) - dp, err = NewHTTPDataSource(ts2.URL+"/"+tinyCoreGz, "", "", "", cdiv1.DataVolumeKubeVirt, "") + dp, err = NewHTTPDataSource(ts2.URL+"/"+tinyCoreGz, "", "", "", cdiv1.DataVolumeKubeVirt, "", false) Expect(err).NotTo(HaveOccurred()) termMsg := dp.GetTerminationMessage() @@ -445,7 +445,7 @@ var _ = Describe("Http client", func() { var _ = Describe("Http reader", func() { It("should fail when passed an invalid cert directory", func() { - _, total, _, err := createHTTPReader(context.Background(), nil, "", "", "/invalid", nil, nil, cdiv1.DataVolumeKubeVirt) + _, total, _, err := createHTTPReader(context.Background(), nil, "", "", "/invalid", nil, nil, cdiv1.DataVolumeKubeVirt, false) Expect(err).To(HaveOccurred()) Expect(uint64(0)).To(Equal(total)) }) @@ -462,7 +462,7 @@ var _ = Describe("Http reader", func() { defer ts.Close() ep, err := url.Parse(ts.URL) Expect(err).ToNot(HaveOccurred()) - r, total, _, err := createHTTPReader(context.Background(), ep, "user", "password", "", nil, nil, cdiv1.DataVolumeKubeVirt) + r, total, _, err := createHTTPReader(context.Background(), ep, "user", "password", "", nil, nil, cdiv1.DataVolumeKubeVirt, false) Expect(err).ToNot(HaveOccurred()) Expect(uint64(25)).To(Equal(total)) err = r.Close() @@ -485,7 +485,7 @@ var _ = Describe("Http reader", func() { defer ts.Close() ep, err := url.Parse(ts.URL) Expect(err).ToNot(HaveOccurred()) - r, total, _, err := createHTTPReader(context.Background(), ep, "user", "password", "", nil, nil, cdiv1.DataVolumeKubeVirt) + r, total, _, err := createHTTPReader(context.Background(), ep, "user", "password", "", nil, nil, cdiv1.DataVolumeKubeVirt, false) Expect(err).ToNot(HaveOccurred()) Expect(uint64(25)).To(Equal(total)) err = r.Close() @@ -507,7 +507,7 @@ var _ = Describe("Http reader", func() { defer ts.Close() ep, err := url.Parse(ts.URL) Expect(err).ToNot(HaveOccurred()) - r, total, brokenForQemuImg, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt) + r, total, brokenForQemuImg, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt, false) Expect(brokenForQemuImg).To(BeFalse()) Expect(err).ToNot(HaveOccurred()) Expect(uint64(25)).To(Equal(total)) @@ -528,7 +528,7 @@ var _ = Describe("Http reader", func() { defer ts.Close() ep, err := url.Parse(ts.URL) Expect(err).ToNot(HaveOccurred()) - r, total, _, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt) + r, total, _, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt, false) Expect(err).ToNot(HaveOccurred()) Expect(uint64(0)).To(Equal(total)) err = r.Close() @@ -552,7 +552,7 @@ var _ = Describe("Http reader", func() { defer ts.Close() ep, err := url.Parse(ts.URL) Expect(err).ToNot(HaveOccurred()) - r, total, brokenForQemuImg, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt) + r, total, brokenForQemuImg, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt, false) Expect(brokenForQemuImg).To(BeTrue()) Expect(err).ToNot(HaveOccurred()) Expect(uint64(25)).To(Equal(total)) @@ -572,7 +572,7 @@ var _ = Describe("Http reader", func() { defer ts.Close() ep, err := url.Parse(ts.URL) Expect(err).ToNot(HaveOccurred()) - r, total, brokenForQemuImg, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt) + r, total, brokenForQemuImg, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt, false) Expect(brokenForQemuImg).To(BeTrue()) Expect(err).ToNot(HaveOccurred()) Expect(uint64(25)).To(Equal(total)) @@ -587,7 +587,7 @@ var _ = Describe("Http reader", func() { defer ts.Close() ep, err := url.Parse(ts.URL) Expect(err).ToNot(HaveOccurred()) - _, total, _, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt) + _, total, _, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt, false) Expect(err).To(HaveOccurred()) Expect(uint64(0)).To(Equal(total)) Expect("expected status code 200, got 500. Status: 500 Internal Server Error").To(Equal(err.Error())) @@ -604,7 +604,7 @@ var _ = Describe("Http reader", func() { defer ts.Close() ep, err := url.Parse(ts.URL) Expect(err).ToNot(HaveOccurred()) - r, total, _, err := createHTTPReader(context.Background(), ep, "", "", "", []string{"Extra-Header: 123"}, nil, cdiv1.DataVolumeKubeVirt) + r, total, _, err := createHTTPReader(context.Background(), ep, "", "", "", []string{"Extra-Header: 123"}, nil, cdiv1.DataVolumeKubeVirt, false) Expect(err).ToNot(HaveOccurred()) Expect(uint64(0)).To(Equal(total)) err = r.Close() diff --git a/pkg/operator/resources/crds_generated.go b/pkg/operator/resources/crds_generated.go index fcc831d950..0662a86984 100644 --- a/pkg/operator/resources/crds_generated.go +++ b/pkg/operator/resources/crds_generated.go @@ -5977,6 +5977,10 @@ spec: items: type: string type: array + insecureSkipVerify: + description: InsecureSkipVerify is a flag to skip + certificate verification for the HTTP endpoint + type: boolean secretExtraHeaders: description: SecretExtraHeaders is a list of Secret references, each containing an extra HTTP header @@ -6992,6 +6996,10 @@ spec: items: type: string type: array + insecureSkipVerify: + description: InsecureSkipVerify is a flag to skip certificate + verification for the HTTP endpoint + type: boolean secretExtraHeaders: description: SecretExtraHeaders is a list of Secret references, each containing an extra HTTP header that may include sensitive @@ -8082,6 +8090,10 @@ spec: items: type: string type: array + insecureSkipVerify: + description: InsecureSkipVerify is a flag to skip certificate + verification for the HTTP endpoint + type: boolean secretExtraHeaders: description: SecretExtraHeaders is a list of Secret references, each containing an extra HTTP header that may include sensitive diff --git a/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types.go b/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types.go index 5a374a5cc9..9fd0029363 100644 --- a/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types.go +++ b/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types.go @@ -261,6 +261,9 @@ type DataVolumeSourceHTTP struct { // If specified, the importer will verify the downloaded content matches this checksum // +optional Checksum string `json:"checksum,omitempty"` + // InsecureSkipVerify is a flag to skip certificate verification for the HTTP endpoint + // +optional + InsecureSkipVerify *bool `json:"insecureSkipVerify,omitempty"` } // DataVolumeSourceImageIO provides the parameters to create a Data Volume from an imageio source diff --git a/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_swagger_generated.go b/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_swagger_generated.go index 95f10d5718..e43b4c59a4 100644 --- a/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_swagger_generated.go +++ b/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/types_swagger_generated.go @@ -133,6 +133,7 @@ func (DataVolumeSourceHTTP) SwaggerDoc() map[string]string { "extraHeaders": "ExtraHeaders is a list of strings containing extra headers to include with HTTP transfer requests\n+optional", "secretExtraHeaders": "SecretExtraHeaders is a list of Secret references, each containing an extra HTTP header that may include sensitive information\n+optional", "checksum": "Checksum is the expected checksum of the file. Format: \"algorithm:hash\", e.g., \"sha256:1234abcd...\" or \"md5:5678efgh...\"\nSupported algorithms: md5, sha1, sha256, sha512\nIf specified, the importer will verify the downloaded content matches this checksum\n+optional", + "insecureSkipVerify": "InsecureSkipVerify is a flag to skip certificate verification for the HTTP endpoint\n+optional", } } diff --git a/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/zz_generated.deepcopy.go b/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/zz_generated.deepcopy.go index 45d26ca258..8652e98193 100644 --- a/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/zz_generated.deepcopy.go +++ b/staging/src/kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1/zz_generated.deepcopy.go @@ -1057,6 +1057,11 @@ func (in *DataVolumeSourceHTTP) DeepCopyInto(out *DataVolumeSourceHTTP) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.InsecureSkipVerify != nil { + in, out := &in.InsecureSkipVerify, &out.InsecureSkipVerify + *out = new(bool) + **out = **in + } return } From 3bdcb7f1ab7fd326cbcd21d4f703742efdb68099 Mon Sep 17 00:00:00 2001 From: xphyr Date: Mon, 8 Jun 2026 09:57:06 -0400 Subject: [PATCH 02/11] updated tests to check for working insecureSkipVerify Signed-off-by: xphyr --- pkg/importer/http-datasource_test.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/pkg/importer/http-datasource_test.go b/pkg/importer/http-datasource_test.go index 6d2237a339..d883aa0832 100644 --- a/pkg/importer/http-datasource_test.go +++ b/pkg/importer/http-datasource_test.go @@ -610,6 +610,30 @@ var _ = Describe("Http reader", func() { err = r.Close() Expect(err).ToNot(HaveOccurred()) }) + + It("should fail to connect to self signed cert", func() { + ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + })) + defer ts.Close() + ep, err := url.Parse(ts.URL) + Expect(err).ToNot(HaveOccurred()) + _, total, _, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt, false) + Expect(err).To(HaveOccurred()) + Expect(uint64(0)).To(Equal(total)) + }) + + It("should connect to self signed cert with insecureSkipVerify set to true", func() { + ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + })) + defer ts.Close() + ep, err := url.Parse(ts.URL) + Expect(err).ToNot(HaveOccurred()) + _, total, _, err := createHTTPReader(context.Background(), ep, "", "", "", nil, nil, cdiv1.DataVolumeKubeVirt, true) + Expect(err).ToNot(HaveOccurred()) + Expect(uint64(0)).To(Equal(total)) + }) }) var _ = Describe("http pollprogress", func() { From 8e9ba3452e582351cedcfa9ba5aef1c5f9364460 Mon Sep 17 00:00:00 2001 From: xphyr Date: Mon, 8 Jun 2026 16:03:38 -0400 Subject: [PATCH 03/11] adding in functional test Signed-off-by: xphyr --- tests/datavolume_test.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/datavolume_test.go b/tests/datavolume_test.go index 0010af3959..1cfe110b79 100644 --- a/tests/datavolume_test.go +++ b/tests/datavolume_test.go @@ -261,6 +261,13 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests", return dataVolume } + createHTTPSInsecureSkipVerifyDataVolume := func(dataVolumeName, size, url string) *cdiv1.DataVolume { + dataVolume := utils.NewDataVolumeWithHTTPImport(dataVolumeName, size, url) + insecureSkipVerify := true + dataVolume.Spec.Source.HTTP.InsecureSkipVerify = &insecureSkipVerify + return dataVolume + } + createHTTPSDataVolumeWeirdCertFilename := func(dataVolumeName, size, url string) *cdiv1.DataVolume { dataVolume := utils.NewDataVolumeWithHTTPImport(dataVolumeName, size, url) cm, err := utils.CreateCertConfigMapWeirdFilename(f.K8sClient, f.Namespace.Name, f.CdiInstallNs) @@ -1229,6 +1236,30 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests", Message: "checksum validation failed", Reason: "ChecksumError", }}), + Entry("succeed creating import dv with insecureSkipVerify defined", dataVolumeTestArguments{ + name: "dv-https-import-qcow2", + size: "1Gi", + url: httpsTinyCoreQcow2URL, + dvFunc: createHTTPSInsecureSkipVerifyDataVolume, + eventReason: dvc.ImportSucceeded, + phase: cdiv1.Succeeded, + checkPermissions: true, + readyCondition: &cdiv1.DataVolumeCondition{ + Type: cdiv1.DataVolumeReady, + Status: v1.ConditionTrue, + }, + boundCondition: &cdiv1.DataVolumeCondition{ + Type: cdiv1.DataVolumeBound, + Status: v1.ConditionTrue, + Message: "PVC dv-https-import-qcow2 Bound", + Reason: "Bound", + }, + runningCondition: &cdiv1.DataVolumeCondition{ + Type: cdiv1.DataVolumeRunning, + Status: v1.ConditionFalse, + Message: "Import Complete", + Reason: "Completed", + }}), ) savedVddkConfigMap := common.VddkConfigMap + "-saved" From 4649eeb47f4d3d39005a708f03623ada67dbf71d Mon Sep 17 00:00:00 2001 From: xphyr Date: Tue, 9 Jun 2026 10:21:58 -0400 Subject: [PATCH 04/11] updating docs to reflect the new insecureSkipVerify option Signed-off-by: xphyr --- doc/datavolumes.md | 3 ++- .../import-kubevirt-datavolume-skip-tls.yaml | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 manifests/example/import-kubevirt-datavolume-skip-tls.yaml diff --git a/doc/datavolumes.md b/doc/datavolumes.md index de377f7d49..9910f6cdec 100644 --- a/doc/datavolumes.md +++ b/doc/datavolumes.md @@ -121,7 +121,7 @@ spec: ## Source ### HTTP/S3/GCS/Registry source -DataVolumes are an abstraction on top of the annotations one can put on PVCs to trigger CDI. As such DVs have the notion of a 'source' that allows one to specify the source of the data. To import data from an external source, the source has to be either 'http' ,'S3', 'GCS' or 'registry'. If your source requires authentication, you can also pass in a `secretRef` to a Kubernetes [Secret](../manifests/example/endpoint-secret.yaml) containing the authentication information. TLS certificates for https/registry sources may be specified in a [ConfigMap](../manifests/example/cert-configmap.yaml) and referenced by `certConfigMap`. `secretRef` and `certConfigMap` must be in the same namespace as the DataVolume. +DataVolumes are an abstraction on top of the annotations one can put on PVCs to trigger CDI. As such DVs have the notion of a 'source' that allows one to specify the source of the data. To import data from an external source, the source has to be either 'http' ,'S3', 'GCS' or 'registry'. If your source requires authentication, you can also pass in a `secretRef` to a Kubernetes [Secret](../manifests/example/endpoint-secret.yaml) containing the authentication information. TLS certificates for https/registry sources may be specified in a [ConfigMap](../manifests/example/cert-configmap.yaml) and referenced by `certConfigMap`. `secretRef` and `certConfigMap` must be in the same namespace as the DataVolume. TLS verification can also be bypassed by applying `insecureSkipVerify: true` to the http source. ```yaml apiVersion: cdi.kubevirt.io/v1beta1 @@ -143,6 +143,7 @@ spec: [Get GCS example](../manifests/example/import-kubevirt-datavolume-gcs.yaml) [Get secret example](../manifests/example/endpoint-secret.yaml) [Get certificate example](../manifests/example/cert-configmap.yaml) +[Get insecureSkipVerify example](../manifests/example/import-kubevirt-datavolume-skip-tls.yaml) #### Checksum Validation For HTTP/HTTPS sources, you can specify a checksum to verify the integrity of the downloaded data. This helps ensure that the image has not been tampered with during transmission. The checksum field is optional but recommended for production environments. diff --git a/manifests/example/import-kubevirt-datavolume-skip-tls.yaml b/manifests/example/import-kubevirt-datavolume-skip-tls.yaml new file mode 100644 index 0000000000..8410892fca --- /dev/null +++ b/manifests/example/import-kubevirt-datavolume-skip-tls.yaml @@ -0,0 +1,14 @@ +# This example assumes you are using a default storage class +apiVersion: cdi.kubevirt.io/v1beta1 +kind: DataVolume +metadata: + name: my-data-volume +spec: + source: + http: + url: "https://172.16.15.6/iso/cirros-0.4.0-x86_64-disk.img" + insecureSkipVerify: true + storage: + resources: + requests: + storage: 500Mi From 02e1bee1e4f805dd6381699e7aeb32fa1fdeaf4d Mon Sep 17 00:00:00 2001 From: xphyr Date: Tue, 9 Jun 2026 15:31:54 -0400 Subject: [PATCH 05/11] simplifying the datavolume functional test Signed-off-by: xphyr --- tests/datavolume_test.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/datavolume_test.go b/tests/datavolume_test.go index 1cfe110b79..97c296215b 100644 --- a/tests/datavolume_test.go +++ b/tests/datavolume_test.go @@ -261,13 +261,6 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests", return dataVolume } - createHTTPSInsecureSkipVerifyDataVolume := func(dataVolumeName, size, url string) *cdiv1.DataVolume { - dataVolume := utils.NewDataVolumeWithHTTPImport(dataVolumeName, size, url) - insecureSkipVerify := true - dataVolume.Spec.Source.HTTP.InsecureSkipVerify = &insecureSkipVerify - return dataVolume - } - createHTTPSDataVolumeWeirdCertFilename := func(dataVolumeName, size, url string) *cdiv1.DataVolume { dataVolume := utils.NewDataVolumeWithHTTPImport(dataVolumeName, size, url) cm, err := utils.CreateCertConfigMapWeirdFilename(f.K8sClient, f.Namespace.Name, f.CdiInstallNs) @@ -1237,10 +1230,17 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests", Reason: "ChecksumError", }}), Entry("succeed creating import dv with insecureSkipVerify defined", dataVolumeTestArguments{ - name: "dv-https-import-qcow2", - size: "1Gi", - url: httpsTinyCoreQcow2URL, - dvFunc: createHTTPSInsecureSkipVerifyDataVolume, + // Using the httpsTinyCoreQcow2URL which has a self signed cert. + // This will fail without insecureSkipVerify set to true, but should succeed with it. + name: "dv-https-insecure-skip-verify-pass", + size: "1Gi", + url: httpsTinyCoreQcow2URL, + dvFunc: func(name, size, url string) *cdiv1.DataVolume { + dv := utils.NewDataVolumeWithHTTPImport(name, size, url) + insecureSkipVerify := true + dv.Spec.Source.HTTP.InsecureSkipVerify = &insecureSkipVerify + return dv + }, eventReason: dvc.ImportSucceeded, phase: cdiv1.Succeeded, checkPermissions: true, @@ -1251,7 +1251,7 @@ var _ = Describe("[vendor:cnv-qe@redhat.com][level:component]DataVolume tests", boundCondition: &cdiv1.DataVolumeCondition{ Type: cdiv1.DataVolumeBound, Status: v1.ConditionTrue, - Message: "PVC dv-https-import-qcow2 Bound", + Message: "PVC dv-https-insecure-skip-verify-pass Bound", Reason: "Bound", }, runningCondition: &cdiv1.DataVolumeCondition{ From 8b34ebdb268a09643523ff2aceb04cdbea8bd0ac Mon Sep 17 00:00:00 2001 From: xphyr Date: Wed, 10 Jun 2026 12:01:31 -0400 Subject: [PATCH 06/11] adding in unit test for validating proper handling of AnnInsecureSkipVerify Signed-off-by: xphyr --- pkg/controller/common/util_test.go | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/pkg/controller/common/util_test.go b/pkg/controller/common/util_test.go index 60521db4da..2ad852c63f 100644 --- a/pkg/controller/common/util_test.go +++ b/pkg/controller/common/util_test.go @@ -30,6 +30,38 @@ var _ = Describe("GetRequestedImageSize", func() { }) }) +var _ = Describe("UpdateHTTPAnnotations", func() { + It("Should set AnnInsecureSkipVerify to true when DataVolumeSourceHTTP.InsecureSkipVerify is true", func() { + insecureSkipVerify := true + annotations := map[string]string{} + UpdateHTTPAnnotations(annotations, &cdiv1.DataVolumeSourceHTTP{ + URL: "http://example.com", + InsecureSkipVerify: &insecureSkipVerify, + }) + Expect(annotations[AnnInsecureSkipVerify]).To(Equal("true")) + }) + + It("Should not set AnnInsecureSkipVerify when DataVolumeSourceHTTP.InsecureSkipVerify is false", func() { + insecureSkipVerify := false + annotations := map[string]string{} + UpdateHTTPAnnotations(annotations, &cdiv1.DataVolumeSourceHTTP{ + URL: "http://example.com", + InsecureSkipVerify: &insecureSkipVerify, + }) + _, exists := annotations[AnnInsecureSkipVerify] + Expect(exists).To(BeFalse()) + }) + + It("Should not set AnnInsecureSkipVerify when DataVolumeSourceHTTP.InsecureSkipVerify is absent", func() { + annotations := map[string]string{} + UpdateHTTPAnnotations(annotations, &cdiv1.DataVolumeSourceHTTP{ + URL: "http://example.com", + }) + _, exists := annotations[AnnInsecureSkipVerify] + Expect(exists).To(BeFalse()) + }) +}) + var _ = Describe("GetStorageClassByName", func() { It("Should return the default storage class name", func() { client := CreateClient( From 2aea8ad69706544fb03db7fafea59c5867aa2b81 Mon Sep 17 00:00:00 2001 From: Mark DeNeve <3779715+xphyr@users.noreply.github.com> Date: Wed, 10 Jun 2026 12:53:35 -0400 Subject: [PATCH 07/11] added unit test to import-controller around isSecureTLS function Signed-off-by: Mark DeNeve <3779715+xphyr@users.noreply.github.com> --- pkg/controller/import-controller_test.go | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pkg/controller/import-controller_test.go b/pkg/controller/import-controller_test.go index 24098bca51..570aad44f3 100644 --- a/pkg/controller/import-controller_test.go +++ b/pkg/controller/import-controller_test.go @@ -1256,6 +1256,32 @@ var _ = Describe("getInsecureTLS", func() { ) }) +var _ = Describe("isInsecureTLS", func() { + DescribeTable("should", func(source, insecureSkipVerify string, expected bool) { + annotations := map[string]string{ + cc.AnnSource: source, + } + if insecureSkipVerify != "" { + annotations[cc.AnnInsecureSkipVerify] = insecureSkipVerify + } + pvc := cc.CreatePvc("testPVC", "default", annotations, nil) + reconciler := createImportReconciler(pvc) + + cdiConfig := &cdiv1.CDIConfig{} + err := reconciler.client.Get(context.TODO(), types.NamespacedName{Name: common.ConfigName}, cdiConfig) + Expect(err).ToNot(HaveOccurred()) + + result, err := reconciler.isInsecureTLS(pvc, cdiConfig) + Expect(err).ToNot(HaveOccurred()) + Expect(result).To(Equal(expected)) + }, + Entry("return true when AnnInsecureSkipVerify is set to true for http source", cc.SourceHTTP, "true", true), + Entry("return true when AnnInsecureSkipVerify is set to true for imageio source", cc.SourceImageio, "true", true), + Entry("return false when AnnInsecureSkipVerify is not present for http source", cc.SourceHTTP, "", false), + Entry("return false when AnnInsecureSkipVerify is not present for imageio source", cc.SourceImageio, "", false), + ) +}) + var _ = Describe("GetContentType", func() { pvcNoAnno := cc.CreatePvc("testPVCNoAnno", "default", nil, nil) pvcArchiveAnno := cc.CreatePvc("testPVCArchiveAnno", "default", map[string]string{cc.AnnContentType: string(cdiv1.DataVolumeArchive)}, nil) From 32285f23da28bef202c894928fcc2a839e694d8a Mon Sep 17 00:00:00 2001 From: xphyr Date: Fri, 12 Jun 2026 05:51:00 -0400 Subject: [PATCH 08/11] working on new tests, still not quite there yet Signed-off-by: Mark DeNeve <3779715+xphyr@users.noreply.github.com> --- pkg/controller/import-controller_test.go | 57 ++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/pkg/controller/import-controller_test.go b/pkg/controller/import-controller_test.go index 570aad44f3..6ca9590fad 100644 --- a/pkg/controller/import-controller_test.go +++ b/pkg/controller/import-controller_test.go @@ -437,6 +437,63 @@ var _ = Describe("ImportConfig Controller reconcile loop", func() { Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Pod is not owned by PVC")) }) + + It("Should not set the InsecureTLS environment variable if the AnnInsecureSkipVerify annotation is set to false", func() { + pvc := cc.CreatePvc("testPvc1", "default", map[string]string{cc.AnnEndpoint: testEndPoint, cc.AnnImportPod: "importer-testPvc1", cc.AnnInsecureSkipVerify: "false"}, nil) + pvc.Status.Phase = v1.ClaimBound + reconciler = createImportReconciler(pvc) + _, err := reconciler.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "testPvc1", Namespace: "default"}}) + Expect(err).ToNot(HaveOccurred()) + pod := &corev1.Pod{} + err = reconciler.client.Get(context.TODO(), types.NamespacedName{Name: "importer-testPvc1", Namespace: "default"}, pod) + Expect(err).ToNot(HaveOccurred()) + foundAnnInsecureSkipVerify := false + for _, envVar := range pod.Spec.Containers[0].Env { + if envVar.Name == common.InsecureTLSVar { + foundAnnInsecureSkipVerify = true + Expect(envVar.Value).To(Equal("false")) + } + } + Expect(foundAnnInsecureSkipVerify).To(BeTrue()) + }) + + It("Should set the InsecureTLS environment variable to false if the AnnInsecureSkipVerify annotation is absent", func() { + pvc := cc.CreatePvc("testPvc1", "default", map[string]string{cc.AnnEndpoint: testEndPoint, cc.AnnImportPod: "importer-testPvc1"}, nil) + pvc.Status.Phase = v1.ClaimBound + reconciler = createImportReconciler(pvc) + _, err := reconciler.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "testPvc1", Namespace: "default"}}) + Expect(err).ToNot(HaveOccurred()) + pod := &corev1.Pod{} + err = reconciler.client.Get(context.TODO(), types.NamespacedName{Name: "importer-testPvc1", Namespace: "default"}, pod) + Expect(err).ToNot(HaveOccurred()) + foundAnnInsecureSkipVerify := false + for _, envVar := range pod.Spec.Containers[0].Env { + if envVar.Name == common.InsecureTLSVar { + foundAnnInsecureSkipVerify = true + Expect(envVar.Value).To(Equal("false")) + } + } + Expect(foundAnnInsecureSkipVerify).To(BeTrue()) + }) + + It("Should set the InsecureTLS environment variable to true if the AnnInsecureSkipVerify annotation is set to true", func() { + pvc := cc.CreatePvc("testPvc1", "default", map[string]string{cc.AnnEndpoint: testEndPoint, cc.AnnImportPod: "importer-testPvc1", cc.AnnInsecureSkipVerify: "true"}, nil) + pvc.Status.Phase = v1.ClaimBound + reconciler = createImportReconciler(pvc) + _, err := reconciler.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "testPvc1", Namespace: "default"}}) + Expect(err).ToNot(HaveOccurred()) + pod := &corev1.Pod{} + err = reconciler.client.Get(context.TODO(), types.NamespacedName{Name: "importer-testPvc1", Namespace: "default"}, pod) + Expect(err).ToNot(HaveOccurred()) + foundAnnInsecureSkipVerify := false + for _, envVar := range pod.Spec.Containers[0].Env { + if envVar.Name == common.InsecureTLSVar { + foundAnnInsecureSkipVerify = true + Expect(envVar.Value).To(Equal("true")) + } + } + Expect(foundAnnInsecureSkipVerify).To(BeTrue()) + }) }) var _ = Describe("Update PVC from POD", func() { From d7620a465249e1c3254fd3fe9c4ee9f65eae4229 Mon Sep 17 00:00:00 2001 From: Mark DeNeve <3779715+xphyr@users.noreply.github.com> Date: Fri, 12 Jun 2026 06:01:51 -0400 Subject: [PATCH 09/11] fixed the issue with my first unit test Signed-off-by: Mark DeNeve <3779715+xphyr@users.noreply.github.com> --- pkg/controller/import-controller_test.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pkg/controller/import-controller_test.go b/pkg/controller/import-controller_test.go index 6ca9590fad..51873948f5 100644 --- a/pkg/controller/import-controller_test.go +++ b/pkg/controller/import-controller_test.go @@ -477,7 +477,12 @@ var _ = Describe("ImportConfig Controller reconcile loop", func() { }) It("Should set the InsecureTLS environment variable to true if the AnnInsecureSkipVerify annotation is set to true", func() { - pvc := cc.CreatePvc("testPvc1", "default", map[string]string{cc.AnnEndpoint: testEndPoint, cc.AnnImportPod: "importer-testPvc1", cc.AnnInsecureSkipVerify: "true"}, nil) + pvc := cc.CreatePvc("testPvc1", "default", map[string]string{ + cc.AnnEndpoint: testEndPoint, + cc.AnnImportPod: "importer-testPvc1", + cc.AnnInsecureSkipVerify: "true", + cc.AnnSource: cc.SourceHTTP, + }, nil) pvc.Status.Phase = v1.ClaimBound reconciler = createImportReconciler(pvc) _, err := reconciler.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "testPvc1", Namespace: "default"}}) From e73d9a436ef1cfd097286cad66c08d0376080cff Mon Sep 17 00:00:00 2001 From: xphyr Date: Fri, 12 Jun 2026 05:51:00 -0400 Subject: [PATCH 10/11] working on new tests, still not quite there yet Signed-off-by: xphyr --- pkg/controller/import-controller_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/controller/import-controller_test.go b/pkg/controller/import-controller_test.go index 51873948f5..ee5ac10f7b 100644 --- a/pkg/controller/import-controller_test.go +++ b/pkg/controller/import-controller_test.go @@ -478,10 +478,10 @@ var _ = Describe("ImportConfig Controller reconcile loop", func() { It("Should set the InsecureTLS environment variable to true if the AnnInsecureSkipVerify annotation is set to true", func() { pvc := cc.CreatePvc("testPvc1", "default", map[string]string{ - cc.AnnEndpoint: testEndPoint, - cc.AnnImportPod: "importer-testPvc1", - cc.AnnInsecureSkipVerify: "true", - cc.AnnSource: cc.SourceHTTP, + cc.AnnEndpoint: testEndPoint, + cc.AnnImportPod: "importer-testPvc1", + cc.AnnInsecureSkipVerify: "true", + cc.AnnSource: cc.SourceHTTP, }, nil) pvc.Status.Phase = v1.ClaimBound reconciler = createImportReconciler(pvc) From ab328736641af58169c97d9f830929d49ea2ee97 Mon Sep 17 00:00:00 2001 From: xphyr Date: Mon, 6 Jul 2026 16:05:30 -0400 Subject: [PATCH 11/11] adding in additional tests from @akalenyu Signed-off-by: xphyr --- pkg/controller/import-controller_test.go | 6 ++- .../populators/import-populator_test.go | 38 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/pkg/controller/import-controller_test.go b/pkg/controller/import-controller_test.go index ee5ac10f7b..d0967bc205 100644 --- a/pkg/controller/import-controller_test.go +++ b/pkg/controller/import-controller_test.go @@ -439,7 +439,7 @@ var _ = Describe("ImportConfig Controller reconcile loop", func() { }) It("Should not set the InsecureTLS environment variable if the AnnInsecureSkipVerify annotation is set to false", func() { - pvc := cc.CreatePvc("testPvc1", "default", map[string]string{cc.AnnEndpoint: testEndPoint, cc.AnnImportPod: "importer-testPvc1", cc.AnnInsecureSkipVerify: "false"}, nil) + pvc := cc.CreatePvc("testPvc1", "default", map[string]string{cc.AnnEndpoint: testEndPoint, cc.AnnImportPod: "importer-testPvc1", cc.AnnInsecureSkipVerify: "false", cc.AnnSource: cc.SourceHTTP}, nil) pvc.Status.Phase = v1.ClaimBound reconciler = createImportReconciler(pvc) _, err := reconciler.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "testPvc1", Namespace: "default"}}) @@ -458,7 +458,7 @@ var _ = Describe("ImportConfig Controller reconcile loop", func() { }) It("Should set the InsecureTLS environment variable to false if the AnnInsecureSkipVerify annotation is absent", func() { - pvc := cc.CreatePvc("testPvc1", "default", map[string]string{cc.AnnEndpoint: testEndPoint, cc.AnnImportPod: "importer-testPvc1"}, nil) + pvc := cc.CreatePvc("testPvc1", "default", map[string]string{cc.AnnEndpoint: testEndPoint, cc.AnnImportPod: "importer-testPvc1", cc.AnnSource: cc.SourceHTTP}, nil) pvc.Status.Phase = v1.ClaimBound reconciler = createImportReconciler(pvc) _, err := reconciler.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: "testPvc1", Namespace: "default"}}) @@ -1339,7 +1339,9 @@ var _ = Describe("isInsecureTLS", func() { }, Entry("return true when AnnInsecureSkipVerify is set to true for http source", cc.SourceHTTP, "true", true), Entry("return true when AnnInsecureSkipVerify is set to true for imageio source", cc.SourceImageio, "true", true), + Entry("return false when AnnInsecureSkipVerify is set to false for http source", cc.SourceHTTP, "false", false), Entry("return false when AnnInsecureSkipVerify is not present for http source", cc.SourceHTTP, "", false), + Entry("return false when AnnInsecureSkipVerify is set to false for imageio source", cc.SourceImageio, "false", false), Entry("return false when AnnInsecureSkipVerify is not present for imageio source", cc.SourceImageio, "", false), ) }) diff --git a/pkg/controller/populators/import-populator_test.go b/pkg/controller/populators/import-populator_test.go index d2dd663fd6..6068f4bd52 100644 --- a/pkg/controller/populators/import-populator_test.go +++ b/pkg/controller/populators/import-populator_test.go @@ -285,6 +285,44 @@ var _ = Describe("Import populator tests", func() { Entry("retain pod annotation is passed", AnnPodRetainAfterCompletion, "true", "true"), ) + It("Should set AnnInsecureSkipVerify on PVC Prime when InsecureSkipVerify is true", func() { + targetPvc := CreatePvcInStorageClass(targetPvcName, metav1.NamespaceDefault, &sc.Name, map[string]string{}, nil, corev1.ClaimPending) + targetPvc.Spec.DataSourceRef = dataSourceRef + volumeImportSource := getVolumeImportSource(true, metav1.NamespaceDefault) + volumeImportSource.Spec.Source.HTTP.InsecureSkipVerify = ptr.To(true) + + By("Reconcile") + reconciler = createImportPopulatorReconciler(targetPvc, volumeImportSource, sc) + result, err := reconciler.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: targetPvcName, Namespace: metav1.NamespaceDefault}}) + Expect(err).To(Not(HaveOccurred())) + Expect(result).To(Not(BeNil())) + + By("Checking PVC' annotations") + pvcPrime, err := reconciler.getPVCPrime(targetPvc) + Expect(err).ToNot(HaveOccurred()) + Expect(pvcPrime).ToNot(BeNil()) + Expect(pvcPrime.GetAnnotations()[AnnInsecureSkipVerify]).To(Equal("true")) + }) + + It("Should not set AnnInsecureSkipVerify on PVC Prime when InsecureSkipVerify is not set", func() { + targetPvc := CreatePvcInStorageClass(targetPvcName, metav1.NamespaceDefault, &sc.Name, map[string]string{}, nil, corev1.ClaimPending) + targetPvc.Spec.DataSourceRef = dataSourceRef + volumeImportSource := getVolumeImportSource(true, metav1.NamespaceDefault) + + By("Reconcile") + reconciler = createImportPopulatorReconciler(targetPvc, volumeImportSource, sc) + result, err := reconciler.Reconcile(context.TODO(), reconcile.Request{NamespacedName: types.NamespacedName{Name: targetPvcName, Namespace: metav1.NamespaceDefault}}) + Expect(err).To(Not(HaveOccurred())) + Expect(result).To(Not(BeNil())) + + By("Checking PVC' annotations") + pvcPrime, err := reconciler.getPVCPrime(targetPvc) + Expect(err).ToNot(HaveOccurred()) + Expect(pvcPrime).ToNot(BeNil()) + _, exists := pvcPrime.GetAnnotations()[AnnInsecureSkipVerify] + Expect(exists).To(BeFalse()) + }) + It("Should not copy target PVC labels to PVC Prime", func() { targetPvc := CreatePvcInStorageClass(targetPvcName, metav1.NamespaceDefault, &sc.Name, map[string]string{}, map[string]string{"custom-label": "value"}, corev1.ClaimPending)