1 // Package credentials provides credential retrieval and management
3 // The Credentials is the primary method of getting access to and managing
4 // credentials Values. Using dependency injection retrieval of the credential
5 // values is handled by a object which satisfies the Provider interface.
7 // By default the Credentials.Get() will cache the successful result of a
8 // Provider's Retrieve() until Provider.IsExpired() returns true. At which
9 // point Credentials will call Provider's Retrieve() to get new credential Value.
11 // The Provider is responsible for determining when credentials Value have expired.
12 // It is also important to note that Credentials will always call Retrieve the
13 // first time Credentials.Get() is called.
15 // Example of using the environment variable credentials.
17 // creds := credentials.NewEnvCredentials()
19 // // Retrieve the credentials value
20 // credValue, err := creds.Get()
25 // Example of forcing credentials to expire and be refreshed on the next Get().
26 // This may be helpful to proactively expire credentials and refresh them sooner
27 // than they would naturally expire on their own.
29 // creds := credentials.NewCredentials(&ec2rolecreds.EC2RoleProvider{})
31 // credsValue, err := creds.Get()
32 // // New credentials will be retrieved instead of from cache.
37 // Each Provider built into this package also provides a helper method to generate
38 // a Credentials pointer setup with the provider. To use a custom Provider just
39 // create a type which satisfies the Provider interface and pass it to the
40 // NewCredentials method.
42 // type MyProvider struct{}
43 // func (m *MyProvider) Retrieve() (Value, error) {...}
44 // func (m *MyProvider) IsExpired() bool {...}
46 // creds := credentials.NewCredentials(&MyProvider{})
47 // credValue, err := creds.Get()
53 "github.com/aws/aws-sdk-go/aws/awserr"
58 // AnonymousCredentials is an empty Credential object that can be used as
59 // dummy placeholder credentials for requests that do not need signed.
61 // This Credentials can be used to configure a service to not sign requests
62 // when making service API calls. For example, when accessing public
65 // svc := s3.New(session.Must(session.NewSession(&aws.Config{
66 // Credentials: credentials.AnonymousCredentials,
68 // // Access public S3 buckets.
69 var AnonymousCredentials = NewStaticCredentials("", "", "")
71 // A Value is the AWS credentials value for individual credential fields.
76 // AWS Secret Access Key
77 SecretAccessKey string
82 // Provider used to get credentials
86 // A Provider is the interface for any component which will provide credentials
87 // Value. A provider is required to manage its own Expired state, and what to
90 // The Provider should not need to implement its own mutexes, because
91 // that will be managed by Credentials.
92 type Provider interface {
93 // Retrieve returns nil if it successfully retrieved the value.
94 // Error is returned if the value were not obtainable, or empty.
95 Retrieve() (Value, error)
97 // IsExpired returns if the credentials are no longer valid, and need
102 // An Expirer is an interface that Providers can implement to expose the expiration
103 // time, if known. If the Provider cannot accurately provide this info,
104 // it should not implement this interface.
105 type Expirer interface {
106 // The time at which the credentials are no longer valid
107 ExpiresAt() time.Time
110 // An ErrorProvider is a stub credentials provider that always returns an error
111 // this is used by the SDK when construction a known provider is not possible
113 type ErrorProvider struct {
114 // The error to be returned from Retrieve
117 // The provider name to set on the Retrieved returned Value
121 // Retrieve will always return the error that the ErrorProvider was created with.
122 func (p ErrorProvider) Retrieve() (Value, error) {
123 return Value{ProviderName: p.ProviderName}, p.Err
126 // IsExpired will always return not expired.
127 func (p ErrorProvider) IsExpired() bool {
131 // A Expiry provides shared expiration logic to be used by credentials
132 // providers to implement expiry functionality.
134 // The best method to use this struct is as an anonymous field within the
135 // provider's struct.
138 // type EC2RoleProvider struct {
143 // The date/time when to expire on
146 // If set will be used by IsExpired to determine the current time.
147 // Defaults to time.Now if CurrentTime is not set. Available for testing
148 // to be able to mock out the current time.
149 CurrentTime func() time.Time
152 // SetExpiration sets the expiration IsExpired will check when called.
154 // If window is greater than 0 the expiration time will be reduced by the
157 // Using a window is helpful to trigger credentials to expire sooner than
158 // the expiration time given to ensure no requests are made with expired
160 func (e *Expiry) SetExpiration(expiration time.Time, window time.Duration) {
161 e.expiration = expiration
163 e.expiration = e.expiration.Add(-window)
167 // IsExpired returns if the credentials are expired.
168 func (e *Expiry) IsExpired() bool {
169 curTime := e.CurrentTime
173 return e.expiration.Before(curTime())
176 // ExpiresAt returns the expiration time of the credential
177 func (e *Expiry) ExpiresAt() time.Time {
181 // A Credentials provides concurrency safe retrieval of AWS credentials Value.
182 // Credentials will cache the credentials value until they expire. Once the value
183 // expires the next Get will attempt to retrieve valid credentials.
185 // Credentials is safe to use across multiple goroutines and will manage the
186 // synchronous state so the Providers do not need to implement their own
189 // The first Credentials.Get() will always call Provider.Retrieve() to get the
190 // first instance of the credentials Value. All calls to Get() after that
191 // will return the cached credentials Value until IsExpired() returns true.
192 type Credentials struct {
201 // NewCredentials returns a pointer to a new Credentials with the provider set.
202 func NewCredentials(provider Provider) *Credentials {
209 // Get returns the credentials value, or error if the credentials Value failed
212 // Will return the cached credentials Value if it has not expired. If the
213 // credentials Value has expired the Provider's Retrieve() will be called
214 // to refresh the credentials.
216 // If Credentials.Expire() was called the credentials Value will be force
217 // expired, and the next call to Get() will cause them to be refreshed.
218 func (c *Credentials) Get() (Value, error) {
219 // Check the cached credentials first with just the read lock.
228 // Credentials are expired need to retrieve the credentials taking the full
234 creds, err := c.provider.Retrieve()
239 c.forceRefresh = false
245 // Expire expires the credentials and forces them to be retrieved on the
246 // next call to Get().
248 // This will override the Provider's expired state, and force Credentials
249 // to call the Provider's Retrieve().
250 func (c *Credentials) Expire() {
254 c.forceRefresh = true
257 // IsExpired returns if the credentials are no longer valid, and need
260 // If the Credentials were forced to be expired with Expire() this will
261 // reflect that override.
262 func (c *Credentials) IsExpired() bool {
269 // isExpired helper method wrapping the definition of expired credentials.
270 func (c *Credentials) isExpired() bool {
271 return c.forceRefresh || c.provider.IsExpired()
274 // ExpiresAt provides access to the functionality of the Expirer interface of
275 // the underlying Provider, if it supports that interface. Otherwise, it returns
277 func (c *Credentials) ExpiresAt() (time.Time, error) {
281 expirer, ok := c.provider.(Expirer)
283 return time.Time{}, awserr.New("ProviderNotExpirer",
284 fmt.Sprintf("provider %s does not support ExpiresAt()", c.creds.ProviderName),
288 // set expiration time to the distant past
289 return time.Time{}, nil
291 return expirer.ExpiresAt(), nil