diff --git a/internal/controller/dataprotectiontest_controller.go b/internal/controller/dataprotectiontest_controller.go index cf0955f2658..ec0ee8b6a56 100644 --- a/internal/controller/dataprotectiontest_controller.go +++ b/internal/controller/dataprotectiontest_controller.go @@ -142,9 +142,17 @@ func (r *DataProtectionTestReconciler) Reconcile(ctx context.Context, req ctrl.R return ctrl.Result{}, fmt.Errorf("resolved BackupLocationSpec is nil") } + // Retrieve the CAs if provided + caPEMData, err := r.retrieveCAData(ctx, resolvedBackupLocationSpec) + if err != nil { + logger.Error(err, "failed to retrieve CA data from BackupLocation") + r.updateDPTErrorStatus(ctx, fmt.Sprintf("failed to retrieve CA data from BackupLocation: %v", err)) + return ctrl.Result{}, fmt.Errorf("failed to retrieve CA data from BackupLocation: %w", err) + } + // Determine S3-compatible vendor (if applicable) if strings.EqualFold(resolvedBackupLocationSpec.Provider, AWSProvider) { - if err := r.determineVendor(ctx, r.dpt, resolvedBackupLocationSpec); err != nil { + if err := r.determineVendor(ctx, r.dpt, resolvedBackupLocationSpec, caPEMData); err != nil { logger.Error(err, "S3 vendor detection failed") } } @@ -219,7 +227,7 @@ func (r *DataProtectionTestReconciler) SetupWithManager(mgr ctrl.Manager) error // determineVendor sends a HEAD request to the provided s3Url in the BackupLocationSpec config, // extracts the Server header and known fallback headers to set the detected vendor (e.g., AWS, MinIO, Ceph) in the DPT status. // Only applicable for aws-compatible BSLs. -func (r *DataProtectionTestReconciler) determineVendor(ctx context.Context, dpt *oadpv1alpha1.DataProtectionTest, backupLocationSpec *velerov1.BackupStorageLocationSpec) error { +func (r *DataProtectionTestReconciler) determineVendor(ctx context.Context, dpt *oadpv1alpha1.DataProtectionTest, backupLocationSpec *velerov1.BackupStorageLocationSpec, caCertData []byte) error { s3Url := backupLocationSpec.Config["s3Url"] // Fallback to AWS default endpoint if missing @@ -242,7 +250,7 @@ func (r *DataProtectionTestReconciler) determineVendor(ctx context.Context, dpt } // Build HTTP client with TLS configuration - httpClient, err := buildHTTPClientWithTLS(dpt, backupLocationSpec, r.Log) + httpClient, err := buildHTTPClientWithTLS(dpt, backupLocationSpec, r.Log, caCertData) if err != nil { return fmt.Errorf("failed to build HTTP client with TLS: %w", err) } @@ -289,10 +297,14 @@ func (r *DataProtectionTestReconciler) initializeProvider(ctx context.Context, b providerName := strings.ToLower(backupLocationSpec.Provider) //TODO handle credential when not specified + caCertData, err := r.retrieveCAData(ctx, backupLocationSpec) + if err != nil { + return nil, fmt.Errorf("cannot retrieve CA Certificate data: %s", err.Error()) + } switch providerName { case AWSProvider: - return r.initializeAWSProvider(ctx, backupLocationSpec) + return r.initializeAWSProvider(ctx, backupLocationSpec, caCertData) case GCPProvider: return r.initializeGCPProvider(ctx, backupLocationSpec) case AzureProvider: @@ -304,7 +316,7 @@ func (r *DataProtectionTestReconciler) initializeProvider(ctx context.Context, b } // initializeAWSProvider initializes an AWS CloudProvider using credentials and configuration -func (r *DataProtectionTestReconciler) initializeAWSProvider(ctx context.Context, backupLocationSpec *velerov1.BackupStorageLocationSpec) (cloudprovider.CloudProvider, error) { +func (r *DataProtectionTestReconciler) initializeAWSProvider(ctx context.Context, backupLocationSpec *velerov1.BackupStorageLocationSpec, caCertData []byte) (cloudprovider.CloudProvider, error) { r.Log.Info("Initializing AWS provider") if backupLocationSpec.Credential == nil { @@ -353,7 +365,7 @@ func (r *DataProtectionTestReconciler) initializeAWSProvider(ctx context.Context } // Create AWS session with TLS configuration - sess, err := buildAWSSessionWithTLS(r.dpt, backupLocationSpec, region, s3Url, r.Log) + sess, err := buildAWSSessionWithTLS(r.dpt, backupLocationSpec, region, s3Url, r.Log, caCertData) if err != nil { return nil, fmt.Errorf("failed to create AWS session with TLS: %w", err) } @@ -714,3 +726,28 @@ func (r *DataProtectionTestReconciler) updateDPTStatusToComplete(ctx context.Con return r.Status().Update(ctx, latest) }) } + +// retrieveCAData returns the PEM-encoded CA certificate bytes for the given +// BackupStorageLocationSpec. CACertRef (a Secret reference) takes priority over +// the inline CACert field, matching Velero's own resolution order. +// Returns nil, nil when no CA data is configured. +func (r *DataProtectionTestReconciler) retrieveCAData(ctx context.Context, backupLocationSpec *velerov1.BackupStorageLocationSpec) ([]byte, error) { + if backupLocationSpec == nil || backupLocationSpec.ObjectStorage == nil { + return nil, nil + } + + ref := backupLocationSpec.ObjectStorage.CACertRef + if ref != nil { + secret, err := utils.GetProviderSecret(ref.Name, r.NamespacedName.Namespace, r.Client, ctx) + if err != nil { + return nil, err + } + data, found := secret.Data[ref.Key] + if !found { + return nil, fmt.Errorf("secret %q has no key %q", ref.Name, ref.Key) + } + return data, nil + } + + return backupLocationSpec.ObjectStorage.CACert, nil +} diff --git a/internal/controller/dataprotectiontest_controller_test.go b/internal/controller/dataprotectiontest_controller_test.go index 62c89b7a423..188f88cfa91 100644 --- a/internal/controller/dataprotectiontest_controller_test.go +++ b/internal/controller/dataprotectiontest_controller_test.go @@ -18,6 +18,9 @@ package controller import ( "context" + "crypto/x509" + "encoding/pem" + "errors" "fmt" "net/http" "net/http/httptest" @@ -29,6 +32,7 @@ import ( "github.com/stretchr/testify/require" velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1" corev1 "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" @@ -37,6 +41,7 @@ import ( oadpv1alpha1 "github.com/openshift/oadp-operator/api/v1alpha1" "github.com/openshift/oadp-operator/pkg/cloudprovider" + "github.com/openshift/oadp-operator/tests/e2e/lib" ) type mockProvider struct { @@ -56,11 +61,18 @@ func (m *mockProvider) GetBucketMetadata(ctx context.Context, bucket string, log } func TestDetermineVendor(t *testing.T) { + + caPEM, _, err := lib.GenerateSelfSignedCA() + if err != nil { + require.Fail(t, "Fail to generate test CA") + } + tests := []struct { name string serverHeader string extraHeaders map[string]string expectedVendor string + caCertData []byte }{ { name: "Detect AWS via Server header", @@ -111,6 +123,18 @@ func TestDetermineVendor(t *testing.T) { serverHeader: "", expectedVendor: "Unknown", }, + { + name: "With CA Certificate to unknown s3-compatible", + serverHeader: "SomethingElse", + expectedVendor: "somethingelse", + caCertData: caPEM, + }, + { + name: "With CA Certificate to Minio", + serverHeader: "MinIO", + expectedVendor: "MinIO", + caCertData: caPEM, + }, } for _, tc := range tests { @@ -139,7 +163,7 @@ func TestDetermineVendor(t *testing.T) { reconciler := &DataProtectionTestReconciler{} - err := reconciler.determineVendor(context.Background(), dpt, dpt.Spec.BackupLocationSpec) + err := reconciler.determineVendor(context.Background(), dpt, dpt.Spec.BackupLocationSpec, tc.caCertData) require.NoError(t, err) require.Equal(t, tc.expectedVendor, dpt.Status.S3Vendor) }) @@ -529,12 +553,20 @@ func TestCreateVolumeSnapshot(t *testing.T) { } func TestBuildTLSConfig(t *testing.T) { + + caPEM, _, err := lib.GenerateSelfSignedCA() + if err != nil { + require.Fail(t, "Failed to generate CA Certificate for testing.") + } + tests := []struct { name string dpt *oadpv1alpha1.DataProtectionTest bsl *velerov1.BackupStorageLocationSpec + caCertData []byte expectInsecure bool expectCustomCA bool + expectCA []byte expectError bool description string }{ @@ -570,6 +602,7 @@ func TestBuildTLSConfig(t *testing.T) { expectCustomCA: false, // Should not set custom CA when skipTLSVerify is true expectError: false, description: "SkipTLSVerify should take precedence over CA cert", + caCertData: []byte("some-ca-cert"), // Should be ignored due to skipTLSVerify, }, { name: "neither skipTLS nor custom CA", @@ -601,12 +634,52 @@ func TestBuildTLSConfig(t *testing.T) { StorageType: velerov1.StorageType{ ObjectStorage: &velerov1.ObjectStorageLocation{ Bucket: "test-bucket", - CACert: []byte("invalid-base64!"), }, }, }, expectError: true, description: "Should error on invalid base64 CA cert", + caCertData: []byte("invalid-base64!"), + }, + { + name: "with CA Cert from param", + dpt: &oadpv1alpha1.DataProtectionTest{ + Spec: oadpv1alpha1.DataProtectionTestSpec{ + SkipTLSVerify: false, + }, + }, + bsl: &velerov1.BackupStorageLocationSpec{ + StorageType: velerov1.StorageType{ + ObjectStorage: &velerov1.ObjectStorageLocation{ + Bucket: "test-bucket", + }, + }, + }, + expectCustomCA: true, + expectError: false, + expectCA: caPEM, + description: "Should configure custom CA cert in RootCAs passed in from param", + caCertData: caPEM, + }, + { + name: "with CA Cert inline BSL", + dpt: &oadpv1alpha1.DataProtectionTest{ + Spec: oadpv1alpha1.DataProtectionTestSpec{ + SkipTLSVerify: false, + }, + }, + bsl: &velerov1.BackupStorageLocationSpec{ + StorageType: velerov1.StorageType{ + ObjectStorage: &velerov1.ObjectStorageLocation{ + Bucket: "test-bucket", + CACert: caPEM, + }, + }, + }, + expectCustomCA: true, + expectError: false, + description: "Should configure custom CA cert in RootCAs from BSL", + expectCA: caPEM, }, } @@ -614,7 +687,7 @@ func TestBuildTLSConfig(t *testing.T) { t.Run(tt.name, func(t *testing.T) { logger := logr.Discard() - tlsConfig, err := buildTLSConfig(tt.dpt, tt.bsl, logger) + tlsConfig, err := buildTLSConfig(tt.dpt, tt.bsl, logger, tt.caCertData) if tt.expectError { require.Error(t, err) @@ -627,19 +700,36 @@ func TestBuildTLSConfig(t *testing.T) { if tt.expectCustomCA { require.NotNil(t, tlsConfig.RootCAs) - } else if !tt.expectInsecure { - // System certs case - RootCAs should be nil (uses system) - require.Nil(t, tlsConfig.RootCAs) + } + + if tt.expectInsecure { + // RootCAs field is ignored when set to insecure + require.Equal(t, tlsConfig.InsecureSkipVerify, true) + } + + if tt.expectCustomCA && !tt.expectError { + block, _ := pem.Decode(tt.expectCA) + require.NotNil(t, block, "expectCA should be a valid PEM block") + cert, parseErr := x509.ParseCertificate(block.Bytes) + require.NoError(t, parseErr, "expectCA should contain a parseable certificate") + _, verifyErr := cert.Verify(x509.VerifyOptions{Roots: tlsConfig.RootCAs}) + require.NoError(t, verifyErr, "generated CA cert should be trusted by tlsConfig.RootCAs") } }) } } func TestBuildHTTPClientWithTLS(t *testing.T) { + caPEM, _, err := lib.GenerateSelfSignedCA() + if err != nil { + require.Fail(t, "Failed to generate CA certificate for testing.") + } + tests := []struct { name string dpt *oadpv1alpha1.DataProtectionTest bsl *velerov1.BackupStorageLocationSpec + caCertData []byte expectError bool }{ { @@ -653,7 +743,22 @@ func TestBuildHTTPClientWithTLS(t *testing.T) { expectError: false, }, { - name: "invalid CA cert", + name: "invalid CA cert from param", + dpt: &oadpv1alpha1.DataProtectionTest{ + Spec: oadpv1alpha1.DataProtectionTestSpec{ + SkipTLSVerify: false, + }, + }, + bsl: &velerov1.BackupStorageLocationSpec{ + StorageType: velerov1.StorageType{ + ObjectStorage: &velerov1.ObjectStorageLocation{}, + }, + }, + expectError: true, + caCertData: []byte("invalid-base64!"), + }, + { + name: "invalid CA cert from bsl", dpt: &oadpv1alpha1.DataProtectionTest{ Spec: oadpv1alpha1.DataProtectionTestSpec{ SkipTLSVerify: false, @@ -668,13 +773,44 @@ func TestBuildHTTPClientWithTLS(t *testing.T) { }, expectError: true, }, + { + name: "valid generated CA cert from bsl", + dpt: &oadpv1alpha1.DataProtectionTest{ + Spec: oadpv1alpha1.DataProtectionTestSpec{ + SkipTLSVerify: false, + }, + }, + bsl: &velerov1.BackupStorageLocationSpec{ + StorageType: velerov1.StorageType{ + ObjectStorage: &velerov1.ObjectStorageLocation{ + CACert: caPEM, + }, + }, + }, + expectError: false, + }, + { + name: "valid generated CA cert from param", + dpt: &oadpv1alpha1.DataProtectionTest{ + Spec: oadpv1alpha1.DataProtectionTestSpec{ + SkipTLSVerify: false, + }, + }, + bsl: &velerov1.BackupStorageLocationSpec{ + StorageType: velerov1.StorageType{ + ObjectStorage: &velerov1.ObjectStorageLocation{}, + }, + }, + caCertData: caPEM, + expectError: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { logger := logr.Discard() - client, err := buildHTTPClientWithTLS(tt.dpt, tt.bsl, logger) + client, err := buildHTTPClientWithTLS(tt.dpt, tt.bsl, logger, tt.caCertData) if tt.expectError { require.Error(t, err) @@ -689,12 +825,18 @@ func TestBuildHTTPClientWithTLS(t *testing.T) { } func TestBuildAWSSessionWithTLS(t *testing.T) { + caPEM, _, err := lib.GenerateSelfSignedCA() + if err != nil { + require.Fail(t, "Failed to generate CA certificate for testing.") + } + tests := []struct { name string dpt *oadpv1alpha1.DataProtectionTest bsl *velerov1.BackupStorageLocationSpec region string endpoint string + caCertData []byte expectError bool }{ { @@ -737,15 +879,33 @@ func TestBuildAWSSessionWithTLS(t *testing.T) { }, region: "us-east-1", endpoint: "", + caCertData: []byte("invalid-base64!"), expectError: true, }, + { + name: "valid generated CA cert", + dpt: &oadpv1alpha1.DataProtectionTest{ + Spec: oadpv1alpha1.DataProtectionTestSpec{ + SkipTLSVerify: false, + }, + }, + bsl: &velerov1.BackupStorageLocationSpec{ + StorageType: velerov1.StorageType{ + ObjectStorage: &velerov1.ObjectStorageLocation{}, + }, + }, + region: "us-east-1", + endpoint: "", + caCertData: caPEM, + expectError: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { logger := logr.Discard() - session, err := buildAWSSessionWithTLS(tt.dpt, tt.bsl, tt.region, tt.endpoint, logger) + session, err := buildAWSSessionWithTLS(tt.dpt, tt.bsl, tt.region, tt.endpoint, logger, tt.caCertData) if tt.expectError { require.Error(t, err) @@ -1184,3 +1344,160 @@ func TestRunSnapshotTests(t *testing.T) { }) } } + +func TestRetrieveCAData(t *testing.T) { + scheme := runtime.NewScheme() + require.NoError(t, oadpv1alpha1.AddToScheme(scheme)) + require.NoError(t, snapshotv1api.AddToScheme(scheme)) + require.NoError(t, corev1.AddToScheme(scheme)) + + namespace := "dpt-test" + + tests := []struct { + name string + bsl *velerov1.BackupStorageLocationSpec + startingSecret *v1.Secret + expectError error + expectBytes []byte + }{ + { + name: "no bsl spec", + }, + { + name: "no ca certificate", + bsl: &velerov1.BackupStorageLocationSpec{}, + }, + { + name: "inline ca certificate", + bsl: &velerov1.BackupStorageLocationSpec{ + StorageType: velerov1.StorageType{ + ObjectStorage: &velerov1.ObjectStorageLocation{ + CACert: []byte("bad ca data"), + }, + }, + }, + expectBytes: []byte("bad ca data"), + }, + { + name: "ca cert ref", + bsl: &velerov1.BackupStorageLocationSpec{ + StorageType: velerov1.StorageType{ + ObjectStorage: &velerov1.ObjectStorageLocation{ + CACertRef: &v1.SecretKeySelector{ + Key: "ca", + LocalObjectReference: v1.LocalObjectReference{ + Name: "casecret", + }, + }, + }, + }, + }, + startingSecret: &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "casecret", + Namespace: namespace, + }, + Data: map[string][]byte{ + "ca": []byte("more bad ca data"), + }, + }, + expectBytes: []byte("more bad ca data"), + }, + { + name: "missing ca cert ref secret", + bsl: &velerov1.BackupStorageLocationSpec{ + StorageType: velerov1.StorageType{ + ObjectStorage: &velerov1.ObjectStorageLocation{ + CACertRef: &v1.SecretKeySelector{ + Key: "ca", + LocalObjectReference: v1.LocalObjectReference{ + Name: "casecret", + }, + }, + }, + }, + }, + expectError: errors.New("secrets \"casecret\" not found"), + }, + { + name: "ca cert secret has no data", + bsl: &velerov1.BackupStorageLocationSpec{ + StorageType: velerov1.StorageType{ + ObjectStorage: &velerov1.ObjectStorageLocation{ + CACertRef: &v1.SecretKeySelector{ + Key: "ca", + LocalObjectReference: v1.LocalObjectReference{ + Name: "casecret", + }, + }, + }, + }, + }, + startingSecret: &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "casecret", + Namespace: namespace, + }, + Data: map[string][]byte{}, + }, + expectError: errors.New("secret casecret has no data"), + }, + { + name: "ca cert ref points to wrong key", + bsl: &velerov1.BackupStorageLocationSpec{ + StorageType: velerov1.StorageType{ + ObjectStorage: &velerov1.ObjectStorageLocation{ + CACertRef: &v1.SecretKeySelector{ + Key: "ca", + LocalObjectReference: v1.LocalObjectReference{ + Name: "casecret", + }, + }, + }, + }, + }, + startingSecret: &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "casecret", + Namespace: namespace, + }, + Data: map[string][]byte{ + "wrongkey": []byte("not a valid ca"), + }, + }, + expectError: errors.New("secret \"casecret\" has no key \"ca\""), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + + builder := fake.NewClientBuilder().WithScheme(scheme) + if tt.startingSecret != nil { + builder = builder.WithObjects(tt.startingSecret) + } + fakeClient := builder.Build() + + reconciler := &DataProtectionTestReconciler{ + Client: fakeClient, + ClusterWideClient: fakeClient, + Log: logr.Discard(), + NamespacedName: types.NamespacedName{Namespace: namespace, Name: "test-obj"}, + Context: ctx, + } + + caData, err := reconciler.retrieveCAData(reconciler.Context, tt.bsl) + + if tt.expectError == nil { + require.NoError(t, err, "test should not error") + } else { + require.Error(t, err, "test should have errored") + require.Contains(t, err.Error(), tt.expectError.Error(), "error text did not contain required value") + } + + require.Equal(t, tt.expectBytes, caData, "retrieved data of CA not as expected") + }) + } + +} diff --git a/internal/controller/tls_config.go b/internal/controller/tls_config.go index 8926bda596c..f70cefc28ec 100644 --- a/internal/controller/tls_config.go +++ b/internal/controller/tls_config.go @@ -33,9 +33,9 @@ import ( // buildTLSConfig creates a TLS configuration based on the DPT spec and BSL spec. // Priority order: // 1. If skipTLSVerify is true → InsecureSkipVerify: true -// 2. If BSL has caCert → Use custom CA cert +// 2. If BSL has caCert → Use custom CA cert with system certs // 3. Otherwise → Use system certs (default) -func buildTLSConfig(dpt *oadpv1alpha1.DataProtectionTest, bsl *velerov1.BackupStorageLocationSpec, logger logr.Logger) (*tls.Config, error) { +func buildTLSConfig(dpt *oadpv1alpha1.DataProtectionTest, bsl *velerov1.BackupStorageLocationSpec, logger logr.Logger, caCertData []byte) (*tls.Config, error) { tlsConfig := &tls.Config{} // Priority 1: Check if skipTLSVerify is set @@ -45,32 +45,37 @@ func buildTLSConfig(dpt *oadpv1alpha1.DataProtectionTest, bsl *velerov1.BackupSt return tlsConfig, nil } - // Priority 2: Check for custom CA cert in BSL - if bsl != nil && bsl.ObjectStorage != nil && bsl.ObjectStorage.CACert != nil { - logger.Info("Custom CA certificate found in BSL") + // Priority 3: Load default system CA certificates. + caCertPool, err := x509.SystemCertPool() + if err != nil { + return nil, fmt.Errorf("failed to load system certificate pool %v", err) + } - // Use the PEM certificate directly (already decoded by Kubernetes) - caCertPEM := bsl.ObjectStorage.CACert + // Priority 2: Check for custom CA cert in retrieved by the controller from BSL or SecretKeySelector and append. + // caCertData should be passed as parameter to handle the BSL CAData and CACertRef fields + if len(caCertData) > 0 { + logger.Info("Custom CA certificate found in param") - // Create certificate pool with custom CA - caCertPool := x509.NewCertPool() - if !caCertPool.AppendCertsFromPEM(caCertPEM) { - return nil, fmt.Errorf("failed to parse CA certificate") + if !caCertPool.AppendCertsFromPEM(caCertData) { + return nil, fmt.Errorf("failed to parse CA certificates from param") } - tlsConfig.RootCAs = caCertPool - logger.Info("Successfully configured custom CA certificate") - return tlsConfig, nil + logger.Info("Successfully configured custom CA certificate from param") + } else if bsl != nil && bsl.ObjectStorage != nil && len(bsl.ObjectStorage.CACert) > 0 { + logger.Info("Custom CA certificate found in BSL") + if !caCertPool.AppendCertsFromPEM(bsl.ObjectStorage.CACert) { + return nil, fmt.Errorf("failed to parse CA certificates from BSL") + } + logger.Info("Successfully configured custom CA certificate from BSL") } - // Priority 3: Use system certificates (default behavior) - logger.Info("Using system default certificates") + tlsConfig.RootCAs = caCertPool return tlsConfig, nil } // buildHTTPClientWithTLS creates an HTTP client with the appropriate TLS configuration -func buildHTTPClientWithTLS(dpt *oadpv1alpha1.DataProtectionTest, bsl *velerov1.BackupStorageLocationSpec, logger logr.Logger) (*http.Client, error) { - tlsConfig, err := buildTLSConfig(dpt, bsl, logger) +func buildHTTPClientWithTLS(dpt *oadpv1alpha1.DataProtectionTest, bsl *velerov1.BackupStorageLocationSpec, logger logr.Logger, caCertData []byte) (*http.Client, error) { + tlsConfig, err := buildTLSConfig(dpt, bsl, logger, caCertData) if err != nil { return nil, fmt.Errorf("failed to build TLS config: %w", err) } @@ -87,8 +92,8 @@ func buildHTTPClientWithTLS(dpt *oadpv1alpha1.DataProtectionTest, bsl *velerov1. } // buildAWSSessionWithTLS creates an AWS session with the appropriate TLS configuration -func buildAWSSessionWithTLS(dpt *oadpv1alpha1.DataProtectionTest, bsl *velerov1.BackupStorageLocationSpec, region, endpoint string, logger logr.Logger) (*session.Session, error) { - tlsConfig, err := buildTLSConfig(dpt, bsl, logger) +func buildAWSSessionWithTLS(dpt *oadpv1alpha1.DataProtectionTest, bsl *velerov1.BackupStorageLocationSpec, region, endpoint string, logger logr.Logger, caCertData []byte) (*session.Session, error) { + tlsConfig, err := buildTLSConfig(dpt, bsl, logger, caCertData) if err != nil { return nil, fmt.Errorf("failed to build TLS config: %w", err) }