1
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/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 "GetRoleCredentials": func(params *AuthResolverParameters) []*smithyauth.Option {
122 return []*smithyauth.Option{
123 {SchemeID: smithyauth.SchemeIDAnonymous},
124 }
125 },
126
127 "ListAccountRoles": func(params *AuthResolverParameters) []*smithyauth.Option {
128 return []*smithyauth.Option{
129 {SchemeID: smithyauth.SchemeIDAnonymous},
130 }
131 },
132
133 "ListAccounts": func(params *AuthResolverParameters) []*smithyauth.Option {
134 return []*smithyauth.Option{
135 {SchemeID: smithyauth.SchemeIDAnonymous},
136 }
137 },
138
139 "Logout": func(params *AuthResolverParameters) []*smithyauth.Option {
140 return []*smithyauth.Option{
141 {SchemeID: smithyauth.SchemeIDAnonymous},
142 }
143 },
144 }
145
146 func serviceAuthOptions(params *AuthResolverParameters) []*smithyauth.Option {
147 return []*smithyauth.Option{
148 {
149 SchemeID: smithyauth.SchemeIDSigV4,
150 SignerProperties: func() smithy.Properties {
151 var props smithy.Properties
152 smithyhttp.SetSigV4SigningName(&props, "awsssoportal")
153 smithyhttp.SetSigV4SigningRegion(&props, params.Region)
154 return props
155 }(),
156 },
157 }
158 }
159
160 type resolveAuthSchemeMiddleware struct {
161 operation string
162 options Options
163 }
164
165 func (*resolveAuthSchemeMiddleware) ID() string {
166 return "ResolveAuthScheme"
167 }
168
169 func (m *resolveAuthSchemeMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
170 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
171 ) {
172 params := bindAuthResolverParams(m.operation, getOperationInput(ctx), m.options)
173 options, err := m.options.AuthSchemeResolver.ResolveAuthSchemes(ctx, params)
174 if err != nil {
175 return out, metadata, fmt.Errorf("resolve auth scheme: %w", err)
176 }
177
178 scheme, ok := m.selectScheme(options)
179 if !ok {
180 return out, metadata, fmt.Errorf("could not select an auth scheme")
181 }
182
183 ctx = setResolvedAuthScheme(ctx, scheme)
184 return next.HandleFinalize(ctx, in)
185 }
186
187 func (m *resolveAuthSchemeMiddleware) selectScheme(options []*smithyauth.Option) (*resolvedAuthScheme, bool) {
188 for _, option := range options {
189 if option.SchemeID == smithyauth.SchemeIDAnonymous {
190 return newResolvedAuthScheme(smithyhttp.NewAnonymousScheme(), option), true
191 }
192
193 for _, scheme := range m.options.AuthSchemes {
194 if scheme.SchemeID() != option.SchemeID {
195 continue
196 }
197
198 if scheme.IdentityResolver(m.options) != nil {
199 return newResolvedAuthScheme(scheme, option), true
200 }
201 }
202 }
203
204 return nil, false
205 }
206
207 type resolvedAuthSchemeKey struct{}
208
209 type resolvedAuthScheme struct {
210 Scheme smithyhttp.AuthScheme
211 IdentityProperties smithy.Properties
212 SignerProperties smithy.Properties
213 }
214
215 func newResolvedAuthScheme(scheme smithyhttp.AuthScheme, option *smithyauth.Option) *resolvedAuthScheme {
216 return &resolvedAuthScheme{
217 Scheme: scheme,
218 IdentityProperties: option.IdentityProperties,
219 SignerProperties: option.SignerProperties,
220 }
221 }
222
223 func setResolvedAuthScheme(ctx context.Context, scheme *resolvedAuthScheme) context.Context {
224 return middleware.WithStackValue(ctx, resolvedAuthSchemeKey{}, scheme)
225 }
226
227 func getResolvedAuthScheme(ctx context.Context) *resolvedAuthScheme {
228 v, _ := middleware.GetStackValue(ctx, resolvedAuthSchemeKey{}).(*resolvedAuthScheme)
229 return v
230 }
231
232 type getIdentityMiddleware struct {
233 options Options
234 }
235
236 func (*getIdentityMiddleware) ID() string {
237 return "GetIdentity"
238 }
239
240 func (m *getIdentityMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
241 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
242 ) {
243 rscheme := getResolvedAuthScheme(ctx)
244 if rscheme == nil {
245 return out, metadata, fmt.Errorf("no resolved auth scheme")
246 }
247
248 resolver := rscheme.Scheme.IdentityResolver(m.options)
249 if resolver == nil {
250 return out, metadata, fmt.Errorf("no identity resolver")
251 }
252
253 identity, err := resolver.GetIdentity(ctx, rscheme.IdentityProperties)
254 if err != nil {
255 return out, metadata, fmt.Errorf("get identity: %w", err)
256 }
257
258 ctx = setIdentity(ctx, identity)
259 return next.HandleFinalize(ctx, in)
260 }
261
262 type identityKey struct{}
263
264 func setIdentity(ctx context.Context, identity smithyauth.Identity) context.Context {
265 return middleware.WithStackValue(ctx, identityKey{}, identity)
266 }
267
268 func getIdentity(ctx context.Context) smithyauth.Identity {
269 v, _ := middleware.GetStackValue(ctx, identityKey{}).(smithyauth.Identity)
270 return v
271 }
272
273 type signRequestMiddleware struct {
274 }
275
276 func (*signRequestMiddleware) ID() string {
277 return "Signing"
278 }
279
280 func (m *signRequestMiddleware) HandleFinalize(ctx context.Context, in middleware.FinalizeInput, next middleware.FinalizeHandler) (
281 out middleware.FinalizeOutput, metadata middleware.Metadata, err error,
282 ) {
283 req, ok := in.Request.(*smithyhttp.Request)
284 if !ok {
285 return out, metadata, fmt.Errorf("unexpected transport type %T", in.Request)
286 }
287
288 rscheme := getResolvedAuthScheme(ctx)
289 if rscheme == nil {
290 return out, metadata, fmt.Errorf("no resolved auth scheme")
291 }
292
293 identity := getIdentity(ctx)
294 if identity == nil {
295 return out, metadata, fmt.Errorf("no identity")
296 }
297
298 signer := rscheme.Scheme.Signer()
299 if signer == nil {
300 return out, metadata, fmt.Errorf("no signer")
301 }
302
303 if err := signer.SignRequest(ctx, req, identity, rscheme.SignerProperties); err != nil {
304 return out, metadata, fmt.Errorf("sign request: %w", err)
305 }
306
307 return next.HandleFinalize(ctx, in)
308 }
309
View as plain text