@netacea/cloudfront 5.2.54 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +508 -0
- package/dist/index.js +2 -0
- package/package.json +10 -5
- package/.vscode/launch.json +0 -21
- package/.vscode/settings.json +0 -5
- package/CHANGELOG.md +0 -1526
- package/dist/package.json +0 -51
- package/dist/src/Cloudfront.d.ts +0 -93
- package/dist/src/Cloudfront.js +0 -954
- package/dist/src/Cloudfront.js.map +0 -1
- package/dist/src/captchaGet.d.ts +0 -14
- package/dist/src/captchaGet.js +0 -90
- package/dist/src/captchaGet.js.map +0 -1
- package/dist/src/cookieEncryption.d.ts +0 -2
- package/dist/src/cookieEncryption.js +0 -23
- package/dist/src/cookieEncryption.js.map +0 -1
- package/dist/src/dynamicContentType.d.ts +0 -3
- package/dist/src/dynamicContentType.js +0 -47
- package/dist/src/dynamicContentType.js.map +0 -1
- package/dist/src/headers.d.ts +0 -14
- package/dist/src/headers.js +0 -31
- package/dist/src/headers.js.map +0 -1
- package/dist/src/index.d.ts +0 -4
- package/dist/src/index.js +0 -8
- package/dist/src/index.js.map +0 -1
- package/dist/src/retrieveClientIp.d.ts +0 -7
- package/dist/src/retrieveClientIp.js +0 -26
- package/dist/src/retrieveClientIp.js.map +0 -1
- package/dist/src/types.d.ts +0 -70
- package/dist/src/types.js +0 -3
- package/dist/src/types.js.map +0 -1
- package/package.json.bak +0 -51
package/dist/src/Cloudfront.js
DELETED
|
@@ -1,954 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const netaceaintegrationbase_1 = require("@netacea/netaceaintegrationbase");
|
|
4
|
-
const pack = require("../package.json");
|
|
5
|
-
const axios_1 = require("axios");
|
|
6
|
-
const kinesisingest_1 = require("@netacea/kinesisingest");
|
|
7
|
-
const cookieEncryption_1 = require("./cookieEncryption");
|
|
8
|
-
const captchaGet_1 = require("./captchaGet");
|
|
9
|
-
const dynamicContentType_1 = require("./dynamicContentType");
|
|
10
|
-
const retrieveClientIp_1 = require("./retrieveClientIp");
|
|
11
|
-
const headers_1 = require("./headers");
|
|
12
|
-
const { extractCookieAttr, extractAndRemoveCookieAttr, removeDuplicateAttrs } = netaceaintegrationbase_1.lib.cookie.attributes;
|
|
13
|
-
const parseSetCookie = netaceaintegrationbase_1.lib.cookie.parse.parseSetCookie;
|
|
14
|
-
const { configureCookiesDomain } = netaceaintegrationbase_1.lib.cookie.attributes;
|
|
15
|
-
const { matchMap, mitigationTypes, mitigateMap, bestMitigationMap, bestMitigationCaptchaMap, captchaMap, netaceaHeaders } = netaceaintegrationbase_1.dictionary;
|
|
16
|
-
const ONE_HOUR_IN_SECONDS = 60 * 60;
|
|
17
|
-
const ONE_DAY_IN_SECONDS = ONE_HOUR_IN_SECONDS * 24;
|
|
18
|
-
class Cloudfront {
|
|
19
|
-
constructor(options) {
|
|
20
|
-
var _a, _b, _c, _d, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t;
|
|
21
|
-
this.ingestEnabled = true;
|
|
22
|
-
this.encryptedCookies = [];
|
|
23
|
-
// Only kinesis ingest is currently supported.
|
|
24
|
-
options.ingestType = netaceaintegrationbase_1.NetaceaIngestType.KINESIS;
|
|
25
|
-
if (options.kinesis === undefined) {
|
|
26
|
-
console.warn([
|
|
27
|
-
'NETACEA :: Please move kinesis params to "kinesis" object in config.',
|
|
28
|
-
'Backwards compatibility will soon be removed.'
|
|
29
|
-
].join(' '));
|
|
30
|
-
options.kinesis = {
|
|
31
|
-
kinesisStreamName: options.kinesisStreamName,
|
|
32
|
-
kinesisAccessKey: options.kinesisAccessKey,
|
|
33
|
-
kinesisSecretKey: options.kinesisSecretKey,
|
|
34
|
-
maxLogAgeSeconds: 1
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
if (options.apiKey === null || options.apiKey === undefined) {
|
|
38
|
-
throw new Error('apiKey is a required parameter');
|
|
39
|
-
}
|
|
40
|
-
this.apiKey = options.apiKey;
|
|
41
|
-
this.secretKey = options.secretKey;
|
|
42
|
-
this.mitigationServiceUrl = (_a = options.mitigationServiceUrl) !== null && _a !== void 0 ? _a : 'https://mitigations.netacea.net';
|
|
43
|
-
this.ingestServiceUrl = (_b = options.ingestServiceUrl) !== null && _b !== void 0 ? _b : 'https://ingest.netacea.net';
|
|
44
|
-
this.mitigationType = (_c = options.mitigationType) !== null && _c !== void 0 ? _c : netaceaintegrationbase_1.NetaceaMitigationType.INGEST;
|
|
45
|
-
this.ingestType = (_d = options.ingestType) !== null && _d !== void 0 ? _d : netaceaintegrationbase_1.NetaceaIngestType.HTTP;
|
|
46
|
-
this.logVersion = (_f = options.logVersion) !== null && _f !== void 0 ? _f : netaceaintegrationbase_1.NetaceaLogVersion.V1;
|
|
47
|
-
if (this.ingestType === netaceaintegrationbase_1.NetaceaIngestType.KINESIS) {
|
|
48
|
-
if (options.kinesis === undefined) {
|
|
49
|
-
console.warn(`NETACEA WARN: no kinesis args provided, when ingestType is ${this.ingestType}`);
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
this.kinesis = new kinesisingest_1.default({
|
|
53
|
-
...options.kinesis,
|
|
54
|
-
apiKey: this.apiKey
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
if (options.captchaSiteKey !== undefined || options.captchaSecretKey !== undefined) {
|
|
59
|
-
this.captchaSiteKey = options.captchaSiteKey;
|
|
60
|
-
this.captchaSecretKey = options.captchaSecretKey;
|
|
61
|
-
}
|
|
62
|
-
this.timeout = (0, netaceaintegrationbase_1.correctTimeout)((_g = options.timeout) !== null && _g !== void 0 ? _g : 3000);
|
|
63
|
-
this.netaceaCookieName = (_h = options.netaceaCookieName) !== null && _h !== void 0 ? _h : '_mitata';
|
|
64
|
-
this.netaceaCaptchaCookieName = (_j = options.netaceaCaptchaCookieName) !== null && _j !== void 0 ? _j : '_mitatacaptcha';
|
|
65
|
-
this.netaceaCaptchaPath = options.netaceaCaptchaPath;
|
|
66
|
-
this.dynamicCaptchaContentType = (_k = options.dynamicCaptchaContentType) !== null && _k !== void 0 ? _k : false;
|
|
67
|
-
const configuredCookieAttributes = configureCookiesDomain((_l = options.netaceaCookieAttributes) !== null && _l !== void 0 ? _l : '', (_m = options.netaceaCaptchaCookieAttributes) !== null && _m !== void 0 ? _m : '');
|
|
68
|
-
this.netaceaCookieAttributes = (_o = configuredCookieAttributes.cookieAttributes) !== null && _o !== void 0 ? _o : '';
|
|
69
|
-
this.netaceaCaptchaCookieAttributes = (_p = configuredCookieAttributes.captchaCookieAttributes) !== null && _p !== void 0 ? _p : '';
|
|
70
|
-
this.captchaHeader = options.captchaHeader;
|
|
71
|
-
this.ipHeaderName = (_r = (_q = options.ipHeaderName) === null || _q === void 0 ? void 0 : _q.toLowerCase()) === null || _r === void 0 ? void 0 : _r.trim();
|
|
72
|
-
this.encryptedCookies = [
|
|
73
|
-
this.netaceaCookieName,
|
|
74
|
-
this.netaceaCaptchaCookieName
|
|
75
|
-
];
|
|
76
|
-
this.mitataCookieExpirySeconds = (0, netaceaintegrationbase_1.configureMitataExpiry)(this.mitigationType, (_s = options.netaceaCookieExpirySeconds) !== null && _s !== void 0 ? _s : options.mitataCookieExpirySeconds);
|
|
77
|
-
this.ingestEnabled = (_t = options.ingestEnabled) !== null && _t !== void 0 ? _t : true;
|
|
78
|
-
this.cookieEncryptionKey = options.cookieEncryptionKey;
|
|
79
|
-
}
|
|
80
|
-
async run(cloudfrontEvent) {
|
|
81
|
-
try {
|
|
82
|
-
const { uri, method } = this.getRequestResponseFromEvent(cloudfrontEvent).request;
|
|
83
|
-
if (this.isUrlCaptchaGet(uri, method)) {
|
|
84
|
-
const response = await (0, captchaGet_1.handleCaptchaGetRequest)({
|
|
85
|
-
event: cloudfrontEvent,
|
|
86
|
-
secretKey: this.secretKey,
|
|
87
|
-
mitigationCallFn: this.makeMitigateAPICall.bind(this),
|
|
88
|
-
composeResultFn: this.composeResult.bind(this),
|
|
89
|
-
cookieEncryptionKey: this.cookieEncryptionKey,
|
|
90
|
-
netaceaCookieName: this.netaceaCookieName,
|
|
91
|
-
netaceaCaptchaCookieName: this.netaceaCaptchaCookieName,
|
|
92
|
-
ipHeaderName: this.ipHeaderName
|
|
93
|
-
});
|
|
94
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
95
|
-
this.ingest(response);
|
|
96
|
-
return response;
|
|
97
|
-
}
|
|
98
|
-
const netaceaResult = await this.runMitigation(cloudfrontEvent);
|
|
99
|
-
const { request } = this.getRequestResponseFromEvent(cloudfrontEvent);
|
|
100
|
-
this.addNetaceaCookiesToRequest(request, netaceaResult);
|
|
101
|
-
request.headers[Cloudfront.NetaceaTrueUserAgentHeader] = [{
|
|
102
|
-
key: Cloudfront.NetaceaTrueUserAgentHeader,
|
|
103
|
-
value: this.getValueFromHeaderOrDefault(request.headers, 'user-agent', '-')
|
|
104
|
-
}];
|
|
105
|
-
if ((netaceaResult === null || netaceaResult === void 0 ? void 0 : netaceaResult.response) !== undefined) {
|
|
106
|
-
cloudfrontEvent.Records[0].cf.response = netaceaResult.response;
|
|
107
|
-
}
|
|
108
|
-
return cloudfrontEvent;
|
|
109
|
-
}
|
|
110
|
-
catch (err) {
|
|
111
|
-
console.error('Netacea FailOpen - ', err.message);
|
|
112
|
-
return cloudfrontEvent;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
async makeRequest({ host, path, method, body, headers, timeout }) {
|
|
116
|
-
const url = `${host}${path}`;
|
|
117
|
-
const data = await axios_1.default.request({
|
|
118
|
-
url,
|
|
119
|
-
data: body,
|
|
120
|
-
headers,
|
|
121
|
-
method,
|
|
122
|
-
timeout,
|
|
123
|
-
transformResponse: (data) => data
|
|
124
|
-
});
|
|
125
|
-
return {
|
|
126
|
-
headers: data.headers,
|
|
127
|
-
status: data.status,
|
|
128
|
-
body: data.data
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
async mitigate(cloudfrontEvent) {
|
|
132
|
-
var _a;
|
|
133
|
-
try {
|
|
134
|
-
const { netaceaResult, request } = await this.getMitigationResponse(cloudfrontEvent);
|
|
135
|
-
let res;
|
|
136
|
-
if (netaceaResult.mitigated) {
|
|
137
|
-
const headers = {
|
|
138
|
-
'set-cookie': []
|
|
139
|
-
};
|
|
140
|
-
for (const cookie of netaceaResult.setCookie) {
|
|
141
|
-
headers['set-cookie'] = (_a = headers['set-cookie']) !== null && _a !== void 0 ? _a : [];
|
|
142
|
-
headers['set-cookie'].push({
|
|
143
|
-
key: 'set-cookie',
|
|
144
|
-
value: cookie
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
if (netaceaResult.mitigation === 'captcha' && this.captchaHeader !== undefined) {
|
|
148
|
-
headers[this.captchaHeader.name] = [{
|
|
149
|
-
key: this.captchaHeader.name,
|
|
150
|
-
value: this.captchaHeader.value
|
|
151
|
-
}];
|
|
152
|
-
}
|
|
153
|
-
const responseStatus = this.isUrlCaptchaPost(request.uri, request.method)
|
|
154
|
-
? {
|
|
155
|
-
status: '200',
|
|
156
|
-
statusDescription: 'OK',
|
|
157
|
-
body: ''
|
|
158
|
-
}
|
|
159
|
-
: {
|
|
160
|
-
status: '403',
|
|
161
|
-
statusDescription: 'Forbidden',
|
|
162
|
-
body: 'Forbidden'
|
|
163
|
-
};
|
|
164
|
-
res = {
|
|
165
|
-
headers,
|
|
166
|
-
...responseStatus
|
|
167
|
-
};
|
|
168
|
-
let len = 0;
|
|
169
|
-
if (netaceaResult.body !== undefined && netaceaResult.body.length > 0) {
|
|
170
|
-
len = netaceaResult.body.length;
|
|
171
|
-
const isCaptchaJson = (0, dynamicContentType_1.isCaptchaJsonResponse)(netaceaResult.body);
|
|
172
|
-
// lambdas won't let you set body on 403 status codes
|
|
173
|
-
res.status = isCaptchaJson ? '403' : '200';
|
|
174
|
-
res.statusDescription = isCaptchaJson ? 'Forbidden' : 'OK';
|
|
175
|
-
res.body = netaceaResult.body;
|
|
176
|
-
res.bodyEncoding = 'text';
|
|
177
|
-
}
|
|
178
|
-
// We have to ingest here because viewer response doesn't get called
|
|
179
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
180
|
-
this.ingest({
|
|
181
|
-
Records: [{
|
|
182
|
-
cf: {
|
|
183
|
-
request,
|
|
184
|
-
response: {
|
|
185
|
-
status: res.status,
|
|
186
|
-
headers: {
|
|
187
|
-
'content-length': [
|
|
188
|
-
{
|
|
189
|
-
key: 'content-length',
|
|
190
|
-
value: len.toString()
|
|
191
|
-
}
|
|
192
|
-
],
|
|
193
|
-
'set-cookie': netaceaResult.setCookie.map(cookie => {
|
|
194
|
-
return {
|
|
195
|
-
key: 'set-cookie',
|
|
196
|
-
value: cookie
|
|
197
|
-
};
|
|
198
|
-
})
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}]
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
this.addNetaceaCookiesToRequest(request, netaceaResult);
|
|
206
|
-
return {
|
|
207
|
-
response: res,
|
|
208
|
-
sessionStatus: netaceaResult.sessionStatus,
|
|
209
|
-
setCookie: netaceaResult.setCookie
|
|
210
|
-
};
|
|
211
|
-
}
|
|
212
|
-
catch (err) {
|
|
213
|
-
console.error('Netacea FailOpen Error: ', err);
|
|
214
|
-
return {
|
|
215
|
-
sessionStatus: ''
|
|
216
|
-
};
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
async inject(cloudfrontEvent) {
|
|
220
|
-
try {
|
|
221
|
-
const { netaceaResult } = await this.getMitigationResponse(cloudfrontEvent);
|
|
222
|
-
return {
|
|
223
|
-
injectHeaders: netaceaResult.injectHeaders,
|
|
224
|
-
sessionStatus: netaceaResult.sessionStatus,
|
|
225
|
-
setCookie: netaceaResult.setCookie
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
catch (err) {
|
|
229
|
-
console.error('Netacea FailOpen Error: ', err);
|
|
230
|
-
return {
|
|
231
|
-
sessionStatus: '',
|
|
232
|
-
injectHeaders: undefined,
|
|
233
|
-
setCookie: undefined
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
async ingest(cloudfrontEvent) {
|
|
238
|
-
var _a, _b, _c;
|
|
239
|
-
if (!this.ingestEnabled) {
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
const { request, response } = this.getRequestResponseFromEvent(cloudfrontEvent);
|
|
243
|
-
if (response === undefined) {
|
|
244
|
-
throw new Error('Cloudfront response is required to ingest');
|
|
245
|
-
}
|
|
246
|
-
const setCookie = this.getMitataValueFromHeaderOrDefault(response.headers, 'set-cookie');
|
|
247
|
-
const cookieString = setCookie !== ''
|
|
248
|
-
? setCookie
|
|
249
|
-
: this.getMitataValueFromHeaderOrDefault(request.headers, 'cookie');
|
|
250
|
-
let mitata = (_a = await this.readCookie(this.netaceaCookieName, cookieString)) !== null && _a !== void 0 ? _a : '';
|
|
251
|
-
if (mitata === undefined || mitata === '') {
|
|
252
|
-
const cookieString = this.getMitataValueFromHeaderOrDefault(request.headers, 'cookie');
|
|
253
|
-
mitata = (_b = await this.readCookie(this.netaceaCookieName, cookieString)) !== null && _b !== void 0 ? _b : '';
|
|
254
|
-
}
|
|
255
|
-
let match = 0;
|
|
256
|
-
let mitigate = 0;
|
|
257
|
-
let captcha = 0;
|
|
258
|
-
const mitataBits = (0, netaceaintegrationbase_1.matchMitataCookie)(mitata);
|
|
259
|
-
if (mitataBits !== undefined) {
|
|
260
|
-
match = mitataBits.match;
|
|
261
|
-
mitigate = mitataBits.mitigate;
|
|
262
|
-
captcha = mitataBits.captcha;
|
|
263
|
-
}
|
|
264
|
-
const isCaptchaPass = this.shouldSetCaptchaPass(cloudfrontEvent);
|
|
265
|
-
const { sessionStatus } = this.findBestMitigation(match, mitigate, captcha, isCaptchaPass);
|
|
266
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
267
|
-
await this.callIngest({
|
|
268
|
-
bytesSent: this.getValueFromHeaderOrDefault(response.headers, 'content-length', '0'),
|
|
269
|
-
ip: (0, retrieveClientIp_1.retrieveClientIp)(cloudfrontEvent, this.ipHeaderName),
|
|
270
|
-
method: request.method,
|
|
271
|
-
path: request.uri,
|
|
272
|
-
protocol: (_c = request.httpVersion) !== null && _c !== void 0 ? _c : 'HTTP/1.1',
|
|
273
|
-
referer: this.getValueFromHeaderOrDefault(request.headers, 'referer'),
|
|
274
|
-
requestTime: '0',
|
|
275
|
-
status: response.status,
|
|
276
|
-
userAgent: this.getValueFromHeaderOrDefault(request.headers, Cloudfront.NetaceaTrueUserAgentHeader, this.getValueFromHeaderOrDefault(request.headers, 'user-agent')),
|
|
277
|
-
mitataCookie: mitata,
|
|
278
|
-
sessionStatus,
|
|
279
|
-
integrationType: pack.name.replace('@netacea/', ''),
|
|
280
|
-
integrationVersion: pack.version,
|
|
281
|
-
xForwardedFor: this.getValueFromHeaderOrDefault(request.headers, 'x-forwarded-for')
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
addNetaceaCookiesToResponse(cloudfrontEvent) {
|
|
285
|
-
const { response, request } = this.getRequestResponseFromEvent(cloudfrontEvent);
|
|
286
|
-
if (response === undefined) {
|
|
287
|
-
throw new Error('Response required to add cookies to response');
|
|
288
|
-
}
|
|
289
|
-
const headers = request.headers[Cloudfront.NetaceaCookieHeader];
|
|
290
|
-
if (headers !== undefined) {
|
|
291
|
-
let setCookieIncludesNetaceaCookies = false;
|
|
292
|
-
if (response.headers['set-cookie'] === undefined) {
|
|
293
|
-
response.headers['set-cookie'] = [];
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
setCookieIncludesNetaceaCookies = response.headers['set-cookie'].find(v => {
|
|
297
|
-
return v.value.includes(this.netaceaCookieName) || v.value.includes(this.netaceaCaptchaCookieName);
|
|
298
|
-
}) !== undefined;
|
|
299
|
-
}
|
|
300
|
-
if (!setCookieIncludesNetaceaCookies) {
|
|
301
|
-
for (const header of headers) {
|
|
302
|
-
response.headers['set-cookie'].push({
|
|
303
|
-
key: 'set-cookie',
|
|
304
|
-
value: header.value
|
|
305
|
-
});
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
this.setInjectHeaders(cloudfrontEvent);
|
|
310
|
-
}
|
|
311
|
-
setInjectHeaders(cloudfrontEvent) {
|
|
312
|
-
const { response, request } = this.getRequestResponseFromEvent(cloudfrontEvent);
|
|
313
|
-
if (response !== undefined) {
|
|
314
|
-
const match = request.headers['x-netacea-match'];
|
|
315
|
-
const mitigate = request.headers['x-netacea-mitigate'];
|
|
316
|
-
const captcha = request.headers['x-netacea-captcha'];
|
|
317
|
-
const eventId = request.headers['x-netacea-event-id'];
|
|
318
|
-
if (match !== undefined &&
|
|
319
|
-
mitigate !== undefined &&
|
|
320
|
-
captcha !== undefined) {
|
|
321
|
-
response.headers['x-netacea-match'] = match;
|
|
322
|
-
response.headers['x-netacea-mitigate'] = mitigate;
|
|
323
|
-
response.headers['x-netacea-captcha'] = this.shouldSetCaptchaPass(cloudfrontEvent)
|
|
324
|
-
? [{
|
|
325
|
-
key: 'x-netacea-captcha',
|
|
326
|
-
value: '2'
|
|
327
|
-
}]
|
|
328
|
-
: captcha;
|
|
329
|
-
}
|
|
330
|
-
if (eventId !== undefined) {
|
|
331
|
-
response.headers['x-netacea-event-id'] = eventId;
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
getValueFromHeaderOrDefault(headers, key, def = '') {
|
|
336
|
-
if (headers[key] !== undefined) {
|
|
337
|
-
const v = headers[key];
|
|
338
|
-
if (v !== undefined) {
|
|
339
|
-
return v[0].value;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
return def;
|
|
343
|
-
}
|
|
344
|
-
getMitataValueFromHeaderOrDefault(headers, key, def = '') {
|
|
345
|
-
if (headers[key] !== undefined) {
|
|
346
|
-
const v = headers[key];
|
|
347
|
-
if (v !== undefined) {
|
|
348
|
-
const mitataItem = v.find(x => x.value.includes(this.netaceaCookieName));
|
|
349
|
-
if (mitataItem !== undefined) {
|
|
350
|
-
return mitataItem.value;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
return def;
|
|
355
|
-
}
|
|
356
|
-
getRequestResponseFromEvent(event) {
|
|
357
|
-
return event.Records[0].cf;
|
|
358
|
-
}
|
|
359
|
-
async getMitigationResponse(cloudfrontEvent) {
|
|
360
|
-
const { request } = this.getRequestResponseFromEvent(cloudfrontEvent);
|
|
361
|
-
const cookies = this.getMitataValueFromHeaderOrDefault(request.headers, 'cookie');
|
|
362
|
-
const mitata = await this.readCookie(this.netaceaCookieName, cookies);
|
|
363
|
-
const mitataCaptcha = await this.readCookie(this.netaceaCaptchaCookieName, cookies);
|
|
364
|
-
const clientIp = (0, retrieveClientIp_1.retrieveClientIp)(cloudfrontEvent, this.ipHeaderName);
|
|
365
|
-
const userAgent = this.getValueFromHeaderOrDefault(request.headers, 'user-agent');
|
|
366
|
-
const accept = this.getValueFromHeaderOrDefault(request.headers, 'accept', 'text/html');
|
|
367
|
-
const host = this.getValueFromHeaderOrDefault(request.headers, 'host');
|
|
368
|
-
return {
|
|
369
|
-
netaceaResult: await this.processMitigateRequest({
|
|
370
|
-
getBodyFn: async () => { var _a, _b; return await Promise.resolve(Buffer.from((_b = (_a = request.body) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : '', 'base64').toString()); },
|
|
371
|
-
clientIp,
|
|
372
|
-
method: request.method,
|
|
373
|
-
url: request.uri,
|
|
374
|
-
userAgent,
|
|
375
|
-
accept,
|
|
376
|
-
host,
|
|
377
|
-
mitata,
|
|
378
|
-
mitataCaptcha
|
|
379
|
-
}),
|
|
380
|
-
request
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
addNetaceaCookiesToRequest(request, netaceaResult) {
|
|
384
|
-
var _a, _b;
|
|
385
|
-
if (netaceaResult === undefined) {
|
|
386
|
-
return request;
|
|
387
|
-
}
|
|
388
|
-
request.headers[Cloudfront.NetaceaCookieHeader] = [];
|
|
389
|
-
if (netaceaResult.setCookie !== undefined) {
|
|
390
|
-
for (const cookie of netaceaResult.setCookie) {
|
|
391
|
-
const cookieHeader = (_a = request.headers[Cloudfront.NetaceaCookieHeader]) !== null && _a !== void 0 ? _a : [];
|
|
392
|
-
cookieHeader.push({
|
|
393
|
-
key: Cloudfront.NetaceaCookieHeader,
|
|
394
|
-
value: cookie
|
|
395
|
-
});
|
|
396
|
-
request.headers[Cloudfront.NetaceaCookieHeader] = cookieHeader;
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
if (this.mitigationType === netaceaintegrationbase_1.NetaceaMitigationType.INJECT) {
|
|
400
|
-
for (const [key, value] of Object.entries((_b = netaceaResult.injectHeaders) !== null && _b !== void 0 ? _b : {})) {
|
|
401
|
-
request.headers[key] = [
|
|
402
|
-
{
|
|
403
|
-
key,
|
|
404
|
-
value
|
|
405
|
-
}
|
|
406
|
-
];
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
return request;
|
|
410
|
-
}
|
|
411
|
-
getCookieHeader(args) {
|
|
412
|
-
const { request } = this.getRequestResponseFromEvent(args);
|
|
413
|
-
return this.getMitataValueFromHeaderOrDefault(request.headers, 'cookie');
|
|
414
|
-
}
|
|
415
|
-
async encryptCookieValue(cookieValue) {
|
|
416
|
-
if (this.cookieEncryptionKey !== undefined) {
|
|
417
|
-
return await (0, cookieEncryption_1.encrypt)(cookieValue, this.cookieEncryptionKey);
|
|
418
|
-
}
|
|
419
|
-
return cookieValue;
|
|
420
|
-
}
|
|
421
|
-
async decryptCookieValue(encryptedCookieValue) {
|
|
422
|
-
if (this.cookieEncryptionKey !== undefined) {
|
|
423
|
-
return await (0, cookieEncryption_1.decrypt)(encryptedCookieValue, this.cookieEncryptionKey);
|
|
424
|
-
}
|
|
425
|
-
return encryptedCookieValue;
|
|
426
|
-
}
|
|
427
|
-
/**
|
|
428
|
-
* START -- NETACEA BASE METHODS
|
|
429
|
-
*/
|
|
430
|
-
async runMitigation(args) {
|
|
431
|
-
try {
|
|
432
|
-
switch (this.mitigationType) {
|
|
433
|
-
case netaceaintegrationbase_1.NetaceaMitigationType.MITIGATE:
|
|
434
|
-
return await this.mitigate(args);
|
|
435
|
-
case netaceaintegrationbase_1.NetaceaMitigationType.INJECT:
|
|
436
|
-
return await this.inject(args);
|
|
437
|
-
case netaceaintegrationbase_1.NetaceaMitigationType.INGEST:
|
|
438
|
-
return await this.processIngest(args);
|
|
439
|
-
default:
|
|
440
|
-
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
441
|
-
throw new Error(`Netacea Error: Mitigation type ${this.mitigationType} not recognised`);
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
catch (e) {
|
|
445
|
-
console.error('Netacea FAILOPEN Error:', e);
|
|
446
|
-
return {
|
|
447
|
-
injectHeaders: {
|
|
448
|
-
'x-netacea-captcha': '0',
|
|
449
|
-
'x-netacea-match': '0',
|
|
450
|
-
'x-netacea-mitigate': '0'
|
|
451
|
-
},
|
|
452
|
-
sessionStatus: ''
|
|
453
|
-
};
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
/**
|
|
457
|
-
* Returns the value of the cookie with the given name from a string or list of cookies.
|
|
458
|
-
* If the cookie name is included in the encryptedCookies class property,
|
|
459
|
-
* then the cookie value will be decrypted automatically.
|
|
460
|
-
* The method may operate of either the HTTP Cookie or Set-Cookie headers.
|
|
461
|
-
* @param cookieName the name of the cookie to find.
|
|
462
|
-
* @param cookies the full list of cookies, either as a string or an array of strings.
|
|
463
|
-
* @returns the value of the cookie, if found.
|
|
464
|
-
*/
|
|
465
|
-
async readCookie(cookieName, cookies) {
|
|
466
|
-
if (cookies === null || cookies === undefined) {
|
|
467
|
-
return undefined;
|
|
468
|
-
}
|
|
469
|
-
if (typeof cookies === 'string') {
|
|
470
|
-
return await this.readCookie(cookieName, cookies.split(';'));
|
|
471
|
-
}
|
|
472
|
-
const valuePrefix = `${cookieName}=`;
|
|
473
|
-
for (const cookie of cookies) {
|
|
474
|
-
// split again on ; to handle Set-Cookie header format.
|
|
475
|
-
const trimmedCookie = cookie.split(';')[0].trimStart();
|
|
476
|
-
if (trimmedCookie.startsWith(valuePrefix)) {
|
|
477
|
-
const cookieValue = trimmedCookie.slice(valuePrefix.length);
|
|
478
|
-
if (this.encryptedCookies.includes(cookieName)) {
|
|
479
|
-
try {
|
|
480
|
-
return await this.decryptCookieValue(cookieValue);
|
|
481
|
-
}
|
|
482
|
-
catch (_e) {
|
|
483
|
-
return undefined;
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
return cookieValue;
|
|
487
|
-
}
|
|
488
|
-
}
|
|
489
|
-
return undefined;
|
|
490
|
-
}
|
|
491
|
-
async processMitigateRequest(args) {
|
|
492
|
-
const isCaptchaPost = this.isUrlCaptchaPost(args.url, args.method);
|
|
493
|
-
return await (isCaptchaPost
|
|
494
|
-
? this.processCaptcha(args.mitata, args.clientIp, args.userAgent, await args.getBodyFn())
|
|
495
|
-
: this.check(args.mitata, args.clientIp, args.userAgent, args.accept, args.host, args.mitataCaptcha));
|
|
496
|
-
}
|
|
497
|
-
isUrlCaptchaPost(url, method) {
|
|
498
|
-
return url.includes('/AtaVerifyCaptcha') && method.toLowerCase() === 'post';
|
|
499
|
-
}
|
|
500
|
-
isUrlCaptchaGet(url, method) {
|
|
501
|
-
var _a;
|
|
502
|
-
return url.toLowerCase() === ((_a = this.netaceaCaptchaPath) === null || _a === void 0 ? void 0 : _a.toLowerCase()) && method.toLowerCase() === 'get';
|
|
503
|
-
}
|
|
504
|
-
shouldSetCaptchaPass(cloudfrontEvent) {
|
|
505
|
-
const { request, response } = this.getRequestResponseFromEvent(cloudfrontEvent);
|
|
506
|
-
if (this.isUrlCaptchaPost(request.uri, request.method)) {
|
|
507
|
-
return true;
|
|
508
|
-
}
|
|
509
|
-
if (response === undefined) {
|
|
510
|
-
return false;
|
|
511
|
-
}
|
|
512
|
-
const cookies = response.headers['set-cookie'];
|
|
513
|
-
const mitataCaptcha = cookies === null || cookies === void 0 ? void 0 : cookies.find(cookie => cookie.value.split('=')[0] === this.netaceaCaptchaCookieName);
|
|
514
|
-
const mitataCaptchaIsSet = mitataCaptcha !== undefined;
|
|
515
|
-
return this.mitigationType === netaceaintegrationbase_1.NetaceaMitigationType.INJECT && mitataCaptchaIsSet;
|
|
516
|
-
}
|
|
517
|
-
async processCaptcha(netaceaCookie, clientIP, userAgent, captchaData) {
|
|
518
|
-
const { status, match, mitigate, captcha, body, setCookie } = await this.makeCaptchaAPICall(netaceaCookie, clientIP, userAgent, captchaData);
|
|
519
|
-
return this.composeResult(body, setCookie, status, match, mitigate, captcha, true);
|
|
520
|
-
}
|
|
521
|
-
async makeCaptchaAPICall(netaceaCookie, clientIP, userAgent, captchaData) {
|
|
522
|
-
const headers = {
|
|
523
|
-
'X-Netacea-API-Key': this.apiKey,
|
|
524
|
-
'X-Netacea-Client-IP': clientIP,
|
|
525
|
-
'user-agent': userAgent,
|
|
526
|
-
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
|
|
527
|
-
};
|
|
528
|
-
const mitata = (0, netaceaintegrationbase_1.matchMitataCookie)(netaceaCookie);
|
|
529
|
-
if (mitata !== undefined) {
|
|
530
|
-
headers['X-Netacea-UserId'] = mitata.userId;
|
|
531
|
-
}
|
|
532
|
-
if (this.captchaSiteKey !== undefined && this.captchaSecretKey !== undefined) {
|
|
533
|
-
headers['X-Netacea-Captcha-Site-Key'] = this.captchaSiteKey;
|
|
534
|
-
headers['X-Netacea-Captcha-Secret-Key'] = this.captchaSecretKey;
|
|
535
|
-
}
|
|
536
|
-
const res = await this.makeRequest({
|
|
537
|
-
host: this.mitigationServiceUrl,
|
|
538
|
-
path: '/AtaVerifyCaptcha',
|
|
539
|
-
headers,
|
|
540
|
-
method: 'POST',
|
|
541
|
-
body: captchaData,
|
|
542
|
-
timeout: this.timeout
|
|
543
|
-
});
|
|
544
|
-
return await this.getApiCallResponseFromResponse(res, mitata === null || mitata === void 0 ? void 0 : mitata.userId, clientIP);
|
|
545
|
-
}
|
|
546
|
-
async getApiCallResponseFromResponse(response, userId, clientIP, defaultMitataCodes) {
|
|
547
|
-
var _a, _b, _c, _d, _f, _g, _h;
|
|
548
|
-
if (response.status !== 200) {
|
|
549
|
-
throw this.APIError(response);
|
|
550
|
-
}
|
|
551
|
-
let match = (_a = (0, headers_1.getHeaderAsInt)(response.headers, netaceaHeaders.match)) !== null && _a !== void 0 ? _a : NaN;
|
|
552
|
-
let mitigate = (_b = (0, headers_1.getHeaderAsInt)(response.headers, netaceaHeaders.mitigate)) !== null && _b !== void 0 ? _b : NaN;
|
|
553
|
-
let captcha = (_c = (0, headers_1.getHeaderAsInt)(response.headers, netaceaHeaders.captcha)) !== null && _c !== void 0 ? _c : NaN;
|
|
554
|
-
if (isNaN(match)) {
|
|
555
|
-
match = (_d = defaultMitataCodes === null || defaultMitataCodes === void 0 ? void 0 : defaultMitataCodes.match) !== null && _d !== void 0 ? _d : 0;
|
|
556
|
-
}
|
|
557
|
-
if (isNaN(mitigate)) {
|
|
558
|
-
mitigate = (_f = defaultMitataCodes === null || defaultMitataCodes === void 0 ? void 0 : defaultMitataCodes.mitigate) !== null && _f !== void 0 ? _f : 0;
|
|
559
|
-
}
|
|
560
|
-
if (isNaN(captcha)) {
|
|
561
|
-
captcha = (_g = defaultMitataCodes === null || defaultMitataCodes === void 0 ? void 0 : defaultMitataCodes.captcha) !== null && _g !== void 0 ? _g : 0;
|
|
562
|
-
}
|
|
563
|
-
let mitataMaxAge = (_h = (0, headers_1.getHeaderAsInt)(response.headers, netaceaHeaders.mitataExpiry)) !== null && _h !== void 0 ? _h : NaN;
|
|
564
|
-
if (isNaN(mitataMaxAge)) {
|
|
565
|
-
mitataMaxAge = 86400;
|
|
566
|
-
}
|
|
567
|
-
const mitata = await this.createMitata(clientIP, userId, match, mitigate, captcha);
|
|
568
|
-
const mitataCaptcha = await this.createMitataCaptcha(response.headers);
|
|
569
|
-
const setCookie = [
|
|
570
|
-
mitata,
|
|
571
|
-
mitataCaptcha
|
|
572
|
-
].filter(c => c !== undefined);
|
|
573
|
-
const eventId = (0, headers_1.getHeader)(response.headers, netaceaHeaders.eventId);
|
|
574
|
-
return {
|
|
575
|
-
status: response.status,
|
|
576
|
-
match,
|
|
577
|
-
mitigate,
|
|
578
|
-
captcha,
|
|
579
|
-
setCookie,
|
|
580
|
-
body: response.body,
|
|
581
|
-
eventId,
|
|
582
|
-
mitataMaxAge
|
|
583
|
-
};
|
|
584
|
-
}
|
|
585
|
-
APIError(response) {
|
|
586
|
-
let message = 'Unknown error';
|
|
587
|
-
switch (response.status) {
|
|
588
|
-
case 403:
|
|
589
|
-
message = 'Invalid credentials';
|
|
590
|
-
break;
|
|
591
|
-
case 500:
|
|
592
|
-
message = 'Server error';
|
|
593
|
-
break;
|
|
594
|
-
case 502:
|
|
595
|
-
message = 'Bad Gateway';
|
|
596
|
-
break;
|
|
597
|
-
case 503:
|
|
598
|
-
message = 'Service Unavailable';
|
|
599
|
-
break;
|
|
600
|
-
case 400:
|
|
601
|
-
message = 'Invalid request';
|
|
602
|
-
break;
|
|
603
|
-
}
|
|
604
|
-
return new Error(`Error reaching Netacea API (${message}), status: ${response.status}`);
|
|
605
|
-
}
|
|
606
|
-
async createMitata(clientIP, userId, match, mitigate, captcha, maxAge = 86400, expiry = undefined) {
|
|
607
|
-
// serve, fail, cookiefail
|
|
608
|
-
const isCaptchaServe = [1, 3, 5].includes(captcha);
|
|
609
|
-
const isHardBlocked = mitigate === 3;
|
|
610
|
-
const expiryDelta = (isCaptchaServe || isHardBlocked)
|
|
611
|
-
? -60
|
|
612
|
-
: this.mitataCookieExpirySeconds;
|
|
613
|
-
const mitataExpiry = expiry !== null && expiry !== void 0 ? expiry : Math.floor(Date.now() / 1000) + expiryDelta;
|
|
614
|
-
if (this.secretKey === undefined) {
|
|
615
|
-
throw new Error('Cannot build cookie without secret key.');
|
|
616
|
-
}
|
|
617
|
-
const mitataCode = [match, mitigate, captcha].join('');
|
|
618
|
-
const mitataValue = (0, netaceaintegrationbase_1.createMitataCookie)(clientIP, userId, mitataExpiry, this.secretKey, mitataCode);
|
|
619
|
-
let maxAgeAttr = maxAge;
|
|
620
|
-
let path;
|
|
621
|
-
let finalCookieAttr;
|
|
622
|
-
if (this.netaceaCookieAttributes !== '') {
|
|
623
|
-
const { extractedAttribute: exctractedMaxAge, cookieAttributes: cookieAttrsWithoutMaxAge } = extractAndRemoveCookieAttr(this.netaceaCookieAttributes, 'Max-Age');
|
|
624
|
-
maxAgeAttr = exctractedMaxAge !== undefined ? Number(exctractedMaxAge) : maxAge;
|
|
625
|
-
const { extractedAttribute: extractedPath, cookieAttributes } = extractAndRemoveCookieAttr(cookieAttrsWithoutMaxAge, 'Path');
|
|
626
|
-
path = extractedPath !== null && extractedPath !== void 0 ? extractedPath : '/';
|
|
627
|
-
finalCookieAttr = cookieAttributes !== null && cookieAttributes !== void 0 ? cookieAttributes : undefined;
|
|
628
|
-
}
|
|
629
|
-
return await this.buildCookieFromValues(this.netaceaCookieName, mitataValue, maxAgeAttr, finalCookieAttr, path);
|
|
630
|
-
}
|
|
631
|
-
async createMitataCaptcha(headers) {
|
|
632
|
-
var _a, _b;
|
|
633
|
-
let setCookieHeaders = (_a = headers['set-cookie']) !== null && _a !== void 0 ? _a : [];
|
|
634
|
-
setCookieHeaders = typeof setCookieHeaders === 'string'
|
|
635
|
-
? [setCookieHeaders]
|
|
636
|
-
: setCookieHeaders;
|
|
637
|
-
const mitataCaptcha = setCookieHeaders
|
|
638
|
-
.find(cookie => cookie.startsWith('_mitatacaptcha='));
|
|
639
|
-
let mitataCaptchaValue;
|
|
640
|
-
let mitataCaptchaMaxAge = '86400';
|
|
641
|
-
if (mitataCaptcha !== undefined && mitataCaptcha !== '') {
|
|
642
|
-
try {
|
|
643
|
-
const parsed = parseSetCookie(mitataCaptcha);
|
|
644
|
-
mitataCaptchaValue = parsed.value;
|
|
645
|
-
mitataCaptchaMaxAge = (_b = extractCookieAttr(parsed.attributes, 'Max-Age')) !== null && _b !== void 0 ? _b : '86400';
|
|
646
|
-
}
|
|
647
|
-
catch (e) {
|
|
648
|
-
return undefined;
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
if (mitataCaptchaValue === '' || mitataCaptchaValue === undefined) {
|
|
652
|
-
return undefined;
|
|
653
|
-
}
|
|
654
|
-
const attributes = removeDuplicateAttrs([
|
|
655
|
-
this.netaceaCaptchaCookieAttributes,
|
|
656
|
-
'Path=/',
|
|
657
|
-
`Max-Age=${mitataCaptchaMaxAge}`
|
|
658
|
-
]);
|
|
659
|
-
mitataCaptchaValue = this.encryptedCookies.includes(this.netaceaCaptchaCookieName)
|
|
660
|
-
? await this.encryptCookieValue(mitataCaptchaValue)
|
|
661
|
-
: mitataCaptchaValue;
|
|
662
|
-
return `${this.netaceaCaptchaCookieName}=${mitataCaptchaValue}; ${attributes}`;
|
|
663
|
-
}
|
|
664
|
-
async buildCookieFromValues(cookieName, value, maxAge, cookieAttributes, path = '/') {
|
|
665
|
-
const cookieValue = this.encryptedCookies.includes(cookieName)
|
|
666
|
-
? await this.encryptCookieValue(value)
|
|
667
|
-
: value;
|
|
668
|
-
const setCookie = `${cookieName}=${cookieValue}; Max-Age=${maxAge}; Path=${path}`;
|
|
669
|
-
return cookieAttributes !== undefined && cookieAttributes !== ''
|
|
670
|
-
? `${setCookie}; ${cookieAttributes}`
|
|
671
|
-
: setCookie;
|
|
672
|
-
}
|
|
673
|
-
async callIngest(args) {
|
|
674
|
-
const body = this.constructWebLog(args);
|
|
675
|
-
if (this.ingestType === netaceaintegrationbase_1.NetaceaIngestType.KINESIS) {
|
|
676
|
-
if (this.kinesis === undefined) {
|
|
677
|
-
console.error('Netacea Error: Unable to log as Kinesis has not been defined.');
|
|
678
|
-
return;
|
|
679
|
-
}
|
|
680
|
-
try {
|
|
681
|
-
await this.kinesis.ingest({
|
|
682
|
-
...body,
|
|
683
|
-
apiKey: this.apiKey
|
|
684
|
-
}, this.makeRequest.bind(this));
|
|
685
|
-
}
|
|
686
|
-
catch (e) {
|
|
687
|
-
console.error('NETACEA Error: ', e.message);
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
else {
|
|
691
|
-
const headers = {
|
|
692
|
-
'X-Netacea-API-Key': this.apiKey,
|
|
693
|
-
'content-type': 'application/json'
|
|
694
|
-
};
|
|
695
|
-
const res = await this.makeIngestApiCall(headers, body);
|
|
696
|
-
if (res.status !== 200) {
|
|
697
|
-
throw this.APIError(res);
|
|
698
|
-
}
|
|
699
|
-
}
|
|
700
|
-
}
|
|
701
|
-
constructWebLog(args) {
|
|
702
|
-
args.bytesSent = args.bytesSent === '' ? '0' : args.bytesSent;
|
|
703
|
-
if (this.logVersion === netaceaintegrationbase_1.NetaceaLogVersion.V2) {
|
|
704
|
-
return this.constructV2WebLog(args);
|
|
705
|
-
}
|
|
706
|
-
return this.constructV1WebLog(args);
|
|
707
|
-
}
|
|
708
|
-
constructV2WebLog({ ip, userAgent, status, method, path, protocol, referer, bytesSent, requestTime, mitataCookie, sessionStatus, integrationType, integrationVersion, xForwardedFor }) {
|
|
709
|
-
var _a;
|
|
710
|
-
const now = new Date();
|
|
711
|
-
// Paths must be prefixed with '/'
|
|
712
|
-
if (path[0] !== '/') {
|
|
713
|
-
path = `/${path}`;
|
|
714
|
-
}
|
|
715
|
-
let actualQuery;
|
|
716
|
-
const splitPath = path.split('?');
|
|
717
|
-
if (splitPath.length > 1) {
|
|
718
|
-
actualQuery = `?${splitPath[1]}`;
|
|
719
|
-
}
|
|
720
|
-
const actualPath = splitPath[0];
|
|
721
|
-
const userId = (_a = (0, netaceaintegrationbase_1.matchMitataCookie)(mitataCookie)) === null || _a === void 0 ? void 0 : _a.userId;
|
|
722
|
-
const log = {
|
|
723
|
-
status,
|
|
724
|
-
method,
|
|
725
|
-
bytes_sent: (0, netaceaintegrationbase_1.safeParseInt)(bytesSent),
|
|
726
|
-
referrer: referer === '' ? undefined : referer,
|
|
727
|
-
request: `${method} ${actualPath}${actualQuery !== null && actualQuery !== void 0 ? actualQuery : ''} ${protocol}`,
|
|
728
|
-
request_time: (0, netaceaintegrationbase_1.safeParseInt)(requestTime),
|
|
729
|
-
integration_type: integrationType,
|
|
730
|
-
integration_version: integrationVersion,
|
|
731
|
-
client: ip,
|
|
732
|
-
user_agent: userAgent,
|
|
733
|
-
bc_type: sessionStatus === '' ? undefined : sessionStatus,
|
|
734
|
-
hour: now.getUTCHours(),
|
|
735
|
-
minute: now.getUTCMinutes(),
|
|
736
|
-
// '2021-08-04T14:22:41.155Z' = toISOString()
|
|
737
|
-
'@timestamp': now.toISOString().replace('Z', '+00:00'),
|
|
738
|
-
path: actualPath,
|
|
739
|
-
protocol,
|
|
740
|
-
query: actualQuery,
|
|
741
|
-
user_id: userId,
|
|
742
|
-
x_forwarded_for: xForwardedFor
|
|
743
|
-
};
|
|
744
|
-
return log;
|
|
745
|
-
}
|
|
746
|
-
constructV1WebLog({ ip, userAgent, status, method, path, protocol, referer, bytesSent, requestTime, mitataCookie, sessionStatus, integrationType, integrationVersion, xForwardedFor }) {
|
|
747
|
-
const timestamp = new Date().toUTCString();
|
|
748
|
-
return {
|
|
749
|
-
Request: `${method} ${path} ${protocol}`,
|
|
750
|
-
TimeLocal: timestamp,
|
|
751
|
-
RealIp: ip,
|
|
752
|
-
UserAgent: userAgent,
|
|
753
|
-
Status: status,
|
|
754
|
-
RequestTime: requestTime === null || requestTime === void 0 ? void 0 : requestTime.toString(),
|
|
755
|
-
BytesSent: bytesSent === null || bytesSent === void 0 ? void 0 : bytesSent.toString(),
|
|
756
|
-
Referer: referer === '' ? '-' : referer,
|
|
757
|
-
NetaceaUserIdCookie: mitataCookie !== null && mitataCookie !== void 0 ? mitataCookie : '',
|
|
758
|
-
NetaceaMitigationApplied: sessionStatus !== null && sessionStatus !== void 0 ? sessionStatus : '',
|
|
759
|
-
IntegrationType: integrationType !== null && integrationType !== void 0 ? integrationType : '',
|
|
760
|
-
IntegrationVersion: integrationVersion !== null && integrationVersion !== void 0 ? integrationVersion : '',
|
|
761
|
-
XForwardedFor: xForwardedFor
|
|
762
|
-
};
|
|
763
|
-
}
|
|
764
|
-
async makeIngestApiCall(headers, body) {
|
|
765
|
-
return await this.makeRequest({
|
|
766
|
-
host: this.ingestServiceUrl,
|
|
767
|
-
method: 'POST',
|
|
768
|
-
path: '/',
|
|
769
|
-
headers,
|
|
770
|
-
body: JSON.stringify(body),
|
|
771
|
-
timeout: this.timeout
|
|
772
|
-
});
|
|
773
|
-
}
|
|
774
|
-
async processIngest(args) {
|
|
775
|
-
var _a;
|
|
776
|
-
if (this.secretKey === undefined) {
|
|
777
|
-
throw new Error('Secret key is required for ingest');
|
|
778
|
-
}
|
|
779
|
-
const cookies = this.getCookieHeader(args);
|
|
780
|
-
const netaceaCookie = await this.readCookie(this.netaceaCookieName, cookies);
|
|
781
|
-
const cookieInfo = (0, netaceaintegrationbase_1.checkMitataCookie)(netaceaCookie, netaceaintegrationbase_1.ingestIgnoredIpValue, this.secretKey);
|
|
782
|
-
if (!cookieInfo.isPrimaryHashValid) {
|
|
783
|
-
return await this.setIngestOnlyMitataCookie(undefined);
|
|
784
|
-
}
|
|
785
|
-
if (cookieInfo.requiresReissue) {
|
|
786
|
-
return await this.setIngestOnlyMitataCookie((_a = cookieInfo.mitata) === null || _a === void 0 ? void 0 : _a.userId);
|
|
787
|
-
}
|
|
788
|
-
return {
|
|
789
|
-
sessionStatus: '',
|
|
790
|
-
setCookie: []
|
|
791
|
-
};
|
|
792
|
-
}
|
|
793
|
-
async setIngestOnlyMitataCookie(userId) {
|
|
794
|
-
const mitataCookie = await this.createMitata(netaceaintegrationbase_1.ingestIgnoredIpValue, userId, 0, 0, 0, ONE_DAY_IN_SECONDS);
|
|
795
|
-
return {
|
|
796
|
-
sessionStatus: '',
|
|
797
|
-
setCookie: [mitataCookie]
|
|
798
|
-
};
|
|
799
|
-
}
|
|
800
|
-
findBestMitigation(match, mitigate, captcha, isCaptchaPost) {
|
|
801
|
-
var _a, _b, _c;
|
|
802
|
-
const UNKNOWN = 'unknown';
|
|
803
|
-
captcha = this.adjustCaptchaCode(captcha, isCaptchaPost);
|
|
804
|
-
let sessionStatus = (_a = matchMap[match]) !== null && _a !== void 0 ? _a : (UNKNOWN + '_');
|
|
805
|
-
sessionStatus += (_b = mitigateMap[mitigate]) !== null && _b !== void 0 ? _b : UNKNOWN;
|
|
806
|
-
let mitigation = bestMitigationMap[mitigate];
|
|
807
|
-
if (captcha !== 0) {
|
|
808
|
-
sessionStatus += ',' + ((_c = captchaMap[captcha]) !== null && _c !== void 0 ? _c : UNKNOWN);
|
|
809
|
-
const bestCaptchaMitigation = bestMitigationCaptchaMap[captcha];
|
|
810
|
-
if (bestCaptchaMitigation !== undefined) {
|
|
811
|
-
mitigation = bestCaptchaMitigation;
|
|
812
|
-
}
|
|
813
|
-
}
|
|
814
|
-
if (this.mitigationType === netaceaintegrationbase_1.NetaceaMitigationType.INJECT) {
|
|
815
|
-
mitigation = mitigationTypes.none;
|
|
816
|
-
}
|
|
817
|
-
return {
|
|
818
|
-
sessionStatus,
|
|
819
|
-
mitigation,
|
|
820
|
-
parts: {
|
|
821
|
-
match,
|
|
822
|
-
mitigate,
|
|
823
|
-
captcha
|
|
824
|
-
}
|
|
825
|
-
};
|
|
826
|
-
}
|
|
827
|
-
adjustCaptchaCode(captcha, isCaptchaPost) {
|
|
828
|
-
let adjustedCaptchaCode = captcha;
|
|
829
|
-
if (!isCaptchaPost) {
|
|
830
|
-
if (captcha === 2) {
|
|
831
|
-
adjustedCaptchaCode = 4;
|
|
832
|
-
}
|
|
833
|
-
else if (captcha === 3) {
|
|
834
|
-
adjustedCaptchaCode = 5;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
return adjustedCaptchaCode;
|
|
838
|
-
}
|
|
839
|
-
async check(netaceaCookie, clientIP, userAgent, accept, host, captchaCookie) {
|
|
840
|
-
var _a, _b;
|
|
841
|
-
let status, match, mitigate, captcha, body, setCookie, eventId;
|
|
842
|
-
if (this.secretKey === undefined) {
|
|
843
|
-
throw new Error('Secret key is required to mitigate');
|
|
844
|
-
}
|
|
845
|
-
const cookieInfo = (0, netaceaintegrationbase_1.checkMitataCookie)(netaceaCookie, clientIP, this.secretKey);
|
|
846
|
-
if (!cookieInfo.isPrimaryHashValid || cookieInfo.requiresReissue) {
|
|
847
|
-
// Get latest mitigation information
|
|
848
|
-
const result = await this.makeMitigateAPICall({
|
|
849
|
-
userId: (_a = cookieInfo.mitata) === null || _a === void 0 ? void 0 : _a.userId,
|
|
850
|
-
clientIP,
|
|
851
|
-
userAgent,
|
|
852
|
-
captchaCookie,
|
|
853
|
-
accept,
|
|
854
|
-
host
|
|
855
|
-
});
|
|
856
|
-
status = result.status;
|
|
857
|
-
match = result.match;
|
|
858
|
-
mitigate = result.mitigate;
|
|
859
|
-
captcha = result.captcha;
|
|
860
|
-
body = result.body;
|
|
861
|
-
setCookie = [
|
|
862
|
-
await this.createMitata(clientIP, (_b = cookieInfo.mitata) === null || _b === void 0 ? void 0 : _b.userId, match, mitigate, captcha, result.mitataMaxAge)
|
|
863
|
-
];
|
|
864
|
-
eventId = result.eventId;
|
|
865
|
-
}
|
|
866
|
-
else {
|
|
867
|
-
status = -1;
|
|
868
|
-
match = cookieInfo.match;
|
|
869
|
-
mitigate = cookieInfo.mitigate;
|
|
870
|
-
captcha = cookieInfo.captcha;
|
|
871
|
-
body = undefined;
|
|
872
|
-
setCookie = [];
|
|
873
|
-
}
|
|
874
|
-
return this.composeResult(body, setCookie, status, match, mitigate, captcha, false, eventId);
|
|
875
|
-
}
|
|
876
|
-
async makeMitigateAPICall({ userId, clientIP, userAgent, captchaCookie, accept, host, isCaptchaGet = false, defaultMitataCodes, trackingId }) {
|
|
877
|
-
const headers = {
|
|
878
|
-
'X-Netacea-API-Key': this.apiKey,
|
|
879
|
-
'X-Netacea-Client-IP': clientIP,
|
|
880
|
-
'user-agent': userAgent,
|
|
881
|
-
cookie: this.buildCookieHeader({
|
|
882
|
-
_mitatacaptcha: captchaCookie
|
|
883
|
-
})
|
|
884
|
-
};
|
|
885
|
-
if (userId !== undefined) {
|
|
886
|
-
headers['X-Netacea-UserId'] = userId;
|
|
887
|
-
}
|
|
888
|
-
if (this.captchaSiteKey !== undefined && this.captchaSecretKey !== undefined) {
|
|
889
|
-
headers['X-Netacea-Captcha-Site-Key'] = this.captchaSiteKey;
|
|
890
|
-
headers['X-Netacea-Captcha-Secret-Key'] = this.captchaSecretKey;
|
|
891
|
-
}
|
|
892
|
-
if (this.dynamicCaptchaContentType && this.netaceaCaptchaPath !== undefined) {
|
|
893
|
-
headers['X-Netacea-Captcha-Content-Type'] = (0, dynamicContentType_1.acceptHeaderToNetaceaContentType)(accept);
|
|
894
|
-
}
|
|
895
|
-
const isJsonRequest = headers['X-Netacea-Captcha-Content-Type'] === 'application/json';
|
|
896
|
-
const trackingIdQuery = trackingId !== undefined ? `?trackingId=${trackingId}` : '';
|
|
897
|
-
const res = await this.makeRequest({
|
|
898
|
-
host: this.mitigationServiceUrl,
|
|
899
|
-
path: isCaptchaGet ? `/captcha${trackingIdQuery}` : '/',
|
|
900
|
-
headers,
|
|
901
|
-
method: 'GET',
|
|
902
|
-
timeout: this.timeout
|
|
903
|
-
});
|
|
904
|
-
if (isJsonRequest && this.netaceaCaptchaPath !== undefined) {
|
|
905
|
-
res.body = (0, dynamicContentType_1.mitSvcJsonResponseToUrlResponse)(res.body, host, this.netaceaCaptchaPath);
|
|
906
|
-
}
|
|
907
|
-
return await this.getApiCallResponseFromResponse(res, userId, clientIP, defaultMitataCodes);
|
|
908
|
-
}
|
|
909
|
-
buildCookieHeader(cookies) {
|
|
910
|
-
let cookiestr = '';
|
|
911
|
-
let separator = '';
|
|
912
|
-
for (const cookie in cookies) {
|
|
913
|
-
const cookieValue = cookies[cookie];
|
|
914
|
-
if (cookieValue !== undefined) {
|
|
915
|
-
cookiestr = `${cookiestr}${separator}${cookie}=${cookieValue}`;
|
|
916
|
-
separator = '; ';
|
|
917
|
-
}
|
|
918
|
-
}
|
|
919
|
-
return cookiestr;
|
|
920
|
-
}
|
|
921
|
-
composeResult(body, setCookie, status, match, mitigate, captcha, isCaptchaPost, eventId) {
|
|
922
|
-
const bestMitigation = this.findBestMitigation(match, mitigate, captcha, isCaptchaPost);
|
|
923
|
-
const result = {
|
|
924
|
-
body,
|
|
925
|
-
apiCallStatus: status,
|
|
926
|
-
setCookie,
|
|
927
|
-
sessionStatus: bestMitigation.sessionStatus,
|
|
928
|
-
mitigation: bestMitigation.mitigation,
|
|
929
|
-
mitigated: [
|
|
930
|
-
mitigationTypes.block,
|
|
931
|
-
mitigationTypes.captcha,
|
|
932
|
-
mitigationTypes.captchaPass
|
|
933
|
-
].includes(bestMitigation.mitigation)
|
|
934
|
-
};
|
|
935
|
-
if (this.mitigationType === netaceaintegrationbase_1.NetaceaMitigationType.INJECT) {
|
|
936
|
-
const injectHeaders = {
|
|
937
|
-
'x-netacea-match': bestMitigation.parts.match.toString(),
|
|
938
|
-
'x-netacea-mitigate': bestMitigation.parts.mitigate.toString(),
|
|
939
|
-
'x-netacea-captcha': bestMitigation.parts.captcha.toString()
|
|
940
|
-
};
|
|
941
|
-
if (eventId !== undefined) {
|
|
942
|
-
injectHeaders['x-netacea-event-id'] = eventId;
|
|
943
|
-
}
|
|
944
|
-
result.injectHeaders = injectHeaders;
|
|
945
|
-
}
|
|
946
|
-
return result;
|
|
947
|
-
}
|
|
948
|
-
}
|
|
949
|
-
Cloudfront.NetaceaCookieHeader = 'x-netacea-cloudfront-mitata-cookie';
|
|
950
|
-
// The `NetaceaTrueUserAgentHeader` header is needed when the Origin server returns an error
|
|
951
|
-
// We need to ingest in OriginResponse, but for some reason cloudfront overrides the header
|
|
952
|
-
Cloudfront.NetaceaTrueUserAgentHeader = 'x-netacea-true-useragent-header';
|
|
953
|
-
exports.default = Cloudfront;
|
|
954
|
-
//# sourceMappingURL=Cloudfront.js.map
|