-
Notifications
You must be signed in to change notification settings - Fork 0
/
ec2-checkvolume.js
149 lines (130 loc) · 5.65 KB
/
ec2-checkvolume.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
146
147
148
149
/* global input, http, output, JXON */
// Inputs:
// VolumeId (required)
// AWSRegion (required)
// AWSAccessKey (required)
// AWSSecretKey (required)
// AWSSessionToken
//
// Outputs:
// ErrorMessage
// OKToModify
// CurrentSize
//
// 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
];
}
function executeEc2Action(access_key, secret_key, region, request_parameters) {
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
});
return ec2Request.write();
}
function describeVolumesModifications(access_key, secret_key, region) {
const request_parameters = "Action=DescribeVolumesModifications&Version=2016-11-15&VolumeId.1="+input.VolumeId;
return executeEc2Action(access_key, secret_key, region, request_parameters);
}
function describeVolumes(access_key, secret_key, region) {
const request_parameters = "Action=DescribeVolumes&Version=2016-11-15&VolumeId.1="+input.VolumeId;
return executeEc2Action(access_key, secret_key, region, request_parameters);
}
try {
const access_key = input.AWSAccessKey;
const secret_key = input.AWSSecretKey;
const region = input.AWSRegion;
var ec2Response = describeVolumesModifications(access_key, secret_key, region);
if (ec2Response.statusCode === 400) {
var json_error = JXON.parse(ec2Response.body);
if (json_error.response.errors.error.code === "InvalidVolumeModification.NotFound") {
// This volume has never been modified. We need to describe the volume in
// order to get the current size.
output.OKToModify = true;
let volResponse = describeVolumes(access_key, secret_key, region);
let volJson = JXON.parse(volResponse.body);
output.CurrentSize = volJson.describevolumesresponse.volumeset.item.size;
} else {
throw new Error(ec2Response.body);
}
}
if (ec2Response.statusCode !== 200) {
throw new Error(ec2Response.body);
}
var json_mods = JXON.parse(ec2Response.body);
var mod_item = json_mods.describevolumesmodificationsresponse.volumemodificationset.item;
var okToModify = (mod_item.modificationstate === "completed");
output.OKToModify = okToModify;
output.CurrentSize = mod_item.targetsize;
if (!okToModify) {
throw new Error("The volume is not in a state where it can be expanded at this time ("+mod_item.modificationstate+")");
}
} catch (error) {
output.ErrorMessage = error.message;
output.OKToModify = false;
}