badmfck-api-server 4.0.73 → 4.0.74
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.
|
@@ -13,6 +13,7 @@ exports.REQ_MICROSERVICE_CALL = new badmfck_signal_1.Req(undefined, "REQ_MICROSE
|
|
|
13
13
|
class MicroserviceClient extends BaseService_1.BaseService {
|
|
14
14
|
static #clients = new Map();
|
|
15
15
|
static #listener = false;
|
|
16
|
+
static #nextID = 1;
|
|
16
17
|
options;
|
|
17
18
|
constructor(opt) {
|
|
18
19
|
super("MicroserviceClient");
|
|
@@ -34,25 +35,28 @@ class MicroserviceClient extends BaseService_1.BaseService {
|
|
|
34
35
|
}
|
|
35
36
|
async requestMicroserviceCall(req) {
|
|
36
37
|
const url = this.options.host + "/__ms_host_control/receiver";
|
|
37
|
-
const ts = (
|
|
38
|
-
const nonce = crypto_1.default.randomBytes(
|
|
38
|
+
const ts = process.hrtime.bigint().toString();
|
|
39
|
+
const nonce = crypto_1.default.randomBytes(12).toString("hex");
|
|
39
40
|
const headers = {
|
|
40
41
|
"Content-Type": "application/json",
|
|
41
42
|
"x-microservice-id": this.options.id,
|
|
42
43
|
"x-microservice-ts": ts,
|
|
43
44
|
"x-microservice-nonce": nonce
|
|
44
45
|
};
|
|
45
|
-
const data = Buffer.from(JSON.stringify(req), "utf8");
|
|
46
46
|
const secret = Buffer.from(this.options.securityKey, "base64");
|
|
47
|
-
const
|
|
48
|
-
const key =
|
|
49
|
-
const iv =
|
|
50
|
-
const aad = Buffer.from(ts
|
|
47
|
+
const hash = crypto_1.default.createHash("sha256").update(nonce + ts + this.options.securityKey).digest();
|
|
48
|
+
const key = secret;
|
|
49
|
+
const iv = hash.subarray(0, 12);
|
|
50
|
+
const aad = Buffer.from(`${ts}.${nonce}.${this.options.id}`, "utf8");
|
|
51
|
+
const data = Buffer.from(JSON.stringify(req), "utf8");
|
|
51
52
|
const cipher = crypto_1.default.createCipheriv("aes-256-gcm", key, iv);
|
|
52
53
|
cipher.setAAD(aad);
|
|
53
54
|
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
|
|
54
55
|
const tag = cipher.getAuthTag();
|
|
55
|
-
const resp = await Http_1.Http.post(url, {
|
|
56
|
+
const resp = await Http_1.Http.post(url, {
|
|
57
|
+
tag: tag.toString("base64"),
|
|
58
|
+
enc: encrypted.toString("base64")
|
|
59
|
+
}, { headers });
|
|
56
60
|
if (!resp.ok)
|
|
57
61
|
return { ...DefaultErrors_1.default.BAD_REQUEST, details: resp.details, stack: [resp.error] };
|
|
58
62
|
const body = resp.data;
|
|
@@ -1,34 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
4
|
};
|
|
28
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
6
|
exports.MicroserviceHost = void 0;
|
|
30
7
|
const BaseService_1 = require("../BaseService");
|
|
31
|
-
const DefaultErrors_1 =
|
|
8
|
+
const DefaultErrors_1 = __importDefault(require("../structures/DefaultErrors"));
|
|
32
9
|
const crypto_1 = __importDefault(require("crypto"));
|
|
33
10
|
class MicroserviceHost extends BaseService_1.BaseService {
|
|
34
11
|
static #calls = new Set();
|
|
@@ -46,62 +23,47 @@ class MicroserviceHost extends BaseService_1.BaseService {
|
|
|
46
23
|
return MicroserviceHost.#instances.get(id) || null;
|
|
47
24
|
}
|
|
48
25
|
async handleIncomingRequest(req) {
|
|
49
|
-
console.log("Handling incoming request for MicroserviceHost:", this.getName());
|
|
50
26
|
const nonce = req.headers["x-microservice-nonce"];
|
|
51
27
|
const ts = req.headers["x-microservice-ts"];
|
|
52
28
|
if (!nonce || !ts)
|
|
53
29
|
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "missing headers" };
|
|
54
|
-
if (ts.length !== 13 || isNaN(+ts))
|
|
55
|
-
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "invalid timestamp" };
|
|
56
|
-
if (+new Date() - (+ts) > 1000 * 60 * 2)
|
|
57
|
-
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "timestamp too old" };
|
|
58
30
|
const checkCall = MicroserviceHost.#calls.has(nonce + "|" + ts);
|
|
59
31
|
if (checkCall)
|
|
60
32
|
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "replay attack detected" };
|
|
61
33
|
MicroserviceHost.#calls.add(nonce + "|" + ts);
|
|
62
|
-
if (MicroserviceHost.#calls.size >
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const key = crypto_1.default.pbkdf2Sync(secret, salt, 100, 32, "sha256");
|
|
70
|
-
const iv = crypto_1.default.pbkdf2Sync(secret, salt, 100, 16, "sha256");
|
|
71
|
-
const aad = Buffer.from(ts + "." + nonce + "." + this.options.id + "." + this.options.password, "utf8");
|
|
72
|
-
const tag = Buffer.from(req.data.tag, "base64");
|
|
73
|
-
const enc = Buffer.from(req.data.enc, "base64");
|
|
74
|
-
const decipher = crypto_1.default.createDecipheriv("aes-256-gcm", key, iv);
|
|
75
|
-
decipher.setAAD(aad);
|
|
76
|
-
decipher.setAuthTag(tag);
|
|
77
|
-
const decrypted = Buffer.concat([decipher.update(enc), decipher.final()]);
|
|
78
|
-
let request = null;
|
|
79
|
-
try {
|
|
80
|
-
request = JSON.parse(decrypted.toString("utf8"));
|
|
81
|
-
}
|
|
82
|
-
catch (e) {
|
|
83
|
-
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "invalid json request" };
|
|
84
|
-
}
|
|
85
|
-
if (!request) {
|
|
86
|
-
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "no request found" };
|
|
87
|
-
}
|
|
88
|
-
if (typeof request !== "object" || !request.requestName) {
|
|
89
|
-
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "invalid request object" };
|
|
90
|
-
}
|
|
91
|
-
const reqCall = this.options.requests.find(r => r.name === request.requestName);
|
|
92
|
-
if (!reqCall) {
|
|
93
|
-
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "request not found: " + request.requestName };
|
|
34
|
+
if (MicroserviceHost.#calls.size > 10000) {
|
|
35
|
+
const iterator = MicroserviceHost.#calls.values();
|
|
36
|
+
for (let i = 0; i < 100; i++) {
|
|
37
|
+
const val = iterator.next().value;
|
|
38
|
+
if (val)
|
|
39
|
+
MicroserviceHost.#calls.delete(val);
|
|
40
|
+
}
|
|
94
41
|
}
|
|
95
|
-
let response = null;
|
|
96
42
|
try {
|
|
97
|
-
|
|
43
|
+
const secret = Buffer.from(this.options.securityKey, "base64");
|
|
44
|
+
const hash = crypto_1.default.createHash("sha256").update(nonce + ts + this.options.securityKey).digest();
|
|
45
|
+
const key = secret;
|
|
46
|
+
const iv = hash.subarray(0, 12);
|
|
47
|
+
const aad = Buffer.from(`${ts}.${nonce}.${this.options.id}`, "utf8");
|
|
48
|
+
const tag = Buffer.from(req.data.tag, "base64");
|
|
49
|
+
const enc = Buffer.from(req.data.enc, "base64");
|
|
50
|
+
const decipher = crypto_1.default.createDecipheriv("aes-256-gcm", key, iv);
|
|
51
|
+
decipher.setAAD(aad);
|
|
52
|
+
decipher.setAuthTag(tag);
|
|
53
|
+
const decrypted = Buffer.concat([decipher.update(enc), decipher.final()]);
|
|
54
|
+
const request = JSON.parse(decrypted.toString("utf8"));
|
|
55
|
+
if (!request || !request.requestName) {
|
|
56
|
+
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "invalid request object" };
|
|
57
|
+
}
|
|
58
|
+
const reqCall = this.options.requests.find(r => r.name === request.requestName);
|
|
59
|
+
if (!reqCall) {
|
|
60
|
+
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "request not found: " + request.requestName };
|
|
61
|
+
}
|
|
62
|
+
return await reqCall.request(request.requestData);
|
|
98
63
|
}
|
|
99
64
|
catch (e) {
|
|
100
|
-
|
|
101
|
-
return e;
|
|
102
|
-
return { ...DefaultErrors_1.default.INTERNAL_SERVER_ERROR, details: "request execution error: " + e?.message };
|
|
65
|
+
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "decryption failed or invalid json" };
|
|
103
66
|
}
|
|
104
|
-
return response;
|
|
105
67
|
}
|
|
106
68
|
}
|
|
107
69
|
exports.MicroserviceHost = MicroserviceHost;
|