auth.go raw
1 // Code generated by smithy-go-codegen DO NOT EDIT.
2
3 package sts
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 "AssumeRoleWithSAML": func(params *AuthResolverParameters) []*smithyauth.Option {
129 return []*smithyauth.Option{
130 {SchemeID: smithyauth.SchemeIDAnonymous},
131 }
132 },
133
134 "AssumeRoleWithWebIdentity": func(params *AuthResolverParameters) []*smithyauth.Option {
135 return []*smithyauth.Option{
136 {SchemeID: smithyauth.SchemeIDAnonymous},
137 }
138 },
139 }
140
141 func serviceAuthOptions(params *AuthResolverParameters) []*smithyauth.Option {
142 return []*smithyauth.Option{
143 {
144 SchemeID: smithyauth.SchemeIDSigV4,
145 SignerProperties: func() smithy.Properties {
146 var props smithy.Properties
147 smithyhttp.SetSigV4SigningName(&props, "sts")
148 smithyhttp.SetSigV4SigningRegion(&props, params.Region)
149 return props
150 }(),
151 },
152 }
153 }
154
155 type resolveAuthSchemeMiddleware struct {
156 operation string
157 options Options
158 }
159
160 func (*resolveAuthSchemeMiddleware) ID() string {
161 return "ResolveAuthScheme"
162 }
163
164 func (m *resolveAuthSchemeMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
165 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
166 ) {
167 _, span := tracing.StartSpan(ctx, "ResolveAuthScheme")
168 defer span.End()
169
170 params, err := bindAuthResolverParams(ctx, m.operation, getOperationInput(ctx), m.options)
171 if err != nil {
172 return out, metadata, fmt.Errorf("bind auth scheme params: %w", err)
173 }
174 options, err := m.options.AuthSchemeResolver.ResolveAuthSchemes(ctx, params)
175 if err != nil {
176 return out, metadata, fmt.Errorf("resolve auth scheme: %w", err)
177 }
178
179 scheme, ok := m.selectScheme(options)
180 if !ok {
181 return out, metadata, fmt.Errorf("could not select an auth scheme")
182 }
183
184 ctx = setResolvedAuthScheme(ctx, scheme)
185
186 span.SetProperty("auth.scheme_id", scheme.Scheme.SchemeID())
187 span.End()
188 return next.HandleFinalize(ctx, in)
189 }
190
191 func (m *resolveAuthSchemeMiddleware) selectScheme(options []*smithyauth.Option) (*resolvedAuthScheme, bool) {
192 sorted := sortAuthOptions(options, m.options.AuthSchemePreference)
193 for _, option := range sorted {
194 if option.SchemeID == smithyauth.SchemeIDAnonymous {
195 return newResolvedAuthScheme(smithyhttp.NewAnonymousScheme(), option), true
196 }
197
198 for _, scheme := range m.options.AuthSchemes {
199 if scheme.SchemeID() != option.SchemeID {
200 continue
201 }
202
203 if scheme.IdentityResolver(m.options) != nil {
204 return newResolvedAuthScheme(scheme, option), true
205 }
206 }
207 }
208
209 return nil, false
210 }
211
212 func sortAuthOptions(options []*smithyauth.Option, preferred []string) []*smithyauth.Option {
213 byPriority := make([]*smithyauth.Option, 0, len(options))
214 for _, prefName := range preferred {
215 for _, option := range options {
216 optName := option.SchemeID
217 if parts := strings.Split(option.SchemeID, "#"); len(parts) == 2 {
218 optName = parts[1]
219 }
220 if prefName == optName {
221 byPriority = append(byPriority, option)
222 }
223 }
224 }
225 for _, option := range options {
226 if !slices.ContainsFunc(byPriority, func(o *smithyauth.Option) bool {
227 return o.SchemeID == option.SchemeID
228 }) {
229 byPriority = append(byPriority, option)
230 }
231 }
232 return byPriority
233 }
234
235 type resolvedAuthSchemeKey struct{}
236
237 type resolvedAuthScheme struct {
238 Scheme smithyhttp.AuthScheme
239 IdentityProperties smithy.Properties
240 SignerProperties smithy.Properties
241 }
242
243 func newResolvedAuthScheme(scheme smithyhttp.AuthScheme, option *smithyauth.Option) *resolvedAuthScheme {
244 return &resolvedAuthScheme{
245 Scheme: scheme,
246 IdentityProperties: option.IdentityProperties,
247 SignerProperties: option.SignerProperties,
248 }
249 }
250
251 func setResolvedAuthScheme(ctx context.Context, scheme *resolvedAuthScheme) context.Context {
252 return middleware.WithStackValue(ctx, resolvedAuthSchemeKey{}, scheme)
253 }
254
255 func getResolvedAuthScheme(ctx context.Context) *resolvedAuthScheme {
256 v, _ := middleware.GetStackValue(ctx, resolvedAuthSchemeKey{}).(*resolvedAuthScheme)
257 return v
258 }
259
260 type getIdentityMiddleware struct {
261 options Options
262 }
263
264 func (*getIdentityMiddleware) ID() string {
265 return "GetIdentity"
266 }
267
268 func (m *getIdentityMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
269 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
270 ) {
271 innerCtx, span := tracing.StartSpan(ctx, "GetIdentity")
272 defer span.End()
273
274 rscheme := getResolvedAuthScheme(innerCtx)
275 if rscheme == nil {
276 return out, metadata, fmt.Errorf("no resolved auth scheme")
277 }
278
279 resolver := rscheme.Scheme.IdentityResolver(m.options)
280 if resolver == nil {
281 return out, metadata, fmt.Errorf("no identity resolver")
282 }
283
284 identity, err := timeOperationMetric(ctx, "client.call.resolve_identity_duration",
285 func() (smithyauth.Identity, error) {
286 return resolver.GetIdentity(innerCtx, rscheme.IdentityProperties)
287 },
288 func(o *metrics.RecordMetricOptions) {
289 o.Properties.Set("auth.scheme_id", rscheme.Scheme.SchemeID())
290 })
291 if err != nil {
292 return out, metadata, fmt.Errorf("get identity: %w", err)
293 }
294
295 ctx = setIdentity(ctx, identity)
296
297 span.End()
298 return next.HandleFinalize(ctx, in)
299 }
300
301 type identityKey struct{}
302
303 func setIdentity(ctx context.Context, identity smithyauth.Identity) context.Context {
304 return middleware.WithStackValue(ctx, identityKey{}, identity)
305 }
306
307 func getIdentity(ctx context.Context) smithyauth.Identity {
308 v, _ := middleware.GetStackValue(ctx, identityKey{}).(smithyauth.Identity)
309 return v
310 }
311
312 type signRequestMiddleware struct {
313 options Options
314 }
315
316 func (*signRequestMiddleware) ID() string {
317 return "Signing"
318 }
319
320 func (m *signRequestMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
321 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
322 ) {
323 _, span := tracing.StartSpan(ctx, "SignRequest")
324 defer span.End()
325
326 req, ok := in.Request.(*smithyhttp.Request)
327 if !ok {
328 return out, metadata, fmt.Errorf("unexpected transport type %T", in.Request)
329 }
330
331 rscheme := getResolvedAuthScheme(ctx)
332 if rscheme == nil {
333 return out, metadata, fmt.Errorf("no resolved auth scheme")
334 }
335
336 identity := getIdentity(ctx)
337 if identity == nil {
338 return out, metadata, fmt.Errorf("no identity")
339 }
340
341 signer := rscheme.Scheme.Signer()
342 if signer == nil {
343 return out, metadata, fmt.Errorf("no signer")
344 }
345
346 _, err = timeOperationMetric(ctx, "client.call.signing_duration", func() (any, error) {
347 return nil, signer.SignRequest(ctx, req, identity, rscheme.SignerProperties)
348 }, func(o *metrics.RecordMetricOptions) {
349 o.Properties.Set("auth.scheme_id", rscheme.Scheme.SchemeID())
350 })
351 if err != nil {
352 return out, metadata, fmt.Errorf("sign request: %w", err)
353 }
354
355 span.End()
356 return next.HandleFinalize(ctx, in)
357 }
358