From 9b6c2117f391da20382545a957209f5d00dbd936 Mon Sep 17 00:00:00 2001 From: Niels de Vos Date: Mon, 15 Feb 2021 10:53:25 +0100 Subject: [PATCH] rbd: set encryption passphrase on CreateVolume Have the provisioner create the passphrase for the volume, instead of doign it lazily at the time the volume is used for the 1st time. This prevents potential races where pods on different nodes try to store different passphrases at the (almost) same time. Signed-off-by: Niels de Vos --- internal/rbd/controllerserver.go | 28 ++++++++++++++++++---- internal/rbd/nodeserver.go | 4 ++-- internal/util/crypto.go | 40 ++++++++++++++++---------------- 3 files changed, 46 insertions(+), 26 deletions(-) diff --git a/internal/rbd/controllerserver.go b/internal/rbd/controllerserver.go index d13a6cb89..045923872 100644 --- a/internal/rbd/controllerserver.go +++ b/internal/rbd/controllerserver.go @@ -144,7 +144,7 @@ func (cs *ControllerServer) parseVolCreateRequest(ctx context.Context, req *csi. func buildCreateVolumeResponse(ctx context.Context, req *csi.CreateVolumeRequest, rbdVol *rbdVolume) (*csi.CreateVolumeResponse, error) { if rbdVol.Encrypted { - err := rbdVol.ensureEncryptionMetadataSet(rbdImageRequiresEncryption) + err := rbdVol.setupEncryption(ctx) if err != nil { util.ErrorLog(ctx, err.Error()) return nil, status.Error(codes.Internal, err.Error()) @@ -507,10 +507,9 @@ func (cs *ControllerServer) createBackingImage(ctx context.Context, cr *util.Cre } } if rbdVol.Encrypted { - err = rbdVol.ensureEncryptionMetadataSet(rbdImageRequiresEncryption) + err = rbdVol.setupEncryption(ctx) if err != nil { - util.ErrorLog(ctx, "failed to save encryption status, deleting image %s: %s", - rbdVol, err) + util.ErrorLog(ctx, "failed to setup encroption for image %s: %v", rbdVol, err) return status.Error(codes.Internal, err.Error()) } } @@ -1138,3 +1137,24 @@ func (cs *ControllerServer) ControllerExpandVolume(ctx context.Context, req *csi NodeExpansionRequired: nodeExpansion, }, nil } + +// setupEncryption configures the metadata of the RBD image for encryption: +// - the Data-Encryption-Key (DEK) will be generated stored for use by the KMS; +// - the RBD image will be marked to support encryption in its metadata. +func (rv *rbdVolume) setupEncryption(ctx context.Context) error { + err := util.StoreNewCryptoPassphrase(rv.VolID, rv.KMS) + if err != nil { + util.ErrorLog(ctx, "failed to save encryption passphrase for "+ + "image %s: %s", rv.String(), err) + return err + } + + err = rv.ensureEncryptionMetadataSet(rbdImageRequiresEncryption) + if err != nil { + util.ErrorLog(ctx, "failed to save encryption status, deleting "+ + "image %s: %s", rv.String(), err) + return err + } + + return nil +} diff --git a/internal/rbd/nodeserver.go b/internal/rbd/nodeserver.go index b52c8b0b8..132672641 100644 --- a/internal/rbd/nodeserver.go +++ b/internal/rbd/nodeserver.go @@ -830,7 +830,7 @@ func (ns *NodeServer) processEncryptedDevice(ctx context.Context, volOptions *rb } func encryptDevice(ctx context.Context, rbdVol *rbdVolume, devicePath string) error { - passphrase, err := util.GetCryptoPassphrase(ctx, rbdVol.VolID, rbdVol.KMS) + passphrase, err := util.GetCryptoPassphrase(rbdVol.VolID, rbdVol.KMS) if err != nil { util.ErrorLog(ctx, "failed to get crypto passphrase for %s: %v", rbdVol, err) @@ -853,7 +853,7 @@ func encryptDevice(ctx context.Context, rbdVol *rbdVolume, devicePath string) er } func openEncryptedDevice(ctx context.Context, volOptions *rbdVolume, devicePath string) (string, error) { - passphrase, err := util.GetCryptoPassphrase(ctx, volOptions.VolID, volOptions.KMS) + passphrase, err := util.GetCryptoPassphrase(volOptions.VolID, volOptions.KMS) if err != nil { util.ErrorLog(ctx, "failed to get passphrase for encrypted device %s: %v", volOptions, err) diff --git a/internal/util/crypto.go b/internal/util/crypto.go index f98d2ff96..a4be18dc9 100644 --- a/internal/util/crypto.go +++ b/internal/util/crypto.go @@ -95,9 +95,10 @@ func (kms SecretsKMS) GetPassphrase(key string) (string, error) { return kms.passphrase, nil } -// SavePassphrase is not implemented. +// SavePassphrase does nothing, as there is no passphrase per key (volume), so +// no need to store is anywhere. func (kms SecretsKMS) SavePassphrase(key, value string) error { - return fmt.Errorf("save new passphrase is not implemented for Kubernetes secrets") + return nil } // DeletePassphrase is doing nothing as no new passphrases are saved with @@ -171,27 +172,26 @@ func GetKMS(tenant, kmsID string, secrets map[string]string) (EncryptionKMS, err return nil, fmt.Errorf("unknown encryption KMS type %s", kmsType) } +// StoreNewCryptoPassphrase generates a new passphrase and saves it in the KMS. +func StoreNewCryptoPassphrase(volumeID string, kms EncryptionKMS) error { + passphrase, err := generateNewEncryptionPassphrase() + if err != nil { + return fmt.Errorf("failed to generate passphrase for %s: %w", volumeID, err) + } + err = kms.SavePassphrase(volumeID, passphrase) + if err != nil { + return fmt.Errorf("failed to save the passphrase for %s: %w", volumeID, err) + } + return nil +} + // GetCryptoPassphrase Retrieves passphrase to encrypt volume. -func GetCryptoPassphrase(ctx context.Context, volumeID string, kms EncryptionKMS) (string, error) { +func GetCryptoPassphrase(volumeID string, kms EncryptionKMS) (string, error) { passphrase, err := kms.GetPassphrase(volumeID) - if err == nil { - return passphrase, nil + if err != nil { + return "", err } - if _, ok := err.(MissingPassphrase); ok { - DebugLog(ctx, "Encryption passphrase is missing for %s. Generating a new one", - volumeID) - passphrase, err = generateNewEncryptionPassphrase() - if err != nil { - return "", fmt.Errorf("failed to generate passphrase for %s: %w", volumeID, err) - } - err = kms.SavePassphrase(volumeID, passphrase) - if err != nil { - return "", fmt.Errorf("failed to save the passphrase for %s: %w", volumeID, err) - } - return passphrase, nil - } - ErrorLog(ctx, "failed to get encryption passphrase for %s: %s", volumeID, err) - return "", err + return passphrase, nil } // generateNewEncryptionPassphrase generates a random passphrase for encryption.