mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-11-10 00:10:20 +00:00
cleanup: move KMS functionality into its own package
A new "internal/kms" package is introduced, it holds the API that can be consumed by the RBD components. The KMS providers are currently in the same package as the API. With later follow-up changes the providers will be placed in their own sub-package. Because of the name of the package "kms", the types, functions and structs inside the package should not be prefixed with KMS anymore: internal/kms/kms.go:213:6: type name will be used as kms.KMSInitializerArgs by other packages, and that stutters; consider calling this InitializerArgs (golint) Updates: #852 Signed-off-by: Niels de Vos <ndevos@redhat.com>
This commit is contained in:
parent
778b5e86de
commit
4a3b1181ce
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package util
|
package kms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -60,7 +60,7 @@ const (
|
|||||||
awsCMK = "AWS_CMK_ARN"
|
awsCMK = "AWS_CMK_ARN"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ = RegisterKMSProvider(KMSProvider{
|
var _ = RegisterProvider(Provider{
|
||||||
UniqueID: kmsTypeAWSMetadata,
|
UniqueID: kmsTypeAWSMetadata,
|
||||||
Initializer: initAWSMetadataKMS,
|
Initializer: initAWSMetadataKMS,
|
||||||
})
|
})
|
||||||
@ -78,7 +78,7 @@ type AWSMetadataKMS struct {
|
|||||||
cmk string
|
cmk string
|
||||||
}
|
}
|
||||||
|
|
||||||
func initAWSMetadataKMS(args KMSInitializerArgs) (EncryptionKMS, error) {
|
func initAWSMetadataKMS(args ProviderInitArgs) (EncryptionKMS, error) {
|
||||||
kms := &AWSMetadataKMS{
|
kms := &AWSMetadataKMS{
|
||||||
namespace: args.Namespace,
|
namespace: args.Namespace,
|
||||||
}
|
}
|
||||||
@ -152,10 +152,10 @@ func (kms *AWSMetadataKMS) Destroy() {
|
|||||||
// Nothing to do.
|
// Nothing to do.
|
||||||
}
|
}
|
||||||
|
|
||||||
// requiresDEKStore indicates that the DEKs should get stored in the metadata
|
// RequiresDEKStore indicates that the DEKs should get stored in the metadata
|
||||||
// of the volumes. This Amazon KMS provider does not support storing DEKs in
|
// of the volumes. This Amazon KMS provider does not support storing DEKs in
|
||||||
// AWS as that adds additional costs.
|
// AWS as that adds additional costs.
|
||||||
func (kms *AWSMetadataKMS) requiresDEKStore() DEKStoreType {
|
func (kms *AWSMetadataKMS) RequiresDEKStore() DEKStoreType {
|
||||||
return DEKStoreMetadata
|
return DEKStoreMetadata
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package util
|
package kms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package util
|
package kms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -46,6 +46,12 @@ const (
|
|||||||
// defaultKMSConfigMapName default ConfigMap name to fetch kms
|
// defaultKMSConfigMapName default ConfigMap name to fetch kms
|
||||||
// connection details.
|
// connection details.
|
||||||
defaultKMSConfigMapName = "csi-kms-connection-details"
|
defaultKMSConfigMapName = "csi-kms-connection-details"
|
||||||
|
|
||||||
|
// kmsConfigPath is the location of the vault config file.
|
||||||
|
kmsConfigPath = "/etc/ceph-csi-encryption-kms-config/config.json"
|
||||||
|
|
||||||
|
// Default KMS type.
|
||||||
|
DefaultKMSType = "default"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetKMS returns an instance of Key Management System.
|
// GetKMS returns an instance of Key Management System.
|
||||||
@ -56,8 +62,8 @@ const (
|
|||||||
// - secrets contain additional details, like TLS certificates to connect to
|
// - secrets contain additional details, like TLS certificates to connect to
|
||||||
// the KMS
|
// the KMS
|
||||||
func GetKMS(tenant, kmsID string, secrets map[string]string) (EncryptionKMS, error) {
|
func GetKMS(tenant, kmsID string, secrets map[string]string) (EncryptionKMS, error) {
|
||||||
if kmsID == "" || kmsID == defaultKMSType {
|
if kmsID == "" || kmsID == DefaultKMSType {
|
||||||
return initSecretsKMS(secrets)
|
return GetDefaultKMS(secrets)
|
||||||
}
|
}
|
||||||
|
|
||||||
config, err := getKMSConfiguration()
|
config, err := getKMSConfiguration()
|
||||||
@ -170,10 +176,10 @@ func getKMSConfigMap() (map[string]interface{}, error) {
|
|||||||
return kmsConfig, nil
|
return kmsConfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getKMSProvider inspects the configuration and tries to identify what
|
// getProvider inspects the configuration and tries to identify what
|
||||||
// KMSProvider is expected to be used with it. This returns the
|
// Provider is expected to be used with it. This returns the
|
||||||
// KMSProvider.UniqueID.
|
// Provider.UniqueID.
|
||||||
func getKMSProvider(config map[string]interface{}) (string, error) {
|
func getProvider(config map[string]interface{}) (string, error) {
|
||||||
var name string
|
var name string
|
||||||
|
|
||||||
providerName, ok := config[kmsTypeKey]
|
providerName, ok := config[kmsTypeKey]
|
||||||
@ -202,45 +208,45 @@ func getKMSProvider(config map[string]interface{}) (string, error) {
|
|||||||
"configuration option %q or %q", kmsTypeKey, kmsProviderKey)
|
"configuration option %q or %q", kmsTypeKey, kmsProviderKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
// KMSInitializerArgs get passed to KMSInitializerFunc when a new instance of a
|
// ProviderInitArgs get passed to ProviderInitFunc when a new instance of a
|
||||||
// KMSProvider is initialized.
|
// Provider is initialized.
|
||||||
type KMSInitializerArgs struct {
|
type ProviderInitArgs struct {
|
||||||
Tenant string
|
Tenant string
|
||||||
Config map[string]interface{}
|
Config map[string]interface{}
|
||||||
Secrets map[string]string
|
Secrets map[string]string
|
||||||
// Namespace contains the Kubernetes Namespace where the Ceph-CSI Pods
|
// Namespace contains the Kubernetes Namespace where the Ceph-CSI Pods
|
||||||
// are running. This is an optional option, and might be unset when the
|
// are running. This is an optional option, and might be unset when the
|
||||||
// KMSProvider.Initializer is called.
|
// Provider.Initializer is called.
|
||||||
Namespace string
|
Namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
// KMSInitializerFunc gets called when the KMSProvider needs to be
|
// ProviderInitFunc gets called when the Provider needs to be
|
||||||
// instantiated.
|
// instantiated.
|
||||||
type KMSInitializerFunc func(args KMSInitializerArgs) (EncryptionKMS, error)
|
type ProviderInitFunc func(args ProviderInitArgs) (EncryptionKMS, error)
|
||||||
|
|
||||||
type KMSProvider struct {
|
type Provider struct {
|
||||||
UniqueID string
|
UniqueID string
|
||||||
Initializer KMSInitializerFunc
|
Initializer ProviderInitFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
type kmsProviderList struct {
|
type kmsProviderList struct {
|
||||||
providers map[string]KMSProvider
|
providers map[string]Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
// kmsManager is used to create instances for a KMS provider.
|
// kmsManager is used to create instances for a KMS provider.
|
||||||
var kmsManager = kmsProviderList{providers: map[string]KMSProvider{}}
|
var kmsManager = kmsProviderList{providers: map[string]Provider{}}
|
||||||
|
|
||||||
// RegisterKMSProvider uses kmsManager to register the given KMSProvider. The
|
// RegisterProvider uses kmsManager to register the given Provider. The
|
||||||
// KMSProvider.Initializer function will get called when a new instance of the
|
// Provider.Initializer function will get called when a new instance of the
|
||||||
// KMS is required.
|
// KMS is required.
|
||||||
func RegisterKMSProvider(provider KMSProvider) bool {
|
func RegisterProvider(provider Provider) bool {
|
||||||
// validate uniqueness of the UniqueID
|
// validate uniqueness of the UniqueID
|
||||||
if provider.UniqueID == "" {
|
if provider.UniqueID == "" {
|
||||||
panic("a provider MUST set a UniqueID")
|
panic("a provider MUST set a UniqueID")
|
||||||
}
|
}
|
||||||
_, ok := kmsManager.providers[provider.UniqueID]
|
_, ok := kmsManager.providers[provider.UniqueID]
|
||||||
if ok {
|
if ok {
|
||||||
panic("duplicate registration of KMSProvider.UniqueID: " + provider.UniqueID)
|
panic("duplicate registration of Provider.UniqueID: " + provider.UniqueID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate the Initializer
|
// validate the Initializer
|
||||||
@ -253,14 +259,14 @@ func RegisterKMSProvider(provider KMSProvider) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildKMS creates a new KMSProvider instance, based on the configuration that
|
// buildKMS creates a new Provider instance, based on the configuration that
|
||||||
// was passed. This uses getKMSProvider() internally to identify the
|
// was passed. This uses getProvider() internally to identify the
|
||||||
// KMSProvider to instantiate.
|
// Provider to instantiate.
|
||||||
func (kf *kmsProviderList) buildKMS(
|
func (kf *kmsProviderList) buildKMS(
|
||||||
tenant string,
|
tenant string,
|
||||||
config map[string]interface{},
|
config map[string]interface{},
|
||||||
secrets map[string]string) (EncryptionKMS, error) {
|
secrets map[string]string) (EncryptionKMS, error) {
|
||||||
providerName, err := getKMSProvider(config)
|
providerName, err := getProvider(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -271,14 +277,14 @@ func (kf *kmsProviderList) buildKMS(
|
|||||||
providerName)
|
providerName)
|
||||||
}
|
}
|
||||||
|
|
||||||
kmsInitArgs := KMSInitializerArgs{
|
kmsInitArgs := ProviderInitArgs{
|
||||||
Tenant: tenant,
|
Tenant: tenant,
|
||||||
Config: config,
|
Config: config,
|
||||||
Secrets: secrets,
|
Secrets: secrets,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Namespace is an optional parameter, it may not be set and is not
|
// Namespace is an optional parameter, it may not be set and is not
|
||||||
// required for all KMSProviders
|
// required for all Providers
|
||||||
ns, err := getPodNamespace()
|
ns, err := getPodNamespace()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
kmsInitArgs.Namespace = ns
|
kmsInitArgs.Namespace = ns
|
||||||
@ -286,3 +292,96 @@ func (kf *kmsProviderList) buildKMS(
|
|||||||
|
|
||||||
return provider.Initializer(kmsInitArgs)
|
return provider.Initializer(kmsInitArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetDefaultKMS(secrets map[string]string) (EncryptionKMS, error) {
|
||||||
|
provider, ok := kmsManager.providers[DefaultKMSType]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("could not find KMS provider %q", DefaultKMSType)
|
||||||
|
}
|
||||||
|
|
||||||
|
kmsInitArgs := ProviderInitArgs{
|
||||||
|
Secrets: secrets,
|
||||||
|
}
|
||||||
|
|
||||||
|
return provider.Initializer(kmsInitArgs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncryptionKMS provides external Key Management System for encryption
|
||||||
|
// passphrases storage.
|
||||||
|
type EncryptionKMS interface {
|
||||||
|
Destroy()
|
||||||
|
|
||||||
|
// RequiresDEKStore returns the DEKStoreType that is needed to be
|
||||||
|
// configure for the KMS. Nothing needs to be done when this function
|
||||||
|
// returns DEKStoreIntegrated, otherwise you will need to configure an
|
||||||
|
// alternative storage for the DEKs.
|
||||||
|
RequiresDEKStore() DEKStoreType
|
||||||
|
|
||||||
|
// EncryptDEK provides a way for a KMS to encrypt a DEK. In case the
|
||||||
|
// encryption is done transparently inside the KMS service, the
|
||||||
|
// function can return an unencrypted value.
|
||||||
|
EncryptDEK(volumeID, plainDEK string) (string, error)
|
||||||
|
|
||||||
|
// DecryptDEK provides a way for a KMS to decrypt a DEK. In case the
|
||||||
|
// encryption is done transparently inside the KMS service, the
|
||||||
|
// function does not need to do anything except return the encyptedDEK
|
||||||
|
// as it was received.
|
||||||
|
DecryptDEK(volumeID, encyptedDEK string) (string, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DEKStoreType describes what DEKStore needs to be configured when using a
|
||||||
|
// particular KMS. A KMS might support different DEKStores depending on its
|
||||||
|
// configuration.
|
||||||
|
type DEKStoreType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DEKStoreIntegrated indicates that the KMS itself supports storing
|
||||||
|
// DEKs.
|
||||||
|
DEKStoreIntegrated = DEKStoreType("")
|
||||||
|
// DEKStoreMetadata indicates that the KMS should be configured to
|
||||||
|
// store the DEK in the metadata of the volume.
|
||||||
|
DEKStoreMetadata = DEKStoreType("metadata")
|
||||||
|
)
|
||||||
|
|
||||||
|
// DEKStore allows KMS instances to implement a modular backend for DEK
|
||||||
|
// storage. This can be used to store the DEK in a different location, in case
|
||||||
|
// the KMS can not store passphrases for volumes.
|
||||||
|
type DEKStore interface {
|
||||||
|
// StoreDEK saves the DEK in the configured store.
|
||||||
|
StoreDEK(volumeID string, dek string) error
|
||||||
|
// FetchDEK reads the DEK from the configured store and returns it.
|
||||||
|
FetchDEK(volumeID string) (string, error)
|
||||||
|
// RemoveDEK deletes the DEK from the configured store.
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i IntegratedDEK) EncryptDEK(volumeID, plainDEK string) (string, error) {
|
||||||
|
return plainDEK, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i IntegratedDEK) DecryptDEK(volumeID, encyptedDEK string) (string, error) {
|
||||||
|
return encyptedDEK, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getKeys takes a map that uses strings for keys and returns a slice with the
|
||||||
|
// keys.
|
||||||
|
func getKeys(m map[string]interface{}) []string {
|
||||||
|
keys := make([]string, len(m))
|
||||||
|
|
||||||
|
i := 0
|
||||||
|
for k := range m {
|
||||||
|
keys[i] = k
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys
|
||||||
|
}
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package util
|
package kms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@ -22,22 +22,22 @@ import (
|
|||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func noinitKMS(args KMSInitializerArgs) (EncryptionKMS, error) {
|
func noinitKMS(args ProviderInitArgs) (EncryptionKMS, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRegisterKMSProvider(t *testing.T) {
|
func TestRegisterProvider(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
provider KMSProvider
|
provider Provider
|
||||||
panics bool
|
panics bool
|
||||||
}{{
|
}{{
|
||||||
KMSProvider{
|
Provider{
|
||||||
UniqueID: "incomplete-provider",
|
UniqueID: "incomplete-provider",
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
}, {
|
}, {
|
||||||
KMSProvider{
|
Provider{
|
||||||
UniqueID: "initializer-only",
|
UniqueID: "initializer-only",
|
||||||
Initializer: noinitKMS,
|
Initializer: noinitKMS,
|
||||||
},
|
},
|
||||||
@ -47,9 +47,9 @@ func TestRegisterKMSProvider(t *testing.T) {
|
|||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
provider := test.provider
|
provider := test.provider
|
||||||
if test.panics {
|
if test.panics {
|
||||||
assert.Panics(t, func() { RegisterKMSProvider(provider) })
|
assert.Panics(t, func() { RegisterProvider(provider) })
|
||||||
} else {
|
} else {
|
||||||
assert.True(t, RegisterKMSProvider(provider))
|
assert.True(t, RegisterProvider(provider))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package util
|
package kms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -36,9 +36,6 @@ const (
|
|||||||
// Encryption passphrase location in K8s secrets.
|
// Encryption passphrase location in K8s secrets.
|
||||||
encryptionPassphraseKey = "encryptionPassphrase"
|
encryptionPassphraseKey = "encryptionPassphrase"
|
||||||
|
|
||||||
// Default KMS type.
|
|
||||||
defaultKMSType = "default"
|
|
||||||
|
|
||||||
// kmsTypeSecretsMetadata is the SecretsKMS with per-volume encryption,
|
// kmsTypeSecretsMetadata is the SecretsKMS with per-volume encryption,
|
||||||
// where the DEK is stored in the metadata of the volume itself.
|
// where the DEK is stored in the metadata of the volume itself.
|
||||||
kmsTypeSecretsMetadata = "metadata"
|
kmsTypeSecretsMetadata = "metadata"
|
||||||
@ -53,16 +50,21 @@ const (
|
|||||||
|
|
||||||
// SecretsKMS is default KMS implementation that means no KMS is in use.
|
// SecretsKMS is default KMS implementation that means no KMS is in use.
|
||||||
type SecretsKMS struct {
|
type SecretsKMS struct {
|
||||||
integratedDEK
|
IntegratedDEK
|
||||||
|
|
||||||
passphrase string
|
passphrase string
|
||||||
}
|
}
|
||||||
|
|
||||||
// initSecretsKMS initializes a SecretsKMS that uses the passphrase from the
|
var _ = RegisterProvider(Provider{
|
||||||
|
UniqueID: DefaultKMSType,
|
||||||
|
Initializer: newSecretsKMS,
|
||||||
|
})
|
||||||
|
|
||||||
|
// newSecretsKMS initializes a SecretsKMS that uses the passphrase from the
|
||||||
// secret that is configured for the StorageClass. This KMS provider uses a
|
// secret that is configured for the StorageClass. This KMS provider uses a
|
||||||
// single (LUKS) passhprase for all volumes.
|
// single (LUKS) passhprase for all volumes.
|
||||||
func initSecretsKMS(secrets map[string]string) (EncryptionKMS, error) {
|
func newSecretsKMS(args ProviderInitArgs) (EncryptionKMS, error) {
|
||||||
passphraseValue, ok := secrets[encryptionPassphraseKey]
|
passphraseValue, ok := args.Secrets[encryptionPassphraseKey]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("missing encryption passphrase in secrets")
|
return nil, errors.New("missing encryption passphrase in secrets")
|
||||||
}
|
}
|
||||||
@ -98,7 +100,7 @@ type SecretsMetadataKMS struct {
|
|||||||
SecretsKMS
|
SecretsKMS
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = RegisterKMSProvider(KMSProvider{
|
var _ = RegisterProvider(Provider{
|
||||||
UniqueID: kmsTypeSecretsMetadata,
|
UniqueID: kmsTypeSecretsMetadata,
|
||||||
Initializer: initSecretsMetadataKMS,
|
Initializer: initSecretsMetadataKMS,
|
||||||
})
|
})
|
||||||
@ -106,7 +108,7 @@ var _ = RegisterKMSProvider(KMSProvider{
|
|||||||
// initSecretsMetadataKMS initializes a SecretsMetadataKMS that wraps a SecretsKMS,
|
// initSecretsMetadataKMS initializes a SecretsMetadataKMS that wraps a SecretsKMS,
|
||||||
// so that the passphrase from the user provided or StorageClass secrets can be used
|
// so that the passphrase from the user provided or StorageClass secrets can be used
|
||||||
// for encrypting/decrypting DEKs that are stored in a detached DEKStore.
|
// for encrypting/decrypting DEKs that are stored in a detached DEKStore.
|
||||||
func initSecretsMetadataKMS(args KMSInitializerArgs) (EncryptionKMS, error) {
|
func initSecretsMetadataKMS(args ProviderInitArgs) (EncryptionKMS, error) {
|
||||||
var (
|
var (
|
||||||
smKMS SecretsMetadataKMS
|
smKMS SecretsMetadataKMS
|
||||||
encryptionPassphrase string
|
encryptionPassphrase string
|
||||||
@ -179,7 +181,7 @@ func (kms SecretsMetadataKMS) Destroy() {
|
|||||||
kms.SecretsKMS.Destroy()
|
kms.SecretsKMS.Destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kms SecretsMetadataKMS) requiresDEKStore() DEKStoreType {
|
func (kms SecretsMetadataKMS) RequiresDEKStore() DEKStoreType {
|
||||||
return DEKStoreMetadata
|
return DEKStoreMetadata
|
||||||
}
|
}
|
||||||
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package util
|
package kms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
@ -23,6 +23,26 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestNewSecretsKMS(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
secrets := map[string]string{}
|
||||||
|
|
||||||
|
// no passphrase in the secrets, should fail
|
||||||
|
kms, err := newSecretsKMS(ProviderInitArgs{
|
||||||
|
Secrets: secrets,
|
||||||
|
})
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Nil(t, kms)
|
||||||
|
|
||||||
|
// set a passphrase and it should pass
|
||||||
|
secrets[encryptionPassphraseKey] = "plaintext encryption key"
|
||||||
|
kms, err = newSecretsKMS(ProviderInitArgs{
|
||||||
|
Secrets: secrets,
|
||||||
|
})
|
||||||
|
assert.NotNil(t, kms)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestGenerateNonce(t *testing.T) {
|
func TestGenerateNonce(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
size := 64
|
size := 64
|
||||||
@ -44,7 +64,7 @@ func TestGenerateCipher(t *testing.T) {
|
|||||||
|
|
||||||
func TestInitSecretsMetadataKMS(t *testing.T) {
|
func TestInitSecretsMetadataKMS(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
args := KMSInitializerArgs{
|
args := ProviderInitArgs{
|
||||||
Tenant: "tenant",
|
Tenant: "tenant",
|
||||||
Config: nil,
|
Config: nil,
|
||||||
Secrets: map[string]string{},
|
Secrets: map[string]string{},
|
||||||
@ -61,7 +81,7 @@ func TestInitSecretsMetadataKMS(t *testing.T) {
|
|||||||
kms, err = initSecretsMetadataKMS(args)
|
kms, err = initSecretsMetadataKMS(args)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
require.NotNil(t, kms)
|
require.NotNil(t, kms)
|
||||||
assert.Equal(t, DEKStoreMetadata, kms.requiresDEKStore())
|
assert.Equal(t, DEKStoreMetadata, kms.RequiresDEKStore())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWorkflowSecretsMetadataKMS(t *testing.T) {
|
func TestWorkflowSecretsMetadataKMS(t *testing.T) {
|
||||||
@ -69,7 +89,7 @@ func TestWorkflowSecretsMetadataKMS(t *testing.T) {
|
|||||||
secrets := map[string]string{
|
secrets := map[string]string{
|
||||||
encryptionPassphraseKey: "my-passphrase-from-kubernetes",
|
encryptionPassphraseKey: "my-passphrase-from-kubernetes",
|
||||||
}
|
}
|
||||||
args := KMSInitializerArgs{
|
args := ProviderInitArgs{
|
||||||
Tenant: "tenant",
|
Tenant: "tenant",
|
||||||
Config: nil,
|
Config: nil,
|
||||||
Secrets: secrets,
|
Secrets: secrets,
|
||||||
@ -81,9 +101,7 @@ func TestWorkflowSecretsMetadataKMS(t *testing.T) {
|
|||||||
require.NotNil(t, kms)
|
require.NotNil(t, kms)
|
||||||
|
|
||||||
// plainDEK is the (LUKS) passphrase for the volume
|
// plainDEK is the (LUKS) passphrase for the volume
|
||||||
plainDEK, err := generateNewEncryptionPassphrase()
|
plainDEK := "usually created with generateNewEncryptionPassphrase()"
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.NotEqual(t, "", plainDEK)
|
|
||||||
|
|
||||||
encryptedDEK, err := kms.EncryptDEK(volumeID, plainDEK)
|
encryptedDEK, err := kms.EncryptDEK(volumeID, plainDEK)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package util
|
package kms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@ -89,7 +89,7 @@ type vaultConnection struct {
|
|||||||
|
|
||||||
type VaultKMS struct {
|
type VaultKMS struct {
|
||||||
vaultConnection
|
vaultConnection
|
||||||
integratedDEK
|
IntegratedDEK
|
||||||
|
|
||||||
// vaultPassphrasePath (VPP) used to be added before the "key" of the
|
// vaultPassphrasePath (VPP) used to be added before the "key" of the
|
||||||
// secret (like /v1/secret/data/<VPP>/key)
|
// secret (like /v1/secret/data/<VPP>/key)
|
||||||
@ -317,13 +317,13 @@ func (vc *vaultConnection) getDeleteKeyContext() map[string]string {
|
|||||||
return keyContext
|
return keyContext
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = RegisterKMSProvider(KMSProvider{
|
var _ = RegisterProvider(Provider{
|
||||||
UniqueID: kmsTypeVault,
|
UniqueID: kmsTypeVault,
|
||||||
Initializer: initVaultKMS,
|
Initializer: initVaultKMS,
|
||||||
})
|
})
|
||||||
|
|
||||||
// InitVaultKMS returns an interface to HashiCorp Vault KMS.
|
// InitVaultKMS returns an interface to HashiCorp Vault KMS.
|
||||||
func initVaultKMS(args KMSInitializerArgs) (EncryptionKMS, error) {
|
func initVaultKMS(args ProviderInitArgs) (EncryptionKMS, error) {
|
||||||
kms := &VaultKMS{}
|
kms := &VaultKMS{}
|
||||||
err := kms.initConnection(args.Config)
|
err := kms.initConnection(args.Config)
|
||||||
if err != nil {
|
if err != nil {
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package util
|
package kms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -77,14 +77,14 @@ type VaultTenantSA struct {
|
|||||||
saTokenDir string
|
saTokenDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = RegisterKMSProvider(KMSProvider{
|
var _ = RegisterProvider(Provider{
|
||||||
UniqueID: kmsTypeVaultTenantSA,
|
UniqueID: kmsTypeVaultTenantSA,
|
||||||
Initializer: initVaultTenantSA,
|
Initializer: initVaultTenantSA,
|
||||||
})
|
})
|
||||||
|
|
||||||
// initVaultTenantSA returns an interface to HashiCorp Vault KMS where Tenants
|
// initVaultTenantSA returns an interface to HashiCorp Vault KMS where Tenants
|
||||||
// use their ServiceAccount to access the service.
|
// use their ServiceAccount to access the service.
|
||||||
func initVaultTenantSA(args KMSInitializerArgs) (EncryptionKMS, error) {
|
func initVaultTenantSA(args ProviderInitArgs) (EncryptionKMS, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
config := args.Config
|
config := args.Config
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package util
|
package kms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package util
|
package kms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package util
|
package kms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@ -181,7 +181,7 @@ Example JSON structure in the KMS config is,
|
|||||||
*/
|
*/
|
||||||
type vaultTenantConnection struct {
|
type vaultTenantConnection struct {
|
||||||
vaultConnection
|
vaultConnection
|
||||||
integratedDEK
|
IntegratedDEK
|
||||||
|
|
||||||
client *kubernetes.Clientset
|
client *kubernetes.Clientset
|
||||||
|
|
||||||
@ -204,13 +204,13 @@ type VaultTokensKMS struct {
|
|||||||
TokenName string
|
TokenName string
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = RegisterKMSProvider(KMSProvider{
|
var _ = RegisterProvider(Provider{
|
||||||
UniqueID: kmsTypeVaultTokens,
|
UniqueID: kmsTypeVaultTokens,
|
||||||
Initializer: initVaultTokensKMS,
|
Initializer: initVaultTokensKMS,
|
||||||
})
|
})
|
||||||
|
|
||||||
// InitVaultTokensKMS returns an interface to HashiCorp Vault KMS.
|
// InitVaultTokensKMS returns an interface to HashiCorp Vault KMS.
|
||||||
func initVaultTokensKMS(args KMSInitializerArgs) (EncryptionKMS, error) {
|
func initVaultTokensKMS(args ProviderInitArgs) (EncryptionKMS, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
config := args.Config
|
config := args.Config
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package util
|
package kms
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@ -76,7 +76,7 @@ func TestInitVaultTokensKMS(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
args := KMSInitializerArgs{
|
args := ProviderInitArgs{
|
||||||
Tenant: "bob",
|
Tenant: "bob",
|
||||||
Config: make(map[string]interface{}),
|
Config: make(map[string]interface{}),
|
||||||
Secrets: nil,
|
Secrets: nil,
|
@ -22,6 +22,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
kmsapi "github.com/ceph/ceph-csi/internal/kms"
|
||||||
"github.com/ceph/ceph-csi/internal/util"
|
"github.com/ceph/ceph-csi/internal/util"
|
||||||
"github.com/ceph/ceph-csi/internal/util/log"
|
"github.com/ceph/ceph-csi/internal/util/log"
|
||||||
|
|
||||||
@ -289,7 +290,7 @@ func (ri *rbdImage) ParseEncryptionOpts(ctx context.Context, volOptions map[stri
|
|||||||
// configureEncryption sets up the VolumeEncryption for this rbdImage. Once
|
// configureEncryption sets up the VolumeEncryption for this rbdImage. Once
|
||||||
// configured, use isEncrypted() to see if the volume supports encryption.
|
// configured, use isEncrypted() to see if the volume supports encryption.
|
||||||
func (ri *rbdImage) configureEncryption(kmsID string, credentials map[string]string) error {
|
func (ri *rbdImage) configureEncryption(kmsID string, credentials map[string]string) error {
|
||||||
kms, err := util.GetKMS(ri.Owner, kmsID, credentials)
|
kms, err := kmsapi.GetKMS(ri.Owner, kmsID, credentials)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/ceph/ceph-csi/internal/kms"
|
||||||
"github.com/ceph/ceph-csi/internal/util/log"
|
"github.com/ceph/ceph-csi/internal/util/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,9 +34,6 @@ const (
|
|||||||
mapperFilePrefix = "luks-rbd-"
|
mapperFilePrefix = "luks-rbd-"
|
||||||
mapperFilePathPrefix = "/dev/mapper"
|
mapperFilePathPrefix = "/dev/mapper"
|
||||||
|
|
||||||
// kmsConfigPath is the location of the vault config file.
|
|
||||||
kmsConfigPath = "/etc/ceph-csi-encryption-kms-config/config.json"
|
|
||||||
|
|
||||||
// Passphrase size - 20 bytes is 160 bits to satisfy:
|
// Passphrase size - 20 bytes is 160 bits to satisfy:
|
||||||
// https://tools.ietf.org/html/rfc6749#section-10.10
|
// https://tools.ietf.org/html/rfc6749#section-10.10
|
||||||
encryptionPassphraseSize = 20
|
encryptionPassphraseSize = 20
|
||||||
@ -54,11 +52,11 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type VolumeEncryption struct {
|
type VolumeEncryption struct {
|
||||||
KMS EncryptionKMS
|
KMS kms.EncryptionKMS
|
||||||
|
|
||||||
// dekStore that will be used, this can be the EncryptionKMS or a
|
// dekStore that will be used, this can be the EncryptionKMS or a
|
||||||
// different object implementing the DEKStore interface.
|
// different object implementing the DEKStore interface.
|
||||||
dekStore DEKStore
|
dekStore kms.DEKStore
|
||||||
|
|
||||||
id string
|
id string
|
||||||
}
|
}
|
||||||
@ -76,7 +74,7 @@ func FetchEncryptionKMSID(encrypted, kmsID string) (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if kmsID == "" {
|
if kmsID == "" {
|
||||||
kmsID = defaultKMSType
|
kmsID = kms.DefaultKMSType
|
||||||
}
|
}
|
||||||
|
|
||||||
return kmsID, nil
|
return kmsID, nil
|
||||||
@ -88,24 +86,24 @@ func FetchEncryptionKMSID(encrypted, kmsID string) (string, error) {
|
|||||||
// Callers that receive a ErrDEKStoreNeeded error, should use
|
// Callers that receive a ErrDEKStoreNeeded error, should use
|
||||||
// VolumeEncryption.SetDEKStore() to configure an alternative storage for the
|
// VolumeEncryption.SetDEKStore() to configure an alternative storage for the
|
||||||
// DEKs.
|
// DEKs.
|
||||||
func NewVolumeEncryption(id string, kms EncryptionKMS) (*VolumeEncryption, error) {
|
func NewVolumeEncryption(id string, ekms kms.EncryptionKMS) (*VolumeEncryption, error) {
|
||||||
kmsID := id
|
kmsID := id
|
||||||
if kmsID == "" {
|
if kmsID == "" {
|
||||||
// if kmsID is not set, encryption is enabled, and the type is
|
// if kmsID is not set, encryption is enabled, and the type is
|
||||||
// SecretsKMS
|
// SecretsKMS
|
||||||
kmsID = defaultKMSType
|
kmsID = kms.DefaultKMSType
|
||||||
}
|
}
|
||||||
|
|
||||||
ve := &VolumeEncryption{
|
ve := &VolumeEncryption{
|
||||||
id: kmsID,
|
id: kmsID,
|
||||||
KMS: kms,
|
KMS: ekms,
|
||||||
}
|
}
|
||||||
|
|
||||||
if kms.requiresDEKStore() == DEKStoreIntegrated {
|
if ekms.RequiresDEKStore() == kms.DEKStoreIntegrated {
|
||||||
dekStore, ok := kms.(DEKStore)
|
dekStore, ok := ekms.(kms.DEKStore)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("KMS %T does not implement the "+
|
return nil, fmt.Errorf("KMS %T does not implement the "+
|
||||||
"DEKStore interface", kms)
|
"DEKStore interface", ekms)
|
||||||
}
|
}
|
||||||
|
|
||||||
ve.dekStore = dekStore
|
ve.dekStore = dekStore
|
||||||
@ -118,7 +116,7 @@ func NewVolumeEncryption(id string, kms EncryptionKMS) (*VolumeEncryption, error
|
|||||||
|
|
||||||
// SetDEKStore sets the DEKStore for this VolumeEncryption instance. It will be
|
// SetDEKStore sets the DEKStore for this VolumeEncryption instance. It will be
|
||||||
// used when StoreNewCryptoPassphrase() or RemoveDEK() is called.
|
// used when StoreNewCryptoPassphrase() or RemoveDEK() is called.
|
||||||
func (ve *VolumeEncryption) SetDEKStore(dekStore DEKStore) {
|
func (ve *VolumeEncryption) SetDEKStore(dekStore kms.DEKStore) {
|
||||||
ve.dekStore = dekStore
|
ve.dekStore = dekStore
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,72 +139,6 @@ func (ve *VolumeEncryption) GetID() string {
|
|||||||
return ve.id
|
return ve.id
|
||||||
}
|
}
|
||||||
|
|
||||||
// EncryptionKMS provides external Key Management System for encryption
|
|
||||||
// passphrases storage.
|
|
||||||
type EncryptionKMS interface {
|
|
||||||
Destroy()
|
|
||||||
|
|
||||||
// requiresDEKStore returns the DEKStoreType that is needed to be
|
|
||||||
// configure for the KMS. Nothing needs to be done when this function
|
|
||||||
// returns DEKStoreIntegrated, otherwise you will need to configure an
|
|
||||||
// alternative storage for the DEKs.
|
|
||||||
requiresDEKStore() DEKStoreType
|
|
||||||
|
|
||||||
// EncryptDEK provides a way for a KMS to encrypt a DEK. In case the
|
|
||||||
// encryption is done transparently inside the KMS service, the
|
|
||||||
// function can return an unencrypted value.
|
|
||||||
EncryptDEK(volumeID, plainDEK string) (string, error)
|
|
||||||
|
|
||||||
// DecryptDEK provides a way for a KMS to decrypt a DEK. In case the
|
|
||||||
// encryption is done transparently inside the KMS service, the
|
|
||||||
// function does not need to do anything except return the encyptedDEK
|
|
||||||
// as it was received.
|
|
||||||
DecryptDEK(volumeID, encyptedDEK string) (string, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEKStoreType describes what DEKStore needs to be configured when using a
|
|
||||||
// particular KMS. A KMS might support different DEKStores depending on its
|
|
||||||
// configuration.
|
|
||||||
type DEKStoreType string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// DEKStoreIntegrated indicates that the KMS itself supports storing
|
|
||||||
// DEKs.
|
|
||||||
DEKStoreIntegrated = DEKStoreType("")
|
|
||||||
// DEKStoreMetadata indicates that the KMS should be configured to
|
|
||||||
// store the DEK in the metadata of the volume.
|
|
||||||
DEKStoreMetadata = DEKStoreType("metadata")
|
|
||||||
)
|
|
||||||
|
|
||||||
// DEKStore allows KMS instances to implement a modular backend for DEK
|
|
||||||
// storage. This can be used to store the DEK in a different location, in case
|
|
||||||
// the KMS can not store passphrases for volumes.
|
|
||||||
type DEKStore interface {
|
|
||||||
// StoreDEK saves the DEK in the configured store.
|
|
||||||
StoreDEK(volumeID string, dek string) error
|
|
||||||
// FetchDEK reads the DEK from the configured store and returns it.
|
|
||||||
FetchDEK(volumeID string) (string, error)
|
|
||||||
// RemoveDEK deletes the DEK from the configured store.
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i integratedDEK) EncryptDEK(volumeID, plainDEK string) (string, error) {
|
|
||||||
return plainDEK, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i integratedDEK) DecryptDEK(volumeID, encyptedDEK string) (string, error) {
|
|
||||||
return encyptedDEK, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StoreCryptoPassphrase takes an unencrypted passphrase, encrypts it and saves
|
// StoreCryptoPassphrase takes an unencrypted passphrase, encrypts it and saves
|
||||||
// it in the DEKStore.
|
// it in the DEKStore.
|
||||||
func (ve *VolumeEncryption) StoreCryptoPassphrase(volumeID, passphrase string) error {
|
func (ve *VolumeEncryption) StoreCryptoPassphrase(volumeID, passphrase string) error {
|
||||||
|
@ -20,26 +20,12 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/ceph/ceph-csi/internal/kms"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestInitSecretsKMS(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
secrets := map[string]string{}
|
|
||||||
|
|
||||||
// no passphrase in the secrets, should fail
|
|
||||||
kms, err := initSecretsKMS(secrets)
|
|
||||||
assert.Error(t, err)
|
|
||||||
assert.Nil(t, kms)
|
|
||||||
|
|
||||||
// set a passphrase and it should pass
|
|
||||||
secrets[encryptionPassphraseKey] = "plaintext encryption key"
|
|
||||||
kms, err = initSecretsKMS(secrets)
|
|
||||||
assert.NotNil(t, kms)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGenerateNewEncryptionPassphrase(t *testing.T) {
|
func TestGenerateNewEncryptionPassphrase(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
b64Passphrase, err := generateNewEncryptionPassphrase()
|
b64Passphrase, err := generateNewEncryptionPassphrase()
|
||||||
@ -55,17 +41,18 @@ func TestGenerateNewEncryptionPassphrase(t *testing.T) {
|
|||||||
func TestKMSWorkflow(t *testing.T) {
|
func TestKMSWorkflow(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
secrets := map[string]string{
|
secrets := map[string]string{
|
||||||
encryptionPassphraseKey: "workflow test",
|
// FIXME: use encryptionPassphraseKey from SecretsKMS
|
||||||
|
"encryptionPassphrase": "workflow test",
|
||||||
}
|
}
|
||||||
|
|
||||||
kms, err := GetKMS("tenant", defaultKMSType, secrets)
|
kmsProvider, err := kms.GetDefaultKMS(secrets)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
require.NotNil(t, kms)
|
require.NotNil(t, kmsProvider)
|
||||||
|
|
||||||
ve, err := NewVolumeEncryption("", kms)
|
ve, err := NewVolumeEncryption("", kmsProvider)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
require.NotNil(t, ve)
|
require.NotNil(t, ve)
|
||||||
assert.Equal(t, defaultKMSType, ve.GetID())
|
assert.Equal(t, kms.DefaultKMSType, ve.GetID())
|
||||||
|
|
||||||
volumeID := "volume-id"
|
volumeID := "volume-id"
|
||||||
|
|
||||||
@ -74,5 +61,5 @@ func TestKMSWorkflow(t *testing.T) {
|
|||||||
|
|
||||||
passphrase, err := ve.GetCryptoPassphrase(volumeID)
|
passphrase, err := ve.GetCryptoPassphrase(volumeID)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, secrets[encryptionPassphraseKey], passphrase)
|
assert.Equal(t, secrets["encryptionPassphrase"], passphrase)
|
||||||
}
|
}
|
||||||
|
@ -344,20 +344,6 @@ func contains(s []string, key string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// getKeys takes a map that uses strings for keys and returns a slice with the
|
|
||||||
// keys.
|
|
||||||
func getKeys(m map[string]interface{}) []string {
|
|
||||||
keys := make([]string, len(m))
|
|
||||||
|
|
||||||
i := 0
|
|
||||||
for k := range m {
|
|
||||||
keys[i] = k
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
|
|
||||||
return keys
|
|
||||||
}
|
|
||||||
|
|
||||||
// CallStack returns the stack of the calls in the current goroutine. Useful
|
// CallStack returns the stack of the calls in the current goroutine. Useful
|
||||||
// for debugging or reporting errors. This is a friendly alternative to
|
// for debugging or reporting errors. This is a friendly alternative to
|
||||||
// assert() or panic().
|
// assert() or panic().
|
||||||
|
Loading…
Reference in New Issue
Block a user