badmfck-api-server 3.9.95 → 3.9.97
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/apiServer/APIService.js +3 -1
- package/dist/apiServer/external/ExternalService.js +1 -1
- package/dist/apiServer/external/MicroserviceClient.d.ts +22 -1
- package/dist/apiServer/external/MicroserviceClient.js +55 -2
- package/dist/apiServer/external/MicroserviceHost.d.ts +14 -1
- package/dist/apiServer/external/MicroserviceHost.js +99 -2
- package/dist/apiServer/external/MicroserviceHostController.d.ts +6 -0
- package/dist/apiServer/external/MicroserviceHostController.js +55 -0
- package/package.json +1 -1
|
@@ -45,6 +45,7 @@ const MonitorService_1 = require("./MonitorService");
|
|
|
45
45
|
const MysqlAdapter_1 = require("./db/MysqlAdapter");
|
|
46
46
|
const DocumentService_1 = require("./DocumentService");
|
|
47
47
|
const Documentation_1 = require("./documentation/Documentation");
|
|
48
|
+
const MicroserviceHostController_1 = require("./external/MicroserviceHostController");
|
|
48
49
|
let nextLogID = 0;
|
|
49
50
|
function defaultOptions() {
|
|
50
51
|
return {
|
|
@@ -92,7 +93,7 @@ async function Initializer(services) {
|
|
|
92
93
|
}
|
|
93
94
|
exports.Initializer = Initializer;
|
|
94
95
|
class APIService extends BaseService_1.BaseService {
|
|
95
|
-
version = "3.9.
|
|
96
|
+
version = "3.9.97";
|
|
96
97
|
options;
|
|
97
98
|
monitor = null;
|
|
98
99
|
started = new Date();
|
|
@@ -122,6 +123,7 @@ class APIService extends BaseService_1.BaseService {
|
|
|
122
123
|
this.options.endpoints.push(new Monitor_1.Monitor(this.options));
|
|
123
124
|
this.options.endpoints.push(new Documentation_1.Documentation(this.options));
|
|
124
125
|
this.options.endpoints.push(new ExternalServiceEndpoint_1.ExternalServiceEndpoint());
|
|
126
|
+
this.options.endpoints.push(new MicroserviceHostController_1.MicroserviceHostController());
|
|
125
127
|
new DocumentService_1.DocumentGenerator(this.options.endpoints);
|
|
126
128
|
this.monitor = new MonitorService_1.MonitorService();
|
|
127
129
|
this.monitor.init();
|
|
@@ -99,7 +99,7 @@ class ExternalService extends BaseService_1.BaseService {
|
|
|
99
99
|
if (!resp.ok) {
|
|
100
100
|
return { ...DefaultErrors_1.default.BAD_REQUEST, details: resp.details, stack: resp.error };
|
|
101
101
|
}
|
|
102
|
-
const json =
|
|
102
|
+
const json = resp.data;
|
|
103
103
|
if (typeof json === "object" && "error" in json)
|
|
104
104
|
return json.error;
|
|
105
105
|
if (typeof json === "object" && "data" in json)
|
|
@@ -1,4 +1,25 @@
|
|
|
1
|
+
import { Req } from "badmfck-signal";
|
|
1
2
|
import { BaseService } from "../BaseService";
|
|
3
|
+
import { IError } from "../structures/Interfaces";
|
|
4
|
+
export interface IMicroserviceClientOptions {
|
|
5
|
+
id: string;
|
|
6
|
+
securityKey: string;
|
|
7
|
+
host: string;
|
|
8
|
+
password: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const REQ_MICROSERVICE_CALL: Req<{
|
|
11
|
+
id: string;
|
|
12
|
+
requestName: string;
|
|
13
|
+
requestData: any;
|
|
14
|
+
}, any>;
|
|
2
15
|
export declare class MicroserviceClient extends BaseService {
|
|
3
|
-
|
|
16
|
+
#private;
|
|
17
|
+
options: IMicroserviceClientOptions;
|
|
18
|
+
constructor(opt: IMicroserviceClientOptions);
|
|
19
|
+
init(): Promise<void>;
|
|
20
|
+
requestMicroserviceCall(req: {
|
|
21
|
+
id: string;
|
|
22
|
+
requestName: string;
|
|
23
|
+
requestData: any;
|
|
24
|
+
}): Promise<any | IError>;
|
|
4
25
|
}
|
|
@@ -1,10 +1,63 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.MicroserviceClient = void 0;
|
|
6
|
+
exports.MicroserviceClient = exports.REQ_MICROSERVICE_CALL = void 0;
|
|
7
|
+
const badmfck_signal_1 = require("badmfck-signal");
|
|
4
8
|
const BaseService_1 = require("../BaseService");
|
|
9
|
+
const DefaultErrors_1 = __importDefault(require("../structures/DefaultErrors"));
|
|
10
|
+
const Http_1 = require("../http/Http");
|
|
11
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
12
|
+
exports.REQ_MICROSERVICE_CALL = new badmfck_signal_1.Req(undefined, "REQ_MICROSERVICE_CALL");
|
|
5
13
|
class MicroserviceClient extends BaseService_1.BaseService {
|
|
6
|
-
|
|
14
|
+
static #clients = new Map();
|
|
15
|
+
static #listener = false;
|
|
16
|
+
options;
|
|
17
|
+
constructor(opt) {
|
|
7
18
|
super("MicroserviceClient");
|
|
19
|
+
this.options = opt;
|
|
20
|
+
MicroserviceClient.#clients.set(opt.id, this);
|
|
21
|
+
if (!MicroserviceClient.#listener) {
|
|
22
|
+
exports.REQ_MICROSERVICE_CALL.listener = async ({ id, requestName, requestData }) => {
|
|
23
|
+
const client = MicroserviceClient.#clients.get(id);
|
|
24
|
+
if (!client) {
|
|
25
|
+
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "no microservice client found: " + id + ", requestName:" + requestName };
|
|
26
|
+
}
|
|
27
|
+
return await client.requestMicroserviceCall({ id, requestName, requestData });
|
|
28
|
+
};
|
|
29
|
+
MicroserviceClient.#listener = true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async init() {
|
|
33
|
+
super.init();
|
|
34
|
+
}
|
|
35
|
+
async requestMicroserviceCall(req) {
|
|
36
|
+
const url = this.options.host + "/__ms_host_control/receiver";
|
|
37
|
+
const ts = (+new Date()).toString();
|
|
38
|
+
const nonce = crypto_1.default.randomBytes(16).toString("hex");
|
|
39
|
+
const headers = {
|
|
40
|
+
"Content-Type": "application/json",
|
|
41
|
+
"x-microservice-id": this.options.id,
|
|
42
|
+
"x-microservice-ts": ts,
|
|
43
|
+
"x-microservice-nonce": nonce
|
|
44
|
+
};
|
|
45
|
+
const data = Buffer.from(JSON.stringify(req), "utf8");
|
|
46
|
+
const secret = Buffer.from(this.options.securityKey, "base64");
|
|
47
|
+
const salt = crypto_1.default.createHash("sha256").update(nonce + ts).digest();
|
|
48
|
+
const key = crypto_1.default.pbkdf2Sync(secret, salt, 100, 32, "sha256");
|
|
49
|
+
const iv = crypto_1.default.pbkdf2Sync(secret, salt, 100, 16, "sha256");
|
|
50
|
+
const aad = Buffer.from(ts + "." + nonce + "." + this.options.id + "." + this.options.password, "utf8");
|
|
51
|
+
const cipher = crypto_1.default.createCipheriv("aes-256-gcm", key, iv);
|
|
52
|
+
cipher.setAAD(aad);
|
|
53
|
+
const encrypted = Buffer.concat([cipher.update(data), cipher.final()]);
|
|
54
|
+
const tag = cipher.getAuthTag();
|
|
55
|
+
const resp = await Http_1.Http.post(url, { tag: tag.toString("base64"), enc: encrypted.toString("base64") }, { headers });
|
|
56
|
+
if (!resp.ok)
|
|
57
|
+
return { ...DefaultErrors_1.default.BAD_REQUEST, details: resp.details, stack: [resp.error] };
|
|
58
|
+
if (resp.data && typeof resp.data === "object" && "error" in resp.data)
|
|
59
|
+
return resp.data.error;
|
|
60
|
+
return resp.data;
|
|
8
61
|
}
|
|
9
62
|
}
|
|
10
63
|
exports.MicroserviceClient = MicroserviceClient;
|
|
@@ -1,4 +1,17 @@
|
|
|
1
|
+
import { Req } from "badmfck-signal";
|
|
1
2
|
import { BaseService } from "../BaseService";
|
|
3
|
+
import { HTTPRequestVO, IError } from "../structures/Interfaces";
|
|
4
|
+
export interface IMicroserviceHostOptions {
|
|
5
|
+
id: string;
|
|
6
|
+
securityKey: string;
|
|
7
|
+
password: string;
|
|
8
|
+
requests: Req<any, any>[];
|
|
9
|
+
}
|
|
2
10
|
export declare class MicroserviceHost extends BaseService {
|
|
3
|
-
|
|
11
|
+
#private;
|
|
12
|
+
options: IMicroserviceHostOptions;
|
|
13
|
+
constructor(opt: IMicroserviceHostOptions);
|
|
14
|
+
init(): Promise<void>;
|
|
15
|
+
static getMicroservice(id: string): MicroserviceHost | null;
|
|
16
|
+
handleIncomingRequest(req: HTTPRequestVO): Promise<any | IError>;
|
|
4
17
|
}
|
|
@@ -1,10 +1,107 @@
|
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
2
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
29
|
exports.MicroserviceHost = void 0;
|
|
4
30
|
const BaseService_1 = require("../BaseService");
|
|
31
|
+
const DefaultErrors_1 = __importStar(require("../structures/DefaultErrors"));
|
|
32
|
+
const crypto_1 = __importDefault(require("crypto"));
|
|
5
33
|
class MicroserviceHost extends BaseService_1.BaseService {
|
|
6
|
-
|
|
7
|
-
|
|
34
|
+
static #calls = new Set();
|
|
35
|
+
static #instances = new Map();
|
|
36
|
+
options;
|
|
37
|
+
constructor(opt) {
|
|
38
|
+
super("Microservice-host-" + opt.id);
|
|
39
|
+
this.options = opt;
|
|
40
|
+
MicroserviceHost.#instances.set(opt.id, this);
|
|
41
|
+
}
|
|
42
|
+
async init() {
|
|
43
|
+
super.init();
|
|
44
|
+
}
|
|
45
|
+
static getMicroservice(id) {
|
|
46
|
+
return MicroserviceHost.#instances.get(id) || null;
|
|
47
|
+
}
|
|
48
|
+
async handleIncomingRequest(req) {
|
|
49
|
+
console.log("Handling incoming request for MicroserviceHost:", this.getName());
|
|
50
|
+
const nonce = req.headers["x-microservice-nonce"];
|
|
51
|
+
const ts = req.headers["x-microservice-ts"];
|
|
52
|
+
if (!nonce || !ts)
|
|
53
|
+
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
|
+
const checkCall = MicroserviceHost.#calls.has(nonce + "|" + ts);
|
|
59
|
+
if (checkCall)
|
|
60
|
+
return { ...DefaultErrors_1.default.BAD_REQUEST, details: "replay attack detected" };
|
|
61
|
+
MicroserviceHost.#calls.add(nonce + "|" + ts);
|
|
62
|
+
if (MicroserviceHost.#calls.size > 1000) {
|
|
63
|
+
const first = MicroserviceHost.#calls.values().next().value;
|
|
64
|
+
if (first)
|
|
65
|
+
MicroserviceHost.#calls.delete(first);
|
|
66
|
+
}
|
|
67
|
+
const secret = Buffer.from(this.options.securityKey, "base64");
|
|
68
|
+
const salt = crypto_1.default.createHash("sha256").update(nonce + ts).digest();
|
|
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 = req.data.tag;
|
|
73
|
+
const encryptedData = req.data.enc;
|
|
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(encryptedData), 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 };
|
|
94
|
+
}
|
|
95
|
+
let response = null;
|
|
96
|
+
try {
|
|
97
|
+
response = await reqCall.request(request.requestData);
|
|
98
|
+
}
|
|
99
|
+
catch (e) {
|
|
100
|
+
if (DefaultErrors_1.ErrorUtils.isError(e))
|
|
101
|
+
return e;
|
|
102
|
+
return { ...DefaultErrors_1.default.INTERNAL_SERVER_ERROR, details: "request execution error: " + e?.message };
|
|
103
|
+
}
|
|
104
|
+
return response;
|
|
8
105
|
}
|
|
9
106
|
}
|
|
10
107
|
exports.MicroserviceHost = MicroserviceHost;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { BaseEndpoint } from "../BaseEndpoint";
|
|
2
|
+
import { HTTPRequestVO, TransferPacketVO } from "../structures/Interfaces";
|
|
3
|
+
export declare class MicroserviceHostController extends BaseEndpoint {
|
|
4
|
+
constructor();
|
|
5
|
+
receiver(req: HTTPRequestVO): Promise<TransferPacketVO>;
|
|
6
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.MicroserviceHostController = void 0;
|
|
27
|
+
const BaseEndpoint_1 = require("../BaseEndpoint");
|
|
28
|
+
const DefaultErrors_1 = __importStar(require("../structures/DefaultErrors"));
|
|
29
|
+
const MicroserviceHost_1 = require("./MicroserviceHost");
|
|
30
|
+
class MicroserviceHostController extends BaseEndpoint_1.BaseEndpoint {
|
|
31
|
+
constructor() {
|
|
32
|
+
super("__ms_host_control");
|
|
33
|
+
this.ignoreInDocumentation = true;
|
|
34
|
+
this.ignoreHttpLogging = true;
|
|
35
|
+
this.registerEndpoints([{
|
|
36
|
+
ignoreInDocumentation: true,
|
|
37
|
+
endpoint: "receiver",
|
|
38
|
+
handler: this.receiver,
|
|
39
|
+
ignoreInterceptor: true,
|
|
40
|
+
},
|
|
41
|
+
]);
|
|
42
|
+
}
|
|
43
|
+
async receiver(req) {
|
|
44
|
+
if (req.method.toUpperCase() !== "POST")
|
|
45
|
+
throw DefaultErrors_1.default.METHOD_NOT_ALLOWED;
|
|
46
|
+
const microserviceHost = MicroserviceHost_1.MicroserviceHost.getMicroservice(req.headers["x-microservice-id"]);
|
|
47
|
+
if (!microserviceHost)
|
|
48
|
+
throw { ...DefaultErrors_1.default.NOT_FOUND, message: "Microservice host not found" };
|
|
49
|
+
const result = await microserviceHost.handleIncomingRequest(req);
|
|
50
|
+
if (DefaultErrors_1.ErrorUtils.isError(result))
|
|
51
|
+
throw result;
|
|
52
|
+
return { data: result };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.MicroserviceHostController = MicroserviceHostController;
|