diff options
author | vitalyisaev <vitalyisaev@ydb.tech> | 2023-12-12 21:55:07 +0300 |
---|---|---|
committer | vitalyisaev <vitalyisaev@ydb.tech> | 2023-12-12 22:25:10 +0300 |
commit | 4967f99474a4040ba150eb04995de06342252718 (patch) | |
tree | c9c118836513a8fab6e9fcfb25be5d404338bca7 /vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared | |
parent | 2ce9cccb9b0bdd4cd7a3491dc5cbf8687cda51de (diff) | |
download | ydb-4967f99474a4040ba150eb04995de06342252718.tar.gz |
YQ Connector: prepare code base for S3 integration
1. Кодовая база Коннектора переписана с помощью Go дженериков так, чтобы добавление нового источника данных (в частности S3 + csv) максимально переиспользовало имеющийся код (чтобы сохранялась логика нарезания на блоки данных, учёт трафика и пр.)
2. API Connector расширено для работы с S3, но ещё пока не протестировано.
Diffstat (limited to 'vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared')
28 files changed, 1966 insertions, 0 deletions
diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/accesspoint_arn.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/accesspoint_arn.go new file mode 100644 index 0000000000..ec290b2135 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/accesspoint_arn.go @@ -0,0 +1,53 @@ +package arn + +import ( + "strings" + + "github.com/aws/aws-sdk-go-v2/aws/arn" +) + +// AccessPointARN provides representation +type AccessPointARN struct { + arn.ARN + AccessPointName string +} + +// GetARN returns the base ARN for the Access Point resource +func (a AccessPointARN) GetARN() arn.ARN { + return a.ARN +} + +// ParseAccessPointResource attempts to parse the ARN's resource as an +// AccessPoint resource. +// +// Supported Access point resource format: +// - Access point format: arn:{partition}:s3:{region}:{accountId}:accesspoint/{accesspointName} +// - example: arn:aws:s3:us-west-2:012345678901:accesspoint/myaccesspoint +func ParseAccessPointResource(a arn.ARN, resParts []string) (AccessPointARN, error) { + if isFIPS(a.Region) { + return AccessPointARN{}, InvalidARNError{ARN: a, Reason: "FIPS region not allowed in ARN"} + } + if len(a.AccountID) == 0 { + return AccessPointARN{}, InvalidARNError{ARN: a, Reason: "account-id not set"} + } + if len(resParts) == 0 { + return AccessPointARN{}, InvalidARNError{ARN: a, Reason: "resource-id not set"} + } + if len(resParts) > 1 { + return AccessPointARN{}, InvalidARNError{ARN: a, Reason: "sub resource not supported"} + } + + resID := resParts[0] + if len(strings.TrimSpace(resID)) == 0 { + return AccessPointARN{}, InvalidARNError{ARN: a, Reason: "resource-id not set"} + } + + return AccessPointARN{ + ARN: a, + AccessPointName: resID, + }, nil +} + +func isFIPS(region string) bool { + return strings.HasPrefix(region, "fips-") || strings.HasSuffix(region, "-fips") +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/accesspoint_arn_test.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/accesspoint_arn_test.go new file mode 100644 index 0000000000..51221b20f3 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/accesspoint_arn_test.go @@ -0,0 +1,118 @@ +package arn + +import ( + "reflect" + "strings" + "testing" + + "github.com/aws/aws-sdk-go-v2/aws/arn" +) + +func TestParseAccessPointResource(t *testing.T) { + cases := map[string]struct { + ARN arn.ARN + ExpectErr string + ExpectARN AccessPointARN + }{ + "account-id not set": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3", + Region: "us-west-2", + Resource: "accesspoint/myendpoint", + }, + ExpectErr: "account-id not set", + }, + "resource-id not set": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "accesspoint", + }, + ExpectErr: "resource-id not set", + }, + "resource-id empty": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "accesspoint:", + }, + ExpectErr: "resource-id not set", + }, + "resource not supported": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "accesspoint/endpoint/object/key", + }, + ExpectErr: "sub resource not supported", + }, + "valid resource-id": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "accesspoint/endpoint", + }, + ExpectARN: AccessPointARN{ + ARN: arn.ARN{ + Partition: "aws", + Service: "s3", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "accesspoint/endpoint", + }, + AccessPointName: "endpoint", + }, + }, + "invalid FIPS pseudo region in ARN (prefix)": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3", + Region: "fips-us-west-2", + AccountID: "012345678901", + Resource: "accesspoint/endpoint", + }, + ExpectErr: "FIPS region not allowed in ARN", + }, + "invalid FIPS pseudo region in ARN (suffix)": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3", + Region: "us-west-2-fips", + AccountID: "012345678901", + Resource: "accesspoint/endpoint", + }, + ExpectErr: "FIPS region not allowed in ARN", + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + resParts := SplitResource(c.ARN.Resource) + a, err := ParseAccessPointResource(c.ARN, resParts[1:]) + + if len(c.ExpectErr) == 0 && err != nil { + t.Fatalf("expect no error but got %v", err) + } else if len(c.ExpectErr) != 0 && err == nil { + t.Fatalf("expect error %q, but got nil", c.ExpectErr) + } else if len(c.ExpectErr) != 0 && err != nil { + if e, a := c.ExpectErr, err.Error(); !strings.Contains(a, e) { + t.Fatalf("expect error %q, got %q", e, a) + } + return + } + + if e, a := c.ExpectARN, a; !reflect.DeepEqual(e, a) { + t.Errorf("expect %v, got %v", e, a) + } + }) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/arn.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/arn.go new file mode 100644 index 0000000000..06e1a3addd --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/arn.go @@ -0,0 +1,85 @@ +package arn + +import ( + "fmt" + "strings" + + "github.com/aws/aws-sdk-go-v2/aws/arn" +) + +var supportedServiceARN = []string{ + "s3", + "s3-outposts", + "s3-object-lambda", +} + +func isSupportedServiceARN(service string) bool { + for _, name := range supportedServiceARN { + if name == service { + return true + } + } + return false +} + +// Resource provides the interfaces abstracting ARNs of specific resource +// types. +type Resource interface { + GetARN() arn.ARN + String() string +} + +// ResourceParser provides the function for parsing an ARN's resource +// component into a typed resource. +type ResourceParser func(arn.ARN) (Resource, error) + +// ParseResource parses an AWS ARN into a typed resource for the S3 API. +func ParseResource(a arn.ARN, resParser ResourceParser) (resARN Resource, err error) { + if len(a.Partition) == 0 { + return nil, InvalidARNError{ARN: a, Reason: "partition not set"} + } + + if !isSupportedServiceARN(a.Service) { + return nil, InvalidARNError{ARN: a, Reason: "service is not supported"} + } + + if len(a.Resource) == 0 { + return nil, InvalidARNError{ARN: a, Reason: "resource not set"} + } + + return resParser(a) +} + +// SplitResource splits the resource components by the ARN resource delimiters. +func SplitResource(v string) []string { + var parts []string + var offset int + + for offset <= len(v) { + idx := strings.IndexAny(v[offset:], "/:") + if idx < 0 { + parts = append(parts, v[offset:]) + break + } + parts = append(parts, v[offset:idx+offset]) + offset += idx + 1 + } + + return parts +} + +// IsARN returns whether the given string is an ARN +func IsARN(s string) bool { + return arn.IsARN(s) +} + +// InvalidARNError provides the error for an invalid ARN error. +type InvalidARNError struct { + ARN arn.ARN + Reason string +} + +// Error returns a string denoting the occurred InvalidARNError +func (e InvalidARNError) Error() string { + return fmt.Sprintf("invalid Amazon %s ARN, %s, %s", e.ARN.Service, e.Reason, e.ARN.String()) +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/arn_member.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/arn_member.go new file mode 100644 index 0000000000..9a3258e15a --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/arn_member.go @@ -0,0 +1,32 @@ +package arn + +import "fmt" + +// arnable is implemented by the relevant S3/S3Control +// operations which have members that may need ARN +// processing. +type arnable interface { + SetARNMember(string) error + GetARNMember() (*string, bool) +} + +// GetARNField would be called during middleware execution +// to retrieve a member value that is an ARN in need of +// processing. +func GetARNField(input interface{}) (*string, bool) { + v, ok := input.(arnable) + if !ok { + return nil, false + } + return v.GetARNMember() +} + +// SetARNField would called during middleware exeuction +// to set a member value that required ARN processing. +func SetARNField(input interface{}, v string) error { + params, ok := input.(arnable) + if !ok { + return fmt.Errorf("Params does not contain arn field member") + } + return params.SetARNMember(v) +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/arn_test.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/arn_test.go new file mode 100644 index 0000000000..db7beaaf8f --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/arn_test.go @@ -0,0 +1,170 @@ +package arn + +import ( + "reflect" + "strings" + "testing" + + "github.com/aws/aws-sdk-go-v2/aws/arn" +) + +func TestParseResource(t *testing.T) { + cases := map[string]struct { + Input string + MappedResources map[string]func(arn.ARN, []string) (Resource, error) + Expect Resource + ExpectErr string + }{ + "Empty ARN": { + Input: "", + ExpectErr: "arn: invalid prefix", + }, + "No Partition": { + Input: "arn::sqs:us-west-2:012345678901:accesspoint", + ExpectErr: "partition not set", + }, + "Not S3 ARN": { + Input: "arn:aws:sqs:us-west-2:012345678901:accesspoint", + ExpectErr: "service is not supported", + }, + "No Resource": { + Input: "arn:aws:s3:us-west-2:012345678901:", + ExpectErr: "resource not set", + }, + "Unknown Resource Type": { + Input: "arn:aws:s3:us-west-2:012345678901:myresource", + ExpectErr: "unknown resource type", + }, + "Unknown BucketARN Resource Type": { + Input: "arn:aws:s3:us-west-2:012345678901:bucket_name:mybucket", + ExpectErr: "unknown resource type", + }, + "Unknown Resource Type with Resource and Sub-Resource": { + Input: "arn:aws:s3:us-west-2:012345678901:somethingnew:myresource/subresource", + ExpectErr: "unknown resource type", + }, + "Access Point with sub resource": { + Input: "arn:aws:s3:us-west-2:012345678901:accesspoint:myresource/subresource", + MappedResources: map[string]func(arn.ARN, []string) (Resource, error){ + "accesspoint": func(a arn.ARN, parts []string) (Resource, error) { + return ParseAccessPointResource(a, parts) + }, + }, + ExpectErr: "resource not supported", + }, + "AccessPoint Resource Type": { + Input: "arn:aws:s3:us-west-2:012345678901:accesspoint:myendpoint", + MappedResources: map[string]func(arn.ARN, []string) (Resource, error){ + "accesspoint": func(a arn.ARN, parts []string) (Resource, error) { + return ParseAccessPointResource(a, parts) + }, + }, + Expect: AccessPointARN{ + ARN: arn.ARN{ + Partition: "aws", + Service: "s3", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "accesspoint:myendpoint", + }, + AccessPointName: "myendpoint", + }, + }, + "AccessPoint Resource Type With Path Syntax": { + Input: "arn:aws:s3:us-west-2:012345678901:accesspoint/myendpoint", + MappedResources: map[string]func(arn.ARN, []string) (Resource, error){ + "accesspoint": func(a arn.ARN, parts []string) (Resource, error) { + return ParseAccessPointResource(a, parts) + }, + }, + Expect: AccessPointARN{ + ARN: arn.ARN{ + Partition: "aws", + Service: "s3", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "accesspoint/myendpoint", + }, + AccessPointName: "myendpoint", + }, + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + var parsed Resource + arn, err := arn.Parse(c.Input) + if err == nil { + parsed, err = ParseResource(arn, mappedResourceParser(c.MappedResources)) + } + + if len(c.ExpectErr) == 0 && err != nil { + t.Fatalf("expect no error but got %v", err) + } else if len(c.ExpectErr) != 0 && err == nil { + t.Fatalf("expect error but got nil") + } else if len(c.ExpectErr) != 0 && err != nil { + if e, a := c.ExpectErr, err.Error(); !strings.Contains(a, e) { + t.Fatalf("expect error %q, got %q", e, a) + } + return + } + + if e, a := c.Expect, parsed; !reflect.DeepEqual(e, a) { + t.Errorf("Expect %v, got %v", e, a) + } + }) + } +} + +func mappedResourceParser(kinds map[string]func(arn.ARN, []string) (Resource, error)) ResourceParser { + return func(a arn.ARN) (Resource, error) { + parts := SplitResource(a.Resource) + + fn, ok := kinds[parts[0]] + if !ok { + return nil, InvalidARNError{ARN: a, Reason: "unknown resource type"} + } + return fn(a, parts[1:]) + } +} + +func TestSplitResource(t *testing.T) { + cases := []struct { + Input string + Expect []string + }{ + { + Input: "accesspoint:myendpoint", + Expect: []string{"accesspoint", "myendpoint"}, + }, + { + Input: "accesspoint/myendpoint", + Expect: []string{"accesspoint", "myendpoint"}, + }, + { + Input: "accesspoint", + Expect: []string{"accesspoint"}, + }, + { + Input: "accesspoint:", + Expect: []string{"accesspoint", ""}, + }, + { + Input: "accesspoint: ", + Expect: []string{"accesspoint", " "}, + }, + { + Input: "accesspoint:endpoint/object/key", + Expect: []string{"accesspoint", "endpoint", "object", "key"}, + }, + } + + for _, c := range cases { + t.Run(c.Input, func(t *testing.T) { + parts := SplitResource(c.Input) + if e, a := c.Expect, parts; !reflect.DeepEqual(e, a) { + t.Errorf("expect %v, got %v", e, a) + } + }) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/gotest/ya.make b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/gotest/ya.make new file mode 100644 index 0000000000..0db9a0c5c8 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/gotest/ya.make @@ -0,0 +1,5 @@ +GO_TEST_FOR(vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn) + +LICENSE(Apache-2.0) + +END() diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/outpost_arn.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/outpost_arn.go new file mode 100644 index 0000000000..e06a302857 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/outpost_arn.go @@ -0,0 +1,128 @@ +package arn + +import ( + "strings" + + "github.com/aws/aws-sdk-go-v2/aws/arn" +) + +// OutpostARN interface that should be satisfied by outpost ARNs +type OutpostARN interface { + Resource + GetOutpostID() string +} + +// ParseOutpostARNResource will parse a provided ARNs resource using the appropriate ARN format +// and return a specific OutpostARN type +// +// Currently supported outpost ARN formats: +// * Outpost AccessPoint ARN format: +// - ARN format: arn:{partition}:s3-outposts:{region}:{accountId}:outpost/{outpostId}/accesspoint/{accesspointName} +// - example: arn:aws:s3-outposts:us-west-2:012345678901:outpost/op-1234567890123456/accesspoint/myaccesspoint +// +// * Outpost Bucket ARN format: +// - ARN format: arn:{partition}:s3-outposts:{region}:{accountId}:outpost/{outpostId}/bucket/{bucketName} +// - example: arn:aws:s3-outposts:us-west-2:012345678901:outpost/op-1234567890123456/bucket/mybucket +// +// Other outpost ARN formats may be supported and added in the future. +func ParseOutpostARNResource(a arn.ARN, resParts []string) (OutpostARN, error) { + if len(a.Region) == 0 { + return nil, InvalidARNError{ARN: a, Reason: "region not set"} + } + + if isFIPS(a.Region) { + return nil, InvalidARNError{ARN: a, Reason: "FIPS region not allowed in ARN"} + } + + if len(a.AccountID) == 0 { + return nil, InvalidARNError{ARN: a, Reason: "account-id not set"} + } + + // verify if outpost id is present and valid + if len(resParts) == 0 || len(strings.TrimSpace(resParts[0])) == 0 { + return nil, InvalidARNError{ARN: a, Reason: "outpost resource-id not set"} + } + + // verify possible resource type exists + if len(resParts) < 3 { + return nil, InvalidARNError{ + ARN: a, Reason: "incomplete outpost resource type. Expected bucket or access-point resource to be present", + } + } + + // Since we know this is a OutpostARN fetch outpostID + outpostID := strings.TrimSpace(resParts[0]) + + switch resParts[1] { + case "accesspoint": + accesspointARN, err := ParseAccessPointResource(a, resParts[2:]) + if err != nil { + return OutpostAccessPointARN{}, err + } + return OutpostAccessPointARN{ + AccessPointARN: accesspointARN, + OutpostID: outpostID, + }, nil + + case "bucket": + bucketName, err := parseBucketResource(a, resParts[2:]) + if err != nil { + return nil, err + } + return OutpostBucketARN{ + ARN: a, + BucketName: bucketName, + OutpostID: outpostID, + }, nil + + default: + return nil, InvalidARNError{ARN: a, Reason: "unknown resource set for outpost ARN"} + } +} + +// OutpostAccessPointARN represents outpost access point ARN. +type OutpostAccessPointARN struct { + AccessPointARN + OutpostID string +} + +// GetOutpostID returns the outpost id of outpost access point arn +func (o OutpostAccessPointARN) GetOutpostID() string { + return o.OutpostID +} + +// OutpostBucketARN represents the outpost bucket ARN. +type OutpostBucketARN struct { + arn.ARN + BucketName string + OutpostID string +} + +// GetOutpostID returns the outpost id of outpost bucket arn +func (o OutpostBucketARN) GetOutpostID() string { + return o.OutpostID +} + +// GetARN retrives the base ARN from outpost bucket ARN resource +func (o OutpostBucketARN) GetARN() arn.ARN { + return o.ARN +} + +// parseBucketResource attempts to parse the ARN's bucket resource and retrieve the +// bucket resource id. +// +// parseBucketResource only parses the bucket resource id. +func parseBucketResource(a arn.ARN, resParts []string) (bucketName string, err error) { + if len(resParts) == 0 { + return bucketName, InvalidARNError{ARN: a, Reason: "bucket resource-id not set"} + } + if len(resParts) > 1 { + return bucketName, InvalidARNError{ARN: a, Reason: "sub resource not supported"} + } + + bucketName = strings.TrimSpace(resParts[0]) + if len(bucketName) == 0 { + return bucketName, InvalidARNError{ARN: a, Reason: "bucket resource-id not set"} + } + return bucketName, err +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/outpost_arn_test.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/outpost_arn_test.go new file mode 100644 index 0000000000..b21d4bd5d7 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/outpost_arn_test.go @@ -0,0 +1,291 @@ +package arn + +import ( + "reflect" + "strings" + "testing" + + "github.com/aws/aws-sdk-go-v2/aws/arn" +) + +func TestParseOutpostAccessPointARNResource(t *testing.T) { + cases := map[string]struct { + ARN arn.ARN + ExpectErr string + ExpectARN OutpostAccessPointARN + }{ + "region not set": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + AccountID: "012345678901", + Resource: "outpost/myoutpost/accesspoint/myendpoint", + }, + ExpectErr: "region not set", + }, + "account-id not set": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + Region: "us-west-2", + Resource: "outpost/myoutpost/accesspoint/myendpoint", + }, + ExpectErr: "account-id not set", + }, + "resource-id not set": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "myoutpost", + }, + ExpectErr: "resource-id not set", + }, + "resource-id empty": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "outpost:", + }, + ExpectErr: "resource-id not set", + }, + "resource not supported": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "outpost/myoutpost/accesspoint/endpoint/object/key", + }, + ExpectErr: "sub resource not supported", + }, + "access-point not defined": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "outpost/myoutpost/endpoint/object/key", + }, + ExpectErr: "unknown resource set for outpost ARN", + }, + "valid resource-id": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "outpost/myoutpost/accesspoint/myaccesspoint", + }, + ExpectARN: OutpostAccessPointARN{ + AccessPointARN: AccessPointARN{ + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "outpost/myoutpost/accesspoint/myaccesspoint", + }, + AccessPointName: "myaccesspoint", + }, + OutpostID: "myoutpost", + }, + }, + "invalid FIPS pseudo region in ARN (prefix)": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + Region: "fips-us-west-2", + AccountID: "012345678901", + Resource: "outpost/myoutpost/accesspoint/myendpoint", + }, + ExpectErr: "FIPS region not allowed in ARN", + }, + "invalid FIPS pseudo region in ARN (suffix)": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + Region: "us-west-2-fips", + AccountID: "012345678901", + Resource: "outpost/myoutpost/accesspoint/myendpoint", + }, + ExpectErr: "FIPS region not allowed in ARN", + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + resParts := SplitResource(c.ARN.Resource) + a, err := ParseOutpostARNResource(c.ARN, resParts[1:]) + + if len(c.ExpectErr) == 0 && err != nil { + t.Fatalf("expect no error but got %v", err) + } else if len(c.ExpectErr) != 0 && err == nil { + t.Fatalf("expect error %q, but got nil", c.ExpectErr) + } else if len(c.ExpectErr) != 0 && err != nil { + if e, a := c.ExpectErr, err.Error(); !strings.Contains(a, e) { + t.Fatalf("expect error %q, got %q", e, a) + } + return + } + + if e, a := c.ExpectARN, a; !reflect.DeepEqual(e, a) { + t.Errorf("expect %v, got %v", e, a) + } + }) + } +} + +func TestParseOutpostBucketARNResource(t *testing.T) { + cases := map[string]struct { + ARN arn.ARN + ExpectErr string + ExpectARN OutpostBucketARN + }{ + "region not set": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + AccountID: "012345678901", + Resource: "outpost/myoutpost/bucket/mybucket", + }, + ExpectErr: "region not set", + }, + "resource-id empty": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "outpost:", + }, + ExpectErr: "resource-id not set", + }, + "resource not supported": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "outpost/myoutpost/bucket/mybucket/object/key", + }, + ExpectErr: "sub resource not supported", + }, + "bucket not defined": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "outpost/myoutpost/endpoint/object/key", + }, + ExpectErr: "unknown resource set for outpost ARN", + }, + "valid resource-id": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "outpost/myoutpost/bucket/mybucket", + }, + ExpectARN: OutpostBucketARN{ + ARN: arn.ARN{ + Partition: "aws", + Service: "s3-outposts", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "outpost/myoutpost/bucket/mybucket", + }, + BucketName: "mybucket", + OutpostID: "myoutpost", + }, + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + resParts := SplitResource(c.ARN.Resource) + a, err := ParseOutpostARNResource(c.ARN, resParts[1:]) + + if len(c.ExpectErr) == 0 && err != nil { + t.Fatalf("expect no error but got %v", err) + } else if len(c.ExpectErr) != 0 && err == nil { + t.Fatalf("expect error %q, but got nil", c.ExpectErr) + } else if len(c.ExpectErr) != 0 && err != nil { + if e, a := c.ExpectErr, err.Error(); !strings.Contains(a, e) { + t.Fatalf("expect error %q, got %q", e, a) + } + return + } + + if e, a := c.ExpectARN, a; !reflect.DeepEqual(e, a) { + t.Errorf("expect %v, got %v", e, a) + } + }) + } +} + +func TestParseBucketResource(t *testing.T) { + cases := map[string]struct { + ARN arn.ARN + ExpectErr string + ExpectBucketName string + }{ + "resource-id empty": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "bucket:", + }, + ExpectErr: "bucket resource-id not set", + }, + "resource not supported": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "bucket/mybucket/object/key", + }, + ExpectErr: "sub resource not supported", + }, + "valid resource-id": { + ARN: arn.ARN{ + Partition: "aws", + Service: "s3", + Region: "us-west-2", + AccountID: "012345678901", + Resource: "bucket/mybucket", + }, + ExpectBucketName: "mybucket", + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + resParts := SplitResource(c.ARN.Resource) + a, err := parseBucketResource(c.ARN, resParts[1:]) + + if len(c.ExpectErr) == 0 && err != nil { + t.Fatalf("expect no error but got %v", err) + } else if len(c.ExpectErr) != 0 && err == nil { + t.Fatalf("expect error %q, but got nil", c.ExpectErr) + } else if len(c.ExpectErr) != 0 && err != nil { + if e, a := c.ExpectErr, err.Error(); !strings.Contains(a, e) { + t.Fatalf("expect error %q, got %q", e, a) + } + return + } + + if e, a := c.ExpectBucketName, a; !reflect.DeepEqual(e, a) { + t.Errorf("expect %v, got %v", e, a) + } + }) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/s3_object_lambda_arn.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/s3_object_lambda_arn.go new file mode 100644 index 0000000000..513154cc0e --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/s3_object_lambda_arn.go @@ -0,0 +1,15 @@ +package arn + +// S3ObjectLambdaARN represents an ARN for the s3-object-lambda service +type S3ObjectLambdaARN interface { + Resource + + isS3ObjectLambdasARN() +} + +// S3ObjectLambdaAccessPointARN is an S3ObjectLambdaARN for the Access Point resource type +type S3ObjectLambdaAccessPointARN struct { + AccessPointARN +} + +func (s S3ObjectLambdaAccessPointARN) isS3ObjectLambdasARN() {} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/ya.make b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/ya.make new file mode 100644 index 0000000000..5e1a74cbc2 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn/ya.make @@ -0,0 +1,23 @@ +GO_LIBRARY() + +LICENSE(Apache-2.0) + +SRCS( + accesspoint_arn.go + arn.go + arn_member.go + outpost_arn.go + s3_object_lambda_arn.go +) + +GO_TEST_SRCS( + accesspoint_arn_test.go + arn_test.go + outpost_arn_test.go +) + +END() + +RECURSE( + gotest +) diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn_lookup.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn_lookup.go new file mode 100644 index 0000000000..b51532085f --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn_lookup.go @@ -0,0 +1,73 @@ +package s3shared + +import ( + "context" + "fmt" + + "github.com/aws/smithy-go/middleware" + + "github.com/aws/aws-sdk-go-v2/aws/arn" +) + +// ARNLookup is the initial middleware that looks up if an arn is provided. +// This middleware is responsible for fetching ARN from a arnable field, and registering the ARN on +// middleware context. This middleware must be executed before input validation step or any other +// arn processing middleware. +type ARNLookup struct { + + // GetARNValue takes in a input interface and returns a ptr to string and a bool + GetARNValue func(interface{}) (*string, bool) +} + +// ID for the middleware +func (m *ARNLookup) ID() string { + return "S3Shared:ARNLookup" +} + +// HandleInitialize handles the behavior of this initialize step +func (m *ARNLookup) HandleInitialize(ctx context.Context, in middleware.InitializeInput, next middleware.InitializeHandler) ( + out middleware.InitializeOutput, metadata middleware.Metadata, err error, +) { + // check if GetARNValue is supported + if m.GetARNValue == nil { + return next.HandleInitialize(ctx, in) + } + + // check is input resource is an ARN; if not go to next + v, ok := m.GetARNValue(in.Parameters) + if !ok || v == nil || !arn.IsARN(*v) { + return next.HandleInitialize(ctx, in) + } + + // if ARN process ResourceRequest and put it on ctx + av, err := arn.Parse(*v) + if err != nil { + return out, metadata, fmt.Errorf("error parsing arn: %w", err) + } + // set parsed arn on context + ctx = setARNResourceOnContext(ctx, av) + + return next.HandleInitialize(ctx, in) +} + +// arnResourceKey is the key set on context used to identify, retrive an ARN resource +// if present on the context. +type arnResourceKey struct{} + +// SetARNResourceOnContext sets the S3 ARN on the context. +// +// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues +// to clear all stack values. +func setARNResourceOnContext(ctx context.Context, value arn.ARN) context.Context { + return middleware.WithStackValue(ctx, arnResourceKey{}, value) +} + +// GetARNResourceFromContext returns an ARN from context and a bool indicating +// presence of ARN on ctx. +// +// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues +// to clear all stack values. +func GetARNResourceFromContext(ctx context.Context) (arn.ARN, bool) { + v, ok := middleware.GetStackValue(ctx, arnResourceKey{}).(arn.ARN) + return v, ok +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/config/config.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/config/config.go new file mode 100644 index 0000000000..b5d31f5c57 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/config/config.go @@ -0,0 +1,41 @@ +package config + +import "context" + +// UseARNRegionProvider is an interface for retrieving external configuration value for UseARNRegion +type UseARNRegionProvider interface { + GetS3UseARNRegion(ctx context.Context) (value bool, found bool, err error) +} + +// DisableMultiRegionAccessPointsProvider is an interface for retrieving external configuration value for DisableMultiRegionAccessPoints +type DisableMultiRegionAccessPointsProvider interface { + GetS3DisableMultiRegionAccessPoints(ctx context.Context) (value bool, found bool, err error) +} + +// ResolveUseARNRegion extracts the first instance of a UseARNRegion from the config slice. +// Additionally returns a boolean to indicate if the value was found in provided configs, and error if one is encountered. +func ResolveUseARNRegion(ctx context.Context, configs []interface{}) (value bool, found bool, err error) { + for _, cfg := range configs { + if p, ok := cfg.(UseARNRegionProvider); ok { + value, found, err = p.GetS3UseARNRegion(ctx) + if err != nil || found { + break + } + } + } + return +} + +// ResolveDisableMultiRegionAccessPoints extracts the first instance of a DisableMultiRegionAccessPoints from the config slice. +// Additionally returns a boolean to indicate if the value was found in provided configs, and error if one is encountered. +func ResolveDisableMultiRegionAccessPoints(ctx context.Context, configs []interface{}) (value bool, found bool, err error) { + for _, cfg := range configs { + if p, ok := cfg.(DisableMultiRegionAccessPointsProvider); ok { + value, found, err = p.GetS3DisableMultiRegionAccessPoints(ctx) + if err != nil || found { + break + } + } + } + return +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/config/ya.make b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/config/ya.make new file mode 100644 index 0000000000..165270885d --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/config/ya.make @@ -0,0 +1,9 @@ +GO_LIBRARY() + +LICENSE(Apache-2.0) + +SRCS( + config.go +) + +END() diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/endpoint_error.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/endpoint_error.go new file mode 100644 index 0000000000..aa0c3714e2 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/endpoint_error.go @@ -0,0 +1,183 @@ +package s3shared + +import ( + "fmt" + + "github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn" +) + +// TODO: fix these error statements to be relevant to v2 sdk + +const ( + invalidARNErrorErrCode = "InvalidARNError" + configurationErrorErrCode = "ConfigurationError" +) + +// InvalidARNError denotes the error for Invalid ARN +type InvalidARNError struct { + message string + resource arn.Resource + origErr error +} + +// Error returns the InvalidARN error string +func (e InvalidARNError) Error() string { + var extra string + if e.resource != nil { + extra = "ARN: " + e.resource.String() + } + msg := invalidARNErrorErrCode + " : " + e.message + if extra != "" { + msg = msg + "\n\t" + extra + } + + return msg +} + +// OrigErr is the original error wrapped by Invalid ARN Error +func (e InvalidARNError) Unwrap() error { + return e.origErr +} + +// NewInvalidARNError denotes invalid arn error +func NewInvalidARNError(resource arn.Resource, err error) InvalidARNError { + return InvalidARNError{ + message: "invalid ARN", + origErr: err, + resource: resource, + } +} + +// NewInvalidARNWithUnsupportedPartitionError ARN not supported for the target partition +func NewInvalidARNWithUnsupportedPartitionError(resource arn.Resource, err error) InvalidARNError { + return InvalidARNError{ + message: "resource ARN not supported for the target ARN partition", + origErr: err, + resource: resource, + } +} + +// NewInvalidARNWithFIPSError ARN not supported for FIPS region +// +// Deprecated: FIPS will not appear in the ARN region component. +func NewInvalidARNWithFIPSError(resource arn.Resource, err error) InvalidARNError { + return InvalidARNError{ + message: "resource ARN not supported for FIPS region", + resource: resource, + origErr: err, + } +} + +// ConfigurationError is used to denote a client configuration error +type ConfigurationError struct { + message string + resource arn.Resource + clientPartitionID string + clientRegion string + origErr error +} + +// Error returns the Configuration error string +func (e ConfigurationError) Error() string { + extra := fmt.Sprintf("ARN: %s, client partition: %s, client region: %s", + e.resource, e.clientPartitionID, e.clientRegion) + + msg := configurationErrorErrCode + " : " + e.message + if extra != "" { + msg = msg + "\n\t" + extra + } + return msg +} + +// OrigErr is the original error wrapped by Configuration Error +func (e ConfigurationError) Unwrap() error { + return e.origErr +} + +// NewClientPartitionMismatchError stub +func NewClientPartitionMismatchError(resource arn.Resource, clientPartitionID, clientRegion string, err error) ConfigurationError { + return ConfigurationError{ + message: "client partition does not match provided ARN partition", + origErr: err, + resource: resource, + clientPartitionID: clientPartitionID, + clientRegion: clientRegion, + } +} + +// NewClientRegionMismatchError denotes cross region access error +func NewClientRegionMismatchError(resource arn.Resource, clientPartitionID, clientRegion string, err error) ConfigurationError { + return ConfigurationError{ + message: "client region does not match provided ARN region", + origErr: err, + resource: resource, + clientPartitionID: clientPartitionID, + clientRegion: clientRegion, + } +} + +// NewFailedToResolveEndpointError denotes endpoint resolving error +func NewFailedToResolveEndpointError(resource arn.Resource, clientPartitionID, clientRegion string, err error) ConfigurationError { + return ConfigurationError{ + message: "endpoint resolver failed to find an endpoint for the provided ARN region", + origErr: err, + resource: resource, + clientPartitionID: clientPartitionID, + clientRegion: clientRegion, + } +} + +// NewClientConfiguredForFIPSError denotes client config error for unsupported cross region FIPS access +func NewClientConfiguredForFIPSError(resource arn.Resource, clientPartitionID, clientRegion string, err error) ConfigurationError { + return ConfigurationError{ + message: "client configured for fips but cross-region resource ARN provided", + origErr: err, + resource: resource, + clientPartitionID: clientPartitionID, + clientRegion: clientRegion, + } +} + +// NewFIPSConfigurationError denotes a configuration error when a client or request is configured for FIPS +func NewFIPSConfigurationError(resource arn.Resource, clientPartitionID, clientRegion string, err error) ConfigurationError { + return ConfigurationError{ + message: "use of ARN is not supported when client or request is configured for FIPS", + origErr: err, + resource: resource, + clientPartitionID: clientPartitionID, + clientRegion: clientRegion, + } +} + +// NewClientConfiguredForAccelerateError denotes client config error for unsupported S3 accelerate +func NewClientConfiguredForAccelerateError(resource arn.Resource, clientPartitionID, clientRegion string, err error) ConfigurationError { + return ConfigurationError{ + message: "client configured for S3 Accelerate but is not supported with resource ARN", + origErr: err, + resource: resource, + clientPartitionID: clientPartitionID, + clientRegion: clientRegion, + } +} + +// NewClientConfiguredForCrossRegionFIPSError denotes client config error for unsupported cross region FIPS request +func NewClientConfiguredForCrossRegionFIPSError(resource arn.Resource, clientPartitionID, clientRegion string, err error) ConfigurationError { + return ConfigurationError{ + message: "client configured for FIPS with cross-region enabled but is supported with cross-region resource ARN", + origErr: err, + resource: resource, + clientPartitionID: clientPartitionID, + clientRegion: clientRegion, + } +} + +// NewClientConfiguredForDualStackError denotes client config error for unsupported S3 Dual-stack +func NewClientConfiguredForDualStackError(resource arn.Resource, clientPartitionID, clientRegion string, err error) ConfigurationError { + return ConfigurationError{ + message: "client configured for S3 Dual-stack but is not supported with resource ARN", + origErr: err, + resource: resource, + clientPartitionID: clientPartitionID, + clientRegion: clientRegion, + } +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/go_module_metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/go_module_metadata.go new file mode 100644 index 0000000000..fc7e409600 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/go_module_metadata.go @@ -0,0 +1,6 @@ +// Code generated by internal/repotools/cmd/updatemodulemeta DO NOT EDIT. + +package s3shared + +// goModuleVersion is the tagged release for this module +const goModuleVersion = "1.16.0" diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/gotest/ya.make b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/gotest/ya.make new file mode 100644 index 0000000000..1ceac56026 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/gotest/ya.make @@ -0,0 +1,5 @@ +GO_TEST_FOR(vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared) + +LICENSE(Apache-2.0) + +END() diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/host_id.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/host_id.go new file mode 100644 index 0000000000..85b60d2a1b --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/host_id.go @@ -0,0 +1,29 @@ +package s3shared + +import ( + "github.com/aws/smithy-go/middleware" +) + +// hostID is used to retrieve host id from response metadata +type hostID struct { +} + +// SetHostIDMetadata sets the provided host id over middleware metadata +func SetHostIDMetadata(metadata *middleware.Metadata, id string) { + metadata.Set(hostID{}, id) +} + +// GetHostIDMetadata retrieves the host id from middleware metadata +// returns host id as string along with a boolean indicating presence of +// hostId on middleware metadata. +func GetHostIDMetadata(metadata middleware.Metadata) (string, bool) { + if !metadata.Has(hostID{}) { + return "", false + } + + v, ok := metadata.Get(hostID{}).(string) + if !ok { + return "", true + } + return v, true +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/metadata.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/metadata.go new file mode 100644 index 0000000000..f02604cb62 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/metadata.go @@ -0,0 +1,28 @@ +package s3shared + +import ( + "context" + + "github.com/aws/smithy-go/middleware" +) + +// clonedInputKey used to denote if request input was cloned. +type clonedInputKey struct{} + +// SetClonedInputKey sets a key on context to denote input was cloned previously. +// +// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues +// to clear all stack values. +func SetClonedInputKey(ctx context.Context, value bool) context.Context { + return middleware.WithStackValue(ctx, clonedInputKey{}, value) +} + +// IsClonedInput retrieves if context key for cloned input was set. +// If set, we can infer that the reuqest input was cloned previously. +// +// Scoped to stack values. Use github.com/aws/smithy-go/middleware#ClearStackValues +// to clear all stack values. +func IsClonedInput(ctx context.Context) bool { + v, _ := middleware.GetStackValue(ctx, clonedInputKey{}).(bool) + return v +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/metadata_retriever.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/metadata_retriever.go new file mode 100644 index 0000000000..f52f2f11e9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/metadata_retriever.go @@ -0,0 +1,52 @@ +package s3shared + +import ( + "context" + + awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" + "github.com/aws/smithy-go/middleware" + smithyhttp "github.com/aws/smithy-go/transport/http" +) + +const metadataRetrieverID = "S3MetadataRetriever" + +// AddMetadataRetrieverMiddleware adds request id, host id retriever middleware +func AddMetadataRetrieverMiddleware(stack *middleware.Stack) error { + // add metadata retriever middleware before operation deserializers so that it can retrieve metadata such as + // host id, request id from response header returned by operation deserializers + return stack.Deserialize.Insert(&metadataRetriever{}, "OperationDeserializer", middleware.Before) +} + +type metadataRetriever struct { +} + +// ID returns the middleware identifier +func (m *metadataRetriever) ID() string { + return metadataRetrieverID +} + +func (m *metadataRetriever) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( + out middleware.DeserializeOutput, metadata middleware.Metadata, err error, +) { + out, metadata, err = next.HandleDeserialize(ctx, in) + + resp, ok := out.RawResponse.(*smithyhttp.Response) + if !ok { + // No raw response to wrap with. + return out, metadata, err + } + + // check for header for Request id + if v := resp.Header.Get("X-Amz-Request-Id"); len(v) != 0 { + // set reqID on metadata for successful responses. + awsmiddleware.SetRequestIDMetadata(&metadata, v) + } + + // look up host-id + if v := resp.Header.Get("X-Amz-Id-2"); len(v) != 0 { + // set reqID on metadata for successful responses. + SetHostIDMetadata(&metadata, v) + } + + return out, metadata, err +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/resource_request.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/resource_request.go new file mode 100644 index 0000000000..bee8da3fe3 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/resource_request.go @@ -0,0 +1,77 @@ +package s3shared + +import ( + "fmt" + "strings" + + awsarn "github.com/aws/aws-sdk-go-v2/aws/arn" + "github.com/aws/aws-sdk-go-v2/service/internal/s3shared/arn" +) + +// ResourceRequest represents an ARN resource and api request metadata +type ResourceRequest struct { + Resource arn.Resource + // RequestRegion is the region configured on the request config + RequestRegion string + + // SigningRegion is the signing region resolved for the request + SigningRegion string + + // PartitionID is the resolved partition id for the provided request region + PartitionID string + + // UseARNRegion indicates if client should use the region provided in an ARN resource + UseARNRegion bool + + // UseFIPS indicates if te client is configured for FIPS + UseFIPS bool +} + +// ARN returns the resource ARN +func (r ResourceRequest) ARN() awsarn.ARN { + return r.Resource.GetARN() +} + +// ResourceConfiguredForFIPS returns true if resource ARNs region is FIPS +// +// Deprecated: FIPS will not be present in the ARN region +func (r ResourceRequest) ResourceConfiguredForFIPS() bool { + return IsFIPS(r.ARN().Region) +} + +// AllowCrossRegion returns a bool value to denote if S3UseARNRegion flag is set +func (r ResourceRequest) AllowCrossRegion() bool { + return r.UseARNRegion +} + +// IsCrossPartition returns true if request is configured for region of another partition, than +// the partition that resource ARN region resolves to. IsCrossPartition will not return an error, +// if request is not configured with a specific partition id. This might happen if customer provides +// custom endpoint url, but does not associate a partition id with it. +func (r ResourceRequest) IsCrossPartition() (bool, error) { + rv := r.PartitionID + if len(rv) == 0 { + return false, nil + } + + av := r.Resource.GetARN().Partition + if len(av) == 0 { + return false, fmt.Errorf("no partition id for provided ARN") + } + + return !strings.EqualFold(rv, av), nil +} + +// IsCrossRegion returns true if request signing region is not same as arn region +func (r ResourceRequest) IsCrossRegion() bool { + v := r.SigningRegion + return !strings.EqualFold(v, r.Resource.GetARN().Region) +} + +// IsFIPS returns true if region is a fips pseudo-region +// +// Deprecated: FIPS should be specified via EndpointOptions. +func IsFIPS(region string) bool { + return strings.HasPrefix(region, "fips-") || + strings.HasSuffix(region, "-fips") +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/response_error.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/response_error.go new file mode 100644 index 0000000000..8573362430 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/response_error.go @@ -0,0 +1,33 @@ +package s3shared + +import ( + "errors" + "fmt" + + awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http" +) + +// ResponseError provides the HTTP centric error type wrapping the underlying error +// with the HTTP response value and the deserialized RequestID. +type ResponseError struct { + *awshttp.ResponseError + + // HostID associated with response error + HostID string +} + +// ServiceHostID returns the host id associated with Response Error +func (e *ResponseError) ServiceHostID() string { return e.HostID } + +// Error returns the formatted error +func (e *ResponseError) Error() string { + return fmt.Sprintf( + "https response error StatusCode: %d, RequestID: %s, HostID: %s, %v", + e.Response.StatusCode, e.RequestID, e.HostID, e.Err) +} + +// As populates target and returns true if the type of target is a error type that +// the ResponseError embeds, (e.g.S3 HTTP ResponseError) +func (e *ResponseError) As(target interface{}) bool { + return errors.As(e.ResponseError, target) +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/response_error_middleware.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/response_error_middleware.go new file mode 100644 index 0000000000..5435762450 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/response_error_middleware.go @@ -0,0 +1,60 @@ +package s3shared + +import ( + "context" + + awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware" + awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http" + "github.com/aws/smithy-go/middleware" + smithyhttp "github.com/aws/smithy-go/transport/http" +) + +// AddResponseErrorMiddleware adds response error wrapper middleware +func AddResponseErrorMiddleware(stack *middleware.Stack) error { + // add error wrapper middleware before request id retriever middleware so that it can wrap the error response + // returned by operation deserializers + return stack.Deserialize.Insert(&errorWrapper{}, metadataRetrieverID, middleware.Before) +} + +type errorWrapper struct { +} + +// ID returns the middleware identifier +func (m *errorWrapper) ID() string { + return "ResponseErrorWrapper" +} + +func (m *errorWrapper) HandleDeserialize(ctx context.Context, in middleware.DeserializeInput, next middleware.DeserializeHandler) ( + out middleware.DeserializeOutput, metadata middleware.Metadata, err error, +) { + out, metadata, err = next.HandleDeserialize(ctx, in) + if err == nil { + // Nothing to do when there is no error. + return out, metadata, err + } + + resp, ok := out.RawResponse.(*smithyhttp.Response) + if !ok { + // No raw response to wrap with. + return out, metadata, err + } + + // look for request id in metadata + reqID, _ := awsmiddleware.GetRequestIDMetadata(metadata) + // look for host id in metadata + hostID, _ := GetHostIDMetadata(metadata) + + // Wrap the returned smithy error with the request id retrieved from the metadata + err = &ResponseError{ + ResponseError: &awshttp.ResponseError{ + ResponseError: &smithyhttp.ResponseError{ + Response: resp, + Err: err, + }, + RequestID: reqID, + }, + HostID: hostID, + } + + return out, metadata, err +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/s3100continue.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/s3100continue.go new file mode 100644 index 0000000000..0f43ec0d4f --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/s3100continue.go @@ -0,0 +1,54 @@ +package s3shared + +import ( + "context" + "fmt" + "github.com/aws/smithy-go/middleware" + smithyhttp "github.com/aws/smithy-go/transport/http" +) + +const s3100ContinueID = "S3100Continue" +const default100ContinueThresholdBytes int64 = 1024 * 1024 * 2 + +// Add100Continue add middleware, which adds {Expect: 100-continue} header for s3 client HTTP PUT request larger than 2MB +// or with unknown size streaming bodies, during operation builder step +func Add100Continue(stack *middleware.Stack, continueHeaderThresholdBytes int64) error { + return stack.Build.Add(&s3100Continue{ + continueHeaderThresholdBytes: continueHeaderThresholdBytes, + }, middleware.After) +} + +type s3100Continue struct { + continueHeaderThresholdBytes int64 +} + +// ID returns the middleware identifier +func (m *s3100Continue) ID() string { + return s3100ContinueID +} + +func (m *s3100Continue) HandleBuild( + ctx context.Context, in middleware.BuildInput, next middleware.BuildHandler, +) ( + out middleware.BuildOutput, metadata middleware.Metadata, err error, +) { + sizeLimit := default100ContinueThresholdBytes + switch { + case m.continueHeaderThresholdBytes == -1: + return next.HandleBuild(ctx, in) + case m.continueHeaderThresholdBytes > 0: + sizeLimit = m.continueHeaderThresholdBytes + default: + } + + req, ok := in.Request.(*smithyhttp.Request) + if !ok { + return out, metadata, fmt.Errorf("unknown request type %T", req) + } + + if req.ContentLength == -1 || (req.ContentLength == 0 && req.Body != nil) || req.ContentLength >= sizeLimit { + req.Header.Set("Expect", "100-continue") + } + + return next.HandleBuild(ctx, in) +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/s3100continue_test.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/s3100continue_test.go new file mode 100644 index 0000000000..db815c30bd --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/s3100continue_test.go @@ -0,0 +1,96 @@ +package s3shared + +import ( + "context" + "github.com/aws/aws-sdk-go-v2/internal/awstesting" + "github.com/aws/smithy-go/middleware" + smithyhttp "github.com/aws/smithy-go/transport/http" + "testing" +) + +// unit test for service/internal/s3shared/s3100continue.go +func TestAdd100ContinueHttpHeader(t *testing.T) { + const HeaderKey = "Expect" + HeaderValue := "100-continue" + + cases := map[string]struct { + ContentLength int64 + Body *awstesting.ReadCloser + ExpectValueFound string + ContinueHeaderThresholdBytes int64 + }{ + "http request smaller than default 2MB": { + ContentLength: 1, + Body: &awstesting.ReadCloser{Size: 1}, + ExpectValueFound: "", + }, + "http request smaller than configured threshold": { + ContentLength: 1024 * 1024 * 2, + Body: &awstesting.ReadCloser{Size: 1024 * 1024 * 2}, + ExpectValueFound: "", + ContinueHeaderThresholdBytes: 1024 * 1024 * 3, + }, + "http request larger than default 2MB": { + ContentLength: 1024 * 1024 * 3, + Body: &awstesting.ReadCloser{Size: 1024 * 1024 * 3}, + ExpectValueFound: HeaderValue, + }, + "http request larger than configured threshold": { + ContentLength: 1024 * 1024 * 4, + Body: &awstesting.ReadCloser{Size: 1024 * 1024 * 4}, + ExpectValueFound: HeaderValue, + ContinueHeaderThresholdBytes: 1024 * 1024 * 3, + }, + "http put request with unknown -1 ContentLength": { + ContentLength: -1, + Body: &awstesting.ReadCloser{Size: 1024 * 1024 * 10}, + ExpectValueFound: HeaderValue, + }, + "http put request with 0 ContentLength but unknown non-nil body": { + ContentLength: 0, + Body: &awstesting.ReadCloser{Size: 1024 * 1024 * 3}, + ExpectValueFound: HeaderValue, + }, + "http put request with unknown -1 ContentLength and configured threshold": { + ContentLength: -1, + Body: &awstesting.ReadCloser{Size: 1024 * 1024 * 3}, + ExpectValueFound: HeaderValue, + ContinueHeaderThresholdBytes: 1024 * 1024 * 10, + }, + "http put request with continue header disabled": { + ContentLength: 1024 * 1024 * 3, + Body: &awstesting.ReadCloser{Size: 1024 * 1024 * 3}, + ExpectValueFound: "", + ContinueHeaderThresholdBytes: -1, + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + var err error + req := smithyhttp.NewStackRequest().(*smithyhttp.Request) + + req.ContentLength = c.ContentLength + req.Body = c.Body + var updatedRequest *smithyhttp.Request + m := s3100Continue{ + continueHeaderThresholdBytes: c.ContinueHeaderThresholdBytes, + } + _, _, err = m.HandleBuild(context.Background(), + middleware.BuildInput{Request: req}, + middleware.BuildHandlerFunc(func(ctx context.Context, input middleware.BuildInput) ( + out middleware.BuildOutput, metadata middleware.Metadata, err error) { + updatedRequest = input.Request.(*smithyhttp.Request) + return out, metadata, nil + }), + ) + if err != nil { + t.Fatalf("expect no error, got %v", err) + } + + if e, a := c.ExpectValueFound, updatedRequest.Header.Get(HeaderKey); e != a { + t.Errorf("expect header value %v found, got %v", e, a) + } + }) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/update_endpoint.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/update_endpoint.go new file mode 100644 index 0000000000..22773199f6 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/update_endpoint.go @@ -0,0 +1,78 @@ +package s3shared + +import ( + "context" + "fmt" + "strings" + + "github.com/aws/smithy-go/middleware" + smithyhttp "github.com/aws/smithy-go/transport/http" + + awsmiddle "github.com/aws/aws-sdk-go-v2/aws/middleware" +) + +// EnableDualstack represents middleware struct for enabling dualstack support +// +// Deprecated: See EndpointResolverOptions' UseDualStackEndpoint support +type EnableDualstack struct { + // UseDualstack indicates if dualstack endpoint resolving is to be enabled + UseDualstack bool + + // DefaultServiceID is the service id prefix used in endpoint resolving + // by default service-id is 's3' and 's3-control' for service s3, s3control. + DefaultServiceID string +} + +// ID returns the middleware ID. +func (*EnableDualstack) ID() string { + return "EnableDualstack" +} + +// HandleSerialize handles serializer middleware behavior when middleware is executed +func (u *EnableDualstack) HandleSerialize( + ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler, +) ( + out middleware.SerializeOutput, metadata middleware.Metadata, err error, +) { + + // check for host name immutable property + if smithyhttp.GetHostnameImmutable(ctx) { + return next.HandleSerialize(ctx, in) + } + + serviceID := awsmiddle.GetServiceID(ctx) + + // s3-control may be represented as `S3 Control` as in model + if serviceID == "S3 Control" { + serviceID = "s3-control" + } + + if len(serviceID) == 0 { + // default service id + serviceID = u.DefaultServiceID + } + + req, ok := in.Request.(*smithyhttp.Request) + if !ok { + return out, metadata, fmt.Errorf("unknown request type %T", req) + } + + if u.UseDualstack { + parts := strings.Split(req.URL.Host, ".") + if len(parts) < 3 { + return out, metadata, fmt.Errorf("unable to update endpoint host for dualstack, hostname invalid, %s", req.URL.Host) + } + + for i := 0; i+1 < len(parts); i++ { + if strings.EqualFold(parts[i], serviceID) { + parts[i] = parts[i] + ".dualstack" + break + } + } + + // construct the url host + req.URL.Host = strings.Join(parts, ".") + } + + return next.HandleSerialize(ctx, in) +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/xml_utils.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/xml_utils.go new file mode 100644 index 0000000000..65fd07e000 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/xml_utils.go @@ -0,0 +1,89 @@ +package s3shared + +import ( + "encoding/xml" + "fmt" + "io" + "net/http" + "strings" +) + +// ErrorComponents represents the error response fields +// that will be deserialized from an xml error response body +type ErrorComponents struct { + Code string `xml:"Code"` + Message string `xml:"Message"` + RequestID string `xml:"RequestId"` + HostID string `xml:"HostId"` +} + +// GetUnwrappedErrorResponseComponents returns the error fields from an xml error response body +func GetUnwrappedErrorResponseComponents(r io.Reader) (ErrorComponents, error) { + var errComponents ErrorComponents + if err := xml.NewDecoder(r).Decode(&errComponents); err != nil && err != io.EOF { + return ErrorComponents{}, fmt.Errorf("error while deserializing xml error response : %w", err) + } + return errComponents, nil +} + +// GetWrappedErrorResponseComponents returns the error fields from an xml error response body +// in which error code, and message are wrapped by a <Error> tag +func GetWrappedErrorResponseComponents(r io.Reader) (ErrorComponents, error) { + var errComponents struct { + Code string `xml:"Error>Code"` + Message string `xml:"Error>Message"` + RequestID string `xml:"RequestId"` + HostID string `xml:"HostId"` + } + + if err := xml.NewDecoder(r).Decode(&errComponents); err != nil && err != io.EOF { + return ErrorComponents{}, fmt.Errorf("error while deserializing xml error response : %w", err) + } + + return ErrorComponents{ + Code: errComponents.Code, + Message: errComponents.Message, + RequestID: errComponents.RequestID, + HostID: errComponents.HostID, + }, nil +} + +// GetErrorResponseComponents retrieves error components according to passed in options +func GetErrorResponseComponents(r io.Reader, options ErrorResponseDeserializerOptions) (ErrorComponents, error) { + var errComponents ErrorComponents + var err error + + if options.IsWrappedWithErrorTag { + errComponents, err = GetWrappedErrorResponseComponents(r) + } else { + errComponents, err = GetUnwrappedErrorResponseComponents(r) + } + + if err != nil { + return ErrorComponents{}, err + } + + // If an error code or message is not retrieved, it is derived from the http status code + // eg, for S3 service, we derive err code and message, if none is found + if options.UseStatusCode && len(errComponents.Code) == 0 && + len(errComponents.Message) == 0 { + // derive code and message from status code + statusText := http.StatusText(options.StatusCode) + errComponents.Code = strings.Replace(statusText, " ", "", -1) + errComponents.Message = statusText + } + return errComponents, nil +} + +// ErrorResponseDeserializerOptions represents error response deserializer options for s3 and s3-control service +type ErrorResponseDeserializerOptions struct { + // UseStatusCode denotes if status code should be used to retrieve error code, msg + UseStatusCode bool + + // StatusCode is status code of error response + StatusCode int + + //IsWrappedWithErrorTag represents if error response's code, msg is wrapped within an + // additional <Error> tag + IsWrappedWithErrorTag bool +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/xml_utils_test.go b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/xml_utils_test.go new file mode 100644 index 0000000000..6d7efaabf9 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/xml_utils_test.go @@ -0,0 +1,102 @@ +package s3shared + +import ( + "strings" + "testing" +) + +func TestGetResponseErrorCode(t *testing.T) { + const xmlErrorResponse = `<Error> + <Type>Sender</Type> + <Code>InvalidGreeting</Code> + <Message>Hi</Message> + <HostId>bar-id</HostId> + <RequestId>foo-id</RequestId> +</Error>` + + const wrappedXMLErrorResponse = `<ErrorResponse><Error> + <Type>Sender</Type> + <Code>InvalidGreeting</Code> + <Message>Hi</Message> +</Error> + <HostId>bar-id</HostId> + <RequestId>foo-id</RequestId> +</ErrorResponse>` + + cases := map[string]struct { + getErr func() (ErrorComponents, error) + expectedErrorCode string + expectedErrorMessage string + expectedErrorRequestID string + expectedErrorHostID string + }{ + "standard xml error": { + getErr: func() (ErrorComponents, error) { + errResp := strings.NewReader(xmlErrorResponse) + return GetErrorResponseComponents(errResp, ErrorResponseDeserializerOptions{ + UseStatusCode: false, + StatusCode: 0, + IsWrappedWithErrorTag: false, + }) + }, + expectedErrorCode: "InvalidGreeting", + expectedErrorMessage: "Hi", + expectedErrorRequestID: "foo-id", + expectedErrorHostID: "bar-id", + }, + + "s3 no response body": { + getErr: func() (ErrorComponents, error) { + errResp := strings.NewReader("") + return GetErrorResponseComponents(errResp, ErrorResponseDeserializerOptions{ + UseStatusCode: true, + StatusCode: 400, + }) + }, + expectedErrorCode: "BadRequest", + expectedErrorMessage: "Bad Request", + }, + "s3control no response body": { + getErr: func() (ErrorComponents, error) { + errResp := strings.NewReader("") + return GetErrorResponseComponents(errResp, ErrorResponseDeserializerOptions{ + IsWrappedWithErrorTag: true, + }) + }, + }, + "s3control standard response body": { + getErr: func() (ErrorComponents, error) { + errResp := strings.NewReader(wrappedXMLErrorResponse) + return GetErrorResponseComponents(errResp, ErrorResponseDeserializerOptions{ + IsWrappedWithErrorTag: true, + }) + }, + expectedErrorCode: "InvalidGreeting", + expectedErrorMessage: "Hi", + expectedErrorRequestID: "foo-id", + expectedErrorHostID: "bar-id", + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + ec, err := c.getErr() + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + + if e, a := c.expectedErrorCode, ec.Code; !strings.EqualFold(e, a) { + t.Fatalf("expected %v, got %v", e, a) + } + if e, a := c.expectedErrorMessage, ec.Message; !strings.EqualFold(e, a) { + t.Fatalf("expected %v, got %v", e, a) + } + if e, a := c.expectedErrorRequestID, ec.RequestID; !strings.EqualFold(e, a) { + t.Fatalf("expected %v, got %v", e, a) + } + if e, a := c.expectedErrorHostID, ec.HostID; !strings.EqualFold(e, a) { + t.Fatalf("expected %v, got %v", e, a) + } + }) + } +} diff --git a/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/ya.make b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/ya.make new file mode 100644 index 0000000000..512ad83e48 --- /dev/null +++ b/vendor/github.com/aws/aws-sdk-go-v2/service/internal/s3shared/ya.make @@ -0,0 +1,31 @@ +GO_LIBRARY() + +LICENSE(Apache-2.0) + +SRCS( + arn_lookup.go + endpoint_error.go + go_module_metadata.go + host_id.go + metadata.go + metadata_retriever.go + resource_request.go + response_error.go + response_error_middleware.go + s3100continue.go + update_endpoint.go + xml_utils.go +) + +GO_TEST_SRCS( + s3100continue_test.go + xml_utils_test.go +) + +END() + +RECURSE( + arn + config + gotest +) |