Skip to content

Commit

Permalink
Load credentials and pass through via config
Browse files Browse the repository at this point in the history
Update NewObjectBackupStore to take a CredentialsGetter which can be
used to get the credentials for a BackupStorageLocation if it has been
configured with a Credential. If the BSL has a credential, use that
SecretKeySelector to fetch the secret, write the contents to a temp file
and then pass that file through to the plugin via the config map. This
relies on the plugin being able to use the config field.

This does not yet handle VolumeSnapshotLocations or ResticRepositories.

Signed-off-by: Bridget McErlean <[email protected]>
  • Loading branch information
zubron committed Feb 10, 2021
1 parent b4154da commit bb31046
Show file tree
Hide file tree
Showing 20 changed files with 432 additions and 62 deletions.
19 changes: 18 additions & 1 deletion pkg/builder/backup_storage_location_builder.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2020 the Velero contributors.
Copyright the Velero contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -19,6 +19,8 @@ package builder
import (
"time"

corev1api "k8s.io/api/core/v1"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
Expand Down Expand Up @@ -83,6 +85,15 @@ func (b *BackupStorageLocationBuilder) Prefix(val string) *BackupStorageLocation
return b
}

// CACert sets the BackupStorageLocation's object storage CACert.
func (b *BackupStorageLocationBuilder) CACert(val []byte) *BackupStorageLocationBuilder {
if b.object.Spec.StorageType.ObjectStorage == nil {
b.object.Spec.StorageType.ObjectStorage = new(velerov1api.ObjectStorageLocation)
}
b.object.Spec.ObjectStorage.CACert = val
return b
}

// Default sets the BackupStorageLocation's is default or not
func (b *BackupStorageLocationBuilder) Default(isDefault bool) *BackupStorageLocationBuilder {
b.object.Spec.Default = isDefault
Expand Down Expand Up @@ -112,3 +123,9 @@ func (b *BackupStorageLocationBuilder) Phase(phase velerov1api.BackupStorageLoca
b.object.Status.Phase = phase
return b
}

// Credential sets the BackupStorageLocation's credential selector.
func (b *BackupStorageLocationBuilder) Credential(selector *corev1api.SecretKeySelector) *BackupStorageLocationBuilder {
b.object.Spec.Credential = selector
return b
}
20 changes: 14 additions & 6 deletions pkg/cmd/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ import (
"github.com/vmware-tanzu/velero/pkg/cmd"
"github.com/vmware-tanzu/velero/pkg/cmd/util/flag"
"github.com/vmware-tanzu/velero/pkg/cmd/util/signals"
"github.com/vmware-tanzu/velero/pkg/credentials"
"github.com/vmware-tanzu/velero/pkg/util/filesystem"

"github.com/vmware-tanzu/velero/pkg/controller"
velerodiscovery "github.com/vmware-tanzu/velero/pkg/discovery"
Expand Down Expand Up @@ -547,6 +549,12 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string
newPluginManager := func(logger logrus.FieldLogger) clientmgmt.Manager {
return clientmgmt.NewManager(logger, s.logLevel, s.pluginRegistry)
}

credentialFileStore, err := credentials.NewNamespacedFileStore(s.mgr.GetClient(), s.namespace, "/tmp/credentials/", filesystem.NewFileSystem())
cmd.CheckError(err)

backupStoreGetter := persistence.NewObjectBackupStoreGetter(credentialFileStore)

csiVSLister, csiVSCLister := s.getCSISnapshotListers()

backupSyncControllerRunInfo := func() controllerRunInfo {
Expand All @@ -561,7 +569,7 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string
s.kubeClient,
s.config.defaultBackupLocation,
newPluginManager,
persistence.NewObjectBackupStoreGetter(),
backupStoreGetter,
s.logger,
)

Expand Down Expand Up @@ -604,7 +612,7 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string
s.config.formatFlag.Parse(),
csiVSLister,
csiVSCLister,
persistence.NewObjectBackupStoreGetter(),
backupStoreGetter,
)

return controllerRunInfo{
Expand Down Expand Up @@ -661,7 +669,7 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string
csiVSCLister,
s.csiSnapshotClient,
newPluginManager,
persistence.NewObjectBackupStoreGetter(),
backupStoreGetter,
s.metrics,
s.discoveryHelper,
)
Expand Down Expand Up @@ -699,7 +707,7 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string
s.logger,
s.logLevel,
newPluginManager,
persistence.NewObjectBackupStoreGetter(),
backupStoreGetter,
s.metrics,
s.config.formatFlag.Parse(),
)
Expand Down Expand Up @@ -734,7 +742,7 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string
s.mgr.GetClient(),
s.sharedInformerFactory.Velero().V1().Backups().Lister(),
newPluginManager,
persistence.NewObjectBackupStoreGetter(),
backupStoreGetter,
s.logger,
)

