feat: expose external gateway settings

This commit is contained in:
2026-04-29 15:57:02 +00:00
parent 4eba247472
commit d1ce149487
2 changed files with 55 additions and 4 deletions
+39 -1
View File
@@ -41,7 +41,7 @@ export class CloudlySettingsManager {
const masked: servezoneInterfaces.data.ICloudlySettingsMasked = {};
for (const [key, value] of Object.entries(settings)) {
if (typeof value === 'string' && value.length > 4) {
if (this.isSensitiveSettingKey(key) && typeof value === 'string' && value.length > 4) {
// Mask the token, showing only last 4 characters
masked[key] = '****' + value.slice(-4);
} else {
@@ -52,6 +52,21 @@ export class CloudlySettingsManager {
return masked;
}
private isSensitiveSettingKey(key: string): boolean {
const normalizedKey = key.toLowerCase();
return [
'token',
'secret',
'apikey',
'accesskey',
'applicationkey',
'consumerkey',
'keyjson',
'privatekey',
'password',
].some((sensitivePart) => normalizedKey.includes(sensitivePart));
}
/**
* Update multiple settings at once
*/
@@ -65,6 +80,29 @@ export class CloudlySettingsManager {
await this.settingsStore.deleteKey(key as keyof servezoneInterfaces.data.ICloudlySettings);
}
}
if (Object.keys(updates).some((key) => this.isExternalGatewaySettingKey(key))) {
this.refreshExternalGatewayConfig().catch((error) => {
console.log(`External gateway settings refresh failed: ${(error as Error).message}`);
});
}
}
private isExternalGatewaySettingKey(key: string): boolean {
return [
'dcrouterGatewayUrl',
'dcrouterGatewayApiToken',
'dcrouterWorkHosterId',
'dcrouterTargetHost',
'dcrouterTargetPort',
].includes(key);
}
private async refreshExternalGatewayConfig(): Promise<void> {
await Promise.all([
this.cloudlyRef.domainManager.syncExternalGatewayDomains(),
this.cloudlyRef.coreflowManager.pushClusterConfigToConnectedCoreflows(),
]);
}
/**
+15 -2
View File
@@ -63,7 +63,7 @@ export class CloudlyViewSettings extends DeesElement {
try {
const updates: Partial<plugins.interfaces.data.ICloudlySettings> = {};
for (const [key, value] of Object.entries(formData)) {
if (value !== undefined && value !== '****' && !value?.toString().endsWith('****')) {
if (value !== undefined && value !== '****' && !value?.toString().startsWith('****')) {
updates[key as keyof plugins.interfaces.data.ICloudlySettings] = value as string;
}
}
@@ -130,6 +130,20 @@ export class CloudlyViewSettings extends DeesElement {
</div>
</dees-panel>
<dees-panel .title=${'External dcrouter Gateway'} .subtitle=${'Route WorkApps through a dcrouter edge authority'} .variant=${'outline'}>
<div class="form-grid">
<dees-input-text .key=${'dcrouterGatewayUrl'} .label=${'Gateway URL'} .value=${this.settings.dcrouterGatewayUrl || ''} .description=${'Base URL of the dcrouter OpsServer, for example https://edge.example.com'} .required=${false}></dees-input-text>
<dees-input-text .key=${'dcrouterGatewayApiToken'} .label=${'API Token'} .value=${this.settings.dcrouterGatewayApiToken || ''} .isPasswordBool=${true} .description=${'dcrouter API token with workhosters and certificates scopes'} .required=${false}></dees-input-text>
</div>
<div class="form-grid">
<dees-input-text .key=${'dcrouterWorkHosterId'} .label=${'WorkHoster ID'} .value=${this.settings.dcrouterWorkHosterId || ''} .description=${'Optional stable owner ID; defaults to the cluster ID'} .required=${false}></dees-input-text>
<dees-input-text .key=${'dcrouterTargetHost'} .label=${'Target Host'} .value=${this.settings.dcrouterTargetHost || ''} .description=${'Host or IP dcrouter forwards workload traffic to'} .required=${false}></dees-input-text>
</div>
<div class="form-grid single">
<dees-input-text .key=${'dcrouterTargetPort'} .label=${'Target Port'} .value=${this.settings.dcrouterTargetPort || '80'} .description=${'Internal HTTP port dcrouter should forward to'} .required=${false}></dees-input-text>
</div>
</dees-panel>
<dees-panel .title=${'Amazon Web Services'} .subtitle=${'Configure AWS credentials'} .variant=${'outline'}>
<div class="test-status">
${this.renderProviderStatus('aws')}
@@ -203,4 +217,3 @@ declare global {
'cloudly-view-settings': CloudlyViewSettings;
}
}