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 }