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