From 71f6d5769ae09868908b3419a5a4f8b88987637f Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Thu, 24 Dec 2020 00:49:31 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20dnspod=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/certd/package.json | 3 + packages/certd/src/acme.js | 88 +++++++++++++------ .../certd/src/dns-provider/dns-provider.js | 26 +++++- .../certd/src/dns-provider/impl/aliyun.js | 24 +++-- .../certd/src/dns-provider/impl/dnspod.js | 76 ++++++++++++++++ packages/certd/src/index.js | 2 +- packages/certd/src/utils/util.request.js | 56 ++++++++++++ .../certd/test/dns-provider/aliyun.test.js | 24 +++-- .../certd/test/dns-provider/dnspod.test.js | 36 ++++++++ packages/certd/test/index.test.js | 13 +-- packages/certd/test/options.js | 5 +- packages/certd/yarn.lock | 40 +++------ packages/node-acme-client | 2 +- 13 files changed, 300 insertions(+), 95 deletions(-) create mode 100644 packages/certd/src/dns-provider/impl/dnspod.js create mode 100644 packages/certd/src/utils/util.request.js create mode 100644 packages/certd/test/dns-provider/dnspod.test.js diff --git a/packages/certd/package.json b/packages/certd/package.json index 3200c4f0..e8d97f01 100644 --- a/packages/certd/package.json +++ b/packages/certd/package.json @@ -12,9 +12,12 @@ "dependencies": { "@alicloud/pop-core": "^1.7.10", "@types/node": "^14.14.13", + "axios": "^0.21.1", "dayjs": "^1.9.7", "lodash": "^4.17.20", "log4js": "^6.3.0", + "node-forge": "^0.10.0", + "qs": "^6.9.4", "@certd/acme-client": "^0.0.1" }, "devDependencies": { diff --git a/packages/certd/src/acme.js b/packages/certd/src/acme.js index d544a1e5..69d922cc 100644 --- a/packages/certd/src/acme.js +++ b/packages/certd/src/acme.js @@ -1,47 +1,58 @@ import log from './utils/util.log.js' import acme from '@certd/acme-client' import _ from 'lodash' +import path from 'path' import sleep from './utils/util.sleep.js' export class AcmeService { constructor (store) { this.store = store } - async getAccountKey (email) { - let key = this.store.get(this.buildAccountKeyPath(email)) - if (key == null) { - key = await this.createNewKey({ email }) + async getAccountConfig (email) { + let conf = this.store.get(this.buildAccountPath(email)) + if (conf == null) { + conf = {} + } else { + conf = JSON.parse(conf) } - return key + return conf } - buildAccountKeyPath (email) { - return email + '/acme/account.key' + buildAccountPath (email) { + return path.join(email, '/account.json') } - setAccountKey (email, privateKey) { - this.store.set(this.buildAccountKeyPath(email), privateKey) + saveAccountConfig (email, conf) { + this.store.set(this.buildAccountPath(email), JSON.stringify(conf)) } async getAcmeClient (email) { - const key = await this.getAccountKey(email) + const conf = await this.getAccountConfig(email) + if (conf.key == null) { + conf.key = await this.createNewKey() + this.saveAccountConfig(email, conf) + } const client = new acme.Client({ directoryUrl: acme.directory.letsencrypt.staging, - accountKey: key, - backoffAttempts: 10, + accountKey: conf.key, + accountUrl: conf.accountUrl, + backoffAttempts: 20, backoffMin: 5000, backoffMax: 10000 }) + + if (conf.accountUrl == null) { + const accountPayload = { termsOfServiceAgreed: true, contact: [`mailto:${email}`] } + await client.createAccount(accountPayload) + conf.accountUrl = client.getAccountUrl() + this.saveAccountConfig(email, conf) + } return client } - async createNewKey ({ email }) { - const privateKey = await acme.forge.createPrivateKey() - this.setAccountKey(email, privateKey) - } - - async loggerin () { - + async createNewKey () { + const key = await acme.forge.createPrivateKey() + return key.toString() } async challengeCreateFn (authz, challenge, keyAuthorization, dnsProvider) { @@ -67,7 +78,11 @@ export class AcmeService { /* Replace this */ log.info(`Would create TXT record "${dnsRecord}" with value "${recordValue}"`) - return await dnsProvider.createRecord(dnsRecord, 'TXT', recordValue) + return await dnsProvider.createRecord({ + fullRecord: dnsRecord, + type: 'TXT', + value: recordValue + }) } } @@ -77,10 +92,12 @@ export class AcmeService { * @param {object} authz Authorization object * @param {object} challenge Selected challenge * @param {string} keyAuthorization Authorization key + * @param recordItem challengeCreateFn create record item + * @param dnsProvider dnsProvider * @returns {Promise} */ - async challengeRemoveFn (authz, challenge, keyAuthorization, dnsProvider) { + async challengeRemoveFn (authz, challenge, keyAuthorization, recordItem, dnsProvider) { log.info('Triggered challengeRemoveFn()') /* http-01 */ @@ -100,12 +117,24 @@ export class AcmeService { /* Replace this */ log.info(`Would remove TXT record "${dnsRecord}" with value "${recordValue}"`) - await dnsProvider.removeRecord(dnsRecord, 'TXT', keyAuthorization) + await dnsProvider.removeRecord({ + fullRecord: dnsRecord, + type: 'TXT', + value: keyAuthorization, + record: recordItem + }) } } async order ({ email, domains, dnsProvider, dnsProviderCreator, csrInfo }) { const client = await this.getAcmeClient(email) + + let accountUrl + try { + accountUrl = client.getAccountUrl() + } catch (e) { + } + /* Create CSR */ const { commonName, altNames } = this.buildCommonNameByDomains(domains) @@ -120,7 +149,7 @@ export class AcmeService { if (dnsProvider == null) { throw new Error('dnsProvider 不能为空') } - /* Certificate */ + /* 自动申请证书 */ const crt = await client.auto({ csr, email: email, @@ -129,11 +158,20 @@ export class AcmeService { challengeCreateFn: async (authz, challenge, keyAuthorization) => { return await this.challengeCreateFn(authz, challenge, keyAuthorization, dnsProvider) }, - challengeRemoveFn: async (authz, challenge, keyAuthorization) => { - return await this.challengeRemoveFn(authz, challenge, keyAuthorization, dnsProvider) + challengeRemoveFn: async (authz, challenge, keyAuthorization, recordItem) => { + return await this.challengeRemoveFn(authz, challenge, keyAuthorization, recordItem, dnsProvider) } }) + // 保存账号url + if (!accountUrl) { + try { + accountUrl = client.getAccountUrl() + this.setAccountUrl(email, accountUrl) + } catch (e) { + log.warn('保存accountUrl出错', e) + } + } /* Done */ log.debug(`CSR:\n${csr.toString()}`) log.debug(`Certificate:\n${crt.toString()}`) diff --git a/packages/certd/src/dns-provider/dns-provider.js b/packages/certd/src/dns-provider/dns-provider.js index 7754403f..307a35a3 100644 --- a/packages/certd/src/dns-provider/dns-provider.js +++ b/packages/certd/src/dns-provider/dns-provider.js @@ -1,9 +1,29 @@ +import _ from 'lodash' export class DnsProvider { - createRecord (dnsRecord, type, recordValue) { - + async createRecord ({ fullRecord, type, value }) { + throw new Error('请实现 createRecord 方法') } - removeRecord (dnsRecord, type, recordValue) { + async removeRecord ({ fullRecord, type, value, record }) { + throw new Error('请实现 removeRecord 方法') + } + async getDomainList () { + throw new Error('请实现 getDomainList 方法') + } + + async matchDomain (dnsRecord, domainPropName) { + const list = await this.getDomainList() + let domain = null + for (const item of list) { + if (_.endsWith(dnsRecord, item[domainPropName])) { + domain = item + break + } + } + if (!domain) { + throw new Error('找不到域名,请检查域名是否正确:' + dnsRecord) + } + return domain } } diff --git a/packages/certd/src/dns-provider/impl/aliyun.js b/packages/certd/src/dns-provider/impl/aliyun.js index a33fc295..27f98828 100644 --- a/packages/certd/src/dns-provider/impl/aliyun.js +++ b/packages/certd/src/dns-provider/impl/aliyun.js @@ -59,17 +59,18 @@ export default class AliyunDnsProvider extends DnsProvider { return ret.DomainRecords.Record } - async createRecord (dnsRecord, type, recordValue) { - log.info('添加域名解析:', dnsRecord, recordValue) - const domain = await this.matchDomain(dnsRecord) - const rr = dnsRecord.replace('.' + domain, '') + async createRecord ({ fullRecord, type, value }) { + log.info('添加域名解析:', fullRecord, value) + const domain = await this.matchDomain(fullRecord) + const rr = fullRecord.replace('.' + domain, '') const params = { RegionId: 'cn-hangzhou', DomainName: domain, RR: rr, Type: type, - Value: recordValue + Value: value, + Line: 'oversea' // 海外 } const requestOption = { @@ -78,7 +79,7 @@ export default class AliyunDnsProvider extends DnsProvider { try { const ret = await this.client.request('AddDomainRecord', params, requestOption) - console.log('添加域名解析成功:', dnsRecord, recordValue, ret.RecordId) + console.log('添加域名解析成功:', value, value, ret.RecordId) return ret.RecordId } catch (e) { // e.code === 'DomainRecordDuplicate' @@ -87,15 +88,10 @@ export default class AliyunDnsProvider extends DnsProvider { } } - async removeRecord (dnsRecord, type, value) { - const domain = await this.matchDomain(dnsRecord) - const rr = dnsRecord.replace('.' + domain, '') - - const record = await this.getRecords(domain, rr, value) - + async removeRecord ({ fullRecord, type, value, record }) { const params = { RegionId: 'cn-hangzhou', - RecordId: record[0].RecordId + RecordId: record } const requestOption = { @@ -103,7 +99,7 @@ export default class AliyunDnsProvider extends DnsProvider { } const ret = await this.client.request('DeleteDomainRecord', params, requestOption) - log.info('删除域名解析成功:', dnsRecord, value, ret.RecordId) + log.info('删除域名解析成功:', fullRecord, value, ret.RecordId) return ret.RecordId } } diff --git a/packages/certd/src/dns-provider/impl/dnspod.js b/packages/certd/src/dns-provider/impl/dnspod.js new file mode 100644 index 00000000..c86dddf2 --- /dev/null +++ b/packages/certd/src/dns-provider/impl/dnspod.js @@ -0,0 +1,76 @@ +import { DnsProvider } from '../dns-provider.js' +import _ from 'lodash' +import log from '../../utils/util.log.js' +import { request } from '../../utils/util.request.js' +export default class DnspodDnsProvider extends DnsProvider { + constructor (dnsProviderConfig) { + super() + if (!dnsProviderConfig.id || !dnsProviderConfig.token) { + throw new Error('请正确配置dnspod的 id 和 token') + } + this.loginToken = dnsProviderConfig.id + ',' + dnsProviderConfig.token + } + + async doRequest (options) { + const config = { + method: 'post', + formData: { + login_token: this.loginToken, + format: 'json', + lang: 'cn', + error_on_empty: 'no' + }, + timeout: 5000 + } + _.merge(config, options) + + const ret = await request(config) + if (ret?.status?.code !== '1') { + throw new Error('请求失败:' + ret.status.message + ',api=' + config.url) + } + return ret + } + + async getDomainList () { + const ret = await this.doRequest({ + url: 'https://dnsapi.cn/Domain.List' + }) + log.debug('dnspod 域名列表:', ret.domains) + return ret.domains + } + + async createRecord ({ fullRecord, type, value }) { + log.info('添加域名解析:', fullRecord, value) + const domainItem = await this.matchDomain(fullRecord, 'name') + const domain = domainItem.name + const rr = fullRecord.replace('.' + domain, '') + + const ret = await this.doRequest({ + url: 'https://dnsapi.cn/Record.Create', + formData: { + domain, + sub_domain: rr, + record_type: type, + record_line: '默认', + value: value, + mx: 1 + } + }) + console.log('添加域名解析成功:', fullRecord, value, JSON.stringify(ret.record)) + return ret.record + } + + async removeRecord ({ fullRecord, type, value, record }) { + const domain = await this.matchDomain(fullRecord, 'name') + + const ret = await this.doRequest({ + url: 'https://dnsapi.cn/Record.Remove', + formData: { + domain, + record_id: record.id + } + }) + log.info('删除域名解析成功:', fullRecord, value) + return ret.RecordId + } +} diff --git a/packages/certd/src/index.js b/packages/certd/src/index.js index 0b1a578b..c784929a 100644 --- a/packages/certd/src/index.js +++ b/packages/certd/src/index.js @@ -95,7 +95,7 @@ export class Certd { async createDnsProvider (options) { const accessProviders = options.accessProviders - const providerOptions = accessProviders[options.cert.challenge.dnsProvider] + const providerOptions = accessProviders[options.cert.dnsProvider] return await DnsProviderFactory.createByType(providerOptions.providerType, providerOptions) } diff --git a/packages/certd/src/utils/util.request.js b/packages/certd/src/utils/util.request.js new file mode 100644 index 00000000..abda5aaa --- /dev/null +++ b/packages/certd/src/utils/util.request.js @@ -0,0 +1,56 @@ +import axios from 'axios' +import log from './util.log.js' +import qs from 'qs' +/** + * @description 创建请求实例 + */ +function createService () { + // 创建一个 axios 实例 + const service = axios.create() + // 请求拦截 + service.interceptors.request.use( + config => { + if (config.formData) { + config.data = qs.stringify(config.formData, { + arrayFormat: 'indices', + allowDots: true + }) // 序列化请求参数 + delete config.formData + } + return config + }, + error => { + // 发送失败 + log.error(error) + return Promise.reject(error) + } + ) + // 响应拦截 + service.interceptors.response.use( + response => { + return response.data + }, + error => { + // const status = _.get(error, 'response.status') + // switch (status) { + // case 400: error.message = '请求错误'; break + // case 401: error.message = '未授权,请登录'; break + // case 403: error.message = '拒绝访问'; break + // case 404: error.message = `请求地址出错: ${error.response.config.url}`; break + // case 408: error.message = '请求超时'; break + // case 500: error.message = '服务器内部错误'; break + // case 501: error.message = '服务未实现'; break + // case 502: error.message = '网关错误'; break + // case 503: error.message = '服务不可用'; break + // case 504: error.message = '网关超时'; break + // case 505: error.message = 'HTTP版本不受支持'; break + // default: break + // } + log.error('请求出错:', error.response.config.url, error) + return Promise.reject(error) + } + ) + return service +} + +export const request = createService() diff --git a/packages/certd/test/dns-provider/aliyun.test.js b/packages/certd/test/dns-provider/aliyun.test.js index 0eec3899..830c31b1 100644 --- a/packages/certd/test/dns-provider/aliyun.test.js +++ b/packages/certd/test/dns-provider/aliyun.test.js @@ -1,6 +1,7 @@ import pkg from 'chai' import options from '../options.js' import AliyunDnsProvider from '../../src/dns-provider/impl/aliyun.js' +import { Certd } from '../../src/index.js' const { expect } = pkg describe('AliyunDnsProvider', function () { it('#getDomainList', async function () { @@ -17,17 +18,26 @@ describe('AliyunDnsProvider', function () { expect(recordList.length).gt(0) }) - it('#createRecord', async function () { + it('#createAndRemoveRecord', async function () { const aliyunDnsProvider = new AliyunDnsProvider(options.accessProviders.aliyun) - const recordId = await aliyunDnsProvider.createRecord('___certd___.__test__.docmirror.cn', 'TXT', 'aaaa') + const record = await aliyunDnsProvider.createRecord({ fullRecord: '___certd___.__test__.docmirror.cn', type: 'TXT', value: 'aaaa' }) + console.log('recordId', record) + expect(record != null).ok + + const recordId = await aliyunDnsProvider.removeRecord({ fullRecord: '___certd___.__test__.docmirror.cn', type: 'TXT', value: 'aaaa', record }) console.log('recordId', recordId) expect(recordId != null).ok }) - it('#removeRecord', async function () { - const aliyunDnsProvider = new AliyunDnsProvider(options.accessProviders.aliyun) - const recordId = await aliyunDnsProvider.removeRecord('___certd___.__test__.docmirror.cn', 'TXT', 'aaaa') - console.log('recordId', recordId) - expect(recordId != null).ok + it('#申请证书-aliyun', async function () { + this.timeout(300000) + options.args = { forceCert: true } + const certd = new Certd() + const cert = await certd.certApply(options) + expect(cert).ok + expect(cert.crt).ok + expect(cert.key).ok + expect(cert.detail).ok + expect(cert.expires).ok }) }) diff --git a/packages/certd/test/dns-provider/dnspod.test.js b/packages/certd/test/dns-provider/dnspod.test.js new file mode 100644 index 00000000..503d2a4c --- /dev/null +++ b/packages/certd/test/dns-provider/dnspod.test.js @@ -0,0 +1,36 @@ +import pkg from 'chai' +import options from '../options.js' +import DnspodDnsProvider from '../../src/dns-provider/impl/dnspod.js' +import { Certd } from '../../src/index.js' +const { expect } = pkg +describe('DnspodDnsProvider', function () { + it('#getDomainList', async function () { + const dnsProvider = new DnspodDnsProvider(options.accessProviders.dnspod) + const domainList = await dnsProvider.getDomainList() + console.log('domainList', domainList) + expect(domainList.length).gt(0) + }) + + it('#createRecord&removeRecord', async function () { + const dnsProvider = new DnspodDnsProvider(options.accessProviders.dnspod) + const record = await dnsProvider.createRecord({ fullRecord: '___certd___.__test__.certd.xyz', type: 'TXT', value: 'aaaa' }) + console.log('recordId', record.id) + expect(record.id != null).ok + + await dnsProvider.removeRecord({ fullRecord: '___certd___.__test__.certd.xyz', type: 'TXT', value: 'aaaa', record }) + }) + + it('#申请证书', async function () { + this.timeout(300000) + options.cert.domains = ['*.certd.xyz', 'certd.xyz'] + options.cert.dnsProvider = 'dnspod' + options.args = { forceCert: true } + const certd = new Certd() + const cert = await certd.certApply(options) + expect(cert).ok + expect(cert.crt).ok + expect(cert.key).ok + expect(cert.detail).ok + expect(cert.expires).ok + }) +}) diff --git a/packages/certd/test/index.test.js b/packages/certd/test/index.test.js index 9360b6a1..64c46247 100644 --- a/packages/certd/test/index.test.js +++ b/packages/certd/test/index.test.js @@ -14,20 +14,9 @@ describe('Certd', function () { const certd = new Certd() certd.writeCert('xiaojunnuo@qq.com', ['*.domain.cn'], { csr: 'csr', crt: 'aaa', key: 'bbb' }) }) - it('#申请证书-aliyun', async function () { - this.timeout(300000) - options.args = { forceCert: true } - const certd = new Certd() - const cert = await certd.certApply(options) - expect(cert).ok - expect(cert.crt).ok - expect(cert.key).ok - expect(cert.detail).ok - expect(cert.expires).ok - }) it('#readCurrentCert', async function () { const certd = new Certd() - const cert = certd.readCurrentCert('xiaojunnuo@qq.com', ['*.docmirror.cn']) + const cert = certd.readCurrentCert('xiaojunnuo@qq.com', ['*.domain.cn']) expect(cert).to.be.ok expect(cert.crt).ok expect(cert.key).to.be.ok diff --git a/packages/certd/test/options.js b/packages/certd/test/options.js index a6d61ab8..322f7007 100644 --- a/packages/certd/test/options.js +++ b/packages/certd/test/options.js @@ -19,10 +19,7 @@ const defaultOptions = { cert: { domains: ['*.docmirror.club', 'docmirror.club'], email: 'xiaojunnuo@qq.com', - challenge: { - challengeType: 'dns', - dnsProvider: 'aliyun' - }, + dnsProvider: 'aliyun', csrInfo: { country: 'CN', state: 'GuangDong', diff --git a/packages/certd/yarn.lock b/packages/certd/yarn.lock index aabeab12..faf7cef7 100644 --- a/packages/certd/yarn.lock +++ b/packages/certd/yarn.lock @@ -65,17 +65,6 @@ resolved "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== -acme-client@^4.1.2: - version "4.1.2" - resolved "https://registry.npmjs.org/acme-client/-/acme-client-4.1.2.tgz#6072e98cc2e5aaf0a3f769a823b6bc68d034e8da" - integrity sha512-3GlqDVWHgm0xpfnwOME/OpEBwEgO2vOplGEN8miWS7n7A28U9C7MtuTg6AuPYo8Lmqu4SADllnZrMLNasVNLEQ== - dependencies: - axios "0.21.0" - backo2 "^1.0.0" - bluebird "^3.5.0" - debug "^4.1.1" - node-forge "^0.10.0" - acorn-jsx@^5.3.1: version "5.3.1" resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" @@ -175,18 +164,13 @@ astral-regex@^1.0.0: resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== -axios@0.21.0: - version "0.21.0" - resolved "https://registry.npmjs.org/axios/-/axios-0.21.0.tgz#26df088803a2350dff2c27f96fef99fe49442aca" - integrity sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw== +axios@^0.21.1: + version "0.21.1" + resolved "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" + integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== dependencies: follow-redirects "^1.10.0" -backo2@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" - integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= - balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -202,11 +186,6 @@ binary-extensions@^2.0.0: resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== -bluebird@^3.5.0: - version "3.7.2" - resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -750,9 +729,9 @@ flatted@^3.1.0: integrity sha512-tW+UkmtNg/jv9CSofAKvgVcO7c2URjhTdW1ZTkcAritblu8tajiYy7YisnIflEwtKssCtOxpnBRoCB7iap0/TA== follow-redirects@^1.10.0: - version "1.13.0" - resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" - integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== + version "1.13.1" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.1.tgz#5f69b813376cee4fd0474a3aba835df04ab763b7" + integrity sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg== fs-extra@^8.1.0: version "8.1.0" @@ -1404,6 +1383,11 @@ punycode@^2.1.0: resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== +qs@^6.9.4: + version "6.9.4" + resolved "https://registry.npmjs.org/qs/-/qs-6.9.4.tgz#9090b290d1f91728d3c22e54843ca44aea5ab687" + integrity sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ== + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" diff --git a/packages/node-acme-client b/packages/node-acme-client index 5a3f7446..334a7374 160000 --- a/packages/node-acme-client +++ b/packages/node-acme-client @@ -1 +1 @@ -Subproject commit 5a3f7446222fa123b645e51e954ccfd981f459bd +Subproject commit 334a73743d03ca401258dce7ed479a969383689e