diff --git a/backend/src/services/acme-cloudflare.ts b/backend/src/services/acme-cloudflare.ts index d1e26a3..1f4dd4b 100644 --- a/backend/src/services/acme-cloudflare.ts +++ b/backend/src/services/acme-cloudflare.ts @@ -294,6 +294,10 @@ export async function issueCertificateWithCloudflareDns(params: { const serverIp = await resolveServerPublicIp(params.server, clientRos) await syncCertificateDomainRecords(token, domains, serverIp, settings.defaultZoneId) + const trustStores = params.trustStore.filter(Boolean) + const effectiveTrustStores = trustStores.length > 0 ? trustStores : ["www", "api"] + const trustStoreCsv = effectiveTrustStores.join(",") + params.onStep?.("import") const safeBase = params.certName.replace(/[^a-zA-Z0-9._-]+/g, "_") const certFile = `${safeBase}.crt` @@ -304,14 +308,15 @@ export async function issueCertificateWithCloudflareDns(params: { fileName: certRouterFile, name: params.certName, trusted: true, - trustStore: params.trustStore.join(","), + trustStore: trustStoreCsv, }) await clientRos.importCertificate({ fileName: keyRouterFile, name: params.certName, trusted: true, - trustStore: params.trustStore.join(","), + trustStore: trustStoreCsv, }) + await clientRos.applyCertificateToServices(params.certName, effectiveTrustStores) } finally { params.onStep?.("cleanup") for (const item of txtCleanups) { diff --git a/backend/src/services/mikrotik.ts b/backend/src/services/mikrotik.ts index 6a69c4a..7b8970e 100644 --- a/backend/src/services/mikrotik.ts +++ b/backend/src/services/mikrotik.ts @@ -565,12 +565,45 @@ export class MikrotikClient { "file-name": params.fileName, name: params.name, trusted: params.trusted === false ? "no" : "yes", + "trust-store": params.trustStore?.trim() || "www,api", } - if (params.trustStore?.trim()) body["trust-store"] = params.trustStore.trim() if (params.passphrase?.trim()) body.passphrase = params.passphrase.trim() return this.post("/certificate/import", body, 60_000) } + async applyCertificateToServices( + certName: string, + trustStores: string[] = ["www", "api"], + ): Promise { + const stores = trustStores.length > 0 ? trustStores : ["www", "api"] + const targets: string[] = [] + if (stores.includes("www")) targets.push("www-ssl") + if (stores.includes("api")) targets.push("api-ssl") + if (targets.length === 0) targets.push("www-ssl") + + const body = { + disabled: "no", + certificate: certName, + } + for (const serviceName of targets) { + await this.patchIpService(serviceName, body) + } + } + + private async patchIpService(serviceName: string, body: Record): Promise { + const pathByName = `/ip/service/${encodeURIComponent(serviceName)}` + try { + await this.patch(pathByName, body, 30_000) + return + } catch { + const services = await this.get>>("/ip/service") + const row = services.find((service) => String(service.name ?? "") === serviceName) + const id = row?.[".id"] + if (!id) throw new Error(`Сервис RouterOS ${serviceName} не найден`) + await this.patch(`/ip/service/${encodeURIComponent(id)}`, body, 30_000) + } + } + async exportConfigScript(): Promise { const raw = await this.post("/console/export", {}, 30_000)