@camstack/system 1.2.435 → 1.2.437
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/{agent-https-B8lKYVtU.mjs → agent-https-BPfHrI4c.mjs} +3 -3
- package/dist/auth/login-session-manager.d.ts +2 -0
- package/dist/auth/session-revocation-bus.d.ts +32 -0
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.js +1 -1
- package/dist/builtins/addon-pages-aggregator/addon-pages-aggregator.addon.mjs +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.js +1 -1
- package/dist/builtins/addon-widgets-aggregator/addon-widgets-aggregator.addon.mjs +1 -1
- package/dist/builtins/alerts/alerts.addon.js +1 -1
- package/dist/builtins/alerts/alerts.addon.mjs +1 -1
- package/dist/builtins/autotrack/index.js +1 -1
- package/dist/builtins/autotrack/index.mjs +1 -1
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.js +2 -2
- package/dist/builtins/backup-orchestrator/backup-orchestrator.addon.mjs +2 -2
- package/dist/builtins/calendars/calendars.addon.js +1 -1
- package/dist/builtins/calendars/calendars.addon.mjs +1 -1
- package/dist/builtins/camera-grid/index.js +1 -1
- package/dist/builtins/camera-grid/index.mjs +1 -1
- package/dist/builtins/composer/composer.addon.js +2 -2
- package/dist/builtins/composer/composer.addon.mjs +2 -2
- package/dist/builtins/console-logging/index.js +1 -1
- package/dist/builtins/console-logging/index.mjs +1 -1
- package/dist/builtins/core-blocks/core-blocks.addon.js +2 -2
- package/dist/builtins/core-blocks/core-blocks.addon.mjs +5 -5
- package/dist/builtins/device-manager/device-manager.addon.js +2 -2
- package/dist/builtins/device-manager/device-manager.addon.mjs +2 -2
- package/dist/builtins/hub-forwarder/index.js +1 -1
- package/dist/builtins/hub-forwarder/index.mjs +1 -1
- package/dist/builtins/keychain/index.js +6 -7
- package/dist/builtins/keychain/index.mjs +6 -7
- package/dist/builtins/keychain/keychain-service.d.ts +1 -2
- package/dist/builtins/keychain/system-held-secrets.d.ts +5 -5
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.js +1 -1
- package/dist/builtins/liveness-monitor/liveness-monitor.addon.mjs +1 -1
- package/dist/builtins/local-auth/local-auth.addon.js +43 -2
- package/dist/builtins/local-auth/local-auth.addon.mjs +43 -3
- package/dist/builtins/local-network/local-network.addon.js +1 -1
- package/dist/builtins/local-network/local-network.addon.mjs +4 -4
- package/dist/builtins/loki-logging/index.js +1 -1
- package/dist/builtins/loki-logging/index.mjs +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.js +1 -1
- package/dist/builtins/native-metrics/native-metrics.addon.mjs +10 -10
- package/dist/builtins/platform-probe/index.js +1 -1
- package/dist/builtins/platform-probe/index.mjs +8 -8
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.js +1 -1
- package/dist/builtins/remote-access-orchestrator/remote-access-orchestrator.addon.mjs +1 -1
- package/dist/builtins/snapshot/index.js +1 -1
- package/dist/builtins/snapshot/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.js +1 -1
- package/dist/builtins/sqlite-storage/filesystem-storage.addon.mjs +1 -1
- package/dist/builtins/sqlite-storage/index.js +1 -1
- package/dist/builtins/sqlite-storage/index.mjs +1 -1
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.js +3 -3
- package/dist/builtins/sqlite-storage/sqlite-settings.addon.mjs +3 -3
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.js +1 -1
- package/dist/builtins/storage-orchestrator/storage-orchestrator.addon.mjs +1 -1
- package/dist/builtins/system-config/system-config.addon.d.ts +11 -23
- package/dist/builtins/system-config/system-config.addon.js +219 -1479
- package/dist/builtins/system-config/system-config.addon.mjs +222 -1472
- package/dist/builtins/winston-logging/index.js +1 -1
- package/dist/builtins/winston-logging/index.mjs +1 -1
- package/dist/{composition-sources-Cm42mgbv.js → composition-sources-BIT8IUKm.js} +1 -1
- package/dist/{composition-sources-_7W2Ly9s.mjs → composition-sources-tpYR0f1x.mjs} +1 -1
- package/dist/constants-Bc6trhoW.mjs +20 -0
- package/dist/constants-CwRY32Nx.js +66 -0
- package/dist/{device-ca-B6YJZus6.mjs → device-ca-BhdBByGD.mjs} +1 -1
- package/dist/{device-ca-WXuKc8AX.js → device-ca-DImD8IzR.js} +1 -1
- package/dist/{dist-CnUtkSwN.js → dist-CEAyXW3Q.js} +42 -12
- package/dist/{dist-Bz4_y8Xy.mjs → dist-m5JkT8UN.mjs} +33 -3
- package/dist/file-host-worker.js +1 -1
- package/dist/file-host-worker.mjs +1 -1
- package/dist/{hub-mdns-ciao-DJRwtlA8.mjs → hub-mdns-ciao-DMlQTdPU.mjs} +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +135 -796
- package/dist/index.mjs +150 -769
- package/dist/kernel/index.d.ts +7 -21
- package/dist/kernel/moleculer/agent-ui-unlock.d.ts +7 -32
- package/dist/kernel/moleculer/broker-factory.d.ts +3 -9
- package/dist/kernel/moleculer/broker-transport-swap.d.ts +17 -0
- package/dist/kernel/moleculer/hub-service.d.ts +6 -16
- package/dist/kernel/moleculer/mesh-access-middleware.d.ts +7 -17
- package/dist/kernel/moleculer/mesh-identity.d.ts +57 -0
- package/dist/kernel/moleculer/mesh-mtls/constants.d.ts +1 -4
- package/dist/kernel/moleculer/mesh-mtls/index.d.ts +1 -4
- package/dist/kernel/moleculer/mesh-mtls/mesh-ca.d.ts +1 -1
- package/dist/kernel/moleculer/mesh-mtls/mesh-renewal.d.ts +1 -1
- package/dist/kernel/moleculer/node-registry.d.ts +0 -6
- package/dist/kernel/moleculer/register-node-client.d.ts +9 -7
- package/dist/{restore-archive-BNoFLAg8.js → restore-archive-C75srVbG.js} +1 -1
- package/dist/{restore-archive-DJYuznWP.mjs → restore-archive-DNxAStrJ.mjs} +1 -1
- package/dist/{retired-settings-keys-9nA85bwT.mjs → retired-settings-keys-C5qP9QIf.mjs} +1 -1
- package/dist/{retired-settings-keys-CO3RqsDw.js → retired-settings-keys-DNfV28R_.js} +1 -1
- package/dist/{wal-maintenance-D3gwRj1B.js → wal-maintenance-Ch79gy9S.js} +0 -0
- package/dist/{wal-maintenance-DLrbapzi.mjs → wal-maintenance-DvnVO5IK.mjs} +0 -0
- package/package.json +1 -1
- package/dist/builtins/system-config/cluster-secret-keeper.d.ts +0 -63
- package/dist/constants-DL87WgeN.js +0 -221
- package/dist/constants-DoiTA134.mjs +0 -102
- package/dist/kernel/moleculer/agent-mesh-authenticator.d.ts +0 -91
- package/dist/kernel/moleculer/cluster-secret.d.ts +0 -46
- package/dist/kernel/moleculer/mesh-auth-mode.d.ts +0 -58
- package/dist/kernel/moleculer/mesh-authenticator.d.ts +0 -77
- package/dist/kernel/moleculer/mesh-auto-enforce.d.ts +0 -46
- package/dist/kernel/moleculer/mesh-join-client.d.ts +0 -73
- package/dist/kernel/moleculer/mesh-join-hold.d.ts +0 -85
- package/dist/kernel/moleculer/mesh-join-proof.d.ts +0 -39
- package/dist/kernel/moleculer/mesh-mtls/mesh-enroll.d.ts +0 -34
- package/dist/kernel/moleculer/mesh-mtls/mesh-join-token.d.ts +0 -56
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM, r as __exportAll, t as __commonJSMin } from "../../chunk-CNf5ZN-e.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { Br as customAction, Cr as BaseAddon, K as ServerNameSchema, Kr as hydrateSchema, Sr as errMsg, Vr as defineCustomActions, Wn as shortHostname } from "../../dist-m5JkT8UN.mjs";
|
|
3
3
|
import { t as require_safe_buffer } from "../../safe-buffer-B1OjL1I9.mjs";
|
|
4
4
|
import { a as KeyUsagesExtension, c as Pkcs10CertificateRequestGenerator, d as X509Certificate$1, f as X509CertificateGenerator, g as backdatedNotBefore, i as KeyUsageFlags, n as BasicConstraintsExtension, o as PemConverter, p as cryptoProvider, r as ExtendedKeyUsageExtension, s as Pkcs10CertificateRequest, t as AuthorityKeyIdentifierExtension, u as SubjectKeyIdentifierExtension } from "../../x509.es-CDvj67p1.mjs";
|
|
5
|
-
import { A as AgentHttpsNames, M as setProcessAgentHttpsNames, O as AGENT_HTTPS_NAMES_COLLECTION, d as isPrivateAddress, j as getProcessAgentHttpsNames, k as AGENT_HTTPS_NAMES_COLUMNS, u as isLocalOnlyHostname } from "../../agent-https-
|
|
6
|
-
import { a as MESH_CA_KEY_REF,
|
|
5
|
+
import { A as AgentHttpsNames, M as setProcessAgentHttpsNames, O as AGENT_HTTPS_NAMES_COLLECTION, d as isPrivateAddress, j as getProcessAgentHttpsNames, k as AGENT_HTTPS_NAMES_COLUMNS, u as isLocalOnlyHostname } from "../../agent-https-BPfHrI4c.mjs";
|
|
6
|
+
import { a as MESH_CA_KEY_REF, c as SERVER_AUTH_OID, i as MESH_CA_FIELD, n as DEFAULT_HUB_TLS_TCP_PORT, o as MESH_CA_SETTINGS_KEY, r as MESH_CA_COMMON_NAME, s as MESH_CA_VALIDITY_DAYS, t as CLIENT_AUTH_OID } from "../../constants-Bc6trhoW.mjs";
|
|
7
7
|
import { t as require_src } from "../../src-hG4grMU4.mjs";
|
|
8
8
|
import { z } from "zod";
|
|
9
|
-
import { X509Certificate, createHash,
|
|
9
|
+
import { X509Certificate, createHash, createPrivateKey, randomBytes, randomInt, sign, timingSafeEqual, verify, webcrypto } from "node:crypto";
|
|
10
10
|
import { BlockList, isIP } from "node:net";
|
|
11
11
|
import { lstat, readdir, readlink, realpath } from "node:fs/promises";
|
|
12
12
|
import { posix, win32 } from "node:path";
|
|
13
|
+
import os from "node:os";
|
|
13
14
|
import { fileURLToPath } from "node:url";
|
|
14
15
|
import * as xi from "node:fs";
|
|
15
16
|
import * as tls from "node:tls";
|
|
@@ -97,73 +98,27 @@ function createCidrMatcher(entries) {
|
|
|
97
98
|
};
|
|
98
99
|
}
|
|
99
100
|
//#endregion
|
|
100
|
-
//#region src/kernel/moleculer/mesh-auth-mode.ts
|
|
101
|
-
/** The field key inside the `cluster` section. */
|
|
102
|
-
var MESH_AUTH_MODE_FIELD = "meshAuth";
|
|
103
|
-
function isMeshAuthMode(value) {
|
|
104
|
-
return value === "transition" || value === "enforced";
|
|
105
|
-
}
|
|
106
|
-
/** A stored value that is not a mode reads as `transition`: never refuse on a typo. */
|
|
107
|
-
function parseMeshAuthMode(value) {
|
|
108
|
-
return isMeshAuthMode(value) ? value : "transition";
|
|
109
|
-
}
|
|
110
|
-
var MODE_SLOT = Symbol.for("camstack.cluster.mesh-auth-mode");
|
|
111
|
-
var ENFORCER_SLOT = Symbol.for("camstack.cluster.mesh-auth-enforcer");
|
|
112
|
-
var STATUS_SLOT = Symbol.for("camstack.cluster.mesh-auth-status");
|
|
113
|
-
/** Published by `system-config` whenever the stored mode is (re)read. */
|
|
114
|
-
function setProcessMeshAuthMode(mode) {
|
|
115
|
-
Reflect.set(globalThis, MODE_SLOT, mode);
|
|
116
|
-
}
|
|
117
|
-
/**
|
|
118
|
-
* The hub's mode. Until `system-config` has read it: `transition` — the safe
|
|
119
|
-
* side for an upgrading cluster (nothing that worked before is refused), and
|
|
120
|
-
* exactly what an unread setting means.
|
|
121
|
-
*/
|
|
122
|
-
function getProcessMeshAuthMode() {
|
|
123
|
-
return parseMeshAuthMode(Reflect.get(globalThis, MODE_SLOT));
|
|
124
|
-
}
|
|
125
|
-
function setProcessMeshEnforcer(enforcer) {
|
|
126
|
-
if (enforcer === null) Reflect.deleteProperty(globalThis, ENFORCER_SLOT);
|
|
127
|
-
else Reflect.set(globalThis, ENFORCER_SLOT, enforcer);
|
|
128
|
-
}
|
|
129
|
-
/** Ask the owner of the setting to switch to `enforced`. `false` when nobody can. */
|
|
130
|
-
async function requestProcessMeshEnforcement(reason) {
|
|
131
|
-
const enforcer = Reflect.get(globalThis, ENFORCER_SLOT);
|
|
132
|
-
if (typeof enforcer !== "function") return false;
|
|
133
|
-
await enforcer(reason);
|
|
134
|
-
return true;
|
|
135
|
-
}
|
|
136
|
-
/** Published by the hub's broker; read by System → Cluster. */
|
|
137
|
-
function setProcessMeshAuthStatusSource(source) {
|
|
138
|
-
if (source === null) Reflect.deleteProperty(globalThis, STATUS_SLOT);
|
|
139
|
-
else Reflect.set(globalThis, STATUS_SLOT, source);
|
|
140
|
-
}
|
|
141
|
-
function getProcessMeshAuthStatus() {
|
|
142
|
-
const source = Reflect.get(globalThis, STATUS_SLOT);
|
|
143
|
-
return typeof source === "function" ? source() : null;
|
|
144
|
-
}
|
|
145
|
-
//#endregion
|
|
146
101
|
//#region src/kernel/moleculer/agent-ui-unlock.ts
|
|
147
102
|
/**
|
|
148
|
-
* Agent UI remote unlock tickets (D821).
|
|
103
|
+
* Agent UI remote unlock tickets (D821, re-keyed by D857).
|
|
149
104
|
*
|
|
150
|
-
* A hub admin mints a short-lived
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
105
|
+
* A hub admin mints a short-lived ticket bound to one agent `nodeId`, signed
|
|
106
|
+
* with the MESH CA key (ES256 JWS). The agent verifies it
|
|
107
|
+
* with the CA certificate it pinned at pairing and redeems it once for a tab
|
|
108
|
+
* session Bearer. There is no shared secret: a ticket is worth exactly as much
|
|
109
|
+
* as the CA key that signed it, and the agent trusts exactly the CA its
|
|
110
|
+
* operator confirmed during pairing.
|
|
154
111
|
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
* payload = { v: 1, nodeId, exp (ms), jti }
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* D857 (transition release): a ticket signed by the MESH CA key (ES256 JWS) is accepted by an agent
|
|
163
|
-
* IN ADDITION to the HMAC ticket. The removal release mints only this form.
|
|
112
|
+
* ticket = b64url(header) '.' b64url(payload) '.' b64url(ES256 signature)
|
|
113
|
+
* header = { alg: 'ES256', typ: 'camstack-agent-ui-unlock+jwt' }
|
|
114
|
+
* payload = { v: 1, use: 'agent-ui-unlock', nodeId, iat (ms), exp (ms), jti }
|
|
115
|
+
*
|
|
116
|
+
* The `typ` and `use` pins keep a join token or a pairing proof (also signed
|
|
117
|
+
* by the CA key) from ever being accepted here, and the reverse.
|
|
164
118
|
*/
|
|
165
119
|
var AGENT_UI_UNLOCK_TYP = "camstack-agent-ui-unlock+jwt";
|
|
166
120
|
var AGENT_UI_UNLOCK_USE = "agent-ui-unlock";
|
|
121
|
+
var AGENT_UI_UNLOCK_VERSION = 1;
|
|
167
122
|
/** Ticket lifetime — long enough for a redirect hop, short enough to steal poorly. */
|
|
168
123
|
var AGENT_UI_UNLOCK_TTL_MS = 5 * 6e4;
|
|
169
124
|
/**
|
|
@@ -193,18 +148,28 @@ var UnlockTicketJtiStore = class {
|
|
|
193
148
|
for (const [jti, exp] of this.spent) if (exp <= nowMs) this.spent.delete(jti);
|
|
194
149
|
}
|
|
195
150
|
};
|
|
151
|
+
function b64urlJson$1(value) {
|
|
152
|
+
return Buffer.from(JSON.stringify(value), "utf8").toString("base64url");
|
|
153
|
+
}
|
|
196
154
|
function mintAgentUiUnlockTicket(input) {
|
|
197
155
|
const nowMs = input.nowMs ?? Date.now();
|
|
198
156
|
const ttl = Math.min(Math.max(1e3, input.ttlMs ?? 3e5), AGENT_UI_UNLOCK_TTL_MS);
|
|
199
157
|
const payload = {
|
|
200
158
|
v: 1,
|
|
159
|
+
use: AGENT_UI_UNLOCK_USE,
|
|
201
160
|
nodeId: input.nodeId,
|
|
202
161
|
iat: nowMs,
|
|
203
162
|
exp: nowMs + ttl,
|
|
204
163
|
jti: input.jti ?? randomBytes(16).toString("base64url")
|
|
205
164
|
};
|
|
206
|
-
const
|
|
207
|
-
|
|
165
|
+
const signingInput = `${b64urlJson$1({
|
|
166
|
+
alg: "ES256",
|
|
167
|
+
typ: AGENT_UI_UNLOCK_TYP
|
|
168
|
+
})}.${b64urlJson$1(payload)}`;
|
|
169
|
+
return `${signingInput}.${sign("sha256", Buffer.from(signingInput, "utf8"), {
|
|
170
|
+
key: createPrivateKey(input.caKeyPem),
|
|
171
|
+
dsaEncoding: "ieee-p1363"
|
|
172
|
+
}).toString("base64url")}`;
|
|
208
173
|
}
|
|
209
174
|
/** A ticket is issued now-ish, lives at most the TTL, and not before `notBeforeMs`. */
|
|
210
175
|
function issuedSanely(payload, nowMs, notBeforeMs) {
|
|
@@ -213,22 +178,36 @@ function issuedSanely(payload, nowMs, notBeforeMs) {
|
|
|
213
178
|
return notBeforeMs === void 0 || payload.iat >= notBeforeMs;
|
|
214
179
|
}
|
|
215
180
|
/**
|
|
216
|
-
* Verify a ticket
|
|
217
|
-
* signature, shape, expiry or nodeId fails
|
|
181
|
+
* Verify a ticket against the mesh CA certificate the agent pinned. Returns the
|
|
182
|
+
* payload, or `null` when the signature, header, shape, expiry or nodeId fails
|
|
183
|
+
* (no reason string — refuse quietly).
|
|
218
184
|
*/
|
|
219
|
-
function verifyAgentUiUnlockTicket(
|
|
185
|
+
function verifyAgentUiUnlockTicket(caCertPem, ticket, options) {
|
|
220
186
|
const nowMs = options.nowMs ?? Date.now();
|
|
221
|
-
const
|
|
222
|
-
if (
|
|
223
|
-
const payloadB64 =
|
|
224
|
-
|
|
225
|
-
|
|
187
|
+
const parts = ticket.split(".");
|
|
188
|
+
if (parts.length !== 3) return null;
|
|
189
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
190
|
+
if (headerB64 === void 0 || payloadB64 === void 0 || signatureB64 === void 0) return null;
|
|
191
|
+
let header;
|
|
226
192
|
let parsed;
|
|
227
193
|
try {
|
|
194
|
+
header = JSON.parse(Buffer.from(headerB64, "base64url").toString("utf8"));
|
|
228
195
|
parsed = JSON.parse(Buffer.from(payloadB64, "base64url").toString("utf8"));
|
|
229
196
|
} catch {
|
|
230
197
|
return null;
|
|
231
198
|
}
|
|
199
|
+
if (typeof header !== "object" || header === null) return null;
|
|
200
|
+
if (Reflect.get(header, "alg") !== "ES256" || Reflect.get(header, "typ") !== "camstack-agent-ui-unlock+jwt") return null;
|
|
201
|
+
let valid = false;
|
|
202
|
+
try {
|
|
203
|
+
valid = verify("sha256", Buffer.from(`${headerB64}.${payloadB64}`, "utf8"), {
|
|
204
|
+
key: new X509Certificate(caCertPem).publicKey,
|
|
205
|
+
dsaEncoding: "ieee-p1363"
|
|
206
|
+
}, Buffer.from(signatureB64, "base64url"));
|
|
207
|
+
} catch {
|
|
208
|
+
return null;
|
|
209
|
+
}
|
|
210
|
+
if (!valid) return null;
|
|
232
211
|
const payload = parsePayload(parsed);
|
|
233
212
|
if (payload === null) return null;
|
|
234
213
|
if (payload.exp <= nowMs) return null;
|
|
@@ -287,96 +266,7 @@ function parseAgentDashboardOrigins(stored) {
|
|
|
287
266
|
}
|
|
288
267
|
return out;
|
|
289
268
|
}
|
|
290
|
-
function sign$1(secretHash, payloadB64) {
|
|
291
|
-
return createHmac("sha256", Buffer.from(secretHash, "utf8")).update(`${AGENT_UI_UNLOCK_DOMAIN}|${payloadB64}`, "utf8").digest("base64url");
|
|
292
|
-
}
|
|
293
|
-
function sigsEqual(expected, presented) {
|
|
294
|
-
const a = Buffer.from(expected, "utf8");
|
|
295
|
-
const b = Buffer.from(presented, "utf8");
|
|
296
|
-
if (a.length !== b.length) return false;
|
|
297
|
-
return timingSafeEqual(a, b);
|
|
298
|
-
}
|
|
299
269
|
function parsePayload(value) {
|
|
300
|
-
if (typeof value !== "object" || value === null) return null;
|
|
301
|
-
const rec = value;
|
|
302
|
-
if (rec["v"] !== 1) return null;
|
|
303
|
-
const nodeId = rec["nodeId"];
|
|
304
|
-
const exp = rec["exp"];
|
|
305
|
-
const jti = rec["jti"];
|
|
306
|
-
if (typeof nodeId !== "string" || nodeId.length === 0) return null;
|
|
307
|
-
if (typeof exp !== "number" || !Number.isFinite(exp)) return null;
|
|
308
|
-
if (typeof jti !== "string" || jti.length === 0) return null;
|
|
309
|
-
const iat = rec["iat"];
|
|
310
|
-
return {
|
|
311
|
-
v: 1,
|
|
312
|
-
nodeId,
|
|
313
|
-
iat: typeof iat === "number" && Number.isFinite(iat) ? iat : exp - AGENT_UI_UNLOCK_TTL_MS,
|
|
314
|
-
exp,
|
|
315
|
-
jti
|
|
316
|
-
};
|
|
317
|
-
}
|
|
318
|
-
function b64urlJsonEs256(value) {
|
|
319
|
-
return Buffer.from(JSON.stringify(value), "utf8").toString("base64url");
|
|
320
|
-
}
|
|
321
|
-
function mintAgentUiUnlockTicketEs256(input) {
|
|
322
|
-
const nowMs = input.nowMs ?? Date.now();
|
|
323
|
-
const ttl = Math.min(Math.max(1e3, input.ttlMs ?? 3e5), AGENT_UI_UNLOCK_TTL_MS);
|
|
324
|
-
const payload = {
|
|
325
|
-
v: 1,
|
|
326
|
-
use: AGENT_UI_UNLOCK_USE,
|
|
327
|
-
nodeId: input.nodeId,
|
|
328
|
-
iat: nowMs,
|
|
329
|
-
exp: nowMs + ttl,
|
|
330
|
-
jti: input.jti ?? randomBytes(16).toString("base64url")
|
|
331
|
-
};
|
|
332
|
-
const signingInput = `${b64urlJsonEs256({
|
|
333
|
-
alg: "ES256",
|
|
334
|
-
typ: AGENT_UI_UNLOCK_TYP
|
|
335
|
-
})}.${b64urlJsonEs256(payload)}`;
|
|
336
|
-
return `${signingInput}.${sign("sha256", Buffer.from(signingInput, "utf8"), {
|
|
337
|
-
key: createPrivateKey(input.caKeyPem),
|
|
338
|
-
dsaEncoding: "ieee-p1363"
|
|
339
|
-
}).toString("base64url")}`;
|
|
340
|
-
}
|
|
341
|
-
/**
|
|
342
|
-
* Verify a ticket against the mesh CA certificate the agent pinned. Returns the
|
|
343
|
-
* payload, or `null` when the signature, header, shape, expiry or nodeId fails
|
|
344
|
-
* (no reason string — refuse quietly).
|
|
345
|
-
*/
|
|
346
|
-
function verifyAgentUiUnlockTicketEs256(caCertPem, ticket, options) {
|
|
347
|
-
const nowMs = options.nowMs ?? Date.now();
|
|
348
|
-
const parts = ticket.split(".");
|
|
349
|
-
if (parts.length !== 3) return null;
|
|
350
|
-
const [headerB64, payloadB64, signatureB64] = parts;
|
|
351
|
-
if (headerB64 === void 0 || payloadB64 === void 0 || signatureB64 === void 0) return null;
|
|
352
|
-
let header;
|
|
353
|
-
let parsed;
|
|
354
|
-
try {
|
|
355
|
-
header = JSON.parse(Buffer.from(headerB64, "base64url").toString("utf8"));
|
|
356
|
-
parsed = JSON.parse(Buffer.from(payloadB64, "base64url").toString("utf8"));
|
|
357
|
-
} catch {
|
|
358
|
-
return null;
|
|
359
|
-
}
|
|
360
|
-
if (typeof header !== "object" || header === null) return null;
|
|
361
|
-
if (Reflect.get(header, "alg") !== "ES256" || Reflect.get(header, "typ") !== "camstack-agent-ui-unlock+jwt") return null;
|
|
362
|
-
let valid = false;
|
|
363
|
-
try {
|
|
364
|
-
valid = verify("sha256", Buffer.from(`${headerB64}.${payloadB64}`, "utf8"), {
|
|
365
|
-
key: new X509Certificate(caCertPem).publicKey,
|
|
366
|
-
dsaEncoding: "ieee-p1363"
|
|
367
|
-
}, Buffer.from(signatureB64, "base64url"));
|
|
368
|
-
} catch {
|
|
369
|
-
return null;
|
|
370
|
-
}
|
|
371
|
-
if (!valid) return null;
|
|
372
|
-
const payload = parsePayloadEs256(parsed);
|
|
373
|
-
if (payload === null) return null;
|
|
374
|
-
if (payload.exp <= nowMs) return null;
|
|
375
|
-
if (payload.nodeId !== options.expectedNodeId) return null;
|
|
376
|
-
if (!issuedSanely(payload, nowMs, options.notBeforeMs)) return null;
|
|
377
|
-
return payload;
|
|
378
|
-
}
|
|
379
|
-
function parsePayloadEs256(value) {
|
|
380
270
|
if (typeof value !== "object" || value === null) return null;
|
|
381
271
|
const rec = value;
|
|
382
272
|
if (rec["v"] !== 1) return null;
|
|
@@ -384,10 +274,10 @@ function parsePayloadEs256(value) {
|
|
|
384
274
|
const nodeId = rec["nodeId"];
|
|
385
275
|
const exp = rec["exp"];
|
|
386
276
|
const jti = rec["jti"];
|
|
277
|
+
const iat = rec["iat"];
|
|
387
278
|
if (typeof nodeId !== "string" || nodeId.length === 0) return null;
|
|
388
279
|
if (typeof exp !== "number" || !Number.isFinite(exp)) return null;
|
|
389
280
|
if (typeof jti !== "string" || jti.length === 0) return null;
|
|
390
|
-
const iat = rec["iat"];
|
|
391
281
|
if (typeof iat !== "number" || !Number.isFinite(iat)) return null;
|
|
392
282
|
return {
|
|
393
283
|
v: 1,
|
|
@@ -403,7 +293,7 @@ function parsePayloadEs256(value) {
|
|
|
403
293
|
* Hub mesh CA — EC P-256, key in the keychain, cert in `cluster.meshCa`.
|
|
404
294
|
*
|
|
405
295
|
* Distinct from the HTTPS local CA (`tls/cert-issue.ts`, RSA): the mesh CA
|
|
406
|
-
* signs node leaves (CN = nodeID) and
|
|
296
|
+
* signs node leaves (CN = nodeID) and unlock-ticket JWS (ES256). Issuance uses
|
|
407
297
|
* `@peculiar/x509` over WebCrypto — same library the HTTPS path already uses
|
|
408
298
|
* (installed `1.14.3`; registry latest at adoption time was `2.1.0` — stay on
|
|
409
299
|
* the pinned range already shipping).
|
|
@@ -444,7 +334,7 @@ async function exportKeyPem(key) {
|
|
|
444
334
|
function caFingerprint(certPem) {
|
|
445
335
|
return new X509Certificate(certPem).fingerprint256;
|
|
446
336
|
}
|
|
447
|
-
/** Compact fingerprint (lowercase hex, no colons)
|
|
337
|
+
/** Compact fingerprint (lowercase hex, no colons). */
|
|
448
338
|
function caFingerprintCompact(certPem) {
|
|
449
339
|
return createHash("sha256").update(new X509Certificate(certPem).raw).digest("hex");
|
|
450
340
|
}
|
|
@@ -1210,7 +1100,7 @@ function defaultSetTimer(fn, ms) {
|
|
|
1210
1100
|
function defaultSleep(ms) {
|
|
1211
1101
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
1212
1102
|
}
|
|
1213
|
-
function message
|
|
1103
|
+
function message(error) {
|
|
1214
1104
|
return error instanceof Error ? error.message : String(error);
|
|
1215
1105
|
}
|
|
1216
1106
|
async function renewMeshCertificate(deps) {
|
|
@@ -1276,7 +1166,7 @@ async function runRenewal(deps, inFlight) {
|
|
|
1276
1166
|
csrPem = (await deps.client.prepareMeshRenewal()).csrPem;
|
|
1277
1167
|
log.info("Mesh renewal: the node generated a new key and sent its CSR", { tags });
|
|
1278
1168
|
} catch (error) {
|
|
1279
|
-
return fail("prepare", message
|
|
1169
|
+
return fail("prepare", message(error), true);
|
|
1280
1170
|
}
|
|
1281
1171
|
let issued;
|
|
1282
1172
|
try {
|
|
@@ -1290,7 +1180,7 @@ async function runRenewal(deps, inFlight) {
|
|
|
1290
1180
|
}
|
|
1291
1181
|
});
|
|
1292
1182
|
} catch (error) {
|
|
1293
|
-
return fail("issue", message
|
|
1183
|
+
return fail("issue", message(error), true);
|
|
1294
1184
|
}
|
|
1295
1185
|
const newLeaf = describeMeshLeaf(issued.certPem);
|
|
1296
1186
|
deps.registry.beginRenewal(newLeaf.fingerprint);
|
|
@@ -1330,7 +1220,7 @@ async function runRenewal(deps, inFlight) {
|
|
|
1330
1220
|
deadlineTimer.cancel();
|
|
1331
1221
|
await deps.client.rollbackMeshLeaf().catch(() => void 0);
|
|
1332
1222
|
await deps.registry.abandon(newLeaf.fingerprint);
|
|
1333
|
-
return fail("install", message
|
|
1223
|
+
return fail("install", message(error), true);
|
|
1334
1224
|
}
|
|
1335
1225
|
const deadline = now() + timeoutMs;
|
|
1336
1226
|
const registered = await registeredPromise;
|
|
@@ -1359,7 +1249,7 @@ async function runRenewal(deps, inFlight) {
|
|
|
1359
1249
|
}
|
|
1360
1250
|
confirmError = "the node did not confirm the new leaf";
|
|
1361
1251
|
} catch (error) {
|
|
1362
|
-
confirmError = message
|
|
1252
|
+
confirmError = message(error);
|
|
1363
1253
|
log.warn("Mesh renewal: confirm not accepted yet", {
|
|
1364
1254
|
tags,
|
|
1365
1255
|
meta: { error: confirmError }
|
|
@@ -1393,7 +1283,7 @@ async function runRenewal(deps, inFlight) {
|
|
|
1393
1283
|
}
|
|
1394
1284
|
/**
|
|
1395
1285
|
* Revoke every live mesh leaf of `nodeId` and cut its connection. The node cannot
|
|
1396
|
-
* reconnect: it must
|
|
1286
|
+
* reconnect: it must be paired again. The node is NOT forgotten
|
|
1397
1287
|
* (that stays `clusterNodes.forgetNode`).
|
|
1398
1288
|
*/
|
|
1399
1289
|
async function revokeMeshCertificate(deps) {
|
|
@@ -1420,7 +1310,7 @@ async function revokeMeshCertificate(deps) {
|
|
|
1420
1310
|
nodeId,
|
|
1421
1311
|
revokedSerials: serials,
|
|
1422
1312
|
disconnected,
|
|
1423
|
-
next: "The node can no longer connect.
|
|
1313
|
+
next: "The node can no longer connect. Pair it again from the hub (System -> Cluster -> Agents); to remove it from the cluster use Forget node."
|
|
1424
1314
|
};
|
|
1425
1315
|
}
|
|
1426
1316
|
//#endregion
|
|
@@ -1481,872 +1371,6 @@ function emitProcessNodeRegistered(nodeId, addonIds) {
|
|
|
1481
1371
|
} catch {}
|
|
1482
1372
|
}
|
|
1483
1373
|
//#endregion
|
|
1484
|
-
//#region ../../node_modules/jose/dist/webapi/lib/buffer_utils.js
|
|
1485
|
-
var encoder = new TextEncoder(), decoder = new TextDecoder(), strictDecoder = new TextDecoder("utf-8", { fatal: !0 });
|
|
1486
|
-
function concat(...buffers) {
|
|
1487
|
-
const size = buffers.reduce((acc, { length }) => acc + length, 0), buf = new Uint8Array(size);
|
|
1488
|
-
let i = 0;
|
|
1489
|
-
for (const buffer of buffers) buf.set(buffer, i), i += buffer.length;
|
|
1490
|
-
return buf;
|
|
1491
|
-
}
|
|
1492
|
-
var NON_ASCII = /[^\x00-\x7f]/;
|
|
1493
|
-
function encode$1(string) {
|
|
1494
|
-
if (typeof string == "string" && string.length >= 128) {
|
|
1495
|
-
if (NON_ASCII.test(string)) throw new TypeError("non-ASCII string encountered in encode()");
|
|
1496
|
-
return encoder.encode(string);
|
|
1497
|
-
}
|
|
1498
|
-
const bytes = new Uint8Array(string.length);
|
|
1499
|
-
for (let i = 0; i < string.length; i++) {
|
|
1500
|
-
const code = string.charCodeAt(i);
|
|
1501
|
-
if (code > 127) throw new TypeError("non-ASCII string encountered in encode()");
|
|
1502
|
-
bytes[i] = code;
|
|
1503
|
-
}
|
|
1504
|
-
return bytes;
|
|
1505
|
-
}
|
|
1506
|
-
function encodeBase64(input, url = !1) {
|
|
1507
|
-
if (Uint8Array.prototype.toBase64) return input.toBase64({
|
|
1508
|
-
alphabet: url ? "base64url" : "base64",
|
|
1509
|
-
omitPadding: url
|
|
1510
|
-
});
|
|
1511
|
-
const CHUNK_SIZE = 32768, arr = [];
|
|
1512
|
-
for (let i = 0; i < input.length; i += CHUNK_SIZE) arr.push(String.fromCharCode.apply(null, input.subarray(i, i + CHUNK_SIZE)));
|
|
1513
|
-
const encoded = btoa(arr.join(""));
|
|
1514
|
-
return url ? encoded.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_") : encoded;
|
|
1515
|
-
}
|
|
1516
|
-
function decodeBase64(encoded, url = !1) {
|
|
1517
|
-
if (Uint8Array.fromBase64) return Uint8Array.fromBase64(encoded, { alphabet: url ? "base64url" : "base64" });
|
|
1518
|
-
if (url) {
|
|
1519
|
-
if (encoded.includes("+") || encoded.includes("/")) throw new TypeError("Invalid base64url");
|
|
1520
|
-
encoded = encoded.replace(/-/g, "+").replace(/_/g, "/");
|
|
1521
|
-
}
|
|
1522
|
-
const binary = atob(encoded), bytes = new Uint8Array(binary.length);
|
|
1523
|
-
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
1524
|
-
return bytes;
|
|
1525
|
-
}
|
|
1526
|
-
//#endregion
|
|
1527
|
-
//#region ../../node_modules/jose/dist/webapi/util/errors.js
|
|
1528
|
-
var JOSEError = class extends Error {
|
|
1529
|
-
static code = "ERR_JOSE_GENERIC";
|
|
1530
|
-
code = "ERR_JOSE_GENERIC";
|
|
1531
|
-
constructor(message, options) {
|
|
1532
|
-
super(message, options), this.name = this.constructor.name, Error.captureStackTrace?.(this, this.constructor);
|
|
1533
|
-
}
|
|
1534
|
-
};
|
|
1535
|
-
var JWTClaimValidationFailed = class extends JOSEError {
|
|
1536
|
-
static code = "ERR_JWT_CLAIM_VALIDATION_FAILED";
|
|
1537
|
-
code = "ERR_JWT_CLAIM_VALIDATION_FAILED";
|
|
1538
|
-
claim;
|
|
1539
|
-
reason;
|
|
1540
|
-
payload;
|
|
1541
|
-
constructor(message, payload, claim = "unspecified", reason = "unspecified") {
|
|
1542
|
-
super(message, { cause: {
|
|
1543
|
-
claim,
|
|
1544
|
-
reason,
|
|
1545
|
-
payload
|
|
1546
|
-
} }), this.claim = claim, this.reason = reason, this.payload = payload;
|
|
1547
|
-
}
|
|
1548
|
-
};
|
|
1549
|
-
var JWTExpired = class extends JOSEError {
|
|
1550
|
-
static code = "ERR_JWT_EXPIRED";
|
|
1551
|
-
code = "ERR_JWT_EXPIRED";
|
|
1552
|
-
claim;
|
|
1553
|
-
reason;
|
|
1554
|
-
payload;
|
|
1555
|
-
constructor(message, payload, claim = "unspecified", reason = "unspecified") {
|
|
1556
|
-
super(message, { cause: {
|
|
1557
|
-
claim,
|
|
1558
|
-
reason,
|
|
1559
|
-
payload
|
|
1560
|
-
} }), this.claim = claim, this.reason = reason, this.payload = payload;
|
|
1561
|
-
}
|
|
1562
|
-
};
|
|
1563
|
-
var JOSEAlgNotAllowed = class extends JOSEError {
|
|
1564
|
-
static code = "ERR_JOSE_ALG_NOT_ALLOWED";
|
|
1565
|
-
code = "ERR_JOSE_ALG_NOT_ALLOWED";
|
|
1566
|
-
};
|
|
1567
|
-
var JOSENotSupported = class extends JOSEError {
|
|
1568
|
-
static code = "ERR_JOSE_NOT_SUPPORTED";
|
|
1569
|
-
code = "ERR_JOSE_NOT_SUPPORTED";
|
|
1570
|
-
};
|
|
1571
|
-
var JWSInvalid = class extends JOSEError {
|
|
1572
|
-
static code = "ERR_JWS_INVALID";
|
|
1573
|
-
code = "ERR_JWS_INVALID";
|
|
1574
|
-
};
|
|
1575
|
-
var JWTInvalid = class extends JOSEError {
|
|
1576
|
-
static code = "ERR_JWT_INVALID";
|
|
1577
|
-
code = "ERR_JWT_INVALID";
|
|
1578
|
-
};
|
|
1579
|
-
var JWSSignatureVerificationFailed = class extends JOSEError {
|
|
1580
|
-
static code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED";
|
|
1581
|
-
code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED";
|
|
1582
|
-
constructor(message = "signature verification failed", options) {
|
|
1583
|
-
super(message, options);
|
|
1584
|
-
}
|
|
1585
|
-
};
|
|
1586
|
-
//#endregion
|
|
1587
|
-
//#region ../../node_modules/jose/dist/webapi/util/base64url.js
|
|
1588
|
-
var invalid = "The input to be decoded is not correctly encoded.";
|
|
1589
|
-
function decode(input) {
|
|
1590
|
-
try {
|
|
1591
|
-
return decodeBase64(typeof input == "string" ? input : decoder.decode(input), !0);
|
|
1592
|
-
} catch (cause) {
|
|
1593
|
-
throw new TypeError(invalid, { cause });
|
|
1594
|
-
}
|
|
1595
|
-
}
|
|
1596
|
-
function encode(input) {
|
|
1597
|
-
return encodeBase64(typeof input == "string" ? encoder.encode(input) : input, !0);
|
|
1598
|
-
}
|
|
1599
|
-
//#endregion
|
|
1600
|
-
//#region ../../node_modules/jose/dist/webapi/lib/validate.js
|
|
1601
|
-
function isObject$1(input) {
|
|
1602
|
-
if (typeof input != "object" || input === null || Object.prototype.toString.call(input) !== "[object Object]") return !1;
|
|
1603
|
-
const prototype = Object.getPrototypeOf(input);
|
|
1604
|
-
return prototype === null || Object.getPrototypeOf(prototype) === null;
|
|
1605
|
-
}
|
|
1606
|
-
function isDisjoint(...headers) {
|
|
1607
|
-
const parameters = /* @__PURE__ */ new Set();
|
|
1608
|
-
for (const header of headers) if (header) for (const parameter of Object.keys(header)) {
|
|
1609
|
-
if (parameters.has(parameter)) return !1;
|
|
1610
|
-
parameters.add(parameter);
|
|
1611
|
-
}
|
|
1612
|
-
return !0;
|
|
1613
|
-
}
|
|
1614
|
-
function assertNotSet(value, name) {
|
|
1615
|
-
if (value !== void 0) throw new TypeError(`${name} can only be called once`);
|
|
1616
|
-
}
|
|
1617
|
-
function decodeBase64url(value, label, ErrorClass) {
|
|
1618
|
-
try {
|
|
1619
|
-
return decode(value);
|
|
1620
|
-
} catch {
|
|
1621
|
-
throw new ErrorClass(`Failed to base64url decode the ${label}`);
|
|
1622
|
-
}
|
|
1623
|
-
}
|
|
1624
|
-
function encodeBase64url(value, label, ErrorClass) {
|
|
1625
|
-
try {
|
|
1626
|
-
return encode$1(value);
|
|
1627
|
-
} catch {
|
|
1628
|
-
throw new ErrorClass(`The ${label} is not a valid base64url string`);
|
|
1629
|
-
}
|
|
1630
|
-
}
|
|
1631
|
-
function parseJoseHeader(b64, ErrorClass, message) {
|
|
1632
|
-
let parsed;
|
|
1633
|
-
try {
|
|
1634
|
-
parsed = JSON.parse(strictDecoder.decode(decode(b64)));
|
|
1635
|
-
} catch {
|
|
1636
|
-
throw new ErrorClass(message);
|
|
1637
|
-
}
|
|
1638
|
-
if (!isObject$1(parsed)) throw new ErrorClass(message);
|
|
1639
|
-
return parsed;
|
|
1640
|
-
}
|
|
1641
|
-
var JWS_RECOGNIZED = {
|
|
1642
|
-
__proto__: null,
|
|
1643
|
-
b64: !0
|
|
1644
|
-
};
|
|
1645
|
-
function validateAlgorithms(option, algorithms) {
|
|
1646
|
-
if (algorithms !== void 0 && (!Array.isArray(algorithms) || algorithms.some((s) => typeof s != "string"))) throw new TypeError(`"${option}" option must be an array of strings`);
|
|
1647
|
-
return algorithms === void 0 ? void 0 : new Set(algorithms);
|
|
1648
|
-
}
|
|
1649
|
-
function validateCritDuplicates(Err, protectedHeader) {
|
|
1650
|
-
const { crit } = protectedHeader ?? {};
|
|
1651
|
-
if (Array.isArray(crit) && new Set(crit).size !== crit.length) throw new Err("\"crit\" (Critical) Header Parameter MUST NOT contain duplicate values");
|
|
1652
|
-
}
|
|
1653
|
-
function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) {
|
|
1654
|
-
if (joseHeader.crit !== void 0 && protectedHeader?.crit === void 0) throw new Err("\"crit\" (Critical) Header Parameter MUST be integrity protected");
|
|
1655
|
-
if (!protectedHeader || protectedHeader.crit === void 0) return [];
|
|
1656
|
-
if (!Array.isArray(protectedHeader.crit) || protectedHeader.crit.length === 0 || protectedHeader.crit.some((input) => typeof input != "string" || input.length === 0)) throw new Err("\"crit\" (Critical) Header Parameter MUST be an array of non-empty strings when present");
|
|
1657
|
-
const recognized = recognizedOption === void 0 ? recognizedDefault : {
|
|
1658
|
-
__proto__: null,
|
|
1659
|
-
...recognizedOption,
|
|
1660
|
-
...recognizedDefault
|
|
1661
|
-
};
|
|
1662
|
-
for (const parameter of protectedHeader.crit) {
|
|
1663
|
-
if (!(parameter in recognized)) throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`);
|
|
1664
|
-
if (!Object.hasOwn(joseHeader, parameter) || joseHeader[parameter] === void 0) throw new Err(`Extension Header Parameter "${parameter}" is missing`);
|
|
1665
|
-
if (recognized[parameter] && (!Object.hasOwn(protectedHeader, parameter) || protectedHeader[parameter] === void 0)) throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`);
|
|
1666
|
-
}
|
|
1667
|
-
return protectedHeader.crit;
|
|
1668
|
-
}
|
|
1669
|
-
function validateB64(protectedHeader, extensions) {
|
|
1670
|
-
if (extensions.includes("b64")) {
|
|
1671
|
-
const b64 = protectedHeader.b64;
|
|
1672
|
-
if (typeof b64 != "boolean") throw new JWSInvalid("The \"b64\" (base64url-encode payload) Header Parameter must be a boolean");
|
|
1673
|
-
return b64;
|
|
1674
|
-
}
|
|
1675
|
-
return !0;
|
|
1676
|
-
}
|
|
1677
|
-
function serializeJoseHeader(Err, header) {
|
|
1678
|
-
let serialized, parsed;
|
|
1679
|
-
try {
|
|
1680
|
-
serialized = JSON.stringify(header), parsed = JSON.parse(serialized);
|
|
1681
|
-
} catch (cause) {
|
|
1682
|
-
throw new Err("JOSE Header is not valid JSON", { cause });
|
|
1683
|
-
}
|
|
1684
|
-
if (!isObject$1(parsed)) throw new Err("JOSE Header is not a JSON object");
|
|
1685
|
-
return [parsed, serialized];
|
|
1686
|
-
}
|
|
1687
|
-
//#endregion
|
|
1688
|
-
//#region ../../node_modules/jose/dist/webapi/lib/key.js
|
|
1689
|
-
var tag = (key) => key[Symbol.toStringTag], jwkMatchesOp = (entry, key, usage) => {
|
|
1690
|
-
const { alg } = entry;
|
|
1691
|
-
if (key.use !== void 0) {
|
|
1692
|
-
const expected = usage === "sign" || usage === "verify" ? "sig" : "enc";
|
|
1693
|
-
if (key.use !== expected) throw new TypeError(`Invalid key for this operation, its "use" must be "${expected}" when present`);
|
|
1694
|
-
}
|
|
1695
|
-
if (key.alg !== void 0 && key.alg !== alg) throw new TypeError(`Invalid key for this operation, its "alg" must be "${alg}" when present`);
|
|
1696
|
-
if (Array.isArray(key.key_ops)) {
|
|
1697
|
-
const expectedKeyOp = usage === "encrypt" || usage === "decrypt" ? entry.ops?.[usage === "encrypt" ? 0 : 1] : usage;
|
|
1698
|
-
if (expectedKeyOp && !key.key_ops.includes(expectedKeyOp)) throw new TypeError(`Invalid key for this operation, its "key_ops" must include "${expectedKeyOp}" when present`);
|
|
1699
|
-
}
|
|
1700
|
-
};
|
|
1701
|
-
async function prepareKey(entry, key, usage) {
|
|
1702
|
-
const { alg, secret } = entry, privateKey = usage === "decrypt" || usage === "sign";
|
|
1703
|
-
if (secret && key instanceof Uint8Array) return key;
|
|
1704
|
-
let normalized, keyObject;
|
|
1705
|
-
if (isObject$1(key)) {
|
|
1706
|
-
if (normalized = normalizeJwk(key), typeof normalized.kty != "string") throw invalidKeyType(alg, key, secret);
|
|
1707
|
-
if (!(secret ? normalized.kty === "oct" && typeof normalized.k == "string" : normalized.kty !== "oct" && (privateKey ? normalized.kty === "AKP" && typeof normalized.priv == "string" || typeof normalized.d == "string" : normalized.d === void 0 && normalized.priv === void 0))) throw new TypeError(secret ? "JSON Web Key for symmetric algorithms must have JWK \"kty\" (Key Type) equal to \"oct\" and the JWK \"k\" (Key Value) present" : `JSON Web Key for this operation must be a ${privateKey ? "private" : "public"} JWK`);
|
|
1708
|
-
if (jwkMatchesOp(entry, normalized, usage), normalized.kty === "oct") return decode(normalized.k);
|
|
1709
|
-
if (!Object.isFrozen(key)) {
|
|
1710
|
-
const { key_ops } = key;
|
|
1711
|
-
Array.isArray(key_ops) && Object.freeze(key_ops), Object.freeze(key);
|
|
1712
|
-
}
|
|
1713
|
-
} else {
|
|
1714
|
-
if (!isKeyLike(key)) throw invalidKeyType(alg, key, secret);
|
|
1715
|
-
const expectedType = secret ? "secret" : privateKey ? "private" : "public";
|
|
1716
|
-
if (key.type !== expectedType && (secret || [
|
|
1717
|
-
"secret",
|
|
1718
|
-
"public",
|
|
1719
|
-
"private"
|
|
1720
|
-
].includes(key.type))) throw new TypeError(`${tag(key)} instances must be of type "${expectedType}" for the ${alg} algorithm`);
|
|
1721
|
-
if (isCryptoKey(key)) return key;
|
|
1722
|
-
if (keyObject = key, keyObject.type === "secret") return keyObject.export();
|
|
1723
|
-
}
|
|
1724
|
-
cache ||= /* @__PURE__ */ new WeakMap();
|
|
1725
|
-
const cacheKey = key;
|
|
1726
|
-
let cached = cache.get(cacheKey);
|
|
1727
|
-
if (cached?.[alg]) return cached[alg];
|
|
1728
|
-
if (cached || cache.set(cacheKey, cached = {}), keyObject && typeof keyObject.toCryptoKey == "function") {
|
|
1729
|
-
const isPublic = keyObject.type === "public", crv = nist[keyObject.asymmetricKeyDetails?.namedCurve], params = entry.resolve?.({
|
|
1730
|
-
crv,
|
|
1731
|
-
asymmetricKeyType: keyObject.asymmetricKeyType
|
|
1732
|
-
}) ?? entry.subtle;
|
|
1733
|
-
return cached[alg] = keyObject.toCryptoKey(params, isPublic, entry.usages[isPublic ? 0 : 1]);
|
|
1734
|
-
}
|
|
1735
|
-
return normalized ??= keyObject.export({ format: "jwk" }), normalized.alg = alg, cached[alg] = await jwkToKey(entry, normalized);
|
|
1736
|
-
}
|
|
1737
|
-
var cache;
|
|
1738
|
-
var nist = {
|
|
1739
|
-
__proto__: null,
|
|
1740
|
-
prime256v1: "P-256",
|
|
1741
|
-
secp384r1: "P-384",
|
|
1742
|
-
secp521r1: "P-521"
|
|
1743
|
-
};
|
|
1744
|
-
var isCryptoKey = (key) => {
|
|
1745
|
-
if (key?.[Symbol.toStringTag] === "CryptoKey") return !0;
|
|
1746
|
-
try {
|
|
1747
|
-
return key instanceof CryptoKey;
|
|
1748
|
-
} catch {
|
|
1749
|
-
return !1;
|
|
1750
|
-
}
|
|
1751
|
-
}, isKeyObject = (key) => key?.[Symbol.toStringTag] === "KeyObject", isKeyLike = (key) => isCryptoKey(key) || isKeyObject(key);
|
|
1752
|
-
function message(msg, actual, ...types) {
|
|
1753
|
-
if (types.length > 2) {
|
|
1754
|
-
const last = types.pop();
|
|
1755
|
-
msg += `one of type ${types.join(", ")}, or ${last}.`;
|
|
1756
|
-
} else types.length === 2 ? msg += `one of type ${types[0]} or ${types[1]}.` : msg += `of type ${types[0]}.`;
|
|
1757
|
-
return actual == null ? msg += ` Received ${actual}` : typeof actual == "function" && actual.name ? msg += ` Received function ${actual.name}` : typeof actual == "object" && actual != null && actual.constructor?.name && (msg += ` Received an instance of ${actual.constructor.name}`), msg;
|
|
1758
|
-
}
|
|
1759
|
-
function invalidKeyType(alg, actual, secret) {
|
|
1760
|
-
const types = [
|
|
1761
|
-
"CryptoKey",
|
|
1762
|
-
"KeyObject",
|
|
1763
|
-
"JSON Web Key"
|
|
1764
|
-
];
|
|
1765
|
-
return secret && types.push("Uint8Array"), new TypeError(message(`Key for the ${alg} algorithm must be `, actual, ...types));
|
|
1766
|
-
}
|
|
1767
|
-
var unusable = (name, prop = "algorithm.name") => /* @__PURE__ */ new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`);
|
|
1768
|
-
function checkUsage(key, usage) {
|
|
1769
|
-
if (usage && !key.usages.includes(usage)) throw new TypeError(`CryptoKey does not support this operation, its usages must include ${usage}.`);
|
|
1770
|
-
}
|
|
1771
|
-
function checkModulusLength(alg, key) {
|
|
1772
|
-
const { modulusLength } = key.algorithm;
|
|
1773
|
-
if (typeof modulusLength != "number" || modulusLength < 2048) throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`);
|
|
1774
|
-
}
|
|
1775
|
-
function checkCryptoKey(key, expected, usage) {
|
|
1776
|
-
const algorithm = key.algorithm;
|
|
1777
|
-
if (algorithm.name !== expected.name) throw unusable(expected.name);
|
|
1778
|
-
if (expected.hash && algorithm.hash?.name !== expected.hash) throw unusable(expected.hash, "algorithm.hash");
|
|
1779
|
-
if (expected.namedCurve && algorithm.namedCurve !== expected.namedCurve) throw unusable(expected.namedCurve, "algorithm.namedCurve");
|
|
1780
|
-
if (expected.length !== void 0 && algorithm.length !== expected.length) throw unusable(expected.length, "algorithm.length");
|
|
1781
|
-
checkUsage(key, usage);
|
|
1782
|
-
}
|
|
1783
|
-
function snapshotJwk(jwk) {
|
|
1784
|
-
return {
|
|
1785
|
-
__proto__: null,
|
|
1786
|
-
...jwk
|
|
1787
|
-
};
|
|
1788
|
-
}
|
|
1789
|
-
function normalizeJwk(jwk) {
|
|
1790
|
-
const normalized = snapshotJwk(jwk);
|
|
1791
|
-
if (normalized.ext !== void 0 && typeof normalized.ext != "boolean") throw new TypeError("\"ext\" (Extractable) Parameter must be a boolean");
|
|
1792
|
-
if (normalized.key_ops !== void 0) {
|
|
1793
|
-
const value = normalized.key_ops, keyOps = Array.isArray(value) ? [...value] : void 0;
|
|
1794
|
-
if (!keyOps || keyOps.some((operation) => typeof operation != "string") || new Set(keyOps).size !== keyOps.length) throw new TypeError("\"key_ops\" (Key Operations) Parameter must be an array of unique strings");
|
|
1795
|
-
normalized.key_ops = keyOps;
|
|
1796
|
-
}
|
|
1797
|
-
return normalized;
|
|
1798
|
-
}
|
|
1799
|
-
async function jwkToKey(entry, jwk, extractable) {
|
|
1800
|
-
if (!entry.kty.includes(jwk.kty)) throw new JOSENotSupported("Invalid or unsupported JWK \"alg\" (Algorithm) Parameter value");
|
|
1801
|
-
const algorithm = entry.resolve?.({
|
|
1802
|
-
kty: jwk.kty,
|
|
1803
|
-
crv: jwk.crv
|
|
1804
|
-
}) ?? entry.subtle, isPrivate = !!(jwk.d || jwk.priv), keyData = {
|
|
1805
|
-
...jwk,
|
|
1806
|
-
ext: extractable ?? jwk.ext
|
|
1807
|
-
};
|
|
1808
|
-
return keyData.kty !== "AKP" && delete keyData.alg, delete keyData.use, crypto.subtle.importKey("jwk", keyData, algorithm, keyData.ext ?? !isPrivate, jwk.key_ops ?? entry.usages[isPrivate ? 1 : 0]);
|
|
1809
|
-
}
|
|
1810
|
-
async function rawKey(key, expected, usage, extractable = !1) {
|
|
1811
|
-
return key instanceof Uint8Array && (key = await crypto.subtle.importKey("raw", key, expected, extractable, [usage])), checkCryptoKey(key, expected, usage), key;
|
|
1812
|
-
}
|
|
1813
|
-
//#endregion
|
|
1814
|
-
//#region ../../node_modules/jose/dist/webapi/lib/key_descriptor.js
|
|
1815
|
-
function table(entries) {
|
|
1816
|
-
const out = { __proto__: null };
|
|
1817
|
-
for (const alg in entries) out[alg] = {
|
|
1818
|
-
...entries[alg],
|
|
1819
|
-
alg
|
|
1820
|
-
};
|
|
1821
|
-
return out;
|
|
1822
|
-
}
|
|
1823
|
-
//#endregion
|
|
1824
|
-
//#region ../../node_modules/jose/dist/webapi/lib/jws_algorithms.js
|
|
1825
|
-
var sig = [["verify"], ["sign"]];
|
|
1826
|
-
function hmac(bits) {
|
|
1827
|
-
const subtle = {
|
|
1828
|
-
name: "HMAC",
|
|
1829
|
-
hash: `SHA-${bits}`
|
|
1830
|
-
};
|
|
1831
|
-
return {
|
|
1832
|
-
kty: ["oct"],
|
|
1833
|
-
secret: !0,
|
|
1834
|
-
subtle,
|
|
1835
|
-
signing: subtle,
|
|
1836
|
-
usages: sig
|
|
1837
|
-
};
|
|
1838
|
-
}
|
|
1839
|
-
function rsa(bits, saltLength) {
|
|
1840
|
-
const subtle = {
|
|
1841
|
-
name: saltLength ? "RSA-PSS" : "RSASSA-PKCS1-v1_5",
|
|
1842
|
-
hash: `SHA-${bits}`
|
|
1843
|
-
};
|
|
1844
|
-
return {
|
|
1845
|
-
kty: ["RSA"],
|
|
1846
|
-
subtle,
|
|
1847
|
-
signing: saltLength ? {
|
|
1848
|
-
...subtle,
|
|
1849
|
-
saltLength
|
|
1850
|
-
} : subtle,
|
|
1851
|
-
usages: sig,
|
|
1852
|
-
minRsaBits: 2048
|
|
1853
|
-
};
|
|
1854
|
-
}
|
|
1855
|
-
function ecdsa(crv, bits) {
|
|
1856
|
-
return {
|
|
1857
|
-
kty: ["EC"],
|
|
1858
|
-
crv,
|
|
1859
|
-
subtle: {
|
|
1860
|
-
name: "ECDSA",
|
|
1861
|
-
namedCurve: crv
|
|
1862
|
-
},
|
|
1863
|
-
signing: {
|
|
1864
|
-
name: "ECDSA",
|
|
1865
|
-
hash: `SHA-${bits}`
|
|
1866
|
-
},
|
|
1867
|
-
usages: sig
|
|
1868
|
-
};
|
|
1869
|
-
}
|
|
1870
|
-
function eddsa() {
|
|
1871
|
-
const subtle = { name: "Ed25519" };
|
|
1872
|
-
return {
|
|
1873
|
-
kty: ["OKP"],
|
|
1874
|
-
crv: "Ed25519",
|
|
1875
|
-
subtle,
|
|
1876
|
-
signing: subtle,
|
|
1877
|
-
usages: sig
|
|
1878
|
-
};
|
|
1879
|
-
}
|
|
1880
|
-
function mldsa(bits) {
|
|
1881
|
-
const subtle = { name: `ML-DSA-${bits}` };
|
|
1882
|
-
return {
|
|
1883
|
-
kty: ["AKP"],
|
|
1884
|
-
subtle,
|
|
1885
|
-
signing: subtle,
|
|
1886
|
-
usages: sig
|
|
1887
|
-
};
|
|
1888
|
-
}
|
|
1889
|
-
var JWS = table({
|
|
1890
|
-
HS256: hmac(256),
|
|
1891
|
-
HS384: hmac(384),
|
|
1892
|
-
HS512: hmac(512),
|
|
1893
|
-
RS256: rsa(256),
|
|
1894
|
-
RS384: rsa(384),
|
|
1895
|
-
RS512: rsa(512),
|
|
1896
|
-
PS256: rsa(256, 32),
|
|
1897
|
-
PS384: rsa(384, 48),
|
|
1898
|
-
PS512: rsa(512, 64),
|
|
1899
|
-
ES256: ecdsa("P-256", 256),
|
|
1900
|
-
ES384: ecdsa("P-384", 384),
|
|
1901
|
-
ES512: ecdsa("P-521", 512),
|
|
1902
|
-
EdDSA: eddsa(),
|
|
1903
|
-
Ed25519: eddsa(),
|
|
1904
|
-
"ML-DSA-44": mldsa(44),
|
|
1905
|
-
"ML-DSA-65": mldsa(65),
|
|
1906
|
-
"ML-DSA-87": mldsa(87)
|
|
1907
|
-
});
|
|
1908
|
-
function jwsAlgorithm(alg) {
|
|
1909
|
-
const entry = typeof alg == "string" ? JWS[alg] : void 0;
|
|
1910
|
-
if (!entry) throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`);
|
|
1911
|
-
return entry;
|
|
1912
|
-
}
|
|
1913
|
-
//#endregion
|
|
1914
|
-
//#region ../../node_modules/jose/dist/webapi/lib/jws_verify.js
|
|
1915
|
-
function prepareVerify(options) {
|
|
1916
|
-
return [options && validateAlgorithms("algorithms", options.algorithms), options?.crit];
|
|
1917
|
-
}
|
|
1918
|
-
function parseProtectedHeader(encodedProtected) {
|
|
1919
|
-
return encodedProtected === void 0 ? {} : parseJoseHeader(encodedProtected, JWSInvalid, "JWS Protected Header is invalid");
|
|
1920
|
-
}
|
|
1921
|
-
function encodeCompactUnencodedPayload(payload) {
|
|
1922
|
-
try {
|
|
1923
|
-
return encode$1(payload);
|
|
1924
|
-
} catch {
|
|
1925
|
-
throw new JWSInvalid("JWS Compact Serialization payload must use only ASCII characters");
|
|
1926
|
-
}
|
|
1927
|
-
}
|
|
1928
|
-
async function verifySignature(jws, shared, key, encodeUnencodedPayload, parsedProtected) {
|
|
1929
|
-
const { protected: encodedProtected, header, payload: inputPayload } = jws, parsedProt = parsedProtected ?? parseProtectedHeader(encodedProtected);
|
|
1930
|
-
if (!isDisjoint(parsedProt, header)) throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
|
|
1931
|
-
const joseHeader = {
|
|
1932
|
-
...parsedProt,
|
|
1933
|
-
...header
|
|
1934
|
-
}, b64 = validateB64(parsedProt, validateCrit(JWSInvalid, JWS_RECOGNIZED, shared[1], parsedProt, joseHeader)), { alg } = joseHeader;
|
|
1935
|
-
if (typeof alg != "string" || !alg) throw new JWSInvalid("JWS \"alg\" (Algorithm) Header Parameter missing or invalid");
|
|
1936
|
-
if (shared[0] && !shared[0].has(alg)) throw new JOSEAlgNotAllowed("\"alg\" (Algorithm) Header Parameter value not allowed");
|
|
1937
|
-
if (b64) {
|
|
1938
|
-
if (typeof inputPayload != "string") throw new JWSInvalid("JWS Payload must be a string");
|
|
1939
|
-
} else if (typeof inputPayload != "string" && !(inputPayload instanceof Uint8Array)) throw new JWSInvalid("JWS Payload must be a string or an Uint8Array instance");
|
|
1940
|
-
const signingPayload = b64 || typeof inputPayload != "string" ? inputPayload : encodeUnencodedPayload(inputPayload);
|
|
1941
|
-
let resolvedKey = !1;
|
|
1942
|
-
typeof key == "function" && (key = await key(parsedProt, jws), resolvedKey = !0);
|
|
1943
|
-
const entry = jwsAlgorithm(alg), data = concat(encodedProtected !== void 0 ? encode$1(encodedProtected) : new Uint8Array(), encode$1("."), typeof signingPayload == "string" ? shared[2] ??= encodeBase64url(signingPayload, "payload", JWSInvalid) : signingPayload), signature = decodeBase64url(jws.signature, "signature", JWSInvalid), k = await prepareKey(entry, key, "verify"), cryptoKey = await rawKey(k, entry.subtle, "verify");
|
|
1944
|
-
entry.minRsaBits && checkModulusLength(entry.alg, cryptoKey);
|
|
1945
|
-
let verified = !1;
|
|
1946
|
-
try {
|
|
1947
|
-
verified = await crypto.subtle.verify(entry.signing, cryptoKey, signature, data);
|
|
1948
|
-
} catch {}
|
|
1949
|
-
if (!verified) throw new JWSSignatureVerificationFailed();
|
|
1950
|
-
const result = { payload: typeof signingPayload == "string" ? decodeBase64url(signingPayload, "payload", JWSInvalid) : signingPayload };
|
|
1951
|
-
return encodedProtected !== void 0 && (result.protectedHeader = parsedProt), header !== void 0 && (result.unprotectedHeader = header), resolvedKey ? [{
|
|
1952
|
-
...result,
|
|
1953
|
-
key: k
|
|
1954
|
-
}, b64] : [result, b64];
|
|
1955
|
-
}
|
|
1956
|
-
async function verifyCompact(jws, shared, key) {
|
|
1957
|
-
if (jws instanceof Uint8Array && (jws = decoder.decode(jws)), typeof jws != "string") throw new JWSInvalid("Compact JWS must be a string or Uint8Array");
|
|
1958
|
-
const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split(".");
|
|
1959
|
-
if (length !== 3) throw new JWSInvalid("Invalid Compact JWS");
|
|
1960
|
-
return verifySignature({
|
|
1961
|
-
payload,
|
|
1962
|
-
protected: protectedHeader,
|
|
1963
|
-
signature
|
|
1964
|
-
}, shared, key, encodeCompactUnencodedPayload);
|
|
1965
|
-
}
|
|
1966
|
-
//#endregion
|
|
1967
|
-
//#region ../../node_modules/jose/dist/webapi/lib/jwt_claims_set.js
|
|
1968
|
-
var epoch = (date) => Math.floor(date.getTime() / 1e3), multipliers = {
|
|
1969
|
-
s: 1,
|
|
1970
|
-
m: 60,
|
|
1971
|
-
h: 3600,
|
|
1972
|
-
d: 86400,
|
|
1973
|
-
w: 604800,
|
|
1974
|
-
y: 31557600
|
|
1975
|
-
}, REGEX = /^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i, checkFailed = "check_failed";
|
|
1976
|
-
function invalidDuration() {
|
|
1977
|
-
throw new TypeError("Invalid time period format");
|
|
1978
|
-
}
|
|
1979
|
-
function secs(str) {
|
|
1980
|
-
typeof str != "string" && invalidDuration();
|
|
1981
|
-
const matched = REGEX.exec(str);
|
|
1982
|
-
(!matched || matched[4] && matched[1]) && invalidDuration();
|
|
1983
|
-
const value = parseFloat(matched[2]), numericDate2 = Math.round(value * multipliers[matched[3][0].toLowerCase()]);
|
|
1984
|
-
return Number.isFinite(numericDate2) || invalidDuration(), matched[1] === "-" || matched[4] === "ago" ? -numericDate2 : numericDate2;
|
|
1985
|
-
}
|
|
1986
|
-
function validateInput(label, input) {
|
|
1987
|
-
if (!Number.isFinite(input)) throw new TypeError(`Invalid ${label} input`);
|
|
1988
|
-
return input;
|
|
1989
|
-
}
|
|
1990
|
-
function validateStringClaim(claim, value) {
|
|
1991
|
-
if (typeof value != "string") throw new TypeError(`"${claim}" claim must be a string`);
|
|
1992
|
-
}
|
|
1993
|
-
function validateAudienceClaim(value) {
|
|
1994
|
-
if (typeof value != "string" && (!Array.isArray(value) || Array.from(value).some((member) => typeof member != "string"))) throw new TypeError("\"aud\" claim must be a string or an array of strings");
|
|
1995
|
-
}
|
|
1996
|
-
function numericDate(value, label) {
|
|
1997
|
-
return typeof value == "number" ? validateInput(label, value) : value instanceof Date ? validateInput(label, epoch(value)) : epoch(/* @__PURE__ */ new Date()) + secs(value);
|
|
1998
|
-
}
|
|
1999
|
-
var normalizeTyp = (value) => {
|
|
2000
|
-
const normalized = value.toLowerCase();
|
|
2001
|
-
return value.includes("/") ? normalized : `application/${normalized}`;
|
|
2002
|
-
}, checkAudiencePresence = (audPayload, audOption) => typeof audPayload == "string" ? audOption.includes(audPayload) : Array.isArray(audPayload) ? audOption.some((aud) => audPayload.includes(aud)) : !1;
|
|
2003
|
-
function validateNumericDate(payload, claim, required = !1) {
|
|
2004
|
-
const value = payload[claim];
|
|
2005
|
-
if (!(value === void 0 && !required)) {
|
|
2006
|
-
if (typeof value != "number") throw new JWTClaimValidationFailed(`"${claim}" claim must be a number`, payload, claim, "invalid");
|
|
2007
|
-
return value;
|
|
2008
|
-
}
|
|
2009
|
-
}
|
|
2010
|
-
function unexpectedClaim(payload, claim) {
|
|
2011
|
-
throw new JWTClaimValidationFailed(`unexpected "${claim}" claim value`, payload, claim, checkFailed);
|
|
2012
|
-
}
|
|
2013
|
-
function validateClaimsSet(protectedHeader, encodedPayload, options = {}) {
|
|
2014
|
-
let payload;
|
|
2015
|
-
try {
|
|
2016
|
-
payload = JSON.parse(strictDecoder.decode(encodedPayload));
|
|
2017
|
-
} catch {}
|
|
2018
|
-
if (!isObject$1(payload)) throw new JWTInvalid("JWT Claims Set must be a top-level JSON object");
|
|
2019
|
-
const { typ } = options;
|
|
2020
|
-
if (typ !== void 0 && (typeof protectedHeader.typ != "string" || normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) throw new JWTClaimValidationFailed("unexpected \"typ\" JWT header value", payload, "typ", checkFailed);
|
|
2021
|
-
const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options, presenceCheck = [...requiredClaims];
|
|
2022
|
-
maxTokenAge !== void 0 && presenceCheck.push("iat"), audience !== void 0 && presenceCheck.push("aud"), subject !== void 0 && presenceCheck.push("sub"), issuer !== void 0 && presenceCheck.push("iss");
|
|
2023
|
-
for (const claim of new Set(presenceCheck.reverse())) if (!Object.hasOwn(payload, claim)) throw new JWTClaimValidationFailed(`missing required "${claim}" claim`, payload, claim, "missing");
|
|
2024
|
-
issuer !== void 0 && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss) && unexpectedClaim(payload, "iss"), subject !== void 0 && payload.sub !== subject && unexpectedClaim(payload, "sub"), audience !== void 0 && !checkAudiencePresence(payload.aud, typeof audience == "string" ? [audience] : audience) && unexpectedClaim(payload, "aud");
|
|
2025
|
-
const { clockTolerance } = options;
|
|
2026
|
-
let tolerance = 0;
|
|
2027
|
-
if (typeof clockTolerance == "string") tolerance = secs(clockTolerance);
|
|
2028
|
-
else if (clockTolerance !== void 0) {
|
|
2029
|
-
if (typeof clockTolerance != "number") throw new TypeError("Invalid clockTolerance option type");
|
|
2030
|
-
tolerance = clockTolerance;
|
|
2031
|
-
}
|
|
2032
|
-
validateInput("clockTolerance option", tolerance);
|
|
2033
|
-
const { currentDate } = options, now = validateInput("currentDate option", epoch(currentDate === void 0 ? /* @__PURE__ */ new Date() : currentDate)), iat = validateNumericDate(payload, "iat", maxTokenAge !== void 0), nbf = validateNumericDate(payload, "nbf");
|
|
2034
|
-
if (nbf !== void 0 && nbf > now + tolerance) throw new JWTClaimValidationFailed("\"nbf\" claim timestamp check failed", payload, "nbf", checkFailed);
|
|
2035
|
-
const exp = validateNumericDate(payload, "exp");
|
|
2036
|
-
if (exp !== void 0 && exp <= now - tolerance) throw new JWTExpired("\"exp\" claim timestamp check failed", payload, "exp", checkFailed);
|
|
2037
|
-
if (maxTokenAge !== void 0) {
|
|
2038
|
-
const age = now - iat, max = validateInput("maxTokenAge option", typeof maxTokenAge == "number" ? maxTokenAge : secs(maxTokenAge));
|
|
2039
|
-
if (age - tolerance > max) throw new JWTExpired("\"iat\" claim timestamp check failed (too far in the past)", payload, "iat", checkFailed);
|
|
2040
|
-
if (age < -tolerance) throw new JWTClaimValidationFailed("\"iat\" claim timestamp check failed (it should be in the past)", payload, "iat", checkFailed);
|
|
2041
|
-
}
|
|
2042
|
-
return payload;
|
|
2043
|
-
}
|
|
2044
|
-
var producerPayloads;
|
|
2045
|
-
function producerPayload(producer) {
|
|
2046
|
-
return producerPayloads.get(producer);
|
|
2047
|
-
}
|
|
2048
|
-
function jwtData(producer) {
|
|
2049
|
-
const payload = producerPayload(producer);
|
|
2050
|
-
for (const claim of [
|
|
2051
|
-
"iat",
|
|
2052
|
-
"nbf",
|
|
2053
|
-
"exp"
|
|
2054
|
-
]) {
|
|
2055
|
-
const value = payload[claim];
|
|
2056
|
-
if (typeof value == "number" && !Number.isFinite(value)) throw new TypeError(`"${claim}" claim must be a finite number`);
|
|
2057
|
-
}
|
|
2058
|
-
return encoder.encode(JSON.stringify(payload));
|
|
2059
|
-
}
|
|
2060
|
-
var JWTClaimsBuilder = class {
|
|
2061
|
-
constructor(payload = {}) {
|
|
2062
|
-
if (!isObject$1(payload)) throw new TypeError("JWT Claims Set MUST be an object");
|
|
2063
|
-
(producerPayloads ||= /* @__PURE__ */ new WeakMap()).set(this, structuredClone(payload));
|
|
2064
|
-
}
|
|
2065
|
-
setIssuer(value) {
|
|
2066
|
-
return validateStringClaim("iss", value), producerPayload(this).iss = value, this;
|
|
2067
|
-
}
|
|
2068
|
-
setSubject(value) {
|
|
2069
|
-
return validateStringClaim("sub", value), producerPayload(this).sub = value, this;
|
|
2070
|
-
}
|
|
2071
|
-
setAudience(value) {
|
|
2072
|
-
return validateAudienceClaim(value), producerPayload(this).aud = value, this;
|
|
2073
|
-
}
|
|
2074
|
-
setJti(value) {
|
|
2075
|
-
return validateStringClaim("jti", value), producerPayload(this).jti = value, this;
|
|
2076
|
-
}
|
|
2077
|
-
setNotBefore(value) {
|
|
2078
|
-
return producerPayload(this).nbf = numericDate(value, "setNotBefore"), this;
|
|
2079
|
-
}
|
|
2080
|
-
setExpirationTime(value) {
|
|
2081
|
-
return producerPayload(this).exp = numericDate(value, "setExpirationTime"), this;
|
|
2082
|
-
}
|
|
2083
|
-
setIssuedAt(value) {
|
|
2084
|
-
const payload = producerPayload(this);
|
|
2085
|
-
return value === void 0 ? payload.iat = epoch(/* @__PURE__ */ new Date()) : typeof value == "string" ? payload.iat = validateInput("setIssuedAt", epoch(/* @__PURE__ */ new Date()) + secs(value)) : payload.iat = numericDate(value, "setIssuedAt"), this;
|
|
2086
|
-
}
|
|
2087
|
-
};
|
|
2088
|
-
//#endregion
|
|
2089
|
-
//#region ../../node_modules/jose/dist/webapi/jwt/verify.js
|
|
2090
|
-
async function jwtVerify(jwt, key, options) {
|
|
2091
|
-
const [verified, b64] = await verifyCompact(jwt, prepareVerify(options), key);
|
|
2092
|
-
if (!b64) throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
|
|
2093
|
-
const payload = validateClaimsSet(verified.protectedHeader, verified.payload, options);
|
|
2094
|
-
return {
|
|
2095
|
-
...verified,
|
|
2096
|
-
payload
|
|
2097
|
-
};
|
|
2098
|
-
}
|
|
2099
|
-
//#endregion
|
|
2100
|
-
//#region ../../node_modules/jose/dist/webapi/lib/jws_sign.js
|
|
2101
|
-
async function createSignature(input, key, rejectUnencoded) {
|
|
2102
|
-
let [payload, protectedHeader, unprotectedHeader, crit] = input, protectedHeaderString = "";
|
|
2103
|
-
if (protectedHeader !== void 0) {
|
|
2104
|
-
const normalized = serializeJoseHeader(JWSInvalid, protectedHeader);
|
|
2105
|
-
protectedHeader = normalized[0], protectedHeaderString = encode(normalized[1]);
|
|
2106
|
-
}
|
|
2107
|
-
if (unprotectedHeader !== void 0 && (unprotectedHeader = serializeJoseHeader(JWSInvalid, unprotectedHeader)[0]), !protectedHeader && !unprotectedHeader) throw new JWSInvalid("either setProtectedHeader or setUnprotectedHeader must be called before #sign()");
|
|
2108
|
-
if (!isDisjoint(protectedHeader, unprotectedHeader)) throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint");
|
|
2109
|
-
const joseHeader = {
|
|
2110
|
-
...protectedHeader,
|
|
2111
|
-
...unprotectedHeader
|
|
2112
|
-
};
|
|
2113
|
-
validateCritDuplicates(JWSInvalid, protectedHeader);
|
|
2114
|
-
const b64 = validateB64(protectedHeader, validateCrit(JWSInvalid, JWS_RECOGNIZED, crit, protectedHeader, joseHeader));
|
|
2115
|
-
b64 || rejectUnencoded?.();
|
|
2116
|
-
const { alg } = joseHeader;
|
|
2117
|
-
if (typeof alg != "string" || !alg) throw new JWSInvalid("JWS \"alg\" (Algorithm) Header Parameter missing or invalid");
|
|
2118
|
-
const entry = jwsAlgorithm(alg);
|
|
2119
|
-
let payloadS = "", payloadB = payload, data;
|
|
2120
|
-
if (b64) {
|
|
2121
|
-
const encoded = input[4];
|
|
2122
|
-
encoded ? (payloadS = encoded[0] ??= encode(payload), payloadB = encoded[1] ??= encode$1(payloadS)) : (payloadS = encode(payload), data = encoder.encode(`${protectedHeaderString}.${payloadS}`));
|
|
2123
|
-
}
|
|
2124
|
-
data ??= concat(encode$1(protectedHeaderString), encode$1("."), payloadB);
|
|
2125
|
-
const k = await rawKey(await prepareKey(entry, key, "sign"), entry.subtle, "sign");
|
|
2126
|
-
entry.minRsaBits && checkModulusLength(entry.alg, k);
|
|
2127
|
-
const jws = {
|
|
2128
|
-
signature: encode(new Uint8Array(await crypto.subtle.sign(entry.signing, k, data))),
|
|
2129
|
-
payload: payloadS
|
|
2130
|
-
};
|
|
2131
|
-
return protectedHeader && (jws.protected = protectedHeaderString), unprotectedHeader && (jws.header = unprotectedHeader), [jws, b64];
|
|
2132
|
-
}
|
|
2133
|
-
async function createCompactSignature(payload, protectedHeader, crit, key, rejectUnencoded) {
|
|
2134
|
-
const [jws] = await createSignature([
|
|
2135
|
-
payload,
|
|
2136
|
-
protectedHeader,
|
|
2137
|
-
void 0,
|
|
2138
|
-
crit
|
|
2139
|
-
], key, rejectUnencoded);
|
|
2140
|
-
return `${jws.protected}.${jws.payload}.${jws.signature}`;
|
|
2141
|
-
}
|
|
2142
|
-
//#endregion
|
|
2143
|
-
//#region ../../node_modules/jose/dist/webapi/jwt/sign.js
|
|
2144
|
-
var SignJWT_base = JWTClaimsBuilder;
|
|
2145
|
-
var SignJWT = class extends SignJWT_base {
|
|
2146
|
-
#protectedHeader;
|
|
2147
|
-
setProtectedHeader(protectedHeader) {
|
|
2148
|
-
return assertNotSet(this.#protectedHeader, "setProtectedHeader"), this.#protectedHeader = protectedHeader, this;
|
|
2149
|
-
}
|
|
2150
|
-
async sign(key, options) {
|
|
2151
|
-
return createCompactSignature(jwtData(this), this.#protectedHeader, options?.crit, key, () => {
|
|
2152
|
-
throw new JWTInvalid("JWTs MUST NOT use unencoded payload");
|
|
2153
|
-
});
|
|
2154
|
-
}
|
|
2155
|
-
};
|
|
2156
|
-
//#endregion
|
|
2157
|
-
//#region src/kernel/moleculer/mesh-mtls/mesh-join-token.ts
|
|
2158
|
-
/**
|
|
2159
|
-
* Mesh join tokens — single-use JWS ES256 signed with the hub mesh CA key.
|
|
2160
|
-
*
|
|
2161
|
-
* Payload: `{ v, hubUrl, hubMeshAddress, caFingerprint, nodeId, jti, exp }`. The node id is MANDATORY
|
|
2162
|
-
* (D857): a token that does not name the node it is for would let its holder pick any id, `hub` included.
|
|
2163
|
-
* `exp` ≤ now + 1 h. `jti` is recorded until expiry so a token cannot be reused.
|
|
2164
|
-
*/
|
|
2165
|
-
/** In-memory + optional persist of spent `jti` until `exp`. */
|
|
2166
|
-
var JoinTokenJtiStore = class {
|
|
2167
|
-
spent = /* @__PURE__ */ new Map();
|
|
2168
|
-
/** True when `jti` was already consumed (and not yet expired). */
|
|
2169
|
-
isSpent(jti, nowSec = Math.floor(Date.now() / 1e3)) {
|
|
2170
|
-
this.gc(nowSec);
|
|
2171
|
-
return this.spent.has(jti);
|
|
2172
|
-
}
|
|
2173
|
-
/** Record a jti as used until `exp`. Returns false if already spent. */
|
|
2174
|
-
consume(jti, exp, nowSec = Math.floor(Date.now() / 1e3)) {
|
|
2175
|
-
this.gc(nowSec);
|
|
2176
|
-
if (this.spent.has(jti)) return false;
|
|
2177
|
-
this.spent.set(jti, exp);
|
|
2178
|
-
return true;
|
|
2179
|
-
}
|
|
2180
|
-
/** Test helper. */
|
|
2181
|
-
size() {
|
|
2182
|
-
return this.spent.size;
|
|
2183
|
-
}
|
|
2184
|
-
gc(nowSec) {
|
|
2185
|
-
for (const [jti, exp] of this.spent) if (exp <= nowSec) this.spent.delete(jti);
|
|
2186
|
-
}
|
|
2187
|
-
};
|
|
2188
|
-
var processJtiStore = new JoinTokenJtiStore();
|
|
2189
|
-
function processJoinTokenJtiStore() {
|
|
2190
|
-
return processJtiStore;
|
|
2191
|
-
}
|
|
2192
|
-
async function mintMeshJoinToken(input) {
|
|
2193
|
-
if (!isValidAgentNodeId(input.nodeId)) throw new Error(`a join token needs the node id it is for; "${input.nodeId}" is not one an agent may carry`);
|
|
2194
|
-
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
2195
|
-
const nowSec = Math.floor(now.getTime() / 1e3);
|
|
2196
|
-
const exp = nowSec + Math.min(Math.max(1, input.ttlSec ?? 3600), MESH_JOIN_TOKEN_MAX_TTL_SEC);
|
|
2197
|
-
const jti = input.jti ?? randomBytes(16).toString("base64url");
|
|
2198
|
-
return new SignJWT({
|
|
2199
|
-
v: 1,
|
|
2200
|
-
hubUrl: input.hubUrl,
|
|
2201
|
-
hubMeshAddress: input.hubMeshAddress,
|
|
2202
|
-
caFingerprint: caFingerprintCompact(input.ca.certPem),
|
|
2203
|
-
nodeId: input.nodeId,
|
|
2204
|
-
jti,
|
|
2205
|
-
exp
|
|
2206
|
-
}).setProtectedHeader({
|
|
2207
|
-
alg: "ES256",
|
|
2208
|
-
typ: "JWT"
|
|
2209
|
-
}).setIssuedAt(nowSec).setExpirationTime(exp).setJti(jti).sign(input.ca.privateKey);
|
|
2210
|
-
}
|
|
2211
|
-
async function verifyMeshJoinToken(input) {
|
|
2212
|
-
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
2213
|
-
const nowSec = Math.floor(now.getTime() / 1e3);
|
|
2214
|
-
let payload;
|
|
2215
|
-
try {
|
|
2216
|
-
payload = (await jwtVerify(input.token, input.ca.publicKey, {
|
|
2217
|
-
algorithms: ["ES256"],
|
|
2218
|
-
currentDate: now
|
|
2219
|
-
})).payload;
|
|
2220
|
-
} catch (err) {
|
|
2221
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
2222
|
-
if (/exp/i.test(msg) || /timestamp/i.test(msg)) return {
|
|
2223
|
-
ok: false,
|
|
2224
|
-
reason: "token expired"
|
|
2225
|
-
};
|
|
2226
|
-
return {
|
|
2227
|
-
ok: false,
|
|
2228
|
-
reason: `token signature invalid: ${msg}`
|
|
2229
|
-
};
|
|
2230
|
-
}
|
|
2231
|
-
const claims = parseClaims$1(payload);
|
|
2232
|
-
if (claims === null) return {
|
|
2233
|
-
ok: false,
|
|
2234
|
-
reason: "token claims malformed"
|
|
2235
|
-
};
|
|
2236
|
-
if (claims.exp <= nowSec) return {
|
|
2237
|
-
ok: false,
|
|
2238
|
-
reason: "token expired"
|
|
2239
|
-
};
|
|
2240
|
-
const expectedFp = caFingerprintCompact(input.ca.certPem);
|
|
2241
|
-
if (claims.caFingerprint !== expectedFp) return {
|
|
2242
|
-
ok: false,
|
|
2243
|
-
reason: "token caFingerprint does not match this hub CA"
|
|
2244
|
-
};
|
|
2245
|
-
if (input.expectedCaFingerprint !== void 0 && claims.caFingerprint !== normalizeFp(input.expectedCaFingerprint)) return {
|
|
2246
|
-
ok: false,
|
|
2247
|
-
reason: "token caFingerprint pin mismatch"
|
|
2248
|
-
};
|
|
2249
|
-
const store = input.jtiStore ?? processJtiStore;
|
|
2250
|
-
if (input.consume !== false) {
|
|
2251
|
-
if (!store.consume(claims.jti, claims.exp, nowSec)) return {
|
|
2252
|
-
ok: false,
|
|
2253
|
-
reason: "token already used"
|
|
2254
|
-
};
|
|
2255
|
-
} else if (store.isSpent(claims.jti, nowSec)) return {
|
|
2256
|
-
ok: false,
|
|
2257
|
-
reason: "token already used"
|
|
2258
|
-
};
|
|
2259
|
-
return {
|
|
2260
|
-
ok: true,
|
|
2261
|
-
claims
|
|
2262
|
-
};
|
|
2263
|
-
}
|
|
2264
|
-
function normalizeFp(fp) {
|
|
2265
|
-
return fp.replace(/:/g, "").toLowerCase();
|
|
2266
|
-
}
|
|
2267
|
-
function parseClaims$1(payload) {
|
|
2268
|
-
if (payload["v"] !== 1) return null;
|
|
2269
|
-
const hubUrl = payload["hubUrl"];
|
|
2270
|
-
const hubMeshAddress = payload["hubMeshAddress"];
|
|
2271
|
-
const caFingerprint = payload["caFingerprint"];
|
|
2272
|
-
const jti = typeof payload.jti === "string" ? payload.jti : payload["jti"];
|
|
2273
|
-
const exp = typeof payload.exp === "number" ? payload.exp : null;
|
|
2274
|
-
if (typeof hubUrl !== "string" || hubUrl.length === 0) return null;
|
|
2275
|
-
if (typeof hubMeshAddress !== "string" || hubMeshAddress.length === 0) return null;
|
|
2276
|
-
if (typeof caFingerprint !== "string" || caFingerprint.length === 0) return null;
|
|
2277
|
-
if (typeof jti !== "string" || jti.length === 0) return null;
|
|
2278
|
-
if (exp === null) return null;
|
|
2279
|
-
const nodeId = payload["nodeId"];
|
|
2280
|
-
if (typeof nodeId !== "string" || !isValidAgentNodeId(nodeId)) return null;
|
|
2281
|
-
return {
|
|
2282
|
-
v: 1,
|
|
2283
|
-
hubUrl,
|
|
2284
|
-
hubMeshAddress,
|
|
2285
|
-
caFingerprint: normalizeFp(caFingerprint),
|
|
2286
|
-
nodeId,
|
|
2287
|
-
jti,
|
|
2288
|
-
exp
|
|
2289
|
-
};
|
|
2290
|
-
}
|
|
2291
|
-
//#endregion
|
|
2292
|
-
//#region src/kernel/moleculer/mesh-mtls/mesh-enroll.ts
|
|
2293
|
-
/**
|
|
2294
|
-
* `POST /api/mesh/enroll` — verify join token, issue a 30-day leaf from CSR.
|
|
2295
|
-
*/
|
|
2296
|
-
async function enrollMeshNode(body, deps) {
|
|
2297
|
-
if (typeof body.token !== "string" || body.token.length === 0) return {
|
|
2298
|
-
ok: false,
|
|
2299
|
-
error: "token is required",
|
|
2300
|
-
status: 400
|
|
2301
|
-
};
|
|
2302
|
-
if (typeof body.csr !== "string" || !body.csr.includes("BEGIN CERTIFICATE REQUEST")) return {
|
|
2303
|
-
ok: false,
|
|
2304
|
-
error: "csr PEM is required",
|
|
2305
|
-
status: 400
|
|
2306
|
-
};
|
|
2307
|
-
const verified = await verifyMeshJoinToken({
|
|
2308
|
-
token: body.token,
|
|
2309
|
-
ca: deps.ca,
|
|
2310
|
-
jtiStore: deps.jtiStore ?? processJoinTokenJtiStore(),
|
|
2311
|
-
now: deps.now,
|
|
2312
|
-
consume: true
|
|
2313
|
-
});
|
|
2314
|
-
if (!verified.ok) {
|
|
2315
|
-
const status = verified.reason.includes("expired") ? 401 : verified.reason.includes("already used") ? 409 : 401;
|
|
2316
|
-
return {
|
|
2317
|
-
ok: false,
|
|
2318
|
-
error: verified.reason,
|
|
2319
|
-
status
|
|
2320
|
-
};
|
|
2321
|
-
}
|
|
2322
|
-
let leaf;
|
|
2323
|
-
try {
|
|
2324
|
-
leaf = await issueMeshLeafFromCsr(deps.ca, body.csr, {
|
|
2325
|
-
expectedNodeId: verified.claims.nodeId,
|
|
2326
|
-
now: deps.now
|
|
2327
|
-
});
|
|
2328
|
-
} catch (err) {
|
|
2329
|
-
return {
|
|
2330
|
-
ok: false,
|
|
2331
|
-
error: err instanceof Error ? err.message : String(err),
|
|
2332
|
-
status: 400
|
|
2333
|
-
};
|
|
2334
|
-
}
|
|
2335
|
-
try {
|
|
2336
|
-
await deps.onIssued?.(leaf.commonName, leaf.certPem);
|
|
2337
|
-
} catch (err) {
|
|
2338
|
-
deps.onRecordFailed?.(leaf.commonName, err);
|
|
2339
|
-
}
|
|
2340
|
-
return {
|
|
2341
|
-
ok: true,
|
|
2342
|
-
cert: leaf.certPem,
|
|
2343
|
-
caCert: deps.ca.certPem,
|
|
2344
|
-
nodeId: leaf.commonName,
|
|
2345
|
-
notAfter: leaf.notAfter.toISOString(),
|
|
2346
|
-
serialNumber: leaf.serialNumber
|
|
2347
|
-
};
|
|
2348
|
-
}
|
|
2349
|
-
//#endregion
|
|
2350
1374
|
//#region src/kernel/moleculer/mesh-mtls/mesh-tls-enabler.ts
|
|
2351
1375
|
var SLOT = Symbol.for("camstack.mesh.tls-enabler");
|
|
2352
1376
|
function setProcessMeshTlsEnabler(enabler) {
|
|
@@ -22333,7 +21357,7 @@ var require_kleur = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
22333
21357
|
//#region ../../node_modules/moleculer/src/utils.js
|
|
22334
21358
|
var require_utils$3 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
22335
21359
|
var kleur = require_kleur();
|
|
22336
|
-
var os$
|
|
21360
|
+
var os$17 = __require("os");
|
|
22337
21361
|
var path$39 = __require("path");
|
|
22338
21362
|
var fs$18 = __require("fs");
|
|
22339
21363
|
var { TimeoutError } = require_errors$2();
|
|
@@ -22432,7 +21456,7 @@ var require_utils$3 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
22432
21456
|
* @returns
|
|
22433
21457
|
*/
|
|
22434
21458
|
getNodeID() {
|
|
22435
|
-
return os$
|
|
21459
|
+
return os$17.hostname().toLowerCase() + "-" + process.pid;
|
|
22436
21460
|
},
|
|
22437
21461
|
/**
|
|
22438
21462
|
* Get list of local IPs
|
|
@@ -22442,7 +21466,7 @@ var require_utils$3 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
22442
21466
|
getIpList() {
|
|
22443
21467
|
const list = [];
|
|
22444
21468
|
const ilist = [];
|
|
22445
|
-
const interfaces = os$
|
|
21469
|
+
const interfaces = os$17.networkInterfaces();
|
|
22446
21470
|
for (let iface in interfaces) for (let i in interfaces[iface]) {
|
|
22447
21471
|
const f = interfaces[iface]?.[i];
|
|
22448
21472
|
if (f.family === "IPv4") if (f.internal) {
|
|
@@ -24128,7 +23152,7 @@ var require_event$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
24128
23152
|
var require_datadog$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
24129
23153
|
var BaseReporter = require_base$8();
|
|
24130
23154
|
var _ = require_lodash();
|
|
24131
|
-
var os$
|
|
23155
|
+
var os$16 = __require("os");
|
|
24132
23156
|
var { MoleculerError } = require_errors$2();
|
|
24133
23157
|
var METRIC = require_constants$6();
|
|
24134
23158
|
var { isFunction } = require_utils$3();
|
|
@@ -24161,7 +23185,7 @@ var require_datadog$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
24161
23185
|
super(opts);
|
|
24162
23186
|
/** @type {DatadogReporterOptions} */
|
|
24163
23187
|
this.opts = _.defaultsDeep(this.opts, {
|
|
24164
|
-
host: os$
|
|
23188
|
+
host: os$16.hostname(),
|
|
24165
23189
|
baseUrl: BASE_URL,
|
|
24166
23190
|
apiVersion: "v1",
|
|
24167
23191
|
path: "/series",
|
|
@@ -24837,18 +23861,18 @@ var require_cpu_usage$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
24837
23861
|
*
|
|
24838
23862
|
* Based on: https://github.com/icebob/cpu
|
|
24839
23863
|
*/
|
|
24840
|
-
var os$
|
|
23864
|
+
var os$15 = __require("os");
|
|
24841
23865
|
/* istanbul ignore next */
|
|
24842
23866
|
module.exports = function getCpuUsage(sampleTime = 100) {
|
|
24843
23867
|
return new Promise((resolve, reject) => {
|
|
24844
23868
|
try {
|
|
24845
|
-
const first = os$
|
|
23869
|
+
const first = os$15.cpus().map((cpu) => cpu.times);
|
|
24846
23870
|
setTimeout(() => {
|
|
24847
23871
|
try {
|
|
24848
|
-
const second = os$
|
|
23872
|
+
const second = os$15.cpus().map((cpu) => cpu.times);
|
|
24849
23873
|
setTimeout(() => {
|
|
24850
23874
|
try {
|
|
24851
|
-
const third = os$
|
|
23875
|
+
const third = os$15.cpus().map((cpu) => cpu.times);
|
|
24852
23876
|
const usages = [];
|
|
24853
23877
|
for (let i = 0; i < first.length; i++) {
|
|
24854
23878
|
const first_idle = first[i].idle;
|
|
@@ -24881,7 +23905,7 @@ var require_cpu_usage$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
24881
23905
|
//#endregion
|
|
24882
23906
|
//#region ../../node_modules/moleculer/src/metrics/commons.js
|
|
24883
23907
|
var require_commons = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
24884
|
-
var os$
|
|
23908
|
+
var os$14 = __require("os");
|
|
24885
23909
|
var METRIC = require_constants$6();
|
|
24886
23910
|
var cpuUsage = require_cpu_usage$1();
|
|
24887
23911
|
var v8;
|
|
@@ -25060,27 +24084,27 @@ var require_commons = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
25060
24084
|
name: METRIC.OS_TYPE,
|
|
25061
24085
|
type: METRIC.TYPE_INFO,
|
|
25062
24086
|
description: "OS type"
|
|
25063
|
-
}).set(os$
|
|
24087
|
+
}).set(os$14.type());
|
|
25064
24088
|
this.register({
|
|
25065
24089
|
name: METRIC.OS_RELEASE,
|
|
25066
24090
|
type: METRIC.TYPE_INFO,
|
|
25067
24091
|
description: "OS release"
|
|
25068
|
-
}).set(os$
|
|
24092
|
+
}).set(os$14.release());
|
|
25069
24093
|
this.register({
|
|
25070
24094
|
name: METRIC.OS_HOSTNAME,
|
|
25071
24095
|
type: METRIC.TYPE_INFO,
|
|
25072
24096
|
description: "Hostname"
|
|
25073
|
-
}).set(os$
|
|
24097
|
+
}).set(os$14.hostname());
|
|
25074
24098
|
this.register({
|
|
25075
24099
|
name: METRIC.OS_ARCH,
|
|
25076
24100
|
type: METRIC.TYPE_INFO,
|
|
25077
24101
|
description: "OS architecture"
|
|
25078
|
-
}).set(os$
|
|
24102
|
+
}).set(os$14.arch());
|
|
25079
24103
|
this.register({
|
|
25080
24104
|
name: METRIC.OS_PLATFORM,
|
|
25081
24105
|
type: METRIC.TYPE_INFO,
|
|
25082
24106
|
description: "OS platform"
|
|
25083
|
-
}).set(os$
|
|
24107
|
+
}).set(os$14.platform());
|
|
25084
24108
|
const userInfo = getUserInfo();
|
|
25085
24109
|
this.register({
|
|
25086
24110
|
name: METRIC.OS_USER_UID,
|
|
@@ -25231,22 +24255,22 @@ var require_commons = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
25231
24255
|
}
|
|
25232
24256
|
this.set(METRIC.PROCESS_UPTIME, process.uptime());
|
|
25233
24257
|
this.set(METRIC.PROCESS_INTERNAL_ACTIVE_HANDLES, process.getActiveResourcesInfo().length);
|
|
25234
|
-
const freeMem = os$
|
|
25235
|
-
const totalMem = os$
|
|
24258
|
+
const freeMem = os$14.freemem();
|
|
24259
|
+
const totalMem = os$14.totalmem();
|
|
25236
24260
|
const usedMem = totalMem - freeMem;
|
|
25237
24261
|
this.set(METRIC.OS_MEMORY_FREE, freeMem);
|
|
25238
24262
|
this.set(METRIC.OS_MEMORY_USED, usedMem);
|
|
25239
24263
|
this.set(METRIC.OS_MEMORY_TOTAL, totalMem);
|
|
25240
|
-
this.set(METRIC.OS_UPTIME, os$
|
|
25241
|
-
this.set(METRIC.OS_TYPE, os$
|
|
25242
|
-
this.set(METRIC.OS_RELEASE, os$
|
|
25243
|
-
this.set(METRIC.OS_HOSTNAME, os$
|
|
25244
|
-
this.set(METRIC.OS_ARCH, os$
|
|
25245
|
-
this.set(METRIC.OS_PLATFORM, os$
|
|
24264
|
+
this.set(METRIC.OS_UPTIME, os$14.uptime());
|
|
24265
|
+
this.set(METRIC.OS_TYPE, os$14.type());
|
|
24266
|
+
this.set(METRIC.OS_RELEASE, os$14.release());
|
|
24267
|
+
this.set(METRIC.OS_HOSTNAME, os$14.hostname());
|
|
24268
|
+
this.set(METRIC.OS_ARCH, os$14.arch());
|
|
24269
|
+
this.set(METRIC.OS_PLATFORM, os$14.platform());
|
|
25246
24270
|
const getNetworkInterfaces = () => {
|
|
25247
24271
|
const list = [];
|
|
25248
24272
|
const ilist = [];
|
|
25249
|
-
const interfaces = os$
|
|
24273
|
+
const interfaces = os$14.networkInterfaces();
|
|
25250
24274
|
for (let iface in interfaces) for (let i in interfaces[iface]) {
|
|
25251
24275
|
const f = interfaces[iface][i];
|
|
25252
24276
|
if (f.internal) ilist.push({
|
|
@@ -25276,7 +24300,7 @@ var require_commons = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
25276
24300
|
this.set(METRIC.OS_DATETIME_ISO, d.toISOString());
|
|
25277
24301
|
this.set(METRIC.OS_DATETIME_UTC, d.toUTCString());
|
|
25278
24302
|
this.set(METRIC.OS_DATETIME_TZ_OFFSET, d.getTimezoneOffset());
|
|
25279
|
-
const load = os$
|
|
24303
|
+
const load = os$14.loadavg();
|
|
25280
24304
|
this.set(METRIC.OS_CPU_LOAD_1, load[0]);
|
|
25281
24305
|
this.set(METRIC.OS_CPU_LOAD_5, load[1]);
|
|
25282
24306
|
this.set(METRIC.OS_CPU_LOAD_15, load[2]);
|
|
@@ -25284,7 +24308,7 @@ var require_commons = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
25284
24308
|
return this.broker.Promise.resolve().then(() => cpuUsage().then((res) => {
|
|
25285
24309
|
this.set(METRIC.OS_CPU_UTILIZATION, res.avg);
|
|
25286
24310
|
try {
|
|
25287
|
-
const cpus = os$
|
|
24311
|
+
const cpus = os$14.cpus();
|
|
25288
24312
|
this.set(METRIC.OS_CPU_TOTAL, cpus.length);
|
|
25289
24313
|
this.set(METRIC.OS_CPU_USER, cpus.reduce((a, b) => a + b.times.user, 0));
|
|
25290
24314
|
this.set(METRIC.OS_CPU_SYSTEM, cpus.reduce((a, b) => a + b.times.sys, 0));
|
|
@@ -25306,7 +24330,7 @@ var require_commons = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
25306
24330
|
*/
|
|
25307
24331
|
function getUserInfo() {
|
|
25308
24332
|
try {
|
|
25309
|
-
return os$
|
|
24333
|
+
return os$14.userInfo();
|
|
25310
24334
|
} catch {
|
|
25311
24335
|
/* istanbul ignore next */
|
|
25312
24336
|
return {};
|
|
@@ -27742,7 +26766,7 @@ var require_index_min = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
|
27742
26766
|
var require_shard = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
27743
26767
|
var _ = require_lodash();
|
|
27744
26768
|
var BaseStrategy = require_base$7();
|
|
27745
|
-
var crypto$
|
|
26769
|
+
var crypto$3 = __require("crypto");
|
|
27746
26770
|
var { LRUCache } = require_index_min();
|
|
27747
26771
|
var { isFunction, randomInt } = require_utils$3();
|
|
27748
26772
|
/**
|
|
@@ -27848,7 +26872,7 @@ var require_shard = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
27848
26872
|
* @memberof ShardStrategy
|
|
27849
26873
|
*/
|
|
27850
26874
|
getHash(key) {
|
|
27851
|
-
const hash = crypto$
|
|
26875
|
+
const hash = crypto$3.createHash("md5").update(key).digest("hex");
|
|
27852
26876
|
const hashNum = parseInt(hash.substring(0, 8), 16);
|
|
27853
26877
|
return this.opts.ringSize ? hashNum % this.opts.ringSize : hashNum;
|
|
27854
26878
|
}
|
|
@@ -35528,7 +34552,7 @@ var require_node = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
35528
34552
|
//#region ../../node_modules/moleculer/src/registry/node-catalog.js
|
|
35529
34553
|
var require_node_catalog = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
35530
34554
|
var _ = require_lodash();
|
|
35531
|
-
var os$
|
|
34555
|
+
var os$13 = __require("os");
|
|
35532
34556
|
var Node = require_node();
|
|
35533
34557
|
var { getIpList } = require_utils$3();
|
|
35534
34558
|
/**
|
|
@@ -35574,7 +34598,7 @@ var require_node_catalog = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
35574
34598
|
node.local = true;
|
|
35575
34599
|
node.ipList = getIpList();
|
|
35576
34600
|
node.instanceID = this.broker.instanceID;
|
|
35577
|
-
node.hostname = os$
|
|
34601
|
+
node.hostname = os$13.hostname();
|
|
35578
34602
|
node.client = {
|
|
35579
34603
|
type: "nodejs",
|
|
35580
34604
|
version: this.broker.MOLECULER_VERSION,
|
|
@@ -37648,7 +36672,7 @@ var require_console$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
37648
36672
|
var require_datadog$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
37649
36673
|
var BaseLogger = require_base$4();
|
|
37650
36674
|
var _ = require_lodash();
|
|
37651
|
-
var os$
|
|
36675
|
+
var os$12 = __require("os");
|
|
37652
36676
|
var { MoleculerError } = require_errors$2();
|
|
37653
36677
|
var util$5 = __require("util");
|
|
37654
36678
|
var { isObject } = require_utils$3();
|
|
@@ -37681,7 +36705,7 @@ var require_datadog$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
37681
36705
|
apiKey: process.env.DATADOG_API_KEY,
|
|
37682
36706
|
ddSource: "moleculer",
|
|
37683
36707
|
env: void 0,
|
|
37684
|
-
hostname: os$
|
|
36708
|
+
hostname: os$12.hostname(),
|
|
37685
36709
|
objectPrinter: null,
|
|
37686
36710
|
interval: 10 * 1e3
|
|
37687
36711
|
});
|
|
@@ -37877,7 +36901,7 @@ var require_file$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
37877
36901
|
var _ = require_lodash();
|
|
37878
36902
|
var fs$14 = __require("fs/promises");
|
|
37879
36903
|
var path$36 = __require("path");
|
|
37880
|
-
var os$
|
|
36904
|
+
var os$11 = __require("os");
|
|
37881
36905
|
var { makeDirs } = require_utils$3();
|
|
37882
36906
|
/**
|
|
37883
36907
|
* Import types
|
|
@@ -37906,7 +36930,7 @@ var require_file$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
37906
36930
|
this.opts = _.defaultsDeep(this.opts, {
|
|
37907
36931
|
folder: "./logs",
|
|
37908
36932
|
filename: "moleculer-{date}.log",
|
|
37909
|
-
eol: os$
|
|
36933
|
+
eol: os$11.EOL,
|
|
37910
36934
|
interval: 1 * 1e3
|
|
37911
36935
|
});
|
|
37912
36936
|
this.opts.colors = false;
|
|
@@ -38326,7 +37350,7 @@ var require_lib$5 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
38326
37350
|
//#region ../../node_modules/log4js/lib/layouts.js
|
|
38327
37351
|
var require_layouts = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
38328
37352
|
var dateFormat = require_lib$5();
|
|
38329
|
-
var os$
|
|
37353
|
+
var os$10 = __require("os");
|
|
38330
37354
|
var util$3 = __require("util");
|
|
38331
37355
|
var path$35 = __require("path");
|
|
38332
37356
|
var styles = {
|
|
@@ -38452,13 +37476,13 @@ var require_layouts = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
38452
37476
|
return dateFormat.asString(format, loggingEvent.startTime);
|
|
38453
37477
|
}
|
|
38454
37478
|
function hostname() {
|
|
38455
|
-
return os$
|
|
37479
|
+
return os$10.hostname().toString();
|
|
38456
37480
|
}
|
|
38457
37481
|
function formatMessage(loggingEvent) {
|
|
38458
37482
|
return util$3.format(...loggingEvent.data);
|
|
38459
37483
|
}
|
|
38460
37484
|
function endOfLine() {
|
|
38461
|
-
return os$
|
|
37485
|
+
return os$10.EOL;
|
|
38462
37486
|
}
|
|
38463
37487
|
function logLevel(loggingEvent) {
|
|
38464
37488
|
return loggingEvent.level.toString();
|
|
@@ -40057,11 +39081,11 @@ var require_mkdirs = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
40057
39081
|
//#region ../../node_modules/streamroller/node_modules/fs-extra/lib/util/utimes.js
|
|
40058
39082
|
var require_utimes = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
40059
39083
|
var fs = require_graceful_fs();
|
|
40060
|
-
var os$
|
|
39084
|
+
var os$9 = __require("os");
|
|
40061
39085
|
var path$31 = __require("path");
|
|
40062
39086
|
function hasMillisResSync() {
|
|
40063
39087
|
let tmpfile = path$31.join("millis-test-sync" + Date.now().toString() + Math.random().toString().slice(2));
|
|
40064
|
-
tmpfile = path$31.join(os$
|
|
39088
|
+
tmpfile = path$31.join(os$9.tmpdir(), tmpfile);
|
|
40065
39089
|
const d = /* @__PURE__ */ new Date(1435410243862);
|
|
40066
39090
|
fs.writeFileSync(tmpfile, "https://github.com/jprichardson/node-fs-extra/pull/141");
|
|
40067
39091
|
const fd = fs.openSync(tmpfile, "r+");
|
|
@@ -40071,7 +39095,7 @@ var require_utimes = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
40071
39095
|
}
|
|
40072
39096
|
function hasMillisRes(callback) {
|
|
40073
39097
|
let tmpfile = path$31.join("millis-test" + Date.now().toString() + Math.random().toString().slice(2));
|
|
40074
|
-
tmpfile = path$31.join(os$
|
|
39098
|
+
tmpfile = path$31.join(os$9.tmpdir(), tmpfile);
|
|
40075
39099
|
const d = /* @__PURE__ */ new Date(1435410243862);
|
|
40076
39100
|
fs.writeFile(tmpfile, "https://github.com/jprichardson/node-fs-extra/pull/141", (err) => {
|
|
40077
39101
|
if (err) return callback(err);
|
|
@@ -46373,7 +45397,7 @@ var require_multistream = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
46373
45397
|
//#endregion
|
|
46374
45398
|
//#region ../../node_modules/pino/pino.js
|
|
46375
45399
|
var require_pino$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
46376
|
-
var os$
|
|
45400
|
+
var os$8 = __require("node:os");
|
|
46377
45401
|
var stdSerializers = require_pino_std_serializers();
|
|
46378
45402
|
var caller = require_caller();
|
|
46379
45403
|
var redaction = require_redaction();
|
|
@@ -46388,7 +45412,7 @@ var require_pino$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
46388
45412
|
var { chindingsSym, redactFmtSym, serializersSym, timeSym, timeSliceIndexSym, streamSym, stringifySym, stringifySafeSym, stringifiersSym, setLevelSym, endSym, formatOptsSym, messageKeySym, errorKeySym, nestedKeySym, mixinSym, levelCompSym, useOnlyCustomLevelsSym, formattersSym, hooksSym, nestedKeyStrSym, mixinMergeStrategySym, msgPrefixSym } = symbols;
|
|
46389
45413
|
var { epochTime, nullTime } = time;
|
|
46390
45414
|
var { pid } = process;
|
|
46391
|
-
var hostname = os$
|
|
45415
|
+
var hostname = os$8.hostname();
|
|
46392
45416
|
var defaultErrorSerializer = stdSerializers.err;
|
|
46393
45417
|
var normalize = createArgsNormalizer({
|
|
46394
45418
|
level: "info",
|
|
@@ -49106,7 +48130,7 @@ var require_validators$1 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
49106
48130
|
//#region ../../node_modules/moleculer/src/cachers/base.js
|
|
49107
48131
|
var require_base$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
49108
48132
|
var _ = require_lodash();
|
|
49109
|
-
var crypto$
|
|
48133
|
+
var crypto$2 = __require("crypto");
|
|
49110
48134
|
var { METRIC } = require_metrics$1();
|
|
49111
48135
|
var { isObject, isFunction, isDate } = require_utils$3();
|
|
49112
48136
|
/**
|
|
@@ -49370,7 +48394,7 @@ var require_base$2 = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
49370
48394
|
const maxParamsLength = this.opts.maxParamsLength;
|
|
49371
48395
|
if (!maxParamsLength || maxParamsLength < 44 || key.length <= maxParamsLength) return key;
|
|
49372
48396
|
const prefixLength = maxParamsLength - 44;
|
|
49373
|
-
const base64Hash = crypto$
|
|
48397
|
+
const base64Hash = crypto$2.createHash("sha256").update(key).digest("base64");
|
|
49374
48398
|
if (prefixLength < 1) return base64Hash;
|
|
49375
48399
|
return key.substring(0, prefixLength) + base64Hash;
|
|
49376
48400
|
}
|
|
@@ -72493,7 +71517,7 @@ var require_ipaddr = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
72493
71517
|
//#region ../../node_modules/moleculer/src/transporters/tcp/udp-broadcaster.js
|
|
72494
71518
|
var require_udp_broadcaster = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
72495
71519
|
var EventEmitter$3 = __require("events");
|
|
72496
|
-
var os$
|
|
71520
|
+
var os$7 = __require("os");
|
|
72497
71521
|
var dgram = __require("dgram");
|
|
72498
71522
|
var ipaddr = require_ipaddr();
|
|
72499
71523
|
var { randomInt } = require_utils$3();
|
|
@@ -72704,7 +71728,7 @@ var require_udp_broadcaster = /* @__PURE__ */ __commonJSMin(((exports, module) =
|
|
|
72704
71728
|
*/
|
|
72705
71729
|
getBroadcastAddresses() {
|
|
72706
71730
|
const list = [];
|
|
72707
|
-
const interfaces = os$
|
|
71731
|
+
const interfaces = os$7.networkInterfaces();
|
|
72708
71732
|
for (let iface in interfaces) for (let i in interfaces[iface]) {
|
|
72709
71733
|
const f = interfaces[iface][i];
|
|
72710
71734
|
if (f.family === "IPv4") list.push(ipaddr.IPv4.broadcastAddressFromCIDR(f.cidr).toString());
|
|
@@ -72719,7 +71743,7 @@ var require_udp_broadcaster = /* @__PURE__ */ __commonJSMin(((exports, module) =
|
|
|
72719
71743
|
*/
|
|
72720
71744
|
getInterfaceAddresses() {
|
|
72721
71745
|
const list = [];
|
|
72722
|
-
const interfaces = os$
|
|
71746
|
+
const interfaces = os$7.networkInterfaces();
|
|
72723
71747
|
for (let iface in interfaces) for (let i in interfaces[iface]) {
|
|
72724
71748
|
const f = interfaces[iface][i];
|
|
72725
71749
|
if (f.family === "IPv4") list.push(f.address);
|
|
@@ -74002,7 +73026,7 @@ var init_package = __esmMin((() => {
|
|
|
74002
73026
|
//#endregion
|
|
74003
73027
|
//#region ../../node_modules/moleculer/src/health.js
|
|
74004
73028
|
var require_health = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
74005
|
-
var os$
|
|
73029
|
+
var os$6 = __require("os");
|
|
74006
73030
|
var { getIpList } = require_utils$3();
|
|
74007
73031
|
var MOLECULER_VERSION = (init_package(), __toCommonJS(package_exports).default).version;
|
|
74008
73032
|
/**
|
|
@@ -74018,9 +73042,9 @@ var require_health = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
74018
73042
|
};
|
|
74019
73043
|
};
|
|
74020
73044
|
var getCpuInfo = () => {
|
|
74021
|
-
const cpus = os$
|
|
74022
|
-
const load = os$
|
|
74023
|
-
const cores = Array.isArray(cpus) ? os$
|
|
73045
|
+
const cpus = os$6.cpus();
|
|
73046
|
+
const load = os$6.loadavg();
|
|
73047
|
+
const cores = Array.isArray(cpus) ? os$6.cpus().length : null;
|
|
74024
73048
|
return {
|
|
74025
73049
|
load1: load[0],
|
|
74026
73050
|
load5: load[1],
|
|
@@ -74031,8 +73055,8 @@ var require_health = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
74031
73055
|
};
|
|
74032
73056
|
var getMemoryInfo = () => {
|
|
74033
73057
|
const mem = {
|
|
74034
|
-
free: os$
|
|
74035
|
-
total: os$
|
|
73058
|
+
free: os$6.freemem(),
|
|
73059
|
+
total: os$6.totalmem(),
|
|
74036
73060
|
percent: null
|
|
74037
73061
|
};
|
|
74038
73062
|
mem.percent = mem.free * 100 / mem.total;
|
|
@@ -74044,19 +73068,19 @@ var require_health = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
74044
73068
|
*/
|
|
74045
73069
|
var getUserInfo = () => {
|
|
74046
73070
|
try {
|
|
74047
|
-
return os$
|
|
73071
|
+
return os$6.userInfo();
|
|
74048
73072
|
} catch {
|
|
74049
73073
|
return {};
|
|
74050
73074
|
}
|
|
74051
73075
|
};
|
|
74052
73076
|
var getOsInfo = () => {
|
|
74053
73077
|
return {
|
|
74054
|
-
uptime: os$
|
|
74055
|
-
type: os$
|
|
74056
|
-
release: os$
|
|
74057
|
-
hostname: os$
|
|
74058
|
-
arch: os$
|
|
74059
|
-
platform: os$
|
|
73078
|
+
uptime: os$6.uptime(),
|
|
73079
|
+
type: os$6.type(),
|
|
73080
|
+
release: os$6.release(),
|
|
73081
|
+
hostname: os$6.hostname(),
|
|
73082
|
+
arch: os$6.arch(),
|
|
73083
|
+
platform: os$6.platform(),
|
|
74060
73084
|
user: getUserInfo()
|
|
74061
73085
|
};
|
|
74062
73086
|
};
|
|
@@ -75749,11 +74773,11 @@ var require_ttl = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
75749
74773
|
//#endregion
|
|
75750
74774
|
//#region ../../node_modules/recursive-watch/index.js
|
|
75751
74775
|
var require_recursive_watch = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
75752
|
-
var os$
|
|
74776
|
+
var os$5 = __require("os");
|
|
75753
74777
|
var fs$7 = __require("fs");
|
|
75754
74778
|
var path$10 = __require("path");
|
|
75755
74779
|
var Cache = require_ttl();
|
|
75756
|
-
var watchDirectory = os$
|
|
74780
|
+
var watchDirectory = os$5.platform() === "linux" ? watchFallback : watchRecursive;
|
|
75757
74781
|
module.exports = watch;
|
|
75758
74782
|
function watch(name, onchange) {
|
|
75759
74783
|
var clear = null;
|
|
@@ -76118,7 +75142,7 @@ var require_hot_reload = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
76118
75142
|
//#endregion
|
|
76119
75143
|
//#region ../../node_modules/moleculer/src/middlewares/transmit/encryption.js
|
|
76120
75144
|
var require_encryption = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
76121
|
-
var crypto$
|
|
75145
|
+
var crypto$1 = __require("crypto");
|
|
76122
75146
|
/**
|
|
76123
75147
|
* This is a AES encryption middleware to protect the whole
|
|
76124
75148
|
* Moleculer transporter communication with AES.
|
|
@@ -76141,14 +75165,14 @@ var require_encryption = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
76141
75165
|
},
|
|
76142
75166
|
transporterSend(next) {
|
|
76143
75167
|
return (topic, data, meta) => {
|
|
76144
|
-
const encrypter = iv ? crypto$
|
|
75168
|
+
const encrypter = iv ? crypto$1.createCipheriv(algorithm, password, iv) : crypto$1.createCipher(algorithm, password);
|
|
76145
75169
|
return next(topic, Buffer.concat([encrypter.update(data), encrypter.final()]), meta);
|
|
76146
75170
|
};
|
|
76147
75171
|
},
|
|
76148
75172
|
transporterReceive(next) {
|
|
76149
75173
|
return (cmd, data, s) => {
|
|
76150
75174
|
try {
|
|
76151
|
-
const decrypter = iv ? crypto$
|
|
75175
|
+
const decrypter = iv ? crypto$1.createDecipheriv(algorithm, password, iv) : crypto$1.createDecipher(algorithm, password);
|
|
76152
75176
|
return next(cmd, Buffer.concat([decrypter.update(data), decrypter.final()]), s);
|
|
76153
75177
|
} catch (err) {
|
|
76154
75178
|
logger.error("Received packet decryption error.", err);
|
|
@@ -82729,7 +81753,7 @@ var require_has_flag = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
82729
81753
|
//#endregion
|
|
82730
81754
|
//#region ../../node_modules/args/node_modules/supports-color/index.js
|
|
82731
81755
|
var require_supports_color = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
82732
|
-
var os$
|
|
81756
|
+
var os$4 = __require("os");
|
|
82733
81757
|
var hasFlag = require_has_flag();
|
|
82734
81758
|
var env = process.env;
|
|
82735
81759
|
var forceColor;
|
|
@@ -82752,7 +81776,7 @@ var require_supports_color = /* @__PURE__ */ __commonJSMin(((exports, module) =>
|
|
|
82752
81776
|
if (stream && !stream.isTTY && forceColor !== true) return 0;
|
|
82753
81777
|
const min = forceColor ? 1 : 0;
|
|
82754
81778
|
if (process.platform === "win32") {
|
|
82755
|
-
const osRelease = os$
|
|
81779
|
+
const osRelease = os$4.release().split(".");
|
|
82756
81780
|
if (Number(process.versions.node.split(".")[0]) >= 8 && Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
82757
81781
|
return 1;
|
|
82758
81782
|
}
|
|
@@ -83642,8 +82666,8 @@ var require_lib = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
83642
82666
|
var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
83643
82667
|
var fs$2 = __require("fs");
|
|
83644
82668
|
var path$2 = __require("path");
|
|
83645
|
-
var os$
|
|
83646
|
-
var crypto
|
|
82669
|
+
var os$3 = __require("os");
|
|
82670
|
+
var crypto = __require("crypto");
|
|
83647
82671
|
var TIPS = [
|
|
83648
82672
|
"◈ encrypted .env [www.dotenvx.com]",
|
|
83649
82673
|
"◈ secrets for agents [www.dotenvx.com]",
|
|
@@ -83775,7 +82799,7 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
83775
82799
|
return null;
|
|
83776
82800
|
}
|
|
83777
82801
|
function _resolveHome(envPath) {
|
|
83778
|
-
return envPath[0] === "~" ? path$2.join(os$
|
|
82802
|
+
return envPath[0] === "~" ? path$2.join(os$3.homedir(), envPath.slice(1)) : envPath;
|
|
83779
82803
|
}
|
|
83780
82804
|
function _configVault(options) {
|
|
83781
82805
|
const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
@@ -83848,7 +82872,7 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
83848
82872
|
const authTag = ciphertext.subarray(-16);
|
|
83849
82873
|
ciphertext = ciphertext.subarray(12, -16);
|
|
83850
82874
|
try {
|
|
83851
|
-
const aesgcm = crypto
|
|
82875
|
+
const aesgcm = crypto.createDecipheriv("aes-256-gcm", key, nonce);
|
|
83852
82876
|
aesgcm.setAuthTag(authTag);
|
|
83853
82877
|
return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
|
|
83854
82878
|
} catch (error) {
|
|
@@ -83923,7 +82947,7 @@ var require_runner = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
83923
82947
|
var inspect = __require("util").inspect;
|
|
83924
82948
|
var _ = require_lodash();
|
|
83925
82949
|
var Args = require_lib();
|
|
83926
|
-
var os$
|
|
82950
|
+
var os$2 = __require("os");
|
|
83927
82951
|
/** @type {Cluster} */
|
|
83928
82952
|
var cluster = __require("cluster");
|
|
83929
82953
|
var kleur = require_kleur();
|
|
@@ -84229,7 +83253,7 @@ var require_runner = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
84229
83253
|
logger.info(`Worker #${worker.id} restarted`);
|
|
84230
83254
|
} else process.exit(code);
|
|
84231
83255
|
});
|
|
84232
|
-
const workerCount = Number.isInteger(instances) && instances > 0 ? instances : os$
|
|
83256
|
+
const workerCount = Number.isInteger(instances) && instances > 0 ? instances : os$2.cpus().length;
|
|
84233
83257
|
logger.info(`Starting ${workerCount} workers...`);
|
|
84234
83258
|
for (let i = 0; i < workerCount; i++) cluster.fork();
|
|
84235
83259
|
stopSignals.forEach(function(signal) {
|
|
@@ -84367,7 +83391,7 @@ var Gt = (n, t, e) => {
|
|
|
84367
83391
|
}
|
|
84368
83392
|
return h;
|
|
84369
83393
|
};
|
|
84370
|
-
var fe = "\0SLASH" + Math.random() + "\0", ue = "\0OPEN" + Math.random() + "\0", qt = "\0CLOSE" + Math.random() + "\0", de = "\0COMMA" + Math.random() + "\0", pe = "\0PERIOD" + Math.random() + "\0", is = new RegExp(fe, "g"), rs = new RegExp(ue, "g"), ns = new RegExp(qt, "g"), os = new RegExp(de, "g"), hs = new RegExp(pe, "g"), as = /\\\\/g, ls = /\\{/g, cs = /\\}/g, fs = /\\,/g, us = /\\./g, ds = 1e5;
|
|
83394
|
+
var fe = "\0SLASH" + Math.random() + "\0", ue = "\0OPEN" + Math.random() + "\0", qt = "\0CLOSE" + Math.random() + "\0", de = "\0COMMA" + Math.random() + "\0", pe = "\0PERIOD" + Math.random() + "\0", is = new RegExp(fe, "g"), rs = new RegExp(ue, "g"), ns = new RegExp(qt, "g"), os$1 = new RegExp(de, "g"), hs = new RegExp(pe, "g"), as = /\\\\/g, ls = /\\{/g, cs = /\\}/g, fs = /\\,/g, us = /\\./g, ds = 1e5;
|
|
84371
83395
|
function Ht(n) {
|
|
84372
83396
|
return isNaN(n) ? n.charCodeAt(0) : parseInt(n, 10);
|
|
84373
83397
|
}
|
|
@@ -84375,7 +83399,7 @@ function ps(n) {
|
|
|
84375
83399
|
return n.replace(as, fe).replace(ls, ue).replace(cs, qt).replace(fs, de).replace(us, pe);
|
|
84376
83400
|
}
|
|
84377
83401
|
function ms(n) {
|
|
84378
|
-
return n.replace(is, "\\").replace(rs, "{").replace(ns, "}").replace(os, ",").replace(hs, ".");
|
|
83402
|
+
return n.replace(is, "\\").replace(rs, "{").replace(ns, "}").replace(os$1, ",").replace(hs, ".");
|
|
84379
83403
|
}
|
|
84380
83404
|
function me(n) {
|
|
84381
83405
|
if (!n) return [""];
|
|
@@ -88009,6 +87033,11 @@ var TlsTcpTransporter = class extends TcpTransporterBase {
|
|
|
88009
87033
|
this.logger.warn("Dropping mesh packet — an enrolled agent accepts TLS from the hub only");
|
|
88010
87034
|
return;
|
|
88011
87035
|
}
|
|
87036
|
+
const wireSender = peekSender(this, type, message);
|
|
87037
|
+
if (wireSender === null || wireSender === this.nodeID) {
|
|
87038
|
+
this.logger.warn(wireSender === null ? "Dropping mesh packet - it names no sender" : "Dropping mesh packet - it claims this node as its sender");
|
|
87039
|
+
return;
|
|
87040
|
+
}
|
|
88012
87041
|
if (socket !== void 0 && isTlsSocket(socket)) {
|
|
88013
87042
|
const tlsSock = socket;
|
|
88014
87043
|
const identity = tlsSock.meshPeerCn ? {
|
|
@@ -88024,9 +87053,8 @@ var TlsTcpTransporter = class extends TcpTransporterBase {
|
|
|
88024
87053
|
tlsSock.destroy();
|
|
88025
87054
|
return;
|
|
88026
87055
|
}
|
|
88027
|
-
|
|
88028
|
-
|
|
88029
|
-
this.logger.warn(`Dropping forged mesh packet — sender=${sender} peerCN=${identity.cn}`);
|
|
87056
|
+
if (wireSender !== identity.cn) {
|
|
87057
|
+
this.logger.warn(`Dropping forged mesh packet — sender=${wireSender} peerCN=${identity.cn}`);
|
|
88030
87058
|
return;
|
|
88031
87059
|
}
|
|
88032
87060
|
tlsSock.meshPeerCn = identity.cn;
|
|
@@ -89286,196 +88314,24 @@ var HubPairing = class {
|
|
|
89286
88314
|
};
|
|
89287
88315
|
}
|
|
89288
88316
|
};
|
|
89289
|
-
|
|
89290
|
-
|
|
89291
|
-
|
|
89292
|
-
* Keeps the hub's cluster-secret gate in step with System → Cluster (D797,
|
|
89293
|
-
* D802).
|
|
89294
|
-
*
|
|
89295
|
-
* The field is a `password` of `system-config`: its `system-settings` row
|
|
89296
|
-
* (`cluster.clusterSecret`) holds a keychain marker, the value lives in the
|
|
89297
|
-
* keychain (owner `system`). The gate the mesh join reads:
|
|
89298
|
-
*
|
|
89299
|
-
* - no marker → the secret is MANDATORY (D802): the keeper asks
|
|
89300
|
-
* its owner to generate one (`generateSecret`), and
|
|
89301
|
-
* until that succeeds the gate is `off` — no node can
|
|
89302
|
-
* authenticate (mesh auth is always enforced, D821);
|
|
89303
|
-
* - marker + value → `on` — nodes prove the secret;
|
|
89304
|
-
* - marker, no answer → `unknown` — refused, retryably, and retried here.
|
|
89305
|
-
* A locked keychain or a value lost to a reset NEVER opens the gate, and
|
|
89306
|
-
* never triggers a generation (the operator decides what replaces a value
|
|
89307
|
-
* the keychain lost).
|
|
89308
|
-
*
|
|
89309
|
-
* It also publishes the mesh mode (`cluster.meshAuth`, `mesh-auth-mode.ts`).
|
|
89310
|
-
*/
|
|
89311
|
-
/** The field key inside the `cluster` section. */
|
|
89312
|
-
var CLUSTER_SECRET_FIELD = "clusterSecret";
|
|
89313
|
-
var ClusterSecretKeeper = class {
|
|
89314
|
-
deps;
|
|
89315
|
-
retryTimer = null;
|
|
89316
|
-
unsubscribe = null;
|
|
89317
|
-
stopped = false;
|
|
89318
|
-
last = null;
|
|
89319
|
-
constructor(deps) {
|
|
89320
|
-
this.deps = deps;
|
|
89321
|
-
}
|
|
89322
|
-
async start() {
|
|
89323
|
-
this.unsubscribe = this.deps.secrets?.onChange((ref) => {
|
|
89324
|
-
if (ref === CLUSTER_SECRET_REF) this.reload();
|
|
89325
|
-
}) ?? null;
|
|
89326
|
-
await this.reload();
|
|
89327
|
-
}
|
|
89328
|
-
stop() {
|
|
89329
|
-
this.stopped = true;
|
|
89330
|
-
if (this.retryTimer !== null) clearTimeout(this.retryTimer);
|
|
89331
|
-
this.retryTimer = null;
|
|
89332
|
-
this.unsubscribe?.();
|
|
89333
|
-
this.unsubscribe = null;
|
|
89334
|
-
}
|
|
89335
|
-
/** Re-read the row and the keychain; publish the gate. */
|
|
89336
|
-
async reload() {
|
|
89337
|
-
if (this.stopped) return;
|
|
89338
|
-
let gate = await this.compute();
|
|
89339
|
-
if (gate.kind === "off" && this.deps.generateSecret !== void 0 && !this.stopped) gate = await this.generate();
|
|
89340
|
-
if (this.stopped) return;
|
|
89341
|
-
setProcessClusterSecretGate(gate);
|
|
89342
|
-
this.report(gate);
|
|
89343
|
-
if (gate.kind === "unknown" || gate.kind === "off" && this.deps.generateSecret !== void 0) this.scheduleRetry();
|
|
89344
|
-
}
|
|
89345
|
-
async generate() {
|
|
89346
|
-
try {
|
|
89347
|
-
await this.deps.generateSecret?.();
|
|
89348
|
-
} catch (err) {
|
|
89349
|
-
this.deps.logger.error("The cluster secret is mandatory but could not be generated yet — retrying. Agents cannot authenticate until it exists.", { meta: { error: errText(err) } });
|
|
89350
|
-
return { kind: "off" };
|
|
89351
|
-
}
|
|
89352
|
-
this.deps.logger.info("Generated the cluster secret (none was stored). Reveal it on System → Cluster and enter it in each agent.");
|
|
89353
|
-
return this.compute();
|
|
89354
|
-
}
|
|
89355
|
-
async compute() {
|
|
89356
|
-
let section;
|
|
89357
|
-
try {
|
|
89358
|
-
section = await this.deps.readSection();
|
|
89359
|
-
} catch (err) {
|
|
89360
|
-
return {
|
|
89361
|
-
kind: "unknown",
|
|
89362
|
-
reason: `settings unreadable: ${errText(err)}`
|
|
89363
|
-
};
|
|
89364
|
-
}
|
|
89365
|
-
setProcessMeshAuthMode("enforced");
|
|
89366
|
-
const stored = section[CLUSTER_SECRET_FIELD];
|
|
89367
|
-
if (stored === void 0 || stored === null || stored === "") return { kind: "off" };
|
|
89368
|
-
if (!isSecretMarker(stored)) return {
|
|
89369
|
-
kind: "unknown",
|
|
89370
|
-
reason: "stored inline, not in the keychain — set it again in System → Cluster"
|
|
89371
|
-
};
|
|
89372
|
-
const secrets = this.deps.secrets;
|
|
89373
|
-
if (secrets === null) return {
|
|
89374
|
-
kind: "unknown",
|
|
89375
|
-
reason: "no keychain door in this process"
|
|
89376
|
-
};
|
|
89377
|
-
let entry;
|
|
89378
|
-
try {
|
|
89379
|
-
entry = (await secrets.resolve([CLUSTER_SECRET_REF]))[CLUSTER_SECRET_REF];
|
|
89380
|
-
} catch (err) {
|
|
89381
|
-
return {
|
|
89382
|
-
kind: "unknown",
|
|
89383
|
-
reason: errText(err)
|
|
89384
|
-
};
|
|
89385
|
-
}
|
|
89386
|
-
if (entry === void 0) return {
|
|
89387
|
-
kind: "unknown",
|
|
89388
|
-
reason: "no-answer"
|
|
89389
|
-
};
|
|
89390
|
-
switch (entry.kind) {
|
|
89391
|
-
case "value": return {
|
|
89392
|
-
kind: "on",
|
|
89393
|
-
hash: hashClusterSecret(entry.value)
|
|
89394
|
-
};
|
|
89395
|
-
case "unavailable": return {
|
|
89396
|
-
kind: "unknown",
|
|
89397
|
-
reason: entry.reason
|
|
89398
|
-
};
|
|
89399
|
-
case "missing": return {
|
|
89400
|
-
kind: "unknown",
|
|
89401
|
-
reason: "the stored value is gone — set it again in System → Cluster"
|
|
89402
|
-
};
|
|
89403
|
-
case "forbidden": return {
|
|
89404
|
-
kind: "unknown",
|
|
89405
|
-
reason: "forbidden"
|
|
89406
|
-
};
|
|
89407
|
-
}
|
|
89408
|
-
}
|
|
89409
|
-
report(gate) {
|
|
89410
|
-
const changed = this.last !== gate.kind;
|
|
89411
|
-
this.last = gate.kind;
|
|
89412
|
-
if (gate.kind === "unknown") {
|
|
89413
|
-
this.deps.logger.error("Agents cannot register: a cluster secret is set but cannot be read from the keychain. Registrations are refused until it can (no fallback).", { meta: { reason: gate.reason } });
|
|
89414
|
-
return;
|
|
89415
|
-
}
|
|
89416
|
-
if (changed) this.deps.logger.info(gate.kind === "on" ? "Cluster secret set — agents prove it to join the mesh" : "No cluster secret yet — no node can authenticate to the mesh");
|
|
89417
|
-
}
|
|
89418
|
-
scheduleRetry() {
|
|
89419
|
-
if (this.stopped || this.retryTimer !== null) return;
|
|
89420
|
-
this.retryTimer = setTimeout(() => {
|
|
89421
|
-
this.retryTimer = null;
|
|
89422
|
-
this.reload();
|
|
89423
|
-
}, this.deps.retryMs ?? 3e4);
|
|
89424
|
-
this.retryTimer.unref?.();
|
|
89425
|
-
}
|
|
89426
|
-
};
|
|
89427
|
-
function errText(err) {
|
|
89428
|
-
return err instanceof Error ? err.message : String(err);
|
|
89429
|
-
}
|
|
89430
|
-
//#endregion
|
|
89431
|
-
//#region src/builtins/system-config/mesh-actions.ts
|
|
89432
|
-
/**
|
|
89433
|
-
* System → Cluster — mint a single-use mesh join token (Release A) and
|
|
89434
|
-
* agent-ui unlock tickets (D821).
|
|
89435
|
-
*/
|
|
89436
|
-
var mintJoinTokenInputSchema = z.object({
|
|
89437
|
-
/** The node id the token is for - mandatory: the CSR CN must be exactly this. */
|
|
89438
|
-
nodeId: z.string().min(1),
|
|
89439
|
-
/** Override hub HTTPS base (default: local-network publicEndpoint). */
|
|
89440
|
-
hubUrl: z.string().url().optional(),
|
|
89441
|
-
/** Override `host:6443` TLS mesh address carried in the token. */
|
|
89442
|
-
hubMeshAddress: z.string().min(3).optional(),
|
|
89443
|
-
/** Seconds until expiry; capped at 1 h. */
|
|
89444
|
-
ttlSec: z.number().int().positive().max(3600).optional()
|
|
89445
|
-
});
|
|
89446
|
-
var mintJoinTokenOutputSchema = z.object({
|
|
89447
|
-
token: z.string().min(1),
|
|
89448
|
-
exp: z.number().int(),
|
|
89449
|
-
hubUrl: z.string(),
|
|
89450
|
-
hubMeshAddress: z.string(),
|
|
89451
|
-
caFingerprint: z.string(),
|
|
89452
|
-
nodeId: z.string()
|
|
89453
|
-
});
|
|
89454
|
-
var mintAgentUiUnlockInputSchema = z.object({
|
|
88317
|
+
var systemConfigMeshActions = defineCustomActions({
|
|
88318
|
+
/** Hub admin → short-lived ticket the agent redeems for a tab session (D821). */
|
|
88319
|
+
mintAgentUiUnlockTicket: customAction(z.object({
|
|
89455
88320
|
nodeId: z.string().min(1),
|
|
89456
88321
|
/**
|
|
89457
88322
|
* Preferred agent dashboard base (`http://host:4444`). When set, the
|
|
89458
88323
|
* answer includes `dashboardUrl` with `?ticket=` already attached.
|
|
89459
88324
|
*/
|
|
89460
88325
|
dashboardBaseUrl: z.string().url().optional()
|
|
89461
|
-
})
|
|
89462
|
-
var mintAgentUiUnlockOutputSchema = z.object({
|
|
88326
|
+
}), z.object({
|
|
89463
88327
|
ticket: z.string().min(1),
|
|
89464
88328
|
exp: z.number().int(),
|
|
89465
88329
|
nodeId: z.string().min(1),
|
|
89466
88330
|
dashboardUrl: z.string().url().optional()
|
|
89467
|
-
})
|
|
89468
|
-
|
|
89469
|
-
|
|
89470
|
-
|
|
89471
|
-
auth: "admin"
|
|
89472
|
-
}),
|
|
89473
|
-
/** Hub admin → short-lived ticket the agent redeems for a tab session (D821). */
|
|
89474
|
-
mintAgentUiUnlockTicket: customAction(mintAgentUiUnlockInputSchema, mintAgentUiUnlockOutputSchema, {
|
|
89475
|
-
kind: "mutation",
|
|
89476
|
-
auth: "admin"
|
|
89477
|
-
})
|
|
89478
|
-
});
|
|
88331
|
+
}), {
|
|
88332
|
+
kind: "mutation",
|
|
88333
|
+
auth: "admin"
|
|
88334
|
+
}) });
|
|
89479
88335
|
//#endregion
|
|
89480
88336
|
//#region src/builtins/system-config/system-config.addon.ts
|
|
89481
88337
|
/** How often superseded and expired mesh certificate rows are reaped. */
|
|
@@ -89490,13 +88346,13 @@ var MESH_REAP_MS = 24 * 36e5;
|
|
|
89490
88346
|
* state of their own (the session token lifetime).
|
|
89491
88347
|
*
|
|
89492
88348
|
* Sections exposed — this list is the whole of it:
|
|
89493
|
-
* - server (port, host, dataPath — READ-ONLY, loaded from config.yaml at bootstrap
|
|
88349
|
+
* - server (port, host, dataPath — READ-ONLY, loaded from config.yaml at bootstrap;
|
|
88350
|
+
* name = the hub's human name, `server.name`, editable — D861)
|
|
89494
88351
|
* - auth (tokenExpiry = session lifetime, accessTokenExpiry, trustedProxies,
|
|
89495
88352
|
* trustedNetworks)
|
|
89496
|
-
* - cluster (
|
|
89497
|
-
*
|
|
89498
|
-
*
|
|
89499
|
-
* boot; `meshAuth` — transition / enforced. D802)
|
|
88353
|
+
* - cluster (no operator field remains: the cluster secret and the mesh auth
|
|
88354
|
+
* mode were removed by D857 — a node's identity is its mesh
|
|
88355
|
+
* certificate, and agents are paired, not given a secret)
|
|
89500
88356
|
*
|
|
89501
88357
|
* Sections NOT exposed (each owned by the addon that implements them):
|
|
89502
88358
|
* - logging → `winston-logging` addon (level + retention)
|
|
@@ -89530,21 +88386,25 @@ var SECTION_TITLES = {
|
|
|
89530
88386
|
};
|
|
89531
88387
|
/** The keychain owner of the hub's own secrets (D797). */
|
|
89532
88388
|
var SYSTEM_SECRET_OWNER = "system";
|
|
88389
|
+
/** The form key (and the `server` section key) of the hub's human name (D861). */
|
|
88390
|
+
var SERVER_NAME_FIELD = "name";
|
|
89533
88391
|
/** Keys that map 1:1 to a given yml section — used by `updateGlobalSettings`
|
|
89534
88392
|
* to figure out which section owns each key in the incoming patch. */
|
|
89535
88393
|
var KEY_TO_SECTION = {
|
|
89536
88394
|
port: "server",
|
|
89537
88395
|
host: "server",
|
|
89538
88396
|
dataPath: "server",
|
|
88397
|
+
[SERVER_NAME_FIELD]: "server",
|
|
89539
88398
|
tokenExpiry: "auth",
|
|
89540
88399
|
accessTokenExpiry: "auth",
|
|
89541
88400
|
trustedProxies: "auth",
|
|
89542
|
-
trustedNetworks: "auth"
|
|
89543
|
-
[CLUSTER_SECRET_FIELD]: "cluster",
|
|
89544
|
-
[MESH_AUTH_MODE_FIELD]: "cluster"
|
|
88401
|
+
trustedNetworks: "auth"
|
|
89545
88402
|
};
|
|
89546
|
-
/**
|
|
89547
|
-
|
|
88403
|
+
/**
|
|
88404
|
+
* Keys a pre-D857 form may still send. They are dropped with a line, never
|
|
88405
|
+
* written: the cluster secret and the mesh auth mode no longer exist.
|
|
88406
|
+
*/
|
|
88407
|
+
var RETIRED_CLUSTER_KEYS = new Set(["clusterSecret", "meshAuth"]);
|
|
89548
88408
|
/**
|
|
89549
88409
|
* Auth keys holding a list of networks (CIDR or single address). A save with
|
|
89550
88410
|
* an entry that does not parse is REFUSED whole: dropping it would trust less
|
|
@@ -89555,7 +88415,6 @@ var CIDR_LIST_KEYS = new Set(["trustedProxies", "trustedNetworks"]);
|
|
|
89555
88415
|
var SYSTEM_CONFIG_CLUSTER_SECTION_ID = "system-config-cluster";
|
|
89556
88416
|
var SystemConfigAddon = class extends BaseAddon {
|
|
89557
88417
|
id = "system-config";
|
|
89558
|
-
clusterSecretKeeper = null;
|
|
89559
88418
|
meshCaKeeper = null;
|
|
89560
88419
|
meshReapTimer = null;
|
|
89561
88420
|
meshGateTimers = /* @__PURE__ */ new Set();
|
|
@@ -89565,20 +88424,6 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
89565
88424
|
super({});
|
|
89566
88425
|
}
|
|
89567
88426
|
async onInitialize() {
|
|
89568
|
-
this.clusterSecretKeeper = new ClusterSecretKeeper({
|
|
89569
|
-
secrets: this.systemSecrets(),
|
|
89570
|
-
readSection: async () => await this.ctx.settings?.getSection("cluster") ?? {},
|
|
89571
|
-
logger: this.ctx.logger,
|
|
89572
|
-
generateSecret: () => this.generateClusterSecret()
|
|
89573
|
-
});
|
|
89574
|
-
setProcessMeshEnforcer(async (reason) => {
|
|
89575
|
-
await this.writeMeshAuthMode("enforced");
|
|
89576
|
-
this.ctx.logger.info("Mesh authentication is now ENFORCED", { meta: { reason } });
|
|
89577
|
-
});
|
|
89578
|
-
await this.clusterSecretKeeper.start();
|
|
89579
|
-
try {
|
|
89580
|
-
await this.writeMeshAuthMode("enforced");
|
|
89581
|
-
} catch {}
|
|
89582
88427
|
this.meshCaKeeper = new MeshCaKeeper({
|
|
89583
88428
|
secrets: this.systemSecrets(),
|
|
89584
88429
|
readClusterSection: async () => await this.ctx.settings?.getSection("cluster") ?? {},
|
|
@@ -89592,14 +88437,10 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
89592
88437
|
this.ctx.logger.info("Initialized — exposes yml-backed sections via getGlobalSettings");
|
|
89593
88438
|
return {
|
|
89594
88439
|
customActions: systemConfigMeshActions,
|
|
89595
|
-
actionHandlers: {
|
|
89596
|
-
mintJoinToken: async (input) => this.mintJoinToken(parseMintJoinTokenInput(input)),
|
|
89597
|
-
mintAgentUiUnlockTicket: async (input) => this.mintAgentUiUnlock(parseMintUnlockInput(input))
|
|
89598
|
-
}
|
|
88440
|
+
actionHandlers: { mintAgentUiUnlockTicket: async (input) => this.mintAgentUiUnlock(parseMintUnlockInput(input)) }
|
|
89599
88441
|
};
|
|
89600
88442
|
}
|
|
89601
88443
|
async onShutdown() {
|
|
89602
|
-
setProcessMeshEnforcer(null);
|
|
89603
88444
|
setProcessMeshCertificateRegistry(null);
|
|
89604
88445
|
setProcessMeshTlsListenerState(null);
|
|
89605
88446
|
setProcessAgentHttpsNames(null);
|
|
@@ -89610,8 +88451,6 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
89610
88451
|
this.meshGateTimers.clear();
|
|
89611
88452
|
this.meshCaKeeper?.stop();
|
|
89612
88453
|
this.meshCaKeeper = null;
|
|
89613
|
-
this.clusterSecretKeeper?.stop();
|
|
89614
|
-
this.clusterSecretKeeper = null;
|
|
89615
88454
|
}
|
|
89616
88455
|
/**
|
|
89617
88456
|
* The hub's record of mesh leaves (D856): declared and loaded BEFORE the TLS
|
|
@@ -89702,32 +88541,9 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
89702
88541
|
onError: (err) => this.ctx.logger.error("Mesh certificate registry failed to load", { meta: { error: err instanceof Error ? err.message : String(err) } })
|
|
89703
88542
|
});
|
|
89704
88543
|
}
|
|
89705
|
-
async mintJoinToken(input) {
|
|
89706
|
-
const ca = requireProcessMeshCa();
|
|
89707
|
-
const hubUrl = input.hubUrl ?? await this.resolveHubUrl();
|
|
89708
|
-
const hubMeshAddress = input.hubMeshAddress ?? await this.resolveHubMeshAddress();
|
|
89709
|
-
const token = await mintMeshJoinToken({
|
|
89710
|
-
ca,
|
|
89711
|
-
hubUrl,
|
|
89712
|
-
hubMeshAddress,
|
|
89713
|
-
nodeId: input.nodeId,
|
|
89714
|
-
...input.ttlSec !== void 0 ? { ttlSec: input.ttlSec } : {}
|
|
89715
|
-
});
|
|
89716
|
-
return {
|
|
89717
|
-
token,
|
|
89718
|
-
exp: readJwtExp(token),
|
|
89719
|
-
hubUrl,
|
|
89720
|
-
hubMeshAddress,
|
|
89721
|
-
caFingerprint: caFingerprintCompact(ca.certPem),
|
|
89722
|
-
nodeId: input.nodeId
|
|
89723
|
-
};
|
|
89724
|
-
}
|
|
89725
88544
|
/** D821 — short-lived ticket for the agent's `:4444` unlock session. */
|
|
89726
88545
|
async mintAgentUiUnlock(input) {
|
|
89727
|
-
const
|
|
89728
|
-
if (secrets === null) throw new Error("system-config: no keychain door — cannot mint an unlock ticket");
|
|
89729
|
-
const entry = (await secrets.resolve([CLUSTER_SECRET_REF]))[CLUSTER_SECRET_REF];
|
|
89730
|
-
if (entry?.kind !== "value") throw new Error("system-config: cluster secret is not available — cannot mint an unlock ticket");
|
|
88546
|
+
const ca = requireProcessMeshCa();
|
|
89731
88547
|
if (input.dashboardBaseUrl !== void 0) {
|
|
89732
88548
|
const origins = await this.readAgentDashboardOrigins();
|
|
89733
88549
|
if (!isAllowedAgentDashboardReturnTo(input.dashboardBaseUrl, origins)) throw new Error("dashboardBaseUrl is not an allowed agent dashboard origin (:4444 or agentDashboardOrigins)");
|
|
@@ -89735,10 +88551,10 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
89735
88551
|
if (!isKnownAgentAddress(input.dashboardBaseUrl, known, origins)) throw new Error(`dashboardBaseUrl is not an address this hub knows for "${input.nodeId}" - open the agent at its own address`);
|
|
89736
88552
|
}
|
|
89737
88553
|
const ticket = mintAgentUiUnlockTicket({
|
|
89738
|
-
|
|
88554
|
+
caKeyPem: ca.keyPem,
|
|
89739
88555
|
nodeId: input.nodeId
|
|
89740
88556
|
});
|
|
89741
|
-
const payloadJson = Buffer.from(ticket.split(".")[
|
|
88557
|
+
const payloadJson = Buffer.from(ticket.split(".")[1] ?? "", "base64url").toString("utf8");
|
|
89742
88558
|
const exp = JSON.parse(payloadJson).exp ?? 0;
|
|
89743
88559
|
const dashboardUrl = input.dashboardBaseUrl === void 0 ? void 0 : (() => {
|
|
89744
88560
|
const u = new URL(input.dashboardBaseUrl);
|
|
@@ -89759,24 +88575,6 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
89759
88575
|
return [];
|
|
89760
88576
|
}
|
|
89761
88577
|
}
|
|
89762
|
-
async resolveHubUrl() {
|
|
89763
|
-
try {
|
|
89764
|
-
const book = await this.ctx.api?.localNetwork?.getAddresses?.query({ scheme: "https" });
|
|
89765
|
-
const url = book?.roles?.publicEndpoint?.resolved ?? book?.roles?.internal?.resolved ?? null;
|
|
89766
|
-
if (typeof url === "string" && url.length > 0) return url;
|
|
89767
|
-
} catch {}
|
|
89768
|
-
const host = (await this.ctx.settings?.getSection("server"))?.["host"];
|
|
89769
|
-
const port = (await this.ctx.settings?.getSection("server"))?.["port"];
|
|
89770
|
-
return `https://${typeof host === "string" && host.length > 0 && host !== "0.0.0.0" ? host : "127.0.0.1"}:${typeof port === "number" ? port : Number(port) || 4443}`;
|
|
89771
|
-
}
|
|
89772
|
-
async resolveHubMeshAddress() {
|
|
89773
|
-
try {
|
|
89774
|
-
const base = (await this.ctx.api?.localNetwork?.getAddresses?.query({}))?.roles?.internal?.resolved;
|
|
89775
|
-
if (typeof base === "string" && base.length > 0) return `${new URL(base).hostname}:${DEFAULT_HUB_TLS_TCP_PORT}`;
|
|
89776
|
-
} catch {}
|
|
89777
|
-
const host = (await this.ctx.settings?.getSection("server"))?.["host"];
|
|
89778
|
-
return `${typeof host === "string" && host.length > 0 && host !== "0.0.0.0" ? host : "127.0.0.1"}:${DEFAULT_HUB_TLS_TCP_PORT}`;
|
|
89779
|
-
}
|
|
89780
88578
|
/** The keychain handle for owner `system`; `null` where there is no door. */
|
|
89781
88579
|
systemSecrets() {
|
|
89782
88580
|
const forOwner = this.ctx.secrets?.forOwner ?? null;
|
|
@@ -89787,14 +88585,22 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
89787
88585
|
{
|
|
89788
88586
|
id: "system-config-server",
|
|
89789
88587
|
title: SECTION_TITLES["server"],
|
|
89790
|
-
description: "
|
|
88588
|
+
description: "The name of this server, and its connection settings (read-only, loaded from config.yaml at bootstrap).",
|
|
89791
88589
|
columns: 2,
|
|
89792
88590
|
fields: [
|
|
88591
|
+
{
|
|
88592
|
+
type: "text",
|
|
88593
|
+
key: SERVER_NAME_FIELD,
|
|
88594
|
+
label: "Server name",
|
|
88595
|
+
description: `Shown in the admin UI and on the apps' sign-in screen (1 to 48 characters). Leave empty to use this machine's hostname.`,
|
|
88596
|
+
placeholder: hostnameWithoutDomain(),
|
|
88597
|
+
span: 2
|
|
88598
|
+
},
|
|
89793
88599
|
{
|
|
89794
88600
|
type: "info",
|
|
89795
88601
|
key: "server-restart-note",
|
|
89796
88602
|
label: "Restart required",
|
|
89797
|
-
content: "
|
|
88603
|
+
content: "Port, host and data path are read-only. Change them in config.yaml and restart.",
|
|
89798
88604
|
variant: "warning"
|
|
89799
88605
|
},
|
|
89800
88606
|
{
|
|
@@ -89869,14 +88675,9 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
89869
88675
|
{
|
|
89870
88676
|
id: SYSTEM_CONFIG_CLUSTER_SECTION_ID,
|
|
89871
88677
|
title: SECTION_TITLES["cluster"],
|
|
89872
|
-
description: "Agents
|
|
88678
|
+
description: "Agents join this hub by pairing (System → Cluster → Agents): the hub signs a certificate for the agent after the operator confirms the same 6-digit code on the hub and in the agent's own page. There is no shared cluster secret.",
|
|
89873
88679
|
columns: 1,
|
|
89874
|
-
fields: [
|
|
89875
|
-
type: "password",
|
|
89876
|
-
key: CLUSTER_SECRET_FIELD,
|
|
89877
|
-
label: "Cluster secret",
|
|
89878
|
-
description: "Reveal and copy into each agent to pair. Saving a new value rotates it for every agent."
|
|
89879
|
-
}]
|
|
88680
|
+
fields: []
|
|
89880
88681
|
}
|
|
89881
88682
|
] };
|
|
89882
88683
|
}
|
|
@@ -89899,13 +88700,32 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
89899
88700
|
}
|
|
89900
88701
|
/**
|
|
89901
88702
|
* The admin UI / `addonSettings` cap prefer {@link BaseAddon.updateGlobalSettingsAsOperator}.
|
|
89902
|
-
* That BaseAddon path writes the generic addon store and never reaches
|
|
89903
|
-
*
|
|
89904
|
-
*
|
|
88703
|
+
* That BaseAddon path writes the generic addon store and never reaches the
|
|
88704
|
+
* yml sections. Route the operator write through the same section-aware path
|
|
88705
|
+
* as {@link updateGlobalSettings}.
|
|
89905
88706
|
*/
|
|
89906
88707
|
async updateGlobalSettingsAsOperator(patch, _nodeId) {
|
|
89907
88708
|
await this.updateGlobalSettings(patch);
|
|
89908
88709
|
}
|
|
88710
|
+
/**
|
|
88711
|
+
* The value to store for a `name` in a save, or `undefined` for "leave the row
|
|
88712
|
+
* alone". The whole form posts every field, so an empty box on a hub that was
|
|
88713
|
+
* never named is the NORMAL case and must write nothing (D861: a seed never
|
|
88714
|
+
* overwrites); an empty box over a stored name is the operator clearing it,
|
|
88715
|
+
* which stores `''` (readers treat it as unset). Anything else must be a valid
|
|
88716
|
+
* name — refused whole, like the network lists.
|
|
88717
|
+
*/
|
|
88718
|
+
async normalizeServerName(value) {
|
|
88719
|
+
if (value === void 0 || value === null) return void 0;
|
|
88720
|
+
if (typeof value !== "string") throw new Error("The server name must be text");
|
|
88721
|
+
if (value.trim() === "") {
|
|
88722
|
+
const current = (await this.ctx.settings.getSection("server"))[SERVER_NAME_FIELD];
|
|
88723
|
+
return typeof current === "string" && current !== "" ? "" : void 0;
|
|
88724
|
+
}
|
|
88725
|
+
const parsed = ServerNameSchema.safeParse(value);
|
|
88726
|
+
if (!parsed.success) throw new Error(parsed.error.issues[0]?.message ?? "The server name is not valid");
|
|
88727
|
+
return parsed.data;
|
|
88728
|
+
}
|
|
89909
88729
|
async updateGlobalSettings(patch) {
|
|
89910
88730
|
if (!this.ctx.settings) throw new Error("system-config: ctx.settings not available — cannot write sections");
|
|
89911
88731
|
const perSection = /* @__PURE__ */ new Map();
|
|
@@ -89918,11 +88738,23 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
89918
88738
|
this.ctx.logger.warn("cluster.agentDashboardOrigins is no longer writable from settings — ignoring this patch");
|
|
89919
88739
|
continue;
|
|
89920
88740
|
}
|
|
88741
|
+
if (RETIRED_CLUSTER_KEYS.has(key)) {
|
|
88742
|
+
this.ctx.logger.warn(`cluster.${key} is retired (D857) — agents are paired by certificate; ignoring this patch`);
|
|
88743
|
+
continue;
|
|
88744
|
+
}
|
|
89921
88745
|
const section = KEY_TO_SECTION[key];
|
|
89922
88746
|
if (section === void 0) {
|
|
89923
88747
|
this.ctx.logger.warn("update ignored unknown key (not mapped to any section)", { meta: { key } });
|
|
89924
88748
|
continue;
|
|
89925
88749
|
}
|
|
88750
|
+
if (key === SERVER_NAME_FIELD) {
|
|
88751
|
+
const name = await this.normalizeServerName(value);
|
|
88752
|
+
if (name === void 0) continue;
|
|
88753
|
+
const bucket = perSection.get("server") ?? {};
|
|
88754
|
+
bucket[key] = name;
|
|
88755
|
+
perSection.set("server", bucket);
|
|
88756
|
+
continue;
|
|
88757
|
+
}
|
|
89926
88758
|
if (section === "server") {
|
|
89927
88759
|
this.ctx.logger.warn("update ignored read-only server-section key", { meta: { key } });
|
|
89928
88760
|
continue;
|
|
@@ -89939,10 +88771,6 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
89939
88771
|
bucket[key] = value;
|
|
89940
88772
|
}
|
|
89941
88773
|
for (const [section, sectionPatch] of perSection) {
|
|
89942
|
-
if (section === "cluster") {
|
|
89943
|
-
await this.writeClusterSection(sectionPatch);
|
|
89944
|
-
continue;
|
|
89945
|
-
}
|
|
89946
88774
|
await this.ctx.settings.setSection(section, sectionPatch);
|
|
89947
88775
|
this.ctx.logger.info("Wrote keys to section", { meta: {
|
|
89948
88776
|
section,
|
|
@@ -89950,78 +88778,10 @@ var SystemConfigAddon = class extends BaseAddon {
|
|
|
89950
88778
|
} });
|
|
89951
88779
|
}
|
|
89952
88780
|
}
|
|
89953
|
-
/**
|
|
89954
|
-
* The cluster secret's save path: the value goes to the keychain (owner
|
|
89955
|
-
* `system`), the row gets the marker; `''` / a view keeps. `$secretClear` is
|
|
89956
|
-
* REFUSED: the secret is mandatory (D802). A value the keychain cannot store
|
|
89957
|
-
* is REFUSED — never written inline (D787, P5). Mesh auth mode is always
|
|
89958
|
-
* enforced (D821) — a legacy `meshAuth` in the patch is ignored.
|
|
89959
|
-
*/
|
|
89960
|
-
async writeClusterSection(patch) {
|
|
89961
|
-
const { [MESH_AUTH_MODE_FIELD]: _legacyMode, ...secretPatch } = patch;
|
|
89962
|
-
await this.writeMeshAuthMode("enforced");
|
|
89963
|
-
if (Object.keys(secretPatch).length === 0) return;
|
|
89964
|
-
if (isSecretClear(secretPatch["clusterSecret"])) throw new Error("The cluster secret is mandatory and cannot be cleared — save a new value to rotate it");
|
|
89965
|
-
await this.storeClusterSecret(secretPatch);
|
|
89966
|
-
this.ctx.logger.info("Cluster secret updated");
|
|
89967
|
-
await this.clusterSecretKeeper?.reload();
|
|
89968
|
-
}
|
|
89969
|
-
/** Persist + publish mesh auth mode (always `enforced` after D821). */
|
|
89970
|
-
async writeMeshAuthMode(mode) {
|
|
89971
|
-
await this.ctx.settings.setSection("cluster", { [MESH_AUTH_MODE_FIELD]: mode });
|
|
89972
|
-
setProcessMeshAuthMode(mode);
|
|
89973
|
-
}
|
|
89974
|
-
/**
|
|
89975
|
-
* First boot, or a keychain reset that cleared the marker (D802): a fresh
|
|
89976
|
-
* random secret, stored like an operator save. Mesh auth stays enforced
|
|
89977
|
-
* (D821) — every agent must present the secret; there is no transition window.
|
|
89978
|
-
*/
|
|
89979
|
-
async generateClusterSecret() {
|
|
89980
|
-
const settings = this.ctx.settings;
|
|
89981
|
-
const secrets = this.systemSecrets();
|
|
89982
|
-
if (!settings || secrets === null) throw new Error("system-config: no keychain door — the cluster secret cannot be generated");
|
|
89983
|
-
const existing = (await secrets.resolve([CLUSTER_SECRET_REF]))[CLUSTER_SECRET_REF];
|
|
89984
|
-
if (existing?.kind === "value") {
|
|
89985
|
-
await settings.setSection("cluster", { [CLUSTER_SECRET_FIELD]: makeSecretMarker(CLUSTER_SECRET_REF) });
|
|
89986
|
-
this.ctx.logger.warn("The cluster secret row was empty but the keychain holds a value — re-adopted it");
|
|
89987
|
-
return;
|
|
89988
|
-
}
|
|
89989
|
-
if (existing?.kind !== "missing") throw new Error(`the keychain cannot answer for the cluster secret (${existing?.kind ?? "no answer"})`);
|
|
89990
|
-
const value = randomBytes(GENERATED_SECRET_BYTES).toString("base64url");
|
|
89991
|
-
await this.storeClusterSecret({ [CLUSTER_SECRET_FIELD]: value });
|
|
89992
|
-
await settings.setSection("cluster", { [MESH_AUTH_MODE_FIELD]: "enforced" });
|
|
89993
|
-
setProcessMeshAuthMode("enforced");
|
|
89994
|
-
}
|
|
89995
|
-
async storeClusterSecret(patch) {
|
|
89996
|
-
const settings = this.ctx.settings;
|
|
89997
|
-
if (!settings) throw new Error("system-config: ctx.settings not available");
|
|
89998
|
-
const secrets = this.systemSecrets();
|
|
89999
|
-
if (secrets === null) throw new Error("system-config: no keychain door — the cluster secret cannot be stored");
|
|
90000
|
-
const stored = await settings.getSection("cluster");
|
|
90001
|
-
const result = await transformSecretWrite({
|
|
90002
|
-
tree: secretTreeFromSchema(this.buildGlobalSchema()),
|
|
90003
|
-
secrets,
|
|
90004
|
-
patch,
|
|
90005
|
-
stored,
|
|
90006
|
-
operatorWrite: true
|
|
90007
|
-
});
|
|
90008
|
-
if (Object.keys(result.patch).length > 0) await settings.setSection("cluster", result.patch);
|
|
90009
|
-
const { orphaned } = await result.afterWrite();
|
|
90010
|
-
if (orphaned.length > 0) this.ctx.logger.warn("an old cluster secret value could not be deleted from the keychain", { meta: { refs: orphaned } });
|
|
90011
|
-
}
|
|
90012
88781
|
};
|
|
90013
|
-
|
|
90014
|
-
|
|
90015
|
-
|
|
90016
|
-
if (typeof nodeId !== "string" || nodeId.length === 0) throw new Error("system-config: mintJoinToken requires { nodeId } - the node the token is for");
|
|
90017
|
-
const out = { nodeId };
|
|
90018
|
-
const hubUrl = Reflect.get(input, "hubUrl");
|
|
90019
|
-
const hubMeshAddress = Reflect.get(input, "hubMeshAddress");
|
|
90020
|
-
const ttlSec = Reflect.get(input, "ttlSec");
|
|
90021
|
-
if (typeof hubUrl === "string") out.hubUrl = hubUrl;
|
|
90022
|
-
if (typeof hubMeshAddress === "string") out.hubMeshAddress = hubMeshAddress;
|
|
90023
|
-
if (typeof ttlSec === "number") out.ttlSec = ttlSec;
|
|
90024
|
-
return out;
|
|
88782
|
+
/** This machine's hostname without its domain: what an unnamed hub is called. */
|
|
88783
|
+
function hostnameWithoutDomain() {
|
|
88784
|
+
return shortHostname(os.hostname());
|
|
90025
88785
|
}
|
|
90026
88786
|
function parseMintUnlockInput(input) {
|
|
90027
88787
|
if (input === null || typeof input !== "object") throw new Error("system-config: mintAgentUiUnlockTicket requires { nodeId }");
|
|
@@ -90033,15 +88793,5 @@ function parseMintUnlockInput(input) {
|
|
|
90033
88793
|
...typeof dashboardBaseUrl === "string" ? { dashboardBaseUrl } : {}
|
|
90034
88794
|
};
|
|
90035
88795
|
}
|
|
90036
|
-
/** Read `exp` from an unencrypted JWT payload (no verify — already minted here). */
|
|
90037
|
-
function readJwtExp(token) {
|
|
90038
|
-
const parts = token.split(".");
|
|
90039
|
-
if (parts.length < 2 || parts[1] === void 0) return 0;
|
|
90040
|
-
const json = Buffer.from(parts[1], "base64url").toString("utf8");
|
|
90041
|
-
const payload = JSON.parse(json);
|
|
90042
|
-
if (payload === null || typeof payload !== "object") return 0;
|
|
90043
|
-
const exp = Reflect.get(payload, "exp");
|
|
90044
|
-
return typeof exp === "number" ? exp : 0;
|
|
90045
|
-
}
|
|
90046
88796
|
//#endregion
|
|
90047
|
-
export {
|
|
88797
|
+
export { generateMeshKeyPair as $, setProcessMeshPeerTransportLookup as A, describeMeshLeaf as B, setProcessMeshTlsEnabler as C, getProcessPeerLeaf as D, getProcessNodeMeshTransport as E, setProcessMeshTlsListenerState as F, MeshCaKeeper as G, setProcessMeshCertificateRegistry as H, MESH_NODE_CERTIFICATES_COLLECTION as I, caFingerprint as J, getProcessMeshCaState as K, MESH_NODE_CERTIFICATES_COLUMNS as L, revokeMeshCertificate as M, getProcessMeshTlsListenerState as N, isProcessVerifiedMeshPeer as O, openMeshTlsWhenRevocationsLoaded as P, generateMeshCa as Q, MeshCertificateRegistry as R, ServiceBroker as S, SYSTEM_CONFIG_CLUSTER_SECTION_ID, SystemConfigAddon, SystemConfigAddon as default, emitProcessNodeRegistered as T, MeshCrl as U, getProcessMeshCertificateRegistry as V, processMeshCrl as W, createMeshCsrPem as X, caFingerprintCompact as Y, exportMeshPrivateKeyPem as Z, signPairingProof as _, readCidrSetting as _t, hubHostFromMeshAddress as a, AGENT_UI_UNLOCK_TTL_MS as at, TlsTcpTransporter as b, PAIRING_MAX_SESSIONS as c, AGENT_UI_UNLOCK_VERSION as ct, PAIRING_PROTOCOL as d, mintAgentUiUnlockTicket as dt, isValidAgentNodeId as et, PAIRING_TTL_MS as f, parseAgentDashboardOrigins as ft, keyFingerprintShort as g, parseCidrList as gt, describeCsr as h, normalizeIp as ht, AgentPairing as i, AGENT_DASHBOARD_ORIGINS_FIELD as it, renewMeshCertificate as j, onProcessNodeRegistered as k, PAIRING_PATHS as l, UnlockTicketJtiStore as lt, computePairingSas as m, createCidrMatcher as mt, HubPairing as n, issueMeshLeafFromCsr as nt, PAIRING_CODE_DIGITS as o, AGENT_UI_UNLOCK_TYP as ot, computePairingCommitment as p, verifyAgentUiUnlockTicket as pt, requireProcessMeshCa as q, PairingHttpError as r, loadMeshCa as rt, PAIRING_MAX_CODE_ATTEMPTS as s, AGENT_UI_UNLOCK_USE as st, systemConfigMeshActions as t, issueMeshLeafForNode as tt, PAIRING_PIN_DIGITS as u, isAllowedAgentDashboardReturnTo as ut, verifyPairingProof as v, dropProcessPeer as w, Errors as x, MESH_TLS_PORT_HELLO_FIELD as y, RENEWAL_ABANDONED as z };
|