From c6b0587dc0e0b2f537f2f4fd080fafe2132e261a Mon Sep 17 00:00:00 2001 From: Nick Craig-Wood Date: Wed, 1 Mar 2023 16:18:04 +0000 Subject: [PATCH] s3: fix AWS STS failing if --s3-endpoint is set Before this change if an --s3-profile was set which used AWS STS (eg to assume a role) and --s3-endpoint was set then rclone would use the value from --s3-endpoint to contact the STS server which did not work. This fix implements an endpoint resolver which only overrides the "s3" service if --s3-endpoint is set. It sends the "sts" service (and any other service) to the default resolver. Fixes #6443 See: https://forum.rclone.org/t/s3-profile-failing-when-explicit-s3-endpoint-is-present/36063/ --- backend/s3/s3.go | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/backend/s3/s3.go b/backend/s3/s3.go index ef010def5..25b18b5e7 100644 --- a/backend/s3/s3.go +++ b/backend/s3/s3.go @@ -2560,6 +2560,30 @@ func getClient(ctx context.Context, opt *Options) *http.Client { } } +// Default name resolver +var defaultResolver = endpoints.DefaultResolver() + +// resolve (service, region) to endpoint +// +// Used to set endpoint for s3 services and not for other services +type resolver string + +// EndpointFor return the endpoint for s3 if set or the default if not +func (endpoint resolver) EndpointFor(service, region string, opts ...func(*endpoints.Options)) (endpoints.ResolvedEndpoint, error) { + fs.Debugf(nil, "Resolving service %q region %q", service, region) + if service == "s3" { + url := string(endpoint) + if !strings.HasPrefix(url, "http") { + url = "https://" + url + } + return endpoints.ResolvedEndpoint{ + URL: url, + SigningRegion: region, + }, nil + } + return defaultResolver.EndpointFor(service, region, opts...) +} + // s3Connection makes a connection to s3 func s3Connection(ctx context.Context, opt *Options, client *http.Client) (*s3.S3, *session.Session, error) { ci := fs.GetConfig(ctx) @@ -2639,7 +2663,8 @@ func s3Connection(ctx context.Context, opt *Options, client *http.Client) (*s3.S awsConfig.WithRegion(opt.Region) } if opt.Endpoint != "" { - awsConfig.WithEndpoint(opt.Endpoint) + // If endpoint is set, only override the s3 service so we don't break sts + awsConfig.WithEndpointResolver(resolver(opt.Endpoint)) } // awsConfig.WithLogLevel(aws.LogDebugWithSigning)