util: rewrite GetKMS() to use KMS provider plugin API

GetKMS() is the public API that initilizes the KMS providers on demand.
Each provider identifies itself with a KMS-Type, and adds its own
initialization function to a switch/case construct. This is not well
maintainable.

The new GetKMS() can be used the same way, but uses the new kmsManager
interface to create and configure the KMS provider instances.

All existing KMS providers are converted to use the new kmsManager
plugins API.

Signed-off-by: Niels de Vos <ndevos@redhat.com>
This commit is contained in:
Niels de Vos 2021-03-18 13:50:38 +01:00 committed by mergify[bot]
parent b43d28d35b
commit 9317e2afb4
9 changed files with 278 additions and 147 deletions

View File

@ -19,11 +19,8 @@ package util
import (
"context"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"path"
"strings"
@ -34,22 +31,12 @@ const (
mapperFilePrefix = "luks-rbd-"
mapperFilePathPrefix = "/dev/mapper"
kmsTypeKey = "encryptionKMSType"
// 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:
// https://tools.ietf.org/html/rfc6749#section-10.10
encryptionPassphraseSize = 20
// podNamespace ENV should be set in the cephcsi container
podNamespace = "POD_NAMESPACE"
// kmsConfigMapName env to read a ConfigMap by name
kmsConfigMapName = "KMS_CONFIGMAP_NAME"
// defaultConfigMapToRead default ConfigMap name to fetch kms connection details
defaultConfigMapToRead = "csi-kms-connection-details"
)
var (
@ -183,68 +170,6 @@ func (i integratedDEK) DecryptDEK(volumeID, encyptedDEK string) (string, error)
return encyptedDEK, nil
}
// GetKMS returns an instance of Key Management System.
//
// - tenant is the owner of the Volume, used to fetch the Vault Token from the
// Kubernetes Namespace where the PVC lives
// - kmsID is the service name of the KMS configuration
// - secrets contain additional details, like TLS certificates to connect to
// the KMS
func GetKMS(tenant, kmsID string, secrets map[string]string) (EncryptionKMS, error) {
if kmsID == "" || kmsID == defaultKMSType {
return initSecretsKMS(secrets)
}
var config map[string]interface{}
// #nosec
content, err := ioutil.ReadFile(kmsConfigPath)
if err != nil {
if !os.IsNotExist(err) {
return nil, fmt.Errorf("failed to read kms configuration from %s: %w",
kmsConfigPath, err)
}
// If the configmap is not mounted to the CSI pods read the configmap
// the kubernetes.
namespace := os.Getenv(podNamespace)
if namespace == "" {
return nil, fmt.Errorf("%q is not set", podNamespace)
}
name := os.Getenv(kmsConfigMapName)
if name == "" {
name = defaultConfigMapToRead
}
config, err = getVaultConfiguration(namespace, name)
if err != nil {
return nil, fmt.Errorf("failed to read kms configuration from configmap %s in namespace %s: %w",
namespace, name, err)
}
} else {
err = json.Unmarshal(content, &config)
if err != nil {
return nil, fmt.Errorf("failed to parse kms configuration: %w", err)
}
}
kmsConfig, ok := config[kmsID].(map[string]interface{})
if !ok {
return nil, fmt.Errorf("missing encryption KMS configuration with %s", kmsID)
}
kmsType, ok := kmsConfig[kmsTypeKey]
if !ok {
return nil, fmt.Errorf("encryption KMS configuration for %s is missing KMS type", kmsID)
}
switch kmsType {
case kmsTypeSecretsMetadata:
return initSecretsMetadataKMS(kmsID, secrets)
case kmsTypeVault:
return InitVaultKMS(kmsID, kmsConfig, secrets)
case kmsTypeVaultTokens:
return InitVaultTokensKMS(tenant, kmsID, kmsConfig)
}
return nil, fmt.Errorf("unknown encryption KMS type %s", kmsType)
}
// StoreNewCryptoPassphrase generates a new passphrase and saves it in the KMS.
func (ve *VolumeEncryption) StoreNewCryptoPassphrase(volumeID string) error {
passphrase, err := generateNewEncryptionPassphrase()

View File

@ -18,7 +18,10 @@ package util
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"os"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -27,20 +30,122 @@ const (
// kmsProviderKey is the name of the KMS provider that is registered at
// the kmsManager. This is used in the ConfigMap configuration options.
kmsProviderKey = "KMS_PROVIDER"
// kmsTypeKey is the name of the KMS provider that is registered at
// the kmsManager. This is used in the configfile configuration
// options.
kmsTypeKey = "encryptionKMSType"
// podNamespace ENV should be set in the cephcsi container
podNamespace = "POD_NAMESPACE"
// kmsConfigMapName env to read a ConfigMap by name
kmsConfigMapName = "KMS_CONFIGMAP_NAME"
// defaultConfigMapToRead default ConfigMap name to fetch kms connection details
defaultConfigMapToRead = "csi-kms-connection-details"
)
// getKMSConfig returns the (.Data) contents of the ConfigMap.
// GetKMS returns an instance of Key Management System.
//
// FIXME: Ceph-CSI should not talk to Kubernetes directly.
func getKMSConfig(ns, configmap string) (map[string]string, error) {
c := NewK8sClient()
cm, err := c.CoreV1().ConfigMaps(ns).Get(context.Background(),
configmap, metav1.GetOptions{})
// - tenant is the owner of the Volume, used to fetch the Vault Token from the
// Kubernetes Namespace where the PVC lives
// - kmsID is the service name of the KMS configuration
// - secrets contain additional details, like TLS certificates to connect to
// the KMS
func GetKMS(tenant, kmsID string, secrets map[string]string) (EncryptionKMS, error) {
if kmsID == "" || kmsID == defaultKMSType {
return initSecretsKMS(secrets)
}
config, err := getKMSConfiguration()
if err != nil {
return nil, err
}
return cm.Data, nil
// config contains a list of KMS connections, indexed by kmsID
section, ok := config[kmsID]
if !ok {
return nil, fmt.Errorf("could not get KMS configuration "+
"for %q", kmsID)
}
// kmsConfig can have additional sub-sections
kmsConfig, ok := section.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("failed to convert KMS configuration "+
"section: %s", kmsID)
}
return kmsManager.buildKMS(kmsID, tenant, kmsConfig, secrets)
}
// getKMSConfiguration reads the configuration file from the filesystem, or if
// that fails the ConfigMap directly. The returned map contains all the KMS
// configuration sections, each keyed by its own kmsID.
func getKMSConfiguration() (map[string]interface{}, error) {
var config map[string]interface{}
// #nosec
content, err := ioutil.ReadFile(kmsConfigPath)
if err == nil {
// kmsConfigPath exists and was successfully read
err = json.Unmarshal(content, &config)
if err != nil {
return nil, fmt.Errorf("failed to parse KMS "+
"configuration: %w", err)
}
} else {
// an error occurred while reading kmsConfigPath
if !os.IsNotExist(err) {
return nil, fmt.Errorf("failed to read KMS "+
"configuration from %s: %w", kmsConfigPath,
err)
}
// If the configmap is not mounted to the CSI pods read the
// configmap the kubernetes.
config, err = getKMSConfigMap()
if err != nil {
return nil, err
}
}
return config, nil
}
// getKMSConfigMap returns the contents of the ConfigMap.
//
// FIXME: Ceph-CSI should not talk to Kubernetes directly.
func getKMSConfigMap() (map[string]interface{}, error) {
ns := os.Getenv(podNamespace)
if ns == "" {
return nil, fmt.Errorf("%q is not set in the environment",
podNamespace)
}
cmName := os.Getenv(kmsConfigMapName)
if cmName == "" {
cmName = defaultConfigMapToRead
}
c := NewK8sClient()
cm, err := c.CoreV1().ConfigMaps(ns).Get(context.Background(),
cmName, metav1.GetOptions{})
if err != nil {
return nil, err
}
// convert cm.Data from map[string]interface{}
kmsConfig := make(map[string]interface{})
for kmsID, data := range cm.BinaryData {
section := make(map[string]interface{})
err = json.Unmarshal(data, &section)
if err != nil {
return nil, fmt.Errorf("could not convert contents "+
"of %q to s config section", kmsID)
}
kmsConfig[kmsID] = section
}
return kmsConfig, nil
}
// getKMSProvider inspects the configuration and tries to identify what
@ -76,7 +181,7 @@ func getKMSProvider(config map[string]interface{}) (string, error) {
// KMSInitializerArgs get passed to KMSInitializerFunc when a new instance of a
// KMSProvider is initialized.
type KMSInitializerArgs struct {
Id, Tenant string
ID, Tenant string
Config map[string]interface{}
Secrets map[string]string
}
@ -120,7 +225,12 @@ func RegisterKMSProvider(provider KMSProvider) bool {
return true
}
func (kf *kmsProviderList) buildKMS(providerName, kmsID, tenant string, config map[string]interface{}, secrets map[string]string) (EncryptionKMS, error) {
func (kf *kmsProviderList) buildKMS(kmsID, tenant string, config map[string]interface{}, secrets map[string]string) (EncryptionKMS, error) {
providerName, err := getKMSProvider(config)
if err != nil {
return nil, err
}
provider, ok := kf.providers[providerName]
if !ok {
return nil, fmt.Errorf("could not find KMS provider %q",
@ -128,7 +238,7 @@ func (kf *kmsProviderList) buildKMS(providerName, kmsID, tenant string, config m
}
return provider.Initializer(KMSInitializerArgs{
Id: kmsID,
ID: kmsID,
Tenant: tenant,
Config: config,
Secrets: secrets,

View File

@ -22,7 +22,7 @@ import (
"github.com/stretchr/testify/assert"
)
func noinitKMS(id, tenant string, config map[string]interface{}, secrets map[string]string) (EncryptionKMS, error) {
func noinitKMS(args KMSInitializerArgs) (EncryptionKMS, error) {
return nil, nil
}

View File

@ -93,11 +93,16 @@ type SecretsMetadataKMS struct {
encryptionKMSID string
}
var _ = RegisterKMSProvider(KMSProvider{
UniqueID: kmsTypeSecretsMetadata,
Initializer: initSecretsMetadataKMS,
})
// initSecretsMetadataKMS initializes a SecretsMetadataKMS that wraps a
// SecretsKMS, so that the passphrase from the StorageClass secrets can be used
// for encrypting/decrypting DEKs that are stored in a detached DEKStore.
func initSecretsMetadataKMS(encryptionKMSID string, secrets map[string]string) (EncryptionKMS, error) {
eKMS, err := initSecretsKMS(secrets)
func initSecretsMetadataKMS(args KMSInitializerArgs) (EncryptionKMS, error) {
eKMS, err := initSecretsKMS(args.Secrets)
if err != nil {
return nil, err
}
@ -109,7 +114,7 @@ func initSecretsMetadataKMS(encryptionKMSID string, secrets map[string]string) (
smKMS := SecretsMetadataKMS{}
smKMS.SecretsKMS = sKMS
smKMS.encryptionKMSID = encryptionKMSID
smKMS.encryptionKMSID = args.ID
return smKMS, nil
}

View File

@ -41,17 +41,22 @@ func TestGenerateCipher(t *testing.T) {
}
func TestInitSecretsMetadataKMS(t *testing.T) {
secrets := map[string]string{}
args := KMSInitializerArgs{
ID: "secrets-metadata-unit-test",
Tenant: "tenant",
Config: nil,
Secrets: map[string]string{},
}
// passphrase it not set, init should fail
kms, err := initSecretsMetadataKMS("secrets-metadata-unit-test", secrets)
kms, err := initSecretsMetadataKMS(args)
assert.Error(t, err)
assert.Nil(t, kms)
// set a passphrase to get a working KMS
secrets[encryptionPassphraseKey] = "my-passphrase-from-kubernetes"
args.Secrets[encryptionPassphraseKey] = "my-passphrase-from-kubernetes"
kms, err = initSecretsMetadataKMS("secrets-metadata-unit-test", secrets)
kms, err = initSecretsMetadataKMS(args)
assert.NoError(t, err)
require.NotNil(t, kms)
assert.Equal(t, "secrets-metadata-unit-test", kms.GetID())
@ -62,9 +67,15 @@ func TestWorkflowSecretsMetadataKMS(t *testing.T) {
secrets := map[string]string{
encryptionPassphraseKey: "my-passphrase-from-kubernetes",
}
args := KMSInitializerArgs{
ID: "secrets-metadata-unit-test",
Tenant: "tenant",
Config: nil,
Secrets: secrets,
}
volumeID := "csi-vol-1b00f5f8-b1c1-11e9-8421-9243c1f659f0"
kms, err := initSecretsMetadataKMS("secrets-metadata-unit-test", secrets)
kms, err := initSecretsMetadataKMS(args)
assert.NoError(t, err)
require.NotNil(t, kms)
@ -90,3 +101,8 @@ func TestWorkflowSecretsMetadataKMS(t *testing.T) {
assert.NotEqual(t, "", decryptedDEK)
assert.Equal(t, plainDEK, decryptedDEK)
}
func TestSecretsMetadataKMSRegistered(t *testing.T) {
_, ok := kmsManager.providers[kmsTypeSecretsMetadata]
assert.True(t, ok)
}

View File

@ -260,21 +260,26 @@ func (vc *vaultConnection) Destroy() {
}
}
var _ = RegisterKMSProvider(KMSProvider{
UniqueID: kmsTypeVault,
Initializer: initVaultKMS,
})
// InitVaultKMS returns an interface to HashiCorp Vault KMS.
func InitVaultKMS(kmsID string, config map[string]interface{}, secrets map[string]string) (EncryptionKMS, error) {
func initVaultKMS(args KMSInitializerArgs) (EncryptionKMS, error) {
kms := &VaultKMS{}
err := kms.initConnection(kmsID, config)
err := kms.initConnection(args.ID, args.Config)
if err != nil {
return nil, fmt.Errorf("failed to initialize Vault connection: %w", err)
}
err = kms.initCertificates(config, secrets)
err = kms.initCertificates(args.Config, args.Secrets)
if err != nil {
return nil, fmt.Errorf("failed to initialize Vault certificates: %w", err)
}
vaultAuthPath := vaultDefaultAuthPath
err = setConfigString(&vaultAuthPath, config, "vaultAuthPath")
err = setConfigString(&vaultAuthPath, args.Config, "vaultAuthPath")
if err != nil {
return nil, err
}
@ -285,7 +290,7 @@ func InitVaultKMS(kmsID string, config map[string]interface{}, secrets map[strin
}
vaultRole := vaultDefaultRole
err = setConfigString(&vaultRole, config, "vaultRole")
err = setConfigString(&vaultRole, args.Config, "vaultRole")
if err != nil {
return nil, err
}
@ -293,7 +298,7 @@ func InitVaultKMS(kmsID string, config map[string]interface{}, secrets map[strin
// vault.VaultBackendPathKey is "secret/" by default, use vaultPassphraseRoot if configured
vaultPassphraseRoot := ""
err = setConfigString(&vaultPassphraseRoot, config, "vaultPassphraseRoot")
err = setConfigString(&vaultPassphraseRoot, args.Config, "vaultPassphraseRoot")
if err == nil {
// the old example did have "/v1/secret/", convert that format
if strings.HasPrefix(vaultPassphraseRoot, "/v1/") {
@ -306,7 +311,7 @@ func InitVaultKMS(kmsID string, config map[string]interface{}, secrets map[strin
}
kms.vaultPassphrasePath = vaultDefaultPassphrasePath
err = setConfigString(&kms.vaultPassphrasePath, config, "vaultPassphrasePath")
err = setConfigString(&kms.vaultPassphrasePath, args.Config, "vaultPassphrasePath")
if err != nil {
return nil, err
}

View File

@ -20,6 +20,8 @@ import (
"errors"
"os"
"testing"
"github.com/stretchr/testify/assert"
)
func TestDetectAuthMountPath(t *testing.T) {
@ -95,3 +97,8 @@ func TestSetConfigString(t *testing.T) {
t.Error("optionDefaultOverload should have been updated")
}
}
func TestVaultKMSRegistered(t *testing.T) {
_, ok := kmsManager.providers[kmsTypeVault]
assert.True(t, ok)
}

View File

@ -96,38 +96,44 @@ func (v *vaultTokenConf) convertStdVaultToCSIConfig(s *standardVault) {
}
}
// getVaultConfiguration fetches the vault configuration from the kubernetes
// configmap and converts the standard vault configuration (see json tag of
// standardVault structure) to the CSI vault configuration.
func getVaultConfiguration(namespace, name string) (map[string]interface{}, error) {
c := NewK8sClient()
cm, err := c.CoreV1().ConfigMaps(namespace).Get(context.Background(), name, metav1.GetOptions{})
// convertConfig takes the keys/values in standard Vault environment variable
// format, and converts them to the format that is used in the configuration
// file.
// This uses JSON marshaling and unmarshaling to map the Vault environment
// configuration into bytes, then in the standardVault struct, which is passed
// through convertStdVaultToCSIConfig before converting back to a
// map[string]interface{} configuration.
//
// FIXME: this can surely be simplified?!
func transformConfig(svMap map[string]interface{}) (map[string]interface{}, error) {
// convert the map to JSON
data, err := json.Marshal(svMap)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to convert config %T to JSON: %w", svMap, err)
}
config := make(map[string]interface{})
// convert the standard vault configuration to CSI vault configuration and
// store it in the map that CSI expects
for k, v := range cm.Data {
sv := &standardVault{}
err = json.Unmarshal([]byte(v), sv)
if err != nil {
return nil, fmt.Errorf("failed to Unmarshal the vault configuration for %q: %w", k, err)
}
vc := vaultTokenConf{}
vc.convertStdVaultToCSIConfig(sv)
data, err := json.Marshal(vc)
if err != nil {
return nil, fmt.Errorf("failed to Marshal the CSI vault configuration for %q: %w", k, err)
}
jsonMap := make(map[string]interface{})
err = json.Unmarshal(data, &jsonMap)
if err != nil {
return nil, fmt.Errorf("failed to Unmarshal the CSI vault configuration for %q: %w", k, err)
}
config[k] = jsonMap
// convert the JSON back to a standardVault struct
sv := &standardVault{}
err = json.Unmarshal(data, sv)
if err != nil {
return nil, fmt.Errorf("failed to Unmarshal the vault configuration: %w", err)
}
return config, nil
// convert the standardVault struct to a vaultTokenConf struct
vc := vaultTokenConf{}
vc.convertStdVaultToCSIConfig(sv)
data, err = json.Marshal(vc)
if err != nil {
return nil, fmt.Errorf("failed to Marshal the CSI vault configuration: %w", err)
}
// convert the vaultTokenConf struct to a map[string]interface{}
jsonMap := make(map[string]interface{})
err = json.Unmarshal(data, &jsonMap)
if err != nil {
return nil, fmt.Errorf("failed to Unmarshal the CSI vault configuration: %w", err)
}
return jsonMap, nil
}
/*
@ -171,11 +177,29 @@ type VaultTokensKMS struct {
TokenName string
}
var _ = RegisterKMSProvider(KMSProvider{
UniqueID: kmsTypeVaultTokens,
Initializer: initVaultTokensKMS,
})
// InitVaultTokensKMS returns an interface to HashiCorp Vault KMS.
func InitVaultTokensKMS(tenant, kmsID string, config map[string]interface{}) (EncryptionKMS, error) {
// InitVaultTokensKMS returns an interface to HashiCorp Vault KMS.
func initVaultTokensKMS(args KMSInitializerArgs) (EncryptionKMS, error) {
var err error
config := args.Config
_, ok := config[kmsProviderKey]
if ok {
// configuration comes from the ConfigMap, needs to be
// converted to vaultTokenConf type
config, err = transformConfig(config)
if err != nil {
return nil, fmt.Errorf("failed to convert configuration: %w", err)
}
}
kms := &VaultTokensKMS{}
kms.Tenant = tenant
err := kms.initConnection(kmsID, config)
err = kms.initConnection(args.ID, args.Config)
if err != nil {
return nil, fmt.Errorf("failed to initialize Vault connection: %w", err)
}
@ -190,14 +214,15 @@ func InitVaultTokensKMS(tenant, kmsID string, config map[string]interface{}) (En
}
// fetch the configuration for the tenant
if tenant != "" {
if args.Tenant != "" {
kms.Tenant = args.Tenant
tenantsMap, ok := config["tenants"]
if ok {
// tenants is a map per tenant, containing key/values
tenants, ok := tenantsMap.(map[string]map[string]interface{})
if ok {
// get the map for the tenant of the current operation
tenantConfig, ok := tenants[tenant]
tenantConfig, ok := tenants[args.Tenant]
if ok {
// override connection details from the tenant
err = kms.parseConfig(tenantConfig)
@ -216,9 +241,9 @@ func InitVaultTokensKMS(tenant, kmsID string, config map[string]interface{}) (En
// fetch the Vault Token from the Secret (TokenName) in the Kubernetes
// Namespace (tenant)
kms.vaultConfig[api.EnvVaultToken], err = getToken(tenant, kms.TokenName)
kms.vaultConfig[api.EnvVaultToken], err = getToken(args.Tenant, kms.TokenName)
if err != nil {
return nil, fmt.Errorf("failed fetching token from %s/%s: %w", tenant, kms.TokenName, err)
return nil, fmt.Errorf("failed fetching token from %s/%s: %w", args.Tenant, kms.TokenName, err)
}
err = kms.initCertificates(config)

View File

@ -21,6 +21,9 @@ import (
"errors"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestParseConfig(t *testing.T) {
@ -34,7 +37,7 @@ func TestParseConfig(t *testing.T) {
t.Errorf("unexpected error (%T): %s", err, err)
}
// fill default options (normally done in InitVaultTokensKMS)
// fill default options (normally done in initVaultTokensKMS)
config["vaultAddress"] = "https://vault.default.cluster.svc"
config["tenantConfigName"] = vaultTokensDefaultConfigName
config["tenantTokenName"] = vaultTokensDefaultTokenName
@ -65,7 +68,7 @@ func TestParseConfig(t *testing.T) {
// TestInitVaultTokensKMS verifies that passing partial and complex
// configurations get applied correctly.
//
// When vault.New() is called at the end of InitVaultTokensKMS(), errors will
// When vault.New() is called at the end of initVaultTokensKMS(), errors will
// mention the missing VAULT_TOKEN, and that is expected.
func TestInitVaultTokensKMS(t *testing.T) {
if true {
@ -74,39 +77,44 @@ func TestInitVaultTokensKMS(t *testing.T) {
return
}
config := make(map[string]interface{})
args := KMSInitializerArgs{
ID: "vault-tokens-config",
Tenant: "bob",
Config: make(map[string]interface{}),
Secrets: nil,
}
// empty config map
_, err := InitVaultTokensKMS("bob", "vault-tokens-config", config)
_, err := initVaultTokensKMS(args)
if !errors.Is(err, errConfigOptionMissing) {
t.Errorf("unexpected error (%T): %s", err, err)
}
// fill required options
config["vaultAddress"] = "https://vault.default.cluster.svc"
args.Config["vaultAddress"] = "https://vault.default.cluster.svc"
// parsing with all required options
_, err = InitVaultTokensKMS("bob", "vault-tokens-config", config)
_, err = initVaultTokensKMS(args)
if err != nil && !strings.Contains(err.Error(), "VAULT_TOKEN") {
t.Errorf("unexpected error: %s", err)
}
// fill tenants
tenants := make(map[string]interface{})
config["tenants"] = tenants
args.Config["tenants"] = tenants
// empty tenants list
_, err = InitVaultTokensKMS("bob", "vault-tokens-config", config)
_, err = initVaultTokensKMS(args)
if err != nil && !strings.Contains(err.Error(), "VAULT_TOKEN") {
t.Errorf("unexpected error: %s", err)
}
// add tenant "bob"
bob := make(map[string]interface{})
config["tenants"].(map[string]interface{})["bob"] = bob
bob["vaultAddress"] = "https://vault.bob.example.org"
args.Config["tenants"].(map[string]interface{})["bob"] = bob
_, err = InitVaultTokensKMS("bob", "vault-tokens-config", config)
_, err = initVaultTokensKMS(args)
if err != nil && !strings.Contains(err.Error(), "VAULT_TOKEN") {
t.Errorf("unexpected error: %s", err)
}
@ -158,3 +166,33 @@ func TestStdVaultToCSIConfig(t *testing.T) {
t.Errorf("unexpected value for VaultCAVerify: %s", v.VaultCAVerify)
}
}
func TestTransformConfig(t *testing.T) {
cm := make(map[string]interface{})
cm["KMS_PROVIDER"] = "vaulttokens"
cm["VAULT_ADDR"] = "https://vault.example.com"
cm["VAULT_BACKEND_PATH"] = "/secret"
cm["VAULT_CACERT"] = ""
cm["VAULT_TLS_SERVER_NAME"] = "vault.example.com"
cm["VAULT_CLIENT_CERT"] = ""
cm["VAULT_CLIENT_KEY"] = ""
cm["VAULT_NAMESPACE"] = "a-department"
cm["VAULT_SKIP_VERIFY"] = "true" // inverse of "vaultCAVerify"
config, err := transformConfig(cm)
require.NoError(t, err)
assert.Equal(t, config["encryptionKMSType"], cm["KMS_PROVIDER"])
assert.Equal(t, config["vaultAddress"], cm["VAULT_ADDR"])
assert.Equal(t, config["vaultBackendPath"], cm["VAULT_BACKEND_PATH"])
assert.Equal(t, config["vaultCAFromSecret"], cm["VAULT_CACERT"])
assert.Equal(t, config["vaultTLSServerName"], cm["VAULT_TLS_SERVER_NAME"])
assert.Equal(t, config["vaultClientCertFromSecret"], cm["VAULT_CLIENT_CERT"])
assert.Equal(t, config["vaultClientCertKeyFromSecret"], cm["VAULT_CLIENT_KEY"])
assert.Equal(t, config["vaultNamespace"], cm["VAULT_NAMESPACE"])
assert.Equal(t, config["vaultCAVerify"], "false")
}
func TestVaultTokensKMSRegistered(t *testing.T) {
_, ok := kmsManager.providers[kmsTypeVaultTokens]
assert.True(t, ok)
}