mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-01-19 11:51:41 -05:00
90b88e1cf9
In the light of extending our eKMS support it will be helpful to have a tighter use of the word "KMS". KMS should refer to the actual component that manages keys. The keyservice, also called KMS in the constellation code, does not manage keys itself. It talks to a KMS backend, which in turn does the actual key management.
520 lines
18 KiB
Go
520 lines
18 KiB
Go
/*
|
|
Copyright (c) Edgeless Systems GmbH
|
|
|
|
SPDX-License-Identifier: AGPL-3.0-only
|
|
*/
|
|
|
|
package aws
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"crypto/rand"
|
|
"crypto/rsa"
|
|
"crypto/sha256"
|
|
"crypto/x509"
|
|
"encoding/pem"
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/aws/aws-sdk-go-v2/aws"
|
|
"github.com/aws/aws-sdk-go-v2/service/kms"
|
|
"github.com/aws/aws-sdk-go-v2/service/kms/types"
|
|
"github.com/edgelesssys/constellation/v2/keyservice/internal/config"
|
|
"github.com/edgelesssys/constellation/v2/keyservice/internal/storage"
|
|
kmsInterface "github.com/edgelesssys/constellation/v2/keyservice/kms"
|
|
"github.com/stretchr/testify/assert"
|
|
"go.uber.org/goleak"
|
|
)
|
|
|
|
func TestMain(m *testing.M) {
|
|
goleak.VerifyTestMain(m,
|
|
// https://github.com/census-instrumentation/opencensus-go/issues/1262
|
|
goleak.IgnoreTopFunction("go.opencensus.io/stats/view.(*worker).start"),
|
|
)
|
|
}
|
|
|
|
const (
|
|
kekLen = 32
|
|
importedPublicKeyLen = 2048
|
|
)
|
|
|
|
// fakeAWSClient mocks the AWS KMS client.
|
|
type fakeAWSClient struct {
|
|
kekPool map[string][]byte
|
|
keyIDCount int
|
|
keyPairStruct *rsa.PrivateKey
|
|
}
|
|
|
|
// GenerateDataKey creates a new DEK.
|
|
func (m *fakeAWSClient) GenerateDataKey(ctx context.Context, params *kms.GenerateDataKeyInput, optFns ...func(*kms.Options)) (*kms.GenerateDataKeyOutput, error) {
|
|
if params.KeyId == nil {
|
|
return nil, fmt.Errorf("Missing paramerter KeyId")
|
|
}
|
|
|
|
kekID := *params.KeyId
|
|
if _, ok := m.kekPool[kekID]; !ok {
|
|
return nil, kmsInterface.ErrKEKUnknown
|
|
}
|
|
|
|
var keyLen int32
|
|
if params.NumberOfBytes != nil {
|
|
keyLen = *params.NumberOfBytes
|
|
} else {
|
|
switch params.KeySpec {
|
|
case types.DataKeySpecAes128:
|
|
keyLen = 128
|
|
case types.DataKeySpecAes256:
|
|
keyLen = 256
|
|
}
|
|
}
|
|
|
|
dek := make([]byte, keyLen)
|
|
|
|
// should not be random, but dependent on the context and the kekId
|
|
contextKeyID := params.EncryptionContext[DEKContext]
|
|
i := 0
|
|
for i < kekLen/2 {
|
|
dek[i] = contextKeyID[i%len(contextKeyID)]
|
|
i++
|
|
}
|
|
for i < kekLen {
|
|
dek[i] = []byte(*params.KeyId)[i%len(*params.KeyId)]
|
|
i++
|
|
}
|
|
output := &kms.GenerateDataKeyOutput{
|
|
CiphertextBlob: dek,
|
|
KeyId: &kekID,
|
|
Plaintext: dek,
|
|
}
|
|
return output, nil
|
|
}
|
|
|
|
// Listed in order called by CreateKEK
|
|
|
|
// DescribeKey takes an alias and searches in the kekPool whether this alias exists.
|
|
// If the alias exists, return the keyId the alias refers to (identifiable via the same key value). Otherwise, indicate that the key was not found.
|
|
func (m *fakeAWSClient) DescribeKey(ctx context.Context, params *kms.DescribeKeyInput, optFns ...func(*kms.Options)) (*kms.DescribeKeyOutput, error) {
|
|
if aliasKeyValue, ok := m.kekPool[*params.KeyId]; ok {
|
|
awsGeneratedKeyID := m.getIDPartnerByKeyValue(*params.KeyId, aliasKeyValue)
|
|
if awsGeneratedKeyID == "" {
|
|
return nil, errors.New("could not determine id partner")
|
|
}
|
|
describeKeyOutput := &kms.DescribeKeyOutput{
|
|
KeyMetadata: &types.KeyMetadata{
|
|
KeyId: &awsGeneratedKeyID,
|
|
},
|
|
}
|
|
return describeKeyOutput, nil
|
|
}
|
|
return nil, &types.NotFoundException{Message: aws.String("not found exception error")}
|
|
}
|
|
|
|
// CreateKey stores a key in fakeKMSStore.
|
|
func (m *fakeAWSClient) CreateKey(ctx context.Context, params *kms.CreateKeyInput, optFns ...func(*kms.Options)) (*kms.CreateKeyOutput, error) {
|
|
m.keyIDCount++
|
|
kekID := strconv.Itoa(m.keyIDCount)
|
|
|
|
if _, ok := m.kekPool[kekID]; ok {
|
|
return nil, errors.New("Key with this id already exists")
|
|
}
|
|
// Use m.keyIdCount to make the key values unique for the search in describeKey
|
|
kekValue := make([]byte, kekLen)
|
|
for i := 0; i < kekLen; i++ {
|
|
kekValue[i] = byte(m.keyIDCount)
|
|
}
|
|
m.kekPool[kekID] = kekValue
|
|
|
|
keyOutput := &kms.CreateKeyOutput{
|
|
KeyMetadata: &types.KeyMetadata{
|
|
KeyId: &kekID,
|
|
},
|
|
}
|
|
return keyOutput, nil
|
|
}
|
|
|
|
// CreateAlias changes keyId value to alias.
|
|
func (m *fakeAWSClient) CreateAlias(ctx context.Context, params *kms.CreateAliasInput, optFns ...func(*kms.Options)) (*kms.CreateAliasOutput, error) {
|
|
kekValue, ok := m.kekPool[*params.TargetKeyId]
|
|
if !ok {
|
|
return nil, kmsInterface.ErrKEKUnknown
|
|
}
|
|
// Copy the key bytes of the KEK to a new entry using the alias as keyId.
|
|
// As with the KMS, each key can be addressed using either its alias or the incremented keyId generated during creation
|
|
m.kekPool[*params.AliasName] = kekValue
|
|
return &kms.CreateAliasOutput{}, nil
|
|
}
|
|
|
|
// GetParametersForImport returns an empty public key and empty import token.
|
|
func (m *fakeAWSClient) GetParametersForImport(ctx context.Context, params *kms.GetParametersForImportInput, optFns ...func(*kms.Options)) (*kms.GetParametersForImportOutput, error) {
|
|
var err error
|
|
m.keyPairStruct, err = rsa.GenerateKey(rand.Reader, importedPublicKeyLen)
|
|
if err != nil {
|
|
return nil, errors.New("Error generating Key Pair")
|
|
}
|
|
var pki any = &m.keyPairStruct.PublicKey
|
|
publicKeyBytes, err := x509.MarshalPKIXPublicKey(pki)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
importToken := make([]byte, 1)
|
|
getParametersForImportOutput := &kms.GetParametersForImportOutput{
|
|
PublicKey: publicKeyBytes,
|
|
ImportToken: importToken,
|
|
}
|
|
return getParametersForImportOutput, nil
|
|
}
|
|
|
|
// ImportKeyMaterial stores the encrypted KEK in the KMS.
|
|
func (m *fakeAWSClient) ImportKeyMaterial(ctx context.Context, params *kms.ImportKeyMaterialInput, optFns ...func(*kms.Options)) (*kms.ImportKeyMaterialOutput, error) {
|
|
if _, ok := m.kekPool[*params.KeyId]; !ok {
|
|
return nil, kmsInterface.ErrKEKUnknown
|
|
}
|
|
|
|
// decrypt the encryptedKeyMaterial generated using RSAES_OAEP_SHA_256 to get the imported key bytes
|
|
kekValue, err := rsa.DecryptOAEP(sha256.New(), rand.Reader, m.keyPairStruct, params.EncryptedKeyMaterial, nil)
|
|
if err != nil {
|
|
return nil, errors.New("Error decrypting the wrapped key")
|
|
}
|
|
|
|
// Set imported key bytes for keyId and alias
|
|
currentKeyValue := m.kekPool[*params.KeyId]
|
|
aliasID := m.getIDPartnerByKeyValue(*params.KeyId, currentKeyValue)
|
|
if aliasID == "" {
|
|
return nil, errors.New("could not determine id partner")
|
|
}
|
|
m.kekPool[aliasID] = kekValue
|
|
m.kekPool[*params.KeyId] = kekValue
|
|
|
|
return &kms.ImportKeyMaterialOutput{}, nil
|
|
}
|
|
|
|
// PutKeyPolicy sets the policy for an existing KEK in the kms.
|
|
func (m *fakeAWSClient) PutKeyPolicy(ctx context.Context, params *kms.PutKeyPolicyInput, optFns ...func(*kms.Options)) (*kms.PutKeyPolicyOutput, error) {
|
|
return &kms.PutKeyPolicyOutput{}, nil
|
|
}
|
|
|
|
// Decrypt performs decryption.
|
|
// Since the keys are saved in plain text during testing, decrypt returns the saved value.
|
|
func (m *fakeAWSClient) Decrypt(ctx context.Context, params *kms.DecryptInput, optFns ...func(*kms.Options)) (*kms.DecryptOutput, error) {
|
|
decryptOutput := &kms.DecryptOutput{
|
|
Plaintext: params.CiphertextBlob,
|
|
}
|
|
return decryptOutput, nil
|
|
}
|
|
|
|
// getIDPartnerByKeyValue returns a the alternative name of a key, if it exists.
|
|
// For every key there should exist an alias after successful execution of CreateKEK.
|
|
// Both key and its alias are stored with the same key value.
|
|
// For consistency, they should be updated simultaneously, since they must store the same key value.
|
|
func (m *fakeAWSClient) getIDPartnerByKeyValue(keyID1 string, keyValue1 []byte) string {
|
|
// Search for the keyId with the same keyValue the input key has
|
|
for keyID2, keyValue2 := range m.kekPool {
|
|
if bytes.Equal(keyValue2, keyValue1) && keyID2 != keyID1 {
|
|
return keyID2
|
|
}
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// DeleteAlias is a stub.
|
|
func (m *fakeAWSClient) DeleteAlias(ctx context.Context, params *kms.DeleteAliasInput, optFns ...func(*kms.Options)) (*kms.DeleteAliasOutput, error) {
|
|
return &kms.DeleteAliasOutput{}, nil
|
|
}
|
|
|
|
// ScheduleKeyDeletion is a stub.
|
|
func (m *fakeAWSClient) ScheduleKeyDeletion(ctx context.Context, params *kms.ScheduleKeyDeletionInput, optFns ...func(*kms.Options)) (*kms.ScheduleKeyDeletionOutput, error) {
|
|
return &kms.ScheduleKeyDeletionOutput{}, nil
|
|
}
|
|
|
|
// GenerateDataKeyWithoutPlaintext is a stub.
|
|
func (m *fakeAWSClient) GenerateDataKeyWithoutPlaintext(ctx context.Context, params *kms.GenerateDataKeyWithoutPlaintextInput, optFns ...func(*kms.Options)) (*kms.GenerateDataKeyWithoutPlaintextOutput, error) {
|
|
return nil, errors.New("Not implemented")
|
|
}
|
|
|
|
// Encrypt is a stub.
|
|
func (m *fakeAWSClient) Encrypt(ctx context.Context, params *kms.EncryptInput, optFns ...func(*kms.Options)) (*kms.EncryptOutput, error) {
|
|
return nil, errors.New("Not implemented")
|
|
}
|
|
|
|
type stubKeyPolicyProducer struct {
|
|
createKeyPolicyErr error
|
|
}
|
|
|
|
// CreateKeyPolicy creates a key policy.
|
|
func (m *stubKeyPolicyProducer) CreateKeyPolicy(keyID string) (string, error) {
|
|
return "", m.createKeyPolicyErr
|
|
}
|
|
|
|
func TestAWSKMSClient(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
awsClient := &fakeAWSClient{kekPool: make(map[string][]byte, 2)}
|
|
|
|
client := &KMSClient{
|
|
awsClient: awsClient,
|
|
policyProducer: &stubKeyPolicyProducer{},
|
|
storage: storage.NewMemMapStorage(),
|
|
}
|
|
|
|
awsClient.keyIDCount = -1
|
|
|
|
testKEK1ID := "testKEK1"
|
|
testKEK1 := []byte("test KEK")
|
|
testKEK2ID := "testKEK2"
|
|
testKEK2 := []byte("more test KEK")
|
|
ctx := context.Background()
|
|
|
|
// try to get a DEK before setting the KEK
|
|
_, err := client.GetDEK(ctx, testKEK1ID, "volume01", config.SymmetricKeyLength)
|
|
assert.Error(err)
|
|
assert.ErrorIs(err, kmsInterface.ErrKEKUnknown)
|
|
|
|
// test CreateKEK method
|
|
assert.NoError(client.CreateKEK(ctx, testKEK1ID, testKEK1))
|
|
assert.Equal(testKEK1, awsClient.kekPool[strconv.Itoa(awsClient.keyIDCount)])
|
|
|
|
// make sure that CreateKEK is idempotent
|
|
assert.NoError(client.CreateKEK(ctx, testKEK1ID, testKEK1))
|
|
assert.Equal(testKEK1, awsClient.kekPool[strconv.Itoa(awsClient.keyIDCount)])
|
|
|
|
// test setting a second KEK
|
|
assert.NoError(client.CreateKEK(ctx, testKEK2ID, testKEK2))
|
|
assert.Equal(testKEK2, awsClient.kekPool[strconv.Itoa(awsClient.keyIDCount)])
|
|
|
|
// test GetDEK method
|
|
dek1, err := client.GetDEK(ctx, testKEK1ID, "volume01", config.SymmetricKeyLength)
|
|
assert.NoError(err)
|
|
dek2, err := client.GetDEK(ctx, testKEK2ID, "volume02", config.SymmetricKeyLength)
|
|
assert.NoError(err)
|
|
|
|
// make sure that GetDEK is idempotent
|
|
dek1Copy, err := client.GetDEK(ctx, testKEK1ID, "volume01", config.SymmetricKeyLength)
|
|
assert.NoError(err)
|
|
assert.Equal(dek1, dek1Copy)
|
|
dek2Copy, err := client.GetDEK(ctx, testKEK2ID, "volume02", config.SymmetricKeyLength)
|
|
assert.NoError(err)
|
|
assert.Equal(dek2, dek2Copy)
|
|
}
|
|
|
|
func TestCreateKEK(t *testing.T) {
|
|
someErr := errors.New("error")
|
|
importKey := []byte("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA")
|
|
importPubKey, _ := pem.Decode([]byte(`-----BEGIN PUBLIC KEY-----
|
|
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAu+OepfHCTiTi27nkTGke
|
|
dn+AIkiM1AIWWDwqfqG85aNulcj60mGQGXIYV8LoEVkyKOhYBIUmJUaVczB4ltqq
|
|
ZhR7l46RQw2vnv+XiUmfK555d4ZDInyjTusO69hE6tkuYKdXLlG1HzcrhJ254LE2
|
|
wXtE1Yf9DygOsWet+S32gmpfH2whUY1mRTdwW4zoY4c3qtmmWImhVVNr6qR8Z95X
|
|
Y49EteCoNIomQNEZH7EnMlBsh34L7doOsckh1aTvQcrJorQSrBkWKbdV6kvuBKZp
|
|
fLK0DZiOh9BwZCZANtOqgH3V+AuNk338iON8eKCFRjoiQ40YGM6xKH3E6PHVnuKt
|
|
uIO0MPvE0qdV8Lvs+nCCrvwP5sJKZuciM40ioEO1pV1y3491xIxYhx3OfN4gg2h8
|
|
cgdKob/R8qwxqTrfceO36FBFb1vXCUApsm5oy6WxmUtIUgoYhK+6JYpVWDyOJYwP
|
|
iMJhdJA65n2ZliN8NxEhsaFoMgw76BOiD0wkt/CKPmNbOm5MGS3/fiZCt6A6u3cn
|
|
Ubhn4tvjy/q5XzVqZtBeoseW2TyyrsAN53LBkSqag5tG/264CQDigQ6Y/OADOE2x
|
|
n08MyrFHIL/wFMscOvJo7c2Eo4EW1yXkEkAy5tF5PZgnfRObakj4gdqPeq18FNzc
|
|
Y+t5OxL3kL15VzY1Ob0d5cMCAwEAAQ==
|
|
-----END PUBLIC KEY-----`))
|
|
|
|
testCases := map[string]struct {
|
|
client *stubAWSClient
|
|
policyProducer KeyPolicyProducer
|
|
importKey []byte
|
|
cleanupRequired bool
|
|
wantErr bool
|
|
}{
|
|
"create new kek successful": {
|
|
client: &stubAWSClient{createKeyID: "key-id"},
|
|
policyProducer: &stubKeyPolicyProducer{},
|
|
},
|
|
"CreateKeyPolicy fails on existing": {
|
|
client: &stubAWSClient{},
|
|
policyProducer: &stubKeyPolicyProducer{createKeyPolicyErr: someErr},
|
|
wantErr: true,
|
|
},
|
|
"CreateKeyPolicy fails on new": {
|
|
client: &stubAWSClient{describeKeyErr: &types.NotFoundException{}},
|
|
policyProducer: &stubKeyPolicyProducer{createKeyPolicyErr: someErr},
|
|
cleanupRequired: true,
|
|
wantErr: true,
|
|
},
|
|
"PutKeyPolicy fails on new": {
|
|
client: &stubAWSClient{
|
|
describeKeyErr: &types.NotFoundException{},
|
|
putKeyPolicyErr: someErr,
|
|
createKeyID: "key-id",
|
|
},
|
|
policyProducer: &stubKeyPolicyProducer{},
|
|
cleanupRequired: true,
|
|
wantErr: true,
|
|
},
|
|
"CreateAlias fails on new": {
|
|
client: &stubAWSClient{
|
|
describeKeyErr: &types.NotFoundException{},
|
|
createAliasErr: someErr,
|
|
createKeyID: "key-id",
|
|
},
|
|
policyProducer: &stubKeyPolicyProducer{},
|
|
cleanupRequired: true,
|
|
wantErr: true,
|
|
},
|
|
"CreateKey fails on new": {
|
|
client: &stubAWSClient{describeKeyErr: &types.NotFoundException{}, createKeyErr: someErr},
|
|
policyProducer: &stubKeyPolicyProducer{},
|
|
wantErr: true,
|
|
},
|
|
"DescribeKey fails": {
|
|
client: &stubAWSClient{describeKeyErr: someErr},
|
|
policyProducer: &stubKeyPolicyProducer{},
|
|
wantErr: true,
|
|
},
|
|
"DescribeKey fails with not found error": {
|
|
client: &stubAWSClient{describeKeyErr: &types.NotFoundException{}},
|
|
policyProducer: &stubKeyPolicyProducer{},
|
|
},
|
|
"import kek successful": {
|
|
client: &stubAWSClient{getParametersForImportPubKey: importPubKey.Bytes},
|
|
policyProducer: &stubKeyPolicyProducer{},
|
|
importKey: importKey,
|
|
},
|
|
"GetParametersForImport fails on new": {
|
|
client: &stubAWSClient{
|
|
describeKeyErr: &types.NotFoundException{},
|
|
getParametersForImportErr: someErr,
|
|
createKeyID: "key-id",
|
|
},
|
|
policyProducer: &stubKeyPolicyProducer{},
|
|
importKey: importKey,
|
|
cleanupRequired: true,
|
|
wantErr: true,
|
|
},
|
|
"ImportKeyMaterial fails on new": {
|
|
client: &stubAWSClient{
|
|
describeKeyErr: &types.NotFoundException{},
|
|
importKeyMaterialErr: someErr,
|
|
createKeyID: "key-id",
|
|
},
|
|
policyProducer: &stubKeyPolicyProducer{},
|
|
importKey: importKey,
|
|
cleanupRequired: true,
|
|
wantErr: true,
|
|
},
|
|
"GetParametersForImport fails on existing": {
|
|
client: &stubAWSClient{getParametersForImportErr: someErr},
|
|
policyProducer: &stubKeyPolicyProducer{},
|
|
importKey: importKey,
|
|
wantErr: true,
|
|
},
|
|
"ImportKeyMaterial fails on existing": {
|
|
client: &stubAWSClient{importKeyMaterialErr: someErr},
|
|
policyProducer: &stubKeyPolicyProducer{},
|
|
importKey: importKey,
|
|
wantErr: true,
|
|
},
|
|
"errors during cleanup don't stop execution": {
|
|
client: &stubAWSClient{
|
|
describeKeyErr: &types.NotFoundException{},
|
|
deleteAliasErr: someErr,
|
|
createKeyID: "key-id",
|
|
},
|
|
policyProducer: &stubKeyPolicyProducer{createKeyPolicyErr: someErr},
|
|
cleanupRequired: true,
|
|
wantErr: true,
|
|
},
|
|
}
|
|
|
|
for name, tc := range testCases {
|
|
t.Run(name, func(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
client := KMSClient{
|
|
awsClient: tc.client,
|
|
storage: storage.NewMemMapStorage(),
|
|
policyProducer: tc.policyProducer,
|
|
}
|
|
|
|
err := client.CreateKEK(context.Background(), "test-key", tc.importKey)
|
|
if tc.wantErr {
|
|
assert.Error(err)
|
|
if tc.cleanupRequired {
|
|
assert.True(tc.client.cleanUpCalled, "failed to clean up")
|
|
} else {
|
|
assert.False(tc.client.cleanUpCalled, "cleaned up when not necessary")
|
|
}
|
|
} else {
|
|
assert.NoError(err)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
type stubAWSClient struct {
|
|
cleanUpCalled bool
|
|
createAliasErr error
|
|
createKeyErr error
|
|
createKeyID string
|
|
decryptErr error
|
|
deleteAliasErr error
|
|
describeKeyErr error
|
|
encryptErr error
|
|
generateDataKeyErr error
|
|
generateDataKeyWithoutPlaintextErr error
|
|
getParametersForImportErr error
|
|
getParametersForImportPubKey []byte
|
|
importKeyMaterialErr error
|
|
putKeyPolicyErr error
|
|
scheduleKeyDeletionErr error
|
|
}
|
|
|
|
func (s *stubAWSClient) CreateAlias(ctx context.Context, params *kms.CreateAliasInput, optFns ...func(*kms.Options)) (*kms.CreateAliasOutput, error) {
|
|
return &kms.CreateAliasOutput{}, s.createAliasErr
|
|
}
|
|
|
|
func (s *stubAWSClient) CreateKey(ctx context.Context, params *kms.CreateKeyInput, optFns ...func(*kms.Options)) (*kms.CreateKeyOutput, error) {
|
|
return &kms.CreateKeyOutput{KeyMetadata: &types.KeyMetadata{KeyId: aws.String(s.createKeyID)}}, s.createKeyErr
|
|
}
|
|
|
|
func (s *stubAWSClient) Decrypt(ctx context.Context, params *kms.DecryptInput, optFns ...func(*kms.Options)) (*kms.DecryptOutput, error) {
|
|
return &kms.DecryptOutput{}, s.decryptErr
|
|
}
|
|
|
|
func (s *stubAWSClient) DeleteAlias(ctx context.Context, params *kms.DeleteAliasInput, optFns ...func(*kms.Options)) (*kms.DeleteAliasOutput, error) {
|
|
return &kms.DeleteAliasOutput{}, s.deleteAliasErr
|
|
}
|
|
|
|
func (s *stubAWSClient) DescribeKey(ctx context.Context, params *kms.DescribeKeyInput, optFns ...func(*kms.Options)) (*kms.DescribeKeyOutput, error) {
|
|
return &kms.DescribeKeyOutput{KeyMetadata: &types.KeyMetadata{KeyId: params.KeyId}}, s.describeKeyErr
|
|
}
|
|
|
|
func (s *stubAWSClient) Encrypt(ctx context.Context, params *kms.EncryptInput, optFns ...func(*kms.Options)) (*kms.EncryptOutput, error) {
|
|
return &kms.EncryptOutput{}, s.encryptErr
|
|
}
|
|
|
|
func (s *stubAWSClient) GenerateDataKey(ctx context.Context, params *kms.GenerateDataKeyInput, optFns ...func(*kms.Options)) (*kms.GenerateDataKeyOutput, error) {
|
|
return &kms.GenerateDataKeyOutput{}, s.generateDataKeyErr
|
|
}
|
|
|
|
func (s *stubAWSClient) GenerateDataKeyWithoutPlaintext(ctx context.Context, params *kms.GenerateDataKeyWithoutPlaintextInput, optFns ...func(*kms.Options)) (*kms.GenerateDataKeyWithoutPlaintextOutput, error) {
|
|
return &kms.GenerateDataKeyWithoutPlaintextOutput{}, s.generateDataKeyWithoutPlaintextErr
|
|
}
|
|
|
|
func (s *stubAWSClient) GetParametersForImport(ctx context.Context, params *kms.GetParametersForImportInput, optFns ...func(*kms.Options)) (*kms.GetParametersForImportOutput, error) {
|
|
return &kms.GetParametersForImportOutput{
|
|
PublicKey: s.getParametersForImportPubKey,
|
|
}, s.getParametersForImportErr
|
|
}
|
|
|
|
func (s *stubAWSClient) ImportKeyMaterial(ctx context.Context, params *kms.ImportKeyMaterialInput, optFns ...func(*kms.Options)) (*kms.ImportKeyMaterialOutput, error) {
|
|
return &kms.ImportKeyMaterialOutput{}, s.importKeyMaterialErr
|
|
}
|
|
|
|
func (s *stubAWSClient) PutKeyPolicy(ctx context.Context, params *kms.PutKeyPolicyInput, optFns ...func(*kms.Options)) (*kms.PutKeyPolicyOutput, error) {
|
|
return &kms.PutKeyPolicyOutput{}, s.putKeyPolicyErr
|
|
}
|
|
|
|
func (s *stubAWSClient) ScheduleKeyDeletion(ctx context.Context, params *kms.ScheduleKeyDeletionInput, optFns ...func(*kms.Options)) (*kms.ScheduleKeyDeletionOutput, error) {
|
|
s.cleanUpCalled = true
|
|
return &kms.ScheduleKeyDeletionOutput{}, s.scheduleKeyDeletionErr
|
|
}
|