package customizations
import (
awsmiddleware
s3arn
)
const (
s3AccessPoint = "s3-accesspoint"
s3ObjectLambda = "s3-object-lambda"
)
type processARNResource struct {
UseARNRegion bool
UseAccelerate bool
EndpointResolver EndpointResolver
EndpointResolverOptions EndpointResolverOptions
DisableMultiRegionAccessPoints bool
}
func (*processARNResource) () string { return "S3:ProcessARNResource" }
func ( *processARNResource) (
context.Context, middleware.SerializeInput, middleware.SerializeHandler,
) (
middleware.SerializeOutput, middleware.Metadata, error,
) {
, := s3shared.GetARNResourceFromContext()
if ! {
return .HandleSerialize(, )
}
, := .Request.(*http.Request)
if ! {
return , , fmt.Errorf("unknown request type %T", )
}
, := s3arn.ParseEndpointARN()
if != nil {
return , ,
}
:= s3shared.ResourceRequest{
Resource: ,
UseARNRegion: .UseARNRegion,
UseFIPS: .EndpointResolverOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled,
RequestRegion: awsmiddleware.GetRegion(),
SigningRegion: awsmiddleware.GetSigningRegion(),
PartitionID: awsmiddleware.GetPartitionID(),
}
switch tv := .(type) {
case arn.AccessPointARN:
if len(.Region) != 0 {
if := validateRegionForResourceRequest(); != nil {
return , ,
}
}
if len(.Region) == 0 {
if .DisableMultiRegionAccessPoints {
return , , fmt.Errorf("Invalid configuration, Multi-Region access point ARNs are disabled")
}
if .EndpointResolverOptions.UseDualStackEndpoint == aws.DualStackEndpointStateEnabled {
return , , s3shared.NewClientConfiguredForDualStackError(,
.PartitionID, .RequestRegion, nil)
}
}
if .UseAccelerate {
return , , s3shared.NewClientConfiguredForAccelerateError(,
.PartitionID, .RequestRegion, nil)
}
:= .Region
if .UseFIPS && len() == 0 {
return , , s3shared.NewClientConfiguredForFIPSError(
, .PartitionID, .RequestRegion, nil)
}
var func(context.Context, accesspointOptions) (context.Context, error)
if len() == 0 {
= buildMultiRegionAccessPointsRequest
} else {
= buildAccessPointRequest
}
, = (, accesspointOptions{
processARNResource: *,
request: ,
resource: ,
resolveRegion: ,
partitionID: .PartitionID,
requestRegion: .RequestRegion,
})
if != nil {
return , ,
}
case arn.S3ObjectLambdaAccessPointARN:
if := validateRegionForResourceRequest(); != nil {
return , ,
}
if .UseAccelerate {
return , , s3shared.NewClientConfiguredForAccelerateError(,
.PartitionID, .RequestRegion, nil)
}
if .EndpointResolverOptions.UseDualStackEndpoint == aws.DualStackEndpointStateEnabled {
return , , s3shared.NewClientConfiguredForDualStackError(,
.PartitionID, .RequestRegion, nil)
}
:= .Region
, = buildS3ObjectLambdaAccessPointRequest(, accesspointOptions{
processARNResource: *,
request: ,
resource: .AccessPointARN,
resolveRegion: ,
partitionID: .PartitionID,
requestRegion: .RequestRegion,
})
if != nil {
return , ,
}
case arn.OutpostAccessPointARN:
if := validateRegionForResourceRequest(); != nil {
return , ,
}
if .UseAccelerate {
return , , s3shared.NewClientConfiguredForAccelerateError(,
.PartitionID, .RequestRegion, nil)
}
if .EndpointResolverOptions.UseDualStackEndpoint == aws.DualStackEndpointStateEnabled {
return , , s3shared.NewClientConfiguredForDualStackError(,
.PartitionID, .RequestRegion, nil)
}
if .UseFIPS {
return , , s3shared.NewFIPSConfigurationError(, .PartitionID,
.RequestRegion, nil)
}
, = buildOutpostAccessPointRequest(, outpostAccessPointOptions{
processARNResource: *,
resource: ,
request: ,
partitionID: .PartitionID,
requestRegion: .RequestRegion,
})
if != nil {
return , ,
}
default:
return , , s3shared.NewInvalidARNError(, nil)
}
return .HandleSerialize(, )
}
func ( s3shared.ResourceRequest) error {
, := .IsCrossPartition()
if != nil {
return
}
if {
return s3shared.NewClientPartitionMismatchError(.Resource,
.PartitionID, .RequestRegion, nil)
}
if !.AllowCrossRegion() && .IsCrossRegion() {
return s3shared.NewClientRegionMismatchError(.Resource,
.PartitionID, .RequestRegion, nil)
}
return nil
}
type accesspointOptions struct {
processARNResource
request *http.Request
resource arn.AccessPointARN
resolveRegion string
partitionID string
requestRegion string
}
func ( context.Context, accesspointOptions) (context.Context, error) {
:= .resource
:= .request
:= .resolveRegion
:= .Service
:= .EndpointResolverOptions
.Logger = middleware.GetLogger()
.ResolvedRegion = ""
, := .EndpointResolver.ResolveEndpoint(, )
if != nil {
return , s3shared.NewFailedToResolveEndpointError(
,
.partitionID,
.requestRegion,
,
)
}
.URL, = url.Parse(.URL)
if != nil {
return , fmt.Errorf("failed to parse endpoint URL: %w", )
}
if len(.SigningName) != 0 && .Source == aws.EndpointSourceCustom {
= awsmiddleware.SetSigningName(, .SigningName)
} else {
= awsmiddleware.SetSigningName(, )
}
if len(.SigningRegion) != 0 {
= awsmiddleware.SetSigningRegion(, .SigningRegion)
} else {
= awsmiddleware.SetSigningRegion(, )
}
= awsmiddleware.SetServiceID(, s3AccessPoint)
= http.DisableEndpointHostPrefix(, true)
= setBucketToRemoveOnContext(, .String())
if .HostnameImmutable {
return , nil
}
updateS3HostForS3AccessPoint()
, = buildAccessPointHostPrefix(, , )
if != nil {
return ,
}
return , nil
}
func ( context.Context, accesspointOptions) (context.Context, error) {
:= .resource
:= .request
:= .resolveRegion
:= .Service
:= .EndpointResolverOptions
.Logger = middleware.GetLogger()
.ResolvedRegion = ""
, := .EndpointResolver.ResolveEndpoint(, )
if != nil {
return , s3shared.NewFailedToResolveEndpointError(
,
.partitionID,
.requestRegion,
,
)
}
.URL, = url.Parse(.URL)
if != nil {
return , fmt.Errorf("failed to parse endpoint URL: %w", )
}
if len(.SigningName) != 0 && .Source == aws.EndpointSourceCustom {
= awsmiddleware.SetSigningName(, .SigningName)
} else {
= awsmiddleware.SetSigningName(, )
}
if len(.SigningRegion) != 0 {
= awsmiddleware.SetSigningRegion(, .SigningRegion)
} else {
= awsmiddleware.SetSigningRegion(, )
}
= awsmiddleware.SetServiceID(, s3ObjectLambda)
= http.DisableEndpointHostPrefix(, true)
= setBucketToRemoveOnContext(, .String())
if .HostnameImmutable {
return , nil
}
if .Source == aws.EndpointSourceServiceMetadata {
updateS3HostForS3ObjectLambda()
}
, = buildAccessPointHostPrefix(, , )
if != nil {
return ,
}
return , nil
}
func ( context.Context, accesspointOptions) (context.Context, error) {
const = "s3-global."
const = "accesspoint."
:= .resource
:= .request
:= .Service
:= .requestRegion
:= .Partition
:= .EndpointResolverOptions
.Logger = middleware.GetLogger()
, := .EndpointResolver.ResolveEndpoint(, )
if != nil {
return , s3shared.NewFailedToResolveEndpointError(
,
.partitionID,
.requestRegion,
,
)
}
.SigningRegion = "*"
= awsmiddleware.SetSigningRegion(, .SigningRegion)
= SetSignerVersion(, v4a.Version)
if len(.SigningName) != 0 {
= awsmiddleware.SetSigningName(, .SigningName)
} else {
= awsmiddleware.SetSigningName(, )
}
if .HostnameImmutable {
return , nil
}
:= strings.SplitN(.URL, "://", 2)
, := endpoints.GetDNSSuffix(, )
if != nil {
return , fmt.Errorf("Error determining dns suffix from arn partition, %w", )
}
.URL = [0] + "://" + +
.URL, = url.Parse(.URL)
if != nil {
return , fmt.Errorf("failed to parse endpoint URL: %w", )
}
:= .AccessPointName + "." +
.URL.Host = + .URL.Host
if len(.Host) > 0 {
.Host = + .Host
}
if := http.ValidateEndpointHost(.URL.Host); != nil {
return , fmt.Errorf("endpoint validation error: %w, when using arn %v", , )
}
= http.DisableEndpointHostPrefix(, true)
= setBucketToRemoveOnContext(, .String())
return , nil
}
func ( context.Context, *http.Request, arn.AccessPointARN) (context.Context, error) {
:= .AccessPointName + "-" + .AccountID + "."
.URL.Host = + .URL.Host
if len(.Host) > 0 {
.Host = + .Host
}
if := http.ValidateEndpointHost(.URL.Host); != nil {
return , s3shared.NewInvalidARNError(, )
}
return , nil
}
type outpostAccessPointOptions struct {
processARNResource
request *http.Request
resource arn.OutpostAccessPointARN
partitionID string
requestRegion string
}
func ( context.Context, outpostAccessPointOptions) (context.Context, error) {
:= .resource
:= .request
:= .Region
:= .Service
:=
if strings.EqualFold(, "s3-outposts") {
= "s3"
}
:= .EndpointResolverOptions
.Logger = middleware.GetLogger()
.ResolvedRegion = ""
, := .EndpointResolver.ResolveEndpoint(, )
if != nil {
return , s3shared.NewFailedToResolveEndpointError(
,
.partitionID,
.requestRegion,
,
)
}
.URL, = url.Parse(.URL)
if != nil {
return , fmt.Errorf("failed to parse endpoint URL: %w", )
}
if len(.SigningName) != 0 && .Source == aws.EndpointSourceCustom {
= awsmiddleware.SetSigningName(, .SigningName)
} else {
= awsmiddleware.SetSigningName(, )
}
if len(.SigningRegion) != 0 {
= awsmiddleware.SetSigningRegion(, .SigningRegion)
} else {
= awsmiddleware.SetSigningRegion(, )
}
= awsmiddleware.SetServiceID(, )
= http.DisableEndpointHostPrefix(, true)
= setBucketToRemoveOnContext(, .String())
if .HostnameImmutable {
return , nil
}
updateHostPrefix(, , )
:= .AccessPointName + "-" + .AccountID + "." + .OutpostID + "."
.URL.Host = + .URL.Host
if len(.Host) > 0 {
.Host = + .Host
}
if := http.ValidateEndpointHost(.URL.Host); != nil {
return , s3shared.NewInvalidARNError(, )
}
return , nil
}