src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

endpoints.go (17293B)


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