-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.js
110 lines (88 loc) · 2.63 KB
/
index.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
import request from "./request/request.js";
import { sorted, signed } from "./request/headers.js";
import stringToSign from "./stringtosign.js";
import signature from "./signature.js";
const dateCleanRegex = /[:\-]|\.\d{3}/g;
const requestRequired = [
"url",
];
const configRequired = [
"accessKeyId",
"region",
"secretAccessKey",
"service",
];
// Check for required params
const validate = (source, config) => {
if(!source) {
throw new Error(`Missing request object`);
}
if(!config) {
throw new Error(`Missing config object`);
}
let missing = requestRequired.filter((field) => !source[field]);
if(missing.length) {
throw new Error(`Missing required request fields: ${missing.join(", ")}`);
}
missing = configRequired.filter((field) => !config[field]);
if(missing.length) {
throw new Error(`Missing required config fields: ${missing.join(", ")}`);
}
};
const parseDate = ({ headers }) => {
const datetime = "X-Amz-Date" in headers ?
headers["X-Amz-Date"] :
(new Date(headers.Date || Date.now()))
.toISOString()
.replace(dateCleanRegex, "");
return {
short : datetime.split("T")[0],
long : datetime,
};
};
const authorization = (req, sig) => {
const { algorithm, accessKeyId, date, region, service, sortedHeaders } = req;
return [
`${algorithm} Credential=${accessKeyId}/${date.short}/${region}/${service}/aws4_request`,
`SignedHeaders=${signed(sortedHeaders)}`,
`Signature=${sig}`,
].join(", ");
};
export default (source, config) => {
validate(source, config);
const details = Object.assign(
Object.create(null),
{
method : "GET",
},
source,
config,
{
url : new URL(source.url),
algorithm : "AWS4-HMAC-SHA256",
date : parseDate(source),
sortedHeaders : sorted(source),
}
);
const canonical = request(details);
const sts = stringToSign(details, canonical);
const sig = signature(details, sts);
const auth = authorization(details, sig);
/* START.TESTSONLY */
// Add partial output to response for tests
source.test = {
canonical,
sts,
auth,
};
/* END.TESTSONLY */
if(!source.headers) {
source.headers = {};
}
source.headers["X-Amz-Date"] = details.date.long;
if(config.sessionToken) {
source.headers["X-Amz-Security-Token"] = config.sessionToken;
}
source.headers.Authorization = auth;
return source;
};