]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/aws/aws-sdk-go/aws/credentials/credentials.go
update vendor and go.mod
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / aws / aws-sdk-go / aws / credentials / credentials.go
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 //
49 package credentials
50
51 import (
52 "fmt"
53 "sync"
54 "time"
55
56 "github.com/aws/aws-sdk-go/aws/awserr"
57 )
58
59 // AnonymousCredentials is an empty Credential object that can be used as
60 // dummy placeholder credentials for requests that do not need signed.
61 //
62 // This Credentials can be used to configure a service to not sign requests
63 // when making service API calls. For example, when accessing public
64 // s3 buckets.
65 //
66 // svc := s3.New(session.Must(session.NewSession(&aws.Config{
67 // Credentials: credentials.AnonymousCredentials,
68 // })))
69 // // Access public S3 buckets.
70 var AnonymousCredentials = NewStaticCredentials("", "", "")
71
72 // A Value is the AWS credentials value for individual credential fields.
73 type Value struct {
74 // AWS Access key ID
75 AccessKeyID string
76
77 // AWS Secret Access Key
78 SecretAccessKey string
79
80 // AWS Session Token
81 SessionToken string
82
83 // Provider used to get credentials
84 ProviderName string
85 }
86
87 // HasKeys returns if the credentials Value has both AccessKeyID and
88 // SecretAccessKey value set.
89 func (v Value) HasKeys() bool {
90 return len(v.AccessKeyID) != 0 && len(v.SecretAccessKey) != 0
91 }
92
93 // A Provider is the interface for any component which will provide credentials
94 // Value. A provider is required to manage its own Expired state, and what to
95 // be expired means.
96 //
97 // The Provider should not need to implement its own mutexes, because
98 // that will be managed by Credentials.
99 type Provider interface {
100 // Retrieve returns nil if it successfully retrieved the value.
101 // Error is returned if the value were not obtainable, or empty.
102 Retrieve() (Value, error)
103
104 // IsExpired returns if the credentials are no longer valid, and need
105 // to be retrieved.
106 IsExpired() bool
107 }
108
109 // An Expirer is an interface that Providers can implement to expose the expiration
110 // time, if known. If the Provider cannot accurately provide this info,
111 // it should not implement this interface.
112 type Expirer interface {
113 // The time at which the credentials are no longer valid
114 ExpiresAt() time.Time
115 }
116
117 // An ErrorProvider is a stub credentials provider that always returns an error
118 // this is used by the SDK when construction a known provider is not possible
119 // due to an error.
120 type ErrorProvider struct {
121 // The error to be returned from Retrieve
122 Err error
123
124 // The provider name to set on the Retrieved returned Value
125 ProviderName string
126 }
127
128 // Retrieve will always return the error that the ErrorProvider was created with.
129 func (p ErrorProvider) Retrieve() (Value, error) {
130 return Value{ProviderName: p.ProviderName}, p.Err
131 }
132
133 // IsExpired will always return not expired.
134 func (p ErrorProvider) IsExpired() bool {
135 return false
136 }
137
138 // A Expiry provides shared expiration logic to be used by credentials
139 // providers to implement expiry functionality.
140 //
141 // The best method to use this struct is as an anonymous field within the
142 // provider's struct.
143 //
144 // Example:
145 // type EC2RoleProvider struct {
146 // Expiry
147 // ...
148 // }
149 type Expiry struct {
150 // The date/time when to expire on
151 expiration time.Time
152
153 // If set will be used by IsExpired to determine the current time.
154 // Defaults to time.Now if CurrentTime is not set. Available for testing
155 // to be able to mock out the current time.
156 CurrentTime func() time.Time
157 }
158
159 // SetExpiration sets the expiration IsExpired will check when called.
160 //
161 // If window is greater than 0 the expiration time will be reduced by the
162 // window value.
163 //
164 // Using a window is helpful to trigger credentials to expire sooner than
165 // the expiration time given to ensure no requests are made with expired
166 // tokens.
167 func (e *Expiry) SetExpiration(expiration time.Time, window time.Duration) {
168 e.expiration = expiration
169 if window > 0 {
170 e.expiration = e.expiration.Add(-window)
171 }
172 }
173
174 // IsExpired returns if the credentials are expired.
175 func (e *Expiry) IsExpired() bool {
176 curTime := e.CurrentTime
177 if curTime == nil {
178 curTime = time.Now
179 }
180 return e.expiration.Before(curTime())
181 }
182
183 // ExpiresAt returns the expiration time of the credential
184 func (e *Expiry) ExpiresAt() time.Time {
185 return e.expiration
186 }
187
188 // A Credentials provides concurrency safe retrieval of AWS credentials Value.
189 // Credentials will cache the credentials value until they expire. Once the value
190 // expires the next Get will attempt to retrieve valid credentials.
191 //
192 // Credentials is safe to use across multiple goroutines and will manage the
193 // synchronous state so the Providers do not need to implement their own
194 // synchronization.
195 //
196 // The first Credentials.Get() will always call Provider.Retrieve() to get the
197 // first instance of the credentials Value. All calls to Get() after that
198 // will return the cached credentials Value until IsExpired() returns true.
199 type Credentials struct {
200 creds Value
201 forceRefresh bool
202
203 m sync.RWMutex
204
205 provider Provider
206 }
207
208 // NewCredentials returns a pointer to a new Credentials with the provider set.
209 func NewCredentials(provider Provider) *Credentials {
210 return &Credentials{
211 provider: provider,
212 forceRefresh: true,
213 }
214 }
215
216 // Get returns the credentials value, or error if the credentials Value failed
217 // to be retrieved.
218 //
219 // Will return the cached credentials Value if it has not expired. If the
220 // credentials Value has expired the Provider's Retrieve() will be called
221 // to refresh the credentials.
222 //
223 // If Credentials.Expire() was called the credentials Value will be force
224 // expired, and the next call to Get() will cause them to be refreshed.
225 func (c *Credentials) Get() (Value, error) {
226 // Check the cached credentials first with just the read lock.
227 c.m.RLock()
228 if !c.isExpired() {
229 creds := c.creds
230 c.m.RUnlock()
231 return creds, nil
232 }
233 c.m.RUnlock()
234
235 // Credentials are expired need to retrieve the credentials taking the full
236 // lock.
237 c.m.Lock()
238 defer c.m.Unlock()
239
240 if c.isExpired() {
241 creds, err := c.provider.Retrieve()
242 if err != nil {
243 return Value{}, err
244 }
245 c.creds = creds
246 c.forceRefresh = false
247 }
248
249 return c.creds, nil
250 }
251
252 // Expire expires the credentials and forces them to be retrieved on the
253 // next call to Get().
254 //
255 // This will override the Provider's expired state, and force Credentials
256 // to call the Provider's Retrieve().
257 func (c *Credentials) Expire() {
258 c.m.Lock()
259 defer c.m.Unlock()
260
261 c.forceRefresh = true
262 }
263
264 // IsExpired returns if the credentials are no longer valid, and need
265 // to be retrieved.
266 //
267 // If the Credentials were forced to be expired with Expire() this will
268 // reflect that override.
269 func (c *Credentials) IsExpired() bool {
270 c.m.RLock()
271 defer c.m.RUnlock()
272
273 return c.isExpired()
274 }
275
276 // isExpired helper method wrapping the definition of expired credentials.
277 func (c *Credentials) isExpired() bool {
278 return c.forceRefresh || c.provider.IsExpired()
279 }
280
281 // ExpiresAt provides access to the functionality of the Expirer interface of
282 // the underlying Provider, if it supports that interface. Otherwise, it returns
283 // an error.
284 func (c *Credentials) ExpiresAt() (time.Time, error) {
285 c.m.RLock()
286 defer c.m.RUnlock()
287
288 expirer, ok := c.provider.(Expirer)
289 if !ok {
290 return time.Time{}, awserr.New("ProviderNotExpirer",
291 fmt.Sprintf("provider %s does not support ExpiresAt()", c.creds.ProviderName),
292 nil)
293 }
294 if c.forceRefresh {
295 // set expiration time to the distant past
296 return time.Time{}, nil
297 }
298 return expirer.ExpiresAt(), nil
299 }