fix(external-gateway): derive gateway client identity from the dcrouter token and make the settings UI read-only
This commit is contained in:
@@ -10,13 +10,24 @@ type TWorkHosterType = 'onebox';
|
||||
interface IExternalGatewayConfig {
|
||||
url: string;
|
||||
apiToken: string;
|
||||
gatewayClientId: string;
|
||||
gatewayClientType?: TWorkHosterType;
|
||||
gatewayClientId?: string;
|
||||
/** @deprecated Use gatewayClientId. */
|
||||
workHosterId: string;
|
||||
workHosterId?: string;
|
||||
targetHost?: string;
|
||||
targetPort?: number;
|
||||
}
|
||||
|
||||
interface IGatewayClientContextResponse {
|
||||
context: {
|
||||
role: 'admin' | 'gatewayClient' | 'operator';
|
||||
gatewayClient?: {
|
||||
type: 'onebox' | 'cloudly' | 'custom';
|
||||
id: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
interface IWorkHosterDomain {
|
||||
id?: string;
|
||||
name: string;
|
||||
@@ -62,8 +73,8 @@ interface IWorkAppRouteOwnership {
|
||||
}
|
||||
|
||||
interface IGatewayClientOwnership {
|
||||
gatewayClientType: TWorkHosterType;
|
||||
gatewayClientId: string;
|
||||
gatewayClientType?: TWorkHosterType;
|
||||
gatewayClientId?: string;
|
||||
appId: string;
|
||||
hostname: string;
|
||||
}
|
||||
@@ -128,8 +139,14 @@ export class ExternalGatewayManager {
|
||||
if (this.getMode() === 'disabled') {
|
||||
return false;
|
||||
}
|
||||
const config = await this.getConfig({ requireTarget: false });
|
||||
return Boolean(config);
|
||||
const mode = this.getMode();
|
||||
const url = mode === 'managed'
|
||||
? this.oneboxRef.managedDcRouter.getGatewayUrl()
|
||||
: this.normalizeUrl(this.database.getSetting('dcrouterGatewayUrl') || '');
|
||||
const apiToken = mode === 'managed'
|
||||
? await this.oneboxRef.managedDcRouter.getAdminToken()
|
||||
: await this.database.getSecretSetting('dcrouterGatewayApiToken');
|
||||
return Boolean(url && apiToken);
|
||||
}
|
||||
|
||||
public async syncDomains(): Promise<IDomain[]> {
|
||||
@@ -188,7 +205,7 @@ export class ExternalGatewayManager {
|
||||
try {
|
||||
const response = await this.fireDcRouterRequest<{ domains: IWorkHosterDomain[] }>(
|
||||
'getGatewayClientDomains',
|
||||
{ gatewayClientId: config.gatewayClientId },
|
||||
config.gatewayClientId ? { gatewayClientId: config.gatewayClientId } : {},
|
||||
config,
|
||||
);
|
||||
return response.domains.map((domain) => ({
|
||||
@@ -216,7 +233,7 @@ export class ExternalGatewayManager {
|
||||
try {
|
||||
const response = await this.fireDcRouterRequest<{ records: IGatewayDnsRecord[] }>(
|
||||
'getGatewayClientDnsRecords',
|
||||
{ gatewayClientId: config.gatewayClientId },
|
||||
config.gatewayClientId ? { gatewayClientId: config.gatewayClientId } : {},
|
||||
config,
|
||||
);
|
||||
return response.records.map((record) => ({
|
||||
@@ -355,16 +372,27 @@ export class ExternalGatewayManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
const gatewayClientId = mode === 'managed'
|
||||
? this.oneboxRef.managedDcRouter.ensureGatewayClientId()
|
||||
: this.ensureGatewayClientId();
|
||||
const config: IExternalGatewayConfig = {
|
||||
url,
|
||||
apiToken,
|
||||
gatewayClientId,
|
||||
workHosterId: gatewayClientId,
|
||||
};
|
||||
|
||||
const contextClient = await this.getGatewayClientFromToken(config);
|
||||
if (contextClient) {
|
||||
config.gatewayClientType = contextClient.type;
|
||||
config.gatewayClientId = contextClient.id;
|
||||
config.workHosterId = contextClient.id;
|
||||
} else {
|
||||
const fallbackGatewayClientId = mode === 'managed'
|
||||
? this.oneboxRef.managedDcRouter.ensureGatewayClientId()
|
||||
: this.getStoredGatewayClientId();
|
||||
if (fallbackGatewayClientId) {
|
||||
config.gatewayClientType = 'onebox';
|
||||
config.gatewayClientId = fallbackGatewayClientId;
|
||||
config.workHosterId = fallbackGatewayClientId;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.requireTarget !== false) {
|
||||
if (mode === 'managed') {
|
||||
const target = this.oneboxRef.managedDcRouter.getRouteTarget();
|
||||
@@ -417,13 +445,27 @@ export class ExternalGatewayManager {
|
||||
return port;
|
||||
}
|
||||
|
||||
private ensureGatewayClientId(): string {
|
||||
let gatewayClientId = this.database.getSetting('dcrouterGatewayClientId') || this.database.getSetting('dcrouterWorkHosterId');
|
||||
if (!gatewayClientId) {
|
||||
gatewayClientId = crypto.randomUUID();
|
||||
this.database.setSetting('dcrouterGatewayClientId', gatewayClientId);
|
||||
private getStoredGatewayClientId(): string {
|
||||
return this.database.getSetting('dcrouterGatewayClientId') || this.database.getSetting('dcrouterWorkHosterId') || '';
|
||||
}
|
||||
|
||||
private async getGatewayClientFromToken(config: IExternalGatewayConfig): Promise<{ type: TWorkHosterType; id: string } | null> {
|
||||
try {
|
||||
const response = await this.fireDcRouterRequest<IGatewayClientContextResponse>(
|
||||
'getGatewayClientContext',
|
||||
{},
|
||||
config,
|
||||
);
|
||||
const gatewayClient = response.context.gatewayClient;
|
||||
if (!gatewayClient) return null;
|
||||
if (gatewayClient.type !== 'onebox') {
|
||||
throw new Error(`dcrouter token is bound to unsupported gateway client type: ${gatewayClient.type}`);
|
||||
}
|
||||
return { type: gatewayClient.type, id: gatewayClient.id };
|
||||
} catch (error) {
|
||||
logger.debug(`dcrouter gateway client context unavailable: ${getErrorMessage(error)}`);
|
||||
return null;
|
||||
}
|
||||
return gatewayClientId;
|
||||
}
|
||||
|
||||
private buildOwnership(
|
||||
@@ -433,7 +475,7 @@ export class ExternalGatewayManager {
|
||||
): IWorkAppRouteOwnership {
|
||||
return {
|
||||
workHosterType: 'onebox',
|
||||
workHosterId: config.gatewayClientId,
|
||||
workHosterId: config.gatewayClientId || '',
|
||||
workAppId: service.name || `service-${service.id}`,
|
||||
hostname,
|
||||
};
|
||||
@@ -444,12 +486,15 @@ export class ExternalGatewayManager {
|
||||
hostname: string,
|
||||
config: IExternalGatewayConfig,
|
||||
): IGatewayClientOwnership {
|
||||
return {
|
||||
gatewayClientType: 'onebox',
|
||||
gatewayClientId: config.gatewayClientId,
|
||||
const ownership: IGatewayClientOwnership = {
|
||||
gatewayClientType: config.gatewayClientType || 'onebox',
|
||||
appId: service.name || `service-${service.id}`,
|
||||
hostname,
|
||||
};
|
||||
if (config.gatewayClientId) {
|
||||
ownership.gatewayClientId = config.gatewayClientId;
|
||||
}
|
||||
return ownership;
|
||||
}
|
||||
|
||||
private buildRoute(service: IService, config: IExternalGatewayConfig): IDcRouterRouteConfig {
|
||||
|
||||
Reference in New Issue
Block a user