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