Expand Down Expand Up @@ -813,7 +821,7 @@ func (s *server) runControllers(defaultVolumeSnapshotLocations map[string]string
ServerValidationFrequency: s.config.storeValidationFrequency,
},
NewPluginManager: newPluginManager,
BackupStoreGetter: persistence.NewObjectBackupStoreGetter(),
BackupStoreGetter: backupStoreGetter,
Log: s.logger,
}
if err := bslr.SetupWithManager(s.mgr); err != nil {
Expand Down
5 changes: 2 additions & 3 deletions pkg/controller/backup_deletion_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ import (
"github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/fake"
informers "github.com/vmware-tanzu/velero/pkg/generated/informers/externalversions"
"github.com/vmware-tanzu/velero/pkg/metrics"
"github.com/vmware-tanzu/velero/pkg/persistence"
persistencemocks "github.com/vmware-tanzu/velero/pkg/persistence/mocks"
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt"
pluginmocks "github.com/vmware-tanzu/velero/pkg/plugin/mocks"
Expand Down Expand Up @@ -75,7 +74,7 @@ func TestBackupDeletionControllerProcessQueueItem(t *testing.T) {
nil, // csiSnapshotContentLister
nil, // csiSnapshotClient
nil, // new plugin manager func
persistence.NewObjectBackupStoreGetter(),
nil, // backupStoreGetter
metrics.NewServerMetrics(),
nil, // discovery helper
).(*backupDeletionController)
Expand Down Expand Up @@ -1131,7 +1130,7 @@ func TestBackupDeletionControllerDeleteExpiredRequests(t *testing.T) {
nil, // csiSnapshotContentLister
nil, // csiSnapshotClient
nil, // new plugin manager func
persistence.NewObjectBackupStoreGetter(),
nil, // backupStoreGetter
metrics.NewServerMetrics(),
nil, // discovery helper,
).(*backupDeletionController)
Expand Down
3 changes: 2 additions & 1 deletion pkg/controller/backup_storage_location_controller.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2020 the Velero contributors.
Copyright the Velero contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -42,6 +42,7 @@ type BackupStorageLocationReconciler struct {
Client client.Client
Scheme *runtime.Scheme
DefaultBackupLocationInfo storage.DefaultBackupLocationInfo

// use variables to refer to these functions so they can be
// replaced with fakes for testing.
NewPluginManager func(logrus.FieldLogger) clientmgmt.Manager
Expand Down
6 changes: 2 additions & 4 deletions pkg/controller/backup_sync_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import (
"testing"
"time"

"github.com/vmware-tanzu/velero/pkg/persistence"

"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -573,7 +571,7 @@ func TestDeleteOrphanedBackups(t *testing.T) {
nil, // kubeClient
"",
nil, // new plugin manager func
persistence.NewObjectBackupStoreGetter(),
nil, // backupStoreGetter
velerotest.NewLogger(),
).(*backupSyncController)

Expand Down Expand Up @@ -667,7 +665,7 @@ func TestStorageLabelsInDeleteOrphanedBackups(t *testing.T) {
nil, // kubeClient
"",
nil, // new plugin manager func
persistence.NewObjectBackupStoreGetter(),
nil, // backupStoreGetter
velerotest.NewLogger(),
).(*backupSyncController)

Expand Down
4 changes: 3 additions & 1 deletion pkg/controller/download_request_controller.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2017 the Velero contributors.
Copyright the Velero contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -33,6 +33,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"

velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/credentials"
velerov1client "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/typed/velero/v1"
velerov1informers "github.com/vmware-tanzu/velero/pkg/generated/informers/externalversions/velero/v1"
velerov1listers "github.com/vmware-tanzu/velero/pkg/generated/listers/velero/v1"
Expand All @@ -50,6 +51,7 @@ type downloadRequestController struct {
clock clock.Clock
kbClient client.Client
backupLister velerov1listers.BackupLister
credentialsGetter credentials.FileStore
newPluginManager func(logrus.FieldLogger) clientmgmt.Manager
backupStoreGetter persistence.ObjectBackupStoreGetter
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/pod_volume_backup_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ func (c *podVolumeBackupController) processBackup(req *velerov1api.PodVolumeBack
log.WithField("path", path).Debugf("Found path matching glob")

// temp creds
credentialsFile, err := restic.TempCredentialsFile(c.kbClient, req.Namespace, req.Spec.Pod.Namespace, c.fileSystem)
credentialsFile, err := restic.TempCredentialsFile(c.kbClient, req.Namespace, c.fileSystem)
if err != nil {
log.WithError(err).Error("Error creating temp restic credentials file")
return c.fail(req, errors.Wrap(err, "error creating temp restic credentials file").Error(), log)
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/pod_volume_restore_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ func (c *podVolumeRestoreController) processRestore(req *velerov1api.PodVolumeRe
return c.failRestore(req, errors.Wrap(err, "error getting volume directory name").Error(), log)
}

credsFile, err := restic.TempCredentialsFile(c.kbClient, req.Namespace, req.Spec.Pod.Namespace, c.fileSystem)
credsFile, err := restic.TempCredentialsFile(c.kbClient, req.Namespace, c.fileSystem)
if err != nil {
log.WithError(err).Error("Error creating temp restic credentials file")
return c.failRestore(req, errors.Wrap(err, "error creating temp restic credentials file").Error(), log)
Expand Down
5 changes: 2 additions & 3 deletions pkg/controller/restore_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ import (
informers "github.com/vmware-tanzu/velero/pkg/generated/informers/externalversions"
listers "github.com/vmware-tanzu/velero/pkg/generated/listers/velero/v1"
"github.com/vmware-tanzu/velero/pkg/metrics"
"github.com/vmware-tanzu/velero/pkg/persistence"
persistencemocks "github.com/vmware-tanzu/velero/pkg/persistence/mocks"
"github.com/vmware-tanzu/velero/pkg/plugin/clientmgmt"
pluginmocks "github.com/vmware-tanzu/velero/pkg/plugin/mocks"
Expand Down Expand Up @@ -209,7 +208,7 @@ func TestProcessQueueItemSkips(t *testing.T) {
logger,
logrus.InfoLevel,
nil,
persistence.NewObjectBackupStoreGetter(),
nil, // backupStoreGetter
metrics.NewServerMetrics(),
formatFlag,
).(*restoreController)
Expand Down Expand Up @@ -666,7 +665,7 @@ func TestvalidateAndCompleteWhenScheduleNameSpecified(t *testing.T) {
logger,
logrus.DebugLevel,
nil,
persistence.NewObjectBackupStoreGetter(),
nil, // backupStoreGetter
nil,
formatFlag,
).(*restoreController)
Expand Down
82 changes: 82 additions & 0 deletions pkg/credentials/file_store.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
Copyright the Velero contributors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package credentials

import (
"fmt"
"os"
"path/filepath"

"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
kbclient "sigs.k8s.io/controller-runtime/pkg/client"

"github.com/vmware-tanzu/velero/pkg/util/kube"

"github.com/vmware-tanzu/velero/pkg/util/filesystem"
)

// FileStore defines operations for interacting with credentials
// that are stored on a file system.
type FileStore interface {
// Get returns a path on disk where the secret defined by the given
// selector is serialized.
Get(selector *corev1.SecretKeySelector) (string, error)
}

type namespacedFileStore struct {
client kbclient.Client
namespace string

fsRoot string
fs filesystem.Interface
}

func (n *namespacedFileStore) Get(selector *corev1.SecretKeySelector) (string, error) {
creds, err := kube.GetSecretKey(n.client, n.namespace, selector)
if err != nil {
return "", err
}

keyFilePath := filepath.Join(n.fsRoot, fmt.Sprintf("%s-%s", selector.Name, selector.Key))
file, err := n.fs.OpenFile(keyFilePath, os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
return "", errors.Wrap(err, "unable to open credentials file for writing")
}
if _, err := file.Write(creds); err != nil {
return "", errors.Wrap(err, "unable to write credentials to store")
}
if err := file.Close(); err != nil {
return "", errors.Wrap(err, "unable to close credentials file")
}
return keyFilePath, nil
}

func NewNamespacedFileStore(client kbclient.Client, namespace string, fsRoot string, fs filesystem.Interface) (FileStore, error) {
fsNamespaceRoot := filepath.Join(fsRoot, namespace)

if err := fs.MkdirAll(fsNamespaceRoot, 0644); err != nil {
return nil, err
}

return &namespacedFileStore{
client: client,
namespace: namespace,
fsRoot: fsNamespaceRoot,
fs: fs,
}, nil
}
Loading

0 comments on commit bb31046

Please sign in to comment.