@serve.zone/dcrouter 8.1.0 → 9.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_serve/bundle.js +1417 -992
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/cache/classes.cache.cleaner.d.ts +47 -0
- package/dist_ts/cache/classes.cache.cleaner.js +130 -0
- package/dist_ts/cache/classes.cached.document.d.ts +76 -0
- package/dist_ts/cache/classes.cached.document.js +100 -0
- package/dist_ts/cache/classes.cachedb.d.ts +60 -0
- package/dist_ts/cache/classes.cachedb.js +126 -0
- package/dist_ts/cache/documents/classes.cached.email.d.ts +125 -0
- package/dist_ts/cache/documents/classes.cached.email.js +337 -0
- package/dist_ts/cache/documents/classes.cached.ip.reputation.d.ts +119 -0
- package/dist_ts/cache/documents/classes.cached.ip.reputation.js +323 -0
- package/dist_ts/cache/documents/index.d.ts +2 -0
- package/dist_ts/cache/documents/index.js +3 -0
- package/dist_ts/cache/index.d.ts +4 -0
- package/dist_ts/cache/index.js +7 -0
- package/dist_ts/monitoring/classes.metricscache.d.ts +32 -0
- package/dist_ts/monitoring/classes.metricscache.js +63 -0
- package/dist_ts/monitoring/classes.metricsmanager.d.ts +169 -0
- package/dist_ts/monitoring/classes.metricsmanager.js +591 -0
- package/dist_ts/monitoring/index.d.ts +1 -0
- package/dist_ts/monitoring/index.js +2 -0
- package/dist_ts/opsserver/handlers/admin.handler.d.ts +31 -0
- package/dist_ts/opsserver/handlers/admin.handler.js +180 -0
- package/dist_ts/opsserver/handlers/certificate.handler.d.ts +34 -0
- package/dist_ts/opsserver/handlers/certificate.handler.js +419 -0
- package/dist_ts/opsserver/handlers/config.handler.d.ts +9 -0
- package/dist_ts/opsserver/handlers/config.handler.js +169 -0
- package/dist_ts/opsserver/handlers/email-ops.handler.d.ts +32 -0
- package/dist_ts/opsserver/handlers/email-ops.handler.js +226 -0
- package/dist_ts/opsserver/handlers/logs.handler.d.ts +17 -0
- package/dist_ts/opsserver/handlers/logs.handler.js +215 -0
- package/dist_ts/opsserver/handlers/radius.handler.d.ts +8 -0
- package/dist_ts/opsserver/handlers/radius.handler.js +296 -0
- package/dist_ts/opsserver/handlers/remoteingress.handler.d.ts +8 -0
- package/dist_ts/opsserver/handlers/remoteingress.handler.js +154 -0
- package/dist_ts/opsserver/handlers/security.handler.d.ts +11 -0
- package/dist_ts/opsserver/handlers/security.handler.js +232 -0
- package/dist_ts/opsserver/handlers/stats.handler.d.ts +13 -0
- package/dist_ts/opsserver/handlers/stats.handler.js +400 -0
- package/dist_ts/security/classes.securitylogger.d.ts +140 -0
- package/dist_ts/security/classes.securitylogger.js +235 -0
- package/dist_ts/storage/classes.storagemanager.d.ts +82 -0
- package/dist_ts/storage/classes.storagemanager.js +344 -0
- package/dist_ts/storage/index.d.ts +1 -0
- package/dist_ts/storage/index.js +3 -0
- package/dist_ts_interfaces/requests/config.d.ts +77 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate.d.ts +1 -1
- package/dist_ts_web/elements/ops-dashboard.js +15 -5
- package/dist_ts_web/elements/ops-view-apitokens.js +8 -4
- package/dist_ts_web/elements/ops-view-config.d.ts +10 -8
- package/dist_ts_web/elements/ops-view-config.js +215 -297
- package/package.json +2 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/opsserver/handlers/config.handler.ts +154 -72
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate.ts +1 -1
- package/ts_web/elements/ops-dashboard.ts +14 -4
- package/ts_web/elements/ops-view-apitokens.ts +7 -3
- package/ts_web/elements/ops-view-config.ts +237 -299
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
3
|
+
export class CertificateHandler {
|
|
4
|
+
opsServerRef;
|
|
5
|
+
typedrouter = new plugins.typedrequest.TypedRouter();
|
|
6
|
+
constructor(opsServerRef) {
|
|
7
|
+
this.opsServerRef = opsServerRef;
|
|
8
|
+
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
9
|
+
this.registerHandlers();
|
|
10
|
+
}
|
|
11
|
+
registerHandlers() {
|
|
12
|
+
// Get Certificate Overview
|
|
13
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getCertificateOverview', async (dataArg) => {
|
|
14
|
+
const certificates = await this.buildCertificateOverview();
|
|
15
|
+
const summary = this.buildSummary(certificates);
|
|
16
|
+
return { certificates, summary };
|
|
17
|
+
}));
|
|
18
|
+
// Legacy route-based reprovision (backward compat)
|
|
19
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('reprovisionCertificate', async (dataArg) => {
|
|
20
|
+
return this.reprovisionCertificateByRoute(dataArg.routeName);
|
|
21
|
+
}));
|
|
22
|
+
// Domain-based reprovision (preferred)
|
|
23
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('reprovisionCertificateDomain', async (dataArg) => {
|
|
24
|
+
return this.reprovisionCertificateDomain(dataArg.domain);
|
|
25
|
+
}));
|
|
26
|
+
// Delete certificate
|
|
27
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('deleteCertificate', async (dataArg) => {
|
|
28
|
+
return this.deleteCertificate(dataArg.domain);
|
|
29
|
+
}));
|
|
30
|
+
// Export certificate
|
|
31
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('exportCertificate', async (dataArg) => {
|
|
32
|
+
return this.exportCertificate(dataArg.domain);
|
|
33
|
+
}));
|
|
34
|
+
// Import certificate
|
|
35
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('importCertificate', async (dataArg) => {
|
|
36
|
+
return this.importCertificate(dataArg.cert);
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Build domain-centric certificate overview.
|
|
41
|
+
* Instead of one row per route, we produce one row per unique domain.
|
|
42
|
+
*/
|
|
43
|
+
async buildCertificateOverview() {
|
|
44
|
+
const dcRouter = this.opsServerRef.dcRouterRef;
|
|
45
|
+
const smartProxy = dcRouter.smartProxy;
|
|
46
|
+
if (!smartProxy)
|
|
47
|
+
return [];
|
|
48
|
+
const routes = smartProxy.routeManager.getRoutes();
|
|
49
|
+
// Phase 1: Collect unique domains with their associated route info
|
|
50
|
+
const domainMap = new Map();
|
|
51
|
+
for (const route of routes) {
|
|
52
|
+
if (!route.name)
|
|
53
|
+
continue;
|
|
54
|
+
const tls = route.action?.tls;
|
|
55
|
+
if (!tls)
|
|
56
|
+
continue;
|
|
57
|
+
// Skip passthrough routes - they don't manage certificates
|
|
58
|
+
if (tls.mode === 'passthrough')
|
|
59
|
+
continue;
|
|
60
|
+
const routeDomains = route.match.domains
|
|
61
|
+
? (Array.isArray(route.match.domains) ? route.match.domains : [route.match.domains])
|
|
62
|
+
: [];
|
|
63
|
+
// Determine source
|
|
64
|
+
let source = 'none';
|
|
65
|
+
if (tls.certificate === 'auto') {
|
|
66
|
+
if (smartProxy.settings.certProvisionFunction) {
|
|
67
|
+
source = 'provision-function';
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
source = 'acme';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else if (tls.certificate && typeof tls.certificate === 'object') {
|
|
74
|
+
source = 'static';
|
|
75
|
+
}
|
|
76
|
+
const canReprovision = source === 'acme' || source === 'provision-function';
|
|
77
|
+
const tlsMode = tls.mode;
|
|
78
|
+
for (const domain of routeDomains) {
|
|
79
|
+
const existing = domainMap.get(domain);
|
|
80
|
+
if (existing) {
|
|
81
|
+
// Add this route name to the existing domain entry
|
|
82
|
+
if (!existing.routeNames.includes(route.name)) {
|
|
83
|
+
existing.routeNames.push(route.name);
|
|
84
|
+
}
|
|
85
|
+
// Upgrade source if more specific
|
|
86
|
+
if (existing.source === 'none' && source !== 'none') {
|
|
87
|
+
existing.source = source;
|
|
88
|
+
existing.canReprovision = canReprovision;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
domainMap.set(domain, {
|
|
93
|
+
routeNames: [route.name],
|
|
94
|
+
source,
|
|
95
|
+
tlsMode,
|
|
96
|
+
canReprovision,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Phase 2: Resolve status for each unique domain
|
|
102
|
+
const certificates = [];
|
|
103
|
+
for (const [domain, info] of domainMap) {
|
|
104
|
+
let status = 'unknown';
|
|
105
|
+
let expiryDate;
|
|
106
|
+
let issuedAt;
|
|
107
|
+
let issuer;
|
|
108
|
+
let error;
|
|
109
|
+
// Check event-based status from certificateStatusMap (now keyed by domain)
|
|
110
|
+
const eventStatus = dcRouter.certificateStatusMap.get(domain);
|
|
111
|
+
if (eventStatus) {
|
|
112
|
+
status = eventStatus.status;
|
|
113
|
+
expiryDate = eventStatus.expiryDate;
|
|
114
|
+
issuedAt = eventStatus.issuedAt;
|
|
115
|
+
error = eventStatus.error;
|
|
116
|
+
if (eventStatus.source) {
|
|
117
|
+
issuer = eventStatus.source;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Try SmartProxy certificate status if no event data
|
|
121
|
+
if (status === 'unknown' && info.routeNames.length > 0) {
|
|
122
|
+
try {
|
|
123
|
+
const rustStatus = await smartProxy.getCertificateStatus(info.routeNames[0]);
|
|
124
|
+
if (rustStatus) {
|
|
125
|
+
if (rustStatus.expiryDate)
|
|
126
|
+
expiryDate = rustStatus.expiryDate;
|
|
127
|
+
if (rustStatus.issuer)
|
|
128
|
+
issuer = rustStatus.issuer;
|
|
129
|
+
if (rustStatus.issuedAt)
|
|
130
|
+
issuedAt = rustStatus.issuedAt;
|
|
131
|
+
if (rustStatus.status === 'valid' || rustStatus.status === 'expired') {
|
|
132
|
+
status = rustStatus.status;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// Rust bridge may not support this command yet — ignore
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
// Check persisted cert data from StorageManager
|
|
141
|
+
if (status === 'unknown') {
|
|
142
|
+
const cleanDomain = domain.replace(/^\*\.?/, '');
|
|
143
|
+
let certData = await dcRouter.storageManager.getJSON(`/certs/${cleanDomain}`);
|
|
144
|
+
if (!certData) {
|
|
145
|
+
// Also check certStore path (proxy-certs)
|
|
146
|
+
certData = await dcRouter.storageManager.getJSON(`/proxy-certs/${domain}`);
|
|
147
|
+
}
|
|
148
|
+
if (certData?.validUntil) {
|
|
149
|
+
expiryDate = new Date(certData.validUntil).toISOString();
|
|
150
|
+
if (certData.created) {
|
|
151
|
+
issuedAt = new Date(certData.created).toISOString();
|
|
152
|
+
}
|
|
153
|
+
issuer = 'smartacme-dns-01';
|
|
154
|
+
}
|
|
155
|
+
else if (certData?.publicKey) {
|
|
156
|
+
// certStore has the cert — parse PEM for expiry
|
|
157
|
+
try {
|
|
158
|
+
const x509 = new plugins.crypto.X509Certificate(certData.publicKey);
|
|
159
|
+
expiryDate = new Date(x509.validTo).toISOString();
|
|
160
|
+
issuedAt = new Date(x509.validFrom).toISOString();
|
|
161
|
+
}
|
|
162
|
+
catch { /* PEM parsing failed */ }
|
|
163
|
+
status = 'valid';
|
|
164
|
+
issuer = 'cert-store';
|
|
165
|
+
}
|
|
166
|
+
else if (certData) {
|
|
167
|
+
status = 'valid';
|
|
168
|
+
issuer = 'cert-store';
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// Compute status from expiry date
|
|
172
|
+
if (expiryDate && (status === 'valid' || status === 'unknown')) {
|
|
173
|
+
const expiry = new Date(expiryDate);
|
|
174
|
+
const now = new Date();
|
|
175
|
+
const daysUntilExpiry = (expiry.getTime() - now.getTime()) / (1000 * 60 * 60 * 24);
|
|
176
|
+
if (daysUntilExpiry < 0) {
|
|
177
|
+
status = 'expired';
|
|
178
|
+
}
|
|
179
|
+
else if (daysUntilExpiry < 30) {
|
|
180
|
+
status = 'expiring';
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
status = 'valid';
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// Static certs with no other info default to 'valid'
|
|
187
|
+
if (info.source === 'static' && status === 'unknown') {
|
|
188
|
+
status = 'valid';
|
|
189
|
+
}
|
|
190
|
+
// ACME/provision-function routes with no cert data are still provisioning
|
|
191
|
+
if (status === 'unknown' && (info.source === 'acme' || info.source === 'provision-function')) {
|
|
192
|
+
status = 'provisioning';
|
|
193
|
+
}
|
|
194
|
+
// Phase 3: Attach backoff info
|
|
195
|
+
let backoffInfo;
|
|
196
|
+
if (dcRouter.certProvisionScheduler) {
|
|
197
|
+
const bi = await dcRouter.certProvisionScheduler.getBackoffInfo(domain);
|
|
198
|
+
if (bi) {
|
|
199
|
+
backoffInfo = bi;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
certificates.push({
|
|
203
|
+
domain,
|
|
204
|
+
routeNames: info.routeNames,
|
|
205
|
+
status,
|
|
206
|
+
source: info.source,
|
|
207
|
+
tlsMode: info.tlsMode,
|
|
208
|
+
expiryDate,
|
|
209
|
+
issuer,
|
|
210
|
+
issuedAt,
|
|
211
|
+
error,
|
|
212
|
+
canReprovision: info.canReprovision,
|
|
213
|
+
backoffInfo,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return certificates;
|
|
217
|
+
}
|
|
218
|
+
buildSummary(certificates) {
|
|
219
|
+
const summary = { total: 0, valid: 0, expiring: 0, expired: 0, failed: 0, unknown: 0 };
|
|
220
|
+
summary.total = certificates.length;
|
|
221
|
+
for (const cert of certificates) {
|
|
222
|
+
switch (cert.status) {
|
|
223
|
+
case 'valid':
|
|
224
|
+
summary.valid++;
|
|
225
|
+
break;
|
|
226
|
+
case 'expiring':
|
|
227
|
+
summary.expiring++;
|
|
228
|
+
break;
|
|
229
|
+
case 'expired':
|
|
230
|
+
summary.expired++;
|
|
231
|
+
break;
|
|
232
|
+
case 'failed':
|
|
233
|
+
summary.failed++;
|
|
234
|
+
break;
|
|
235
|
+
case 'provisioning': // count as unknown
|
|
236
|
+
case 'unknown':
|
|
237
|
+
summary.unknown++;
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return summary;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Legacy route-based reprovisioning
|
|
245
|
+
*/
|
|
246
|
+
async reprovisionCertificateByRoute(routeName) {
|
|
247
|
+
const dcRouter = this.opsServerRef.dcRouterRef;
|
|
248
|
+
const smartProxy = dcRouter.smartProxy;
|
|
249
|
+
if (!smartProxy) {
|
|
250
|
+
return { success: false, message: 'SmartProxy is not running' };
|
|
251
|
+
}
|
|
252
|
+
try {
|
|
253
|
+
await smartProxy.provisionCertificate(routeName);
|
|
254
|
+
// Clear event-based status for domains in this route
|
|
255
|
+
for (const [domain, entry] of dcRouter.certificateStatusMap) {
|
|
256
|
+
if (entry.routeNames.includes(routeName)) {
|
|
257
|
+
dcRouter.certificateStatusMap.delete(domain);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
return { success: true, message: `Certificate reprovisioning triggered for route '${routeName}'` };
|
|
261
|
+
}
|
|
262
|
+
catch (err) {
|
|
263
|
+
return { success: false, message: err.message || 'Failed to reprovision certificate' };
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Domain-based reprovisioning — clears backoff first, then triggers provision
|
|
268
|
+
*/
|
|
269
|
+
async reprovisionCertificateDomain(domain) {
|
|
270
|
+
const dcRouter = this.opsServerRef.dcRouterRef;
|
|
271
|
+
const smartProxy = dcRouter.smartProxy;
|
|
272
|
+
if (!smartProxy) {
|
|
273
|
+
return { success: false, message: 'SmartProxy is not running' };
|
|
274
|
+
}
|
|
275
|
+
// Clear backoff for this domain (user override)
|
|
276
|
+
if (dcRouter.certProvisionScheduler) {
|
|
277
|
+
await dcRouter.certProvisionScheduler.clearBackoff(domain);
|
|
278
|
+
}
|
|
279
|
+
// Clear status map entry so it gets refreshed
|
|
280
|
+
dcRouter.certificateStatusMap.delete(domain);
|
|
281
|
+
// Try to provision via SmartAcme directly
|
|
282
|
+
if (dcRouter.smartAcme) {
|
|
283
|
+
try {
|
|
284
|
+
await dcRouter.smartAcme.getCertificateForDomain(domain);
|
|
285
|
+
return { success: true, message: `Certificate reprovisioning triggered for domain '${domain}'` };
|
|
286
|
+
}
|
|
287
|
+
catch (err) {
|
|
288
|
+
return { success: false, message: err.message || `Failed to reprovision certificate for ${domain}` };
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// Fallback: try provisioning via the first matching route
|
|
292
|
+
const routeNames = dcRouter.findRouteNamesForDomain(domain);
|
|
293
|
+
if (routeNames.length > 0) {
|
|
294
|
+
try {
|
|
295
|
+
await smartProxy.provisionCertificate(routeNames[0]);
|
|
296
|
+
return { success: true, message: `Certificate reprovisioning triggered for domain '${domain}' via route '${routeNames[0]}'` };
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
return { success: false, message: err.message || `Failed to reprovision certificate for ${domain}` };
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
return { success: false, message: `No routes found for domain '${domain}'` };
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Delete certificate data for a domain from storage
|
|
306
|
+
*/
|
|
307
|
+
async deleteCertificate(domain) {
|
|
308
|
+
const dcRouter = this.opsServerRef.dcRouterRef;
|
|
309
|
+
const cleanDomain = domain.replace(/^\*\.?/, '');
|
|
310
|
+
// Delete from all known storage paths
|
|
311
|
+
const paths = [
|
|
312
|
+
`/proxy-certs/${domain}`,
|
|
313
|
+
`/proxy-certs/${cleanDomain}`,
|
|
314
|
+
`/certs/${cleanDomain}`,
|
|
315
|
+
];
|
|
316
|
+
for (const path of paths) {
|
|
317
|
+
try {
|
|
318
|
+
await dcRouter.storageManager.delete(path);
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
// Path may not exist — ignore
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
// Clear from in-memory status map
|
|
325
|
+
dcRouter.certificateStatusMap.delete(domain);
|
|
326
|
+
// Clear backoff info
|
|
327
|
+
if (dcRouter.certProvisionScheduler) {
|
|
328
|
+
await dcRouter.certProvisionScheduler.clearBackoff(domain);
|
|
329
|
+
}
|
|
330
|
+
return { success: true, message: `Certificate data deleted for '${domain}'` };
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Export certificate data for a domain as ICert-shaped JSON
|
|
334
|
+
*/
|
|
335
|
+
async exportCertificate(domain) {
|
|
336
|
+
const dcRouter = this.opsServerRef.dcRouterRef;
|
|
337
|
+
const cleanDomain = domain.replace(/^\*\.?/, '');
|
|
338
|
+
// Try SmartAcme /certs/ path first (has full ICert fields)
|
|
339
|
+
let certData = await dcRouter.storageManager.getJSON(`/certs/${cleanDomain}`);
|
|
340
|
+
if (certData && certData.publicKey && certData.privateKey) {
|
|
341
|
+
return {
|
|
342
|
+
success: true,
|
|
343
|
+
cert: {
|
|
344
|
+
id: certData.id || plugins.crypto.randomUUID(),
|
|
345
|
+
domainName: certData.domainName || domain,
|
|
346
|
+
created: certData.created || Date.now(),
|
|
347
|
+
validUntil: certData.validUntil || 0,
|
|
348
|
+
privateKey: certData.privateKey,
|
|
349
|
+
publicKey: certData.publicKey,
|
|
350
|
+
csr: certData.csr || '',
|
|
351
|
+
},
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
// Fallback: try /proxy-certs/ with original domain
|
|
355
|
+
certData = await dcRouter.storageManager.getJSON(`/proxy-certs/${domain}`);
|
|
356
|
+
if (!certData || !certData.publicKey) {
|
|
357
|
+
// Try with clean domain
|
|
358
|
+
certData = await dcRouter.storageManager.getJSON(`/proxy-certs/${cleanDomain}`);
|
|
359
|
+
}
|
|
360
|
+
if (certData && certData.publicKey && certData.privateKey) {
|
|
361
|
+
return {
|
|
362
|
+
success: true,
|
|
363
|
+
cert: {
|
|
364
|
+
id: plugins.crypto.randomUUID(),
|
|
365
|
+
domainName: domain,
|
|
366
|
+
created: certData.validFrom || Date.now(),
|
|
367
|
+
validUntil: certData.validUntil || 0,
|
|
368
|
+
privateKey: certData.privateKey,
|
|
369
|
+
publicKey: certData.publicKey,
|
|
370
|
+
csr: '',
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
return { success: false, message: `No certificate data found for '${domain}'` };
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Import a certificate from ICert-shaped JSON
|
|
378
|
+
*/
|
|
379
|
+
async importCertificate(cert) {
|
|
380
|
+
// Validate PEM content
|
|
381
|
+
if (!cert.publicKey || !cert.publicKey.includes('-----BEGIN CERTIFICATE-----')) {
|
|
382
|
+
return { success: false, message: 'Invalid publicKey: must contain a PEM-encoded certificate' };
|
|
383
|
+
}
|
|
384
|
+
if (!cert.privateKey || !cert.privateKey.includes('-----BEGIN')) {
|
|
385
|
+
return { success: false, message: 'Invalid privateKey: must contain a PEM-encoded key' };
|
|
386
|
+
}
|
|
387
|
+
const dcRouter = this.opsServerRef.dcRouterRef;
|
|
388
|
+
const cleanDomain = cert.domainName.replace(/^\*\.?/, '');
|
|
389
|
+
// Save to /certs/ (SmartAcme-compatible path)
|
|
390
|
+
await dcRouter.storageManager.setJSON(`/certs/${cleanDomain}`, {
|
|
391
|
+
id: cert.id,
|
|
392
|
+
domainName: cert.domainName,
|
|
393
|
+
created: cert.created,
|
|
394
|
+
validUntil: cert.validUntil,
|
|
395
|
+
privateKey: cert.privateKey,
|
|
396
|
+
publicKey: cert.publicKey,
|
|
397
|
+
csr: cert.csr || '',
|
|
398
|
+
});
|
|
399
|
+
// Also save to /proxy-certs/ (proxy-cert format)
|
|
400
|
+
await dcRouter.storageManager.setJSON(`/proxy-certs/${cert.domainName}`, {
|
|
401
|
+
domain: cert.domainName,
|
|
402
|
+
publicKey: cert.publicKey,
|
|
403
|
+
privateKey: cert.privateKey,
|
|
404
|
+
ca: undefined,
|
|
405
|
+
validUntil: cert.validUntil,
|
|
406
|
+
validFrom: cert.created,
|
|
407
|
+
});
|
|
408
|
+
// Update in-memory status map
|
|
409
|
+
dcRouter.certificateStatusMap.set(cert.domainName, {
|
|
410
|
+
status: 'valid',
|
|
411
|
+
source: 'static',
|
|
412
|
+
expiryDate: cert.validUntil ? new Date(cert.validUntil).toISOString() : undefined,
|
|
413
|
+
issuedAt: cert.created ? new Date(cert.created).toISOString() : undefined,
|
|
414
|
+
routeNames: [],
|
|
415
|
+
});
|
|
416
|
+
return { success: true, message: `Certificate imported for '${cert.domainName}'` };
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2VydGlmaWNhdGUuaGFuZGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzL29wc3NlcnZlci9oYW5kbGVycy9jZXJ0aWZpY2F0ZS5oYW5kbGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFFNUMsT0FBTyxLQUFLLFVBQVUsTUFBTSxpQ0FBaUMsQ0FBQztBQUU5RCxNQUFNLE9BQU8sa0JBQWtCO0lBR1Q7SUFGYixXQUFXLEdBQUcsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBRTVELFlBQW9CLFlBQXVCO1FBQXZCLGlCQUFZLEdBQVosWUFBWSxDQUFXO1FBQ3pDLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDL0QsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVPLGdCQUFnQjtRQUN0QiwyQkFBMkI7UUFDM0IsSUFBSSxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQzlCLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQ25DLHdCQUF3QixFQUN4QixLQUFLLEVBQUUsT0FBTyxFQUFFLEVBQUU7WUFDaEIsTUFBTSxZQUFZLEdBQUcsTUFBTSxJQUFJLENBQUMsd0JBQXdCLEVBQUUsQ0FBQztZQUMzRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FBQyxDQUFDO1lBQ2hELE9BQU8sRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDbkMsQ0FBQyxDQUNGLENBQ0YsQ0FBQztRQUVGLG1EQUFtRDtRQUNuRCxJQUFJLENBQUMsV0FBVyxDQUFDLGVBQWUsQ0FDOUIsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLFlBQVksQ0FDbkMsd0JBQXdCLEVBQ3hCLEtBQUssRUFBRSxPQUFPLEVB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
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import type { OpsServer } from '../classes.opsserver.js';
|
|
3
|
+
export declare class ConfigHandler {
|
|
4
|
+
private opsServerRef;
|
|
5
|
+
typedrouter: plugins.typedrequest.TypedRouter;
|
|
6
|
+
constructor(opsServerRef: OpsServer);
|
|
7
|
+
private registerHandlers;
|
|
8
|
+
private getConfiguration;
|
|
9
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import * as paths from '../../paths.js';
|
|
3
|
+
import * as interfaces from '../../../dist_ts_interfaces/index.js';
|
|
4
|
+
export class ConfigHandler {
|
|
5
|
+
opsServerRef;
|
|
6
|
+
typedrouter = new plugins.typedrequest.TypedRouter();
|
|
7
|
+
constructor(opsServerRef) {
|
|
8
|
+
this.opsServerRef = opsServerRef;
|
|
9
|
+
// Add this handler's router to the parent
|
|
10
|
+
this.opsServerRef.typedrouter.addTypedRouter(this.typedrouter);
|
|
11
|
+
this.registerHandlers();
|
|
12
|
+
}
|
|
13
|
+
registerHandlers() {
|
|
14
|
+
// Get Configuration Handler (read-only)
|
|
15
|
+
this.typedrouter.addTypedHandler(new plugins.typedrequest.TypedHandler('getConfiguration', async (dataArg, toolsArg) => {
|
|
16
|
+
const config = await this.getConfiguration();
|
|
17
|
+
return {
|
|
18
|
+
config,
|
|
19
|
+
section: dataArg.section,
|
|
20
|
+
};
|
|
21
|
+
}));
|
|
22
|
+
}
|
|
23
|
+
async getConfiguration() {
|
|
24
|
+
const dcRouter = this.opsServerRef.dcRouterRef;
|
|
25
|
+
const opts = dcRouter.options;
|
|
26
|
+
const resolvedPaths = dcRouter.resolvedPaths;
|
|
27
|
+
// --- System ---
|
|
28
|
+
const storageBackend = opts.storage?.readFunction
|
|
29
|
+
? 'custom'
|
|
30
|
+
: opts.storage?.fsPath
|
|
31
|
+
? 'filesystem'
|
|
32
|
+
: 'memory';
|
|
33
|
+
const system = {
|
|
34
|
+
baseDir: resolvedPaths.dcrouterHomeDir,
|
|
35
|
+
dataDir: resolvedPaths.dataDir,
|
|
36
|
+
publicIp: opts.publicIp || null,
|
|
37
|
+
proxyIps: opts.proxyIps || [],
|
|
38
|
+
uptime: Math.floor(process.uptime()),
|
|
39
|
+
storageBackend,
|
|
40
|
+
storagePath: opts.storage?.fsPath || null,
|
|
41
|
+
};
|
|
42
|
+
// --- SmartProxy ---
|
|
43
|
+
let acmeInfo = null;
|
|
44
|
+
if (opts.smartProxyConfig?.acme) {
|
|
45
|
+
const acme = opts.smartProxyConfig.acme;
|
|
46
|
+
acmeInfo = {
|
|
47
|
+
enabled: acme.enabled !== false,
|
|
48
|
+
accountEmail: acme.accountEmail || '',
|
|
49
|
+
useProduction: acme.useProduction !== false,
|
|
50
|
+
autoRenew: acme.autoRenew !== false,
|
|
51
|
+
renewThresholdDays: acme.renewThresholdDays || 30,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
let routeCount = 0;
|
|
55
|
+
if (dcRouter.routeConfigManager) {
|
|
56
|
+
try {
|
|
57
|
+
const merged = await dcRouter.routeConfigManager.getMergedRoutes();
|
|
58
|
+
routeCount = merged.routes.length;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
routeCount = opts.smartProxyConfig?.routes?.length || 0;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else if (opts.smartProxyConfig?.routes) {
|
|
65
|
+
routeCount = opts.smartProxyConfig.routes.length;
|
|
66
|
+
}
|
|
67
|
+
const smartProxy = {
|
|
68
|
+
enabled: !!dcRouter.smartProxy,
|
|
69
|
+
routeCount,
|
|
70
|
+
acme: acmeInfo,
|
|
71
|
+
};
|
|
72
|
+
// --- Email ---
|
|
73
|
+
let emailDomains = [];
|
|
74
|
+
if (dcRouter.emailServer && dcRouter.emailServer.domainRegistry) {
|
|
75
|
+
emailDomains = dcRouter.emailServer.domainRegistry.getAllDomains();
|
|
76
|
+
}
|
|
77
|
+
else if (opts.emailConfig?.domains) {
|
|
78
|
+
emailDomains = opts.emailConfig.domains.map((d) => typeof d === 'string' ? d : d.domain);
|
|
79
|
+
}
|
|
80
|
+
let portMapping = null;
|
|
81
|
+
if (opts.emailPortConfig?.portMapping) {
|
|
82
|
+
portMapping = {};
|
|
83
|
+
for (const [ext, int] of Object.entries(opts.emailPortConfig.portMapping)) {
|
|
84
|
+
portMapping[String(ext)] = int;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const email = {
|
|
88
|
+
enabled: !!dcRouter.emailServer,
|
|
89
|
+
ports: opts.emailConfig?.ports || [],
|
|
90
|
+
portMapping,
|
|
91
|
+
hostname: opts.emailConfig?.hostname || null,
|
|
92
|
+
domains: emailDomains,
|
|
93
|
+
emailRouteCount: opts.emailConfig?.routes?.length || 0,
|
|
94
|
+
receivedEmailsPath: opts.emailPortConfig?.receivedEmailsPath || null,
|
|
95
|
+
};
|
|
96
|
+
// --- DNS ---
|
|
97
|
+
const dnsRecords = (opts.dnsRecords || []).map(r => ({
|
|
98
|
+
name: r.name,
|
|
99
|
+
type: r.type,
|
|
100
|
+
value: r.value,
|
|
101
|
+
ttl: r.ttl,
|
|
102
|
+
}));
|
|
103
|
+
const dns = {
|
|
104
|
+
enabled: !!dcRouter.dnsServer,
|
|
105
|
+
port: 53,
|
|
106
|
+
nsDomains: opts.dnsNsDomains || [],
|
|
107
|
+
scopes: opts.dnsScopes || [],
|
|
108
|
+
recordCount: dnsRecords.length,
|
|
109
|
+
records: dnsRecords,
|
|
110
|
+
dnsChallenge: !!opts.dnsChallenge?.cloudflareApiKey,
|
|
111
|
+
};
|
|
112
|
+
// --- TLS ---
|
|
113
|
+
let tlsSource = 'none';
|
|
114
|
+
if (opts.tls?.certPath && opts.tls?.keyPath) {
|
|
115
|
+
tlsSource = 'static';
|
|
116
|
+
}
|
|
117
|
+
else if (opts.smartProxyConfig?.acme?.enabled !== false && opts.smartProxyConfig?.acme) {
|
|
118
|
+
tlsSource = 'acme';
|
|
119
|
+
}
|
|
120
|
+
const tls = {
|
|
121
|
+
contactEmail: opts.tls?.contactEmail || opts.smartProxyConfig?.acme?.accountEmail || null,
|
|
122
|
+
domain: opts.tls?.domain || null,
|
|
123
|
+
source: tlsSource,
|
|
124
|
+
certPath: opts.tls?.certPath || null,
|
|
125
|
+
keyPath: opts.tls?.keyPath || null,
|
|
126
|
+
};
|
|
127
|
+
// --- Cache ---
|
|
128
|
+
const cacheConfig = opts.cacheConfig;
|
|
129
|
+
const cache = {
|
|
130
|
+
enabled: cacheConfig?.enabled !== false,
|
|
131
|
+
storagePath: cacheConfig?.storagePath || resolvedPaths.defaultTsmDbPath,
|
|
132
|
+
dbName: cacheConfig?.dbName || 'dcrouter',
|
|
133
|
+
defaultTTLDays: cacheConfig?.defaultTTLDays || 30,
|
|
134
|
+
cleanupIntervalHours: cacheConfig?.cleanupIntervalHours || 1,
|
|
135
|
+
ttlConfig: cacheConfig?.ttlConfig ? { ...cacheConfig.ttlConfig } : {},
|
|
136
|
+
};
|
|
137
|
+
// --- RADIUS ---
|
|
138
|
+
const radiusCfg = opts.radiusConfig;
|
|
139
|
+
const radius = {
|
|
140
|
+
enabled: !!dcRouter.radiusServer,
|
|
141
|
+
authPort: radiusCfg?.authPort || null,
|
|
142
|
+
acctPort: radiusCfg?.acctPort || null,
|
|
143
|
+
bindAddress: radiusCfg?.bindAddress || null,
|
|
144
|
+
clientCount: radiusCfg?.clients?.length || 0,
|
|
145
|
+
vlanDefaultVlan: radiusCfg?.vlanAssignment?.defaultVlan ?? null,
|
|
146
|
+
vlanAllowUnknownMacs: radiusCfg?.vlanAssignment?.allowUnknownMacs ?? null,
|
|
147
|
+
vlanMappingCount: radiusCfg?.vlanAssignment?.mappings?.length || 0,
|
|
148
|
+
};
|
|
149
|
+
// --- Remote Ingress ---
|
|
150
|
+
const riCfg = opts.remoteIngressConfig;
|
|
151
|
+
const remoteIngress = {
|
|
152
|
+
enabled: !!dcRouter.remoteIngressManager,
|
|
153
|
+
tunnelPort: riCfg?.tunnelPort || null,
|
|
154
|
+
hubDomain: riCfg?.hubDomain || null,
|
|
155
|
+
tlsConfigured: !!(riCfg?.tls?.certPath && riCfg?.tls?.keyPath),
|
|
156
|
+
};
|
|
157
|
+
return {
|
|
158
|
+
system,
|
|
159
|
+
smartProxy,
|
|
160
|
+
email,
|
|
161
|
+
dns,
|
|
162
|
+
tls,
|
|
163
|
+
cache,
|
|
164
|
+
radius,
|
|
165
|
+
remoteIngress,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmhhbmRsZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90cy9vcHNzZXJ2ZXIvaGFuZGxlcnMvY29uZmlnLmhhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUM1QyxPQUFPLEtBQUssS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBRXhDLE9BQU8sS0FBSyxVQUFVLE1BQU0saUNBQWlDLENBQUM7QUFFOUQsTUFBTSxPQUFPLGFBQWE7SUFHSjtJQUZiLFdBQVcsR0FBRyxJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsV0FBVyxFQUFFLENBQUM7SUFFNUQsWUFBb0IsWUFBdUI7UUFBdkIsaUJBQVksR0FBWixZQUFZLENBQVc7UUFDekMsMENBQTBDO1FBQzFDLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7UUFDL0QsSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7SUFDMUIsQ0FBQztJQUVPLGdCQUFnQjtRQUN0Qix3Q0FBd0M7UUFDeEMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxlQUFlLENBQzlCLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQ25DLGtCQUFrQixFQUNsQixLQUFLLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxFQUFFO1lBQzFCLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUM7WUFDN0MsT0FBTztnQkFDTCxNQUFNO2dCQUNOLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTzthQUN6QixDQUFDO1FBQ0osQ0FBQyxDQUNGLENBQ0YsQ0FBQztJQUNKLENBQUM7SUFFTyxLQUFLLENBQUMsZ0JBQWdCO1FBQzVCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsV0FBVyxDQUFDO1FBQy9DLE1BQU0sSUFBSSxH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
|