diff --git a/go.mod b/go.mod index a463f785..124cacf5 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ go 1.18 require ( github.com/aws/aws-sdk-go v1.42.33 + github.com/btcsuite/btcd v0.22.1 github.com/golang/mock v1.6.0 github.com/google/tink/go v1.6.1 github.com/gorilla/mux v1.8.0 @@ -15,6 +16,7 @@ require ( github.com/hyperledger/aries-framework-go/component/storageutil v0.0.0-20220610133818-119077b0ec85 github.com/hyperledger/aries-framework-go/spi v0.0.0-20220610133818-119077b0ec85 github.com/igor-pavlenko/httpsignatures-go v0.0.23 + github.com/minio/sha256-simd v0.1.1 github.com/piprate/json-gold v0.4.1 github.com/prometheus/client_golang v1.11.0 github.com/rs/xid v1.3.0 @@ -29,7 +31,6 @@ require ( github.com/VictoriaMetrics/fastcache v1.5.7 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bluele/gcache v0.0.2 // indirect - github.com/btcsuite/btcd v0.22.1 // indirect github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect github.com/cenkalti/backoff/v4 v4.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect @@ -45,7 +46,6 @@ require ( github.com/kilic/bls12-381 v0.1.1-0.20210503002446-7b7597926c69 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 // indirect - github.com/minio/sha256-simd v0.1.1 // indirect github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/multiformats/go-base32 v0.0.4 // indirect diff --git a/pkg/aws/opts.go b/pkg/aws/opts.go new file mode 100644 index 00000000..3d46b6de --- /dev/null +++ b/pkg/aws/opts.go @@ -0,0 +1,36 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package aws + +import ( + "os" +) + +type opts struct { + keyAliasPrefix string +} + +// NewOpts create new opts populated with environment variable. +func newOpts() *opts { + value, _ := os.LookupEnv("AWS_KEY_ALIAS_PREFIX") + + return &opts{ + keyAliasPrefix: value, + } +} + +func (o *opts) KeyAliasPrefix() string { + return o.keyAliasPrefix +} + +// Opts a Functional Options. +type Opts func(opts *opts) + +// WithKeyAliasPrefix sets the given prefix in the returns Opts. +func WithKeyAliasPrefix(prefix string) Opts { + return func(opts *opts) { opts.keyAliasPrefix = prefix } +} diff --git a/pkg/aws/opts_test.go b/pkg/aws/opts_test.go new file mode 100644 index 00000000..2c56e64b --- /dev/null +++ b/pkg/aws/opts_test.go @@ -0,0 +1,37 @@ +/* +Copyright SecureKey Technologies Inc. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package aws //nolint:testpackage + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestOpts(t *testing.T) { + t.Run("options: defaults", func(t *testing.T) { + options := newOpts() + + require.Equal(t, "", options.KeyAliasPrefix()) + }) + + t.Run("options: set manually", func(t *testing.T) { + options := newOpts() + + WithKeyAliasPrefix("keyaliasprefix")(options) + + require.Equal(t, "keyaliasprefix", options.KeyAliasPrefix()) + }) + + t.Run("options: env vars", func(t *testing.T) { + t.Setenv("AWS_KEY_ALIAS_PREFIX", "keyaliasprefix") + + options := newOpts() + + require.Equal(t, "keyaliasprefix", options.KeyAliasPrefix()) + }) +} diff --git a/pkg/aws/service.go b/pkg/aws/service.go index 86342e0c..9719407f 100644 --- a/pkg/aws/service.go +++ b/pkg/aws/service.go @@ -25,12 +25,13 @@ import ( "github.com/minio/sha256-simd" ) -type awsClient interface { +type awsClient interface { //nolint:dupl Sign(input *kms.SignInput) (*kms.SignOutput, error) GetPublicKey(input *kms.GetPublicKeyInput) (*kms.GetPublicKeyOutput, error) Verify(input *kms.VerifyInput) (*kms.VerifyOutput, error) DescribeKey(input *kms.DescribeKeyInput) (*kms.DescribeKeyOutput, error) CreateKey(input *kms.CreateKeyInput) (*kms.CreateKeyOutput, error) + CreateAlias(input *kms.CreateAliasInput) (*kms.CreateAliasOutput, error) } type metricsProvider interface { @@ -48,6 +49,7 @@ type ecdsaSignature struct { // Service aws kms. type Service struct { + options *opts client awsClient metrics metricsProvider healthCheckKeyID string @@ -73,8 +75,14 @@ var keySpecToCurve = map[string]elliptic.Curve{ } // New return aws service. -func New(awsSession *session.Session, metrics metricsProvider, healthCheckKeyID string) *Service { - return &Service{client: kms.New(awsSession), metrics: metrics, healthCheckKeyID: healthCheckKeyID} +func New(awsSession *session.Session, metrics metricsProvider, healthCheckKeyID string, opts ...Opts) *Service { + options := newOpts() + + for _, opt := range opts { + opt(options) + } + + return &Service{options: options, client: kms.New(awsSession), metrics: metrics, healthCheckKeyID: healthCheckKeyID} } // Sign data. @@ -226,6 +234,16 @@ func (s *Service) Create(kt arieskms.KeyType) (string, interface{}, error) { return "", nil, err } + aliasPrefix := s.options.KeyAliasPrefix() + if strings.TrimSpace(aliasPrefix) != "" { + aliasName := fmt.Sprintf("%s.%s", aliasPrefix, *result.KeyMetadata.KeyId) + + _, err = s.client.CreateAlias(&kms.CreateAliasInput{AliasName: &aliasName, TargetKeyId: result.KeyMetadata.KeyId}) + if err != nil { + return "", nil, err + } + } + return *result.KeyMetadata.KeyId, *result.KeyMetadata.KeyId, nil } diff --git a/pkg/aws/service_test.go b/pkg/aws/service_test.go index bce62a50..2872e5d2 100644 --- a/pkg/aws/service_test.go +++ b/pkg/aws/service_test.go @@ -30,9 +30,10 @@ func TestSign(t *testing.T) { Region: aws.String("ca"), CredentialsChainVerboseErrors: aws.Bool(true), }) + require.NoError(t, err) - svc := New(awsSession, &mockMetrics{}, "") + svc := New(awsSession, &mockMetrics{}, "", []Opts{}...) svc.client = &mockAWSClient{signFunc: func(input *kms.SignInput) (*kms.SignOutput, error) { return &kms.SignOutput{ @@ -62,7 +63,7 @@ func TestSign(t *testing.T) { }) require.NoError(t, err) - svc := New(awsSession, &mockMetrics{}, "") + svc := New(awsSession, &mockMetrics{}, "", []Opts{}...) svc.client = &mockAWSClient{signFunc: func(input *kms.SignInput) (*kms.SignOutput, error) { return nil, fmt.Errorf("failed to sign") @@ -89,7 +90,7 @@ func TestSign(t *testing.T) { }) require.NoError(t, err) - svc := New(awsSession, &mockMetrics{}, "") + svc := New(awsSession, &mockMetrics{}, "", []Opts{}...) _, err = svc.Sign([]byte("msg"), "aws-kms://arn:aws:kms:key1") require.Error(t, err) @@ -108,7 +109,8 @@ func TestHealthCheck(t *testing.T) { require.NoError(t, err) svc := New(awsSession, &mockMetrics{}, - "aws-kms://arn:aws:kms:ca-central-1:111122223333:key/800d5768-3fd7-4edd-a4b8-4c81c3e4c147") + "aws-kms://arn:aws:kms:ca-central-1:111122223333:key/800d5768-3fd7-4edd-a4b8-4c81c3e4c147", + []Opts{}...) svc.client = &mockAWSClient{describeKeyFunc: func(input *kms.DescribeKeyInput) (*kms.DescribeKeyOutput, error) { return &kms.DescribeKeyOutput{}, nil @@ -128,7 +130,8 @@ func TestHealthCheck(t *testing.T) { require.NoError(t, err) svc := New(awsSession, &mockMetrics{}, - "aws-kms://arn:aws:kms:ca-central-1:111122223333:key/800d5768-3fd7-4edd-a4b8-4c81c3e4c147") + "aws-kms://arn:aws:kms:ca-central-1:111122223333:key/800d5768-3fd7-4edd-a4b8-4c81c3e4c147", + []Opts{}...) svc.client = &mockAWSClient{describeKeyFunc: func(input *kms.DescribeKeyInput) (*kms.DescribeKeyOutput, error) { return nil, fmt.Errorf("failed to list keys") @@ -150,7 +153,7 @@ func TestCreate(t *testing.T) { }) require.NoError(t, err) - svc := New(awsSession, &mockMetrics{}, "") + svc := New(awsSession, &mockMetrics{}, "", []Opts{}...) keyID := "key1" @@ -163,6 +166,33 @@ func TestCreate(t *testing.T) { require.Contains(t, result, keyID) }) + t.Run("success: with key alias prefix", func(t *testing.T) { + endpoint := localhost + awsSession, err := session.NewSession(&aws.Config{ + Endpoint: &endpoint, + Region: aws.String("ca"), + CredentialsChainVerboseErrors: aws.Bool(true), + }) + require.NoError(t, err) + + svc := New(awsSession, &mockMetrics{}, "", WithKeyAliasPrefix("dummyKeyAlias")) + + keyID := "key1" + + svc.client = &mockAWSClient{ + createKeyFunc: func(input *kms.CreateKeyInput) (*kms.CreateKeyOutput, error) { + return &kms.CreateKeyOutput{KeyMetadata: &kms.KeyMetadata{KeyId: &keyID}}, nil + }, + createAliasFunc: func(input *kms.CreateAliasInput) (*kms.CreateAliasOutput, error) { + return &kms.CreateAliasOutput{}, nil + }, + } + + result, _, err := svc.Create(arieskms.ECDSAP256DER) + require.NoError(t, err) + require.Contains(t, result, keyID) + }) + t.Run("key not supported", func(t *testing.T) { endpoint := localhost awsSession, err := session.NewSession(&aws.Config{ @@ -172,7 +202,7 @@ func TestCreate(t *testing.T) { }) require.NoError(t, err) - svc := New(awsSession, &mockMetrics{}, "") + svc := New(awsSession, &mockMetrics{}, "", []Opts{}...) _, _, err = svc.Create(arieskms.ED25519) require.Error(t, err) @@ -190,7 +220,7 @@ func TestGet(t *testing.T) { }) require.NoError(t, err) - svc := New(awsSession, &mockMetrics{}, "") + svc := New(awsSession, &mockMetrics{}, "", []Opts{}...) keyID, err := svc.Get("key1") require.NoError(t, err) @@ -210,7 +240,7 @@ func TestCreateAndPubKeyBytes(t *testing.T) { keyID := "aws-kms://arn:aws:kms:ca-central-1:111122223333:key/800d5768-3fd7-4edd-a4b8-4c81c3e4c147" - svc := New(awsSession, &mockMetrics{}, "") + svc := New(awsSession, &mockMetrics{}, "", []Opts{}...) svc.client = &mockAWSClient{ getPublicKeyFunc: func(input *kms.GetPublicKeyInput) (*kms.GetPublicKeyOutput, error) { @@ -242,7 +272,7 @@ func TestSignMulti(t *testing.T) { }) require.NoError(t, err) - svc := New(awsSession, &mockMetrics{}, "") + svc := New(awsSession, &mockMetrics{}, "", []Opts{}...) _, err = svc.SignMulti(nil, nil) require.Error(t, err) @@ -259,7 +289,7 @@ func TestPubKeyBytes(t *testing.T) { }) require.NoError(t, err) - svc := New(awsSession, &mockMetrics{}, "") + svc := New(awsSession, &mockMetrics{}, "", []Opts{}...) svc.client = &mockAWSClient{getPublicKeyFunc: func(input *kms.GetPublicKeyInput) (*kms.GetPublicKeyOutput, error) { signingAlgo := "ECDSA_SHA_256" @@ -286,7 +316,7 @@ func TestPubKeyBytes(t *testing.T) { }) require.NoError(t, err) - svc := New(awsSession, &mockMetrics{}, "") + svc := New(awsSession, &mockMetrics{}, "", []Opts{}...) svc.client = &mockAWSClient{getPublicKeyFunc: func(input *kms.GetPublicKeyInput) (*kms.GetPublicKeyOutput, error) { return nil, fmt.Errorf("failed to export public key") @@ -307,7 +337,7 @@ func TestPubKeyBytes(t *testing.T) { }) require.NoError(t, err) - svc := New(awsSession, &mockMetrics{}, "") + svc := New(awsSession, &mockMetrics{}, "", []Opts{}...) _, _, err = svc.ExportPubKeyBytes("aws-kms://arn:aws:kms:key1") require.Error(t, err) @@ -321,6 +351,7 @@ type mockAWSClient struct { verifyFunc func(input *kms.VerifyInput) (*kms.VerifyOutput, error) describeKeyFunc func(input *kms.DescribeKeyInput) (*kms.DescribeKeyOutput, error) createKeyFunc func(input *kms.CreateKeyInput) (*kms.CreateKeyOutput, error) + createAliasFunc func(input *kms.CreateAliasInput) (*kms.CreateAliasOutput, error) } func (m *mockAWSClient) Sign(input *kms.SignInput) (*kms.SignOutput, error) { @@ -363,6 +394,14 @@ func (m *mockAWSClient) CreateKey(input *kms.CreateKeyInput) (*kms.CreateKeyOutp return nil, nil //nolint:nilnil } +func (m *mockAWSClient) CreateAlias(input *kms.CreateAliasInput) (*kms.CreateAliasOutput, error) { + if m.createAliasFunc != nil { + return m.createAliasFunc(input) + } + + return nil, nil //nolint:nilnil +} + type mockMetrics struct{} func (m *mockMetrics) SignCount() { diff --git a/test/bdd/go.mod b/test/bdd/go.mod index 08760058..d64b86c5 100644 --- a/test/bdd/go.mod +++ b/test/bdd/go.mod @@ -7,7 +7,6 @@ module github.com/trustbloc/kms/test/bdd go 1.18 require ( - github.com/coreos/go-oidc/v3 v3.1.0 github.com/cucumber/godog v0.10.0 github.com/google/uuid v1.3.0 github.com/greenpau/go-calculator v1.0.1 @@ -16,9 +15,6 @@ require ( github.com/hyperledger/aries-framework-go/component/storageutil v0.0.0-20220610133818-119077b0ec85 github.com/hyperledger/aries-framework-go/spi v0.0.0-20220614152730-3d817acfa48b github.com/igor-pavlenko/httpsignatures-go v0.0.23 - github.com/lafriks/go-shamir v1.1.0 - github.com/ory/hydra-client-go v1.10.6 - github.com/rs/xid v1.3.0 github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693 github.com/teserakt-io/golang-ed25519 v0.0.0-20210104091850-3888c087a4c8 github.com/tidwall/gjson v1.9.3 @@ -26,7 +22,6 @@ require ( github.com/trustbloc/auth/spi/gnap v0.0.0-20220721161924-5a7b16c4282f github.com/trustbloc/edge-core v0.1.8 github.com/trustbloc/kms v0.1.9-0.20220526151939-d46e46e8f7e1 - golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 ) require ( @@ -43,6 +38,7 @@ require ( github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/containerd/continuity v0.2.2 // indirect + github.com/coreos/go-oidc/v3 v3.1.0 // indirect github.com/cucumber/gherkin-go/v11 v11.0.0 // indirect github.com/cucumber/messages-go/v10 v10.0.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -107,6 +103,7 @@ require ( github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect github.com/opencontainers/runc v1.1.2 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect + github.com/ory/hydra-client-go v1.10.6 // indirect github.com/piprate/json-gold v0.4.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -134,6 +131,7 @@ require ( go.mongodb.org/mongo-driver v1.9.1 // indirect golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect + golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect golang.org/x/text v0.3.7 // indirect diff --git a/test/bdd/go.sum b/test/bdd/go.sum index bcf69076..5410b33e 100644 --- a/test/bdd/go.sum +++ b/test/bdd/go.sum @@ -715,8 +715,6 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lafriks/go-shamir v1.1.0 h1:80AU8M1G+W9BBlnh8rqLR8mSqP44fDND+61UxR7yaB4= -github.com/lafriks/go-shamir v1.1.0/go.mod h1:Sfy1w+uElJphCKcJc7Ku5Wp9SDFKQ53OQ+NHUEtfUK4= github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80= github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= @@ -952,7 +950,6 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/xid v1.3.0 h1:6NjYksEUlhurdVehpc7S7dk6DAmcKv8V9gG0FsVN2U4= -github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -1046,8 +1043,6 @@ github.com/trustbloc/auth/spi/gnap v0.0.0-20220721161924-5a7b16c4282f h1:ZgraGeo github.com/trustbloc/auth/spi/gnap v0.0.0-20220721161924-5a7b16c4282f/go.mod h1:ONvkj2rTwuhwQqtfJO7m4H9njyCr7LSJ8zHudZngoKs= github.com/trustbloc/edge-core v0.1.8 h1:m4X5XNDwiHJjGf8gHnpo6aLkBYuqDyNRq+npjxLc5cY= github.com/trustbloc/edge-core v0.1.8/go.mod h1:gfoyG/xquRXyHkww0ldM2jwOTuKKZpHYn+87f+TBQ8M= -github.com/trustbloc/edv v0.1.8 h1:0kD73Ni/9CdahanWtkPxmEYZN3G4I+ea5LLay7FGhZY= -github.com/trustbloc/edv v0.1.8/go.mod h1:jK3Gj7/06qZ12LlE/rsD2/Uu3fwOVKsouT8fMlwRWoA= github.com/trustbloc/orb v1.0.0-rc2.0.20220811160855-64ffb892b32b h1:lWbbe9PIx8mTXi+zR6r67dDcreePdoalWy7yQWOzGRc= github.com/trustbloc/orb v1.0.0-rc2.0.20220811160855-64ffb892b32b/go.mod h1:WN2/ZXjYqRjrYPgWplsyWWxkag6WTRxD26tw1iLPRgM= github.com/trustbloc/sidetree-core-go v1.0.0-rc2.0.20220729143551-6cda4cea3bf5 h1:v32O23Ox/uwrwros6Zk6XZHdZT7MAO/2pFTU7xcmfoU=