@serve.zone/dcrouter 13.27.1 → 13.28.0
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 +913 -799
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dcrouter.d.ts +2 -1
- package/dist_ts/classes.dcrouter.js +11 -6
- package/dist_ts/config/classes.gateway-client-manager.d.ts +22 -0
- package/dist_ts/config/classes.gateway-client-manager.js +101 -0
- package/dist_ts/config/index.d.ts +1 -0
- package/dist_ts/config/index.js +2 -1
- package/dist_ts/db/documents/classes.gateway-client.doc.d.ts +18 -0
- package/dist_ts/db/documents/classes.gateway-client.doc.js +133 -0
- package/dist_ts/db/documents/index.d.ts +1 -0
- package/dist_ts/db/documents/index.js +2 -1
- package/dist_ts/opsserver/handlers/certificate.handler.js +5 -1
- package/dist_ts/opsserver/handlers/workhoster.handler.d.ts +4 -0
- package/dist_ts/opsserver/handlers/workhoster.handler.js +146 -16
- package/dist_ts_apiclient/classes.workhoster.d.ts +1 -0
- package/dist_ts_apiclient/classes.workhoster.js +5 -1
- package/dist_ts_interfaces/data/workhoster.d.ts +28 -3
- package/dist_ts_interfaces/requests/workhoster.d.ts +83 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/appstate.d.ts +29 -0
- package/dist_ts_web/appstate.js +79 -1
- package/dist_ts_web/elements/access/ops-view-apitokens.js +2 -1
- package/dist_ts_web/elements/access/ops-view-gatewayclients.d.ts +15 -0
- package/dist_ts_web/elements/access/ops-view-gatewayclients.js +293 -0
- package/dist_ts_web/elements/domains/ops-view-certificates.d.ts +6 -0
- package/dist_ts_web/elements/domains/ops-view-certificates.js +155 -13
- package/dist_ts_web/elements/network/ops-view-routes.js +2 -1
- package/dist_ts_web/elements/ops-dashboard.js +3 -1
- package/dist_ts_web/router.js +3 -3
- package/package.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dcrouter.ts +10 -5
- package/ts/config/classes.gateway-client-manager.ts +117 -0
- package/ts/config/index.ts +2 -1
- package/ts/db/documents/classes.gateway-client.doc.ts +54 -0
- package/ts/db/documents/index.ts +1 -0
- package/ts/opsserver/handlers/certificate.handler.ts +5 -0
- package/ts/opsserver/handlers/workhoster.handler.ts +191 -17
- package/ts_apiclient/classes.workhoster.ts +8 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/appstate.ts +111 -0
- package/ts_web/elements/access/ops-view-apitokens.ts +1 -0
- package/ts_web/elements/access/ops-view-gatewayclients.ts +250 -0
- package/ts_web/elements/domains/ops-view-certificates.ts +166 -11
- package/ts_web/elements/network/ops-view-routes.ts +1 -0
- package/ts_web/elements/ops-dashboard.ts +2 -0
- package/ts_web/router.ts +2 -2
package/dist_ts_web/router.js
CHANGED
|
@@ -8,7 +8,7 @@ const subviewMap = {
|
|
|
8
8
|
overview: ['stats', 'configuration'],
|
|
9
9
|
network: ['activity', 'routes', 'sourceprofiles', 'networktargets', 'targetprofiles', 'remoteingress', 'vpn'],
|
|
10
10
|
email: ['log', 'security', 'domains'],
|
|
11
|
-
access: ['apitokens', 'users'],
|
|
11
|
+
access: ['gatewayclients', 'apitokens', 'users'],
|
|
12
12
|
security: ['overview', 'blocked', 'authentication'],
|
|
13
13
|
domains: ['providers', 'domains', 'dns', 'certificates'],
|
|
14
14
|
};
|
|
@@ -17,7 +17,7 @@ const defaultSubview = {
|
|
|
17
17
|
overview: 'stats',
|
|
18
18
|
network: 'activity',
|
|
19
19
|
email: 'log',
|
|
20
|
-
access: '
|
|
20
|
+
access: 'gatewayclients',
|
|
21
21
|
security: 'overview',
|
|
22
22
|
domains: 'domains',
|
|
23
23
|
};
|
|
@@ -148,4 +148,4 @@ class AppRouter {
|
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
export const appRouter = new AppRouter();
|
|
151
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
151
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfd2ViL3JvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEtBQUssUUFBUSxNQUFNLGVBQWUsQ0FBQztBQUUxQyxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDO0FBRXJFLHFDQUFxQztBQUNyQyxNQUFNLFNBQVMsR0FBRyxDQUFDLE1BQU0sQ0FBVSxDQUFDO0FBRXBDLHdDQUF3QztBQUN4QyxNQUFNLFVBQVUsR0FBc0M7SUFDcEQsUUFBUSxFQUFFLENBQUMsT0FBTyxFQUFFLGVBQWUsQ0FBVTtJQUM3QyxPQUFPLEVBQUUsQ0FBQyxVQUFVLEVBQUUsUUFBUSxFQUFFLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLGVBQWUsRUFBRSxLQUFLLENBQVU7SUFDdEgsS0FBSyxFQUFFLENBQUMsS0FBSyxFQUFFLFVBQVUsRUFBRSxTQUFTLENBQVU7SUFDOUMsTUFBTSxFQUFFLENBQUMsZ0JBQWdCLEVBQUUsV0FBVyxFQUFFLE9BQU8sQ0FBVTtJQUN6RCxRQUFRLEVBQUUsQ0FBQyxVQUFVLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixDQUFVO0lBQzVELE9BQU8sRUFBRSxDQUFDLFdBQVcsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLGNBQWMsQ0FBVTtDQUNsRSxDQUFDO0FBRUYsdURBQXVEO0FBQ3ZELE1BQU0sY0FBYyxHQUEyQjtJQUM3QyxRQUFRLEVBQUUsT0FBTztJQUNqQixPQUFPLEVBQUUsVUFBVTtJQUNuQixLQUFLLEVBQUUsS0FBSztJQUNaLE1BQU0sRUFBRSxnQkFBZ0I7SUFDeEIsUUFBUSxFQUFFLFVBQVU7SUFDcEIsT0FBTyxFQUFFLFNBQVM7Q0FDbkIsQ0FBQztBQUVGLE1BQU0sQ0FBQyxNQUFNLGtC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
|
package/package.json
CHANGED
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/classes.dcrouter.ts
CHANGED
|
@@ -25,7 +25,7 @@ import { MetricsManager } from './monitoring/index.js';
|
|
|
25
25
|
import { RadiusServer, type IRadiusServerConfig } from './radius/index.js';
|
|
26
26
|
import { RemoteIngressManager, TunnelManager } from './remoteingress/index.js';
|
|
27
27
|
import { VpnManager, type IVpnManagerConfig } from './vpn/index.js';
|
|
28
|
-
import { RouteConfigManager, ApiTokenManager, ReferenceResolver, DbSeeder, TargetProfileManager } from './config/index.js';
|
|
28
|
+
import { RouteConfigManager, ApiTokenManager, GatewayClientManager, ReferenceResolver, DbSeeder, TargetProfileManager } from './config/index.js';
|
|
29
29
|
import type { TIpAllowEntry } from './config/classes.route-config-manager.js';
|
|
30
30
|
import { SecurityLogger, ContentScanner, IPReputationChecker, SecurityPolicyManager } from './security/index.js';
|
|
31
31
|
import { type IHttp3Config, augmentRoutesWithHttp3 } from './http3/index.js';
|
|
@@ -276,6 +276,7 @@ export class DcRouter {
|
|
|
276
276
|
// Programmatic config API
|
|
277
277
|
public routeConfigManager?: RouteConfigManager;
|
|
278
278
|
public apiTokenManager?: ApiTokenManager;
|
|
279
|
+
public gatewayClientManager?: GatewayClientManager;
|
|
279
280
|
public referenceResolver?: ReferenceResolver;
|
|
280
281
|
public targetProfileManager?: TargetProfileManager;
|
|
281
282
|
|
|
@@ -617,6 +618,8 @@ export class DcRouter {
|
|
|
617
618
|
);
|
|
618
619
|
this.apiTokenManager = new ApiTokenManager();
|
|
619
620
|
await this.apiTokenManager.initialize();
|
|
621
|
+
this.gatewayClientManager = new GatewayClientManager();
|
|
622
|
+
await this.gatewayClientManager.initialize();
|
|
620
623
|
await this.routeConfigManager.initialize(
|
|
621
624
|
this.seedConfigRoutes as import('../ts_interfaces/data/remoteingress.js').IDcRouterRouteConfig[],
|
|
622
625
|
this.seedEmailRoutes as import('../ts_interfaces/data/remoteingress.js').IDcRouterRouteConfig[],
|
|
@@ -634,6 +637,7 @@ export class DcRouter {
|
|
|
634
637
|
.withStop(async () => {
|
|
635
638
|
this.routeConfigManager = undefined;
|
|
636
639
|
this.apiTokenManager = undefined;
|
|
640
|
+
this.gatewayClientManager = undefined;
|
|
637
641
|
this.referenceResolver = undefined;
|
|
638
642
|
this.targetProfileManager = undefined;
|
|
639
643
|
})
|
|
@@ -1101,6 +1105,7 @@ export class DcRouter {
|
|
|
1101
1105
|
});
|
|
1102
1106
|
|
|
1103
1107
|
const scheduler = this.certProvisionScheduler;
|
|
1108
|
+
smartProxyConfig.certProvisionFallbackToAcme = false;
|
|
1104
1109
|
smartProxyConfig.certProvisionFunction = async (domain, eventComms) => {
|
|
1105
1110
|
// If SmartAcme is not yet ready (still starting or retrying), fall back to HTTP-01
|
|
1106
1111
|
if (!this.smartAcmeReady) {
|
|
@@ -1149,10 +1154,10 @@ export class DcRouter {
|
|
|
1149
1154
|
await scheduler.clearBackoff(domain);
|
|
1150
1155
|
return result;
|
|
1151
1156
|
} catch (err: unknown) {
|
|
1152
|
-
|
|
1153
|
-
await scheduler.recordFailure(domain,
|
|
1154
|
-
eventComms.warn(
|
|
1155
|
-
|
|
1157
|
+
const message = `DNS-01 failed for ${domain}: ${(err as Error).message}`;
|
|
1158
|
+
await scheduler.recordFailure(domain, message);
|
|
1159
|
+
eventComms.warn(message);
|
|
1160
|
+
throw new Error(message);
|
|
1156
1161
|
}
|
|
1157
1162
|
};
|
|
1158
1163
|
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import { GatewayClientDoc } from '../db/index.js';
|
|
3
|
+
import type { IGatewayClient } from '../../ts_interfaces/data/workhoster.js';
|
|
4
|
+
|
|
5
|
+
const defaultCapabilities: IGatewayClient['capabilities'] = {
|
|
6
|
+
readDomains: true,
|
|
7
|
+
readDnsRecords: true,
|
|
8
|
+
syncRoutes: true,
|
|
9
|
+
syncDnsRecords: false,
|
|
10
|
+
requestCertificates: false,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export class GatewayClientManager {
|
|
14
|
+
public async initialize(): Promise<void> {}
|
|
15
|
+
|
|
16
|
+
public async listClients(): Promise<IGatewayClient[]> {
|
|
17
|
+
const docs = await GatewayClientDoc.findAll();
|
|
18
|
+
return docs.map((doc) => this.toPublicClient(doc));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public async getClient(id: string): Promise<IGatewayClient | null> {
|
|
22
|
+
const doc = await GatewayClientDoc.findById(id);
|
|
23
|
+
return doc ? this.toPublicClient(doc) : null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
public async createClient(options: {
|
|
27
|
+
id?: string;
|
|
28
|
+
type: IGatewayClient['type'];
|
|
29
|
+
name: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
hostnamePatterns?: string[];
|
|
32
|
+
allowedRouteTargets?: IGatewayClient['allowedRouteTargets'];
|
|
33
|
+
capabilities?: IGatewayClient['capabilities'];
|
|
34
|
+
createdBy: string;
|
|
35
|
+
}): Promise<IGatewayClient> {
|
|
36
|
+
const id = this.normalizeId(options.id || `${options.type}-${plugins.uuid.v4()}`);
|
|
37
|
+
if (!id) {
|
|
38
|
+
throw new Error('gateway client id is required');
|
|
39
|
+
}
|
|
40
|
+
if (await GatewayClientDoc.findById(id)) {
|
|
41
|
+
throw new Error('gateway client already exists');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const now = Date.now();
|
|
45
|
+
const doc = new GatewayClientDoc();
|
|
46
|
+
doc.id = id;
|
|
47
|
+
doc.type = options.type;
|
|
48
|
+
doc.name = options.name.trim();
|
|
49
|
+
doc.description = options.description?.trim() || undefined;
|
|
50
|
+
doc.hostnamePatterns = this.normalizeStringList(options.hostnamePatterns || []);
|
|
51
|
+
doc.allowedRouteTargets = this.normalizeAllowedRouteTargets(options.allowedRouteTargets || []);
|
|
52
|
+
doc.capabilities = { ...defaultCapabilities, ...(options.capabilities || {}) };
|
|
53
|
+
doc.enabled = true;
|
|
54
|
+
doc.createdAt = now;
|
|
55
|
+
doc.updatedAt = now;
|
|
56
|
+
doc.createdBy = options.createdBy;
|
|
57
|
+
await doc.save();
|
|
58
|
+
return this.toPublicClient(doc);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
public async updateClient(
|
|
62
|
+
id: string,
|
|
63
|
+
patch: Partial<Pick<IGatewayClient, 'name' | 'description' | 'hostnamePatterns' | 'allowedRouteTargets' | 'capabilities' | 'enabled'>>,
|
|
64
|
+
): Promise<IGatewayClient | null> {
|
|
65
|
+
const doc = await GatewayClientDoc.findById(id);
|
|
66
|
+
if (!doc) return null;
|
|
67
|
+
if (patch.name !== undefined) doc.name = patch.name.trim();
|
|
68
|
+
if (patch.description !== undefined) doc.description = patch.description.trim() || undefined;
|
|
69
|
+
if (patch.hostnamePatterns !== undefined) doc.hostnamePatterns = this.normalizeStringList(patch.hostnamePatterns);
|
|
70
|
+
if (patch.allowedRouteTargets !== undefined) doc.allowedRouteTargets = this.normalizeAllowedRouteTargets(patch.allowedRouteTargets);
|
|
71
|
+
if (patch.capabilities !== undefined) doc.capabilities = { ...defaultCapabilities, ...patch.capabilities };
|
|
72
|
+
if (patch.enabled !== undefined) doc.enabled = patch.enabled;
|
|
73
|
+
doc.updatedAt = Date.now();
|
|
74
|
+
await doc.save();
|
|
75
|
+
return this.toPublicClient(doc);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public async deleteClient(id: string): Promise<boolean> {
|
|
79
|
+
const doc = await GatewayClientDoc.findById(id);
|
|
80
|
+
if (!doc) return false;
|
|
81
|
+
await doc.delete();
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private normalizeId(id: string): string {
|
|
86
|
+
return id.trim().toLowerCase().replace(/[^a-z0-9._-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private normalizeStringList(values: string[]): string[] {
|
|
90
|
+
return values.map((value) => value.trim().toLowerCase()).filter(Boolean);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private normalizeAllowedRouteTargets(targets: IGatewayClient['allowedRouteTargets']): IGatewayClient['allowedRouteTargets'] {
|
|
94
|
+
return targets
|
|
95
|
+
.map((target) => ({
|
|
96
|
+
host: target.host.trim().toLowerCase(),
|
|
97
|
+
ports: target.ports.filter((port) => Number.isInteger(port) && port > 0 && port <= 65535),
|
|
98
|
+
}))
|
|
99
|
+
.filter((target) => target.host && target.ports.length > 0);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
private toPublicClient(doc: GatewayClientDoc): IGatewayClient {
|
|
103
|
+
return {
|
|
104
|
+
id: doc.id,
|
|
105
|
+
type: doc.type,
|
|
106
|
+
name: doc.name,
|
|
107
|
+
description: doc.description,
|
|
108
|
+
hostnamePatterns: doc.hostnamePatterns || [],
|
|
109
|
+
allowedRouteTargets: doc.allowedRouteTargets || [],
|
|
110
|
+
capabilities: doc.capabilities || {},
|
|
111
|
+
enabled: doc.enabled,
|
|
112
|
+
createdAt: doc.createdAt,
|
|
113
|
+
updatedAt: doc.updatedAt,
|
|
114
|
+
createdBy: doc.createdBy,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
package/ts/config/index.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
export * from './validator.js';
|
|
3
3
|
export { RouteConfigManager } from './classes.route-config-manager.js';
|
|
4
4
|
export { ApiTokenManager } from './classes.api-token-manager.js';
|
|
5
|
+
export { GatewayClientManager } from './classes.gateway-client-manager.js';
|
|
5
6
|
export { ReferenceResolver } from './classes.reference-resolver.js';
|
|
6
7
|
export { DbSeeder } from './classes.db-seeder.js';
|
|
7
|
-
export { TargetProfileManager } from './classes.target-profile-manager.js';
|
|
8
|
+
export { TargetProfileManager } from './classes.target-profile-manager.js';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import * as plugins from '../../plugins.js';
|
|
2
|
+
import { DcRouterDb } from '../classes.dcrouter-db.js';
|
|
3
|
+
import type { IApiTokenPolicy, TGatewayClientType } from '../../../ts_interfaces/data/route-management.js';
|
|
4
|
+
|
|
5
|
+
const getDb = () => DcRouterDb.getInstance().getDb();
|
|
6
|
+
|
|
7
|
+
@plugins.smartdata.Collection(() => getDb())
|
|
8
|
+
export class GatewayClientDoc extends plugins.smartdata.SmartDataDbDoc<GatewayClientDoc, GatewayClientDoc> {
|
|
9
|
+
@plugins.smartdata.unI()
|
|
10
|
+
@plugins.smartdata.svDb()
|
|
11
|
+
public id!: string;
|
|
12
|
+
|
|
13
|
+
@plugins.smartdata.svDb()
|
|
14
|
+
public type!: TGatewayClientType;
|
|
15
|
+
|
|
16
|
+
@plugins.smartdata.svDb()
|
|
17
|
+
public name: string = '';
|
|
18
|
+
|
|
19
|
+
@plugins.smartdata.svDb()
|
|
20
|
+
public description?: string;
|
|
21
|
+
|
|
22
|
+
@plugins.smartdata.svDb()
|
|
23
|
+
public hostnamePatterns: string[] = [];
|
|
24
|
+
|
|
25
|
+
@plugins.smartdata.svDb()
|
|
26
|
+
public allowedRouteTargets: NonNullable<IApiTokenPolicy['allowedRouteTargets']> = [];
|
|
27
|
+
|
|
28
|
+
@plugins.smartdata.svDb()
|
|
29
|
+
public capabilities: NonNullable<IApiTokenPolicy['capabilities']> = {};
|
|
30
|
+
|
|
31
|
+
@plugins.smartdata.svDb()
|
|
32
|
+
public enabled: boolean = true;
|
|
33
|
+
|
|
34
|
+
@plugins.smartdata.svDb()
|
|
35
|
+
public createdAt!: number;
|
|
36
|
+
|
|
37
|
+
@plugins.smartdata.svDb()
|
|
38
|
+
public updatedAt!: number;
|
|
39
|
+
|
|
40
|
+
@plugins.smartdata.svDb()
|
|
41
|
+
public createdBy!: string;
|
|
42
|
+
|
|
43
|
+
constructor() {
|
|
44
|
+
super();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public static async findById(id: string): Promise<GatewayClientDoc | null> {
|
|
48
|
+
return await GatewayClientDoc.getInstance({ id });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public static async findAll(): Promise<GatewayClientDoc[]> {
|
|
52
|
+
return await GatewayClientDoc.getInstances({});
|
|
53
|
+
}
|
|
54
|
+
}
|
package/ts/db/documents/index.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from './classes.security-policy-audit.doc.js';
|
|
|
8
8
|
// Config document classes
|
|
9
9
|
export * from './classes.route.doc.js';
|
|
10
10
|
export * from './classes.api-token.doc.js';
|
|
11
|
+
export * from './classes.gateway-client.doc.js';
|
|
11
12
|
export * from './classes.source-profile.doc.js';
|
|
12
13
|
export * from './classes.target-profile.doc.js';
|
|
13
14
|
export * from './classes.network-target.doc.js';
|
|
@@ -307,6 +307,11 @@ export class CertificateHandler {
|
|
|
307
307
|
}
|
|
308
308
|
}
|
|
309
309
|
|
|
310
|
+
if (backoffInfo && status !== 'valid' && status !== 'expiring') {
|
|
311
|
+
status = 'failed';
|
|
312
|
+
error = error || backoffInfo.lastError;
|
|
313
|
+
}
|
|
314
|
+
|
|
310
315
|
certificates.push({
|
|
311
316
|
domain,
|
|
312
317
|
routeNames: info.routeNames,
|
|
@@ -45,6 +45,16 @@ export class WorkHosterHandler {
|
|
|
45
45
|
throw new plugins.typedrequest.TypedResponseError('unauthorized');
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
private async requireAdmin(request: { identity?: interfaces.data.IIdentity }): Promise<string> {
|
|
49
|
+
if (request.identity?.jwt) {
|
|
50
|
+
const isAdmin = await this.opsServerRef.adminHandler.adminIdentityGuard.exec({
|
|
51
|
+
identity: request.identity,
|
|
52
|
+
});
|
|
53
|
+
if (isAdmin) return request.identity.userId;
|
|
54
|
+
}
|
|
55
|
+
throw new plugins.typedrequest.TypedResponseError('admin identity required');
|
|
56
|
+
}
|
|
57
|
+
|
|
48
58
|
private registerHandlers(): void {
|
|
49
59
|
this.typedrouter.addTypedHandler(
|
|
50
60
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetGatewayCapabilities>(
|
|
@@ -56,6 +66,122 @@ export class WorkHosterHandler {
|
|
|
56
66
|
),
|
|
57
67
|
);
|
|
58
68
|
|
|
69
|
+
this.typedrouter.addTypedHandler(
|
|
70
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetGatewayClientContext>(
|
|
71
|
+
'getGatewayClientContext',
|
|
72
|
+
async (dataArg) => {
|
|
73
|
+
const auth = await this.requireAuth(dataArg, 'gateway-clients:read');
|
|
74
|
+
return {
|
|
75
|
+
context: this.getGatewayClientContext(auth),
|
|
76
|
+
capabilities: this.getGatewayCapabilities(),
|
|
77
|
+
};
|
|
78
|
+
},
|
|
79
|
+
),
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
this.typedrouter.addTypedHandler(
|
|
83
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_ListGatewayClients>(
|
|
84
|
+
'listGatewayClients',
|
|
85
|
+
async (dataArg) => {
|
|
86
|
+
await this.requireAdmin(dataArg);
|
|
87
|
+
return { gatewayClients: await this.listManagedGatewayClients() };
|
|
88
|
+
},
|
|
89
|
+
),
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
this.typedrouter.addTypedHandler(
|
|
93
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateGatewayClient>(
|
|
94
|
+
'createGatewayClient',
|
|
95
|
+
async (dataArg) => {
|
|
96
|
+
const userId = await this.requireAdmin(dataArg);
|
|
97
|
+
const manager = this.opsServerRef.dcRouterRef.gatewayClientManager;
|
|
98
|
+
if (!manager) return { success: false, message: 'Gateway client management not initialized' };
|
|
99
|
+
try {
|
|
100
|
+
const gatewayClient = await manager.createClient({
|
|
101
|
+
id: dataArg.id,
|
|
102
|
+
type: dataArg.type,
|
|
103
|
+
name: dataArg.name,
|
|
104
|
+
description: dataArg.description,
|
|
105
|
+
hostnamePatterns: dataArg.hostnamePatterns,
|
|
106
|
+
allowedRouteTargets: dataArg.allowedRouteTargets,
|
|
107
|
+
capabilities: dataArg.capabilities,
|
|
108
|
+
createdBy: userId,
|
|
109
|
+
});
|
|
110
|
+
return { success: true, gatewayClient };
|
|
111
|
+
} catch (error) {
|
|
112
|
+
return { success: false, message: (error as Error).message };
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
),
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
this.typedrouter.addTypedHandler(
|
|
119
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpdateGatewayClient>(
|
|
120
|
+
'updateGatewayClient',
|
|
121
|
+
async (dataArg) => {
|
|
122
|
+
await this.requireAdmin(dataArg);
|
|
123
|
+
const manager = this.opsServerRef.dcRouterRef.gatewayClientManager;
|
|
124
|
+
if (!manager) return { success: false, message: 'Gateway client management not initialized' };
|
|
125
|
+
const gatewayClient = await manager.updateClient(dataArg.id, {
|
|
126
|
+
name: dataArg.name,
|
|
127
|
+
description: dataArg.description,
|
|
128
|
+
hostnamePatterns: dataArg.hostnamePatterns,
|
|
129
|
+
allowedRouteTargets: dataArg.allowedRouteTargets,
|
|
130
|
+
capabilities: dataArg.capabilities,
|
|
131
|
+
enabled: dataArg.enabled,
|
|
132
|
+
});
|
|
133
|
+
return gatewayClient
|
|
134
|
+
? { success: true, gatewayClient }
|
|
135
|
+
: { success: false, message: 'Gateway client not found' };
|
|
136
|
+
},
|
|
137
|
+
),
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
this.typedrouter.addTypedHandler(
|
|
141
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_DeleteGatewayClient>(
|
|
142
|
+
'deleteGatewayClient',
|
|
143
|
+
async (dataArg) => {
|
|
144
|
+
await this.requireAdmin(dataArg);
|
|
145
|
+
const manager = this.opsServerRef.dcRouterRef.gatewayClientManager;
|
|
146
|
+
if (!manager) return { success: false, message: 'Gateway client management not initialized' };
|
|
147
|
+
const success = await manager.deleteClient(dataArg.id);
|
|
148
|
+
return { success, message: success ? undefined : 'Gateway client not found' };
|
|
149
|
+
},
|
|
150
|
+
),
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
this.typedrouter.addTypedHandler(
|
|
154
|
+
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_CreateGatewayClientToken>(
|
|
155
|
+
'createGatewayClientToken',
|
|
156
|
+
async (dataArg) => {
|
|
157
|
+
const userId = await this.requireAdmin(dataArg);
|
|
158
|
+
const gatewayClient = await this.opsServerRef.dcRouterRef.gatewayClientManager?.getClient(dataArg.gatewayClientId);
|
|
159
|
+
const tokenManager = this.opsServerRef.dcRouterRef.apiTokenManager;
|
|
160
|
+
if (!gatewayClient || !gatewayClient.enabled) {
|
|
161
|
+
return { success: false, message: 'Gateway client not found or disabled' };
|
|
162
|
+
}
|
|
163
|
+
if (!tokenManager) {
|
|
164
|
+
return { success: false, message: 'Token management not initialized' };
|
|
165
|
+
}
|
|
166
|
+
const result = await tokenManager.createToken(
|
|
167
|
+
dataArg.name?.trim() || `${gatewayClient.name} Token`,
|
|
168
|
+
['gateway-clients:read', 'gateway-clients:write'],
|
|
169
|
+
dataArg.expiresInDays ?? null,
|
|
170
|
+
userId,
|
|
171
|
+
{
|
|
172
|
+
role: 'gatewayClient',
|
|
173
|
+
scopes: ['gateway-clients:read', 'gateway-clients:write'],
|
|
174
|
+
gatewayClient: { type: gatewayClient.type, id: gatewayClient.id },
|
|
175
|
+
hostnamePatterns: gatewayClient.hostnamePatterns,
|
|
176
|
+
allowedRouteTargets: gatewayClient.allowedRouteTargets,
|
|
177
|
+
capabilities: gatewayClient.capabilities,
|
|
178
|
+
},
|
|
179
|
+
);
|
|
180
|
+
return { success: true, tokenId: result.id, tokenValue: result.rawToken };
|
|
181
|
+
},
|
|
182
|
+
),
|
|
183
|
+
);
|
|
184
|
+
|
|
59
185
|
this.typedrouter.addTypedHandler(
|
|
60
186
|
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetGatewayClientDomains>(
|
|
61
187
|
'getGatewayClientDomains',
|
|
@@ -183,6 +309,30 @@ export class WorkHosterHandler {
|
|
|
183
309
|
};
|
|
184
310
|
}
|
|
185
311
|
|
|
312
|
+
private getGatewayClientContext(auth: TAuthContext): interfaces.data.IGatewayClientContext {
|
|
313
|
+
const policy = auth.token?.policy;
|
|
314
|
+
const role = auth.isAdmin ? 'admin' : policy?.role || 'operator';
|
|
315
|
+
return {
|
|
316
|
+
role,
|
|
317
|
+
scopes: auth.token?.scopes || ['*'],
|
|
318
|
+
gatewayClient: policy?.gatewayClient,
|
|
319
|
+
hostnamePatterns: policy?.hostnamePatterns || [],
|
|
320
|
+
allowedRouteTargets: policy?.allowedRouteTargets || [],
|
|
321
|
+
capabilities: policy?.capabilities || {},
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
private async listManagedGatewayClients(): Promise<interfaces.data.IGatewayClient[]> {
|
|
326
|
+
const manager = this.opsServerRef.dcRouterRef.gatewayClientManager;
|
|
327
|
+
if (!manager) return [];
|
|
328
|
+
const clients = await manager.listClients();
|
|
329
|
+
const tokens = this.opsServerRef.dcRouterRef.apiTokenManager?.listTokens() || [];
|
|
330
|
+
return clients.map((client) => ({
|
|
331
|
+
...client,
|
|
332
|
+
tokenCount: tokens.filter((token) => token.policy?.gatewayClient?.id === client.id).length,
|
|
333
|
+
}));
|
|
334
|
+
}
|
|
335
|
+
|
|
186
336
|
private buildExternalKey(ownership: interfaces.data.IWorkAppRouteOwnership): string {
|
|
187
337
|
return [
|
|
188
338
|
ownership.workHosterType,
|
|
@@ -212,15 +362,38 @@ export class WorkHosterHandler {
|
|
|
212
362
|
return policyClient.id;
|
|
213
363
|
}
|
|
214
364
|
|
|
215
|
-
private
|
|
365
|
+
private resolveGatewayClientOwnership(
|
|
366
|
+
auth: TAuthContext,
|
|
367
|
+
ownership: interfaces.data.IGatewayClientOwnership,
|
|
368
|
+
): Required<interfaces.data.IGatewayClientOwnership> {
|
|
216
369
|
const policy = auth.token?.policy;
|
|
217
|
-
if (
|
|
218
|
-
|
|
219
|
-
|
|
370
|
+
if (policy?.role === 'gatewayClient') {
|
|
371
|
+
if (!policy.gatewayClient) {
|
|
372
|
+
throw new plugins.typedrequest.TypedResponseError('gateway client token is missing gatewayClient binding');
|
|
373
|
+
}
|
|
374
|
+
if (ownership.gatewayClientType && ownership.gatewayClientType !== policy.gatewayClient.type) {
|
|
375
|
+
throw new plugins.typedrequest.TypedResponseError('gateway client token cannot act for this ownership');
|
|
376
|
+
}
|
|
377
|
+
if (ownership.gatewayClientId && ownership.gatewayClientId !== policy.gatewayClient.id) {
|
|
378
|
+
throw new plugins.typedrequest.TypedResponseError('gateway client token cannot act for this ownership');
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
gatewayClientType: policy.gatewayClient.type,
|
|
382
|
+
gatewayClientId: policy.gatewayClient.id,
|
|
383
|
+
appId: ownership.appId,
|
|
384
|
+
hostname: ownership.hostname,
|
|
385
|
+
};
|
|
220
386
|
}
|
|
221
|
-
|
|
222
|
-
|
|
387
|
+
|
|
388
|
+
if (!ownership.gatewayClientType || !ownership.gatewayClientId) {
|
|
389
|
+
throw new plugins.typedrequest.TypedResponseError('gateway client ownership is missing type or id');
|
|
223
390
|
}
|
|
391
|
+
return ownership as Required<interfaces.data.IGatewayClientOwnership>;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
private assertGatewayClientOwnership(auth: TAuthContext, ownership: Required<interfaces.data.IGatewayClientOwnership>): void {
|
|
395
|
+
const policy = auth.token?.policy;
|
|
396
|
+
if (!policy || policy.role !== 'gatewayClient') return;
|
|
224
397
|
if (!this.matchesHostnamePatterns(ownership.hostname, policy.hostnamePatterns || [])) {
|
|
225
398
|
throw new plugins.typedrequest.TypedResponseError('hostname is outside token policy');
|
|
226
399
|
}
|
|
@@ -403,7 +576,8 @@ export class WorkHosterHandler {
|
|
|
403
576
|
enabled?: boolean,
|
|
404
577
|
deleteRoute?: boolean,
|
|
405
578
|
): Promise<interfaces.data.IGatewayClientRouteSyncResult> {
|
|
406
|
-
this.
|
|
579
|
+
const resolvedOwnership = this.resolveGatewayClientOwnership(auth, ownership);
|
|
580
|
+
this.assertGatewayClientOwnership(auth, resolvedOwnership);
|
|
407
581
|
this.assertRouteTargetsAllowed(auth, route);
|
|
408
582
|
|
|
409
583
|
const manager = this.opsServerRef.dcRouterRef.routeConfigManager;
|
|
@@ -411,7 +585,7 @@ export class WorkHosterHandler {
|
|
|
411
585
|
return { success: false, message: 'Route management not initialized' };
|
|
412
586
|
}
|
|
413
587
|
|
|
414
|
-
const externalKey = this.buildGatewayClientExternalKey(
|
|
588
|
+
const externalKey = this.buildGatewayClientExternalKey(resolvedOwnership);
|
|
415
589
|
const existingRoute = manager.findApiRouteByExternalKey(externalKey);
|
|
416
590
|
|
|
417
591
|
if (deleteRoute) {
|
|
@@ -430,15 +604,15 @@ export class WorkHosterHandler {
|
|
|
430
604
|
|
|
431
605
|
const metadata: interfaces.data.IRouteMetadata = {
|
|
432
606
|
ownerType: 'gatewayClient',
|
|
433
|
-
gatewayClientType:
|
|
434
|
-
gatewayClientId:
|
|
435
|
-
gatewayClientAppId:
|
|
436
|
-
workHosterType:
|
|
437
|
-
workHosterId:
|
|
438
|
-
workAppId:
|
|
607
|
+
gatewayClientType: resolvedOwnership.gatewayClientType,
|
|
608
|
+
gatewayClientId: resolvedOwnership.gatewayClientId,
|
|
609
|
+
gatewayClientAppId: resolvedOwnership.appId,
|
|
610
|
+
workHosterType: resolvedOwnership.gatewayClientType,
|
|
611
|
+
workHosterId: resolvedOwnership.gatewayClientId,
|
|
612
|
+
workAppId: resolvedOwnership.appId,
|
|
439
613
|
externalKey,
|
|
440
614
|
};
|
|
441
|
-
const normalizedRoute = this.normalizeGatewayClientRoute(route,
|
|
615
|
+
const normalizedRoute = this.normalizeGatewayClientRoute(route, resolvedOwnership, externalKey);
|
|
442
616
|
|
|
443
617
|
if (existingRoute) {
|
|
444
618
|
const result = await manager.updateRoute(existingRoute.id, {
|
|
@@ -455,7 +629,7 @@ export class WorkHosterHandler {
|
|
|
455
629
|
return { success: true, action: 'created', routeId };
|
|
456
630
|
}
|
|
457
631
|
|
|
458
|
-
private buildGatewayClientExternalKey(ownership: interfaces.data.IGatewayClientOwnership): string {
|
|
632
|
+
private buildGatewayClientExternalKey(ownership: Required<interfaces.data.IGatewayClientOwnership>): string {
|
|
459
633
|
return [
|
|
460
634
|
ownership.gatewayClientType,
|
|
461
635
|
ownership.gatewayClientId,
|
|
@@ -478,7 +652,7 @@ export class WorkHosterHandler {
|
|
|
478
652
|
|
|
479
653
|
private normalizeGatewayClientRoute(
|
|
480
654
|
route: interfaces.data.IDcRouterRouteConfig,
|
|
481
|
-
ownership: interfaces.data.IGatewayClientOwnership
|
|
655
|
+
ownership: Required<interfaces.data.IGatewayClientOwnership>,
|
|
482
656
|
externalKey: string,
|
|
483
657
|
): interfaces.data.IDcRouterRouteConfig {
|
|
484
658
|
const normalizedRoute = { ...route };
|
|
@@ -12,6 +12,14 @@ export class WorkHosterManager {
|
|
|
12
12
|
return response.capabilities;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
+
public async getGatewayClientContext(): Promise<interfaces.data.IGatewayClientContext> {
|
|
16
|
+
const response = await this.clientRef.request<interfaces.requests.IReq_GetGatewayClientContext>(
|
|
17
|
+
'getGatewayClientContext',
|
|
18
|
+
this.clientRef.buildRequestPayload() as any,
|
|
19
|
+
);
|
|
20
|
+
return response.context;
|
|
21
|
+
}
|
|
22
|
+
|
|
15
23
|
public async getDomains(): Promise<interfaces.data.IWorkHosterDomain[]> {
|
|
16
24
|
const response = await this.clientRef.request<interfaces.requests.IReq_GetWorkHosterDomains>(
|
|
17
25
|
'getWorkHosterDomains',
|