Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9f430de16 |
@@ -161,11 +161,11 @@ async function listDnsRecordsByName(token: string, zoneId: string, fqdn: string)
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function upsertARecord(token: string, zoneId: string, fqdn: string, ip: string): Promise<void> {
|
async function upsertARecord(token: string, zoneId: string, fqdn: string, ip: string): Promise<"updated" | "created" | "skipped_cname"> {
|
||||||
const records = await listDnsRecordsByName(token, zoneId, fqdn)
|
const records = await listDnsRecordsByName(token, zoneId, fqdn)
|
||||||
const existingA = records.find((record) => record.type === "A")
|
const existingA = records.find((record) => record.type === "A")
|
||||||
if (existingA) {
|
if (existingA) {
|
||||||
if (existingA.content === ip) return
|
if (existingA.content === ip) return "updated"
|
||||||
await cloudflareRequest<CfDnsRecord>(token, `/zones/${zoneId}/dns_records/${existingA.id}`, {
|
await cloudflareRequest<CfDnsRecord>(token, `/zones/${zoneId}/dns_records/${existingA.id}`, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
@@ -176,11 +176,12 @@ async function upsertARecord(token: string, zoneId: string, fqdn: string, ip: st
|
|||||||
proxied: false,
|
proxied: false,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
return
|
return "updated"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CNAME на CN/SAN (алиас на канонический хост) — норма; A конфликтует с CNAME и для DNS-01 не нужен
|
||||||
if (records.some((record) => record.type === "CNAME")) {
|
if (records.some((record) => record.type === "CNAME")) {
|
||||||
throw new Error(`Для ${fqdn} уже есть CNAME в Cloudflare — A-запись не создана`)
|
return "skipped_cname"
|
||||||
}
|
}
|
||||||
|
|
||||||
await cloudflareRequest<{ id: string }>(token, `/zones/${zoneId}/dns_records`, {
|
await cloudflareRequest<{ id: string }>(token, `/zones/${zoneId}/dns_records`, {
|
||||||
@@ -193,6 +194,7 @@ async function upsertARecord(token: string, zoneId: string, fqdn: string, ip: st
|
|||||||
proxied: false,
|
proxied: false,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
|
return "created"
|
||||||
}
|
}
|
||||||
|
|
||||||
async function syncCertificateDomainRecords(
|
async function syncCertificateDomainRecords(
|
||||||
@@ -200,11 +202,14 @@ async function syncCertificateDomainRecords(
|
|||||||
domains: string[],
|
domains: string[],
|
||||||
serverIp: string,
|
serverIp: string,
|
||||||
defaultZoneId?: string,
|
defaultZoneId?: string,
|
||||||
): Promise<void> {
|
): Promise<{ skippedCname: string[] }> {
|
||||||
|
const skippedCname: string[] = []
|
||||||
for (const domain of domains) {
|
for (const domain of domains) {
|
||||||
const zoneId = await resolveZoneId(token, domain, defaultZoneId)
|
const zoneId = await resolveZoneId(token, domain, defaultZoneId)
|
||||||
await upsertARecord(token, zoneId, domain, serverIp)
|
const result = await upsertARecord(token, zoneId, domain, serverIp)
|
||||||
|
if (result === "skipped_cname") skippedCname.push(domain)
|
||||||
}
|
}
|
||||||
|
return { skippedCname }
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sleep(ms: number) {
|
async function sleep(ms: number) {
|
||||||
@@ -296,9 +301,26 @@ export async function issueCertificateWithCloudflareDns(params: {
|
|||||||
const finalized = await client.finalizeOrder(order, csr)
|
const finalized = await client.finalizeOrder(order, csr)
|
||||||
const certPem = await client.getCertificate(finalized)
|
const certPem = await client.getCertificate(finalized)
|
||||||
|
|
||||||
|
// A-sync опционален: DNS-01 уже завершён. CNAME на CN (msk2 → msk-gw02) не должен валить импорт.
|
||||||
const clientRos = MikrotikClient.fromServer(params.server)
|
const clientRos = MikrotikClient.fromServer(params.server)
|
||||||
const serverIp = await resolveServerPublicIp(params.server, clientRos)
|
try {
|
||||||
await syncCertificateDomainRecords(token, domains, serverIp, settings.defaultZoneId)
|
params.onStep?.("dns_a_sync")
|
||||||
|
const serverIp = await resolveServerPublicIp(params.server, clientRos)
|
||||||
|
const { skippedCname } = await syncCertificateDomainRecords(
|
||||||
|
token,
|
||||||
|
domains,
|
||||||
|
serverIp,
|
||||||
|
settings.defaultZoneId,
|
||||||
|
)
|
||||||
|
if (skippedCname.length > 0) {
|
||||||
|
params.onStep?.(
|
||||||
|
`dns_a_sync_skip_cname:${skippedCname.join(",")}`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
const msg = e instanceof Error ? e.message : "ошибка DNS A-sync"
|
||||||
|
params.onStep?.(`dns_a_sync_warn:${msg}`)
|
||||||
|
}
|
||||||
|
|
||||||
const trustStores = params.trustStore.filter(Boolean)
|
const trustStores = params.trustStore.filter(Boolean)
|
||||||
const effectiveTrustStores = trustStores.length > 0 ? trustStores : ["www", "api"]
|
const effectiveTrustStores = trustStores.length > 0 ? trustStores : ["www", "api"]
|
||||||
|
|||||||
Reference in New Issue
Block a user