@serve.zone/dcrouter 17.10.0 → 17.10.2
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/deno.json +1 -1
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/dns/classes.gateway-route-dns-reconciler.d.ts +7 -0
- package/dist_ts/dns/classes.gateway-route-dns-reconciler.js +37 -6
- package/dist_ts/opsserver/handlers/gatewayclient.handler.d.ts +1 -0
- package/dist_ts/opsserver/handlers/gatewayclient.handler.js +14 -1
- package/dist_ts_migrations/index.js +122 -9
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/package.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/dns/classes.gateway-route-dns-reconciler.ts +41 -6
- package/ts/opsserver/handlers/gatewayclient.handler.ts +22 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@serve.zone/dcrouter',
|
|
6
|
-
version: '17.10.
|
|
6
|
+
version: '17.10.2',
|
|
7
7
|
description: 'A multifaceted routing service handling mail and SMS delivery functions.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfd2ViLzAwX2NvbW1pdGluZm9fZGF0YS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLFVBQVUsR0FBRztJQUN4QixJQUFJLEVBQUUsc0JBQXNCO0lBQzVCLE9BQU8sRUFBRSxTQUFTO0lBQ2xCLFdBQVcsRUFBRSwwRUFBMEU7Q0FDeEYsQ0FBQSJ9
|
package/package.json
CHANGED
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -132,8 +132,12 @@ export class GatewayRouteDnsReconciler {
|
|
|
132
132
|
const targetIp = optionsArg.delete
|
|
133
133
|
? undefined
|
|
134
134
|
: this.getDesiredTargetIp(optionsArg.gatewayClientId, hostname);
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
// Routes synced before proxy intent was persisted carry no intent at all.
|
|
136
|
+
// Resolving that to a hardcoded default here would delete a live proxied
|
|
137
|
+
// record and recreate it unproxied, so the intent stays undefined until it
|
|
138
|
+
// can be resolved against the current record state under the hostname lock.
|
|
139
|
+
const proxiedIntent = optionsArg.proxied;
|
|
140
|
+
const workKey = this.buildWorkKey(optionsArg, hostname, mode, targetIp, proxiedIntent);
|
|
137
141
|
const latestIntent = this.latestIntentByHostname.get(hostname);
|
|
138
142
|
if (latestIntent?.workKey === workKey) return await latestIntent.promise;
|
|
139
143
|
|
|
@@ -156,7 +160,7 @@ export class GatewayRouteDnsReconciler {
|
|
|
156
160
|
mode,
|
|
157
161
|
checkedAt,
|
|
158
162
|
targetIp,
|
|
159
|
-
|
|
163
|
+
proxiedIntent,
|
|
160
164
|
executionArg.providerZoneRefreshes,
|
|
161
165
|
);
|
|
162
166
|
});
|
|
@@ -184,7 +188,7 @@ export class GatewayRouteDnsReconciler {
|
|
|
184
188
|
mode: Exclude<plugins.servezoneInterfaces.data.TGatewayRouteDnsMode, 'skip'>,
|
|
185
189
|
checkedAt: number,
|
|
186
190
|
targetIp: string | undefined,
|
|
187
|
-
|
|
191
|
+
proxiedIntent: boolean | undefined,
|
|
188
192
|
providerZoneRefreshes?: Map<string, Promise<IProviderZoneRefreshResult>>,
|
|
189
193
|
): Promise<TGatewayDnsResult> {
|
|
190
194
|
const claimOwnerId = this.buildClaimOwnerId(optionsArg.gatewayClientId, hostname);
|
|
@@ -294,6 +298,11 @@ export class GatewayRouteDnsReconciler {
|
|
|
294
298
|
);
|
|
295
299
|
}
|
|
296
300
|
|
|
301
|
+
// Absent proxy intent must never be read as "not proxied": that would make
|
|
302
|
+
// the desired lookup miss a live proxied record and replace it with an
|
|
303
|
+
// unproxied one, exposing the origin. Fall back to the stored record state
|
|
304
|
+
// the same way dnsMode and ingress fall back to their persisted values.
|
|
305
|
+
const proxied = proxiedIntent ?? this.getStoredProxiedState(records, recordType, claimOwnerId);
|
|
297
306
|
const desired = records.find((recordArg) => recordArg.type === recordType
|
|
298
307
|
&& recordArg.value === targetIp
|
|
299
308
|
&& recordArg.ttl === GATEWAY_ROUTE_DNS_TTL
|
|
@@ -620,7 +629,7 @@ export class GatewayRouteDnsReconciler {
|
|
|
620
629
|
hostnameArg: string,
|
|
621
630
|
modeArg: Exclude<plugins.servezoneInterfaces.data.TGatewayRouteDnsMode, 'skip'>,
|
|
622
631
|
targetIpArg: string | undefined,
|
|
623
|
-
proxiedArg: boolean,
|
|
632
|
+
proxiedArg: boolean | undefined,
|
|
624
633
|
): string {
|
|
625
634
|
return JSON.stringify({
|
|
626
635
|
hostname: hostnameArg,
|
|
@@ -629,11 +638,37 @@ export class GatewayRouteDnsReconciler {
|
|
|
629
638
|
mode: modeArg,
|
|
630
639
|
delete: optionsArg.delete === true,
|
|
631
640
|
targetIp: targetIpArg || null,
|
|
632
|
-
proxied: proxiedArg,
|
|
641
|
+
proxied: proxiedArg ?? null,
|
|
633
642
|
claims: this.getActiveClaimsForHostname(hostnameArg),
|
|
634
643
|
});
|
|
635
644
|
}
|
|
636
645
|
|
|
646
|
+
/**
|
|
647
|
+
* Recover the effective proxy state for a claim whose route carries no
|
|
648
|
+
* explicit proxy intent. Preferring the reconciler's own record keeps managed
|
|
649
|
+
* proxying stable, and falling back to any address record under the hostname
|
|
650
|
+
* keeps an operator's proxy protection when automation claims the hostname.
|
|
651
|
+
*/
|
|
652
|
+
private getStoredProxiedState(
|
|
653
|
+
recordsArg: DnsRecordDoc[],
|
|
654
|
+
recordTypeArg: 'A' | 'AAAA',
|
|
655
|
+
claimOwnerIdArg: string,
|
|
656
|
+
): boolean {
|
|
657
|
+
const isOwned = (recordArg: DnsRecordDoc) => recordArg.managedBy === GATEWAY_ROUTE_DNS_MANAGED_BY
|
|
658
|
+
&& recordArg.managedOwnerId === claimOwnerIdArg;
|
|
659
|
+
const preferenceOrder: Array<(recordArg: DnsRecordDoc) => boolean> = [
|
|
660
|
+
(recordArg) => recordArg.type === recordTypeArg && isOwned(recordArg),
|
|
661
|
+
(recordArg) => isOwned(recordArg),
|
|
662
|
+
(recordArg) => recordArg.type === recordTypeArg,
|
|
663
|
+
() => true,
|
|
664
|
+
];
|
|
665
|
+
for (const matches of preferenceOrder) {
|
|
666
|
+
const candidate = recordsArg.find((recordArg) => matches(recordArg));
|
|
667
|
+
if (candidate) return candidate.proxied === true;
|
|
668
|
+
}
|
|
669
|
+
return false;
|
|
670
|
+
}
|
|
671
|
+
|
|
637
672
|
private async refreshProviderZone(
|
|
638
673
|
zoneIdArg: string,
|
|
639
674
|
providerZoneRefreshesArg?: Map<string, Promise<IProviderZoneRefreshResult>>,
|
|
@@ -1383,6 +1383,12 @@ export class GatewayClientHandler {
|
|
|
1383
1383
|
? { gatewayDnsProxied: dnsProxied } : {}),
|
|
1384
1384
|
};
|
|
1385
1385
|
const normalizedRoute = this.normalizeGatewayClientRoute(validatedRoute, resolvedOwnership, externalKey);
|
|
1386
|
+
if (
|
|
1387
|
+
validatedRoute.remoteIngress === undefined
|
|
1388
|
+
&& existingRoute?.route.remoteIngress
|
|
1389
|
+
) {
|
|
1390
|
+
normalizedRoute.remoteIngress = structuredClone(existingRoute.route.remoteIngress);
|
|
1391
|
+
}
|
|
1386
1392
|
if (!normalizedRoute.ingress) {
|
|
1387
1393
|
const existingIngress = existingRoute?.route.ingress;
|
|
1388
1394
|
normalizedRoute.ingress = existingIngress
|
|
@@ -1396,6 +1402,7 @@ export class GatewayClientHandler {
|
|
|
1396
1402
|
+ `${existingIngress ? 'preserved stored policy' : 'applied legacy directHub+smartVpn compatibility policy'}`,
|
|
1397
1403
|
);
|
|
1398
1404
|
}
|
|
1405
|
+
this.assertGatewayRouteHasIngressPath(normalizedRoute);
|
|
1399
1406
|
|
|
1400
1407
|
if (existingRoute) {
|
|
1401
1408
|
const snapshot = structuredClone(existingRoute);
|
|
@@ -1770,6 +1777,21 @@ export class GatewayClientHandler {
|
|
|
1770
1777
|
return normalizedRoute;
|
|
1771
1778
|
}
|
|
1772
1779
|
|
|
1780
|
+
private assertGatewayRouteHasIngressPath(
|
|
1781
|
+
routeArg: interfaces.data.IDcRouterRouteConfig,
|
|
1782
|
+
): void {
|
|
1783
|
+
if (
|
|
1784
|
+
routeArg.ingress?.directHub
|
|
1785
|
+
|| routeArg.ingress?.smartVpn
|
|
1786
|
+
|| routeArg.remoteIngress?.enabled
|
|
1787
|
+
) {
|
|
1788
|
+
return;
|
|
1789
|
+
}
|
|
1790
|
+
throw new plugins.typedrequest.TypedResponseError(
|
|
1791
|
+
'gateway route must enable directHub, smartVpn, or RemoteIngress',
|
|
1792
|
+
);
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1773
1795
|
private assertGatewayClientRouteOwnership(
|
|
1774
1796
|
ownership: TResolvedGatewayClientOwnership,
|
|
1775
1797
|
route?: interfaces.data.IDcRouterRouteConfig,
|