From 1b280a2940f9e2d919b0bf23b89cc185be1fa498 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Mon, 5 May 2025 21:43:39 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=A0=B9=E6=8D=AESOA=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E5=88=A4=E6=96=AD=E5=AD=90=E5=9F=9F=E5=90=8D=E6=89=98=E7=AE=A1?= =?UTF-8?q?=E6=9C=89=E7=BC=BA=E9=99=B7=EF=BC=8C=E6=94=B9=E5=9B=9E=E6=89=8B?= =?UTF-8?q?=E5=8A=A8=E9=85=8D=E7=BD=AE=E5=AD=90=E5=9F=9F=E5=90=8D=E6=89=98?= =?UTF-8?q?=E7=AE=A1=E8=AE=B0=E5=BD=95=E7=9A=84=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/core/acme-client/test/soa.spec.mjs | 11 +++++ .../src/dns-provider/domain-parser.ts | 49 ++++++++++--------- .../src/plugin/cert-plugin/acme.ts | 5 +- .../cname-record-info.vue | 16 +++--- .../src/router/source/modules/about.tsx | 6 +-- .../src/router/source/modules/certd.ts | 22 ++++----- .../cname/service/cname-provider-service.ts | 1 + .../cname/service/cname-record-service.ts | 33 ++++++++----- 8 files changed, 85 insertions(+), 58 deletions(-) create mode 100644 packages/core/acme-client/test/soa.spec.mjs diff --git a/packages/core/acme-client/test/soa.spec.mjs b/packages/core/acme-client/test/soa.spec.mjs new file mode 100644 index 00000000..a16a9215 --- /dev/null +++ b/packages/core/acme-client/test/soa.spec.mjs @@ -0,0 +1,11 @@ +import {assert} from 'chai' +import {resolveDomainBySoaRecord} from "../src/util.js" +describe('dns', () => { + it('resolveDomainBySoaRecord', async () => { + const resp = await resolveDomainBySoaRecord("a.corp.smartdeer.com") + + assert.equal(resp, "smartdeer.com") + + }); + +}) \ No newline at end of file diff --git a/packages/plugins/plugin-cert/src/dns-provider/domain-parser.ts b/packages/plugins/plugin-cert/src/dns-provider/domain-parser.ts index 08f48785..654c43db 100644 --- a/packages/plugins/plugin-cert/src/dns-provider/domain-parser.ts +++ b/packages/plugins/plugin-cert/src/dns-provider/domain-parser.ts @@ -1,7 +1,6 @@ import { IDomainParser, ISubDomainsGetter } from "./api"; //@ts-ignore import psl from "psl"; -import { resolveDomainBySoaRecord } from "@certd/acme-client"; import { logger, utils } from "@certd/basic"; export class DomainParser implements IDomainParser { @@ -10,7 +9,7 @@ export class DomainParser implements IDomainParser { this.subDomainsGetter = subDomainsGetter; } - parseDomain(fullDomain: string) { + parseDomainByPsl(fullDomain: string) { const parsed = psl.parse(fullDomain) as psl.ParsedDomain; if (parsed.error) { throw new Error(`解析${fullDomain}域名失败:` + JSON.stringify(parsed.error)); @@ -26,30 +25,34 @@ export class DomainParser implements IDomainParser { logger.info(`从缓存获取到主域名:${fullDomain}->${value}`); return value; } - try { - const mainDomain = await resolveDomainBySoaRecord(fullDomain); - if (mainDomain) { - utils.cache.set(cacheKey, mainDomain, { - ttl: 2 * 60 * 1000, - }); - logger.info(`获取到主域名:${fullDomain}->${mainDomain}`); - return mainDomain; - } - } catch (e) { - logger.error("从SOA获取主域名失败", e.message); - } - - // const subDomains = await this.subDomainsGetter.getSubDomains(); - // if (subDomains && subDomains.length > 0) { - // for (const subDomain of subDomains) { - // if (fullDomain.endsWith(subDomain)) { - // //找到子域名托管 - // return subDomain; - // } + // try { + // const mainDomain = await resolveDomainBySoaRecord(fullDomain); + // if (mainDomain) { + // utils.cache.set(cacheKey, mainDomain, { + // ttl: 2 * 60 * 1000, + // }); + // logger.info(`获取到主域名:${fullDomain}->${mainDomain}`); + // return mainDomain; // } + // } catch (e) { + // logger.error("从SOA获取主域名失败", e.message); // } - const res = this.parseDomain(fullDomain); + const subDomains = await this.subDomainsGetter.getSubDomains(); + if (subDomains && subDomains.length > 0) { + for (const subDomain of subDomains) { + if (fullDomain.endsWith(subDomain)) { + //找到子域名托管 + utils.cache.set(cacheKey, subDomain, { + ttl: 2 * 60 * 1000, + }); + logger.info(`获取到子域名托管域名:${fullDomain}->${subDomain}`); + return subDomain; + } + } + } + + const res = this.parseDomainByPsl(fullDomain); logger.info(`从psl获取主域名:${fullDomain}->${res}`); return res; } diff --git a/packages/plugins/plugin-cert/src/plugin/cert-plugin/acme.ts b/packages/plugins/plugin-cert/src/plugin/cert-plugin/acme.ts index f479be75..d01d8d11 100644 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/acme.ts +++ b/packages/plugins/plugin-cert/src/plugin/cert-plugin/acme.ts @@ -248,7 +248,10 @@ export class AcmeService { fullRecord = cname.fullRecord; } } else { - this.logger.error("未找到域名Cname校验计划,使用默认的dnsProvider"); + this.logger.error(`未找到域名${fullDomain}的CNAME校验计划,请修改证书申请配置`); + } + if (dnsProvider == null) { + throw new Error(`未找到域名${fullDomain}CNAME校验计划的DnsProvider,请修改证书申请配置`); } } else if (domainVerifyPlan.type === "http") { const httpVerifyPlan = domainVerifyPlan.httpVerifyPlan; diff --git a/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/cname-record-info.vue b/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/cname-record-info.vue index 610cbf2d..3f814dff 100644 --- a/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/cname-record-info.vue +++ b/packages/ui/certd-client/src/components/plugins/cert/domains-verify-plan-editor/cname-record-info.vue @@ -8,7 +8,7 @@ CNAME - + @@ -38,12 +38,12 @@ const statusDict = dict({ { label: "验证中", value: "validating", color: "blue" }, { label: "验证成功", value: "valid", color: "green" }, { label: "验证失败", value: "failed", color: "red" }, - { label: "验证超时", value: "timeout", color: "red" } - ] + { label: "验证超时", value: "timeout", color: "red" }, + ], }); defineOptions({ - name: "CnameRecordInfo" + name: "CnameRecordInfo", }); const props = defineProps<{ @@ -55,7 +55,7 @@ const emit = defineEmits<{ { id: number | null; status: string | null; - } + }, ]; }>(); @@ -64,7 +64,7 @@ const cnameRecord = ref(null); function onRecordChange() { emit("change", { id: cnameRecord.value?.id, - status: cnameRecord.value?.status + status: cnameRecord.value?.status, }); } @@ -90,11 +90,11 @@ async function doRefresh() { watch( () => props.domain, - async (value) => { + async value => { await doRefresh(); }, { - immediate: true + immediate: true, } ); diff --git a/packages/ui/certd-client/src/router/source/modules/about.tsx b/packages/ui/certd-client/src/router/source/modules/about.tsx index ff401a80..a2ca004e 100644 --- a/packages/ui/certd-client/src/router/source/modules/about.tsx +++ b/packages/ui/certd-client/src/router/source/modules/about.tsx @@ -16,9 +16,9 @@ export const aboutResource = [ show: () => { const settingStore = useSettingStore(); return !settingStore.isComm; - } - } - } + }, + }, + }, ]; export default aboutResource; diff --git a/packages/ui/certd-client/src/router/source/modules/certd.ts b/packages/ui/certd-client/src/router/source/modules/certd.ts index 2d6bd6e8..a9c992be 100644 --- a/packages/ui/certd-client/src/router/source/modules/certd.ts +++ b/packages/ui/certd-client/src/router/source/modules/certd.ts @@ -98,17 +98,17 @@ export const certdResources = [ keepAlive: true, }, }, - // { - // title: "子域名托管设置", - // name: "SubDomain", - // path: "/certd/pipeline/subDomain", - // component: "/certd/pipeline/sub-domain/index.vue", - // meta: { - // icon: "material-symbols:approval-delegation-outline", - // auth: true, - // keepAlive: true, - // }, - // }, + { + title: "子域名托管设置", + name: "SubDomain", + path: "/certd/pipeline/subDomain", + component: "/certd/pipeline/sub-domain/index.vue", + meta: { + icon: "material-symbols:approval-delegation-outline", + auth: true, + keepAlive: true, + }, + }, { title: "流水线分组管理", name: "PipelineGroupManager", diff --git a/packages/ui/certd-server/src/modules/cname/service/cname-provider-service.ts b/packages/ui/certd-server/src/modules/cname/service/cname-provider-service.ts index 0bdd9d82..d0a1b26b 100644 --- a/packages/ui/certd-server/src/modules/cname/service/cname-provider-service.ts +++ b/packages/ui/certd-server/src/modules/cname/service/cname-provider-service.ts @@ -114,4 +114,5 @@ export class CnameProviderService extends BaseService { } return await super.info(id, infoIgnoreProperty); } + } diff --git a/packages/ui/certd-server/src/modules/cname/service/cname-record-service.ts b/packages/ui/certd-server/src/modules/cname/service/cname-record-service.ts index e9adb77c..329a810f 100644 --- a/packages/ui/certd-server/src/modules/cname/service/cname-record-service.ts +++ b/packages/ui/certd-server/src/modules/cname/service/cname-record-service.ts @@ -20,6 +20,7 @@ type CnameCheckCacheValue = { recordRes?: any; startTime: number; intervalId?: NodeJS.Timeout; + dnsProvider?: IDnsProvider; }; /** * 授权 @@ -235,6 +236,23 @@ export class CnameRecordService extends BaseService { return dnsProvider; }; + const clearVerifyRecord = async () => { + cache.delete(cacheKey); + try { + let dnsProvider =value.dnsProvider + if (!dnsProvider) { + dnsProvider = await buildDnsProvider(); + } + await dnsProvider.removeRecord({ + recordReq: value.recordReq, + recordRes: value.recordRes, + }); + logger.info('删除CNAME的校验DNS记录成功'); + } catch (e) { + logger.error(`删除CNAME的校验DNS记录失败, ${e.message},req:${JSON.stringify(value.recordReq)},recordRes:${JSON.stringify(value.recordRes)}`, e); + } + }; + const checkRecordValue = async () => { if (value.pass) { return true; @@ -243,7 +261,7 @@ export class CnameRecordService extends BaseService { logger.warn(`cname验证超时,停止检查,${bean.domain} ${testRecordValue}`); clearInterval(value.intervalId); await this.updateStatus(bean.id, 'timeout'); - cache.delete(cacheKey); + await clearVerifyRecord() return false; } @@ -270,17 +288,7 @@ export class CnameRecordService extends BaseService { logger.info(`检测到CNAME配置,修改状态 ${fullDomain} ${testRecordValue}`); await this.updateStatus(bean.id, 'valid'); value.pass = true; - cache.delete(cacheKey); - try { - const dnsProvider = await buildDnsProvider(); - await dnsProvider.removeRecord({ - recordReq: value.recordReq, - recordRes: value.recordRes, - }); - logger.info('删除CNAME的校验DNS记录成功'); - } catch (e) { - logger.error(`删除CNAME的校验DNS记录失败, ${e.message},req:${JSON.stringify(value.recordReq)},recordRes:${JSON.stringify(value.recordRes)}`, e); - } + await clearVerifyRecord() return success; } }; @@ -306,6 +314,7 @@ export class CnameRecordService extends BaseService { }; const dnsProvider = await buildDnsProvider(); const recordRes = await dnsProvider.createRecord(req); + value.dnsProvider = dnsProvider; value.validating = true; value.recordReq = req; value.recordRes = recordRes;