Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 43 additions & 6 deletions internal/controller/dataprotectiontest_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Comment thread
msfrucht marked this conversation as resolved.

// 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")
}
}
Expand Down Expand Up @@ -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
Expand All @@ -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)
}
Expand Down Expand Up @@ -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:
Expand All @@ -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 {
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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
}
Loading