resolve_bearer_token.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package config
  2. import (
  3. "context"
  4. "fmt"
  5. "time"
  6. "github.com/aws/aws-sdk-go-v2/aws"
  7. "github.com/aws/aws-sdk-go-v2/credentials/ssocreds"
  8. "github.com/aws/aws-sdk-go-v2/service/ssooidc"
  9. smithybearer "github.com/aws/smithy-go/auth/bearer"
  10. )
  11. // resolveBearerAuthToken extracts a token provider from the config sources.
  12. //
  13. // If an explicit bearer authentication token provider is not found the
  14. // resolver will fallback to resolving token provider via other config sources
  15. // such as SharedConfig.
  16. func resolveBearerAuthToken(ctx context.Context, cfg *aws.Config, configs configs) error {
  17. found, err := resolveBearerAuthTokenProvider(ctx, cfg, configs)
  18. if found || err != nil {
  19. return err
  20. }
  21. return resolveBearerAuthTokenProviderChain(ctx, cfg, configs)
  22. }
  23. // resolveBearerAuthTokenProvider extracts the first instance of
  24. // BearerAuthTokenProvider from the config sources.
  25. //
  26. // The resolved BearerAuthTokenProvider will be wrapped in a cache to ensure
  27. // the Token is only refreshed when needed. This also protects the
  28. // TokenProvider so it can be used concurrently.
  29. //
  30. // Config providers used:
  31. // * bearerAuthTokenProviderProvider
  32. func resolveBearerAuthTokenProvider(ctx context.Context, cfg *aws.Config, configs configs) (bool, error) {
  33. tokenProvider, found, err := getBearerAuthTokenProvider(ctx, configs)
  34. if !found || err != nil {
  35. return false, err
  36. }
  37. cfg.BearerAuthTokenProvider, err = wrapWithBearerAuthTokenCache(
  38. ctx, configs, tokenProvider)
  39. if err != nil {
  40. return false, err
  41. }
  42. return true, nil
  43. }
  44. func resolveBearerAuthTokenProviderChain(ctx context.Context, cfg *aws.Config, configs configs) (err error) {
  45. _, sharedConfig, _ := getAWSConfigSources(configs)
  46. var provider smithybearer.TokenProvider
  47. if sharedConfig.SSOSession != nil {
  48. provider, err = resolveBearerAuthSSOTokenProvider(
  49. ctx, cfg, sharedConfig.SSOSession, configs)
  50. }
  51. if err == nil && provider != nil {
  52. cfg.BearerAuthTokenProvider, err = wrapWithBearerAuthTokenCache(
  53. ctx, configs, provider)
  54. }
  55. return err
  56. }
  57. func resolveBearerAuthSSOTokenProvider(ctx context.Context, cfg *aws.Config, session *SSOSession, configs configs) (*ssocreds.SSOTokenProvider, error) {
  58. ssoTokenProviderOptionsFn, found, err := getSSOTokenProviderOptions(ctx, configs)
  59. if err != nil {
  60. return nil, fmt.Errorf("failed to get SSOTokenProviderOptions from config sources, %w", err)
  61. }
  62. var optFns []func(*ssocreds.SSOTokenProviderOptions)
  63. if found {
  64. optFns = append(optFns, ssoTokenProviderOptionsFn)
  65. }
  66. cachePath, err := ssocreds.StandardCachedTokenFilepath(session.Name)
  67. if err != nil {
  68. return nil, fmt.Errorf("failed to get SSOTokenProvider's cache path, %w", err)
  69. }
  70. client := ssooidc.NewFromConfig(*cfg)
  71. provider := ssocreds.NewSSOTokenProvider(client, cachePath, optFns...)
  72. return provider, nil
  73. }
  74. // wrapWithBearerAuthTokenCache will wrap provider with an smithy-go
  75. // bearer/auth#TokenCache with the provided options if the provider is not
  76. // already a TokenCache.
  77. func wrapWithBearerAuthTokenCache(
  78. ctx context.Context,
  79. cfgs configs,
  80. provider smithybearer.TokenProvider,
  81. optFns ...func(*smithybearer.TokenCacheOptions),
  82. ) (smithybearer.TokenProvider, error) {
  83. _, ok := provider.(*smithybearer.TokenCache)
  84. if ok {
  85. return provider, nil
  86. }
  87. tokenCacheConfigOptions, optionsFound, err := getBearerAuthTokenCacheOptions(ctx, cfgs)
  88. if err != nil {
  89. return nil, err
  90. }
  91. opts := make([]func(*smithybearer.TokenCacheOptions), 0, 2+len(optFns))
  92. opts = append(opts, func(o *smithybearer.TokenCacheOptions) {
  93. o.RefreshBeforeExpires = 5 * time.Minute
  94. o.RetrieveBearerTokenTimeout = 30 * time.Second
  95. })
  96. opts = append(opts, optFns...)
  97. if optionsFound {
  98. opts = append(opts, tokenCacheConfigOptions)
  99. }
  100. return smithybearer.NewTokenCache(provider, opts...), nil
  101. }