1
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/middleware"
12 smithyhttp "github.com/aws/smithy-go/transport/http"
13 )
14
15 func bindAuthParamsRegion(params *AuthResolverParameters, _ interface{}, options Options) {
16 params.Region = options.Region
17 }
18
19 type setLegacyContextSigningOptionsMiddleware struct {
20 }
21
22 func (*setLegacyContextSigningOptionsMiddleware) ID() string {
23 return "setLegacyContextSigningOptions"
24 }
25
26 func (m *setLegacyContextSigningOptionsMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
27 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
28 ) {
29 rscheme := getResolvedAuthScheme(ctx)
30 schemeID := rscheme.Scheme.SchemeID()
31
32 if sn := awsmiddleware.GetSigningName(ctx); sn != "" {
33 if schemeID == "aws.auth#sigv4" {
34 smithyhttp.SetSigV4SigningName(&rscheme.SignerProperties, sn)
35 } else if schemeID == "aws.auth#sigv4a" {
36 smithyhttp.SetSigV4ASigningName(&rscheme.SignerProperties, sn)
37 }
38 }
39
40 if sr := awsmiddleware.GetSigningRegion(ctx); sr != "" {
41 if schemeID == "aws.auth#sigv4" {
42 smithyhttp.SetSigV4SigningRegion(&rscheme.SignerProperties, sr)
43 } else if schemeID == "aws.auth#sigv4a" {
44 smithyhttp.SetSigV4ASigningRegions(&rscheme.SignerProperties, []string{sr})
45 }
46 }
47
48 return next.HandleFinalize(ctx, in)
49 }
50
51 func addSetLegacyContextSigningOptionsMiddleware(stack *middleware.Stack) error {
52 return stack.Finalize.Insert(&setLegacyContextSigningOptionsMiddleware{}, "Signing", middleware.Before)
53 }
54
55 type withAnonymous struct {
56 resolver AuthSchemeResolver
57 }
58
59 var _ AuthSchemeResolver = (*withAnonymous)(nil)
60
61 func (v *withAnonymous) ResolveAuthSchemes(ctx context.Context, params *AuthResolverParameters) ([]*smithyauth.Option, error) {
62 opts, err := v.resolver.ResolveAuthSchemes(ctx, params)
63 if err != nil {
64 return nil, err
65 }
66
67 opts = append(opts, &smithyauth.Option{
68 SchemeID: smithyauth.SchemeIDAnonymous,
69 })
70 return opts, nil
71 }
72
73 func wrapWithAnonymousAuth(options *Options) {
74 if _, ok := options.AuthSchemeResolver.(*defaultAuthSchemeResolver); !ok {
75 return
76 }
77
78 options.AuthSchemeResolver = &withAnonymous{
79 resolver: options.AuthSchemeResolver,
80 }
81 }
82
83
84
85 type AuthResolverParameters struct {
86
87 Operation string
88
89
90 Region string
91 }
92
93 func bindAuthResolverParams(operation string, input interface{}, options Options) *AuthResolverParameters {
94 params := &AuthResolverParameters{
95 Operation: operation,
96 }
97
98 bindAuthParamsRegion(params, input, options)
99
100 return params
101 }
102
103
104
105 type AuthSchemeResolver interface {
106 ResolveAuthSchemes(context.Context, *AuthResolverParameters) ([]*smithyauth.Option, error)
107 }
108
109 type defaultAuthSchemeResolver struct{}
110
111 var _ AuthSchemeResolver = (*defaultAuthSchemeResolver)(nil)
112
113 func (*defaultAuthSchemeResolver) ResolveAuthSchemes(ctx context.Context, params *AuthResolverParameters) ([]*smithyauth.Option, error) {
114 if overrides, ok := operationAuthOptions[params.Operation]; ok {
115 return overrides(params), nil
116 }
117 return serviceAuthOptions(params), nil
118 }
119
120 var operationAuthOptions = map[string]func(*AuthResolverParameters) []*smithyauth.Option{
121 "AssumeRoleWithSAML": func(params *AuthResolverParameters) []*smithyauth.Option {
122 return []*smithyauth.Option{
123 {SchemeID: smithyauth.SchemeIDAnonymous},
124 }
125 },
126
127 "AssumeRoleWithWebIdentity": func(params *AuthResolverParameters) []*smithyauth.Option {
128 return []*smithyauth.Option{
129 {SchemeID: smithyauth.SchemeIDAnonymous},
130 }
131 },
132 }
133
134 func serviceAuthOptions(params *AuthResolverParameters) []*smithyauth.Option {
135 return []*smithyauth.Option{
136 {
137 SchemeID: smithyauth.SchemeIDSigV4,
138 SignerProperties: func() smithy.Properties {
139 var props smithy.Properties
140 smithyhttp.SetSigV4SigningName(&props, "sts")
141 smithyhttp.SetSigV4SigningRegion(&props, params.Region)
142 return props
143 }(),
144 },
145 }
146 }
147
148 type resolveAuthSchemeMiddleware struct {
149 operation string
150 options Options
151 }
152
153 func (*resolveAuthSchemeMiddleware) ID() string {
154 return "ResolveAuthScheme"
155 }
156
157 func (m *resolveAuthSchemeMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
158 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
159 ) {
160 params := bindAuthResolverParams(m.operation, getOperationInput(ctx), m.options)
161 options, err := m.options.AuthSchemeResolver.ResolveAuthSchemes(ctx, params)
162 if err != nil {
163 return out, metadata, fmt.Errorf("resolve auth scheme: %w", err)
164 }
165
166 scheme, ok := m.selectScheme(options)
167 if !ok {
168 return out, metadata, fmt.Errorf("could not select an auth scheme")
169 }
170
171 ctx = setResolvedAuthScheme(ctx, scheme)
172 return next.HandleFinalize(ctx, in)
173 }
174
175 func (m *resolveAuthSchemeMiddleware) selectScheme(options []*smithyauth.Option) (*resolvedAuthScheme, bool) {
176 for _, option := range options {
177 if option.SchemeID == smithyauth.SchemeIDAnonymous {
178 return newResolvedAuthScheme(smithyhttp.NewAnonymousScheme(), option), true
179 }
180
181 for _, scheme := range m.options.AuthSchemes {
182 if scheme.SchemeID() != option.SchemeID {
183 continue
184 }
185
186 if scheme.IdentityResolver(m.options) != nil {
187 return newResolvedAuthScheme(scheme, option), true
188 }
189 }
190 }
191
192 return nil, false
193 }
194
195 type resolvedAuthSchemeKey struct{}
196
197 type resolvedAuthScheme struct {
198 Scheme smithyhttp.AuthScheme
199 IdentityProperties smithy.Properties
200 SignerProperties smithy.Properties
201 }
202
203 func newResolvedAuthScheme(scheme smithyhttp.AuthScheme, option *smithyauth.Option) *resolvedAuthScheme {
204 return &resolvedAuthScheme{
205 Scheme: scheme,
206 IdentityProperties: option.IdentityProperties,
207 SignerProperties: option.SignerProperties,
208 }
209 }
210
211 func setResolvedAuthScheme(ctx context.Context, scheme *resolvedAuthScheme) context.Context {
212 return middleware.WithStackValue(ctx, resolvedAuthSchemeKey{}, scheme)
213 }
214
215 func getResolvedAuthScheme(ctx context.Context) *resolvedAuthScheme {
216 v, _ := middleware.GetStackValue(ctx, resolvedAuthSchemeKey{}).(*resolvedAuthScheme)
217 return v
218 }
219
220 type getIdentityMiddleware struct {
221 options Options
222 }
223
224 func (*getIdentityMiddleware) ID() string {
225 return "GetIdentity"
226 }
227
228 func (m *getIdentityMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
229 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
230 ) {
231 rscheme := getResolvedAuthScheme(ctx)
232 if rscheme == nil {
233 return out, metadata, fmt.Errorf("no resolved auth scheme")
234 }
235
236 resolver := rscheme.Scheme.IdentityResolver(m.options)
237 if resolver == nil {
238 return out, metadata, fmt.Errorf("no identity resolver")
239 }
240
241 identity, err := resolver.GetIdentity(ctx, rscheme.IdentityProperties)
242 if err != nil {
243 return out, metadata, fmt.Errorf("get identity: %w", err)
244 }
245
246 ctx = setIdentity(ctx, identity)
247 return next.HandleFinalize(ctx, in)
248 }
249
250 type identityKey struct{}
251
252 func setIdentity(ctx context.Context, identity smithyauth.Identity) context.Context {
253 return middleware.WithStackValue(ctx, identityKey{}, identity)
254 }
255
256 func getIdentity(ctx context.Context) smithyauth.Identity {
257 v, _ := middleware.GetStackValue(ctx, identityKey{}).(smithyauth.Identity)
258 return v
259 }
260
261 type signRequestMiddleware struct {
262 }
263
264 func (*signRequestMiddleware) ID() string {
265 return "Signing"
266 }
267
268 func (m *signRequestMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
269 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
270 ) {
271 req, ok := in.Request.(*smithyhttp.Request)
272 if !ok {
273 return out, metadata, fmt.Errorf("unexpected transport type %T", in.Request)
274 }
275
276 rscheme := getResolvedAuthScheme(ctx)
277 if rscheme == nil {
278 return out, metadata, fmt.Errorf("no resolved auth scheme")
279 }
280
281 identity := getIdentity(ctx)
282 if identity == nil {
283 return out, metadata, fmt.Errorf("no identity")
284 }
285
286 signer := rscheme.Scheme.Signer()
287 if signer == nil {
288 return out, metadata, fmt.Errorf("no signer")
289 }
290
291 if err := signer.SignRequest(ctx, req, identity, rscheme.SignerProperties); err != nil {
292 return out, metadata, fmt.Errorf("sign request: %w", err)
293 }
294
295 return next.HandleFinalize(ctx, in)
296 }
297
View as plain text