Skip to content

Commit

Permalink
feat: kms per profile & bdd for eddsa-rdfc-2022 (#1766)
Browse files Browse the repository at this point in the history
* feat: kms per profile

* feat: kms type

* fix: verify channel

* fix: tests

* fix: more tests

* fix: kms type

* fix: tests

* feat: add more tests

* feat: add master key as param
  • Loading branch information
skynet2 authored Oct 1, 2024
1 parent 28eb83c commit 41cf070
Show file tree
Hide file tree
Showing 22 changed files with 463 additions and 100 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ ALPINE_IMAGE ?=alpine
OPENSSL_IMAGE ?=frapsoft/openssl
GOPROXY ?= https://proxy.golang.org

VC_FRAMEWORK_VERSION = 62cdfe76225e3bec435d678a331a064e602a4dcf
VC_FRAMEWORK_VERSION = a58759112df5dec505bb1bd37c1baa1c8fcd823c
KMS_FRAMEWORK_VERSION = 59c2830d27fd44f9a3a663242a4aa61544ce622e
DID_GO_VERSION = aa500e57d8bdf51c90c20d3a6c815fdc76f716c3
SIDE_TREE_VERSION = f4260aff710479ba5fa3f0c61b51d451d9041225
Expand Down
10 changes: 10 additions & 0 deletions cmd/vc-rest/startcmd/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ const (
aliasPrefixFlagUsage = "alias prefix" +
commonEnvVarUsageText + aliasPrefixEnvKey

masterKeyFlagName = "local-kms-master-key"
masterKeyEnvKey = "VC_REST_LOCAL_KMS_MASTER_KEY"
masterKeyFlagUsage = "Local KMS master key" +
commonEnvVarUsageText + masterKeyEnvKey

// Linter gosec flags these as "potential hardcoded credentials". They are not, hence the nolint annotations.
kmsSecretsDatabaseTypeFlagName = "default-kms-secrets-database-type" //nolint: gosec
kmsSecretsDatabaseTypeEnvKey = "VC_REST_DEFAULT_KMS_SECRETS_DATABASE_TYPE" //nolint: gosec
Expand Down Expand Up @@ -490,6 +495,7 @@ type kmsParameters struct {
kmsSecretsDatabasePrefix string
secretLockKeyPath string
aliasPrefix string
masterKey string
}

// nolint: gocyclo,funlen
Expand Down Expand Up @@ -953,6 +959,8 @@ func getKMSParameters(cmd *cobra.Command) (*kmsParameters, error) {
secretLockKeyPath := cmdutils.GetUserSetOptionalVarFromString(cmd, secretLockKeyPathFlagName, secretLockKeyPathEnvKey)
aliasPrefix := cmdutils.GetUserSetOptionalVarFromString(cmd, aliasPrefixFlagName, aliasPrefixEnvKey)

masterKey := cmdutils.GetUserSetOptionalVarFromString(cmd, masterKeyFlagName, masterKeyEnvKey)

keyDatabaseType, err := cmdutils.GetUserSetVarFromString(cmd, kmsSecretsDatabaseTypeFlagName,
kmsSecretsDatabaseTypeEnvKey, kmsType != kms.Local)
if err != nil {
Expand All @@ -972,6 +980,7 @@ func getKMSParameters(cmd *cobra.Command) (*kmsParameters, error) {
kmsSecretsDatabaseURL: keyDatabaseURL,
kmsSecretsDatabasePrefix: keyDatabasePrefix,
aliasPrefix: aliasPrefix,
masterKey: masterKey,
}, nil
}

Expand Down Expand Up @@ -1150,6 +1159,7 @@ func createFlags(startCmd *cobra.Command) {
startCmd.Flags().String(kmsEndpointFlagName, "", kmsEndpointFlagUsage)
startCmd.Flags().String(secretLockKeyPathFlagName, "", secretLockKeyPathFlagUsage)
startCmd.Flags().String(aliasPrefixFlagName, "", aliasPrefixFlagUsage)
startCmd.Flags().String(masterKeyFlagName, "", masterKeyFlagUsage)
startCmd.Flags().String(kmsRegionFlagName, "", kmsRegionFlagUsage)
startCmd.Flags().StringP(tlsCertificateFlagName, "", "", tlsCertificateFlagUsage)
startCmd.Flags().StringP(tlsKeyFlagName, "", "", tlsKeyFlagUsage)
Expand Down
9 changes: 6 additions & 3 deletions cmd/vc-rest/startcmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,7 @@ func buildEchoHandler(

tlsConfig := &tls.Config{RootCAs: conf.RootCAs, MinVersion: tls.VersionTLS12}

defaultVCSKeyManager, err := kms.NewAriesKeyManager(&kms.Config{
defaultKmsConfig := kms.Config{
KMSType: conf.StartupParameters.kmsParameters.kmsType,
Endpoint: conf.StartupParameters.kmsParameters.kmsEndpoint,
Region: conf.StartupParameters.kmsParameters.kmsRegion,
Expand All @@ -460,12 +460,15 @@ func buildEchoHandler(
DBURL: conf.StartupParameters.dbParameters.databaseURL,
DBPrefix: conf.StartupParameters.dbParameters.databasePrefix,
AliasPrefix: conf.StartupParameters.kmsParameters.aliasPrefix,
}, metrics)
MasterKey: conf.StartupParameters.kmsParameters.masterKey,
}

defaultVCSKeyManager, err := kms.NewAriesKeyManager(&defaultKmsConfig, metrics)
if err != nil {
return nil, fmt.Errorf("failed to create default kms: %w", err)
}

kmsRegistry := kms.NewRegistry(defaultVCSKeyManager)
kmsRegistry := kms.NewRegistry(defaultVCSKeyManager, defaultKmsConfig, metrics)

var redisClient, redisClientNoTracing *redisclient.Client
if conf.StartupParameters.transientDataParams.storeType == redisStore {
Expand Down
4 changes: 3 additions & 1 deletion pkg/doc/vc/crypto/dataIntegrity.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ func (c *Crypto) signCredentialLDPDataIntegrity(signerData *vc.Signer,
}

func (c *Crypto) getDataIntegritySignerInitializer(
dataIntegritySuiteType string, signer vc.SignerAlgorithm) (dataintegritysuite.SignerInitializer, error) {
dataIntegritySuiteType string,
signer vc.SignerAlgorithm,
) (dataintegritysuite.SignerInitializer, error) {
switch dataIntegritySuiteType { //nolint: exhaustive
case ecdsa2019.SuiteType, ecdsa2019.SuiteTypeNew:
return ecdsa2019.NewSignerInitializer(&ecdsa2019.SignerInitializerOptions{
Expand Down
31 changes: 22 additions & 9 deletions pkg/kms/arieskms.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package kms
import (
"context"
"fmt"
"io"
"strings"
"time"

Expand Down Expand Up @@ -125,7 +126,10 @@ func NewAriesKeyManager(cfg *Config, metrics metricsProvider) (*KeyManager, erro
}

func createLocalKMS(cfg *Config) (api.Suite, error) {
secretLockService, err := createLocalSecretLock(cfg.SecretLockKeyPath)
secretLockService, err := createLocalSecretLock(
cfg.SecretLockKeyPath,
cfg.MasterKey,
)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -187,14 +191,23 @@ func (km *KeyManager) NewVCSigner(
return signer.NewKMSSigner(fks, signatureType, km.metrics), nil
}

func createLocalSecretLock(keyPath string) (secretlock.Service, error) {
if keyPath == "" {
return nil, fmt.Errorf("no key defined for local secret lock")
}

primaryKeyReader, err := local.MasterKeyFromPath(keyPath)
if err != nil {
return nil, err
func createLocalSecretLock(
keyPath string,
kmsMasterKey string,
) (secretlock.Service, error) {
var err error
var primaryKeyReader io.Reader

if kmsMasterKey != "" {
primaryKeyReader = strings.NewReader(kmsMasterKey)
} else {
if keyPath == "" {
return nil, fmt.Errorf("no key defined for local secret lock")
}
primaryKeyReader, err = local.MasterKeyFromPath(keyPath)
if err != nil {
return nil, err
}
}

secretLock, err := local.NewService(primaryKeyReader, nil)
Expand Down
44 changes: 42 additions & 2 deletions pkg/kms/arieskms_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"io"
"net/http"
"os"
"testing"
Expand Down Expand Up @@ -87,6 +88,26 @@ func TestNewLocalKeyManager(t *testing.T) {
require.NoError(t, err)
})

t.Run("Success env", func(t *testing.T) {
pool, mongoDBResource := startMongoDBContainer(t)

defer func() {
require.NoError(t, pool.Purge(mongoDBResource), "failed to purge MongoDB resource")
}()

km, err := kms.NewAriesKeyManager(&kms.Config{
KMSType: kms.Local,
SecretLockKeyPath: secretLockKeyFile,
DBType: "mongodb",
DBURL: mongoDBConnString,
DBPrefix: "test",
MasterKey: "00kIMo3wwfp1r8OOR8QMSkyIByY8ZHBKJy4l0u2i9f4=",
}, nil)

require.NoError(t, err)
require.NotNil(t, km)
})

t.Run("Fail mongodb", func(t *testing.T) {
km, err := kms.NewAriesKeyManager(&kms.Config{
KMSType: kms.Local,
Expand Down Expand Up @@ -157,10 +178,10 @@ func TestNewAWSKeyManager(t *testing.T) {
require.NotNil(t, km)
require.NoError(t, err)

_, _, err = km.CreateJWKKey(arieskms.ED25519Type)
_, _, err = km.CreateJWKKey(arieskms.NISTP384ECDHKW)

require.Error(t, err)
require.Contains(t, err.Error(), "key not supported ED25519")
require.Contains(t, err.Error(), "key not supported NISTP384ECDHKW")
})
}

Expand Down Expand Up @@ -227,6 +248,25 @@ func startMongoDBContainer(t *testing.T) (*dctest.Pool, *dctest.Resource) {
return pool, mongoDBResource
}

func TestGenerateMasterKey(t *testing.T) {
masterKey, err := GenerateMasterKey(32) // aes-256
require.NoError(t, err)
require.Len(t, masterKey, 32)

masterKeyBase64 := base64.URLEncoding.EncodeToString(masterKey)
require.NotEmpty(t, masterKeyBase64)
}

// GenerateMasterKey generates a random master key of specified length.
func GenerateMasterKey(length int) ([]byte, error) {
masterKey := make([]byte, length)
_, err := io.ReadFull(rand.Reader, masterKey)
if err != nil {
return nil, err
}
return masterKey, nil
}

func waitForMongoDBToBeUp() error {
return backoff.Retry(pingMongoDB, backoff.WithMaxRetries(backoff.NewConstantBackOff(time.Second), 30))
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/kms/aws/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,8 @@ func (s *Service) Create(kt arieskms.KeyType) (string, interface{}, error) {
var keySpec types.KeySpec

switch string(kt) {
case arieskms.ED25519:
keySpec = types.KeySpecEccNistP256
case arieskms.ECDSAP256DER:
keySpec = types.KeySpecEccNistP256
case arieskms.ECDSAP384DER:
Expand Down
2 changes: 1 addition & 1 deletion pkg/kms/aws/service_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 6 additions & 10 deletions pkg/kms/aws/service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,9 @@ func TestCreate(t *testing.T) {

svc := New(awsConfig, metric, "", []Opts{}...)

_, _, err := svc.Create(arieskms.ED25519)
_, _, err := svc.Create(arieskms.X25519ECDHKW)
require.Error(t, err)
require.Contains(t, err.Error(), "key not supported ED25519")
require.Contains(t, err.Error(), "key not supported X25519ECDHKW")
})

t.Run("create error", func(t *testing.T) {
Expand Down Expand Up @@ -555,22 +555,18 @@ func TestCreateAndPubKeyBytes(t *testing.T) {

svc := New(&awsConfig, metric, "", []Opts{}...)

_, _, err := svc.CreateAndExportPubKeyBytes(arieskms.ED25519)
_, _, err := svc.CreateAndExportPubKeyBytes(arieskms.X25519ECDHKW)
require.Error(t, err)
require.Contains(t, err.Error(), "key not supported ED25519")
require.Contains(t, err.Error(), "key not supported X25519ECDHKW")

suite := NewSuite(&awsConfig, metric, "", []Opts{}...)

creator, err := suite.RawKeyCreator()
require.NoError(t, err)

_, err = creator.Create(arieskms.ED25519Type)
_, err = creator.Create(arieskms.X25519ECDHKW)
require.Error(t, err)
require.Contains(t, err.Error(), "key not supported ED25519")

_, _, err = creator.CreateRaw(arieskms.ED25519Type)
require.Error(t, err)
require.Contains(t, err.Error(), "key not supported ED25519")
require.Contains(t, err.Error(), "key not supported X25519ECDHKW")
})

t.Run("export error", func(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion pkg/kms/kms.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const (

// Config configure kms that stores signing keys.
type Config struct {
KMSType Type
KMSType Type `json:"kmsType"`
Endpoint string
Region string
AliasPrefix string
Expand All @@ -38,6 +38,7 @@ type Config struct {
DBType string
DBURL string
DBPrefix string
MasterKey string
}

type VCSKeyManager interface {
Expand Down
2 changes: 1 addition & 1 deletion pkg/kms/mocks/kms_mocks.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 18 additions & 9 deletions pkg/kms/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,21 @@ SPDX-License-Identifier: Apache-2.0

package kms

import (
"fmt"
)

type Registry struct {
defaultVCSKeyManager VCSKeyManager
defaultVCSKeyManager VCSKeyManager
defaultConfig Config
defaultMetricProvider metricsProvider
}

func NewRegistry(defaultVCSKeyManager VCSKeyManager) *Registry {
func NewRegistry(
defaultVCSKeyManager VCSKeyManager,
defaultKmsConfig Config,
defaultMetricProvider metricsProvider,
) *Registry {
return &Registry{
defaultVCSKeyManager: defaultVCSKeyManager,
defaultConfig: defaultKmsConfig,
defaultVCSKeyManager: defaultVCSKeyManager,
defaultMetricProvider: defaultMetricProvider,
}
}

Expand All @@ -25,6 +29,11 @@ func (r *Registry) GetKeyManager(config *Config) (VCSKeyManager, error) {
return r.defaultVCSKeyManager, nil
}

// TODO handle kms per profile creation
return nil, fmt.Errorf("unsupported profile kms")
cfgCopy := r.defaultConfig
cfgCopy.KMSType = config.KMSType
if config.MasterKey != "" {
cfgCopy.MasterKey = config.MasterKey
}

return NewAriesKeyManager(&cfgCopy, r.defaultMetricProvider)
}
15 changes: 13 additions & 2 deletions pkg/kms/registry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,27 @@ import (
)

func TestNewRegistry(t *testing.T) {
r := kms.NewRegistry(nil)
r := kms.NewRegistry(nil, kms.Config{}, nil)
require.NotNil(t, r)
}

func TestRegistry_GetKeyManager(t *testing.T) {
t.Run("Default config local kms", func(t *testing.T) {
r := kms.NewRegistry(nil)
r := kms.NewRegistry(nil, kms.Config{KMSType: kms.Local}, nil)
require.NotNil(t, r)

_, err := r.GetKeyManager(nil)
require.NoError(t, err)
})

t.Run("Fallback kms", func(t *testing.T) {
r := kms.NewRegistry(nil, kms.Config{KMSType: kms.Local}, nil)
require.NotNil(t, r)

_, err := r.GetKeyManager(&kms.Config{
KMSType: "aws",
})

require.NoError(t, err)
})
}
Loading

0 comments on commit 41cf070

Please sign in to comment.