diff --git a/.gitignore b/.gitignore index 77982bf1..7991e904 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ .idea go.work go.work.sum +.env +.envrc diff --git a/wrappers/awskms/awskms.go b/wrappers/awskms/awskms.go index 4b1f6c73..d1b10979 100644 --- a/wrappers/awskms/awskms.go +++ b/wrappers/awskms/awskms.go @@ -10,20 +10,20 @@ import ( "os" "sync/atomic" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/aws/aws-sdk-go/service/kms/kmsiface" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/kms" cleanhttp "github.com/hashicorp/go-cleanhttp" "github.com/hashicorp/go-hclog" wrapping "github.com/hashicorp/go-kms-wrapping/v2" - "github.com/hashicorp/go-secure-stdlib/awsutil" + "github.com/hashicorp/go-secure-stdlib/awsutil/v2" ) // These constants contain the accepted env vars; the Vault one is for backwards compat const ( - EnvAwsKmsWrapperKeyId = "AWSKMS_WRAPPER_KEY_ID" - EnvVaultAwsKmsSealKeyId = "VAULT_AWSKMS_SEAL_KEY_ID" + EnvAwsKmsWrapperKeyId = "AWSKMS_WRAPPER_KEY_ID" + EnvVaultAwsKmsSealKeyId = "VAULT_AWSKMS_SEAL_KEY_ID" + DeprecatedEnvAwsKmsEndpoint = "AWS_KMS_ENDPOINT" + EnvAwsKmsEndpoint = "AWSKMS_ENDPOINT" ) const ( @@ -52,11 +52,18 @@ type Wrapper struct { currentKeyId *atomic.Value - client kmsiface.KMSAPI + client KmsApi logger hclog.Logger } +// KmsApi defines the functionality expected to be implemented by the AWS SDK v2 kms package. +type KmsApi interface { + Encrypt(ctx context.Context, input *kms.EncryptInput, opts ...func(*kms.Options)) (*kms.EncryptOutput, error) + Decrypt(ctx context.Context, input *kms.DecryptInput, opts ...func(*kms.Options)) (*kms.DecryptOutput, error) + DescribeKey(ctx context.Context, inpput *kms.DescribeKeyInput, opts ...func(*kms.Options)) (*kms.DescribeKeyOutput, error) +} + // Ensure that we are implementing Wrapper var _ wrapping.Wrapper = (*Wrapper)(nil) @@ -77,7 +84,7 @@ func NewWrapper() *Wrapper { // * Passed in config map // * Instance metadata role (access key and secret key) // * Default values -func (k *Wrapper) SetConfig(_ context.Context, opt ...wrapping.Option) (*wrapping.WrapperConfig, error) { +func (k *Wrapper) SetConfig(ctx context.Context, opt ...wrapping.Option) (*wrapping.WrapperConfig, error) { opts, err := getOpts(opt...) if err != nil { return nil, err @@ -103,7 +110,7 @@ func (k *Wrapper) SetConfig(_ context.Context, opt ...wrapping.Option) (*wrappin k.currentKeyId.Store(k.keyId) // Please see GetRegion for an explanation of the order in which region is parsed. - k.region, err = awsutil.GetRegion(opts.withRegion) + k.region, err = awsutil.GetRegion(ctx, opts.withRegion) if err != nil { return nil, err } @@ -119,7 +126,11 @@ func (k *Wrapper) SetConfig(_ context.Context, opt ...wrapping.Option) (*wrappin k.roleArn = opts.withRoleArn if !opts.withDisallowEnvVars { - k.endpoint = os.Getenv("AWS_KMS_ENDPOINT") + ep := os.Getenv(EnvAwsKmsEndpoint) + if ep == "" { + ep = os.Getenv(DeprecatedEnvAwsKmsEndpoint) + } + k.endpoint = ep } if k.endpoint == "" { k.endpoint = opts.withEndpoint @@ -127,15 +138,15 @@ func (k *Wrapper) SetConfig(_ context.Context, opt ...wrapping.Option) (*wrappin // Check and set k.client if k.client == nil { - client, err := k.GetAwsKmsClient() + client, err := k.GetAwsKmsClient(ctx) if err != nil { return nil, fmt.Errorf("error initializing AWS KMS wrapping client: %w", err) } if !k.keyNotRequired { // Test the client connection using provided key ID - keyInfo, err := client.DescribeKey(&kms.DescribeKeyInput{ - KeyId: aws.String(k.keyId), + keyInfo, err := client.DescribeKey(ctx, &kms.DescribeKeyInput{ + KeyId: &k.keyId, }) if err != nil { return nil, fmt.Errorf("error fetching AWS KMS wrapping key information: %w", err) @@ -143,7 +154,7 @@ func (k *Wrapper) SetConfig(_ context.Context, opt ...wrapping.Option) (*wrappin if keyInfo == nil || keyInfo.KeyMetadata == nil || keyInfo.KeyMetadata.KeyId == nil { return nil, errors.New("no key information returned") } - k.currentKeyId.Store(aws.StringValue(keyInfo.KeyMetadata.KeyId)) + k.currentKeyId.Store(*keyInfo.KeyMetadata.KeyId) } k.client = client @@ -174,7 +185,7 @@ func (k *Wrapper) KeyId(_ context.Context) (string, error) { // Encrypt is used to encrypt the master key using the the AWS CMK. // This returns the ciphertext, and/or any errors from this // call. This should be called after the KMS client has been instantiated. -func (k *Wrapper) Encrypt(_ context.Context, plaintext []byte, opt ...wrapping.Option) (*wrapping.BlobInfo, error) { +func (k *Wrapper) Encrypt(ctx context.Context, plaintext []byte, opt ...wrapping.Option) (*wrapping.BlobInfo, error) { if plaintext == nil { return nil, fmt.Errorf("given plaintext for encryption is nil") } @@ -189,10 +200,10 @@ func (k *Wrapper) Encrypt(_ context.Context, plaintext []byte, opt ...wrapping.O } input := &kms.EncryptInput{ - KeyId: aws.String(k.keyId), + KeyId: &k.keyId, Plaintext: env.Key, } - output, err := k.client.Encrypt(input) + output, err := k.client.Encrypt(ctx, input) if err != nil { return nil, fmt.Errorf("error encrypting data: %w", err) } @@ -203,8 +214,8 @@ func (k *Wrapper) Encrypt(_ context.Context, plaintext []byte, opt ...wrapping.O // used for encryption. This is helpful if you are looking to reencyrpt // your data when it is not using the latest key id. See these docs relating // to key rotation https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html - keyId := aws.StringValue(output.KeyId) - k.currentKeyId.Store(keyId) + keyId := output.KeyId + k.currentKeyId.Store(*keyId) ret := &wrapping.BlobInfo{ Ciphertext: env.Ciphertext, @@ -214,7 +225,7 @@ func (k *Wrapper) Encrypt(_ context.Context, plaintext []byte, opt ...wrapping.O // Even though we do not use the key id during decryption, store it // to know exactly the specific key used in encryption in case we // want to rewrap older entries - KeyId: keyId, + KeyId: *keyId, WrappedKey: output.CiphertextBlob, }, } @@ -223,7 +234,7 @@ func (k *Wrapper) Encrypt(_ context.Context, plaintext []byte, opt ...wrapping.O } // Decrypt is used to decrypt the ciphertext. This should be called after Init. -func (k *Wrapper) Decrypt(_ context.Context, in *wrapping.BlobInfo, opt ...wrapping.Option) ([]byte, error) { +func (k *Wrapper) Decrypt(ctx context.Context, in *wrapping.BlobInfo, opt ...wrapping.Option) ([]byte, error) { if in == nil { return nil, fmt.Errorf("given input for decryption is nil") } @@ -242,7 +253,7 @@ func (k *Wrapper) Decrypt(_ context.Context, in *wrapping.BlobInfo, opt ...wrapp CiphertextBlob: in.Ciphertext, } - output, err := k.client.Decrypt(input) + output, err := k.client.Decrypt(ctx, input) if err != nil { return nil, fmt.Errorf("error decrypting data: %w", err) } @@ -254,7 +265,7 @@ func (k *Wrapper) Decrypt(_ context.Context, in *wrapping.BlobInfo, opt ...wrapp input := &kms.DecryptInput{ CiphertextBlob: in.KeyInfo.WrappedKey, } - output, err := k.client.Decrypt(input) + output, err := k.client.Decrypt(ctx, input) if err != nil { return nil, fmt.Errorf("error decrypting data encryption key: %w", err) } @@ -277,48 +288,47 @@ func (k *Wrapper) Decrypt(_ context.Context, in *wrapping.BlobInfo, opt ...wrapp } // Client returns the AWS KMS client used by the wrapper. -func (k *Wrapper) Client() kmsiface.KMSAPI { +func (k *Wrapper) Client() KmsApi { return k.client } // GetAwsKmsClient returns an instance of the KMS client. -func (k *Wrapper) GetAwsKmsClient() (*kms.KMS, error) { - credsConfig := &awsutil.CredentialsConfig{} - - credsConfig.AccessKey = k.accessKey - credsConfig.SecretKey = k.secretKey - credsConfig.SessionToken = k.sessionToken - credsConfig.Filename = k.sharedCredsFilename - credsConfig.Profile = k.sharedCredsProfile - credsConfig.RoleARN = k.roleArn - credsConfig.RoleSessionName = k.roleSessionName - credsConfig.WebIdentityTokenFile = k.webIdentityTokenFile - credsConfig.Region = k.region - credsConfig.Logger = k.logger - - credsConfig.HTTPClient = cleanhttp.DefaultClient() - - creds, err := credsConfig.GenerateCredentialChain() +func (k *Wrapper) GetAwsKmsClient(ctx context.Context) (*kms.Client, error) { + credsConfig := &awsutil.CredentialsConfig{ + AccessKey: k.accessKey, + SecretKey: k.secretKey, + SessionToken: k.sessionToken, + Filename: k.sharedCredsFilename, + Profile: k.sharedCredsProfile, + RoleARN: k.roleArn, + RoleSessionName: k.roleSessionName, + WebIdentityTokenFile: k.webIdentityTokenFile, + Region: k.region, + Logger: k.logger, + HTTPClient: cleanhttp.DefaultClient(), + } + + creds, err := credsConfig.GenerateCredentialChain(ctx) if err != nil { return nil, err } - awsConfig := &aws.Config{ - Credentials: creds, - Region: aws.String(credsConfig.Region), - HTTPClient: cleanhttp.DefaultClient(), + clientOpts := []func(*config.LoadOptions) error{ + config.WithCredentialsProvider(creds.Credentials), + config.WithRegion(k.region), + config.WithHTTPClient(cleanhttp.DefaultClient()), } if k.endpoint != "" { - awsConfig.Endpoint = aws.String(k.endpoint) + clientOpts = append(clientOpts, config.WithBaseEndpoint(k.endpoint)) } - sess, err := session.NewSession(awsConfig) + cfg, err := config.LoadDefaultConfig(ctx, clientOpts...) if err != nil { return nil, err } - client := kms.New(sess) + client := kms.NewFromConfig(cfg) return client, nil } diff --git a/wrappers/awskms/awskms_test.go b/wrappers/awskms/awskms_test.go index 6a7d83af..05b2e3cb 100644 --- a/wrappers/awskms/awskms_test.go +++ b/wrappers/awskms/awskms_test.go @@ -6,206 +6,271 @@ package awskms import ( "context" "os" - "reflect" "testing" - "github.com/aws/aws-sdk-go/aws" wrapping "github.com/hashicorp/go-kms-wrapping/v2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) -func TestAwsKmsWrapper(t *testing.T) { - s := NewWrapper() - s.client = &mockClient{ - keyId: aws.String(awsTestKeyId), - } +const ( + awsTestKeyId = "foo" + envAwsProfile = "AWS_PROFILE" + envAwsRegion = "AWS_REGION" +) - _, err := s.SetConfig(nil) - if err == nil { - t.Fatal("expected error when AwsKms wrapping key ID is not provided") +func TestSetConfig(t *testing.T) { + // Works around lack of AWS_REGION var in CI + if os.Getenv(envAwsRegion) == "" { + os.Setenv(envAwsRegion, "us-west-2") + defer os.Setenv(envAwsRegion, "") } - // Set the key - oldKeyId := os.Getenv(EnvAwsKmsWrapperKeyId) - os.Setenv(EnvAwsKmsWrapperKeyId, awsTestKeyId) - defer os.Setenv(EnvAwsKmsWrapperKeyId, oldKeyId) - _, err = s.SetConfig(nil) - if err != nil { - t.Fatal(err) - } -} + t.Run("Failure - No wrapper key ID", func(t *testing.T) { + wrapperWithMock := NewWrapper() + wrapperWithMock.client = &mockClient{ + keyId: awsTestKeyId, + } + oldKeyId := os.Getenv(EnvAwsKmsWrapperKeyId) + os.Setenv(EnvAwsKmsWrapperKeyId, "") + defer os.Setenv(EnvAwsKmsWrapperKeyId, oldKeyId) -func TestAwsKmsWrapper_IgnoreEnv(t *testing.T) { - wrapper := NewAwsKmsTestWrapper() + _, err := wrapperWithMock.SetConfig(context.Background()) + require.Error(t, err, "expected error when AwsKms wrapping key ID is not provided") + }) - // Setup environment values to ignore for the following values - for _, envVar := range []string{EnvAwsKmsWrapperKeyId, EnvVaultAwsKmsSealKeyId, "AWS_KMS_ENDPOINT"} { - oldVal := os.Getenv(envVar) - os.Setenv(envVar, "envValue") - defer os.Setenv(envVar, oldVal) - } + t.Run("Success - Test key ID pulled from environment variables", func(t *testing.T) { + wrapperWithMock := NewWrapper() + wrapperWithMock.client = &mockClient{ + keyId: awsTestKeyId, + } + oldKeyId := os.Getenv(EnvAwsKmsWrapperKeyId) + os.Setenv(EnvAwsKmsWrapperKeyId, awsTestKeyId) + defer os.Setenv(EnvAwsKmsWrapperKeyId, oldKeyId) - config := map[string]string{ - "disallow_env_vars": "true", - "kms_key_id": "a-key-key", - "access_key": "a-access-key", - "secret_key": "a-secret-key", - "endpoint": "my-endpoint", - } + _, err := wrapperWithMock.SetConfig(context.Background()) + require.NoError(t, err) + }) + + t.Run("Success - Ignore environment variables", func(t *testing.T) { + // Setup environment values to ignore for the following values + for _, envVar := range []string{EnvAwsKmsWrapperKeyId, EnvVaultAwsKmsSealKeyId, EnvAwsKmsEndpoint, EnvAwsKmsEndpoint} { + oldVal := os.Getenv(envVar) + os.Setenv(envVar, "") + defer os.Setenv(envVar, oldVal) + } + wrapperWithMock := NewWrapper() + wrapperWithMock.client = &mockClient{ + keyId: awsTestKeyId, + } + + config := map[string]string{ + "disallow_env_vars": "true", + "kms_key_id": "a-key-key", + "access_key": "a-access-key", + "secret_key": "a-secret-key", + "endpoint": "my-endpoint", + } + + _, err := wrapperWithMock.SetConfig(context.Background(), wrapping.WithConfigMap(config)) + require.NoError(t, err) + + require.Equal(t, config["access_key"], wrapperWithMock.accessKey) + require.Equal(t, config["secret_key"], wrapperWithMock.secretKey) + require.Equal(t, config["kms_key_id"], wrapperWithMock.keyId) + require.Equal(t, config["endpoint"], wrapperWithMock.endpoint) + }) + + t.Run("Success - endpoint set automatically", func(t *testing.T) { + wrapperWithMock := NewWrapper() + wrapperWithMock.client = &mockClient{ + keyId: awsTestKeyId, + } + _, err := wrapperWithMock.SetConfig(t.Context(), WithKeyNotRequired(true)) + require.NoError(t, err) + + c, err := wrapperWithMock.GetAwsKmsClient(t.Context()) + require.NoError(t, err) + require.Nil(t, c.Options().BaseEndpoint) + }) + + t.Run("Success - custom endpoint set from environment variables", func(t *testing.T) { + expectedEndpoint := "https://example.com/0" + oldEndpoint := os.Getenv(EnvAwsKmsEndpoint) + os.Setenv(EnvAwsKmsEndpoint, expectedEndpoint) + defer os.Setenv(EnvAwsKmsEndpoint, oldEndpoint) + wrapperWithMock := NewWrapper() + wrapperWithMock.client = &mockClient{ + keyId: awsTestKeyId, + } + + _, err := wrapperWithMock.SetConfig(t.Context(), WithKeyNotRequired(true)) + require.NoError(t, err) + + c, err := wrapperWithMock.GetAwsKmsClient(t.Context()) + require.NoError(t, err) + assert.Equal(t, expectedEndpoint, *(c.Options().BaseEndpoint)) + }) + + t.Run("Success - custom endpoint set from config", func(t *testing.T) { + expectedEndpoint := "https://example.com/1" + + cfg := map[string]string{ + "endpoint": expectedEndpoint, + } + wrapperWithMock := NewWrapper() + wrapperWithMock.client = &mockClient{ + keyId: awsTestKeyId, + } + + _, err := wrapperWithMock.SetConfig(t.Context(), wrapping.WithConfigMap(cfg), WithKeyNotRequired(true)) + require.NoError(t, err) + + c, err := wrapperWithMock.GetAwsKmsClient(t.Context()) + require.NoError(t, err) + assert.Equal(t, expectedEndpoint, *(c.Options().BaseEndpoint)) + }) + + t.Run("Success - custom endpoint set from environment variables taking precedence over config", func(t *testing.T) { + expectedEndpoint := "https://example.com/2" + oldEndpoint := os.Getenv(EnvAwsKmsEndpoint) + os.Setenv(EnvAwsKmsEndpoint, expectedEndpoint) + defer os.Setenv(EnvAwsKmsEndpoint, oldEndpoint) + wrapperWithMock := NewWrapper() + wrapperWithMock.client = &mockClient{ + keyId: awsTestKeyId, + } + + cfg := map[string]string{ + "endpoint": "https://example.com/3", + } - _, err := wrapper.SetConfig(context.Background(), wrapping.WithConfigMap(config)) - assert.NoError(t, err) + _, err := wrapperWithMock.SetConfig(t.Context(), wrapping.WithConfigMap(cfg), WithKeyNotRequired(true)) + require.NoError(t, err) - require.Equal(t, config["access_key"], wrapper.accessKey) - require.Equal(t, config["secret_key"], wrapper.secretKey) - require.Equal(t, config["kms_key_id"], wrapper.keyId) - require.Equal(t, config["endpoint"], wrapper.endpoint) + c, err := wrapperWithMock.GetAwsKmsClient(t.Context()) + require.NoError(t, err) + assert.Equal(t, expectedEndpoint, *(c.Options().BaseEndpoint)) + }) } -func TestAwsKmsWrapper_Lifecycle(t *testing.T) { - if os.Getenv(EnvAwsKmsWrapperKeyId) == "" && os.Getenv(EnvVaultAwsKmsSealKeyId) == "" { - t.SkipNow() - } - s := NewWrapper() - s.client = &mockClient{ - keyId: aws.String(awsTestKeyId), - } - oldKeyId := os.Getenv(EnvAwsKmsWrapperKeyId) - os.Setenv(EnvAwsKmsWrapperKeyId, awsTestKeyId) - defer os.Setenv(EnvAwsKmsWrapperKeyId, oldKeyId) - testEncryptionRoundTrip(t, s) +func TestEncryptAndDecrypt(t *testing.T) { + t.Run("Success - mock client", func(t *testing.T) { + // Works around lack of AWS_REGION var in CI + if os.Getenv(envAwsRegion) == "" { + os.Setenv(envAwsRegion, "us-west-2") + defer os.Setenv(envAwsRegion, "") + } + wrapperWithMock := NewWrapper() + wrapperWithMock.client = &mockClient{ + keyId: awsTestKeyId, + } + oldKeyId := os.Getenv(EnvAwsKmsWrapperKeyId) + os.Setenv(EnvAwsKmsWrapperKeyId, awsTestKeyId) + defer os.Setenv(EnvAwsKmsWrapperKeyId, oldKeyId) + encryptionRoundTrip(t, wrapperWithMock) + }) + // To run the concrete enryption test, the following env variables need to be set: + // - AWSKMS_WRAPPER_KEY_ID or VAULT_AWSKMS_SEAL_KEY_ID + // - This is the ID of a KMS key in AWS that is symmetric with encrypt & decrypt usage. + // - AWS_ACCESS_KEY_ID + // - AWS_SECRET_ACCESS_KEY + // - AWS_SESSION_TOKEN + // - AWS_REGION + // - Works around https://hashicorp.atlassian.net/browse/ICU-17849 + + t.Run("Success - concrete client", func(t *testing.T) { + if os.Getenv(EnvAwsKmsWrapperKeyId) == "" && os.Getenv(EnvVaultAwsKmsSealKeyId) == "" { + t.Skip("AWSKMS_WRAPPER_KEY_ID or VAULT_AWSKMS_SEAL_KEY_ID required for concrete encryption test") + } + if os.Getenv("AWS_ACCESS_KEY_ID") == "" { + t.Skip("AWS_ACCESS_KEY_ID required for concrete encryption test") + } + if os.Getenv("AWS_SECRET_ACCESS_KEY") == "" { + t.Skip("AWS_SECRET_ACCESS_KEY required for concrete encryption test") + } + if os.Getenv("AWS_SESSION_TOKEN") == "" { + t.Skip("AWS_SESSION_TOKEN required for concrete encryption test") + } + if os.Getenv("AWS_REGION") == "" { + t.Skip("AWS_REGION required for concrete encryption test") + } + w := NewWrapper() + + encryptionRoundTrip(t, w) + }) } -// This test executes real calls. The calls themselves should be free, -// but the KMS key used is generally not free. AWS charges about $1/month -// per key. +// Shared profile test setup: +// - Create a role in AWS that whatever role/user you're authenticating as has permission to sts::SetSourceIdentity as +// - Create two profiles in ~/.aws/config +// - A source profile that has credentials or some method of logging in +// - A sink profile that uses `source_profile=$YOUR_SOURCE_PROFILE` and `role_arn=$YOUR_NEW_ROLE` // -// To run this test, the following env variables need to be set: -// - AWSKMS_WRAPPER_KEY_ID or VAULT_AWSKMS_SEAL_KEY_ID -// - AWS_REGION -// - AWS_ACCESS_KEY_ID -// - AWS_SECRET_ACCESS_KEY -func TestAccAwsKmsWrapper_Lifecycle(t *testing.T) { +// - Set AWS_PROFILE=$SINK_PROFILE (for shared profile through AWS_PROFILE) +// - Set TEST_PROFILE=$SINK_PROFILE (for shared profile through WithSharedCredsProfile) +// - Set AWS_REGION and AWS_KMS_WRAPPER_KEY_ID as above +func TestSharedProfiles(t *testing.T) { + if os.Getenv("AWS_REGION") == "" { + t.Skip("AWS_REGION required for shared profiles tests") + } if os.Getenv(EnvAwsKmsWrapperKeyId) == "" && os.Getenv(EnvVaultAwsKmsSealKeyId) == "" { - t.SkipNow() + t.Skip("AWSKMS_WRAPPER_KEY_ID or VAULT_AWSKMS_SEAL_KEY_ID required for shared profiles tests") } - s := NewWrapper() - testEncryptionRoundTrip(t, s) -} -func testEncryptionRoundTrip(t *testing.T, w *Wrapper) { - w.SetConfig(context.Background()) - input := []byte("foo") - swi, err := w.Encrypt(context.Background(), input, nil) - if err != nil { - t.Fatalf("err: %s", err.Error()) - } + t.Run("Success - shared profile from WithSharedCredsProfile", func(t *testing.T) { + prof := os.Getenv("TEST_PROFILE") + if prof == "" { + t.Skip("TEST_PROFILE required for shared profile from WithSharedCredsProfile test") + } + // Prevent AWS_PROFILE from clobbering this test + if old := os.Getenv(envAwsProfile); old != "" { + os.Setenv(envAwsProfile, "") + defer os.Setenv(envAwsProfile, old) + } - pt, err := w.Decrypt(context.Background(), swi, nil) - if err != nil { - t.Fatalf("err: %s", err.Error()) - } + w := NewWrapper() - if !reflect.DeepEqual(input, pt) { - t.Fatalf("expected %s, got %s", input, pt) - } + _, err := w.SetConfig(t.Context(), WithSharedCredsProfile(prof)) + require.NoError(t, err) + + encryptionRoundTrip(t, w) + }) + + t.Run("Success - shared profile from AWS_PROFILE", func(t *testing.T) { + // Default awskms config pulls shared creds from AWS_PROFILE if it's set + if os.Getenv(envAwsProfile) == "" { + t.Skip("AWS_PROFILE required for shared profile from AWS_PROFILE test") + } + + w := NewWrapper() + _, err := w.SetConfig(t.Context()) + require.NoError(t, err) + encryptionRoundTrip(t, w) + }) + + t.Run("Failure - no shared config", func(t *testing.T) { + if old := os.Getenv(envAwsProfile); old != "" { + os.Setenv(envAwsProfile, "") + defer os.Setenv(envAwsProfile, old) + } + + w := NewWrapper() + + _, err := w.SetConfig(t.Context(), WithSharedCredsProfile("this-profile-definitely-doesn't-exist")) + require.Error(t, err) + }) } -func TestAwsKmsWrapper_custom_endpoint(t *testing.T) { - customEndpoint := "https://custom.endpoint" - customEndpoint2 := "https://custom.endpoint.2" - endpointENV := "AWS_KMS_ENDPOINT" - - // unset at end of test - os.Setenv(EnvAwsKmsWrapperKeyId, awsTestKeyId) - defer func() { - if err := os.Unsetenv(EnvAwsKmsWrapperKeyId); err != nil { - t.Fatal(err) - } - }() - - cfg := make(map[string]string) - cfg["endpoint"] = customEndpoint - - testCases := []struct { - Title string - Env string - Config map[string]string - Expected *string - }{ - { - // Default will have nil for the config endpoint, and be looked up - // dynamically by the SDK - Title: "Default", - }, - { - Title: "Environment", - Env: customEndpoint, - Expected: aws.String(customEndpoint), - }, - { - Title: "Config", - Config: cfg, - Expected: aws.String(customEndpoint), - }, - { - // Expect environment to take precedence over configuration - Title: "Env-Config", - Env: customEndpoint2, - Config: cfg, - Expected: aws.String(customEndpoint2), - }, - } +func encryptionRoundTrip(t *testing.T, w *Wrapper) { + _, err := w.SetConfig(t.Context()) + require.NoError(t, err) - for _, tc := range testCases { - t.Run(tc.Title, func(t *testing.T) { - s := NewWrapper() - - s.client = &mockClient{ - keyId: aws.String(awsTestKeyId), - } - - if tc.Env != "" { - if err := os.Setenv(endpointENV, tc.Env); err != nil { - t.Fatal(err) - } - } - - // cfg starts as nil, and takes a test case value if given. If not, - // SetConfig is called with nil and creates it's own config - var cfg map[string]string - if tc.Config != nil { - cfg = tc.Config - } - if _, err := s.SetConfig(context.Background(), wrapping.WithConfigMap(cfg)); err != nil { - t.Fatalf("error setting config: %s", err) - } - - // call GetAwsKmsClient() to get the configured client and verify it's - // endpoint - k, err := s.GetAwsKmsClient() - if err != nil { - t.Fatal(err) - } - - if tc.Expected == nil && k.Config.Endpoint != nil { - t.Fatalf("Expected nil endpoint, got: (%s)", *k.Config.Endpoint) - } - - if tc.Expected != nil { - if k.Config.Endpoint == nil { - t.Fatal("expected custom endpoint, but config was nil") - } - if *k.Config.Endpoint != *tc.Expected { - t.Fatalf("expected custom endpoint (%s), got: (%s)", *tc.Expected, *k.Config.Endpoint) - } - } - - // clear endpoint env after each test - if err := os.Unsetenv(endpointENV); err != nil { - t.Fatal(err) - } - }) - } + expected := []byte("foo") + swi, err := w.Encrypt(context.Background(), expected, nil) + require.NoError(t, err) + + output, err := w.Decrypt(context.Background(), swi, nil) + require.NoError(t, err) + assert.Equal(t, expected, output) } diff --git a/wrappers/awskms/go.mod b/wrappers/awskms/go.mod index 6a5a9904..a4da2259 100644 --- a/wrappers/awskms/go.mod +++ b/wrappers/awskms/go.mod @@ -1,33 +1,48 @@ -module github.com/hashicorp/go-kms-wrapping/wrappers/awskms/v2 +module github.com/hashicorp/go-kms-wrapping/wrappers/awskms/v3 -go 1.20 +go 1.24.0 require ( - github.com/aws/aws-sdk-go v1.55.5 + github.com/aws/aws-sdk-go-v2 v1.39.2 + github.com/aws/aws-sdk-go-v2/config v1.31.12 + github.com/aws/aws-sdk-go-v2/service/kms v1.45.6 github.com/hashicorp/go-cleanhttp v0.5.2 - github.com/hashicorp/go-hclog v1.5.0 - github.com/hashicorp/go-kms-wrapping/v2 v2.0.17 - github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6 - github.com/stretchr/testify v1.8.4 + github.com/hashicorp/go-hclog v1.6.3 + github.com/hashicorp/go-kms-wrapping/v2 v2.0.18 + github.com/hashicorp/go-secure-stdlib/awsutil/v2 v2.1.1 + github.com/stretchr/testify v1.11.1 + go.uber.org/mock v0.6.0 ) require ( + github.com/aws/aws-sdk-go-v2/credentials v1.18.16 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect + github.com/aws/aws-sdk-go-v2/service/iam v1.47.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.29.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 // indirect + github.com/aws/smithy-go v1.23.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fatih/color v1.14.1 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-secure-stdlib/parseutil v0.1.9 // indirect + github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect - github.com/hashicorp/go-sockaddr v1.0.6 // indirect + github.com/hashicorp/go-sockaddr v1.0.7 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.14.1 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect - golang.org/x/sys v0.29.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect + golang.org/x/sys v0.36.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/wrappers/awskms/go.sum b/wrappers/awskms/go.sum index 1f565df3..b586aaff 100644 --- a/wrappers/awskms/go.sum +++ b/wrappers/awskms/go.sum @@ -1,103 +1,137 @@ -github.com/aws/aws-sdk-go v1.30.27/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= -github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= -github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.39.2 h1:EJLg8IdbzgeD7xgvZ+I8M1e0fL0ptn/M47lianzth0I= +github.com/aws/aws-sdk-go-v2 v1.39.2/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY= +github.com/aws/aws-sdk-go-v2 v1.39.6 h1:2JrPCVgWJm7bm83BDwY5z8ietmeJUbh3O2ACnn+Xsqk= +github.com/aws/aws-sdk-go-v2 v1.39.6/go.mod h1:c9pm7VwuW0UPxAEYGyTmyurVcNrbF6Rt/wixFqDhcjE= +github.com/aws/aws-sdk-go-v2/config v1.31.12 h1:pYM1Qgy0dKZLHX2cXslNacbcEFMkDMl+Bcj5ROuS6p8= +github.com/aws/aws-sdk-go-v2/config v1.31.12/go.mod h1:/MM0dyD7KSDPR+39p9ZNVKaHDLb9qnfDurvVS2KAhN8= +github.com/aws/aws-sdk-go-v2/config v1.31.17 h1:QFl8lL6RgakNK86vusim14P2k8BFSxjvUkcWLDjgz9Y= +github.com/aws/aws-sdk-go-v2/config v1.31.17/go.mod h1:V8P7ILjp/Uef/aX8TjGk6OHZN6IKPM5YW6S78QnRD5c= +github.com/aws/aws-sdk-go-v2/credentials v1.18.16 h1:4JHirI4zp958zC026Sm+V4pSDwW4pwLefKrc0bF2lwI= +github.com/aws/aws-sdk-go-v2/credentials v1.18.16/go.mod h1:qQMtGx9OSw7ty1yLclzLxXCRbrkjWAM7JnObZjmCB7I= +github.com/aws/aws-sdk-go-v2/credentials v1.18.21 h1:56HGpsgnmD+2/KpG0ikvvR8+3v3COCwaF4r+oWwOeNA= +github.com/aws/aws-sdk-go-v2/credentials v1.18.21/go.mod h1:3YELwedmQbw7cXNaII2Wywd+YY58AmLPwX4LzARgmmA= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9 h1:Mv4Bc0mWmv6oDuSWTKnk+wgeqPL5DRFu5bQL9BGPQ8Y= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.9/go.mod h1:IKlKfRppK2a1y0gy1yH6zD+yX5uplJ6UuPlgd48dJiQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13 h1:T1brd5dR3/fzNFAQch/iBKeX07/ffu/cLu+q+RuzEWk= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.13/go.mod h1:Peg/GBAQ6JDt+RoBf4meB1wylmAipb7Kg2ZFakZTlwk= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 h1:se2vOWGD3dWQUtfn4wEjRQJb1HK1XsNIt825gskZ970= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9/go.mod h1:hijCGH2VfbZQxqCDN7bwz/4dzxV+hkyhjawAtdPWKZA= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13 h1:a+8/MLcWlIxo1lF9xaGt3J/u3yOZx+CdSveSNwjhD40= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.13/go.mod h1:oGnKwIYZ4XttyU2JWxFrwvhF6YKiK/9/wmE3v3Iu9K8= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 h1:6RBnKZLkJM4hQ+kN6E7yWFveOTg8NLPHAkqrs4ZPlTU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9/go.mod h1:V9rQKRmK7AWuEsOMnHzKj8WyrIir1yUJbZxDuZLFvXI= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13 h1:HBSI2kDkMdWz4ZM7FjwE7e/pWDEZ+nR95x8Ztet1ooY= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.13/go.mod h1:YE94ZoDArI7awZqJzBAZ3PDD2zSfuP7w6P2knOzIn8M= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= +github.com/aws/aws-sdk-go-v2/service/iam v1.47.7 h1:0EDAdmMTzsgXl++8a0JZ+Yx0/dOqT8o/EONknxlQK94= +github.com/aws/aws-sdk-go-v2/service/iam v1.47.7/go.mod h1:NkNbn/8/mFrPUq0Kg6EM6c0+GaTLG+aPzXxwB7RF5xo= +github.com/aws/aws-sdk-go-v2/service/iam v1.49.2 h1:XeF6yEMX4/FxoSHCE1VNMOZ0t+mGnf/onqVe9dDVAlQ= +github.com/aws/aws-sdk-go-v2/service/iam v1.49.2/go.mod h1:cuEMbL1mNtO1sUyT+DYDNIA8Y7aJG1oIdgHqUk29Uzk= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1 h1:oegbebPEMA/1Jny7kvwejowCaHz1FWZAQ94WXFNCyTM= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.1/go.mod h1:kemo5Myr9ac0U9JfSjMo9yHLtw+pECEHsFtJ9tqCEI8= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3 h1:x2Ibm/Af8Fi+BH+Hsn9TXGdT+hKbDd5XOTZxTMxDk7o= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.3/go.mod h1:IW1jwyrQgMdhisceG8fQLmQIydcT/jWY21rFhzgaKwo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9 h1:5r34CgVOD4WZudeEKZ9/iKpiT6cM1JyEROpXjOcdWv8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.9/go.mod h1:dB12CEbNWPbzO2uC6QSWHteqOg4JfBVJOojbAoAUb5I= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13 h1:kDqdFvMY4AtKoACfzIGD8A0+hbT41KTKF//gq7jITfM= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.13/go.mod h1:lmKuogqSU3HzQCwZ9ZtcqOc5XGMqtDK7OIc2+DxiUEg= +github.com/aws/aws-sdk-go-v2/service/kms v1.45.6 h1:Br3kil4j7RPW+7LoLVkYt8SuhIWlg6ylmbmzXJ7PgXY= +github.com/aws/aws-sdk-go-v2/service/kms v1.45.6/go.mod h1:FKXkHzw1fJZtg1P1qoAIiwen5thz/cDRTTDCIu8ljxc= +github.com/aws/aws-sdk-go-v2/service/kms v1.47.1 h1:6+C0RoGF4HJQALrsecOXN7cm/l5rgNHCw2xbcvFgpH4= +github.com/aws/aws-sdk-go-v2/service/kms v1.47.1/go.mod h1:VJcNH6BLr+3VJwinRKdotLOMglHO8mIKlD3ea5c7hbw= +github.com/aws/aws-sdk-go-v2/service/sso v1.29.6 h1:A1oRkiSQOWstGh61y4Wc/yQ04sqrQZr1Si/oAXj20/s= +github.com/aws/aws-sdk-go-v2/service/sso v1.29.6/go.mod h1:5PfYspyCU5Vw1wNPsxi15LZovOnULudOQuVxphSflQA= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.1 h1:0JPwLz1J+5lEOfy/g0SURC9cxhbQ1lIMHMa+AHZSzz0= +github.com/aws/aws-sdk-go-v2/service/sso v1.30.1/go.mod h1:fKvyjJcz63iL/ftA6RaM8sRCtN4r4zl4tjL3qw5ec7k= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1 h1:5fm5RTONng73/QA73LhCNR7UT9RpFH3hR6HWL6bIgVY= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.1/go.mod h1:xBEjWD13h+6nq+z4AkqSfSvqRKFgDIQeaMguAJndOWo= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.5 h1:OWs0/j2UYR5LOGi88sD5/lhN6TDLG6SfA7CqsQO9zF0= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.5/go.mod h1:klO+ejMvYsB4QATfEOIXk8WAEwN4N0aBfJpvC+5SZBo= +github.com/aws/aws-sdk-go-v2/service/sts v1.38.6 h1:p3jIvqYwUZgu/XYeI48bJxOhvm47hZb5HUQ0tn6Q9kA= +github.com/aws/aws-sdk-go-v2/service/sts v1.38.6/go.mod h1:WtKK+ppze5yKPkZ0XwqIVWD4beCwv056ZbPQNoeHqM8= +github.com/aws/aws-sdk-go-v2/service/sts v1.39.1 h1:mLlUgHn02ue8whiR4BmxxGJLR2gwU6s6ZzJ5wDamBUs= +github.com/aws/aws-sdk-go-v2/service/sts v1.39.1/go.mod h1:E19xDjpzPZC7LS2knI9E6BaRFDK43Eul7vd6rSq2HWk= +github.com/aws/smithy-go v1.23.0 h1:8n6I3gXzWJB2DxBDnfxgBaSX6oe0d/t10qGz7OKqMCE= +github.com/aws/smithy-go v1.23.0/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI= +github.com/aws/smithy-go v1.23.2 h1:Crv0eatJUQhaManss33hS5r40CG3ZFH+21XSkqMrIUM= +github.com/aws/smithy-go v1.23.2/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w= -github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg= -github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.16.2/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= -github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= -github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= -github.com/hashicorp/go-kms-wrapping/v2 v2.0.17 h1:UjjwDABbv2Usc+ESZTC4DXimCRIyWUDBJe/LOUFxe/M= -github.com/hashicorp/go-kms-wrapping/v2 v2.0.17/go.mod h1:M79wTAvbhiVLo1WmglCPBgI5CEETtZWh18B3eXipmFc= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-kms-wrapping/v2 v2.0.18 h1:DLfC677GfKEpSAFpEWvl1vXsGpEcSHmbhBaPLrdDQHc= +github.com/hashicorp/go-kms-wrapping/v2 v2.0.18/go.mod h1:t/eaR/mi2mw3klfl1WEAuiLKrlZ/Q8cosmsT+RIPLu0= +github.com/hashicorp/go-kms-wrapping/v2 v2.0.19 h1:FX7HrkfkYomf4SlMrwzOP32FXuFltq34Qy/gXk1Tp5Y= +github.com/hashicorp/go-kms-wrapping/v2 v2.0.19/go.mod h1:wpZygQlPUUGt4Klgg+RlCaq/KRe8XinEzqTf7QmvrNo= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= -github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6 h1:W9WN8p6moV1fjKLkeqEgkAMu5rauy9QeYDAmIaPuuiA= -github.com/hashicorp/go-secure-stdlib/awsutil v0.1.6/go.mod h1:MpCPSPGLDILGb4JMm94/mMi3YysIqsXzGCzkEZjcjXg= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.9 h1:FW0YttEnUNDJ2WL9XcrrfteS1xW8u+sh4ggM8pN5isQ= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.9/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0= +github.com/hashicorp/go-secure-stdlib/awsutil/v2 v2.1.0 h1:V3TJFolOHYSDqQLbTUBygXtbX4jKXyBcDoU+KNZE1Ak= +github.com/hashicorp/go-secure-stdlib/awsutil/v2 v2.1.0/go.mod h1:OeRwM2eWNW62L1Z+8GvoZM5nQJMRWBewHSoo77qmb4Y= +github.com/hashicorp/go-secure-stdlib/awsutil/v2 v2.1.1 h1:rXE5JmHT14VYLVm+hHSqBOojPl0rlBqJx6YLikUuCgM= +github.com/hashicorp/go-secure-stdlib/awsutil/v2 v2.1.1/go.mod h1:6+rVulOPNCQbL3Xv2iLCqM0JmU2WO2wRzP1C6hBKeB8= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 h1:U+kC2dOhMFQctRfhK0gRctKAPTloZdMU5ZJxaesJ/VM= +github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0/go.mod h1:Ll013mhdmsVDuoIXVfBtvgGJsXDYkTw1kooNcoCXuE0= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= -github.com/hashicorp/go-sockaddr v1.0.6 h1:RSG8rKU28VTUTvEKghe5gIhIQpv8evvNpnDEyqO4u9I= -github.com/hashicorp/go-sockaddr v1.0.6/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI= +github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw= +github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -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/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/wrappers/awskms/testing.go b/wrappers/awskms/mockclient_test.go similarity index 53% rename from wrappers/awskms/testing.go rename to wrappers/awskms/mockclient_test.go index 76160f8d..de677194 100644 --- a/wrappers/awskms/testing.go +++ b/wrappers/awskms/mockclient_test.go @@ -4,32 +4,22 @@ package awskms import ( + "context" "encoding/base64" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/aws/aws-sdk-go/service/kms/kmsiface" + "github.com/aws/aws-sdk-go-v2/service/kms" + "github.com/aws/aws-sdk-go-v2/service/kms/types" + "github.com/hashicorp/go-secure-stdlib/awsutil/v2" ) -const awsTestKeyId = "foo" - -func NewAwsKmsTestWrapper() *Wrapper { - s := NewWrapper() - s.client = &mockClient{ - keyId: aws.String(awsTestKeyId), - } - return s -} - type mockClient struct { - kmsiface.KMSAPI - keyId *string + KmsApi + keyId string } // Encrypt is a mocked call that returns a base64 encoded string. -func (m *mockClient) Encrypt(input *kms.EncryptInput) (*kms.EncryptOutput, error) { - m.keyId = input.KeyId +func (m *mockClient) Encrypt(_ context.Context, input *kms.EncryptInput, _ ...func(*kms.Options)) (*kms.EncryptOutput, error) { + m.keyId = *input.KeyId encoded := make([]byte, base64.StdEncoding.EncodedLen(len(input.Plaintext))) base64.StdEncoding.Encode(encoded, input.Plaintext) @@ -41,7 +31,7 @@ func (m *mockClient) Encrypt(input *kms.EncryptInput) (*kms.EncryptOutput, error } // Decrypt is a mocked call that returns a decoded base64 string. -func (m *mockClient) Decrypt(input *kms.DecryptInput) (*kms.DecryptOutput, error) { +func (m *mockClient) Decrypt(_ context.Context, input *kms.DecryptInput, _ ...func(*kms.Options)) (*kms.DecryptOutput, error) { decLen := base64.StdEncoding.DecodedLen(len(input.CiphertextBlob)) decoded := make([]byte, decLen) len, err := base64.StdEncoding.Decode(decoded, input.CiphertextBlob) @@ -54,20 +44,24 @@ func (m *mockClient) Decrypt(input *kms.DecryptInput) (*kms.DecryptOutput, error } return &kms.DecryptOutput{ - KeyId: m.keyId, + KeyId: &m.keyId, Plaintext: decoded, }, nil } // DescribeKey is a mocked call that returns the keyId. -func (m *mockClient) DescribeKey(input *kms.DescribeKeyInput) (*kms.DescribeKeyOutput, error) { - if m.keyId == nil { - return nil, awserr.New(kms.ErrCodeNotFoundException, "key not found", nil) +func (m *mockClient) DescribeKey(_ context.Context, inpput *kms.DescribeKeyInput, _ ...func(*kms.Options)) (*kms.DescribeKeyOutput, error) { + if m.keyId == "" { + return nil, &awsutil.MockAWSErr{ + Code: "ErrCodeNotFoundException", + Message: "Key not found", + } + } return &kms.DescribeKeyOutput{ - KeyMetadata: &kms.KeyMetadata{ - KeyId: m.keyId, + KeyMetadata: &types.KeyMetadata{ + KeyId: &m.keyId, }, }, nil }