]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go
Merge branch 'fix_read_test' of github.com:alexandreFre/terraform-provider-statuscake
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / aws / aws-sdk-go / aws / credentials / credentials.go
CommitLineData
bae9f6d2
JC
1// Package credentials provides credential retrieval and management
2//
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.
6//
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.
10//
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.
14//
15// Example of using the environment variable credentials.
16//
17// creds := credentials.NewEnvCredentials()
18//
19// // Retrieve the credentials value
20// credValue, err := creds.Get()
21// if err != nil {
22// // handle error
23// }
24//
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.
28//
29// creds := credentials.NewCredentials(&ec2rolecreds.EC2RoleProvider{})
30// creds.Expire()
31// credsValue, err := creds.Get()
32// // New credentials will be retrieved instead of from cache.
33//
34//
35// Custom Provider
36//
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.
41//
42// type MyProvider struct{}
43// func (m *MyProvider) Retrieve() (Value, error) {...}
44// func (m *MyProvider) IsExpired() bool {...}
45//
46// creds := credentials.NewCredentials(&MyProvider{})
47// credValue, err := creds.Get()
48//
49package credentials
50
51import (
107c1cdb
ND
52 "fmt"
53 "github.com/aws/aws-sdk-go/aws/awserr"
bae9f6d2
JC
54 "sync"
55 "time"
56)
57
58// AnonymousCredentials is an empty Credential object that can be used as
59// dummy placeholder credentials for requests that do not need signed.
60//
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
63// s3 buckets.
64//
65// svc := s3.New(session.Must(session.NewSession(&aws.Config{
66// Credentials: credentials.AnonymousCredentials,
67// })))
68// // Access public S3 buckets.
bae9f6d2
JC
69var AnonymousCredentials = NewStaticCredentials("", "", "")
70
71// A Value is the AWS credentials value for individual credential fields.
72type Value struct {
73 // AWS Access key ID
74 AccessKeyID string
75
76 // AWS Secret Access Key
77 SecretAccessKey string
78
79 // AWS Session Token
80 SessionToken string
81
82 // Provider used to get credentials
83 ProviderName string
84}
85
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
88// be expired means.
89//
90// The Provider should not need to implement its own mutexes, because
91// that will be managed by Credentials.
92type 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)
96
97 // IsExpired returns if the credentials are no longer valid, and need
98 // to be retrieved.
99 IsExpired() bool
100}
101
107c1cdb
ND
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.
105type Expirer interface {
106 // The time at which the credentials are no longer valid
107 ExpiresAt() time.Time
108}
109
bae9f6d2
JC
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
112// due to an error.
113type ErrorProvider struct {
114 // The error to be returned from Retrieve
115 Err error
116
117 // The provider name to set on the Retrieved returned Value
118 ProviderName string
119}
120
121// Retrieve will always return the error that the ErrorProvider was created with.
122func (p ErrorProvider) Retrieve() (Value, error) {
123 return Value{ProviderName: p.ProviderName}, p.Err
124}
125
126// IsExpired will always return not expired.
127func (p ErrorProvider) IsExpired() bool {
128 return false
129}
130
131// A Expiry provides shared expiration logic to be used by credentials
132// providers to implement expiry functionality.
133//
134// The best method to use this struct is as an anonymous field within the
135// provider's struct.
136//
137// Example:
138// type EC2RoleProvider struct {
139// Expiry
140// ...
141// }
142type Expiry struct {
143 // The date/time when to expire on
144 expiration time.Time
145
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
150}
151
152// SetExpiration sets the expiration IsExpired will check when called.
153//
154// If window is greater than 0 the expiration time will be reduced by the
155// window value.
156//
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
159// tokens.
160func (e *Expiry) SetExpiration(expiration time.Time, window time.Duration) {
161 e.expiration = expiration
162 if window > 0 {
163 e.expiration = e.expiration.Add(-window)
164 }
165}
166
167// IsExpired returns if the credentials are expired.
168func (e *Expiry) IsExpired() bool {
107c1cdb
ND
169 curTime := e.CurrentTime
170 if curTime == nil {
171 curTime = time.Now
bae9f6d2 172 }
107c1cdb 173 return e.expiration.Before(curTime())
bae9f6d2
JC
174}
175
107c1cdb
ND
176// ExpiresAt returns the expiration time of the credential
177func (e *Expiry) ExpiresAt() time.Time {
178 return e.expiration
179}
180
181// A Credentials provides concurrency safe retrieval of AWS credentials Value.
bae9f6d2
JC
182// Credentials will cache the credentials value until they expire. Once the value
183// expires the next Get will attempt to retrieve valid credentials.
184//
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
187// synchronization.
188//
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.
192type Credentials struct {
193 creds Value
194 forceRefresh bool
15c0b25d
AP
195
196 m sync.RWMutex
bae9f6d2
JC
197
198 provider Provider
199}
200
201// NewCredentials returns a pointer to a new Credentials with the provider set.
202func NewCredentials(provider Provider) *Credentials {
203 return &Credentials{
204 provider: provider,
205 forceRefresh: true,
206 }
207}
208
209// Get returns the credentials value, or error if the credentials Value failed
210// to be retrieved.
211//
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.
215//
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.
218func (c *Credentials) Get() (Value, error) {
15c0b25d
AP
219 // Check the cached credentials first with just the read lock.
220 c.m.RLock()
221 if !c.isExpired() {
222 creds := c.creds
223 c.m.RUnlock()
224 return creds, nil
225 }
226 c.m.RUnlock()
227
228 // Credentials are expired need to retrieve the credentials taking the full
229 // lock.
bae9f6d2
JC
230 c.m.Lock()
231 defer c.m.Unlock()
232
233 if c.isExpired() {
234 creds, err := c.provider.Retrieve()
235 if err != nil {
236 return Value{}, err
237 }
238 c.creds = creds
239 c.forceRefresh = false
240 }
241
242 return c.creds, nil
243}
244
245// Expire expires the credentials and forces them to be retrieved on the
246// next call to Get().
247//
248// This will override the Provider's expired state, and force Credentials
249// to call the Provider's Retrieve().
250func (c *Credentials) Expire() {
251 c.m.Lock()
252 defer c.m.Unlock()
253
254 c.forceRefresh = true
255}
256
257// IsExpired returns if the credentials are no longer valid, and need
258// to be retrieved.
259//
260// If the Credentials were forced to be expired with Expire() this will
261// reflect that override.
262func (c *Credentials) IsExpired() bool {
15c0b25d
AP
263 c.m.RLock()
264 defer c.m.RUnlock()
bae9f6d2
JC
265
266 return c.isExpired()
267}
268
269// isExpired helper method wrapping the definition of expired credentials.
270func (c *Credentials) isExpired() bool {
271 return c.forceRefresh || c.provider.IsExpired()
272}
107c1cdb
ND
273
274// ExpiresAt provides access to the functionality of the Expirer interface of
275// the underlying Provider, if it supports that interface. Otherwise, it returns
276// an error.
277func (c *Credentials) ExpiresAt() (time.Time, error) {
278 c.m.RLock()
279 defer c.m.RUnlock()
280
281 expirer, ok := c.provider.(Expirer)
282 if !ok {
283 return time.Time{}, awserr.New("ProviderNotExpirer",
284 fmt.Sprintf("provider %s does not support ExpiresAt()", c.creds.ProviderName),
285 nil)
286 }
287 if c.forceRefresh {
288 // set expiration time to the distant past
289 return time.Time{}, nil
290 }
291 return expirer.ExpiresAt(), nil
292}