diff --git a/constants.go b/constants.go index ff9356f2b63d6..7dd7e6b14bbe5 100644 --- a/constants.go +++ b/constants.go @@ -384,6 +384,9 @@ const ( // SSEKMSKey is an optional switch to use an KMS CMK key for S3 SSE. SSEKMSKey = "sse_kms_key" + // S3UsePathStyle is an optional switch to use an path style access for S3 buckets + S3UsePathStyle = "use_s3_path_style" + // SchemeFile configures local disk-based file storage for audit events SchemeFile = "file" diff --git a/docs/pages/reference/backends.mdx b/docs/pages/reference/backends.mdx index 662f03c3a9b64..5ab4353ffb2e2 100644 --- a/docs/pages/reference/backends.mdx +++ b/docs/pages/reference/backends.mdx @@ -651,6 +651,10 @@ Service reads these parameters to configure its interactions with S3: - `use_fips_endpoint=true` - [Configure S3 FIPS endpoints](#configuring-aws-fips-endpoints) +- `use_s3_path_style` - Whether to use path-style instead of virtual-host-style URLs for the + bucket. Only applies when a custom endpoint is set. Defaults to true when unset. If used + without a custom endpoint set, this option has no effect. + ### S3 IAM policy (!docs/pages/includes/s3-iam-policy.mdx!) diff --git a/lib/events/s3sessions/s3handler.go b/lib/events/s3sessions/s3handler.go index f4492d27337a9..0cd94f6d6301f 100644 --- a/lib/events/s3sessions/s3handler.go +++ b/lib/events/s3sessions/s3handler.go @@ -97,6 +97,8 @@ type Config struct { Insecure bool // DisableServerSideEncryption is an optional switch to opt out of SSE in case the provider does not support it DisableServerSideEncryption bool + + UsePathStyle *bool } // SetFromURL sets values on the Config from the supplied URI @@ -147,6 +149,18 @@ func (s *Config) SetFromURL(in *url.URL, inRegion string) error { } } + if val := in.Query().Get(teleport.S3UsePathStyle); val != "" { + usePathStyle, err := strconv.ParseBool(val) + if err != nil { + return trace.BadParameter(boolErrorTemplate, in.String(), teleport.S3UsePathStyle, val) + } + s.UsePathStyle = &usePathStyle + } else { + // Default path style to true for backwards compatibility + usePathStyle := true + s.UsePathStyle = &usePathStyle + } + s.Region = region s.Bucket = in.Host s.Path = in.Path @@ -163,6 +177,12 @@ func (s *Config) CheckAndSetDefaults() error { s.Endpoint = endpoint.CreateURI(s.Endpoint, s.Insecure) } + // Default path style to true for backwards compatibility + if s.UsePathStyle == nil { + pathStyle := true + s.UsePathStyle = &pathStyle + } + return nil } @@ -224,7 +244,7 @@ func NewHandler(ctx context.Context, cfg Config) (*Handler, error) { opts = append(opts, config.WithBaseEndpoint(cfg.Endpoint)) s3Opts = append(s3Opts, func(options *s3.Options) { - options.UsePathStyle = true + options.UsePathStyle = *cfg.UsePathStyle }) } diff --git a/lib/events/s3sessions/s3handler_config_test.go b/lib/events/s3sessions/s3handler_config_test.go index d6af6a6df109b..2e2fa6346c845 100644 --- a/lib/events/s3sessions/s3handler_config_test.go +++ b/lib/events/s3sessions/s3handler_config_test.go @@ -115,6 +115,27 @@ func TestConfig_SetFromURL(t *testing.T) { require.Equal(t, types.ClusterAuditConfigSpecV2_FIPS_DISABLED, config.UseFIPSEndpoint) }, }, + { + name: "path style addressing enabled via url", + url: "s3://path/bucket/adit?use_s3_path_style=true", + cfgAssertion: func(t *testing.T, config Config) { + require.True(t, *config.UsePathStyle) + }, + }, + { + name: "path style addressing enabled by default", + url: "s3://path/bucket/audit", + cfgAssertion: func(t *testing.T, config Config) { + require.True(t, *config.UsePathStyle) + }, + }, + { + name: "path style addressing disable via url", + url: "s3://path/bucket/audit?use_s3_path_style=false", + cfgAssertion: func(t *testing.T, config Config) { + require.False(t, *config.UsePathStyle) + }, + }, } for _, tt := range cases {