Skip to content

Commit 30abd3d

Browse files
committed
Add ability to use KMS encrypted endpoint
1 parent 7d924b1 commit 30abd3d

File tree

4 files changed

+134
-4
lines changed

4 files changed

+134
-4
lines changed

go.mod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ go 1.15
44

55
require (
66
github.com/aws/aws-sdk-go v1.35.23
7+
github.com/aws/aws-sdk-go-v2 v1.17.1
8+
github.com/aws/aws-sdk-go-v2/config v1.17.11
9+
github.com/aws/aws-sdk-go-v2/service/kms v1.18.16
710
github.com/google/uuid v1.1.2
811
github.com/sirupsen/logrus v1.7.0
12+
golang.org/x/sys v0.2.0 // indirect
913
)

go.sum

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,36 @@
11
github.com/aws/aws-sdk-go v1.35.23 h1:SCP0d0XvyJTDmfnHEQPvBaYi3kea1VNUo7uQmkVgFts=
22
github.com/aws/aws-sdk-go v1.35.23/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k=
3+
github.com/aws/aws-sdk-go-v2 v1.17.1 h1:02c72fDJr87N8RAC2s3Qu0YuvMRZKNZJ9F+lAehCazk=
4+
github.com/aws/aws-sdk-go-v2 v1.17.1/go.mod h1:JLnGeGONAyi2lWXI1p0PCIOIy333JMVK1U7Hf0aRFLw=
5+
github.com/aws/aws-sdk-go-v2/config v1.17.11 h1:9JQUKwRN8oUqeOFIrNaH6RSPmmcNk1+bQrDka/f/bPc=
6+
github.com/aws/aws-sdk-go-v2/config v1.17.11/go.mod h1:cw6HIEr0FaZQfcoyRWYZpMfv4qAH19hZFZ5mglwWo3g=
7+
github.com/aws/aws-sdk-go-v2/credentials v1.12.24 h1:yz4fhoMfgwymG0rU6q5eCydFhYNQxk9yrNjMA7L7xmg=
8+
github.com/aws/aws-sdk-go-v2/credentials v1.12.24/go.mod h1:prZpUfBu1KZLBLVX482Sq4DpDXGugAre08TPEc21GUg=
9+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19 h1:E3PXZSI3F2bzyj6XxUXdTIfvp425HHhwKsFvmzBwHgs=
10+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.12.19/go.mod h1:VihW95zQpeKQWVPGkwT+2+WJNQV8UXFfMTWdU6VErL8=
11+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25 h1:nBO/RFxeq/IS5G9Of+ZrgucRciie2qpLy++3UGZ+q2E=
12+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.25/go.mod h1:Zb29PYkf42vVYQY6pvSyJCJcFHlPIiY+YKdPtwnvMkY=
13+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19 h1:oRHDrwCTVT8ZXi4sr9Ld+EXk7N/KGssOr2ygNeojEhw=
14+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.19/go.mod h1:6Q0546uHDp421okhmmGfbxzq2hBqbXFNpi4k+Q1JnQA=
15+
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.26 h1:Mza+vlnZr+fPKFKRq/lKGVvM6B/8ZZmNdEopOwSQLms=
16+
github.com/aws/aws-sdk-go-v2/internal/ini v1.3.26/go.mod h1:Y2OJ+P+MC1u1VKnavT+PshiEuGPyh/7DqxoDNij4/bg=
17+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.19 h1:GE25AWCdNUPh9AOJzI9KIJnja7IwUc1WyUqz/JTyJ/I=
18+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.19/go.mod h1:02CP6iuYP+IVnBX5HULVdSAku/85eHB2Y9EsFhrkEwU=
19+
github.com/aws/aws-sdk-go-v2/service/kms v1.18.16 h1:KHzeOb0G5ZvaIOewRSs3iyHR5MeAKkIZ75tUJCO9ijg=
20+
github.com/aws/aws-sdk-go-v2/service/kms v1.18.16/go.mod h1:kZodDPTQjSH/qM6/OvyTfM5mms5JHB/EKYp5dhn/vI4=
21+
github.com/aws/aws-sdk-go-v2/service/sso v1.11.25 h1:GFZitO48N/7EsFDt8fMa5iYdmWqkUDDB3Eje6z3kbG0=
22+
github.com/aws/aws-sdk-go-v2/service/sso v1.11.25/go.mod h1:IARHuzTXmj1C0KS35vboR0FeJ89OkEy1M9mWbK2ifCI=
23+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8 h1:jcw6kKZrtNfBPJkaHrscDOZoe5gvi9wjudnxvozYFJo=
24+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.13.8/go.mod h1:er2JHN+kBY6FcMfcBBKNGCT3CarImmdFzishsqBmSRI=
25+
github.com/aws/aws-sdk-go-v2/service/sts v1.17.2 h1:tpwEMRdMf2UsplengAOnmSIRdvAxf75oUFR+blBr92I=
26+
github.com/aws/aws-sdk-go-v2/service/sts v1.17.2/go.mod h1:bXcN3koeVYiJcdDU89n3kCYILob7Y34AeLopUbZgLT4=
27+
github.com/aws/smithy-go v1.13.4 h1:/RN2z1txIJWeXeOkzX+Hk/4Uuvv7dWtCjbmVJcrskyk=
28+
github.com/aws/smithy-go v1.13.4/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
329
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
430
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
531
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
32+
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
33+
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
634
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
735
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
836
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
@@ -21,8 +49,9 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
2149
golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI=
2250
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
2351
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
24-
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
2552
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
53+
golang.org/x/sys v0.2.0 h1:ljd4t30dBnAvMZaQCevtY0xLLD0A+bRZXbgLMLU1F/A=
54+
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
2655
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
2756
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
2857
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

