| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- package s3
- import (
- "net/url"
- "strings"
- "github.com/aws/aws-sdk-go/aws"
- "github.com/aws/aws-sdk-go/aws/awserr"
- "github.com/aws/aws-sdk-go/aws/endpoints"
- "github.com/aws/aws-sdk-go/aws/request"
- "github.com/aws/aws-sdk-go/internal/s3shared"
- "github.com/aws/aws-sdk-go/internal/s3shared/arn"
- "github.com/aws/aws-sdk-go/private/protocol"
- )
- const (
- accessPointPrefixLabel = "accesspoint"
- accountIDPrefixLabel = "accountID"
- accessPointPrefixTemplate = "{" + accessPointPrefixLabel + "}-{" + accountIDPrefixLabel + "}."
- outpostPrefixLabel = "outpost"
- outpostAccessPointPrefixTemplate = accessPointPrefixTemplate + "{" + outpostPrefixLabel + "}."
- )
- // hasCustomEndpoint returns true if endpoint is a custom endpoint
- func hasCustomEndpoint(r *request.Request) bool {
- return len(aws.StringValue(r.Config.Endpoint)) > 0
- }
- // accessPointEndpointBuilder represents the endpoint builder for access point arn
- type accessPointEndpointBuilder arn.AccessPointARN
- // build builds the endpoint for corresponding access point arn
- //
- // For building an endpoint from access point arn, format used is:
- // - Access point endpoint format : {accesspointName}-{accountId}.s3-accesspoint.{region}.{dnsSuffix}
- // - example : myaccesspoint-012345678901.s3-accesspoint.us-west-2.amazonaws.com
- //
- // Access Point Endpoint requests are signed using "s3" as signing name.
- func (a accessPointEndpointBuilder) build(req *request.Request) error {
- resolveService := arn.AccessPointARN(a).Service
- resolveRegion := arn.AccessPointARN(a).Region
- endpoint, err := resolveRegionalEndpoint(req, resolveRegion, "", resolveService)
- if err != nil {
- return s3shared.NewFailedToResolveEndpointError(arn.AccessPointARN(a),
- req.ClientInfo.PartitionID, resolveRegion, err)
- }
- endpoint.URL = endpoints.AddScheme(endpoint.URL, aws.BoolValue(req.Config.DisableSSL))
- if !hasCustomEndpoint(req) {
- if err = updateRequestEndpoint(req, endpoint.URL); err != nil {
- return err
- }
- // dual stack provided by endpoint resolver
- updateS3HostForS3AccessPoint(req)
- }
- protocol.HostPrefixBuilder{
- Prefix: accessPointPrefixTemplate,
- LabelsFn: a.hostPrefixLabelValues,
- }.Build(req)
- // signer redirection
- redirectSigner(req, endpoint.SigningName, endpoint.SigningRegion)
- err = protocol.ValidateEndpointHost(req.Operation.Name, req.HTTPRequest.URL.Host)
- if err != nil {
- return s3shared.NewInvalidARNError(arn.AccessPointARN(a), err)
- }
- return nil
- }
- func (a accessPointEndpointBuilder) hostPrefixLabelValues() map[string]string {
- return map[string]string{
- accessPointPrefixLabel: arn.AccessPointARN(a).AccessPointName,
- accountIDPrefixLabel: arn.AccessPointARN(a).AccountID,
- }
- }
- // s3ObjectLambdaAccessPointEndpointBuilder represents the endpoint builder for an s3 object lambda access point arn
- type s3ObjectLambdaAccessPointEndpointBuilder arn.S3ObjectLambdaAccessPointARN
- // build builds the endpoint for corresponding access point arn
- //
- // For building an endpoint from access point arn, format used is:
- // - Access point endpoint format : {accesspointName}-{accountId}.s3-object-lambda.{region}.{dnsSuffix}
- // - example : myaccesspoint-012345678901.s3-object-lambda.us-west-2.amazonaws.com
- //
- // Access Point Endpoint requests are signed using "s3-object-lambda" as signing name.
- func (a s3ObjectLambdaAccessPointEndpointBuilder) build(req *request.Request) error {
- resolveRegion := arn.S3ObjectLambdaAccessPointARN(a).Region
- endpoint, err := resolveRegionalEndpoint(req, resolveRegion, "", EndpointsID)
- if err != nil {
- return s3shared.NewFailedToResolveEndpointError(arn.S3ObjectLambdaAccessPointARN(a),
- req.ClientInfo.PartitionID, resolveRegion, err)
- }
- endpoint.URL = endpoints.AddScheme(endpoint.URL, aws.BoolValue(req.Config.DisableSSL))
- endpoint.SigningName = s3ObjectsLambdaNamespace
- if !hasCustomEndpoint(req) {
- if err = updateRequestEndpoint(req, endpoint.URL); err != nil {
- return err
- }
- updateS3HostPrefixForS3ObjectLambda(req)
- }
- protocol.HostPrefixBuilder{
- Prefix: accessPointPrefixTemplate,
- LabelsFn: a.hostPrefixLabelValues,
- }.Build(req)
- // signer redirection
- redirectSigner(req, endpoint.SigningName, endpoint.SigningRegion)
- err = protocol.ValidateEndpointHost(req.Operation.Name, req.HTTPRequest.URL.Host)
- if err != nil {
- return s3shared.NewInvalidARNError(arn.S3ObjectLambdaAccessPointARN(a), err)
- }
- return nil
- }
- func (a s3ObjectLambdaAccessPointEndpointBuilder) hostPrefixLabelValues() map[string]string {
- return map[string]string{
- accessPointPrefixLabel: arn.S3ObjectLambdaAccessPointARN(a).AccessPointName,
- accountIDPrefixLabel: arn.S3ObjectLambdaAccessPointARN(a).AccountID,
- }
- }
- // outpostAccessPointEndpointBuilder represents the Endpoint builder for outpost access point arn.
- type outpostAccessPointEndpointBuilder arn.OutpostAccessPointARN
- // build builds an endpoint corresponding to the outpost access point arn.
- //
- // For building an endpoint from outpost access point arn, format used is:
- // - Outpost access point endpoint format : {accesspointName}-{accountId}.{outpostId}.s3-outposts.{region}.{dnsSuffix}
- // - example : myaccesspoint-012345678901.op-01234567890123456.s3-outposts.us-west-2.amazonaws.com
- //
- // Outpost AccessPoint Endpoint request are signed using "s3-outposts" as signing name.
- func (o outpostAccessPointEndpointBuilder) build(req *request.Request) error {
- resolveRegion := o.Region
- resolveService := o.Service
- endpointsID := resolveService
- if resolveService == s3OutpostsNamespace {
- endpointsID = "s3"
- }
- endpoint, err := resolveRegionalEndpoint(req, resolveRegion, "", endpointsID)
- if err != nil {
- return s3shared.NewFailedToResolveEndpointError(o,
- req.ClientInfo.PartitionID, resolveRegion, err)
- }
- endpoint.URL = endpoints.AddScheme(endpoint.URL, aws.BoolValue(req.Config.DisableSSL))
- if !hasCustomEndpoint(req) {
- if err = updateRequestEndpoint(req, endpoint.URL); err != nil {
- return err
- }
- updateHostPrefix(req, endpointsID, resolveService)
- }
- protocol.HostPrefixBuilder{
- Prefix: outpostAccessPointPrefixTemplate,
- LabelsFn: o.hostPrefixLabelValues,
- }.Build(req)
- // set the signing region, name to resolved names from ARN
- redirectSigner(req, resolveService, resolveRegion)
- err = protocol.ValidateEndpointHost(req.Operation.Name, req.HTTPRequest.URL.Host)
- if err != nil {
- return s3shared.NewInvalidARNError(o, err)
- }
- return nil
- }
- func (o outpostAccessPointEndpointBuilder) hostPrefixLabelValues() map[string]string {
- return map[string]string{
- accessPointPrefixLabel: o.AccessPointName,
- accountIDPrefixLabel: o.AccountID,
- outpostPrefixLabel: o.OutpostID,
- }
- }
- func resolveRegionalEndpoint(r *request.Request, region, resolvedRegion, endpointsID string) (endpoints.ResolvedEndpoint, error) {
- return r.Config.EndpointResolver.EndpointFor(endpointsID, region, func(opts *endpoints.Options) {
- opts.DisableSSL = aws.BoolValue(r.Config.DisableSSL)
- opts.UseDualStack = aws.BoolValue(r.Config.UseDualStack)
- opts.UseDualStackEndpoint = r.Config.UseDualStackEndpoint
- opts.UseFIPSEndpoint = r.Config.UseFIPSEndpoint
- opts.S3UsEast1RegionalEndpoint = endpoints.RegionalS3UsEast1Endpoint
- opts.ResolvedRegion = resolvedRegion
- opts.Logger = r.Config.Logger
- opts.LogDeprecated = r.Config.LogLevel.Matches(aws.LogDebugWithDeprecated)
- })
- }
- func updateRequestEndpoint(r *request.Request, endpoint string) (err error) {
- r.HTTPRequest.URL, err = url.Parse(endpoint + r.Operation.HTTPPath)
- if err != nil {
- return awserr.New(request.ErrCodeSerialization,
- "failed to parse endpoint URL", err)
- }
- return nil
- }
- // redirectSigner sets signing name, signing region for a request
- func redirectSigner(req *request.Request, signingName string, signingRegion string) {
- req.ClientInfo.SigningName = signingName
- req.ClientInfo.SigningRegion = signingRegion
- }
- func updateS3HostForS3AccessPoint(req *request.Request) {
- updateHostPrefix(req, "s3", s3AccessPointNamespace)
- }
- func updateS3HostPrefixForS3ObjectLambda(req *request.Request) {
- updateHostPrefix(req, "s3", s3ObjectsLambdaNamespace)
- }
- func updateHostPrefix(req *request.Request, oldEndpointPrefix, newEndpointPrefix string) {
- host := req.HTTPRequest.URL.Host
- if strings.HasPrefix(host, oldEndpointPrefix) {
- // replace service hostlabel oldEndpointPrefix to newEndpointPrefix
- req.HTTPRequest.URL.Host = newEndpointPrefix + host[len(oldEndpointPrefix):]
- }
- }
|