diff --git a/docs/guide/use/rerun/images/rerun.png b/docs/guide/use/rerun/images/rerun.png new file mode 100644 index 000000000..41f853021 Binary files /dev/null and b/docs/guide/use/rerun/images/rerun.png differ diff --git a/docs/guide/use/rerun/index.md b/docs/guide/use/rerun/index.md new file mode 100644 index 000000000..29ad53b6a --- /dev/null +++ b/docs/guide/use/rerun/index.md @@ -0,0 +1,5 @@ +# 如何强制重新执行任务 + +## 强制重新执行任务 + +![](./images/rerun.png) \ No newline at end of file diff --git a/packages/core/acme-client/src/auto.js b/packages/core/acme-client/src/auto.js index 087d28f2d..07635263e 100644 --- a/packages/core/acme-client/src/auto.js +++ b/packages/core/acme-client/src/auto.js @@ -182,12 +182,19 @@ module.exports = async (client, userOpts) => { authorizations.forEach((authz) => { const d = authz.identifier.value; + log(`authorization:domain = ${d}, value = ${JSON.stringify(authz)}`); + + if (authz.status === 'valid') { + log(`[auto] [${d}] Authorization already has valid status, no need to complete challenges`); + return; + } let setd = false; // eslint-disable-next-line no-restricted-syntax for (const group of domainSets) { if (!group[d]) { group[d] = authz; setd = true; + break; } } if (!setd) { @@ -197,6 +204,8 @@ module.exports = async (client, userOpts) => { } }); + // log(`domainSets:${JSON.stringify(domainSets)}`); + const allChallengePromises = []; // eslint-disable-next-line no-restricted-syntax for (const domainSet of domainSets) { @@ -252,17 +261,34 @@ module.exports = async (client, userOpts) => { log(`证书申请失败${e.message}`); throw e; } + finally { + if (client.opts.sslProvider !== 'google') { + // letsencrypt 如果同时检出两个TXT记录,会以第一个为准,就会校验失败,所以需要提前删除 + log(`清理challenge痕迹,length:${clearTasks.length}`); + try { + // eslint-disable-next-line no-await-in-loop + await runAllPromise(clearTasks); + } + catch (e) { + log('清理challenge失败'); + log(e); + } + } + } } } finally { - log(`清理challenge痕迹,length:${clearTasks.length}`); - try { + if (client.opts.sslProvider === 'google') { + // google 相同的域名txt记录是一样的,不能提前删除,否则校验失败 + log(`清理challenge痕迹,length:${clearTasks.length}`); + try { // eslint-disable-next-line no-await-in-loop - await runAllPromise(clearTasks); - } - catch (e) { - log('清理challenge失败'); - log(e); + await runAllPromise(clearTasks); + } + catch (e) { + log('清理challenge失败'); + log(e); + } } } diff --git a/packages/core/acme-client/src/client.js b/packages/core/acme-client/src/client.js index f32cd17cc..f96adc370 100644 --- a/packages/core/acme-client/src/client.js +++ b/packages/core/acme-client/src/client.js @@ -558,6 +558,7 @@ class AcmeClient { const verifyFn = async (abort) => { if (this.opts.signal && this.opts.signal.aborted) { + abort(); throw new Error('用户取消'); } diff --git a/packages/core/acme-client/src/logger.js b/packages/core/acme-client/src/logger.js index 3659c5176..166a7a9ce 100644 --- a/packages/core/acme-client/src/logger.js +++ b/packages/core/acme-client/src/logger.js @@ -22,7 +22,7 @@ exports.setLogger = (fn) => { * @param {string} msg Message */ -exports.log = (msg) => { - debug(msg); - logger(msg); +exports.log = (...msg) => { + debug(...msg); + logger(...msg); }; diff --git a/packages/core/acme-client/types/index.d.ts b/packages/core/acme-client/types/index.d.ts index 77a0122dc..56e4cf110 100644 --- a/packages/core/acme-client/types/index.d.ts +++ b/packages/core/acme-client/types/index.d.ts @@ -37,6 +37,7 @@ export type UrlMapping={ */ export interface ClientOptions { + sslProvider:string; directoryUrl: string; accountKey: PrivateKeyBuffer | PrivateKeyString; accountUrl?: string; 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 0160094cf..79784e048 100644 --- a/packages/plugins/plugin-cert/src/plugin/cert-plugin/acme.ts +++ b/packages/plugins/plugin-cert/src/plugin/cert-plugin/acme.ts @@ -89,12 +89,15 @@ export class AcmeService { } async getAcmeClient(email: string, isTest = false): Promise { + const mappings = {}; + if (this.sslProvider === "google") { + mappings["acme-v02.api.letsencrypt.org"] = this.options.reverseProxy || "le.px.certd.handfree.work"; + } else if (this.sslProvider === "letsencrypt") { + mappings["dv.acme-v02.api.pki.goog"] = this.options.reverseProxy || "gg.px.certd.handfree.work"; + } const urlMapping: UrlMapping = { enabled: false, - mappings: { - "acme-v02.api.letsencrypt.org": this.options.reverseProxy || "le.px.certd.handfree.work", - "dv.acme-v02.api.pki.goog": this.options.reverseProxy || "gg.px.certd.handfree.work", - }, + mappings, }; const conf = await this.getAccountConfig(email, urlMapping); if (conf.key == null) { @@ -119,6 +122,7 @@ export class AcmeService { } } const client = new acme.Client({ + sslProvider: this.sslProvider, directoryUrl: directoryUrl, accountKey: conf.key, accountUrl: conf.accountUrl, @@ -172,7 +176,7 @@ export class AcmeService { this.logger.info(`Would create TXT record "${fullRecord}" with value "${recordValue}"`); let domain = parseDomain(fullDomain); - this.logger.info("解析到域名domain=", domain); + this.logger.info("解析到域名domain=" + domain); if (domainsVerifyPlan) { //按照计划执行 diff --git a/packages/ui/certd-client/src/router/source/header.ts b/packages/ui/certd-client/src/router/source/header.ts index 7467caef3..5a074857a 100644 --- a/packages/ui/certd-client/src/router/source/header.ts +++ b/packages/ui/certd-client/src/router/source/header.ts @@ -1,7 +1,10 @@ export const headerResource = [ { title: "文档", - path: "https://certd.docmirror.cn" + path: "https://certd.docmirror.cn", + meta: { + icon: "ion:document-text-outline" + }, }, { title: "源码", diff --git a/packages/ui/certd-client/src/style/common.less b/packages/ui/certd-client/src/style/common.less index 13d8b97c0..361011c21 100644 --- a/packages/ui/certd-client/src/style/common.less +++ b/packages/ui/certd-client/src/style/common.less @@ -170,6 +170,9 @@ h1, h2, h3, h4, h5, h6 { color: #1890ff; } +.iconify{ + //font-size: 16px; +} .icon-box { display: inline-flex; diff --git a/packages/ui/certd-client/src/views/certd/pipeline/pipeline/index.vue b/packages/ui/certd-client/src/views/certd/pipeline/pipeline/index.vue index 3f5ec18cd..70e69d7c1 100644 --- a/packages/ui/certd-client/src/views/certd/pipeline/pipeline/index.vue +++ b/packages/ui/certd-client/src/views/certd/pipeline/pipeline/index.vue @@ -101,8 +101,9 @@ diff --git a/packages/ui/certd-server/src/plugins/plugin-cloudflare/dns-provider.ts b/packages/ui/certd-server/src/plugins/plugin-cloudflare/dns-provider.ts index f4b1ce1fc..fe67282a0 100644 --- a/packages/ui/certd-server/src/plugins/plugin-cloudflare/dns-provider.ts +++ b/packages/ui/certd-server/src/plugins/plugin-cloudflare/dns-provider.ts @@ -37,8 +37,12 @@ export class CloudflareDnsProvider extends AbstractDnsProvider } async getZoneId(domain: string) { + this.logger.info('获取zoneId:', domain); const url = `https://api.cloudflare.com/client/v4/zones?name=${domain}`; const res = await this.doRequestApi(url, null, 'get'); + if (res.result.length === 0) { + throw new Error(`未找到域名${domain}的zoneId`); + } return res.result[0].id; }