Skip to content

Commit

Permalink
plugin: add generic KES KeyStore plugin v1 (#121)
Browse files Browse the repository at this point in the history
This commit adds a generic KeyStore plugin API
to the KES server.

Now, the KES server can talk to an external plugin
that implements four REST endpoints for creating,
listing, accessing and deleting keys.

This commit also adds the plugin specification.

With KeyStore plugins it is possible to support
proprietary/custom KMS/KeyStore implementations
that should not be published.

For a more detailed explanation about plugins
and how they should be implemented take a look
at the generic/spec-v1.md

Signed-off-by: Andreas Auernhammer <aead@mail.de>
  • Loading branch information
Andreas Auernhammer committed May 3, 2021
1 parent b9e4806 commit 8af5141
Show file tree
Hide file tree
Showing 7 changed files with 867 additions and 4 deletions.
1 change: 0 additions & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ linters:
- unused
- structcheck
- prealloc
- maligned
- unconvert

issues:
Expand Down
40 changes: 39 additions & 1 deletion cmd/kes/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/minio/kes/internal/fs"
"github.com/minio/kes/internal/gcp"
"github.com/minio/kes/internal/gemalto"
"github.com/minio/kes/internal/generic"
"github.com/minio/kes/internal/mem"
"github.com/minio/kes/internal/secret"
"github.com/minio/kes/internal/vault"
Expand Down Expand Up @@ -226,6 +227,15 @@ type kmsServerConfig struct {
Path string `yaml:"path"`
} `yaml:"fs"`

Generic struct {
Endpoint string `yaml:"endpoint"`
TLS struct {
KeyPath string `yaml:"key"`
CertPath string `yaml:"cert"`
CAPath string `yaml:"ca"`
} `yaml:"tls"`
} `yaml:"generic"`

Vault struct {
Endpoint string `yaml:"endpoint"`
EnginePath string `yaml:"engine"`
Expand Down Expand Up @@ -322,6 +332,8 @@ func (config *kmsServerConfig) SetDefaults() {
// returns an error.
func (config *kmsServerConfig) Verify() error {
switch {
case config.Fs.Path != "" && config.Generic.Endpoint != "":
return errors.New("ambiguous configuration: FS and Generic endpoint specified at the same time")
case config.Fs.Path != "" && config.Vault.Endpoint != "":
return errors.New("ambiguous configuration: FS and Hashicorp Vault endpoint specified at the same time")
case config.Fs.Path != "" && config.Aws.SecretsManager.Endpoint != "":
Expand All @@ -330,6 +342,14 @@ func (config *kmsServerConfig) Verify() error {
return errors.New("ambiguous configuration: FS and Gemalto KeySecure endpoint are specified at the same time")
case config.Fs.Path != "" && config.GCP.SecretManager.ProjectID != "":
return errors.New("ambiguous configuration: FS and GCP secret manager are specified at the same time")
case config.Generic.Endpoint != "" && config.Vault.Endpoint != "":
return errors.New("ambiguous configuration: Generic and Hashicorp Vault endpoint are specified at the same time")
case config.Generic.Endpoint != "" && config.Aws.SecretsManager.Endpoint != "":
return errors.New("ambiguous configuration: Generic and AWS SecretsManager endpoint are specified at the same time")
case config.Generic.Endpoint != "" && config.Gemalto.KeySecure.Endpoint != "":
return errors.New("ambiguous configuration: Generic and Gemalto KeySecure endpoint are specified at the same time")
case config.Generic.Endpoint != "" && config.GCP.SecretManager.ProjectID != "":
return errors.New("ambiguous configuration: Generic and GCP SecretManager endpoint are specified at the same time")
case config.Vault.Endpoint != "" && config.Aws.SecretsManager.Endpoint != "":
return errors.New("ambiguous configuration: Hashicorp Vault and AWS SecretsManager endpoint are specified at the same time")
case config.Vault.Endpoint != "" && config.Gemalto.KeySecure.Endpoint != "":
Expand Down Expand Up @@ -381,6 +401,21 @@ func (config *kmsServerConfig) Connect(quiet quiet, errorLog *stdlog.Logger) (*s
Dir: config.Fs.Path,
ErrorLog: errorLog,
}
case config.Generic.Endpoint != "":
genericStore := &generic.Store{
Endpoint: config.Generic.Endpoint,
KeyPath: config.Generic.TLS.KeyPath,
CertPath: config.Generic.TLS.CertPath,
CAPath: config.Generic.TLS.CAPath,
ErrorLog: errorLog,
}
msg := fmt.Sprintf("Authenticating to generic KeyStore '%s' ... ", config.Generic.Endpoint)
quiet.Print(msg)
if err := genericStore.Authenticate(); err != nil {
return nil, fmt.Errorf("failed to connect to generic KeyStore: %v", err)
}
quiet.ClearMessage(msg)
store.Remote = genericStore
case config.Vault.Endpoint != "":
vaultStore := &vault.Store{
Addr: config.Vault.Endpoint,
Expand Down Expand Up @@ -446,7 +481,7 @@ func (config *kmsServerConfig) Connect(quiet quiet, errorLog *stdlog.Logger) (*s
}

msg := fmt.Sprintf("Authenticating to Gemalto KeySecure '%s' ... ", gemaltoStore.Endpoint)
quiet.Printf(msg)
quiet.Print(msg)
if err := gemaltoStore.Authenticate(); err != nil {
return nil, fmt.Errorf("failed to connect to Gemalto KeySecure: %v", err)
}
Expand Down Expand Up @@ -489,6 +524,9 @@ func (config *kmsServerConfig) Description() (kind, endpoint string, err error)
if endpoint, err = filepath.Abs(config.Fs.Path); err != nil {
endpoint = config.Fs.Path
}
case config.Generic.Endpoint != "":
kind = "Generic"
endpoint = config.Generic.Endpoint
case config.Vault.Endpoint != "":
kind = "Hashicorp Vault"
endpoint = config.Vault.Endpoint
Expand Down
4 changes: 2 additions & 2 deletions internal/gemalto/key-secure.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func (s *KeySecure) Get(key string) (string, error) {
}

// Delete removes a the value associated with the given key
// from Vault, if it exists.
// from Gemalto, if it exists.
func (s *KeySecure) Delete(key string) error {
url := fmt.Sprintf("%s/api/v1/vault/secrets/%s?type=name", s.Endpoint, key)
req, err := http.NewRequest(http.MethodDelete, url, nil)
Expand Down Expand Up @@ -295,7 +295,7 @@ func (s *KeySecure) List(ctx context.Context) (secret.Iterator, error) {
url := fmt.Sprintf("%s/api/v1/vault/secrets?limit=%d&skip=%d", s.Endpoint, limit, skip)
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
logf(s.ErrorLog, "gemalto: failed to list keys: %q", err)
logf(s.ErrorLog, "gemalto: failed to list keys: %v", err)
iterator.SetErr(errListKey)
break
}
Expand Down

0 comments on commit 8af5141

Please sign in to comment.