@@ -18,15 +18,27 @@ require('../metadata_service');
18
18
* AWS.config.credentials = new AWS.EC2MetadataCredentials({
19
19
* httpOptions: { timeout: 5000 }, // 5 second timeout
20
20
* maxRetries: 10, // retry 10 times
21
- * retryDelayOptions: { base: 200 } // see AWS.Config for information
21
+ * retryDelayOptions: { base: 200 }, // see AWS.Config for information
22
+ * logger: console // see AWS.Config for information
22
23
* });
24
+ * ```
23
25
*
24
26
* If your requests are timing out in connecting to the metadata service, such
25
27
* as when testing on a development machine, you can use the connectTimeout
26
28
* option, specified in milliseconds, which also defaults to 1 second.
27
- * ```
29
+ *
30
+ * If the requests failed or returns expired credentials, it will
31
+ * extend the expiration of current credential, with a warning message. For more
32
+ * information, please go to:
33
+ * https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html
34
+ *
35
+ * @!attribute originalExpiration
36
+ * @return [Date] The optional original expiration of the current credential.
37
+ * In case of AWS outage, the EC2 metadata will extend expiration of the
38
+ * existing credential.
28
39
*
29
40
* @see AWS.Config.retryDelayOptions
41
+ * @see AWS.Config.logger
30
42
*
31
43
* @!macro nobrowser
32
44
*/
@@ -44,7 +56,7 @@ AWS.EC2MetadataCredentials = AWS.util.inherit(AWS.Credentials, {
44
56
options . httpOptions ) ;
45
57
46
58
this . metadataService = new AWS . MetadataService ( options ) ;
47
- this . metadata = { } ;
59
+ this . logger = options . logger || AWS . config && AWS . config . logger ;
48
60
} ,
49
61
50
62
/**
@@ -62,6 +74,13 @@ AWS.EC2MetadataCredentials = AWS.util.inherit(AWS.Credentials, {
62
74
*/
63
75
defaultMaxRetries : 3 ,
64
76
77
+ /**
78
+ * The original expiration of the current credential. In case of AWS
79
+ * outage, the EC2 metadata will extend expiration of the existing
80
+ * credential.
81
+ */
82
+ originalExpiration : undefined ,
83
+
65
84
/**
66
85
* Loads the credentials from the instance metadata service
67
86
*
@@ -84,24 +103,62 @@ AWS.EC2MetadataCredentials = AWS.util.inherit(AWS.Credentials, {
84
103
load : function load ( callback ) {
85
104
var self = this ;
86
105
self . metadataService . loadCredentials ( function ( err , creds ) {
87
- if ( ! err ) {
88
- var currentTime = AWS . util . date . getDate ( ) ;
89
- var expireTime = new Date ( creds . Expiration ) ;
90
- if ( expireTime < currentTime ) {
91
- err = AWS . util . error (
92
- new Error ( 'EC2 Instance Metadata Serivce provided expired credentials' ) ,
93
- { code : 'EC2MetadataCredentialsProviderFailure' }
94
- ) ;
106
+ if ( err ) {
107
+ if ( self . hasLoadedCredentials ( ) ) {
108
+ self . extendExpirationIfExpired ( ) ;
109
+ callback ( ) ;
95
110
} else {
96
- self . expired = false ;
97
- self . metadata = creds ;
98
- self . accessKeyId = creds . AccessKeyId ;
99
- self . secretAccessKey = creds . SecretAccessKey ;
100
- self . sessionToken = creds . Token ;
101
- self . expireTime = expireTime ;
111
+ callback ( err ) ;
102
112
}
113
+ } else {
114
+ self . setCredentials ( creds ) ;
115
+ self . extendExpirationIfExpired ( ) ;
116
+ callback ( ) ;
103
117
}
104
- callback ( err ) ;
105
118
} ) ;
119
+ } ,
120
+
121
+ /**
122
+ * Whether this credential has been loaded.
123
+ * @api private
124
+ */
125
+ hasLoadedCredentials : function hasLoadedCredentials ( ) {
126
+ return this . AccessKeyId && this . secretAccessKey ;
127
+ } ,
128
+
129
+ /**
130
+ * if expired, extend the expiration by 15 minutes base plus a jitter of 5
131
+ * minutes range.
132
+ * @api private
133
+ */
134
+ extendExpirationIfExpired : function extendExpirationIfExpired ( ) {
135
+ if ( this . needsRefresh ( ) ) {
136
+ this . originalExpiration = this . originalExpiration || this . expireTime ;
137
+ this . expired = false ;
138
+ var nextTimeout = 15 * 60 + Math . floor ( Math . random ( ) * 5 * 60 ) ;
139
+ var currentTime = AWS . util . date . getDate ( ) . getTime ( ) ;
140
+ this . expireTime = new Date ( currentTime + nextTimeout * 1000 ) ;
141
+ // TODO: add doc link;
142
+ this . logger . warn ( 'Attempting credential expiration extension due to a '
143
+ + 'credential service availability issue. A refresh of these '
144
+ + 'credentials will be attempted again at ' + this . expireTime
145
+ + '\nFor more information, please visit: https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html' ) ;
146
+ }
147
+ } ,
148
+
149
+ /**
150
+ * Update the credential with new credential responded from EC2 metadata
151
+ * service.
152
+ * @api private
153
+ */
154
+ setCredentials : function setCredentials ( creds ) {
155
+ var currentTime = AWS . util . date . getDate ( ) . getTime ( ) ;
156
+ var expireTime = new Date ( creds . Expiration ) ;
157
+ this . expired = currentTime >= expireTime ? true : false ;
158
+ this . metadata = creds ;
159
+ this . accessKeyId = creds . AccessKeyId ;
160
+ this . secretAccessKey = creds . SecretAccessKey ;
161
+ this . sessionToken = creds . Token ;
162
+ this . expireTime = expireTime ;
106
163
}
107
164
} ) ;
0 commit comments