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 }