165 lines
5.4 KiB
JavaScript
165 lines
5.4 KiB
JavaScript
var AWS = require('../core');
|
|
require('../metadata_service');
|
|
|
|
/**
|
|
* Represents credentials received from the metadata service on an EC2 instance.
|
|
*
|
|
* By default, this class will connect to the metadata service using
|
|
* {AWS.MetadataService} and attempt to load any available credentials. If it
|
|
* can connect, and credentials are available, these will be used with zero
|
|
* configuration.
|
|
*
|
|
* This credentials class will by default timeout after 1 second of inactivity
|
|
* and retry 3 times.
|
|
* If your requests to the EC2 metadata service are timing out, you can increase
|
|
* these values by configuring them directly:
|
|
*
|
|
* ```javascript
|
|
* AWS.config.credentials = new AWS.EC2MetadataCredentials({
|
|
* httpOptions: { timeout: 5000 }, // 5 second timeout
|
|
* maxRetries: 10, // retry 10 times
|
|
* retryDelayOptions: { base: 200 }, // see AWS.Config for information
|
|
* logger: console // see AWS.Config for information
|
|
* ec2MetadataV1Disabled: false // whether to block IMDS v1 fallback.
|
|
* });
|
|
* ```
|
|
*
|
|
* If your requests are timing out in connecting to the metadata service, such
|
|
* as when testing on a development machine, you can use the connectTimeout
|
|
* option, specified in milliseconds, which also defaults to 1 second.
|
|
*
|
|
* If the requests failed or returns expired credentials, it will
|
|
* extend the expiration of current credential, with a warning message. For more
|
|
* information, please go to:
|
|
* https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html
|
|
*
|
|
* @!attribute originalExpiration
|
|
* @return [Date] The optional original expiration of the current credential.
|
|
* In case of AWS outage, the EC2 metadata will extend expiration of the
|
|
* existing credential.
|
|
*
|
|
* @see AWS.Config.retryDelayOptions
|
|
* @see AWS.Config.logger
|
|
*
|
|
* @!macro nobrowser
|
|
*/
|
|
AWS.EC2MetadataCredentials = AWS.util.inherit(AWS.Credentials, {
|
|
constructor: function EC2MetadataCredentials(options) {
|
|
AWS.Credentials.call(this);
|
|
|
|
options = options ? AWS.util.copy(options) : {};
|
|
options = AWS.util.merge(
|
|
{maxRetries: this.defaultMaxRetries}, options);
|
|
if (!options.httpOptions) options.httpOptions = {};
|
|
options.httpOptions = AWS.util.merge(
|
|
{timeout: this.defaultTimeout,
|
|
connectTimeout: this.defaultConnectTimeout},
|
|
options.httpOptions);
|
|
|
|
this.metadataService = new AWS.MetadataService(options);
|
|
this.logger = options.logger || AWS.config && AWS.config.logger;
|
|
},
|
|
|
|
/**
|
|
* @api private
|
|
*/
|
|
defaultTimeout: 1000,
|
|
|
|
/**
|
|
* @api private
|
|
*/
|
|
defaultConnectTimeout: 1000,
|
|
|
|
/**
|
|
* @api private
|
|
*/
|
|
defaultMaxRetries: 3,
|
|
|
|
/**
|
|
* The original expiration of the current credential. In case of AWS
|
|
* outage, the EC2 metadata will extend expiration of the existing
|
|
* credential.
|
|
*/
|
|
originalExpiration: undefined,
|
|
|
|
/**
|
|
* Loads the credentials from the instance metadata service
|
|
*
|
|
* @callback callback function(err)
|
|
* Called when the instance metadata service responds (or fails). When
|
|
* this callback is called with no error, it means that the credentials
|
|
* information has been loaded into the object (as the `accessKeyId`,
|
|
* `secretAccessKey`, and `sessionToken` properties).
|
|
* @param err [Error] if an error occurred, this value will be filled
|
|
* @see get
|
|
*/
|
|
refresh: function refresh(callback) {
|
|
this.coalesceRefresh(callback || AWS.util.fn.callback);
|
|
},
|
|
|
|
/**
|
|
* @api private
|
|
* @param callback
|
|
*/
|
|
load: function load(callback) {
|
|
var self = this;
|
|
self.metadataService.loadCredentials(function(err, creds) {
|
|
if (err) {
|
|
if (self.hasLoadedCredentials()) {
|
|
self.extendExpirationIfExpired();
|
|
callback();
|
|
} else {
|
|
callback(err);
|
|
}
|
|
} else {
|
|
self.setCredentials(creds);
|
|
self.extendExpirationIfExpired();
|
|
callback();
|
|
}
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Whether this credential has been loaded.
|
|
* @api private
|
|
*/
|
|
hasLoadedCredentials: function hasLoadedCredentials() {
|
|
return this.AccessKeyId && this.secretAccessKey;
|
|
},
|
|
|
|
/**
|
|
* if expired, extend the expiration by 15 minutes base plus a jitter of 5
|
|
* minutes range.
|
|
* @api private
|
|
*/
|
|
extendExpirationIfExpired: function extendExpirationIfExpired() {
|
|
if (this.needsRefresh()) {
|
|
this.originalExpiration = this.originalExpiration || this.expireTime;
|
|
this.expired = false;
|
|
var nextTimeout = 15 * 60 + Math.floor(Math.random() * 5 * 60);
|
|
var currentTime = AWS.util.date.getDate().getTime();
|
|
this.expireTime = new Date(currentTime + nextTimeout * 1000);
|
|
// TODO: add doc link;
|
|
this.logger.warn('Attempting credential expiration extension due to a '
|
|
+ 'credential service availability issue. A refresh of these '
|
|
+ 'credentials will be attempted again at ' + this.expireTime
|
|
+ '\nFor more information, please visit: https://docs.aws.amazon.com/sdkref/latest/guide/feature-static-credentials.html');
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Update the credential with new credential responded from EC2 metadata
|
|
* service.
|
|
* @api private
|
|
*/
|
|
setCredentials: function setCredentials(creds) {
|
|
var currentTime = AWS.util.date.getDate().getTime();
|
|
var expireTime = new Date(creds.Expiration);
|
|
this.expired = currentTime >= expireTime ? true : false;
|
|
this.metadata = creds;
|
|
this.accessKeyId = creds.AccessKeyId;
|
|
this.secretAccessKey = creds.SecretAccessKey;
|
|
this.sessionToken = creds.Token;
|
|
this.expireTime = expireTime;
|
|
}
|
|
});
|