UNPKG

4.36 kBJavaScriptView Raw
1var AWS = require('./core');
2require('./http');
3var inherit = AWS.util.inherit;
4
5/**
6 * Represents a metadata service available on EC2 instances. Using the
7 * {request} method, you can receieve metadata about any available resource
8 * on the metadata service.
9 *
10 * You can disable the use of the IMDS by setting the AWS_EC2_METADATA_DISABLED
11 * environment variable to a truthy value.
12 *
13 * @!attribute [r] httpOptions
14 * @return [map] a map of options to pass to the underlying HTTP request:
15 *
16 * * **timeout** (Number) — a timeout value in milliseconds to wait
17 * before aborting the connection. Set to 0 for no timeout.
18 *
19 * @!macro nobrowser
20 */
21AWS.MetadataService = inherit({
22 /**
23 * @return [String] the hostname of the instance metadata service
24 */
25 host: '169.254.169.254',
26
27 /**
28 * @!ignore
29 */
30
31 /**
32 * Default HTTP options. By default, the metadata service is set to not
33 * timeout on long requests. This means that on non-EC2 machines, this
34 * request will never return. If you are calling this operation from an
35 * environment that may not always run on EC2, set a `timeout` value so
36 * the SDK will abort the request after a given number of milliseconds.
37 */
38 httpOptions: { timeout: 0 },
39
40 /**
41 * Creates a new MetadataService object with a given set of options.
42 *
43 * @option options host [String] the hostname of the instance metadata
44 * service
45 * @option options httpOptions [map] a map of options to pass to the
46 * underlying HTTP request:
47 *
48 * * **timeout** (Number) — a timeout value in milliseconds to wait
49 * before aborting the connection. Set to 0 for no timeout.
50 * @option options maxRetries [Integer] the maximum number of retries to
51 * perform for timeout errors
52 * @option options retryDelayOptions [map] A set of options to configure the
53 * retry delay on retryable errors. See AWS.Config for details.
54 */
55 constructor: function MetadataService(options) {
56 AWS.util.update(this, options);
57 },
58
59 /**
60 * Sends a request to the instance metadata service for a given resource.
61 *
62 * @param path [String] the path of the resource to get
63 * @callback callback function(err, data)
64 * Called when a response is available from the service.
65 * @param err [Error, null] if an error occurred, this value will be set
66 * @param data [String, null] if the request was successful, the body of
67 * the response
68 */
69 request: function request(path, callback) {
70 if (process.env[AWS.util.imdsDisabledEnv]) {
71 callback(new Error('EC2 Instance Metadata Service access disabled'));
72 return;
73 }
74
75 path = path || '/';
76 var httpRequest = new AWS.HttpRequest('http://' + this.host + path);
77 httpRequest.method = 'GET';
78 AWS.util.handleRequestWithRetries(httpRequest, this, callback);
79 },
80
81 /**
82 * @api private
83 */
84 loadCredentialsCallbacks: [],
85
86 /**
87 * Loads a set of credentials stored in the instance metadata service
88 *
89 * @api private
90 * @callback callback function(err, credentials)
91 * Called when credentials are loaded from the resource
92 * @param err [Error] if an error occurred, this value will be set
93 * @param credentials [Object] the raw JSON object containing all
94 * metadata from the credentials resource
95 */
96 loadCredentials: function loadCredentials(callback) {
97 var self = this;
98 var basePath = '/latest/meta-data/iam/security-credentials/';
99 self.loadCredentialsCallbacks.push(callback);
100 if (self.loadCredentialsCallbacks.length > 1) { return; }
101
102 function callbacks(err, creds) {
103 var cb;
104 while ((cb = self.loadCredentialsCallbacks.shift()) !== undefined) {
105 cb(err, creds);
106 }
107 }
108
109 self.request(basePath, function (err, roleName) {
110 if (err) callbacks(err);
111 else {
112 roleName = roleName.split('\n')[0]; // grab first (and only) role
113 self.request(basePath + roleName, function (credErr, credData) {
114 if (credErr) callbacks(credErr);
115 else {
116 try {
117 var credentials = JSON.parse(credData);
118 callbacks(null, credentials);
119 } catch (parseError) {
120 callbacks(parseError);
121 }
122 }
123 });
124 }
125 });
126 }
127});
128
129/**
130 * @api private
131 */
132module.exports = AWS.MetadataService;