presign.js
3.56 KB
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
var AWS = require('../core');
var inherit = AWS.util.inherit;
/**
* @api private
*/
var expiresHeader = 'presigned-expires';
/**
* @api private
*/
function signedUrlBuilder(request) {
var expires = request.httpRequest.headers[expiresHeader];
var signerClass = request.service.getSignerClass(request);
delete request.httpRequest.headers['User-Agent'];
delete request.httpRequest.headers['X-Amz-User-Agent'];
if (signerClass === AWS.Signers.V4) {
if (expires > 604800) { // one week expiry is invalid
var message = 'Presigning does not support expiry time greater ' +
'than a week with SigV4 signing.';
throw AWS.util.error(new Error(), {
code: 'InvalidExpiryTime', message: message, retryable: false
});
}
request.httpRequest.headers[expiresHeader] = expires;
} else if (signerClass === AWS.Signers.S3) {
var now = request.service ? request.service.getSkewCorrectedDate() : AWS.util.date.getDate();
request.httpRequest.headers[expiresHeader] = parseInt(
AWS.util.date.unixTimestamp(now) + expires, 10).toString();
} else {
throw AWS.util.error(new Error(), {
message: 'Presigning only supports S3 or SigV4 signing.',
code: 'UnsupportedSigner', retryable: false
});
}
}
/**
* @api private
*/
function signedUrlSigner(request) {
var endpoint = request.httpRequest.endpoint;
var parsedUrl = AWS.util.urlParse(request.httpRequest.path);
var queryParams = {};
if (parsedUrl.search) {
queryParams = AWS.util.queryStringParse(parsedUrl.search.substr(1));
}
var auth = request.httpRequest.headers['Authorization'].split(' ');
if (auth[0] === 'AWS') {
auth = auth[1].split(':');
queryParams['AWSAccessKeyId'] = auth[0];
queryParams['Signature'] = auth[1];
AWS.util.each(request.httpRequest.headers, function (key, value) {
if (key === expiresHeader) key = 'Expires';
if (key.indexOf('x-amz-meta-') === 0) {
// Delete existing, potentially not normalized key
delete queryParams[key];
key = key.toLowerCase();
}
queryParams[key] = value;
});
delete request.httpRequest.headers[expiresHeader];
delete queryParams['Authorization'];
delete queryParams['Host'];
} else if (auth[0] === 'AWS4-HMAC-SHA256') { // SigV4 signing
auth.shift();
var rest = auth.join(' ');
var signature = rest.match(/Signature=(.*?)(?:,|\s|\r?\n|$)/)[1];
queryParams['X-Amz-Signature'] = signature;
delete queryParams['Expires'];
}
// build URL
endpoint.pathname = parsedUrl.pathname;
endpoint.search = AWS.util.queryParamsToString(queryParams);
}
/**
* @api private
*/
AWS.Signers.Presign = inherit({
/**
* @api private
*/
sign: function sign(request, expireTime, callback) {
request.httpRequest.headers[expiresHeader] = expireTime || 3600;
request.on('build', signedUrlBuilder);
request.on('sign', signedUrlSigner);
request.removeListener('afterBuild',
AWS.EventListeners.Core.SET_CONTENT_LENGTH);
request.removeListener('afterBuild',
AWS.EventListeners.Core.COMPUTE_SHA256);
request.emit('beforePresign', [request]);
if (callback) {
request.build(function() {
if (this.response.error) callback(this.response.error);
else {
callback(null, AWS.util.urlFormat(request.httpRequest.endpoint));
}
});
} else {
request.build();
if (request.response.error) throw request.response.error;
return AWS.util.urlFormat(request.httpRequest.endpoint);
}
}
});
/**
* @api private
*/
module.exports = AWS.Signers.Presign;