Skip to content

Commit

Permalink
OADP-639: Pass custom CA configuration to restic replication source. (#…
Browse files Browse the repository at this point in the history
…198)

Signed-off-by: Matthew Arnold <marnold@redhat.com>
  • Loading branch information
mrnold committed Apr 11, 2023
1 parent a1affb1 commit b1eedc1
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 5 deletions.
11 changes: 11 additions & 0 deletions controllers/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ const (
GoogleApplicationCredentials = "GOOGLE_APPLICATION_CREDENTIALS"

// Restic repo vars
ResticCustomCA = "RESTIC_CUSTOM_CA"
ResticPassword = "RESTIC_PASSWORD"
ResticRepository = "RESTIC_REPOSITORY"
ResticPruneInterval = "restic-prune-interval"
Expand Down Expand Up @@ -103,6 +104,7 @@ var (

GoogleApplicationCredentialsValue []byte

ResticCustomCAValue []byte
ResticPasswordValue []byte
ResticRepoValue string
ResticPruneIntervalValue []byte
Expand Down Expand Up @@ -161,6 +163,8 @@ func BuildResticSecret(givensecret *corev1.Secret, secret *corev1.Secret, restic
AWSDefaultRegionValue = val
case key == ResticPassword:
ResticPasswordValue = val
case key == ResticCustomCA:
ResticCustomCAValue = val
}
}

Expand All @@ -170,6 +174,7 @@ func BuildResticSecret(givensecret *corev1.Secret, secret *corev1.Secret, restic
AWSAccessKey: AWSAccessValue,
AWSSecretKey: AWSSecretValue,
AWSDefaultRegion: AWSDefaultRegionValue,
ResticCustomCA: ResticCustomCAValue,
ResticPassword: ResticPasswordValue,
ResticRepository: []byte(resticrepo),
ResticPruneInterval: []byte(pruneInterval),
Expand All @@ -188,6 +193,8 @@ func BuildResticSecret(givensecret *corev1.Secret, secret *corev1.Secret, restic
AzureAccountKeyValue = val
case key == ResticPassword:
ResticPasswordValue = val
case key == ResticCustomCA:
ResticCustomCAValue = val
}
}

Expand All @@ -196,6 +203,7 @@ func BuildResticSecret(givensecret *corev1.Secret, secret *corev1.Secret, restic
Data: map[string][]byte{
AzureAccountName: AzureAccountNameValue,
AzureAccountKey: AzureAccountKeyValue,
ResticCustomCA: ResticCustomCAValue,
ResticPassword: ResticPasswordValue,
ResticRepository: []byte(resticrepo),
ResticPruneInterval: []byte(pruneInterval),
Expand All @@ -212,13 +220,16 @@ func BuildResticSecret(givensecret *corev1.Secret, secret *corev1.Secret, restic
GoogleApplicationCredentialsValue = val
case key == ResticPassword:
ResticPasswordValue = val
case key == ResticCustomCA:
ResticCustomCAValue = val
}
}

// build new Restic secret
resticSecretData := &corev1.Secret{
Data: map[string][]byte{
GoogleApplicationCredentials: GoogleApplicationCredentialsValue,
ResticCustomCA: ResticCustomCAValue,
ResticPassword: ResticPasswordValue,
ResticRepository: []byte(resticrepo),
ResticPruneInterval: []byte(pruneInterval),
Expand Down
7 changes: 7 additions & 0 deletions controllers/replicationdestination.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ func (r *VolumeSnapshotRestoreReconciler) buildReplicationDestination(replicatio
replicationDestination.Spec = replicationDestinationSpec
}

// include custom CA if specified
resticCustomCA := resticSecret.Data[ResticCustomCA]
if len(resticCustomCA) > 0 {
replicationDestination.Spec.Restic.CustomCA.SecretName = resticSecret.Name
replicationDestination.Spec.Restic.CustomCA.Key = ResticCustomCA
}

return nil
}

Expand Down
68 changes: 68 additions & 0 deletions controllers/replicationdestination_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package controllers

import (
"context"
"fmt"
"testing"

controllerruntime "sigs.k8s.io/controller-runtime"
Expand Down Expand Up @@ -35,6 +36,7 @@ func TestVolumeSnapshotRestoreReconciler_buildReplicationDestination(t *testing.
Scheme *runtime.Scheme
want bool
wantErr bool
validate func(*volsyncv1alpha1.ReplicationDestination) error
}{
// TODO: Add test cases
{
Expand Down Expand Up @@ -201,6 +203,66 @@ func TestVolumeSnapshotRestoreReconciler_buildReplicationDestination(t *testing.
want: false,
wantErr: true,
},
{
name: "Should pass custom CA field through to restic secret",
vsr: &volsnapmoverv1alpha1.VolumeSnapshotRestore{
ObjectMeta: v1.ObjectMeta{
Name: "sample-vsr",
Namespace: "bar",
},
Spec: volsnapmoverv1alpha1.VolumeSnapshotRestoreSpec{
ResticSecretRef: corev1.LocalObjectReference{
Name: "secret",
},
VolumeSnapshotMoverBackupref: volsnapmoverv1alpha1.VSBRef{
BackedUpPVCData: volsnapmoverv1alpha1.PVCData{
Name: "test-pvc",
Size: "1G",
StorageClassName: "test-class",
},
},
ProtectedNamespace: "test-ns",
},
},
repDest: &volsyncv1alpha1.ReplicationDestination{
ObjectMeta: v1.ObjectMeta{
Name: "sample-vsb-rep-src",
Namespace: namespace,
},
},
secret: &corev1.Secret{
ObjectMeta: v1.ObjectMeta{
Name: "test-secret",
Namespace: "test-ns",
},
Data: map[string][]byte{
ResticCustomCA: []byte("test-secret"),
},
},
configMap: &corev1.ConfigMap{
ObjectMeta: v1.ObjectMeta{
Name: "datamover-config",
Namespace: namespace,
},
},
serviceAcct: &corev1.ServiceAccount{
ObjectMeta: v1.ObjectMeta{
Name: "velero",
Namespace: namespace,
},
},
want: true,
wantErr: false,
validate: func(rd *volsyncv1alpha1.ReplicationDestination) error {
if rd.Spec.Restic.CustomCA.Key != ResticCustomCA {
return fmt.Errorf("restic custom CA key name mismatch, got %s, expected %s", rd.Spec.Restic.CustomCA.Key, ResticCustomCA)
}
if rd.Spec.Restic.CustomCA.SecretName != "test-secret" {
return fmt.Errorf("restic custom CA secret name mismatch, got %s, expected %s", rd.Spec.Restic.CustomCA.SecretName, "test-secret")
}
return nil
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand All @@ -222,6 +284,12 @@ func TestVolumeSnapshotRestoreReconciler_buildReplicationDestination(t *testing.
if err == nil && tt.want && !tt.wantErr {
t.Logf("buildReplicationDestination() err = %v, wantErr %v", err, tt.wantErr)
}

if tt.validate != nil {
if err = tt.validate(tt.repDest); err != nil {
t.Errorf("validation error: %v", err)
}
}
})
}
}
7 changes: 7 additions & 0 deletions controllers/replicationsource.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,13 @@ func (r *VolumeSnapshotBackupReconciler) buildReplicationSource(replicationSourc
replicationSource.Spec = replicationSourceSpec
}

// pass along a custom CA if specified
resticCustomCA := resticSecret.Data[ResticCustomCA]
if len(resticCustomCA) > 0 {
replicationSource.Spec.Restic.CustomCA.SecretName = resticSecret.Name
replicationSource.Spec.Restic.CustomCA.Key = ResticCustomCA
}

return nil
}

Expand Down
84 changes: 79 additions & 5 deletions controllers/replicationsource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package controllers

import (
"context"
"fmt"
"testing"

controllerruntime "sigs.k8s.io/controller-runtime"
Expand All @@ -25,18 +26,19 @@ import (
const (
aws_access_key_id = "some_aws_access_key_id"
aws_secret_access_key = "some_aws_secret_access_key"
restic_custom_ca = "sample-vsb-secret"
restic_password = "some_restic_password"
restic_repo = "some_restic_repo"
namespace = "foo"
)

var (
secretData = map[string][]byte{
"data": []byte(
"AWS_ACCESS_KEY_ID:" + aws_access_key_id + "\n" +
"AWS_SECRET_ACCESS_KEY:" + aws_secret_access_key + "\n" +
"RESTIC_PASSWORD:" + restic_password + "\n" +
"RESTIC_REPOSITORY:" + restic_repo),
"AWS_ACCESS_KEY_ID": []byte(aws_access_key_id),
"AWS_SECRET_ACCESS_KEY": []byte(aws_secret_access_key),
"RESTIC_PASSWORD": []byte(restic_password),
"RESTIC_REPOSITORY": []byte(restic_repo),
"RESTIC_CUSTOM_CA": []byte(restic_custom_ca),
}
)

Expand Down Expand Up @@ -76,6 +78,7 @@ func TestVolumeSnapshotMoverBackupReconciler_BuildReplicationSource(t *testing.T
configMap *corev1.ConfigMap
serviceAcct *corev1.ServiceAccount
wantErr bool
validate func(*volsyncv1alpha1.ReplicationSource) error
}{
// TODO: Add test cases.
{
Expand Down Expand Up @@ -286,6 +289,71 @@ func TestVolumeSnapshotMoverBackupReconciler_BuildReplicationSource(t *testing.T
serviceAcct: nil,
wantErr: true,
},
{
name: "Should pass custom CA field through to restic secret",
vsb: &volsnapmoverv1alpha1.VolumeSnapshotBackup{
ObjectMeta: v1.ObjectMeta{
Name: "sample-vsb",
Namespace: "bar",
},
Spec: volsnapmoverv1alpha1.VolumeSnapshotBackupSpec{
VolumeSnapshotContent: corev1.ObjectReference{
Name: "sample-snapshot",
},
ProtectedNamespace: "foo",
},
},
pvc: &corev1.PersistentVolumeClaim{
ObjectMeta: v1.ObjectMeta{
Name: "sample-pvc",
Namespace: namespace,
},
Spec: corev1.PersistentVolumeClaimSpec{
AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce},
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceName(corev1.ResourceStorage): resource.MustParse("10Gi"),
},
},
},
},
secret: &corev1.Secret{
ObjectMeta: v1.ObjectMeta{
Name: restic_custom_ca,
Namespace: namespace,
},
Data: secretData,
},
repsrc: &volsyncv1alpha1.ReplicationSource{
ObjectMeta: v1.ObjectMeta{
Name: "sample-vsb-rep-src",
Namespace: namespace,
},
},
configMap: &corev1.ConfigMap{
ObjectMeta: v1.ObjectMeta{
Name: "datamover-config",
Namespace: namespace,
},
},
serviceAcct: &corev1.ServiceAccount{
ObjectMeta: v1.ObjectMeta{
Name: "velero",
Namespace: namespace,
},
},
wantErr: false,
validate: func(rs *volsyncv1alpha1.ReplicationSource) error {
t.Logf("Secret data: %s", secretData)
if rs.Spec.Restic.CustomCA.Key != ResticCustomCA {
return fmt.Errorf("restic custom CA key name mismatch, got %s, expected %s", rs.Spec.Restic.CustomCA.Key, ResticCustomCA)
}
if rs.Spec.Restic.CustomCA.SecretName != restic_custom_ca {
return fmt.Errorf("restic custom CA secret name mismatch, got %s, expected %s", rs.Spec.Restic.CustomCA.SecretName, restic_custom_ca)
}
return nil
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down Expand Up @@ -315,6 +383,12 @@ func TestVolumeSnapshotMoverBackupReconciler_BuildReplicationSource(t *testing.T
t.Errorf("VolumeSnapshotMoverBackupReconciler.buildReplicationSource() error = %v, wantErr %v", err, tt.wantErr)
return
}

if tt.validate != nil {
if err = tt.validate(tt.repsrc); err != nil {
t.Errorf("validation error: %v", err)
}
}
})
}
}
Expand Down

0 comments on commit b1eedc1

Please sign in to comment.