Call per-tenant dashboard SSL agent when issuing domain SSL.

Issue SSL on one domain now passes tenantApex to the dashboards agent instead of renewing the shared multi-tenant cert.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-26 01:20:03 +03:30
co-authored by Cursor
parent 3f266a2dcb
commit 6cd0b009ef
+22 -8
View File
@@ -103,13 +103,15 @@ export class DomainAdminService {
} }
/** Fire-and-forget or blocking call to the dashboards VPS ssl-sync agent. */ /** Fire-and-forget or blocking call to the dashboards VPS ssl-sync agent. */
private async callDashboardSslSync(opts: { wait: boolean }) { private async callDashboardSslSync(opts: { wait: boolean; tenantApex?: string }) {
const agentUrl = this.config.get<string>('SSL_SYNC_AGENT_URL')?.trim(); const agentUrl = this.config.get<string>('SSL_SYNC_AGENT_URL')?.trim();
const token = this.config.get<string>('SSL_SYNC_AGENT_TOKEN')?.trim(); const token = this.config.get<string>('SSL_SYNC_AGENT_TOKEN')?.trim();
if (!agentUrl || !token) { if (!agentUrl || !token) {
throw new ServiceUnavailableException('SSL sync agent is not configured'); throw new ServiceUnavailableException('SSL sync agent is not configured');
} }
const tenantApex = opts.tenantApex?.trim().toLowerCase();
let response: Response; let response: Response;
try { try {
response = await fetch(agentUrl, { response = await fetch(agentUrl, {
@@ -118,7 +120,10 @@ export class DomainAdminService {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'X-SSL-Sync-Agent-Token': token, 'X-SSL-Sync-Agent-Token': token,
}, },
body: JSON.stringify({ wait: opts.wait }), body: JSON.stringify({
wait: opts.wait,
...(tenantApex ? { tenantApex } : {}),
}),
}); });
} catch { } catch {
throw new ServiceUnavailableException('Could not reach SSL sync agent'); throw new ServiceUnavailableException('Could not reach SSL sync agent');
@@ -368,30 +373,39 @@ export class DomainAdminService {
if (!businessOk || !customerOk) { if (!businessOk || !customerOk) {
try { try {
await this.callDashboardSslSync({ wait: true }); await this.callDashboardSslSync({ wait: true, tenantApex: apex });
businessOk = await probeTlsHost(businessHost); businessOk = await probeTlsHost(businessHost);
customerOk = await probeTlsHost(customerHost); customerOk = await probeTlsHost(customerHost);
if (!hosts.business.detail) { if (!hosts.business.detail) {
hosts.business = businessOk hosts.business = businessOk
? { host: businessHost, status: 'issued', detail: 'Covered by dashboard cert' } ? {
host: businessHost,
status: 'issued',
detail: 'Dashboard cert issued for this domain only',
}
: { : {
host: businessHost, host: businessHost,
status: 'failed', status: 'failed',
detail: 'Dashboard SSL sync finished but probe still failed', detail: 'Tenant dashboard SSL finished but probe still failed',
}; };
} }
if (!hosts.customer.detail) { if (!hosts.customer.detail) {
hosts.customer = customerOk hosts.customer = customerOk
? { host: customerHost, status: 'issued', detail: 'Covered by dashboard cert' } ? {
host: customerHost,
status: 'issued',
detail: 'Dashboard cert issued for this domain only',
}
: { : {
host: customerHost, host: customerHost,
status: 'failed', status: 'failed',
detail: 'Dashboard SSL sync finished but probe still failed', detail: 'Tenant dashboard SSL finished but probe still failed',
}; };
} }
} catch (err) { } catch (err) {
const detail = err instanceof Error ? err.message : 'Dashboard SSL sync failed'; const detail =
err instanceof Error ? err.message : 'Tenant dashboard SSL failed';
if (!businessOk) { if (!businessOk) {
hosts.business = { host: businessHost, status: 'failed', detail }; hosts.business = { host: businessHost, status: 'failed', detail };
} }