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