lambda-extensions/config/config.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
// LambdaExtensionConfig config for storing all configurable parameters
1818
type LambdaExtensionConfig struct {
1919
SumoHTTPEndpoint string
20+
KMSKeyId string
2021
EnableFailover bool
2122
S3BucketName string
2223
S3BucketRegion string
@@ -36,6 +37,7 @@ type LambdaExtensionConfig struct {
3637
SourceCategoryOverride string
3738
EnhanceJsonLogs bool
3839
EnableSpanDrops bool
40+
KmsCacheSeconds int64
3941
}
4042

4143
var defaultLogTypes = []string{"platform", "function"}
@@ -46,6 +48,7 @@ func GetConfig() (*LambdaExtensionConfig, error) {
4648

4749
config := &LambdaExtensionConfig{
4850
SumoHTTPEndpoint: os.Getenv("SUMO_HTTP_ENDPOINT"),
51+
KMSKeyId: os.Getenv("KMS_KEY_ID"),
4952
S3BucketName: os.Getenv("SUMO_S3_BUCKET_NAME"),
5053
S3BucketRegion: os.Getenv("SUMO_S3_BUCKET_REGION"),
5154
AWSLambdaRuntimeAPI: os.Getenv("AWS_LAMBDA_RUNTIME_API"),
@@ -78,40 +81,54 @@ func (cfg *LambdaExtensionConfig) setDefaults() {
7881
logTypes := os.Getenv("SUMO_LOG_TYPES")
7982
enhanceJsonLogs := os.Getenv("SUMO_ENHANCE_JSON_LOGS")
8083
enableSpanDrops := os.Getenv("SUMO_SPAN_DROP")
84+
kmsCacheSeconds := os.Getenv("KMS_CACHE_SECONDS")
8185

8286
if numRetry == "" {
8387
cfg.NumRetry = 3
8488
}
89+
8590
if logLevel == "" {
8691
cfg.LogLevel = logrus.InfoLevel
8792
}
93+
8894
if maxDataQueueLength == "" {
8995
cfg.MaxDataQueueLength = 20
9096
}
97+
9198
if maxConcurrentRequests == "" {
9299
cfg.MaxConcurrentRequests = 3
93100
}
101+
94102
if enableFailover == "" {
95103
cfg.EnableFailover = false
96104
}
105+
97106
if cfg.AWSLambdaRuntimeAPI == "" {
98107
cfg.AWSLambdaRuntimeAPI = "127.0.0.1:9001"
99108
}
109+
100110
if logTypes == "" {
101111
cfg.LogTypes = defaultLogTypes
102112
} else {
103113
cfg.LogTypes = strings.Split(logTypes, ",")
104114
}
115+
105116
if retrySleepTime == "" {
106117
cfg.RetrySleepTime = 300 * time.Millisecond
107118
}
119+
108120
if enhanceJsonLogs == "" {
109121
cfg.EnhanceJsonLogs = true
110122
}
123+
111124
if enableSpanDrops == "" {
112125
// by default, spans will not be dropped if user did not configure the env variable
113126
cfg.EnableSpanDrops = false
114127
}
128+
129+
if kmsCacheSeconds == "" {
130+
cfg.KmsCacheSeconds = 5
131+
}
115132
}
116133

117134
func (cfg *LambdaExtensionConfig) validateConfig() error {
@@ -123,6 +140,7 @@ func (cfg *LambdaExtensionConfig) validateConfig() error {
123140
retrySleepTime := os.Getenv("SUMO_RETRY_SLEEP_TIME_MS")
124141
enhanceJsonLogs := os.Getenv("SUMO_ENHANCE_JSON_LOGS")
125142
enableSpanDrops := os.Getenv("SUMO_SPAN_DROP")
143+
kmsCacheSeconds := os.Getenv("KMS_CACHE_SECONDS")
126144

127145
var allErrors []string
128146
var err error
@@ -132,7 +150,7 @@ func (cfg *LambdaExtensionConfig) validateConfig() error {
132150
}
133151

134152
// Todo test url valid
135-
if cfg.SumoHTTPEndpoint != "" {
153+
if cfg.SumoHTTPEndpoint != "" && cfg.KMSKeyId == "" {
136154
_, err = url.ParseRequestURI(cfg.SumoHTTPEndpoint)
137155
if err != nil {
138156
allErrors = append(allErrors, "SUMO_HTTP_ENDPOINT is not Valid")
@@ -214,6 +232,13 @@ func (cfg *LambdaExtensionConfig) validateConfig() error {
214232
}
215233
}
216234

235+
if kmsCacheSeconds != "" {
236+
cfg.KmsCacheSeconds, err = strconv.ParseInt(kmsCacheSeconds, 10, 32)
237+
if err != nil {
238+
allErrors = append(allErrors, fmt.Sprintf("Unable to parse KMS_CACHE_SECONDS: %v", err))
239+
}
240+
}
241+
217242
// test valid log format type
218243
for _, logType := range cfg.LogTypes {
219244
if !utils.StringInSlice(strings.TrimSpace(logType), validLogTypes) {

lambda-extensions/sumoclient/sumoclient.go

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package sumoclient
33
import (
44
"bytes"
55
"context"
6+
b64 "encoding/base64"
67
"encoding/binary"
78
"encoding/json"
89
"fmt"
@@ -14,11 +15,18 @@ import (
1415

1516
"github.com/SumoLogic/sumologic-lambda-extensions/lambda-extensions/config"
1617

18+
"github.com/aws/aws-sdk-go-v2/aws"
19+
awsConfig "github.com/aws/aws-sdk-go-v2/config"
20+
"github.com/aws/aws-sdk-go-v2/service/kms"
21+
1722
uuid "github.com/google/uuid"
1823
"github.com/sirupsen/logrus"
1924
)
2025

21-
var isColdStart = true
26+
var isColdStart bool = true
27+
28+
var decryptedSumoHttpEndpoint string
29+
var kmsEndpointCacheTime = time.Now().Add(-5 * time.Minute)
2230

2331
// LogSender interface which needs to be implemented to send logs
2432
type LogSender interface {
@@ -37,6 +45,12 @@ type sumoLogicClient struct {
3745
// It is assumed that logs will be array of json objects and all channel payloads satisfy this format
3846
type responseBody []map[string]interface{}
3947

48+
type KMSDecryptAPI interface {
49+
Decrypt(ctx context.Context,
50+
params *kms.DecryptInput,
51+
optFns ...func(*kms.Options)) (*kms.DecryptOutput, error)
52+
}
53+
4054
// NewLogSenderClient returns interface pointing to the concrete version of LogSender client
4155
func NewLogSenderClient(logger *logrus.Entry, cfg *config.LambdaExtensionConfig) LogSender {
4256
// setting the cold start variable here since this function is called
@@ -56,8 +70,12 @@ func (s *sumoLogicClient) getColdStart() bool {
5670
}
5771

5872
func (s *sumoLogicClient) makeRequest(ctx context.Context, buf *bytes.Buffer) (*http.Response, error) {
73+
endpoint, err := s.getHttpEndpoint()
74+
if err != nil {
75+
err = fmt.Errorf("Failed to get SUMO HTTP Endpoint", err)
76+
}
5977

60-
request, err := http.NewRequestWithContext(ctx, "POST", s.config.SumoHTTPEndpoint, buf)
78+
request, err := http.NewRequestWithContext(ctx, "POST", endpoint, buf)
6179
if err != nil {
6280
err = fmt.Errorf("http.NewRequest() error: %v", err)
6381
return nil, err
@@ -74,6 +92,56 @@ func (s *sumoLogicClient) makeRequest(ctx context.Context, buf *bytes.Buffer) (*
7492
return response, err
7593
}
7694

95+
// Use cached KMS decrypted endpoint, refresh the cached endpoint, or return unencrypted endpoint
96+
func (s *sumoLogicClient) getHttpEndpoint() (string, error) {
97+
if s.config.KMSKeyId == "" {
98+
return s.config.SumoHTTPEndpoint, nil
99+
}
100+
101+
if s.config.KMSKeyId != "" && time.Until(kmsEndpointCacheTime) > 0 {
102+
return decryptedSumoHttpEndpoint, nil
103+
}
104+
105+
if s.config.KMSKeyId != "" && (time.Until(kmsEndpointCacheTime) <= 0 || s.config.KmsCacheSeconds == 0) {
106+
107+
cfg, err := awsConfig.LoadDefaultConfig(context.TODO())
108+
if err != nil {
109+
fmt.Errorf("Configuration error in aws client,", err)
110+
}
111+
112+
client := kms.NewFromConfig(cfg)
113+
114+
blob, err := b64.StdEncoding.DecodeString(s.config.SumoHTTPEndpoint)
115+
if err != nil {
116+
fmt.Errorf("Error converting string to blob,", err)
117+
}
118+
119+
input := &kms.DecryptInput{
120+
CiphertextBlob: blob,
121+
KeyId: aws.String(s.config.KMSKeyId),
122+
}
123+
124+
result, err := DecodeData(context.TODO(), client, input)
125+
126+
if err != nil {
127+
fmt.Errorf("Got error decrypting data: ", err)
128+
return "", err
129+
}
130+
131+
// Set the decrypted endpoint var as decrypted string to use as cache
132+
decryptedSumoHttpEndpoint := string(result.Plaintext)
133+
134+
// Set new cache time
135+
kmsEndpointCacheTime = time.Now()
136+
137+
return decryptedSumoHttpEndpoint, nil
138+
}
139+
140+
err := fmt.Errorf("Failed to select a valid Sumo HTTP endpoint")
141+
142+
return "", err
143+
}
144+
77145
// getS3KeyName returns the key by combining function name, version, date and uuid(version 1)
78146
func (s *sumoLogicClient) getS3KeyName() (string, error) {
79147
currentTime := time.Now()
@@ -414,3 +482,7 @@ func (s *sumoLogicClient) postToSumo(ctx context.Context, logStringToSend *strin
414482

415483
return nil
416484
}
485+
486+
func DecodeData(c context.Context, api KMSDecryptAPI, input *kms.DecryptInput) (*kms.DecryptOutput, error) {
487+
return api.Decrypt(c, input)
488+
}

0 commit comments

Comments
 (0)