133 lines
4.3 KiB
JavaScript
133 lines
4.3 KiB
JavaScript
|
var AWS = require('./core');
|
||
|
require('./http');
|
||
|
var inherit = AWS.util.inherit;
|
||
|
|
||
|
/**
|
||
|
* Represents a metadata service available on EC2 instances. Using the
|
||
|
* {request} method, you can receieve metadata about any available resource
|
||
|
* on the metadata service.
|
||
|
*
|
||
|
* You can disable the use of the IMDS by setting the AWS_EC2_METADATA_DISABLED
|
||
|
* environment variable to a truthy value.
|
||
|
*
|
||
|
* @!attribute [r] httpOptions
|
||
|
* @return [map] a map of options to pass to the underlying HTTP request:
|
||
|
*
|
||
|
* * **timeout** (Number) — a timeout value in milliseconds to wait
|
||
|
* before aborting the connection. Set to 0 for no timeout.
|
||
|
*
|
||
|
* @!macro nobrowser
|
||
|
*/
|
||
|
AWS.MetadataService = inherit({
|
||
|
/**
|
||
|
* @return [String] the hostname of the instance metadata service
|
||
|
*/
|
||
|
host: '169.254.169.254',
|
||
|
|
||
|
/**
|
||
|
* @!ignore
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Default HTTP options. By default, the metadata service is set to not
|
||
|
* timeout on long requests. This means that on non-EC2 machines, this
|
||
|
* request will never return. If you are calling this operation from an
|
||
|
* environment that may not always run on EC2, set a `timeout` value so
|
||
|
* the SDK will abort the request after a given number of milliseconds.
|
||
|
*/
|
||
|
httpOptions: { timeout: 0 },
|
||
|
|
||
|
/**
|
||
|
* Creates a new MetadataService object with a given set of options.
|
||
|
*
|
||
|
* @option options host [String] the hostname of the instance metadata
|
||
|
* service
|
||
|
* @option options httpOptions [map] a map of options to pass to the
|
||
|
* underlying HTTP request:
|
||
|
*
|
||
|
* * **timeout** (Number) — a timeout value in milliseconds to wait
|
||
|
* before aborting the connection. Set to 0 for no timeout.
|
||
|
* @option options maxRetries [Integer] the maximum number of retries to
|
||
|
* perform for timeout errors
|
||
|
* @option options retryDelayOptions [map] A set of options to configure the
|
||
|
* retry delay on retryable errors. See AWS.Config for details.
|
||
|
*/
|
||
|
constructor: function MetadataService(options) {
|
||
|
AWS.util.update(this, options);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* Sends a request to the instance metadata service for a given resource.
|
||
|
*
|
||
|
* @param path [String] the path of the resource to get
|
||
|
* @callback callback function(err, data)
|
||
|
* Called when a response is available from the service.
|
||
|
* @param err [Error, null] if an error occurred, this value will be set
|
||
|
* @param data [String, null] if the request was successful, the body of
|
||
|
* the response
|
||
|
*/
|
||
|
request: function request(path, callback) {
|
||
|
if (process.env[AWS.util.imdsDisabledEnv]) {
|
||
|
callback(new Error('EC2 Instance Metadata Service access disabled'));
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
path = path || '/';
|
||
|
var httpRequest = new AWS.HttpRequest('http://' + this.host + path);
|
||
|
httpRequest.method = 'GET';
|
||
|
AWS.util.handleRequestWithRetries(httpRequest, this, callback);
|
||
|
},
|
||
|
|
||
|
/**
|
||
|
* @api private
|
||
|
*/
|
||
|
loadCredentialsCallbacks: [],
|
||
|
|
||
|
/**
|
||
|
* Loads a set of credentials stored in the instance metadata service
|
||
|
*
|
||
|
* @api private
|
||
|
* @callback callback function(err, credentials)
|
||
|
* Called when credentials are loaded from the resource
|
||
|
* @param err [Error] if an error occurred, this value will be set
|
||
|
* @param credentials [Object] the raw JSON object containing all
|
||
|
* metadata from the credentials resource
|
||
|
*/
|
||
|
loadCredentials: function loadCredentials(callback) {
|
||
|
var self = this;
|
||
|
var basePath = '/latest/meta-data/iam/security-credentials/';
|
||
|
self.loadCredentialsCallbacks.push(callback);
|
||
|
if (self.loadCredentialsCallbacks.length > 1) { return; }
|
||
|
|
||
|
function callbacks(err, creds) {
|
||
|
var cb;
|
||
|
while ((cb = self.loadCredentialsCallbacks.shift()) !== undefined) {
|
||
|
cb(err, creds);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
self.request(basePath, function (err, roleName) {
|
||
|
if (err) callbacks(err);
|
||
|
else {
|
||
|
roleName = roleName.split('\n')[0]; // grab first (and only) role
|
||
|
self.request(basePath + roleName, function (credErr, credData) {
|
||
|
if (credErr) callbacks(credErr);
|
||
|
else {
|
||
|
try {
|
||
|
var credentials = JSON.parse(credData);
|
||
|
callbacks(null, credentials);
|
||
|
} catch (parseError) {
|
||
|
callbacks(parseError);
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
|
||
|
/**
|
||
|
* @api private
|
||
|
*/
|
||
|
module.exports = AWS.MetadataService;
|