chain_provider.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. package credentials
  2. import (
  3. "github.com/ks3sdklib/aws-sdk-go/internal/apierr"
  4. )
  5. var (
  6. // ErrNoValidProvidersFoundInChain Is returned when there are no valid
  7. // providers in the ChainProvider.
  8. ErrNoValidProvidersFoundInChain = apierr.New("NoCredentialProviders", "no valid providers in chain", nil)
  9. )
  10. // A ChainProvider will search for a provider which returns credentials
  11. // and cache that provider until Retrieve is called again.
  12. //
  13. // The ChainProvider provides a way of chaining multiple providers together
  14. // which will pick the first available using priority order of the Providers
  15. // in the list.
  16. //
  17. // If none of the Providers retrieve valid credentials Value, ChainProvider's
  18. // Retrieve() will return the error ErrNoValidProvidersFoundInChain.
  19. //
  20. // If a Provider is found which returns valid credentials Value ChainProvider
  21. // will cache that Provider for all calls to IsExpired(), until Retrieve is
  22. // called again.
  23. //
  24. // Example of ChainProvider to be used with an EnvProvider and EC2RoleProvider.
  25. // In this example EnvProvider will first check if any credentials are available
  26. // vai the environment variables. If there are none ChainProvider will check
  27. // the next Provider in the list, EC2RoleProvider in this case. If EC2RoleProvider
  28. // does not return any credentials ChainProvider will return the error
  29. // ErrNoValidProvidersFoundInChain
  30. //
  31. // creds := NewChainCredentials(
  32. // []Provider{
  33. // &EnvProvider{},
  34. // &EC2RoleProvider{},
  35. // })
  36. // creds.Retrieve()
  37. //
  38. type ChainProvider struct {
  39. Providers []Provider
  40. curr Provider
  41. }
  42. // NewChainCredentials returns a pointer to a new Credentials object
  43. // wrapping a chain of providers.
  44. func NewChainCredentials(providers []Provider) *Credentials {
  45. return NewCredentials(&ChainProvider{
  46. Providers: append([]Provider{}, providers...),
  47. })
  48. }
  49. // Retrieve returns the credentials value or error if no provider returned
  50. // without error.
  51. //
  52. // If a provider is found it will be cached and any calls to IsExpired()
  53. // will return the expired state of the cached provider.
  54. func (c *ChainProvider) Retrieve() (Value, error) {
  55. for _, p := range c.Providers {
  56. if creds, err := p.Retrieve(); err == nil {
  57. c.curr = p
  58. return creds, nil
  59. }
  60. }
  61. c.curr = nil
  62. // TODO better error reporting. maybe report error for each failed retrieve?
  63. return Value{}, ErrNoValidProvidersFoundInChain
  64. }
  65. // IsExpired will returned the expired state of the currently cached provider
  66. // if there is one. If there is no current provider, true will be returned.
  67. func (c *ChainProvider) IsExpired() bool {
  68. if c.curr != nil {
  69. return c.curr.IsExpired()
  70. }
  71. return true
  72. }