138 lines
3.8 KiB
TypeScript
138 lines
3.8 KiB
TypeScript
import * as plugins from './coreflow.plugins.js';
|
|
import { Coreflow } from './coreflow.classes.coreflow.js';
|
|
import { logger } from './coreflow.logging.js';
|
|
|
|
export interface IExternalGatewayConfig {
|
|
url: string;
|
|
apiToken: string;
|
|
workHosterType: 'cloudly';
|
|
workHosterId: string;
|
|
targetHost?: string;
|
|
targetPort?: number;
|
|
}
|
|
|
|
interface IWorkAppRouteSyncResult {
|
|
success: boolean;
|
|
action?: 'created' | 'updated' | 'deleted' | 'unchanged';
|
|
routeId?: string;
|
|
message?: string;
|
|
}
|
|
|
|
interface IDcRouterCertificateExport {
|
|
success: boolean;
|
|
cert?: {
|
|
id: string;
|
|
domainName: string;
|
|
created: number;
|
|
validUntil: number;
|
|
privateKey: string;
|
|
publicKey: string;
|
|
csr: string;
|
|
};
|
|
message?: string;
|
|
}
|
|
|
|
export class ExternalGatewayConnector {
|
|
constructor(public coreflowRef: Coreflow) {}
|
|
|
|
public isConfigured(configArg?: IExternalGatewayConfig): configArg is IExternalGatewayConfig {
|
|
return Boolean(
|
|
configArg?.url
|
|
&& configArg.apiToken
|
|
&& configArg.workHosterId
|
|
&& configArg.targetHost
|
|
&& configArg.targetPort,
|
|
);
|
|
}
|
|
|
|
public async syncWorkAppRoute(optionsArg: {
|
|
config: IExternalGatewayConfig | undefined;
|
|
service: plugins.servezoneInterfaces.data.IService;
|
|
hostname: string;
|
|
}): Promise<void> {
|
|
const config = optionsArg.config;
|
|
if (!this.isConfigured(config)) return;
|
|
|
|
const result = await this.fireDcRouterRequest<IWorkAppRouteSyncResult>(
|
|
config,
|
|
'syncWorkAppRoute',
|
|
{
|
|
ownership: {
|
|
workHosterType: 'cloudly',
|
|
workHosterId: config.workHosterId,
|
|
workAppId: optionsArg.service.id || optionsArg.service.data.name,
|
|
hostname: optionsArg.hostname,
|
|
},
|
|
route: {
|
|
name: this.routeName(optionsArg.hostname),
|
|
match: {
|
|
ports: [443],
|
|
domains: [optionsArg.hostname],
|
|
},
|
|
action: {
|
|
type: 'forward',
|
|
targets: [{ host: config.targetHost!, port: config.targetPort! }],
|
|
tls: {
|
|
mode: 'terminate',
|
|
certificate: 'auto',
|
|
},
|
|
websocket: {
|
|
enabled: true,
|
|
},
|
|
},
|
|
},
|
|
enabled: true,
|
|
},
|
|
);
|
|
|
|
if (!result.success) {
|
|
throw new Error(result.message || `dcrouter route sync failed for ${optionsArg.hostname}`);
|
|
}
|
|
|
|
logger.log('success', `external gateway route ${result.action || 'synced'} for ${optionsArg.hostname}`);
|
|
}
|
|
|
|
public async exportCertificateForDomain(
|
|
configArg: IExternalGatewayConfig | undefined,
|
|
hostnameArg: string,
|
|
): Promise<plugins.tsclass.network.ICert | undefined> {
|
|
if (!configArg?.url || !configArg.apiToken) return undefined;
|
|
|
|
const result = await this.fireDcRouterRequest<IDcRouterCertificateExport>(
|
|
configArg,
|
|
'exportCertificate',
|
|
{ domain: hostnameArg },
|
|
);
|
|
|
|
if (!result.success || !result.cert) return undefined;
|
|
return {
|
|
id: result.cert.id,
|
|
domainName: result.cert.domainName,
|
|
created: result.cert.created,
|
|
validUntil: result.cert.validUntil,
|
|
privateKey: result.cert.privateKey,
|
|
publicKey: result.cert.publicKey,
|
|
csr: result.cert.csr,
|
|
};
|
|
}
|
|
|
|
private routeName(hostnameArg: string): string {
|
|
return `cloudly-${hostnameArg.replace(/[^a-zA-Z0-9]+/g, '-').replace(/^-|-$/g, '')}`;
|
|
}
|
|
|
|
private async fireDcRouterRequest<TResponse>(
|
|
configArg: IExternalGatewayConfig,
|
|
methodArg: string,
|
|
requestDataArg: Record<string, unknown>,
|
|
): Promise<TResponse> {
|
|
const typedRequest = new plugins.typedrequest.TypedRequest<any>(
|
|
`${configArg.url.replace(/\/+$/, '')}/typedrequest`,
|
|
methodArg,
|
|
);
|
|
return await typedRequest.fire({
|
|
...requestDataArg,
|
|
apiToken: configArg.apiToken,
|
|
}) as TResponse;
|
|
}
|
|
}
|