src

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

endpoints.go (16762B)


      1 // Code generated by smithy-go-codegen DO NOT EDIT.
      2 
      3 package ssooidc
      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/ssooidc/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 = "sso-oauth"
    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_OIDC")
    208 
    209 	if g && !s {
    210 		return
    211 	}
    212 
    213 	value, found, err := internalConfig.ResolveServiceBaseEndpoint(context.Background(), "SSO OIDC", 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://oidc-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 _PartitionResult.SupportsFIPS == true {
    377 					if _PartitionResult.Name == "aws-us-gov" {
    378 						uriString := func() string {
    379 							var out strings.Builder
    380 							out.WriteString("https://oidc.")
    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://oidc-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://oidc.")
    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://oidc.")
    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 }