...

Source file src/github.com/aws/aws-sdk-go-v2/service/sso/endpoints.go

Documentation: github.com/aws/aws-sdk-go-v2/service/sso

     1  // Code generated by smithy-go-codegen DO NOT EDIT.
     2  
     3  package sso
     4  
     5  import (
     6  	"context"
     7  	"errors"
     8  	"fmt"
     9  	"github.com/aws/aws-sdk-go-v2/aws"
    10  	awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
    11  	internalConfig "github.com/aws/aws-sdk-go-v2/internal/configsources"
    12  	"github.com/aws/aws-sdk-go-v2/internal/endpoints"
    13  	"github.com/aws/aws-sdk-go-v2/internal/endpoints/awsrulesfn"
    14  	internalendpoints "github.com/aws/aws-sdk-go-v2/service/sso/internal/endpoints"
    15  	smithyauth "github.com/aws/smithy-go/auth"
    16  	smithyendpoints "github.com/aws/smithy-go/endpoints"
    17  	"github.com/aws/smithy-go/middleware"
    18  	"github.com/aws/smithy-go/ptr"
    19  	smithyhttp "github.com/aws/smithy-go/transport/http"
    20  	"net/http"
    21  	"net/url"
    22  	"os"
    23  	"strings"
    24  )
    25  
    26  // EndpointResolverOptions is the service endpoint resolver options
    27  type EndpointResolverOptions = internalendpoints.Options
    28  
    29  // EndpointResolver interface for resolving service endpoints.
    30  type EndpointResolver interface {
    31  	ResolveEndpoint(region string, options EndpointResolverOptions) (aws.Endpoint, error)
    32  }
    33  
    34  var _ EndpointResolver = &internalendpoints.Resolver{}
    35  
    36  // NewDefaultEndpointResolver constructs a new service endpoint resolver
    37  func NewDefaultEndpointResolver() *internalendpoints.Resolver {
    38  	return internalendpoints.New()
    39  }
    40  
    41  // EndpointResolverFunc is a helper utility that wraps a function so it satisfies
    42  // the EndpointResolver interface. This is useful when you want to add additional
    43  // endpoint resolving logic, or stub out specific endpoints with custom values.
    44  type EndpointResolverFunc func(region string, options EndpointResolverOptions) (aws.Endpoint, error)
    45  
    46  func (fn EndpointResolverFunc) ResolveEndpoint(region string, options EndpointResolverOptions) (endpoint aws.Endpoint, err error) {
    47  	return fn(region, options)
    48  }
    49  
    50  // EndpointResolverFromURL returns an EndpointResolver configured using the
    51  // provided endpoint url. By default, the resolved endpoint resolver uses the
    52  // client region as signing region, and the endpoint source is set to
    53  // EndpointSourceCustom.You can provide functional options to configure endpoint
    54  // values for the resolved endpoint.
    55  func EndpointResolverFromURL(url string, optFns ...func(*aws.Endpoint)) EndpointResolver {
    56  	e := aws.Endpoint{URL: url, Source: aws.EndpointSourceCustom}
    57  	for _, fn := range optFns {
    58  		fn(&e)
    59  	}
    60  
    61  	return EndpointResolverFunc(
    62  		func(region string, options EndpointResolverOptions) (aws.Endpoint, error) {
    63  			if len(e.SigningRegion) == 0 {
    64  				e.SigningRegion = region
    65  			}
    66  			return e, nil
    67  		},
    68  	)
    69  }
    70  
    71  type ResolveEndpoint struct {
    72  	Resolver EndpointResolver
    73  	Options  EndpointResolverOptions
    74  }
    75  
    76  func (*ResolveEndpoint) ID() string {
    77  	return "ResolveEndpoint"
    78  }
    79  
    80  func (m *ResolveEndpoint) HandleSerialize(ctx context.Context, in middleware.SerializeInput, next middleware.SerializeHandler) (
    81  	out middleware.SerializeOutput, metadata middleware.Metadata, err error,
    82  ) {
    83  	if !awsmiddleware.GetRequiresLegacyEndpoints(ctx) {
    84  		return next.HandleSerialize(ctx, in)
    85  	}
    86  
    87  	req, ok := in.Request.(*smithyhttp.Request)
    88  	if !ok {
    89  		return out, metadata, fmt.Errorf("unknown transport type %T", in.Request)
    90  	}
    91  
    92  	if m.Resolver == nil {
    93  		return out, metadata, fmt.Errorf("expected endpoint resolver to not be nil")
    94  	}
    95  
    96  	eo := m.Options
    97  	eo.Logger = middleware.GetLogger(ctx)
    98  
    99  	var endpoint aws.Endpoint
   100  	endpoint, err = m.Resolver.ResolveEndpoint(awsmiddleware.GetRegion(ctx), eo)
   101  	if err != nil {
   102  		nf := (&aws.EndpointNotFoundError{})
   103  		if errors.As(err, &nf) {
   104  			ctx = awsmiddleware.SetRequiresLegacyEndpoints(ctx, false)
   105  			return next.HandleSerialize(ctx, in)
   106  		}
   107  		return out, metadata, fmt.Errorf("failed to resolve service endpoint, %w", err)
   108  	}
   109  
   110  	req.URL, err = url.Parse(endpoint.URL)
   111  	if err != nil {
   112  		return out, metadata, fmt.Errorf("failed to parse endpoint URL: %w", err)
   113  	}
   114  
   115  	if len(awsmiddleware.GetSigningName(ctx)) == 0 {
   116  		signingName := endpoint.SigningName
   117  		if len(signingName) == 0 {
   118  			signingName = "awsssoportal"
   119  		}
   120  		ctx = awsmiddleware.SetSigningName(ctx, signingName)
   121  	}
   122  	ctx = awsmiddleware.SetEndpointSource(ctx, endpoint.Source)
   123  	ctx = smithyhttp.SetHostnameImmutable(ctx, endpoint.HostnameImmutable)
   124  	ctx = awsmiddleware.SetSigningRegion(ctx, endpoint.SigningRegion)
   125  	ctx = awsmiddleware.SetPartitionID(ctx, endpoint.PartitionID)
   126  	return next.HandleSerialize(ctx, in)
   127  }
   128  func addResolveEndpointMiddleware(stack *middleware.Stack, o Options) error {
   129  	return stack.Serialize.Insert(&ResolveEndpoint{
   130  		Resolver: o.EndpointResolver,
   131  		Options:  o.EndpointOptions,
   132  	}, "OperationSerializer", middleware.Before)
   133  }
   134  
   135  func removeResolveEndpointMiddleware(stack *middleware.Stack) error {
   136  	_, err := stack.Serialize.Remove((&ResolveEndpoint{}).ID())
   137  	return err
   138  }
   139  
   140  type wrappedEndpointResolver struct {
   141  	awsResolver aws.EndpointResolverWithOptions
   142  }
   143  
   144  func (w *wrappedEndpointResolver) ResolveEndpoint(region string, options EndpointResolverOptions) (endpoint aws.Endpoint, err error) {
   145  	return w.awsResolver.ResolveEndpoint(ServiceID, region, options)
   146  }
   147  
   148  type awsEndpointResolverAdaptor func(service, region string) (aws.Endpoint, error)
   149  
   150  func (a awsEndpointResolverAdaptor) ResolveEndpoint(service, region string, options ...interface{}) (aws.Endpoint, error) {
   151  	return a(service, region)
   152  }
   153  
   154  var _ aws.EndpointResolverWithOptions = awsEndpointResolverAdaptor(nil)
   155  
   156  // withEndpointResolver returns an aws.EndpointResolverWithOptions that first delegates endpoint resolution to the awsResolver.
   157  // If awsResolver returns aws.EndpointNotFoundError error, the v1 resolver middleware will swallow the error,
   158  // and set an appropriate context flag such that fallback will occur when EndpointResolverV2 is invoked
   159  // via its middleware.
   160  //
   161  // If another error (besides aws.EndpointNotFoundError) is returned, then that error will be propagated.
   162  func withEndpointResolver(awsResolver aws.EndpointResolver, awsResolverWithOptions aws.EndpointResolverWithOptions) EndpointResolver {
   163  	var resolver aws.EndpointResolverWithOptions
   164  
   165  	if awsResolverWithOptions != nil {
   166  		resolver = awsResolverWithOptions
   167  	} else if awsResolver != nil {
   168  		resolver = awsEndpointResolverAdaptor(awsResolver.ResolveEndpoint)
   169  	}
   170  
   171  	return &wrappedEndpointResolver{
   172  		awsResolver: resolver,
   173  	}
   174  }
   175  
   176  func finalizeClientEndpointResolverOptions(options *Options) {
   177  	options.EndpointOptions.LogDeprecated = options.ClientLogMode.IsDeprecatedUsage()
   178  
   179  	if len(options.EndpointOptions.ResolvedRegion) == 0 {
   180  		const fipsInfix = "-fips-"
   181  		const fipsPrefix = "fips-"
   182  		const fipsSuffix = "-fips"
   183  
   184  		if strings.Contains(options.Region, fipsInfix) ||
   185  			strings.Contains(options.Region, fipsPrefix) ||
   186  			strings.Contains(options.Region, fipsSuffix) {
   187  			options.EndpointOptions.ResolvedRegion = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(
   188  				options.Region, fipsInfix, "-"), fipsPrefix, ""), fipsSuffix, "")
   189  			options.EndpointOptions.UseFIPSEndpoint = aws.FIPSEndpointStateEnabled
   190  		}
   191  	}
   192  
   193  }
   194  
   195  func resolveEndpointResolverV2(options *Options) {
   196  	if options.EndpointResolverV2 == nil {
   197  		options.EndpointResolverV2 = NewDefaultEndpointResolverV2()
   198  	}
   199  }
   200  
   201  func resolveBaseEndpoint(cfg aws.Config, o *Options) {
   202  	if cfg.BaseEndpoint != nil {
   203  		o.BaseEndpoint = cfg.BaseEndpoint
   204  	}
   205  
   206  	_, g := os.LookupEnv("AWS_ENDPOINT_URL")
   207  	_, s := os.LookupEnv("AWS_ENDPOINT_URL_SSO")
   208  
   209  	if g && !s {
   210  		return
   211  	}
   212  
   213  	value, found, err := internalConfig.ResolveServiceBaseEndpoint(context.Background(), "SSO", cfg.ConfigSources)
   214  	if found && err == nil {
   215  		o.BaseEndpoint = &value
   216  	}
   217  }
   218  
   219  func bindRegion(region string) *string {
   220  	if region == "" {
   221  		return nil
   222  	}
   223  	return aws.String(endpoints.MapFIPSRegion(region))
   224  }
   225  
   226  // EndpointParameters provides the parameters that influence how endpoints are
   227  // resolved.
   228  type EndpointParameters struct {
   229  	// The AWS region used to dispatch the request.
   230  	//
   231  	// Parameter is
   232  	// required.
   233  	//
   234  	// AWS::Region
   235  	Region *string
   236  
   237  	// When true, use the dual-stack endpoint. If the configured endpoint does not
   238  	// support dual-stack, dispatching the request MAY return an error.
   239  	//
   240  	// Defaults to
   241  	// false if no value is provided.
   242  	//
   243  	// AWS::UseDualStack
   244  	UseDualStack *bool
   245  
   246  	// When true, send this request to the FIPS-compliant regional endpoint. If the
   247  	// configured endpoint does not have a FIPS compliant endpoint, dispatching the
   248  	// request will return an error.
   249  	//
   250  	// Defaults to false if no value is
   251  	// provided.
   252  	//
   253  	// AWS::UseFIPS
   254  	UseFIPS *bool
   255  
   256  	// Override the endpoint used to send this request
   257  	//
   258  	// Parameter is
   259  	// required.
   260  	//
   261  	// SDK::Endpoint
   262  	Endpoint *string
   263  }
   264  
   265  // ValidateRequired validates required parameters are set.
   266  func (p EndpointParameters) ValidateRequired() error {
   267  	if p.UseDualStack == nil {
   268  		return fmt.Errorf("parameter UseDualStack is required")
   269  	}
   270  
   271  	if p.UseFIPS == nil {
   272  		return fmt.Errorf("parameter UseFIPS is required")
   273  	}
   274  
   275  	return nil
   276  }
   277  
   278  // WithDefaults returns a shallow copy of EndpointParameterswith default values
   279  // applied to members where applicable.
   280  func (p EndpointParameters) WithDefaults() EndpointParameters {
   281  	if p.UseDualStack == nil {
   282  		p.UseDualStack = ptr.Bool(false)
   283  	}
   284  
   285  	if p.UseFIPS == nil {
   286  		p.UseFIPS = ptr.Bool(false)
   287  	}
   288  	return p
   289  }
   290  
   291  // EndpointResolverV2 provides the interface for resolving service endpoints.
   292  type EndpointResolverV2 interface {
   293  	// ResolveEndpoint attempts to resolve the endpoint with the provided options,
   294  	// returning the endpoint if found. Otherwise an error is returned.
   295  	ResolveEndpoint(ctx context.Context, params EndpointParameters) (
   296  		smithyendpoints.Endpoint, error,
   297  	)
   298  }
   299  
   300  // resolver provides the implementation for resolving endpoints.
   301  type resolver struct{}
   302  
   303  func NewDefaultEndpointResolverV2() EndpointResolverV2 {
   304  	return &resolver{}
   305  }
   306  
   307  // ResolveEndpoint attempts to resolve the endpoint with the provided options,
   308  // returning the endpoint if found. Otherwise an error is returned.
   309  func (r *resolver) ResolveEndpoint(
   310  	ctx context.Context, params EndpointParameters,
   311  ) (
   312  	endpoint smithyendpoints.Endpoint, err error,
   313  ) {
   314  	params = params.WithDefaults()
   315  	if err = params.ValidateRequired(); err != nil {
   316  		return endpoint, fmt.Errorf("endpoint parameters are not valid, %w", err)
   317  	}
   318  	_UseDualStack := *params.UseDualStack
   319  	_UseFIPS := *params.UseFIPS
   320  
   321  	if exprVal := params.Endpoint; exprVal != nil {
   322  		_Endpoint := *exprVal
   323  		_ = _Endpoint
   324  		if _UseFIPS == true {
   325  			return endpoint, fmt.Errorf("endpoint rule error, %s", "Invalid Configuration: FIPS and custom endpoint are not supported")
   326  		}
   327  		if _UseDualStack == true {
   328  			return endpoint, fmt.Errorf("endpoint rule error, %s", "Invalid Configuration: Dualstack and custom endpoint are not supported")
   329  		}
   330  		uriString := _Endpoint
   331  
   332  		uri, err := url.Parse(uriString)
   333  		if err != nil {
   334  			return endpoint, fmt.Errorf("Failed to parse uri: %s", uriString)
   335  		}
   336  
   337  		return smithyendpoints.Endpoint{
   338  			URI:     *uri,
   339  			Headers: http.Header{},
   340  		}, nil
   341  	}
   342  	if exprVal := params.Region; exprVal != nil {
   343  		_Region := *exprVal
   344  		_ = _Region
   345  		if exprVal := awsrulesfn.GetPartition(_Region); exprVal != nil {
   346  			_PartitionResult := *exprVal
   347  			_ = _PartitionResult
   348  			if _UseFIPS == true {
   349  				if _UseDualStack == true {
   350  					if true == _PartitionResult.SupportsFIPS {
   351  						if true == _PartitionResult.SupportsDualStack {
   352  							uriString := func() string {
   353  								var out strings.Builder
   354  								out.WriteString("https://portal.sso-fips.")
   355  								out.WriteString(_Region)
   356  								out.WriteString(".")
   357  								out.WriteString(_PartitionResult.DualStackDnsSuffix)
   358  								return out.String()
   359  							}()
   360  
   361  							uri, err := url.Parse(uriString)
   362  							if err != nil {
   363  								return endpoint, fmt.Errorf("Failed to parse uri: %s", uriString)
   364  							}
   365  
   366  							return smithyendpoints.Endpoint{
   367  								URI:     *uri,
   368  								Headers: http.Header{},
   369  							}, nil
   370  						}
   371  					}
   372  					return endpoint, fmt.Errorf("endpoint rule error, %s", "FIPS and DualStack are enabled, but this partition does not support one or both")
   373  				}
   374  			}
   375  			if _UseFIPS == true {
   376  				if true == _PartitionResult.SupportsFIPS {
   377  					if "aws-us-gov" == _PartitionResult.Name {
   378  						uriString := func() string {
   379  							var out strings.Builder
   380  							out.WriteString("https://portal.sso.")
   381  							out.WriteString(_Region)
   382  							out.WriteString(".amazonaws.com")
   383  							return out.String()
   384  						}()
   385  
   386  						uri, err := url.Parse(uriString)
   387  						if err != nil {
   388  							return endpoint, fmt.Errorf("Failed to parse uri: %s", uriString)
   389  						}
   390  
   391  						return smithyendpoints.Endpoint{
   392  							URI:     *uri,
   393  							Headers: http.Header{},
   394  						}, nil
   395  					}
   396  					uriString := func() string {
   397  						var out strings.Builder
   398  						out.WriteString("https://portal.sso-fips.")
   399  						out.WriteString(_Region)
   400  						out.WriteString(".")
   401  						out.WriteString(_PartitionResult.DnsSuffix)
   402  						return out.String()
   403  					}()
   404  
   405  					uri, err := url.Parse(uriString)
   406  					if err != nil {
   407  						return endpoint, fmt.Errorf("Failed to parse uri: %s", uriString)
   408  					}
   409  
   410  					return smithyendpoints.Endpoint{
   411  						URI:     *uri,
   412  						Headers: http.Header{},
   413  					}, nil
   414  				}
   415  				return endpoint, fmt.Errorf("endpoint rule error, %s", "FIPS is enabled but this partition does not support FIPS")
   416  			}
   417  			if _UseDualStack == true {
   418  				if true == _PartitionResult.SupportsDualStack {
   419  					uriString := func() string {
   420  						var out strings.Builder
   421  						out.WriteString("https://portal.sso.")
   422  						out.WriteString(_Region)
   423  						out.WriteString(".")
   424  						out.WriteString(_PartitionResult.DualStackDnsSuffix)
   425  						return out.String()
   426  					}()
   427  
   428  					uri, err := url.Parse(uriString)
   429  					if err != nil {
   430  						return endpoint, fmt.Errorf("Failed to parse uri: %s", uriString)
   431  					}
   432  
   433  					return smithyendpoints.Endpoint{
   434  						URI:     *uri,
   435  						Headers: http.Header{},
   436  					}, nil
   437  				}
   438  				return endpoint, fmt.Errorf("endpoint rule error, %s", "DualStack is enabled but this partition does not support DualStack")
   439  			}
   440  			uriString := func() string {
   441  				var out strings.Builder
   442  				out.WriteString("https://portal.sso.")
   443  				out.WriteString(_Region)
   444  				out.WriteString(".")
   445  				out.WriteString(_PartitionResult.DnsSuffix)
   446  				return out.String()
   447  			}()
   448  
   449  			uri, err := url.Parse(uriString)
   450  			if err != nil {
   451  				return endpoint, fmt.Errorf("Failed to parse uri: %s", uriString)
   452  			}
   453  
   454  			return smithyendpoints.Endpoint{
   455  				URI:     *uri,
   456  				Headers: http.Header{},
   457  			}, nil
   458  		}
   459  		return endpoint, fmt.Errorf("Endpoint resolution failed. Invalid operation or environment input.")
   460  	}
   461  	return endpoint, fmt.Errorf("endpoint rule error, %s", "Invalid Configuration: Missing Region")
   462  }
   463  
   464  type endpointParamsBinder interface {
   465  	bindEndpointParams(*EndpointParameters)
   466  }
   467  
   468  func bindEndpointParams(input interface{}, options Options) *EndpointParameters {
   469  	params := &EndpointParameters{}
   470  
   471  	params.Region = bindRegion(options.Region)
   472  	params.UseDualStack = aws.Bool(options.EndpointOptions.UseDualStackEndpoint == aws.DualStackEndpointStateEnabled)
   473  	params.UseFIPS = aws.Bool(options.EndpointOptions.UseFIPSEndpoint == aws.FIPSEndpointStateEnabled)
   474  	params.Endpoint = options.BaseEndpoint
   475  
   476  	if b, ok := input.(endpointParamsBinder); ok {
   477  		b.bindEndpointParams(params)
   478  	}
   479  
   480  	return params
   481  }
   482  
   483  type resolveEndpointV2Middleware struct {
   484  	options Options
   485  }
   486  
   487  func (*resolveEndpointV2Middleware) ID() string {
   488  	return "ResolveEndpointV2"
   489  }
   490  
   491  func (m *resolveEndpointV2Middleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
   492  	out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
   493  ) {
   494  	if awsmiddleware.GetRequiresLegacyEndpoints(ctx) {
   495  		return next.HandleFinalize(ctx, in)
   496  	}
   497  
   498  	req, ok := in.Request.(*smithyhttp.Request)
   499  	if !ok {
   500  		return out, metadata, fmt.Errorf("unknown transport type %T", in.Request)
   501  	}
   502  
   503  	if m.options.EndpointResolverV2 == nil {
   504  		return out, metadata, fmt.Errorf("expected endpoint resolver to not be nil")
   505  	}
   506  
   507  	params := bindEndpointParams(getOperationInput(ctx), m.options)
   508  	endpt, err := m.options.EndpointResolverV2.ResolveEndpoint(ctx, *params)
   509  	if err != nil {
   510  		return out, metadata, fmt.Errorf("failed to resolve service endpoint, %w", err)
   511  	}
   512  
   513  	if endpt.URI.RawPath == "" && req.URL.RawPath != "" {
   514  		endpt.URI.RawPath = endpt.URI.Path
   515  	}
   516  	req.URL.Scheme = endpt.URI.Scheme
   517  	req.URL.Host = endpt.URI.Host
   518  	req.URL.Path = smithyhttp.JoinPath(endpt.URI.Path, req.URL.Path)
   519  	req.URL.RawPath = smithyhttp.JoinPath(endpt.URI.RawPath, req.URL.RawPath)
   520  	for k := range endpt.Headers {
   521  		req.Header.Set(k, endpt.Headers.Get(k))
   522  	}
   523  
   524  	rscheme := getResolvedAuthScheme(ctx)
   525  	if rscheme == nil {
   526  		return out, metadata, fmt.Errorf("no resolved auth scheme")
   527  	}
   528  
   529  	opts, _ := smithyauth.GetAuthOptions(&endpt.Properties)
   530  	for _, o := range opts {
   531  		rscheme.SignerProperties.SetAll(&o.SignerProperties)
   532  	}
   533  
   534  	return next.HandleFinalize(ctx, in)
   535  }
   536  

View as plain text