mirror of https://github.com/certd/certd
chore: auto
parent
af5e1b805f
commit
896cd950e9
|
@ -62,12 +62,14 @@ export interface IDomainParser {
|
|||
|
||||
export type DnsVerifier = {
|
||||
// dns直接校验
|
||||
dnsProviderType: string;
|
||||
dnsProviderAccessId: number;
|
||||
dnsProviderType?: string;
|
||||
dnsProviderAccessId?: number;
|
||||
};
|
||||
|
||||
export type CnameVerifier = {
|
||||
cnameRecord: string;
|
||||
hostRecord: string;
|
||||
domain: string;
|
||||
recordValue: string;
|
||||
};
|
||||
|
||||
export type HttpVerifier = {
|
||||
|
|
|
@ -269,11 +269,11 @@ export class AcmeService {
|
|||
throw new Error("不支持的校验类型", domainVerifyPlan.type);
|
||||
}
|
||||
} else {
|
||||
this.logger.info("未找到域名校验计划,使用默认的dnsProvider");
|
||||
this.logger.warn(`未找到域名${fullDomain}的校验计划,使用默认的dnsProvider`);
|
||||
}
|
||||
}
|
||||
if (!dnsProvider) {
|
||||
this.logger.error("dnsProvider不存在,无法申请证书");
|
||||
throw new Error(`域名${fullDomain}没有匹配到任何校验方式,证书申请失败`);
|
||||
}
|
||||
|
||||
const dnsChallenge = getChallenge("dns-01");
|
||||
|
|
|
@ -66,15 +66,15 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
|||
{ value: "cname", label: "CNAME代理验证" },
|
||||
{ value: "http", label: "HTTP文件验证" },
|
||||
{ value: "dnses", label: "多DNS提供商" },
|
||||
{ value: "auto", label: "自动选择" },
|
||||
{ value: "auto", label: "自动匹配" },
|
||||
],
|
||||
},
|
||||
required: true,
|
||||
helper: `1. <b>DNS直接验证</b>:域名dns解析是在阿里云/腾讯云/华为云/CF/NameSilo/西数/火山/dns.la/京东云/51dns的,选它
|
||||
2. <b>CNAME代理验证</b>:支持任何注册商的域名,第一次需要手动添加CNAME记录(建议将DNS服务器修改为阿里云/腾讯云的,然后使用DNS直接验证)
|
||||
2. <b>CNAME代理验证</b>:支持任何注册商的域名,第一次需要手动添加[CNAME记录](#/certd/cname/record)(建议将DNS服务器修改为阿里云/腾讯云的,然后使用DNS直接验证)
|
||||
3. <b>HTTP文件验证</b>:不支持泛域名,需要配置网站文件上传
|
||||
4. <b>多DNS提供商</b>:每个域名可以选择独立的DNS提供商
|
||||
5. <b>自动选择</b>:需要在[域名管理](#/certd/cert/domain)中事先配置好校验方式
|
||||
5. <b>自动匹配</b>:需要在[域名管理](#/certd/cert/domain)中事先配置好校验方式
|
||||
`,
|
||||
})
|
||||
challengeType!: string;
|
||||
|
@ -469,13 +469,13 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
|||
for (const fullDomain of domains) {
|
||||
const domain = fullDomain.replaceAll("*.", "");
|
||||
const mainDomain = await domainParser.parse(domain);
|
||||
const planSetting = verifyPlanSetting[mainDomain];
|
||||
const planSetting: DomainVerifyPlanInput = verifyPlanSetting[mainDomain];
|
||||
if (planSetting.type === "dns") {
|
||||
await this.createDnsDomainVerifyPlan(planSetting[mainDomain], domain, mainDomain);
|
||||
plan[domain] = await this.createDnsDomainVerifyPlan(planSetting, domain, mainDomain);
|
||||
} else if (planSetting.type === "cname") {
|
||||
await this.createCnameDomainVerifyPlan(domain, mainDomain);
|
||||
plan[domain] = await this.createCnameDomainVerifyPlan(domain, mainDomain);
|
||||
} else if (planSetting.type === "http") {
|
||||
await this.createHttpDomainVerifyPlan(planSetting.httpVerifyPlan[domain], domain, mainDomain);
|
||||
plan[domain] = await this.createHttpDomainVerifyPlan(planSetting.httpVerifyPlan[domain], domain, mainDomain);
|
||||
}
|
||||
}
|
||||
return plan;
|
||||
|
@ -486,7 +486,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
|||
// domain list
|
||||
const domainList = new Set<string>();
|
||||
//整理域名
|
||||
for (let domain in this.domains) {
|
||||
for (let domain of domains) {
|
||||
domain = domain.replaceAll("*.", "");
|
||||
domainList.add(domain);
|
||||
}
|
||||
|
@ -563,7 +563,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
|||
domain,
|
||||
mainDomain,
|
||||
cnameVerifyPlan: {
|
||||
domain,
|
||||
domain: cnameRecord.cnameProvider.domain,
|
||||
fullRecord: cnameRecord.recordValue,
|
||||
dnsProvider,
|
||||
},
|
||||
|
|
|
@ -714,6 +714,7 @@ export default {
|
|||
},
|
||||
domain: {
|
||||
domainManager: "Domain Manager",
|
||||
domainDescription: "used to auto apply for certificate", //管理域名的校验方式,用于申请证书时自动选择验证方式
|
||||
domain: "Domain",
|
||||
challengeType: "Challenge Type",
|
||||
dnsProviderType: "DNS Provider Type",
|
||||
|
@ -722,5 +723,7 @@ export default {
|
|||
httpUploaderAccess: "HTTP Uploader Access",
|
||||
httpUploadRootDir: "HTTP Upload Root Dir",
|
||||
disabled: "Disabled",
|
||||
challengeSetting: "Challenge Setting",
|
||||
gotoCnameTip: "Please go to CNAME Record Page",
|
||||
},
|
||||
};
|
||||
|
|
|
@ -14,6 +14,8 @@ export default {
|
|||
search: "Search",
|
||||
enabled: "Enabled",
|
||||
disabled: "Disabled",
|
||||
enable: "Enable",
|
||||
disable: "Disable",
|
||||
edit: "Edit",
|
||||
delete: "Delete",
|
||||
create: "Create",
|
||||
|
|
|
@ -717,6 +717,7 @@ export default {
|
|||
},
|
||||
domain: {
|
||||
domainManager: "域名管理",
|
||||
domainDescription: "管理域名的校验方式,用于申请证书时自动选择验证方式",
|
||||
domain: "域名",
|
||||
challengeType: "校验类型",
|
||||
dnsProviderType: "DNS提供商类型",
|
||||
|
@ -725,5 +726,7 @@ export default {
|
|||
httpUploaderAccess: "上传授权信息",
|
||||
httpUploadRootDir: "网站根路径",
|
||||
disabled: "禁用/启用",
|
||||
challengeSetting: "校验配置",
|
||||
gotoCnameTip: "CNAME域名配置请前往CNAME记录页面添加",
|
||||
},
|
||||
};
|
||||
|
|
|
@ -14,6 +14,8 @@ export default {
|
|||
search: "搜索",
|
||||
enabled: "已启用",
|
||||
disabled: "已禁用",
|
||||
enable: "启用",
|
||||
disable: "禁用",
|
||||
edit: "修改",
|
||||
delete: "删除",
|
||||
create: "新增",
|
||||
|
|
|
@ -7,6 +7,7 @@ import { useUserStore } from "/@/store/user";
|
|||
import { useSettingStore } from "/@/store/settings";
|
||||
import { Dicts } from "/@/components/plugins/lib/dicts";
|
||||
import { createAccessApi } from "/@/views/certd/access/api";
|
||||
import { Modal } from "ant-design-vue";
|
||||
|
||||
export default function ({ crudExpose, context }: CreateCrudOptionsProps): CreateCrudOptionsRet {
|
||||
const router = useRouter();
|
||||
|
@ -73,13 +74,20 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
delRequest,
|
||||
},
|
||||
tabs: {
|
||||
name: "status",
|
||||
name: "challengeType",
|
||||
show: true,
|
||||
},
|
||||
rowHandle: {
|
||||
minWidth: 200,
|
||||
fixed: "right",
|
||||
},
|
||||
form: {
|
||||
beforeSubmit({ form }) {
|
||||
if (form.challengeType === "cname") {
|
||||
throw new Error("CNAME方式请前往CNAME记录页面进行管理");
|
||||
}
|
||||
},
|
||||
},
|
||||
columns: {
|
||||
id: {
|
||||
title: "ID",
|
||||
|
@ -114,11 +122,28 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
title: t("certd.domain.challengeType"),
|
||||
type: "dict-select",
|
||||
dict: Dicts.challengeTypeDict,
|
||||
search: {
|
||||
show: true,
|
||||
},
|
||||
form: {
|
||||
required: true,
|
||||
valueChange({ value }) {
|
||||
if (value === "cname") {
|
||||
Modal.confirm({
|
||||
title: t("certd.domain.gotoCnameTip"),
|
||||
async onOk() {
|
||||
router.push({
|
||||
path: "/certd/cname/record",
|
||||
});
|
||||
crudExpose.getFormWrapperRef().close();
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
column: {
|
||||
sorter: true,
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
/**
|
||||
|
@ -196,6 +221,10 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
form: {
|
||||
component: {
|
||||
name: "AccessSelector",
|
||||
vModel: "modelValue",
|
||||
type: compute(({ form }) => {
|
||||
return form.httpUploaderType;
|
||||
}),
|
||||
},
|
||||
show: compute(({ form }) => {
|
||||
return form.challengeType === "http";
|
||||
|
@ -226,16 +255,17 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
},
|
||||
},
|
||||
challengeSetting: {
|
||||
title: "校验配置",
|
||||
title: t("certd.domain.challengeSetting"),
|
||||
type: "text",
|
||||
form: { show: false },
|
||||
column: {
|
||||
width: 400,
|
||||
width: 600,
|
||||
conditionalRender: false,
|
||||
cellRender({ row }) {
|
||||
if (row.challengeType === "dns") {
|
||||
return (
|
||||
<div class={"flex"}>
|
||||
<fs-values-format modelValue={row.challengeType} dict={Dicts.challengeTypeDict} color={"auto"}></fs-values-format>
|
||||
<fs-values-format modelValue={row.dnsProviderType} dict={dnsProviderTypeDict} color={"auto"}></fs-values-format>
|
||||
<fs-values-format class={"ml-5"} modelValue={row.dnsProviderAccess} dict={accessDict} color={"auto"}></fs-values-format>
|
||||
</div>
|
||||
|
@ -243,9 +273,10 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
} else if (row.challengeType === "http") {
|
||||
return (
|
||||
<div class={"flex"}>
|
||||
<fs-values-format modelValue={row.challengeType} dict={Dicts.challengeTypeDict} color={"auto"}></fs-values-format>
|
||||
<fs-values-format modelValue={row.httpUploaderType} dict={httpUploaderTypeDict} color={"auto"}></fs-values-format>
|
||||
<fs-values-format class={"ml-5"} modelValue={row.httpUploaderAccess} dict={accessDict} color={"auto"}></fs-values-format>
|
||||
<a-tag class={"ml-5"}>{row.httpUploadRootDir}</a-tag>
|
||||
<a-tag class={"ml-5 flex items-center"}>路径:{row.httpUploadRootDir}</a-tag>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -255,10 +286,11 @@ export default function ({ crudExpose, context }: CreateCrudOptionsProps): Creat
|
|||
disabled: {
|
||||
title: t("certd.domain.disabled"),
|
||||
type: "dict-switch",
|
||||
search: { show: true },
|
||||
dict: dict({
|
||||
data: [
|
||||
{ label: "启用", value: false, color: "green" },
|
||||
{ label: "禁用", value: true, color: "red" },
|
||||
{ label: t("common.enabled"), value: false, color: "green" },
|
||||
{ label: t("common.disabled"), value: true, color: "red" },
|
||||
],
|
||||
}),
|
||||
form: {
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
<template #header>
|
||||
<div class="title">
|
||||
{{ t("certd.domain.domainManager") }}
|
||||
<span class="sub"> </span>
|
||||
<span class="sub">
|
||||
{{ t("certd.domain.domainDescription") }}
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||
|
|
|
@ -7,6 +7,8 @@ import {SubDomainService} from "../../pipeline/service/sub-domain-service.js";
|
|||
import {DomainParser} from "@certd/plugin-cert/dist/dns-provider/domain-parser.js";
|
||||
import {DomainVerifiers} from "@certd/plugin-cert";
|
||||
import { SubDomainsGetter } from '../../pipeline/service/getter/sub-domain-getter.js';
|
||||
import { CnameRecordService } from '../../cname/service/cname-record-service.js';
|
||||
import { CnameRecordEntity } from "../../cname/entity/cname-record.js";
|
||||
|
||||
|
||||
/**
|
||||
|
@ -23,6 +25,9 @@ export class DomainService extends BaseService<DomainEntity> {
|
|||
@Inject()
|
||||
subDomainService: SubDomainService;
|
||||
|
||||
@Inject()
|
||||
cnameRecordService: CnameRecordService;
|
||||
|
||||
//@ts-ignore
|
||||
getRepository() {
|
||||
return this.repository;
|
||||
|
@ -96,10 +101,12 @@ export class DomainService extends BaseService<DomainEntity> {
|
|||
//去重
|
||||
allDomains = [...new Set(allDomains)]
|
||||
|
||||
//从 domain 表中获取配置
|
||||
const domainRecords = await this.find({
|
||||
where: {
|
||||
domain: In(allDomains),
|
||||
userId
|
||||
userId,
|
||||
disabled:false,
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -107,16 +114,28 @@ export class DomainService extends BaseService<DomainEntity> {
|
|||
pre[item.domain] = item
|
||||
return pre
|
||||
}, {})
|
||||
const cnameMap = domainRecords.filter(item=>item.challengeType === 'cname').reduce((pre, item) => {
|
||||
pre[item.domain] = item
|
||||
return pre
|
||||
}, {})
|
||||
|
||||
const httpMap = domainRecords.filter(item=>item.challengeType === 'http').reduce((pre, item) => {
|
||||
pre[item.domain] = item
|
||||
return pre
|
||||
}, {})
|
||||
|
||||
|
||||
//从cname record表中获取配置
|
||||
const cnameRecords = await this.cnameRecordService.find({
|
||||
where: {
|
||||
domain: In(allDomains),
|
||||
userId,
|
||||
status: "valid",
|
||||
}
|
||||
})
|
||||
|
||||
const cnameMap = cnameRecords.reduce((pre, item) => {
|
||||
pre[item.domain] = item
|
||||
return pre
|
||||
}, {})
|
||||
|
||||
//构建域名验证计划
|
||||
const domainVerifiers:DomainVerifiers = {}
|
||||
|
||||
for (const domain of domains) {
|
||||
|
@ -130,19 +149,21 @@ export class DomainService extends BaseService<DomainEntity> {
|
|||
type: 'dns',
|
||||
dns: {
|
||||
dnsProviderType: dnsRecord.dnsProviderType,
|
||||
dnsProviderAccessId: dnsRecord.dnsProviderAccessId
|
||||
dnsProviderAccessId: dnsRecord.dnsProviderAccess
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
const cnameRecord = cnameMap[mainDomain]
|
||||
const cnameRecord:CnameRecordEntity = cnameMap[mainDomain]
|
||||
if (cnameRecord) {
|
||||
domainVerifiers[domain] = {
|
||||
domain,
|
||||
mainDomain,
|
||||
type: 'cname',
|
||||
cname: {
|
||||
cnameRecord: cnameRecord.cnameRecord
|
||||
domain: cnameRecord.domain,
|
||||
hostRecord: cnameRecord.hostRecord,
|
||||
recordValue: cnameRecord.recordValue
|
||||
}
|
||||
}
|
||||
continue
|
||||
|
|
Loading…
Reference in New Issue