perimeterx-js-core 0.29.0 → 0.30.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/lib/cjs/activities/HttpActivityClient.js +20 -17
- package/lib/cjs/config/ConfigurationBase.js +7 -0
- package/lib/cjs/enforcer/utils.js +1 -3
- package/lib/cjs/flow/EndEnforcerFlow.js +2 -2
- package/lib/cjs/phase/impl/SendAsyncActivitiesPhase.js +6 -2
- package/lib/cjs/phase/impl/SendLogsPhase.js +6 -2
- package/lib/cjs/phase/impl/SendTelemetryActivityPhase.js +6 -2
- package/lib/cjs/products/credential_intelligence/CredentialIntelligence.js +32 -8
- package/lib/cjs/utils/constants.js +1 -1
- package/lib/esm/activities/HttpActivityClient.js +18 -12
- package/lib/esm/config/ConfigurationBase.js +3 -0
- package/lib/esm/enforcer/utils.js +1 -3
- package/lib/esm/flow/EndEnforcerFlow.js +2 -2
- package/lib/esm/phase/impl/SendAsyncActivitiesPhase.js +8 -2
- package/lib/esm/phase/impl/SendLogsPhase.js +8 -2
- package/lib/esm/phase/impl/SendTelemetryActivityPhase.js +8 -2
- package/lib/esm/products/credential_intelligence/CredentialIntelligence.js +33 -8
- package/lib/esm/utils/constants.js +1 -1
- package/lib/types/config/ConfigurationBase.d.ts +1 -0
- package/lib/types/config/IConfiguration.d.ts +4 -0
- package/lib/types/phase/impl/SendAsyncActivitiesPhase.d.ts +4 -2
- package/lib/types/phase/impl/SendLogsPhase.d.ts +2 -1
- package/lib/types/phase/impl/SendTelemetryActivityPhase.d.ts +4 -2
- package/lib/types/products/credential_intelligence/CredentialIntelligence.d.ts +5 -1
- package/lib/types/utils/constants.d.ts +1 -1
- package/package.json +1 -1
|
@@ -63,24 +63,21 @@ var HttpActivityClient = /** @class */ (function () {
|
|
|
63
63
|
*/
|
|
64
64
|
HttpActivityClient.prototype.sendActivities = function (context) {
|
|
65
65
|
return __awaiter(this, void 0, void 0, function () {
|
|
66
|
-
var activities
|
|
66
|
+
var activities;
|
|
67
67
|
return __generator(this, function (_a) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
activities
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
return [4 /*yield*/, this.postActivities(activities, context.logger)];
|
|
77
|
-
case 1: return [2 /*return*/, _a.sent()];
|
|
78
|
-
case 2:
|
|
79
|
-
e_1 = _a.sent();
|
|
80
|
-
context.logger.error("unable to send activities - ".concat(e_1));
|
|
81
|
-
return [2 /*return*/, false];
|
|
82
|
-
case 3: return [2 /*return*/];
|
|
68
|
+
try {
|
|
69
|
+
activities = this.createActivities(context);
|
|
70
|
+
if (!activities || activities.length === 0) {
|
|
71
|
+
context.logger.debug('no activities to send');
|
|
72
|
+
return [2 /*return*/, true];
|
|
73
|
+
}
|
|
74
|
+
return [2 /*return*/, this.postActivities(activities, context.logger)];
|
|
83
75
|
}
|
|
76
|
+
catch (e) {
|
|
77
|
+
context.logger.error("unable to send activities - ".concat(e));
|
|
78
|
+
return [2 /*return*/, false];
|
|
79
|
+
}
|
|
80
|
+
return [2 /*return*/];
|
|
84
81
|
});
|
|
85
82
|
});
|
|
86
83
|
};
|
|
@@ -171,11 +168,12 @@ var HttpActivityClient = /** @class */ (function () {
|
|
|
171
168
|
*/
|
|
172
169
|
HttpActivityClient.prototype.postActivities = function (activities, logger) {
|
|
173
170
|
return __awaiter(this, void 0, void 0, function () {
|
|
174
|
-
var url, method, headers, body, req, res;
|
|
171
|
+
var url, method, headers, body, req, res, e_1;
|
|
175
172
|
var _a;
|
|
176
173
|
return __generator(this, function (_b) {
|
|
177
174
|
switch (_b.label) {
|
|
178
175
|
case 0:
|
|
176
|
+
_b.trys.push([0, 2, , 3]);
|
|
179
177
|
url = "".concat(this.config.backendCollectorUrl).concat(constants_1.ACTIVITIES_ENDPOINT);
|
|
180
178
|
method = http_1.HttpMethod.POST;
|
|
181
179
|
headers = (_a = {},
|
|
@@ -192,6 +190,11 @@ var HttpActivityClient = /** @class */ (function () {
|
|
|
192
190
|
case 1:
|
|
193
191
|
res = _b.sent();
|
|
194
192
|
return [2 /*return*/, (res === null || res === void 0 ? void 0 : res.status) === 200];
|
|
193
|
+
case 2:
|
|
194
|
+
e_1 = _b.sent();
|
|
195
|
+
logger.error("failed to post activities - ".concat(e_1));
|
|
196
|
+
return [2 /*return*/, false];
|
|
197
|
+
case 3: return [2 /*return*/];
|
|
195
198
|
}
|
|
196
199
|
});
|
|
197
200
|
});
|
|
@@ -782,6 +782,13 @@ var ConfigurationBase = /** @class */ (function () {
|
|
|
782
782
|
enumerable: false,
|
|
783
783
|
configurable: true
|
|
784
784
|
});
|
|
785
|
+
Object.defineProperty(ConfigurationBase.prototype, "awaitAsyncHttpRequests", {
|
|
786
|
+
get: function () {
|
|
787
|
+
return true;
|
|
788
|
+
},
|
|
789
|
+
enumerable: false,
|
|
790
|
+
configurable: true
|
|
791
|
+
});
|
|
785
792
|
Object.defineProperty(ConfigurationBase.prototype, "isPostEnforceEnabled", {
|
|
786
793
|
get: function () {
|
|
787
794
|
return true;
|
|
@@ -66,9 +66,7 @@ var createEnforcerProducts = function (config, products, base64Utils, hashUtils,
|
|
|
66
66
|
var _a;
|
|
67
67
|
var botDefender = (products === null || products === void 0 ? void 0 : products.bd) || new products_1.BotDefender(config, { base64Utils: base64Utils, ipRangeChecker: ipRangeChecker, urlUtils: urlUtils });
|
|
68
68
|
var accountDefender = (products === null || products === void 0 ? void 0 : products.ad) || new products_1.AccountDefender(config, { base64Utils: base64Utils });
|
|
69
|
-
var credentialIntelligence = config
|
|
70
|
-
? (products === null || products === void 0 ? void 0 : products.ci) || new products_1.CredentialIntelligence(config, { hashUtils: hashUtils, urlUtils: urlUtils })
|
|
71
|
-
: undefined;
|
|
69
|
+
var credentialIntelligence = (products === null || products === void 0 ? void 0 : products.ci) || new products_1.CredentialIntelligence(config, { hashUtils: hashUtils, urlUtils: urlUtils });
|
|
72
70
|
var hypeSaleChallenge = (products === null || products === void 0 ? void 0 : products.hsc) || new products_1.HypeSaleChallenge(config, { base64Utils: base64Utils });
|
|
73
71
|
return _a = {},
|
|
74
72
|
_a[products_1.ProductName.BOT_DEFENDER] = botDefender,
|
|
@@ -23,8 +23,8 @@ var EndEnforcerFlow = /** @class */ (function (_super) {
|
|
|
23
23
|
function EndEnforcerFlow(config, _a) {
|
|
24
24
|
var logServiceClient = _a.logServiceClient, telemetry = _a.telemetry, remoteConfigManager = _a.remoteConfigManager, activityClient = _a.activityClient;
|
|
25
25
|
var phases = [
|
|
26
|
-
new phase_1.SendAsyncActivitiesPhase(activityClient),
|
|
27
|
-
new phase_1.SendTelemetryActivityPhase(telemetry),
|
|
26
|
+
new phase_1.SendAsyncActivitiesPhase(config, activityClient),
|
|
27
|
+
new phase_1.SendTelemetryActivityPhase(config, telemetry),
|
|
28
28
|
];
|
|
29
29
|
if (remoteConfigManager) {
|
|
30
30
|
phases.push(new phase_1.UpdateRemoteConfigPhase(config, remoteConfigManager));
|
|
@@ -42,16 +42,20 @@ var action_1 = require("../../action/index.js");
|
|
|
42
42
|
* The `SendAsyncActivitiesPhase` class is responsible for sending all necessary asynchronous activities based on the context.
|
|
43
43
|
*/
|
|
44
44
|
var SendAsyncActivitiesPhase = /** @class */ (function () {
|
|
45
|
-
function SendAsyncActivitiesPhase(activityClient) {
|
|
45
|
+
function SendAsyncActivitiesPhase(config, activityClient) {
|
|
46
|
+
this.config = config;
|
|
46
47
|
this.activityClient = activityClient;
|
|
47
48
|
}
|
|
48
49
|
SendAsyncActivitiesPhase.prototype.execute = function (context) {
|
|
49
50
|
return __awaiter(this, void 0, void 0, function () {
|
|
51
|
+
var promise;
|
|
50
52
|
return __generator(this, function (_a) {
|
|
51
53
|
switch (_a.label) {
|
|
52
54
|
case 0:
|
|
53
55
|
if (![action_1.Action.PASS_REQUEST, action_1.Action.BLOCK, action_1.Action.SIMULATED_BLOCK].includes(context.action)) return [3 /*break*/, 2];
|
|
54
|
-
|
|
56
|
+
promise = this.activityClient.sendActivities(context);
|
|
57
|
+
if (!this.config.awaitAsyncHttpRequests) return [3 /*break*/, 2];
|
|
58
|
+
return [4 /*yield*/, promise];
|
|
55
59
|
case 1:
|
|
56
60
|
_a.sent();
|
|
57
61
|
_a.label = 2;
|
|
@@ -41,16 +41,20 @@ exports.SendLogsPhase = void 0;
|
|
|
41
41
|
* The `SendLogsPhase` class is responsible for sending logs to the HUMAN logging service.
|
|
42
42
|
*/
|
|
43
43
|
var SendLogsPhase = /** @class */ (function () {
|
|
44
|
-
function SendLogsPhase(
|
|
44
|
+
function SendLogsPhase(config, logServiceClient) {
|
|
45
|
+
this.config = config;
|
|
45
46
|
this.logServiceClient = logServiceClient;
|
|
46
47
|
}
|
|
47
48
|
SendLogsPhase.prototype.execute = function (context) {
|
|
48
49
|
return __awaiter(this, void 0, void 0, function () {
|
|
50
|
+
var promise;
|
|
49
51
|
return __generator(this, function (_a) {
|
|
50
52
|
switch (_a.label) {
|
|
51
53
|
case 0:
|
|
52
54
|
if (!context.shouldSendLogs) return [3 /*break*/, 2];
|
|
53
|
-
|
|
55
|
+
promise = this.logServiceClient.sendLogs(context);
|
|
56
|
+
if (!this.config.awaitAsyncHttpRequests) return [3 /*break*/, 2];
|
|
57
|
+
return [4 /*yield*/, promise];
|
|
54
58
|
case 1:
|
|
55
59
|
_a.sent();
|
|
56
60
|
_a.label = 2;
|
|
@@ -41,16 +41,20 @@ exports.SendTelemetryActivityPhase = void 0;
|
|
|
41
41
|
* The `SendTelemetryActivityPhase` class is responsible for sending the telemetry activity if necessary.
|
|
42
42
|
*/
|
|
43
43
|
var SendTelemetryActivityPhase = /** @class */ (function () {
|
|
44
|
-
function SendTelemetryActivityPhase(telemetry) {
|
|
44
|
+
function SendTelemetryActivityPhase(config, telemetry) {
|
|
45
|
+
this.config = config;
|
|
45
46
|
this.telemetry = telemetry;
|
|
46
47
|
}
|
|
47
48
|
SendTelemetryActivityPhase.prototype.execute = function (context) {
|
|
48
49
|
return __awaiter(this, void 0, void 0, function () {
|
|
50
|
+
var promise;
|
|
49
51
|
return __generator(this, function (_a) {
|
|
50
52
|
switch (_a.label) {
|
|
51
53
|
case 0:
|
|
52
54
|
if (!context.shouldSendTelemetry) return [3 /*break*/, 2];
|
|
53
|
-
|
|
55
|
+
promise = this.telemetry.sendTelemetry(context);
|
|
56
|
+
if (!this.config.awaitAsyncHttpRequests) return [3 /*break*/, 2];
|
|
57
|
+
return [4 /*yield*/, promise];
|
|
54
58
|
case 1:
|
|
55
59
|
_a.sent();
|
|
56
60
|
_a.label = 2;
|
|
@@ -55,7 +55,9 @@ var constants_1 = require("./constants.js");
|
|
|
55
55
|
var CredentialIntelligence = /** @class */ (function () {
|
|
56
56
|
function CredentialIntelligence(config, options) {
|
|
57
57
|
this.config = config;
|
|
58
|
-
this.
|
|
58
|
+
this.options = options;
|
|
59
|
+
this.remoteConfigVersion = config.remoteConfigVersion;
|
|
60
|
+
this.endpointManager = new endpoint_1.CredentialEndpointManager(this.initializeCredentialIntelligenceEndpoints(this.config, this.options));
|
|
59
61
|
}
|
|
60
62
|
CredentialIntelligence.prototype.enrichContextFromRequest = function (context) {
|
|
61
63
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -63,6 +65,12 @@ var CredentialIntelligence = /** @class */ (function () {
|
|
|
63
65
|
return __generator(this, function (_a) {
|
|
64
66
|
switch (_a.label) {
|
|
65
67
|
case 0:
|
|
68
|
+
if (!this.config.ciEnabled) {
|
|
69
|
+
return [2 /*return*/, null];
|
|
70
|
+
}
|
|
71
|
+
if (this.shouldRefreshCredentialIntelligenceEndpoints()) {
|
|
72
|
+
this.refreshCredentialIntelligenceEndpoints();
|
|
73
|
+
}
|
|
66
74
|
endpointIndex = this.endpointManager.getEndpointIndex(context);
|
|
67
75
|
if (endpointIndex === -1) {
|
|
68
76
|
return [2 /*return*/, null];
|
|
@@ -159,14 +167,30 @@ var CredentialIntelligence = /** @class */ (function () {
|
|
|
159
167
|
request.headers.set(constants_1.ADDITIONAL_S2S_URL_HEADER_NAME, "".concat(this.config.backendCollectorUrl).concat(activities_1.ACTIVITIES_ENDPOINT));
|
|
160
168
|
};
|
|
161
169
|
CredentialIntelligence.prototype.initializeCredentialIntelligenceEndpoints = function (config, options) {
|
|
162
|
-
|
|
170
|
+
var _this = this;
|
|
171
|
+
return config.ciEndpoints
|
|
172
|
+
.map(function (endpointConfig) {
|
|
163
173
|
var _a;
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
174
|
+
try {
|
|
175
|
+
var matcher = endpoint_1.CredentialIntelligenceEndpointMatcherFactory.create(endpointConfig);
|
|
176
|
+
var extractor = endpoint_1.CredentialExtractorFactory.create(endpointConfig, options.urlUtils);
|
|
177
|
+
var protocol = endpoint_1.CredentialIntelligenceHashProtocolFactory.create(((_a = endpointConfig.protocol) !== null && _a !== void 0 ? _a : config.ciDefaultVersion), options.hashUtils);
|
|
178
|
+
var loginSuccessfulParser = endpoint_1.LoginSuccessfulParserFactory.create(config, endpointConfig);
|
|
179
|
+
return new endpoint_1.CredentialEndpoint(matcher, extractor, protocol, loginSuccessfulParser);
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
_this.config.logger.error("caught error initializing credential intelligence endpoint: ".concat(error));
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
})
|
|
186
|
+
.filter(function (endpoint) { return endpoint !== null; });
|
|
187
|
+
};
|
|
188
|
+
CredentialIntelligence.prototype.shouldRefreshCredentialIntelligenceEndpoints = function () {
|
|
189
|
+
return this.remoteConfigVersion !== this.config.remoteConfigVersion;
|
|
190
|
+
};
|
|
191
|
+
CredentialIntelligence.prototype.refreshCredentialIntelligenceEndpoints = function () {
|
|
192
|
+
this.remoteConfigVersion = this.config.remoteConfigVersion;
|
|
193
|
+
this.endpointManager = new endpoint_1.CredentialEndpointManager(this.initializeCredentialIntelligenceEndpoints(this.config, this.options));
|
|
170
194
|
};
|
|
171
195
|
return CredentialIntelligence;
|
|
172
196
|
}());
|
|
@@ -15,4 +15,4 @@ exports.PUSH_DATA_FEATURE_HEADER_NAME = 'x-px-feature';
|
|
|
15
15
|
exports.EMAIL_ADDRESS_REGEX = /^[a-zA-Z0-9_+&*-]+(?:\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,7}$/;
|
|
16
16
|
exports.URL_REGEX = /^(https?:)\/\/(([^@\s:\/]+):?([^@\s\/]*)@)?(([^:\/?#]*)(?:\:([0-9]+))?)(\/?[^?#]*)(\?[^#]*|)(#.*|)$/;
|
|
17
17
|
exports.REGEX_STRUCTURE = /^\/(.+?)\/([gimsuyvd]*)$/;
|
|
18
|
-
exports.CORE_MODULE_VERSION = 'JS Core 0.
|
|
18
|
+
exports.CORE_MODULE_VERSION = 'JS Core 0.30.1';
|
|
@@ -31,7 +31,7 @@ export class HttpActivityClient {
|
|
|
31
31
|
context.logger.debug('no activities to send');
|
|
32
32
|
return true;
|
|
33
33
|
}
|
|
34
|
-
return
|
|
34
|
+
return this.postActivities(activities, context.logger);
|
|
35
35
|
}
|
|
36
36
|
catch (e) {
|
|
37
37
|
context.logger.error(`unable to send activities - ${e}`);
|
|
@@ -124,16 +124,22 @@ export class HttpActivityClient {
|
|
|
124
124
|
* @protected
|
|
125
125
|
*/
|
|
126
126
|
async postActivities(activities, logger) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
127
|
+
try {
|
|
128
|
+
const url = `${this.config.backendCollectorUrl}${ACTIVITIES_ENDPOINT}`;
|
|
129
|
+
const method = HttpMethod.POST;
|
|
130
|
+
const headers = {
|
|
131
|
+
[CONTENT_TYPE_HEADER_NAME]: [ContentType.APPLICATION_JSON],
|
|
132
|
+
[AUTHORIZATION_HEADER_NAME]: [getAuthorizationHeader(this.config.authToken)],
|
|
133
|
+
};
|
|
134
|
+
const body = activities.length === 1 ? JSON.stringify(activities[0]) : JSON.stringify(activities);
|
|
135
|
+
logger.debug(`sending ${activities.map(({ type }) => `${type} activity`).join(', ')} to ${url}`);
|
|
136
|
+
const req = new OutgoingRequestImpl({ url, method, headers, body });
|
|
137
|
+
const res = await this.httpClient.send(req, { timeoutMs: this.config.asyncTimeout });
|
|
138
|
+
return res?.status === 200;
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
logger.error(`failed to post activities - ${e}`);
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
138
144
|
}
|
|
139
145
|
}
|
|
@@ -68,9 +68,7 @@ export const createEnforcerInitializationBlock = (config, options) => {
|
|
|
68
68
|
export const createEnforcerProducts = (config, products, base64Utils, hashUtils, urlUtils, ipRangeChecker) => {
|
|
69
69
|
const botDefender = products?.bd || new BotDefender(config, { base64Utils, ipRangeChecker, urlUtils });
|
|
70
70
|
const accountDefender = products?.ad || new AccountDefender(config, { base64Utils });
|
|
71
|
-
const credentialIntelligence = config
|
|
72
|
-
? products?.ci || new CredentialIntelligence(config, { hashUtils, urlUtils })
|
|
73
|
-
: undefined;
|
|
71
|
+
const credentialIntelligence = products?.ci || new CredentialIntelligence(config, { hashUtils, urlUtils });
|
|
74
72
|
const hypeSaleChallenge = products?.hsc || new HypeSaleChallenge(config, { base64Utils });
|
|
75
73
|
return {
|
|
76
74
|
[ProductName.BOT_DEFENDER]: botDefender,
|
|
@@ -3,8 +3,8 @@ import { Flow } from './Flow.js';
|
|
|
3
3
|
export class EndEnforcerFlow extends Flow {
|
|
4
4
|
constructor(config, { logServiceClient, telemetry, remoteConfigManager, activityClient, }) {
|
|
5
5
|
const phases = [
|
|
6
|
-
new SendAsyncActivitiesPhase(activityClient),
|
|
7
|
-
new SendTelemetryActivityPhase(telemetry),
|
|
6
|
+
new SendAsyncActivitiesPhase(config, activityClient),
|
|
7
|
+
new SendTelemetryActivityPhase(config, telemetry),
|
|
8
8
|
];
|
|
9
9
|
if (remoteConfigManager) {
|
|
10
10
|
phases.push(new UpdateRemoteConfigPhase(config, remoteConfigManager));
|
|
@@ -3,13 +3,19 @@ import { Action } from '../../action/index.js';
|
|
|
3
3
|
* The `SendAsyncActivitiesPhase` class is responsible for sending all necessary asynchronous activities based on the context.
|
|
4
4
|
*/
|
|
5
5
|
export class SendAsyncActivitiesPhase {
|
|
6
|
+
config;
|
|
6
7
|
activityClient;
|
|
7
|
-
constructor(activityClient) {
|
|
8
|
+
constructor(config, activityClient) {
|
|
9
|
+
this.config = config;
|
|
8
10
|
this.activityClient = activityClient;
|
|
9
11
|
}
|
|
10
12
|
async execute(context) {
|
|
11
13
|
if ([Action.PASS_REQUEST, Action.BLOCK, Action.SIMULATED_BLOCK].includes(context.action)) {
|
|
12
|
-
|
|
14
|
+
// ensure error handling is done in the sendActivities method
|
|
15
|
+
const promise = this.activityClient.sendActivities(context);
|
|
16
|
+
if (this.config.awaitAsyncHttpRequests) {
|
|
17
|
+
await promise;
|
|
18
|
+
}
|
|
13
19
|
}
|
|
14
20
|
return { done: false };
|
|
15
21
|
}
|
|
@@ -2,13 +2,19 @@
|
|
|
2
2
|
* The `SendLogsPhase` class is responsible for sending logs to the HUMAN logging service.
|
|
3
3
|
*/
|
|
4
4
|
export class SendLogsPhase {
|
|
5
|
+
config;
|
|
5
6
|
logServiceClient;
|
|
6
|
-
constructor(
|
|
7
|
+
constructor(config, logServiceClient) {
|
|
8
|
+
this.config = config;
|
|
7
9
|
this.logServiceClient = logServiceClient;
|
|
8
10
|
}
|
|
9
11
|
async execute(context) {
|
|
10
12
|
if (context.shouldSendLogs) {
|
|
11
|
-
|
|
13
|
+
// ensure error handling is done in the sendLogs method
|
|
14
|
+
const promise = this.logServiceClient.sendLogs(context);
|
|
15
|
+
if (this.config.awaitAsyncHttpRequests) {
|
|
16
|
+
await promise;
|
|
17
|
+
}
|
|
12
18
|
}
|
|
13
19
|
return { done: false };
|
|
14
20
|
}
|
|
@@ -2,13 +2,19 @@
|
|
|
2
2
|
* The `SendTelemetryActivityPhase` class is responsible for sending the telemetry activity if necessary.
|
|
3
3
|
*/
|
|
4
4
|
export class SendTelemetryActivityPhase {
|
|
5
|
+
config;
|
|
5
6
|
telemetry;
|
|
6
|
-
constructor(telemetry) {
|
|
7
|
+
constructor(config, telemetry) {
|
|
8
|
+
this.config = config;
|
|
7
9
|
this.telemetry = telemetry;
|
|
8
10
|
}
|
|
9
11
|
async execute(context) {
|
|
10
12
|
if (context.shouldSendTelemetry) {
|
|
11
|
-
|
|
13
|
+
// ensure error handling is done in the sendTelemetry method
|
|
14
|
+
const promise = this.telemetry.sendTelemetry(context);
|
|
15
|
+
if (this.config.awaitAsyncHttpRequests) {
|
|
16
|
+
await promise;
|
|
17
|
+
}
|
|
12
18
|
}
|
|
13
19
|
return { done: false };
|
|
14
20
|
}
|
|
@@ -4,12 +4,22 @@ import { CredentialEndpoint, CredentialEndpointManager, CredentialExtractorFacto
|
|
|
4
4
|
import { ADDITIONAL_S2S_ACTIVITY_HEADER_NAME, ADDITIONAL_S2S_URL_HEADER_NAME, COMPROMISED_CREDENTIALS_HEADER_VALUE, } from './constants.js';
|
|
5
5
|
export class CredentialIntelligence {
|
|
6
6
|
config;
|
|
7
|
+
options;
|
|
8
|
+
remoteConfigVersion;
|
|
7
9
|
endpointManager;
|
|
8
10
|
constructor(config, options) {
|
|
9
11
|
this.config = config;
|
|
10
|
-
this.
|
|
12
|
+
this.options = options;
|
|
13
|
+
this.remoteConfigVersion = config.remoteConfigVersion;
|
|
14
|
+
this.endpointManager = new CredentialEndpointManager(this.initializeCredentialIntelligenceEndpoints(this.config, this.options));
|
|
11
15
|
}
|
|
12
16
|
async enrichContextFromRequest(context) {
|
|
17
|
+
if (!this.config.ciEnabled) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
if (this.shouldRefreshCredentialIntelligenceEndpoints()) {
|
|
21
|
+
this.refreshCredentialIntelligenceEndpoints();
|
|
22
|
+
}
|
|
13
23
|
const endpointIndex = this.endpointManager.getEndpointIndex(context);
|
|
14
24
|
if (endpointIndex === -1) {
|
|
15
25
|
return null;
|
|
@@ -66,12 +76,27 @@ export class CredentialIntelligence {
|
|
|
66
76
|
request.headers.set(ADDITIONAL_S2S_URL_HEADER_NAME, `${this.config.backendCollectorUrl}${ACTIVITIES_ENDPOINT}`);
|
|
67
77
|
}
|
|
68
78
|
initializeCredentialIntelligenceEndpoints(config, options) {
|
|
69
|
-
return config.ciEndpoints
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
return config.ciEndpoints
|
|
80
|
+
.map((endpointConfig) => {
|
|
81
|
+
try {
|
|
82
|
+
const matcher = CredentialIntelligenceEndpointMatcherFactory.create(endpointConfig);
|
|
83
|
+
const extractor = CredentialExtractorFactory.create(endpointConfig, options.urlUtils);
|
|
84
|
+
const protocol = CredentialIntelligenceHashProtocolFactory.create((endpointConfig.protocol ?? config.ciDefaultVersion), options.hashUtils);
|
|
85
|
+
const loginSuccessfulParser = LoginSuccessfulParserFactory.create(config, endpointConfig);
|
|
86
|
+
return new CredentialEndpoint(matcher, extractor, protocol, loginSuccessfulParser);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
this.config.logger.error(`caught error initializing credential intelligence endpoint: ${error}`);
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
})
|
|
93
|
+
.filter((endpoint) => endpoint !== null);
|
|
94
|
+
}
|
|
95
|
+
shouldRefreshCredentialIntelligenceEndpoints() {
|
|
96
|
+
return this.remoteConfigVersion !== this.config.remoteConfigVersion;
|
|
97
|
+
}
|
|
98
|
+
refreshCredentialIntelligenceEndpoints() {
|
|
99
|
+
this.remoteConfigVersion = this.config.remoteConfigVersion;
|
|
100
|
+
this.endpointManager = new CredentialEndpointManager(this.initializeCredentialIntelligenceEndpoints(this.config, this.options));
|
|
76
101
|
}
|
|
77
102
|
}
|
|
@@ -12,4 +12,4 @@ export const PUSH_DATA_FEATURE_HEADER_NAME = 'x-px-feature';
|
|
|
12
12
|
export const EMAIL_ADDRESS_REGEX = /^[a-zA-Z0-9_+&*-]+(?:\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,7}$/;
|
|
13
13
|
export const URL_REGEX = /^(https?:)\/\/(([^@\s:\/]+):?([^@\s\/]*)@)?(([^:\/?#]*)(?:\:([0-9]+))?)(\/?[^?#]*)(\?[^#]*|)(#.*|)$/;
|
|
14
14
|
export const REGEX_STRUCTURE = /^\/(.+?)\/([gimsuyvd]*)$/;
|
|
15
|
-
export const CORE_MODULE_VERSION = 'JS Core 0.
|
|
15
|
+
export const CORE_MODULE_VERSION = 'JS Core 0.30.1';
|
|
@@ -144,5 +144,6 @@ export declare abstract class ConfigurationBase<Req, Res, Added, Removed extends
|
|
|
144
144
|
get snippetInjectionEnabled(): boolean;
|
|
145
145
|
get createCustomSnippet(): CustomSnippetFunction<Req, Res, Added, Removed> | null;
|
|
146
146
|
get enableBlockedUrlOnCaptchaBlockPage(): boolean;
|
|
147
|
+
get awaitAsyncHttpRequests(): boolean;
|
|
147
148
|
get isPostEnforceEnabled(): boolean;
|
|
148
149
|
}
|
|
@@ -396,6 +396,10 @@ export interface IConfiguration<Req, Res, Added, Removed> {
|
|
|
396
396
|
* Whether the enforcer has access to the HTTP response, which is required for the postEnforce function call
|
|
397
397
|
*/
|
|
398
398
|
readonly isPostEnforceEnabled: boolean;
|
|
399
|
+
/**
|
|
400
|
+
* Whether to await asynchronous HTTP requests (e.g., async activities, remote logger, telemetry)
|
|
401
|
+
*/
|
|
402
|
+
readonly awaitAsyncHttpRequests: boolean;
|
|
399
403
|
/**
|
|
400
404
|
* The version of the token the enforcer is able to parse.
|
|
401
405
|
*/
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { IConfiguration } from '../../config';
|
|
1
2
|
import { IContext } from '../../context';
|
|
2
3
|
import { IActivityClient } from '../../activities';
|
|
3
4
|
import { PhaseResult } from '../PhaseResult';
|
|
@@ -5,8 +6,9 @@ import { IPhase } from '../IPhase';
|
|
|
5
6
|
/**
|
|
6
7
|
* The `SendAsyncActivitiesPhase` class is responsible for sending all necessary asynchronous activities based on the context.
|
|
7
8
|
*/
|
|
8
|
-
export declare class SendAsyncActivitiesPhase<Req, Res> implements IPhase<Req, Res> {
|
|
9
|
+
export declare class SendAsyncActivitiesPhase<Req, Res, Added, Removed> implements IPhase<Req, Res> {
|
|
10
|
+
protected readonly config: IConfiguration<Req, Res, Added, Removed>;
|
|
9
11
|
protected readonly activityClient: IActivityClient<Req, Res>;
|
|
10
|
-
constructor(activityClient: IActivityClient<Req, Res>);
|
|
12
|
+
constructor(config: IConfiguration<Req, Res, Added, Removed>, activityClient: IActivityClient<Req, Res>);
|
|
11
13
|
execute(context: IContext<Req, Res>): Promise<PhaseResult>;
|
|
12
14
|
}
|
|
@@ -7,7 +7,8 @@ import { ILogServiceClient } from '../../logger';
|
|
|
7
7
|
* The `SendLogsPhase` class is responsible for sending logs to the HUMAN logging service.
|
|
8
8
|
*/
|
|
9
9
|
export declare class SendLogsPhase<Req, Res, Added, Removed> implements IPhase<Req, Res> {
|
|
10
|
+
private readonly config;
|
|
10
11
|
private readonly logServiceClient;
|
|
11
|
-
constructor(
|
|
12
|
+
constructor(config: IConfiguration<Req, Res, Added, Removed>, logServiceClient: ILogServiceClient<Req, Res>);
|
|
12
13
|
execute(context: IContext<Req, Res>): Promise<PhaseResult>;
|
|
13
14
|
}
|
|
@@ -2,12 +2,14 @@ import { IPhase } from '../IPhase';
|
|
|
2
2
|
import { PhaseResult } from '../PhaseResult';
|
|
3
3
|
import { IContext } from '../../context';
|
|
4
4
|
import { ITelemetry } from '../../telemetry';
|
|
5
|
+
import { IConfiguration } from '../../config';
|
|
5
6
|
/**
|
|
6
7
|
* The `SendTelemetryActivityPhase` class is responsible for sending the telemetry activity if necessary.
|
|
7
8
|
*/
|
|
8
|
-
export declare class SendTelemetryActivityPhase<Req, Res> implements IPhase<Req, Res> {
|
|
9
|
+
export declare class SendTelemetryActivityPhase<Req, Res, Added, Removed> implements IPhase<Req, Res> {
|
|
10
|
+
protected readonly config: IConfiguration<Req, Res, Added, Removed>;
|
|
9
11
|
protected readonly telemetry: ITelemetry<Req, Res>;
|
|
10
|
-
constructor(telemetry: ITelemetry<Req, Res>);
|
|
12
|
+
constructor(config: IConfiguration<Req, Res, Added, Removed>, telemetry: ITelemetry<Req, Res>);
|
|
11
13
|
execute(context: IContext<Req, Res>): Promise<PhaseResult>;
|
|
12
14
|
protected sendTelemetry(context: IContext<Req, Res>): Promise<void>;
|
|
13
15
|
}
|
|
@@ -11,7 +11,9 @@ export type CredentialIntelligenceOptions = {
|
|
|
11
11
|
};
|
|
12
12
|
export declare class CredentialIntelligence<Req, Res, Added, Removed> implements ICredentialIntelligence<Req, Res> {
|
|
13
13
|
protected readonly config: IConfiguration<Req, Res, Added, Removed>;
|
|
14
|
-
protected readonly
|
|
14
|
+
protected readonly options: CredentialIntelligenceOptions;
|
|
15
|
+
protected remoteConfigVersion: number;
|
|
16
|
+
protected endpointManager: CredentialEndpointManager<Req, Res>;
|
|
15
17
|
constructor(config: IConfiguration<Req, Res, Added, Removed>, options: CredentialIntelligenceOptions);
|
|
16
18
|
enrichContextFromRequest(context: ReadonlyContext<Req, Res>): Promise<CredentialIntelligenceData | null>;
|
|
17
19
|
enrichContextFromRiskApi(context: ReadonlyContext<Req, Res>): Promise<Partial<CredentialIntelligenceData> | null>;
|
|
@@ -23,4 +25,6 @@ export declare class CredentialIntelligence<Req, Res, Added, Removed> implements
|
|
|
23
25
|
protected shouldSetAdditionalS2SActivityHeaders(): boolean;
|
|
24
26
|
protected setAdditionalS2SActivityHeaders(request: IIncomingRequest<Req>, context: ReadonlyContext<Req, Res>): void;
|
|
25
27
|
protected initializeCredentialIntelligenceEndpoints(config: IConfiguration<Req, Res, Added, Removed>, options: CredentialIntelligenceOptions): ICredentialEndpoint<Req, Res>[];
|
|
28
|
+
protected shouldRefreshCredentialIntelligenceEndpoints(): boolean;
|
|
29
|
+
protected refreshCredentialIntelligenceEndpoints(): void;
|
|
26
30
|
}
|
|
@@ -12,4 +12,4 @@ export declare const PUSH_DATA_FEATURE_HEADER_NAME = "x-px-feature";
|
|
|
12
12
|
export declare const EMAIL_ADDRESS_REGEX: RegExp;
|
|
13
13
|
export declare const URL_REGEX: RegExp;
|
|
14
14
|
export declare const REGEX_STRUCTURE: RegExp;
|
|
15
|
-
export declare const CORE_MODULE_VERSION = "JS Core 0.
|
|
15
|
+
export declare const CORE_MODULE_VERSION = "JS Core 0.30.1";
|