src

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

auth.go (10994B)


      1 // Code generated by smithy-go-codegen DO NOT EDIT.
      2 
      3 package sso
      4 
      5 import (
      6 	"context"
      7 	"fmt"
      8 	"slices"
      9 	"strings"
     10 
     11 	awsmiddleware "github.com/aws/aws-sdk-go-v2/aws/middleware"
     12 	smithy "github.com/aws/smithy-go"
     13 	smithyauth "github.com/aws/smithy-go/auth"
     14 	"github.com/aws/smithy-go/metrics"
     15 	"github.com/aws/smithy-go/middleware"
     16 	"github.com/aws/smithy-go/tracing"
     17 	smithyhttp "github.com/aws/smithy-go/transport/http"
     18 )
     19 
     20 func bindAuthParamsRegion(_ interface{}, params *AuthResolverParameters, _ interface{}, options Options) error {
     21 	params.Region = options.Region
     22 	return nil
     23 }
     24 
     25 type setLegacyContextSigningOptionsMiddleware struct {
     26 }
     27 
     28 func (*setLegacyContextSigningOptionsMiddleware) ID() string {
     29 	return "setLegacyContextSigningOptions"
     30 }
     31 
     32 func (m *setLegacyContextSigningOptionsMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
     33 	out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
     34 ) {
     35 	rscheme := getResolvedAuthScheme(ctx)
     36 	schemeID := rscheme.Scheme.SchemeID()
     37 
     38 	if sn := awsmiddleware.GetSigningName(ctx); sn != "" {
     39 		if schemeID == "aws.auth#sigv4" {
     40 			smithyhttp.SetSigV4SigningName(&rscheme.SignerProperties, sn)
     41 		} else if schemeID == "aws.auth#sigv4a" {
     42 			smithyhttp.SetSigV4ASigningName(&rscheme.SignerProperties, sn)
     43 		}
     44 	}
     45 
     46 	if sr := awsmiddleware.GetSigningRegion(ctx); sr != "" {
     47 		if schemeID == "aws.auth#sigv4" {
     48 			smithyhttp.SetSigV4SigningRegion(&rscheme.SignerProperties, sr)
     49 		} else if schemeID == "aws.auth#sigv4a" {
     50 			smithyhttp.SetSigV4ASigningRegions(&rscheme.SignerProperties, []string{sr})
     51 		}
     52 	}
     53 
     54 	return next.HandleFinalize(ctx, in)
     55 }
     56 
     57 func addSetLegacyContextSigningOptionsMiddleware(stack *middleware.Stack) error {
     58 	return stack.Finalize.Insert(&setLegacyContextSigningOptionsMiddleware{}, "Signing", middleware.Before)
     59 }
     60 
     61 type withAnonymous struct {
     62 	resolver AuthSchemeResolver
     63 }
     64 
     65 var _ AuthSchemeResolver = (*withAnonymous)(nil)
     66 
     67 func (v *withAnonymous) ResolveAuthSchemes(ctx context.Context, params *AuthResolverParameters) ([]*smithyauth.Option, error) {
     68 	opts, err := v.resolver.ResolveAuthSchemes(ctx, params)
     69 	if err != nil {
     70 		return nil, err
     71 	}
     72 
     73 	opts = append(opts, &smithyauth.Option{
     74 		SchemeID: smithyauth.SchemeIDAnonymous,
     75 	})
     76 	return opts, nil
     77 }
     78 
     79 func wrapWithAnonymousAuth(options *Options) {
     80 	if _, ok := options.AuthSchemeResolver.(*defaultAuthSchemeResolver); !ok {
     81 		return
     82 	}
     83 
     84 	options.AuthSchemeResolver = &withAnonymous{
     85 		resolver: options.AuthSchemeResolver,
     86 	}
     87 }
     88 
     89 // AuthResolverParameters contains the set of inputs necessary for auth scheme
     90 // resolution.
     91 type AuthResolverParameters struct {
     92 	// The name of the operation being invoked.
     93 	Operation string
     94 
     95 	// The region in which the operation is being invoked.
     96 	Region string
     97 }
     98 
     99 func bindAuthResolverParams(ctx context.Context, operation string, input interface{}, options Options) (*AuthResolverParameters, error) {
    100 	params := &AuthResolverParameters{
    101 		Operation: operation,
    102 	}
    103 
    104 	if err := bindAuthParamsRegion(ctx, params, input, options); err != nil {
    105 		return nil, err
    106 	}
    107 
    108 	return params, nil
    109 }
    110 
    111 // AuthSchemeResolver returns a set of possible authentication options for an
    112 // operation.
    113 type AuthSchemeResolver interface {
    114 	ResolveAuthSchemes(context.Context, *AuthResolverParameters) ([]*smithyauth.Option, error)
    115 }
    116 
    117 type defaultAuthSchemeResolver struct{}
    118 
    119 var _ AuthSchemeResolver = (*defaultAuthSchemeResolver)(nil)
    120 
    121 func (*defaultAuthSchemeResolver) ResolveAuthSchemes(ctx context.Context, params *AuthResolverParameters) ([]*smithyauth.Option, error) {
    122 	if overrides, ok := operationAuthOptions[params.Operation]; ok {
    123 		return overrides(params), nil
    124 	}
    125 	return serviceAuthOptions(params), nil
    126 }
    127 
    128 var operationAuthOptions = map[string]func(*AuthResolverParameters) []*smithyauth.Option{
    129 	"GetRoleCredentials": func(params *AuthResolverParameters) []*smithyauth.Option {
    130 		return []*smithyauth.Option{
    131 			{SchemeID: smithyauth.SchemeIDAnonymous},
    132 		}
    133 	},
    134 
    135 	"ListAccountRoles": func(params *AuthResolverParameters) []*smithyauth.Option {
    136 		return []*smithyauth.Option{
    137 			{SchemeID: smithyauth.SchemeIDAnonymous},
    138 		}
    139 	},
    140 
    141 	"ListAccounts": func(params *AuthResolverParameters) []*smithyauth.Option {
    142 		return []*smithyauth.Option{
    143 			{SchemeID: smithyauth.SchemeIDAnonymous},
    144 		}
    145 	},
    146 
    147 	"Logout": func(params *AuthResolverParameters) []*smithyauth.Option {
    148 		return []*smithyauth.Option{
    149 			{SchemeID: smithyauth.SchemeIDAnonymous},
    150 		}
    151 	},
    152 }
    153 
    154 func serviceAuthOptions(params *AuthResolverParameters) []*smithyauth.Option {
    155 	return []*smithyauth.Option{
    156 		{
    157 			SchemeID: smithyauth.SchemeIDSigV4,
    158 			SignerProperties: func() smithy.Properties {
    159 				var props smithy.Properties
    160 				smithyhttp.SetSigV4SigningName(&props, "awsssoportal")
    161 				smithyhttp.SetSigV4SigningRegion(&props, params.Region)
    162 				return props
    163 			}(),
    164 		},
    165 	}
    166 }
    167 
    168 type resolveAuthSchemeMiddleware struct {
    169 	operation string
    170 	options   Options
    171 }
    172 
    173 func (*resolveAuthSchemeMiddleware) ID() string {
    174 	return "ResolveAuthScheme"
    175 }
    176 
    177 func (m *resolveAuthSchemeMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
    178 	out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
    179 ) {
    180 	_, span := tracing.StartSpan(ctx, "ResolveAuthScheme")
    181 	defer span.End()
    182 
    183 	params, err := bindAuthResolverParams(ctx, m.operation, getOperationInput(ctx), m.options)
    184 	if err != nil {
    185 		return out, metadata, fmt.Errorf("bind auth scheme params: %w", err)
    186 	}
    187 	options, err := m.options.AuthSchemeResolver.ResolveAuthSchemes(ctx, params)
    188 	if err != nil {
    189 		return out, metadata, fmt.Errorf("resolve auth scheme: %w", err)
    190 	}
    191 
    192 	scheme, ok := m.selectScheme(options)
    193 	if !ok {
    194 		return out, metadata, fmt.Errorf("could not select an auth scheme")
    195 	}
    196 
    197 	ctx = setResolvedAuthScheme(ctx, scheme)
    198 
    199 	span.SetProperty("auth.scheme_id", scheme.Scheme.SchemeID())
    200 	span.End()
    201 	return next.HandleFinalize(ctx, in)
    202 }
    203 
    204 func (m *resolveAuthSchemeMiddleware) selectScheme(options []*smithyauth.Option) (*resolvedAuthScheme, bool) {
    205 	sorted := sortAuthOptions(options, m.options.AuthSchemePreference)
    206 	for _, option := range sorted {
    207 		if option.SchemeID == smithyauth.SchemeIDAnonymous {
    208 			return newResolvedAuthScheme(smithyhttp.NewAnonymousScheme(), option), true
    209 		}
    210 
    211 		for _, scheme := range m.options.AuthSchemes {
    212 			if !matchSchemeID(scheme.SchemeID(), option.SchemeID) {
    213 				continue
    214 			}
    215 
    216 			if scheme.IdentityResolver(m.options) != nil {
    217 				return newResolvedAuthScheme(scheme, option), true
    218 			}
    219 		}
    220 	}
    221 
    222 	return nil, false
    223 }
    224 
    225 func matchSchemeID(registered, option string) bool {
    226 	if registered == option {
    227 		return true
    228 	}
    229 	if i := strings.LastIndex(registered, "#"); i != -1 {
    230 		return registered[i+1:] == option
    231 	}
    232 	return false
    233 }
    234 
    235 func sortAuthOptions(options []*smithyauth.Option, preferred []string) []*smithyauth.Option {
    236 	byPriority := make([]*smithyauth.Option, 0, len(options))
    237 	for _, prefName := range preferred {
    238 		for _, option := range options {
    239 			optName := option.SchemeID
    240 			if parts := strings.Split(option.SchemeID, "#"); len(parts) == 2 {
    241 				optName = parts[1]
    242 			}
    243 			if prefName == optName {
    244 				byPriority = append(byPriority, option)
    245 			}
    246 		}
    247 	}
    248 	for _, option := range options {
    249 		if !slices.ContainsFunc(byPriority, func(o *smithyauth.Option) bool {
    250 			return o.SchemeID == option.SchemeID
    251 		}) {
    252 			byPriority = append(byPriority, option)
    253 		}
    254 	}
    255 	return byPriority
    256 }
    257 
    258 type resolvedAuthSchemeKey struct{}
    259 
    260 type resolvedAuthScheme struct {
    261 	Scheme             smithyhttp.AuthScheme
    262 	IdentityProperties smithy.Properties
    263 	SignerProperties   smithy.Properties
    264 }
    265 
    266 func newResolvedAuthScheme(scheme smithyhttp.AuthScheme, option *smithyauth.Option) *resolvedAuthScheme {
    267 	return &resolvedAuthScheme{
    268 		Scheme:             scheme,
    269 		IdentityProperties: option.IdentityProperties,
    270 		SignerProperties:   option.SignerProperties,
    271 	}
    272 }
    273 
    274 func setResolvedAuthScheme(ctx context.Context, scheme *resolvedAuthScheme) context.Context {
    275 	return middleware.WithStackValue(ctx, resolvedAuthSchemeKey{}, scheme)
    276 }
    277 
    278 func getResolvedAuthScheme(ctx context.Context) *resolvedAuthScheme {
    279 	v, _ := middleware.GetStackValue(ctx, resolvedAuthSchemeKey{}).(*resolvedAuthScheme)
    280 	return v
    281 }
    282 
    283 type getIdentityMiddleware struct {
    284 	options Options
    285 }
    286 
    287 func (*getIdentityMiddleware) ID() string {
    288 	return "GetIdentity"
    289 }
    290 
    291 func (m *getIdentityMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
    292 	out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
    293 ) {
    294 	innerCtx, span := tracing.StartSpan(ctx, "GetIdentity")
    295 	defer span.End()
    296 
    297 	rscheme := getResolvedAuthScheme(innerCtx)
    298 	if rscheme == nil {
    299 		return out, metadata, fmt.Errorf("no resolved auth scheme")
    300 	}
    301 
    302 	resolver := rscheme.Scheme.IdentityResolver(m.options)
    303 	if resolver == nil {
    304 		return out, metadata, fmt.Errorf("no identity resolver")
    305 	}
    306 
    307 	identity, err := timeOperationMetric(ctx, "client.call.resolve_identity_duration",
    308 		func() (smithyauth.Identity, error) {
    309 			return resolver.GetIdentity(innerCtx, rscheme.IdentityProperties)
    310 		},
    311 		func(o *metrics.RecordMetricOptions) {
    312 			o.Properties.Set("auth.scheme_id", rscheme.Scheme.SchemeID())
    313 		})
    314 	if err != nil {
    315 		return out, metadata, fmt.Errorf("get identity: %w", err)
    316 	}
    317 
    318 	ctx = setIdentity(ctx, identity)
    319 
    320 	span.End()
    321 	return next.HandleFinalize(ctx, in)
    322 }
    323 
    324 type identityKey struct{}
    325 
    326 func setIdentity(ctx context.Context, identity smithyauth.Identity) context.Context {
    327 	return middleware.WithStackValue(ctx, identityKey{}, identity)
    328 }
    329 
    330 func getIdentity(ctx context.Context) smithyauth.Identity {
    331 	v, _ := middleware.GetStackValue(ctx, identityKey{}).(smithyauth.Identity)
    332 	return v
    333 }
    334 
    335 type signRequestMiddleware struct {
    336 	options Options
    337 }
    338 
    339 func (*signRequestMiddleware) ID() string {
    340 	return "Signing"
    341 }
    342 
    343 func (m *signRequestMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
    344 	out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
    345 ) {
    346 	_, span := tracing.StartSpan(ctx, "SignRequest")
    347 	defer span.End()
    348 
    349 	req, ok := in.Request.(*smithyhttp.Request)
    350 	if !ok {
    351 		return out, metadata, fmt.Errorf("unexpected transport type %T", in.Request)
    352 	}
    353 
    354 	rscheme := getResolvedAuthScheme(ctx)
    355 	if rscheme == nil {
    356 		return out, metadata, fmt.Errorf("no resolved auth scheme")
    357 	}
    358 
    359 	identity := getIdentity(ctx)
    360 	if identity == nil {
    361 		return out, metadata, fmt.Errorf("no identity")
    362 	}
    363 
    364 	signer := rscheme.Scheme.Signer()
    365 	if signer == nil {
    366 		return out, metadata, fmt.Errorf("no signer")
    367 	}
    368 
    369 	_, err = timeOperationMetric(ctx, "client.call.signing_duration", func() (any, error) {
    370 		return nil, signer.SignRequest(ctx, req, identity, rscheme.SignerProperties)
    371 	}, func(o *metrics.RecordMetricOptions) {
    372 		o.Properties.Set("auth.scheme_id", rscheme.Scheme.SchemeID())
    373 	})
    374 	if err != nil {
    375 		return out, metadata, fmt.Errorf("sign request: %w", err)
    376 	}
    377 
    378 	span.End()
    379 	return next.HandleFinalize(ctx, in)
    380 }