From 075ea1811533da8ce23ab4deddbc2e9d58fa760f Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Fri, 26 Aug 2022 16:18:21 -0400 Subject: [PATCH 1/7] upgrade sdk --- go.mod | 3 + go.sum | 25 ++++++++ internal/metrics/kms_decrypter.go | 32 ++++++----- internal/metrics/kms_decrypter_test.go | 80 -------------------------- 4 files changed, 46 insertions(+), 94 deletions(-) delete mode 100644 internal/metrics/kms_decrypter_test.go diff --git a/go.mod b/go.mod index 71dff838..a1084cf9 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/DataDog/datadog-go v4.8.3+incompatible github.com/aws/aws-lambda-go v1.29.0 github.com/aws/aws-sdk-go v1.43.37 + github.com/aws/aws-sdk-go-v2 v1.16.11 github.com/aws/aws-xray-sdk-go v1.6.0 github.com/cenkalti/backoff v2.2.1+incompatible github.com/sony/gobreaker v0.5.0 @@ -20,6 +21,8 @@ require ( github.com/DataDog/sketches-go v1.4.1 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect github.com/andybalholm/brotli v1.0.4 // indirect + github.com/aws/aws-sdk-go-v2/config v1.17.1 // indirect + github.com/aws/aws-sdk-go-v2/service/kms v1.18.5 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgraph-io/ristretto v0.1.0 // indirect diff --git a/go.sum b/go.sum index 7fb7ed70..b0b30991 100644 --- a/go.sum +++ b/go.sum @@ -89,18 +89,42 @@ github.com/aws/aws-sdk-go v1.43.37 h1:kyZ7UjaPZaCik+asF33UFOOYSwr9liDRr/UM/vuw8y github.com/aws/aws-sdk-go v1.43.37/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo= github.com/aws/aws-sdk-go-v2 v1.0.0/go.mod h1:smfAbmpW+tcRVuNUjo3MOArSZmW72t62rkCzc2i0TWM= github.com/aws/aws-sdk-go-v2 v1.6.0/go.mod h1:tI4KhsR5VkzlUa2DZAdwx7wCAYGwkZZ1H31PYrBFx1w= +github.com/aws/aws-sdk-go-v2 v1.16.11 h1:xM1ZPSvty3xVmdxiGr7ay/wlqv+MWhH0rMlyLdbC0YQ= +github.com/aws/aws-sdk-go-v2 v1.16.11/go.mod h1:WTACcleLz6VZTp7fak4EO5b9Q4foxbn+8PIz3PmyKlo= github.com/aws/aws-sdk-go-v2/config v1.0.0/go.mod h1:WysE/OpUgE37tjtmtJd8GXgT8s1euilE5XtUkRNUQ1w= +github.com/aws/aws-sdk-go-v2/config v1.17.1 h1:BWxTjokU/69BZ4DnLrZco6OvBDii6ToEdfBL/y5I1nA= +github.com/aws/aws-sdk-go-v2/config v1.17.1/go.mod h1:uOxDHjBemNTF2Zos+fgG0NNfE86wn1OAHDTGxjMEYi0= github.com/aws/aws-sdk-go-v2/credentials v1.0.0/go.mod h1:/SvsiqBf509hG4Bddigr3NB12MIpfHhZapyBurJe8aY= +github.com/aws/aws-sdk-go-v2/credentials v1.12.14 h1:AtVG/amkjbDBfnPr/tuW2IG18HGNznP6L12Dx0rLz+Q= +github.com/aws/aws-sdk-go-v2/credentials v1.12.14/go.mod h1:opAndTyq+YN7IpVG57z2CeNuXSQMqTYxGGlYH0m0RMY= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.0/go.mod h1:wpMHDCXvOXZxGCRSidyepa8uJHY4vaBGfY2/+oKU/Bc= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.12 h1:wgJBHO58Pc1V1QAnzdVM3JK3WbE/6eUF0JxCZ+/izz0= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.12/go.mod h1:aZ4vZnyUuxedC7eD4JyEHpGnCz+O2sHQEx3VvAwklSE= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.18 h1:OmiwoVyLKEqqD5GvB683dbSqxiOfvx4U2lDZhG2Esc4= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.18/go.mod h1:348MLhzV1GSlZSMusdwQpXKbhD7X2gbI/TxwAPKkYZQ= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.12 h1:5mvQDtNWtI6H56+E4LUnLWEmATMB7oEh+Z9RurtIuC0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.12/go.mod h1:ckaCVTEdGAxO6KwTGzgskxR1xM+iJW4lxMyDFVda2Fc= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.19 h1:g5qq9sgtEzt2szMaDqQO6fqKe026T6dHTFJp5NsPzkQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.3.19/go.mod h1:cVHo8KTuHjShb9V8/VjH3S/8+xPu16qx8fdGwmotJhE= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.0/go.mod h1:3jExOmpbjgPnz2FJaMOfbSk1heTkZ66aD3yNtVhnjvI= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.12 h1:7iPTTX4SAI2U2VOogD7/gmHlsgnYSgoNHt7MSQXtG2M= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.12/go.mod h1:1TODGhheLWjpQWSuhYuAUWYTCKwEjx2iblIFKDHjeTc= +github.com/aws/aws-sdk-go-v2/service/kms v1.18.5 h1:bgIax/BQB8/U8qXavwKFOPzbnSAAQjPQ5hDM4FwN2gA= +github.com/aws/aws-sdk-go-v2/service/kms v1.18.5/go.mod h1:WG8HUJKtDqXJM3+CNZeN+2wvdcJb5vprKo01fr1KQW4= github.com/aws/aws-sdk-go-v2/service/route53 v1.6.2/go.mod h1:ZnAMilx42P7DgIrdjlWCkNIGSBLzeyk6T31uB8oGTwY= github.com/aws/aws-sdk-go-v2/service/sqs v1.0.0/go.mod h1:w5BclCU8ptTbagzXS/fHBr+vAyXUjggg/72qDIURKMk= +github.com/aws/aws-sdk-go-v2/service/sso v1.11.17 h1:pXxu9u2z1UqSbjO9YA8kmFJBhFc1EVTDaf7A+S+Ivq8= +github.com/aws/aws-sdk-go-v2/service/sso v1.11.17/go.mod h1:mS5xqLZc/6kc06IpXn5vRxdLaED+jEuaSRv5BxtnsiY= github.com/aws/aws-sdk-go-v2/service/sts v1.0.0/go.mod h1:5f+cELGATgill5Pu3/vK3Ebuigstc+qYEHW5MvGWZO4= +github.com/aws/aws-sdk-go-v2/service/sts v1.16.13 h1:dl8T0PJlN92rvEGOEUiD0+YPYdPEaCZK0TqHukvSfII= +github.com/aws/aws-sdk-go-v2/service/sts v1.16.13/go.mod h1:Ru3QVMLygVs/07UQ3YDur1AQZZp2tUNje8wfloFttC0= github.com/aws/aws-xray-sdk-go v1.6.0 h1:w4dPTvHZtbQg3dQFTRTu4TIunlfJCRGKdmGYZkcEJwI= github.com/aws/aws-xray-sdk-go v1.6.0/go.mod h1:k+NuTgdU+z07L3l8lnGHK+/luqe8TKmZJNpQAoVfLeY= github.com/aws/smithy-go v1.0.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= github.com/aws/smithy-go v1.4.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/aws/smithy-go v1.11.0/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM= +github.com/aws/smithy-go v1.12.1 h1:yQRC55aXN/y1W10HgwHle01DRuV9Dpf31iGkotjt3Ag= +github.com/aws/smithy-go v1.12.1/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= @@ -272,6 +296,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= diff --git a/internal/metrics/kms_decrypter.go b/internal/metrics/kms_decrypter.go index eee261a3..3a8d10f1 100644 --- a/internal/metrics/kms_decrypter.go +++ b/internal/metrics/kms_decrypter.go @@ -8,14 +8,14 @@ package metrics import ( + "context" "encoding/base64" "fmt" "os" "github.com/DataDog/datadog-lambda-go/internal/logger" - "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" ) type ( @@ -25,25 +25,25 @@ type ( } kmsDecrypter struct { - kmsClient *kms.KMS + kmsClient *kms.Client } ) // functionNameEnvVar is the environment variable that stores the Lambda function name -const functionNameEnvVar = "AWS_LAMBDA_FUNCTION_NAME" +const functionNameEnvVar string = "AWS_LAMBDA_FUNCTION_NAME" // encryptionContextKey is the key added to the encryption context by the Lambda console UI -const encryptionContextKey = "LambdaFunctionName" +const encryptionContextKey string = "LambdaFunctionName" // MakeKMSDecrypter creates a new decrypter which uses the AWS KMS service to decrypt variables func MakeKMSDecrypter() Decrypter { - sess, err := session.NewSession(nil) + cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { - logger.Error(fmt.Errorf("could not create a new aws-sdk session: %v", err)) + logger.Error(fmt.Errorf("could not create a new aws-sdk config: %v", err)) panic(err) } return &kmsDecrypter{ - kmsClient: kms.New(sess), + kmsClient: kms.NewFromConfig(cfg), } } @@ -51,9 +51,13 @@ func (kd *kmsDecrypter) Decrypt(ciphertext string) (string, error) { return decryptKMS(kd.kmsClient, ciphertext) } +func defaultDecryptOpt(opt *kms.Options) { + opt.EndpointResolver = kms.NewDefaultEndpointResolver() +} + // decryptKMS decodes and deciphers the base64-encoded ciphertext given as a parameter using KMS. // For this to work properly, the Lambda function must have the appropriate IAM permissions. -func decryptKMS(kmsClient kmsiface.KMSAPI, ciphertext string) (string, error) { +func decryptKMS(kmsClient *kms.Client, ciphertext string) (string, error) { decodedBytes, err := base64.StdEncoding.DecodeString(ciphertext) if err != nil { return "", fmt.Errorf("failed to encode cipher text to base64: %v", err) @@ -68,18 +72,18 @@ func decryptKMS(kmsClient kmsiface.KMSAPI, ciphertext string) (string, error) { params := &kms.DecryptInput{ CiphertextBlob: decodedBytes, } - response, err := kmsClient.Decrypt(params) + response, err := kmsClient.Decrypt(context.TODO(), params, defaultDecryptOpt) if err != nil { logger.Debug("Failed to decrypt ciphertext without encryption context, retrying with encryption context") // Try with encryption context, in case API key was encrypted using the AWS Console params = &kms.DecryptInput{ CiphertextBlob: decodedBytes, - EncryptionContext: map[string]*string{ - encryptionContextKey: &functionName, + EncryptionContext: map[string]string{ + encryptionContextKey: functionName, }, } - response, err = kmsClient.Decrypt(params) + response, err = kmsClient.Decrypt(context.TODO(), params, defaultDecryptOpt) if err != nil { return "", fmt.Errorf("failed to decrypt ciphertext with kms: %v", err) } diff --git a/internal/metrics/kms_decrypter_test.go b/internal/metrics/kms_decrypter_test.go deleted file mode 100644 index f71f0ab5..00000000 --- a/internal/metrics/kms_decrypter_test.go +++ /dev/null @@ -1,80 +0,0 @@ -// Unless explicitly stated otherwise all files in this repository are licensed -// under the Apache License Version 2.0. -// This product includes software developed at Datadog (https://www.datadoghq.com/). -// Copyright 2016-present Datadog, Inc. - -package metrics - -import ( - "bytes" - "errors" - "os" - "testing" - - "github.com/aws/aws-sdk-go/service/kms" - "github.com/aws/aws-sdk-go/service/kms/kmsiface" - "github.com/stretchr/testify/assert" -) - -// mockEncryptedAPIKeyBase64 represents an API key encrypted with KMS and encoded as a base64 string -const mockEncryptedAPIKeyBase64 = "MjIyMjIyMjIyMjIyMjIyMg==" - -// mockDecodedEncryptedAPIKey represents the encrypted API key after it has been decoded from base64 -const mockDecodedEncryptedAPIKey = "2222222222222222" - -// expectedDecryptedAPIKey represents the true value of the API key after decryption by KMS -const expectedDecryptedAPIKey = "1111111111111111" - -// mockFunctionName represents the name of the current function -var mockFunctionName = "my-Function" - -type mockKMSClientWithEncryptionContext struct { - kmsiface.KMSAPI -} - -func (mockKMSClientWithEncryptionContext) Decrypt(params *kms.DecryptInput) (*kms.DecryptOutput, error) { - encryptionContextPointer, exists := params.EncryptionContext[encryptionContextKey] - if !exists { - return nil, errors.New("InvalidCiphertextException") - } - if *encryptionContextPointer != mockFunctionName { - return nil, errors.New("InvalidCiphertextException") - } - if bytes.Equal(params.CiphertextBlob, []byte(mockDecodedEncryptedAPIKey)) { - return &kms.DecryptOutput{ - Plaintext: []byte(expectedDecryptedAPIKey), - }, nil - } - return nil, errors.New("KMS error") -} - -type mockKMSClientNoEncryptionContext struct { - kmsiface.KMSAPI -} - -func (mockKMSClientNoEncryptionContext) Decrypt(params *kms.DecryptInput) (*kms.DecryptOutput, error) { - if params.EncryptionContext[encryptionContextKey] != nil { - return nil, errors.New("InvalidCiphertextException") - } - if bytes.Equal(params.CiphertextBlob, []byte(mockDecodedEncryptedAPIKey)) { - return &kms.DecryptOutput{ - Plaintext: []byte(expectedDecryptedAPIKey), - }, nil - } - return nil, errors.New("KMS error") -} - -func TestDecryptKMSWithEncryptionContext(t *testing.T) { - os.Setenv(functionNameEnvVar, mockFunctionName) - defer os.Setenv(functionNameEnvVar, "") - - client := mockKMSClientWithEncryptionContext{} - result, _ := decryptKMS(client, mockEncryptedAPIKeyBase64) - assert.Equal(t, expectedDecryptedAPIKey, result) -} - -func TestDecryptKMSNoEncryptionContext(t *testing.T) { - client := mockKMSClientNoEncryptionContext{} - result, _ := decryptKMS(client, mockEncryptedAPIKeyBase64) - assert.Equal(t, expectedDecryptedAPIKey, result) -} From debabe1fbd3489ffb2e579f38c1e11de97b3ccaf Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Mon, 29 Aug 2022 16:19:50 -0400 Subject: [PATCH 2/7] update --- internal/metrics/kms_decrypter.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/internal/metrics/kms_decrypter.go b/internal/metrics/kms_decrypter.go index 3a8d10f1..fa4cdc5d 100644 --- a/internal/metrics/kms_decrypter.go +++ b/internal/metrics/kms_decrypter.go @@ -51,10 +51,6 @@ func (kd *kmsDecrypter) Decrypt(ciphertext string) (string, error) { return decryptKMS(kd.kmsClient, ciphertext) } -func defaultDecryptOpt(opt *kms.Options) { - opt.EndpointResolver = kms.NewDefaultEndpointResolver() -} - // decryptKMS decodes and deciphers the base64-encoded ciphertext given as a parameter using KMS. // For this to work properly, the Lambda function must have the appropriate IAM permissions. func decryptKMS(kmsClient *kms.Client, ciphertext string) (string, error) { @@ -72,7 +68,7 @@ func decryptKMS(kmsClient *kms.Client, ciphertext string) (string, error) { params := &kms.DecryptInput{ CiphertextBlob: decodedBytes, } - response, err := kmsClient.Decrypt(context.TODO(), params, defaultDecryptOpt) + response, err := kmsClient.Decrypt(context.TODO(), params) if err != nil { logger.Debug("Failed to decrypt ciphertext without encryption context, retrying with encryption context") @@ -83,7 +79,7 @@ func decryptKMS(kmsClient *kms.Client, ciphertext string) (string, error) { encryptionContextKey: functionName, }, } - response, err = kmsClient.Decrypt(context.TODO(), params, defaultDecryptOpt) + response, err = kmsClient.Decrypt(context.TODO(), params) if err != nil { return "", fmt.Errorf("failed to decrypt ciphertext with kms: %v", err) } From bc3c1061e8b5f8985cb9b180cc8ddf03c9aa2a5e Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Mon, 29 Aug 2022 20:37:36 -0400 Subject: [PATCH 3/7] debug error --- internal/metrics/kms_decrypter.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/metrics/kms_decrypter.go b/internal/metrics/kms_decrypter.go index fa4cdc5d..46d74630 100644 --- a/internal/metrics/kms_decrypter.go +++ b/internal/metrics/kms_decrypter.go @@ -72,6 +72,7 @@ func decryptKMS(kmsClient *kms.Client, ciphertext string) (string, error) { if err != nil { logger.Debug("Failed to decrypt ciphertext without encryption context, retrying with encryption context") + fmt.Printf("===ERROR===: %v", err) // Try with encryption context, in case API key was encrypted using the AWS Console params = &kms.DecryptInput{ CiphertextBlob: decodedBytes, From 481cb5747fadb54f8d837a429259ab3eeb64fdae Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Tue, 30 Aug 2022 10:43:54 -0400 Subject: [PATCH 4/7] clean up --- internal/metrics/kms_decrypter.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/metrics/kms_decrypter.go b/internal/metrics/kms_decrypter.go index 46d74630..3a2a9274 100644 --- a/internal/metrics/kms_decrypter.go +++ b/internal/metrics/kms_decrypter.go @@ -39,7 +39,7 @@ const encryptionContextKey string = "LambdaFunctionName" func MakeKMSDecrypter() Decrypter { cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { - logger.Error(fmt.Errorf("could not create a new aws-sdk config: %v", err)) + logger.Error(fmt.Errorf("could not create a new aws config: %v", err)) panic(err) } return &kmsDecrypter{ @@ -72,7 +72,6 @@ func decryptKMS(kmsClient *kms.Client, ciphertext string) (string, error) { if err != nil { logger.Debug("Failed to decrypt ciphertext without encryption context, retrying with encryption context") - fmt.Printf("===ERROR===: %v", err) // Try with encryption context, in case API key was encrypted using the AWS Console params = &kms.DecryptInput{ CiphertextBlob: decodedBytes, From b7fab89e39b7a667bee34bf91e524a497b667b92 Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Wed, 31 Aug 2022 13:09:38 -0400 Subject: [PATCH 5/7] tidy --- go.mod | 17 +++++++++++++---- go.sum | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index a1084cf9..eb0646f2 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,8 @@ go 1.17 require ( github.com/DataDog/datadog-go v4.8.3+incompatible github.com/aws/aws-lambda-go v1.29.0 - github.com/aws/aws-sdk-go v1.43.37 - github.com/aws/aws-sdk-go-v2 v1.16.11 + github.com/aws/aws-sdk-go-v2/config v1.17.1 + github.com/aws/aws-sdk-go-v2/service/kms v1.18.5 github.com/aws/aws-xray-sdk-go v1.6.0 github.com/cenkalti/backoff v2.2.1+incompatible github.com/sony/gobreaker v0.5.0 @@ -21,8 +21,17 @@ require ( github.com/DataDog/sketches-go v1.4.1 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect github.com/andybalholm/brotli v1.0.4 // indirect - github.com/aws/aws-sdk-go-v2/config v1.17.1 // indirect - github.com/aws/aws-sdk-go-v2/service/kms v1.18.5 // indirect + github.com/aws/aws-sdk-go v1.43.37 // indirect + github.com/aws/aws-sdk-go-v2 v1.16.11 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.12.14 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.12 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.18 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.12 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.19 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.12 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.11.17 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.16.13 // indirect + github.com/aws/smithy-go v1.12.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgraph-io/ristretto v0.1.0 // indirect diff --git a/go.sum b/go.sum index b0b30991..a73a8fd2 100644 --- a/go.sum +++ b/go.sum @@ -294,8 +294,8 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= From 2b1233fda57dba26ddebb53be24e90b0d00c7230 Mon Sep 17 00:00:00 2001 From: Rey Abolofia Date: Sat, 29 Oct 2022 00:17:42 -0700 Subject: [PATCH 6/7] Re-add unittest. --- internal/metrics/kms_decrypter.go | 6 +- internal/metrics/kms_decrypter_test.go | 76 ++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 internal/metrics/kms_decrypter_test.go diff --git a/internal/metrics/kms_decrypter.go b/internal/metrics/kms_decrypter.go index 3a2a9274..bcc218fd 100644 --- a/internal/metrics/kms_decrypter.go +++ b/internal/metrics/kms_decrypter.go @@ -27,6 +27,10 @@ type ( kmsDecrypter struct { kmsClient *kms.Client } + + clientDecrypter interface { + Decrypt(context.Context, *kms.DecryptInput, ...func(*kms.Options)) (*kms.DecryptOutput, error) + } ) // functionNameEnvVar is the environment variable that stores the Lambda function name @@ -53,7 +57,7 @@ func (kd *kmsDecrypter) Decrypt(ciphertext string) (string, error) { // decryptKMS decodes and deciphers the base64-encoded ciphertext given as a parameter using KMS. // For this to work properly, the Lambda function must have the appropriate IAM permissions. -func decryptKMS(kmsClient *kms.Client, ciphertext string) (string, error) { +func decryptKMS(kmsClient clientDecrypter, ciphertext string) (string, error) { decodedBytes, err := base64.StdEncoding.DecodeString(ciphertext) if err != nil { return "", fmt.Errorf("failed to encode cipher text to base64: %v", err) diff --git a/internal/metrics/kms_decrypter_test.go b/internal/metrics/kms_decrypter_test.go new file mode 100644 index 00000000..5621fbbc --- /dev/null +++ b/internal/metrics/kms_decrypter_test.go @@ -0,0 +1,76 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the Apache License Version 2.0. +// This product includes software developed at Datadog (https://www.datadoghq.com/). +// Copyright 2016-present Datadog, Inc. + +package metrics + +import ( + "bytes" + "context" + "errors" + "os" + "testing" + + "github.com/aws/aws-sdk-go-v2/service/kms" + "github.com/stretchr/testify/assert" +) + +// mockEncryptedAPIKeyBase64 represents an API key encrypted with KMS and encoded as a base64 string +const mockEncryptedAPIKeyBase64 = "MjIyMjIyMjIyMjIyMjIyMg==" + +// mockDecodedEncryptedAPIKey represents the encrypted API key after it has been decoded from base64 +const mockDecodedEncryptedAPIKey = "2222222222222222" + +// expectedDecryptedAPIKey represents the true value of the API key after decryption by KMS +const expectedDecryptedAPIKey = "1111111111111111" + +// mockFunctionName represents the name of the current function +var mockFunctionName = "my-Function" + +type mockKMSClientWithEncryptionContext struct{} + +func (mockKMSClientWithEncryptionContext) Decrypt(_ context.Context, params *kms.DecryptInput, _ ...func(*kms.Options)) (*kms.DecryptOutput, error) { + encryptionContextPointer, exists := params.EncryptionContext[encryptionContextKey] + if !exists { + return nil, errors.New("InvalidCiphertextException") + } + if encryptionContextPointer != mockFunctionName { + return nil, errors.New("InvalidCiphertextException") + } + if bytes.Equal(params.CiphertextBlob, []byte(mockDecodedEncryptedAPIKey)) { + return &kms.DecryptOutput{ + Plaintext: []byte(expectedDecryptedAPIKey), + }, nil + } + return nil, errors.New("KMS error") +} + +type mockKMSClientNoEncryptionContext struct{} + +func (mockKMSClientNoEncryptionContext) Decrypt(_ context.Context, params *kms.DecryptInput, _ ...func(*kms.Options)) (*kms.DecryptOutput, error) { + if params.EncryptionContext[encryptionContextKey] != "" { + return nil, errors.New("InvalidCiphertextException") + } + if bytes.Equal(params.CiphertextBlob, []byte(mockDecodedEncryptedAPIKey)) { + return &kms.DecryptOutput{ + Plaintext: []byte(expectedDecryptedAPIKey), + }, nil + } + return nil, errors.New("KMS error") +} + +func TestDecryptKMSWithEncryptionContext(t *testing.T) { + os.Setenv(functionNameEnvVar, mockFunctionName) + defer os.Setenv(functionNameEnvVar, "") + + client := mockKMSClientWithEncryptionContext{} + result, _ := decryptKMS(client, mockEncryptedAPIKeyBase64) + assert.Equal(t, expectedDecryptedAPIKey, result) +} + +func TestDecryptKMSNoEncryptionContext(t *testing.T) { + client := mockKMSClientNoEncryptionContext{} + result, _ := decryptKMS(client, mockEncryptedAPIKeyBase64) + assert.Equal(t, expectedDecryptedAPIKey, result) +} From 80e9e1e994d061fa06fc2d8a09cba90b38e0eb2d Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Mon, 31 Oct 2022 10:51:19 -0400 Subject: [PATCH 7/7] ctx todo -> background --- internal/metrics/kms_decrypter.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/metrics/kms_decrypter.go b/internal/metrics/kms_decrypter.go index bcc218fd..11c149d6 100644 --- a/internal/metrics/kms_decrypter.go +++ b/internal/metrics/kms_decrypter.go @@ -41,7 +41,7 @@ const encryptionContextKey string = "LambdaFunctionName" // MakeKMSDecrypter creates a new decrypter which uses the AWS KMS service to decrypt variables func MakeKMSDecrypter() Decrypter { - cfg, err := config.LoadDefaultConfig(context.TODO()) + cfg, err := config.LoadDefaultConfig(context.Background()) if err != nil { logger.Error(fmt.Errorf("could not create a new aws config: %v", err)) panic(err) @@ -72,7 +72,8 @@ func decryptKMS(kmsClient clientDecrypter, ciphertext string) (string, error) { params := &kms.DecryptInput{ CiphertextBlob: decodedBytes, } - response, err := kmsClient.Decrypt(context.TODO(), params) + ctx := context.Background() + response, err := kmsClient.Decrypt(ctx, params) if err != nil { logger.Debug("Failed to decrypt ciphertext without encryption context, retrying with encryption context") @@ -83,7 +84,7 @@ func decryptKMS(kmsClient clientDecrypter, ciphertext string) (string, error) { encryptionContextKey: functionName, }, } - response, err = kmsClient.Decrypt(context.TODO(), params) + response, err = kmsClient.Decrypt(ctx, params) if err != nil { return "", fmt.Errorf("failed to decrypt ciphertext with kms: %v", err) }