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 }