From 47d5b90e4420aa96f113a07f7909d3f07c83f9a0 Mon Sep 17 00:00:00 2001 From: Yaron Schneider Date: Fri, 23 Sep 2022 15:35:15 -0700 Subject: [PATCH] Add presigning to aws s3 binding (#2121) * add presigning to aws s3 binding Signed-off-by: yaron2 * fix error shadowing Signed-off-by: yaron2 * typo and error consistency Signed-off-by: yaron2 Signed-off-by: yaron2 --- bindings/aws/s3/s3.go | 44 +++++++++++++++++++++++++++++++------- bindings/aws/s3/s3_test.go | 2 ++ 2 files changed, 38 insertions(+), 8 deletions(-) diff --git a/bindings/aws/s3/s3.go b/bindings/aws/s3/s3.go index 2df93fad6..1fde94747 100644 --- a/bindings/aws/s3/s3.go +++ b/bindings/aws/s3/s3.go @@ -24,6 +24,7 @@ import ( "net/http" "os" "strconv" + "time" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" @@ -41,6 +42,7 @@ const ( metadataDecodeBase64 = "decodeBase64" metadataEncodeBase64 = "encodeBase64" metadataFilePath = "filePath" + metadataPresignTTL = "presignTTL" metadataKey = "key" @@ -69,11 +71,13 @@ type s3Metadata struct { DisableSSL bool `json:"disableSSL,string"` InsecureSSL bool `json:"insecureSSL,string"` FilePath string + PresignTTL string } type createResponse struct { - Location string `json:"location"` - VersionID *string `json:"versionID"` + Location string `json:"location"` + VersionID *string `json:"versionID"` + PresignURL string `json:"presignURL,omitempty"` } type listPayload struct { @@ -140,14 +144,14 @@ func (s *AWSS3) Operations() []bindings.OperationKind { func (s *AWSS3) create(ctx context.Context, req *bindings.InvokeRequest) (*bindings.InvokeResponse, error) { metadata, err := s.metadata.mergeWithRequestMetadata(req) if err != nil { - return nil, fmt.Errorf("s3 binding error. error merge metadata : %w", err) + return nil, fmt.Errorf("s3 binding error: error merging metadata: %w", err) } var key string if val, ok := req.Metadata[metadataKey]; ok && val != "" { key = val } else { key = uuid.New().String() - s.logger.Debugf("key not found. generating key %s", key) + s.logger.Debugf("s3 binding: key not found. generating key %s", key) } d, err := strconv.Unquote(string(req.Data)) @@ -175,15 +179,35 @@ func (s *AWSS3) create(ctx context.Context, req *bindings.InvokeRequest) (*bindi Body: r, }) if err != nil { - return nil, fmt.Errorf("s3 binding error. Uploading: %w", err) + return nil, fmt.Errorf("s3 binding error: Uploading: %w", err) + } + + var presignURL string + if metadata.PresignTTL != "" { + d, parseErr := time.ParseDuration(metadata.PresignTTL) + if parseErr != nil { + return nil, fmt.Errorf("s3 binding error: Cannot parse duration %s: %s", metadata.PresignTTL, parseErr) + } + + req, _ := s.s3Client.GetObjectRequest(&s3.GetObjectInput{ + Bucket: aws.String(metadata.Bucket), + Key: aws.String(key), + }) + url, signErr := req.Presign(d) + if signErr != nil { + return nil, fmt.Errorf("s3 binding error: Failed to presign URL: %s", signErr) + } + + presignURL = url } jsonResponse, err := json.Marshal(createResponse{ - Location: resultUpload.Location, - VersionID: resultUpload.VersionID, + Location: resultUpload.Location, + VersionID: resultUpload.VersionID, + PresignURL: presignURL, }) if err != nil { - return nil, fmt.Errorf("s3 binding error. Error marshalling create response: %w", err) + return nil, fmt.Errorf("s3 binding error: Error marshalling create response: %w", err) } return &bindings.InvokeResponse{ @@ -337,5 +361,9 @@ func (metadata s3Metadata) mergeWithRequestMetadata(req *bindings.InvokeRequest) merged.FilePath = val } + if val, ok := req.Metadata[metadataPresignTTL]; ok && val != "" { + merged.PresignTTL = val + } + return merged, nil } diff --git a/bindings/aws/s3/s3_test.go b/bindings/aws/s3/s3_test.go index ba4abb17f..8c8c31fb1 100644 --- a/bindings/aws/s3/s3_test.go +++ b/bindings/aws/s3/s3_test.go @@ -66,6 +66,7 @@ func TestMergeWithRequestMetadata(t *testing.T) { "decodeBase64": "yes", "encodeBase64": "false", "filePath": "/usr/vader.darth", + "presignTTL": "15s", } mergedMeta, err := meta.mergeWithRequestMetadata(&request) @@ -83,6 +84,7 @@ func TestMergeWithRequestMetadata(t *testing.T) { assert.Equal(t, true, mergedMeta.DecodeBase64) assert.Equal(t, false, mergedMeta.EncodeBase64) assert.Equal(t, "/usr/vader.darth", mergedMeta.FilePath) + assert.Equal(t, "15s", mergedMeta.PresignTTL) }) t.Run("Has invalid merged metadata decodeBase64", func(t *testing.T) {