From 9ac7f5640099b6f4f87606e1f590af97cfa3e71b Mon Sep 17 00:00:00 2001 From: Niels de Vos Date: Mon, 15 Feb 2021 10:24:47 +0100 Subject: [PATCH] util: move existing KMS implementations to the DEKStore interface Use DEKStore API for Fetching and Storing passphrases. Drop the fallback for the old KMS interface that is now provided as DEKStore. The original implementation has been re-used for the DEKStore interface. This also moves GetCryptoPassphrase/StoreNewCryptoPassphrase functions to methods of VolumeEncryption. Signed-off-by: Niels de Vos --- internal/rbd/controllerserver.go | 2 +- internal/rbd/encryption.go | 6 +++--- internal/util/crypto.go | 29 ++++++++++++++++++++++------- internal/util/crypto_test.go | 8 ++++++-- internal/util/secretskms.go | 12 ++++++------ internal/util/vault.go | 12 ++++++------ internal/util/vault_tokens.go | 12 ++++++------ 7 files changed, 50 insertions(+), 31 deletions(-) diff --git a/internal/rbd/controllerserver.go b/internal/rbd/controllerserver.go index 11b28d3a5..8d6107a54 100644 --- a/internal/rbd/controllerserver.go +++ b/internal/rbd/controllerserver.go @@ -691,7 +691,7 @@ func (cs *ControllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol } if rbdVol.isEncrypted() { - if err = rbdVol.encryption.KMS.DeletePassphrase(rbdVol.VolID); err != nil { + if err = rbdVol.encryption.RemoveDEK(rbdVol.VolID); err != nil { util.WarningLog(ctx, "failed to clean the passphrase for volume %s: %s", rbdVol.VolID, err) } } diff --git a/internal/rbd/encryption.go b/internal/rbd/encryption.go index e22f53994..0767b8884 100644 --- a/internal/rbd/encryption.go +++ b/internal/rbd/encryption.go @@ -90,7 +90,7 @@ func (rv *rbdVolume) isEncrypted() bool { // - 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.encryption.KMS) + err := rv.encryption.StoreNewCryptoPassphrase(rv.VolID) if err != nil { util.ErrorLog(ctx, "failed to save encryption passphrase for "+ "image %s: %s", rv.String(), err) @@ -108,7 +108,7 @@ func (rv *rbdVolume) setupEncryption(ctx context.Context) error { } func (rv *rbdVolume) encryptDevice(ctx context.Context, devicePath string) error { - passphrase, err := util.GetCryptoPassphrase(rv.VolID, rv.encryption.KMS) + passphrase, err := rv.encryption.GetCryptoPassphrase(rv.VolID) if err != nil { util.ErrorLog(ctx, "failed to get crypto passphrase for %s: %v", rv.String(), err) @@ -131,7 +131,7 @@ func (rv *rbdVolume) encryptDevice(ctx context.Context, devicePath string) error } func (rv *rbdVolume) openEncryptedDevice(ctx context.Context, devicePath string) (string, error) { - passphrase, err := util.GetCryptoPassphrase(rv.VolID, rv.encryption.KMS) + passphrase, err := rv.encryption.GetCryptoPassphrase(rv.VolID) if err != nil { util.ErrorLog(ctx, "failed to get passphrase for encrypted device %s: %v", rv.String(), err) diff --git a/internal/util/crypto.go b/internal/util/crypto.go index 1f15a3cea..bdc0e2773 100644 --- a/internal/util/crypto.go +++ b/internal/util/crypto.go @@ -106,13 +106,20 @@ func (ve *VolumeEncryption) Destroy() { ve.KMS.Destroy() } +// RemoveDEK deletes the DEK for a particular volumeID from the DEKStore linked +// with this VolumeEncryption instance. +func (ve *VolumeEncryption) RemoveDEK(volumeID string) error { + if ve.dekStore == nil { + return ErrDEKStoreNotFound + } + + return ve.dekStore.RemoveDEK(volumeID) +} + // EncryptionKMS provides external Key Management System for encryption // passphrases storage. type EncryptionKMS interface { Destroy() - GetPassphrase(key string) (string, error) - SavePassphrase(key, value string) error - DeletePassphrase(key string) error GetID() string // requiresDEKStore returns the DEKStoreType that is needed to be @@ -148,6 +155,13 @@ type DEKStore interface { RemoveDEK(volumeID string) error } +// integratedDEK is a DEKStore that can not be configured. Either the KMS does +// not use a DEK, or the DEK is stored in the KMS without additional +// configuration options. +type integratedDEK struct{} + +func (i integratedDEK) requiresDEKStore() DEKStoreType { return DEKStoreIntegrated } + // GetKMS returns an instance of Key Management System. // // - tenant is the owner of the Volume, used to fetch the Vault Token from the @@ -209,12 +223,13 @@ func GetKMS(tenant, kmsID string, secrets map[string]string) (EncryptionKMS, err } // StoreNewCryptoPassphrase generates a new passphrase and saves it in the KMS. -func StoreNewCryptoPassphrase(volumeID string, kms EncryptionKMS) error { +func (ve *VolumeEncryption) StoreNewCryptoPassphrase(volumeID string) error { passphrase, err := generateNewEncryptionPassphrase() if err != nil { return fmt.Errorf("failed to generate passphrase for %s: %w", volumeID, err) } - err = kms.SavePassphrase(volumeID, passphrase) + + err = ve.dekStore.StoreDEK(volumeID, passphrase) if err != nil { return fmt.Errorf("failed to save the passphrase for %s: %w", volumeID, err) } @@ -222,8 +237,8 @@ func StoreNewCryptoPassphrase(volumeID string, kms EncryptionKMS) error { } // GetCryptoPassphrase Retrieves passphrase to encrypt volume. -func GetCryptoPassphrase(volumeID string, kms EncryptionKMS) (string, error) { - passphrase, err := kms.GetPassphrase(volumeID) +func (ve *VolumeEncryption) GetCryptoPassphrase(volumeID string) (string, error) { + passphrase, err := ve.dekStore.FetchDEK(volumeID) if err != nil { return "", err } diff --git a/internal/util/crypto_test.go b/internal/util/crypto_test.go index 3b622a08f..61cce4b81 100644 --- a/internal/util/crypto_test.go +++ b/internal/util/crypto_test.go @@ -60,12 +60,16 @@ func TestKMSWorkflow(t *testing.T) { require.NotNil(t, kms) assert.Equal(t, defaultKMSType, kms.GetID()) + ve, err := NewVolumeEncryption(kms) + assert.NoError(t, err) + require.NotNil(t, ve) + volumeID := "volume-id" - err = StoreNewCryptoPassphrase(volumeID, kms) + err = ve.StoreNewCryptoPassphrase(volumeID) assert.NoError(t, err) - passphrase, err := GetCryptoPassphrase(volumeID, kms) + passphrase, err := ve.GetCryptoPassphrase(volumeID) assert.NoError(t, err) assert.Equal(t, secrets[encryptionPassphraseKey], passphrase) } diff --git a/internal/util/secretskms.go b/internal/util/secretskms.go index 45320ecd4..ea6f70179 100644 --- a/internal/util/secretskms.go +++ b/internal/util/secretskms.go @@ -56,19 +56,19 @@ func (kms SecretsKMS) Destroy() { // nothing to do } -// GetPassphrase returns passphrase from Kubernetes secrets. -func (kms SecretsKMS) GetPassphrase(key string) (string, error) { +// FetchDEK returns passphrase from Kubernetes secrets. +func (kms SecretsKMS) FetchDEK(key string) (string, error) { return kms.passphrase, nil } -// SavePassphrase does nothing, as there is no passphrase per key (volume), so +// StoreDEK 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 { +func (kms SecretsKMS) StoreDEK(key, value string) error { return nil } -// DeletePassphrase is doing nothing as no new passphrases are saved with +// RemoveDEK is doing nothing as no new passphrases are saved with // SecretsKMS. -func (kms SecretsKMS) DeletePassphrase(key string) error { +func (kms SecretsKMS) RemoveDEK(key string) error { return nil } diff --git a/internal/util/vault.go b/internal/util/vault.go index 91889aaa7..97766a19e 100644 --- a/internal/util/vault.go +++ b/internal/util/vault.go @@ -328,9 +328,9 @@ func (vc *vaultConnection) GetID() string { return vc.EncryptionKMSID } -// GetPassphrase returns passphrase from Vault. The passphrase is stored in a +// FetchDEK returns passphrase from Vault. The passphrase is stored in a // data.data.passphrase structure. -func (kms *VaultKMS) GetPassphrase(key string) (string, error) { +func (kms *VaultKMS) FetchDEK(key string) (string, error) { s, err := kms.secrets.GetSecret(filepath.Join(kms.vaultPassphrasePath, key), kms.keyContext) if err != nil { return "", err @@ -348,8 +348,8 @@ func (kms *VaultKMS) GetPassphrase(key string) (string, error) { return passphrase, nil } -// SavePassphrase saves new passphrase in Vault. -func (kms *VaultKMS) SavePassphrase(key, value string) error { +// StoreDEK saves new passphrase in Vault. +func (kms *VaultKMS) StoreDEK(key, value string) error { data := map[string]interface{}{ "data": map[string]string{ "passphrase": value, @@ -365,8 +365,8 @@ func (kms *VaultKMS) SavePassphrase(key, value string) error { return nil } -// DeletePassphrase deletes passphrase from Vault. -func (kms *VaultKMS) DeletePassphrase(key string) error { +// RemoveDEK deletes passphrase from Vault. +func (kms *VaultKMS) RemoveDEK(key string) error { pathKey := filepath.Join(kms.vaultPassphrasePath, key) err := kms.secrets.DeleteSecret(pathKey, kms.keyContext) if err != nil { diff --git a/internal/util/vault_tokens.go b/internal/util/vault_tokens.go index ca04a57ee..36ae5ea2e 100644 --- a/internal/util/vault_tokens.go +++ b/internal/util/vault_tokens.go @@ -347,9 +347,9 @@ func (kms *VaultTokensKMS) initCertificates(config map[string]interface{}) error return nil } -// GetPassphrase returns passphrase from Vault. The passphrase is stored in a +// FetchDEK returns passphrase from Vault. The passphrase is stored in a // data.data.passphrase structure. -func (kms *VaultTokensKMS) GetPassphrase(key string) (string, error) { +func (kms *VaultTokensKMS) FetchDEK(key string) (string, error) { s, err := kms.secrets.GetSecret(key, kms.keyContext) if err != nil { return "", err @@ -367,8 +367,8 @@ func (kms *VaultTokensKMS) GetPassphrase(key string) (string, error) { return passphrase, nil } -// SavePassphrase saves new passphrase in Vault. -func (kms *VaultTokensKMS) SavePassphrase(key, value string) error { +// StoreDEK saves new passphrase in Vault. +func (kms *VaultTokensKMS) StoreDEK(key, value string) error { data := map[string]interface{}{ "data": map[string]string{ "passphrase": value, @@ -383,8 +383,8 @@ func (kms *VaultTokensKMS) SavePassphrase(key, value string) error { return nil } -// DeletePassphrase deletes passphrase from Vault. -func (kms *VaultTokensKMS) DeletePassphrase(key string) error { +// RemoveDEK deletes passphrase from Vault. +func (kms *VaultTokensKMS) RemoveDEK(key string) error { err := kms.secrets.DeleteSecret(key, kms.keyContext) if err != nil { return fmt.Errorf("delete passphrase at %s request to vault failed: %w", key, err)