-
Notifications
You must be signed in to change notification settings - Fork 0
/
ec2-getvolumeid.js
145 lines (128 loc) · 5.13 KB
/
ec2-getvolumeid.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/* global input, output, http, JXON */
// Inputs:
// AWSAccountId (required)
// AWSRegion (required)
// AWSInstanceId (required)
// AWSAccessKey (required)
// AWSSecretKey (required)
// AWSSessionToken
// DeviceName (required)
//
// Outputs:
// VolumeId
// ErrorMessage
// Matched
//
// Endpoints:
// It is necessary to create an endpoint for each region used. The endpoint name
// must be of the form ec2.<region>.amazonaws.com and have a base URL of
// https://ec2.<region>.amazonaws.com. No authentication.
const jsSHA = require('jsSHA');
const hmacSha256 = (signingKey, stringToSign, type="HEX") => {
var sha_ob = new jsSHA("SHA-256", "TEXT");
sha_ob.setHMACKey(signingKey, type);
sha_ob.update(stringToSign);
return sha_ob.getHMAC("HEX");
};
function hashSha256(stringToHash) {
var sha_ob = new jsSHA('SHA-256', "TEXT");
sha_ob.update(stringToHash);
return sha_ob.getHash("HEX");
}
function prependLeadingZeroes(n) {
if (n <= 9) {
return "0" + n;
}
return n.toString();
}
function getSignatureKey(key, dateStamp, regionName, serviceName) {
var kDate = hmacSha256(`AWS4${key}`, dateStamp, "TEXT");
var kRegion = hmacSha256(kDate, regionName);
var kService = hmacSha256(kRegion, serviceName);
var kSigning = hmacSha256(kService, "aws4_request");
return kSigning;
}
function buildHeader(access_key, secret_key, region, request_parameters) {
const method = "GET";
const service = "ec2";
const host = service+"."+region+".amazonaws.com";
const t = new Date();
const datestamp = `${t.getFullYear()}${prependLeadingZeroes(t.getMonth()+1)}${prependLeadingZeroes(t.getDate())}`;
// 4-digit year, 2-digit month, 2-digit date, T, 2-digit hour, 2-digit minutes, 2-digit seconds, Z
const amzdate = datestamp+"T"+prependLeadingZeroes(t.getHours())+prependLeadingZeroes(t.getMinutes())+prependLeadingZeroes(t.getSeconds())+"Z";
const canonical_uri = "/";
const canonical_querystring = request_parameters;
const canonical_headers = `host:${host}\nx-amz-date:${amzdate}\n`;
const signed_headers = 'host;x-amz-date';
// Calculate the hash of the payload which, for GET, is empty
const payload_hash = hashSha256("");
const canonical_request = method + '\n' + canonical_uri + '\n' + canonical_querystring + '\n' + canonical_headers + '\n' + signed_headers + '\n' + payload_hash;
const algorithm = 'AWS4-HMAC-SHA256';
const credential_scope = datestamp + '/' + region + '/' + service + '/' + 'aws4_request';
const string_to_sign = algorithm + '\n' + amzdate + '\n' + credential_scope + '\n' + hashSha256(canonical_request);
const signing_key = getSignatureKey(secret_key, datestamp, region, service);
const signature = hmacSha256(signing_key, string_to_sign).toString('hex');
const authorization_header = algorithm + ' ' + 'Credential=' + access_key + '/' + credential_scope + ', ' + 'SignedHeaders=' + signed_headers + ', ' + 'Signature=' + signature;
var requestHeaders = {
"host": host,
"x-amz-date": amzdate,
"Content-type": "application/json",
"Authorization": authorization_header
};
return [
requestHeaders,
host
];
}
try {
const access_key = input.AWSAccessKey;
const secret_key = input.AWSSecretKey;
const region = input.AWSRegion;
const request_parameters = "Action=DescribeInstances&InstanceId.1="+input.AWSInstanceId+"&Version=2016-11-15";
const blob = buildHeader(access_key, secret_key, region, request_parameters);
var requestHeaders = blob[0];
const host = blob[1];
if (input.AWSSessionToken) {
requestHeaders["X-Amz-Security-Token"] = input.AWSSessionToken;
}
var ec2Request = http.request({
endpoint: host,
path: "/?"+request_parameters,
method: 'GET',
headers: requestHeaders
});
var ec2Response = ec2Request.write();
if (ec2Response.statusCode !== 200) {
throw new Error(ec2Response.body);
}
var found_device = false;
var device = input.DeviceName;
var mapped_device = '/dev/s' + device.substr(2);
var description = ec2Response.body;
var json_desc = JXON.parse(description);
var devs = json_desc.describeinstancesresponse.reservationset.item.instancesset.item.blockdevicemapping.item;
// If there is only one attached drive, JXON returns a dictionary rather than an array.
if (Array.isArray(devs)) {
for (var i=0, size=devs.length; i < size; i++) {
var item = devs[i];
if (item.devicename === mapped_device) {
output.VolumeId = item.ebs.volumeid;
found_device = true;
break;
}
}
} else {
// Single device
if (devs.devicename === mapped_device) {
output.VolumeId = devs.ebs.volumeid;
found_device = true;
}
}
if (!found_device) {
throw new Error("Unable to find device "+device+" (a.k.a. "+mapped_device+") attached to instance");
}
output.Matched = found_device;
} catch (error) {
output.ErrorMessage = error.message;
output.Matched = false;
}