Add cloudprovidedkms provider support

This commit is contained in:
Saksham Sharma 2017-07-27 16:06:20 -07:00
parent b76c63a9f0
commit 68a32c06b4
4 changed files with 105 additions and 11 deletions

View File

@ -36,10 +36,11 @@ import (
) )
const ( const (
aesCBCTransformerPrefixV1 = "k8s:enc:aescbc:v1:" aesCBCTransformerPrefixV1 = "k8s:enc:aescbc:v1:"
aesGCMTransformerPrefixV1 = "k8s:enc:aesgcm:v1:" aesGCMTransformerPrefixV1 = "k8s:enc:aesgcm:v1:"
secretboxTransformerPrefixV1 = "k8s:enc:secretbox:v1:" secretboxTransformerPrefixV1 = "k8s:enc:secretbox:v1:"
kmsTransformerPrefixV1 = "k8s:enc:kms:v1:" kmsTransformerPrefixV1 = "k8s:enc:kms:v1:"
cloudProvidedKMSTransformerPrefixV1 = "k8s:enc:cloudprovidedkms:v1:"
) )
// GetTransformerOverrides returns the transformer overrides by reading and parsing the encryption provider configuration file // GetTransformerOverrides returns the transformer overrides by reading and parsing the encryption provider configuration file
@ -150,7 +151,6 @@ func GetPrefixTransformers(config *ResourceConfig) ([]value.PrefixTransformer, e
if found == true { if found == true {
return nil, fmt.Errorf("more than one provider specified in a single element, should split into different list elements") return nil, fmt.Errorf("more than one provider specified in a single element, should split into different list elements")
} }
f, err := os.Open(provider.KMS.ConfigFile) f, err := os.Open(provider.KMS.ConfigFile)
if err != nil { if err != nil {
return nil, fmt.Errorf("error opening KMS provider configuration file %q: %v", provider.KMS.ConfigFile, err) return nil, fmt.Errorf("error opening KMS provider configuration file %q: %v", provider.KMS.ConfigFile, err)
@ -163,7 +163,19 @@ func GetPrefixTransformers(config *ResourceConfig) ([]value.PrefixTransformer, e
if pluginFound == false { if pluginFound == false {
return nil, fmt.Errorf("KMS plugin %q not found", provider.KMS.Name) return nil, fmt.Errorf("KMS plugin %q not found", provider.KMS.Name)
} }
transformer, err = getEnvelopePrefixTransformer(provider.KMS, envelopeService) transformer, err = getEnvelopePrefixTransformer(provider.KMS.CoreKMSConfig, envelopeService, kmsTransformerPrefixV1)
found = true
}
if provider.CloudProvidedKMS != nil {
if found == true {
return nil, fmt.Errorf("more than one provider specified in a single element, should split into different list elements")
}
envelopeService, err := KMSPluginRegistry.getCloudProvidedPlugin(provider.CloudProvidedKMS.Name)
if err != nil {
return nil, fmt.Errorf("could not configure Cloud-Provided KMS plugin %q, %v", provider.CloudProvidedKMS.Name, err)
}
transformer, err = getEnvelopePrefixTransformer(provider.CloudProvidedKMS.CoreKMSConfig, envelopeService, cloudProvidedKMSTransformerPrefixV1)
found = true found = true
} }
@ -284,13 +296,13 @@ func GetSecretboxPrefixTransformer(config *SecretboxConfig) (value.PrefixTransfo
// getEnvelopePrefixTransformer returns a prefix transformer from the provided config. // getEnvelopePrefixTransformer returns a prefix transformer from the provided config.
// envelopeService is used as the root of trust. // envelopeService is used as the root of trust.
func getEnvelopePrefixTransformer(config *KMSConfig, envelopeService envelope.Service) (value.PrefixTransformer, error) { func getEnvelopePrefixTransformer(config *CoreKMSConfig, envelopeService envelope.Service, prefix string) (value.PrefixTransformer, error) {
envelopeTransformer, err := envelope.NewEnvelopeTransformer(envelopeService, config.CacheSize, aestransformer.NewCBCTransformer) envelopeTransformer, err := envelope.NewEnvelopeTransformer(envelopeService, config.CacheSize, aestransformer.NewCBCTransformer)
if err != nil { if err != nil {
return value.PrefixTransformer{}, err return value.PrefixTransformer{}, err
} }
return value.PrefixTransformer{ return value.PrefixTransformer{
Transformer: envelopeTransformer, Transformer: envelopeTransformer,
Prefix: []byte(kmsTransformerPrefixV1 + config.Name + ":"), Prefix: []byte(prefix + config.Name + ":"),
}, nil }, nil
} }

View File

@ -58,6 +58,9 @@ resources:
name: testprovider name: testprovider
configfile: testproviderconfig configfile: testproviderconfig
cachesize: 10 cachesize: 10
- cloudprovidedkms:
name: testprovider
cachesize: 10
- aescbc: - aescbc:
keys: keys:
- name: key1 - name: key1
@ -97,6 +100,9 @@ resources:
secret: c2VjcmV0IGlzIHNlY3VyZQ== secret: c2VjcmV0IGlzIHNlY3VyZQ==
- name: key2 - name: key2
secret: dGhpcyBpcyBwYXNzd29yZA== secret: dGhpcyBpcyBwYXNzd29yZA==
- cloudprovidedkms:
name: testprovider
cachesize: 10
- identity: {} - identity: {}
` `
@ -118,6 +124,9 @@ resources:
configfile: testproviderconfig configfile: testproviderconfig
cachesize: 10 cachesize: 10
- identity: {} - identity: {}
- cloudprovidedkms:
name: testprovider
cachesize: 10
- secretbox: - secretbox:
keys: keys:
- name: key1 - name: key1
@ -141,6 +150,9 @@ resources:
keys: keys:
- name: key1 - name: key1
secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY= secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
- cloudprovidedkms:
name: testprovider
cachesize: 10
- aescbc: - aescbc:
keys: keys:
- name: key1 - name: key1
@ -182,6 +194,45 @@ resources:
- name: key2 - name: key2
secret: dGhpcyBpcyBwYXNzd29yZA== secret: dGhpcyBpcyBwYXNzd29yZA==
- identity: {} - identity: {}
- cloudprovidedkms:
name: testprovider
cachesize: 10
- aesgcm:
keys:
- name: key1
secret: c2VjcmV0IGlzIHNlY3VyZQ==
- name: key2
secret: dGhpcyBpcyBwYXNzd29yZA==
`
correctConfigWithCloudProvidedKMSFirst = `
kind: EncryptionConfig
apiVersion: v1
resources:
- resources:
- secrets
providers:
- cloudprovidedkms:
name: testprovider
cachesize: 10
- kms:
name: testprovider
configfile: testproviderconfig
cachesize: 10
- secretbox:
keys:
- name: key1
secret: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
- aescbc:
keys:
- name: key1
secret: c2VjcmV0IGlzIHNlY3VyZQ==
- name: key2
secret: dGhpcyBpcyBwYXNzd29yZA==
- identity: {}
- cloudprovidedkms:
name: testprovider
cachesize: 10
- aesgcm: - aesgcm:
keys: keys:
- name: key1 - name: key1
@ -252,6 +303,12 @@ func TestEncryptionProviderConfigCorrect(t *testing.T) {
KMSPluginRegistry.Register(testEnvelopeServiceProviderName, func(config io.Reader) (envelope.Service, error) { KMSPluginRegistry.Register(testEnvelopeServiceProviderName, func(config io.Reader) (envelope.Service, error) {
return &testEnvelopeService{}, nil return &testEnvelopeService{}, nil
}) })
KMSPluginRegistry.RegisterCloudProvidedKMSPlugin(func(name string) (envelope.Service, error) {
if name == testEnvelopeServiceProviderName {
return &testEnvelopeService{}, nil
}
return nil, fmt.Errorf("no such cloud provided KMS plugin registered: %q", name)
})
// Creates compound/prefix transformers with different ordering of available transformers. // Creates compound/prefix transformers with different ordering of available transformers.
// Transforms data using one of them, and tries to untransform using the others. // Transforms data using one of them, and tries to untransform using the others.
@ -281,12 +338,18 @@ func TestEncryptionProviderConfigCorrect(t *testing.T) {
t.Fatalf("error while parsing configuration file: %s.\nThe file was:\n%s", err, correctConfigWithKMSFirst) t.Fatalf("error while parsing configuration file: %s.\nThe file was:\n%s", err, correctConfigWithKMSFirst)
} }
cloudProvidedKMSFirstTransformerOverrides, err := ParseEncryptionConfiguration(strings.NewReader(correctConfigWithCloudProvidedKMSFirst))
if err != nil {
t.Fatalf("error while parsing configuration file: %s.\nThe file was:\n%s", err, correctConfigWithCloudProvidedKMSFirst)
}
// Pick the transformer for any of the returned resources. // Pick the transformer for any of the returned resources.
identityFirstTransformer := identityFirstTransformerOverrides[schema.ParseGroupResource("secrets")] identityFirstTransformer := identityFirstTransformerOverrides[schema.ParseGroupResource("secrets")]
aesGcmFirstTransformer := aesGcmFirstTransformerOverrides[schema.ParseGroupResource("secrets")] aesGcmFirstTransformer := aesGcmFirstTransformerOverrides[schema.ParseGroupResource("secrets")]
aesCbcFirstTransformer := aesCbcFirstTransformerOverrides[schema.ParseGroupResource("secrets")] aesCbcFirstTransformer := aesCbcFirstTransformerOverrides[schema.ParseGroupResource("secrets")]
secretboxFirstTransformer := secretboxFirstTransformerOverrides[schema.ParseGroupResource("secrets")] secretboxFirstTransformer := secretboxFirstTransformerOverrides[schema.ParseGroupResource("secrets")]
kmsFirstTransformer := kmsFirstTransformerOverrides[schema.ParseGroupResource("secrets")] kmsFirstTransformer := kmsFirstTransformerOverrides[schema.ParseGroupResource("secrets")]
cloudProvidedKMSFirstTransformer := cloudProvidedKMSFirstTransformerOverrides[schema.ParseGroupResource("secrets")]
context := value.DefaultContext([]byte(sampleContextText)) context := value.DefaultContext([]byte(sampleContextText))
originalText := []byte(sampleText) originalText := []byte(sampleText)
@ -300,6 +363,7 @@ func TestEncryptionProviderConfigCorrect(t *testing.T) {
{secretboxFirstTransformer, "secretboxFirst"}, {secretboxFirstTransformer, "secretboxFirst"},
{identityFirstTransformer, "identityFirst"}, {identityFirstTransformer, "identityFirst"},
{kmsFirstTransformer, "kmsFirst"}, {kmsFirstTransformer, "kmsFirst"},
{cloudProvidedKMSFirstTransformer, "cloudProvidedKMSFirst"},
} }
for _, testCase := range transformers { for _, testCase := range transformers {

View File

@ -18,6 +18,7 @@ package encryptionconfig
import ( import (
"bytes" "bytes"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"reflect" "reflect"
@ -112,6 +113,9 @@ func (ps *KMSPlugins) fetchPluginFromRegistry(name string) (Factory, bool) {
// getCloudProvidedPlugin creates an instance of the named cloud provided KMS plugin. // getCloudProvidedPlugin creates an instance of the named cloud provided KMS plugin.
func (ps *KMSPlugins) getCloudProvidedPlugin(name string) (envelope.Service, error) { func (ps *KMSPlugins) getCloudProvidedPlugin(name string) (envelope.Service, error) {
if ps.cloudKMS == nil {
return nil, fmt.Errorf("no cloud registered for KMS plugins")
}
return ps.cloudKMS(name) return ps.cloudKMS(name)
} }

View File

@ -45,8 +45,11 @@ type ProviderConfig struct {
Secretbox *SecretboxConfig `json:"secretbox,omitempty"` Secretbox *SecretboxConfig `json:"secretbox,omitempty"`
// identity is the (empty) configuration for the identity transformer. // identity is the (empty) configuration for the identity transformer.
Identity *IdentityConfig `json:"identity,omitempty"` Identity *IdentityConfig `json:"identity,omitempty"`
// kms contains the name and path to configuration file for a KMS based envelope transformer. // kms contains the name, cache size and path to configuration file for a KMS based envelope transformer.
KMS *KMSConfig `json:"kms,omitempty"` KMS *KMSConfig `json:"kms,omitempty"`
// cloudProvidedKMSConfig contains the name and cache size for a KMS based envelope transformer which uses
// the KMS provided by the cloud.
CloudProvidedKMS *CloudProvidedKMSConfig `json:"cloudprovidedkms,omitempty"`
} }
// AESConfig contains the API configuration for an AES transformer. // AESConfig contains the API configuration for an AES transformer.
@ -74,13 +77,24 @@ type Key struct {
// IdentityConfig is an empty struct to allow identity transformer in provider configuration. // IdentityConfig is an empty struct to allow identity transformer in provider configuration.
type IdentityConfig struct{} type IdentityConfig struct{}
// KMS contains the name and path to configuration file for a KMS based envelope transformer. // CoreKMSConfig contains the name and cache sized for a KMS based envelope transformer.
type KMSConfig struct { type CoreKMSConfig struct {
// name is the name of the KMS plugin to be used. // name is the name of the KMS plugin to be used.
Name string `json:"name"` Name string `json:"name"`
// cacheSize is the maximum number of secrets which are cached in memory. The default value is 1000. // cacheSize is the maximum number of secrets which are cached in memory. The default value is 1000.
// +optional // +optional
CacheSize int `json:"cachesize,omitempty"` CacheSize int `json:"cachesize,omitempty"`
}
// KMSConfig contains the name, cache size and path to configuration file for a KMS based envelope transformer.
type KMSConfig struct {
*CoreKMSConfig
// configfile is the path to the configuration file for the named KMS provider. // configfile is the path to the configuration file for the named KMS provider.
ConfigFile string `json:"configfile"` ConfigFile string `json:"configfile"`
} }
// CloudProvidedKMSConfig contains the name and cache size for a KMS based envelope transformer which uses
// the KMS provided by the cloud.
type CloudProvidedKMSConfig struct {
*CoreKMSConfig
}