mirror of https://github.com/certd/certd
perf: 腾讯云dns provider 支持腾讯云的accessId
parent
ae0f16bf35
commit
e0eb3a4413
Binary file not shown.
After Width: | Height: | Size: 149 KiB |
Binary file not shown.
After Width: | Height: | Size: 98 KiB |
|
@ -0,0 +1,16 @@
|
||||||
|
# 腾讯云
|
||||||
|
|
||||||
|
|
||||||
|
## DNSPOD 授权设置
|
||||||
|
目前腾讯云管理的域名的dns暂时只支持从DNSPOD进行设置
|
||||||
|
打开 https://console.dnspod.cn/account/token/apikey
|
||||||
|
然后按如下方式获取DNSPOD的授权
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
## 腾讯云API密钥设置
|
||||||
|
|
||||||
|
腾讯云其他部署需要API密钥,需要在腾讯云控制台进行设置
|
||||||
|
打开 https://console.cloud.tencent.com/cam/capi
|
||||||
|
然后按如下方式获取腾讯云的API密钥
|
||||||
|

|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
const { readCsrDomains } = require('./crypto');
|
const { readCsrDomains } = require('./crypto');
|
||||||
const { log } = require('./logger');
|
const { log } = require('./logger');
|
||||||
|
const { wait } = require('./wait');
|
||||||
|
|
||||||
const defaultOpts = {
|
const defaultOpts = {
|
||||||
csr: null,
|
csr: null,
|
||||||
|
@ -118,7 +119,18 @@ module.exports = async function(client, userOpts) {
|
||||||
let recordItem = null;
|
let recordItem = null;
|
||||||
try {
|
try {
|
||||||
recordItem = await opts.challengeCreateFn(authz, challenge, keyAuthorization);
|
recordItem = await opts.challengeCreateFn(authz, challenge, keyAuthorization);
|
||||||
|
log(`[auto] [${d}] challengeCreateFn success`);
|
||||||
|
log(`[auto] [${d}] add challengeRemoveFn()`);
|
||||||
|
clearTasks.push(async () => {
|
||||||
|
/* Trigger challengeRemoveFn(), suppress errors */
|
||||||
|
log(`[auto] [${d}] Trigger challengeRemoveFn()`);
|
||||||
|
try {
|
||||||
|
await opts.challengeRemoveFn(authz, challenge, keyAuthorization, recordItem);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
log(`[auto] [${d}] challengeRemoveFn threw error: ${e.message}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
// throw new Error('测试异常');
|
// throw new Error('测试异常');
|
||||||
/* Challenge verification */
|
/* Challenge verification */
|
||||||
if (opts.skipChallengeVerification === true) {
|
if (opts.skipChallengeVerification === true) {
|
||||||
|
@ -140,19 +152,6 @@ module.exports = async function(client, userOpts) {
|
||||||
log(`[auto] [${d}] challengeCreateFn threw error: ${e.message}`);
|
log(`[auto] [${d}] challengeCreateFn threw error: ${e.message}`);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
log(`[auto] [${d}] add challengeRemoveFn()`);
|
|
||||||
clearTasks.push(async () => {
|
|
||||||
/* Trigger challengeRemoveFn(), suppress errors */
|
|
||||||
log(`[auto] [${d}] Trigger challengeRemoveFn()`);
|
|
||||||
try {
|
|
||||||
await opts.challengeRemoveFn(authz, challenge, keyAuthorization, recordItem);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
log(`[auto] [${d}] challengeRemoveFn threw error: ${e.message}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
/* Deactivate pending authz when unable to complete challenge */
|
/* Deactivate pending authz when unable to complete challenge */
|
||||||
|
@ -186,14 +185,21 @@ module.exports = async function(client, userOpts) {
|
||||||
return promise;
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
// function runPromisePa(tasks) {
|
async function runPromisePa(tasks) {
|
||||||
// return Promise.all(tasks.map((task) => task()));
|
const results = [];
|
||||||
// }
|
// eslint-disable-next-line no-await-in-loop,no-restricted-syntax
|
||||||
|
for (const task of tasks) {
|
||||||
|
results.push(task());
|
||||||
|
// eslint-disable-next-line no-await-in-loop
|
||||||
|
await wait(30000);
|
||||||
|
}
|
||||||
|
return Promise.all(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
log('开始challenge');
|
log('开始challenge');
|
||||||
await runAllPromise(challengePromises);
|
await runPromisePa(challengePromises);
|
||||||
|
|
||||||
log('challenge结束');
|
log('challenge结束');
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
async function wait(ms) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, ms);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
wait
|
||||||
|
};
|
|
@ -45,7 +45,7 @@ export class AcmeService {
|
||||||
directoryUrl: isTest ? acme.directory.letsencrypt.staging : acme.directory.letsencrypt.production,
|
directoryUrl: isTest ? acme.directory.letsencrypt.staging : acme.directory.letsencrypt.production,
|
||||||
accountKey: conf.key,
|
accountKey: conf.key,
|
||||||
accountUrl: conf.accountUrl,
|
accountUrl: conf.accountUrl,
|
||||||
backoffAttempts: 20,
|
backoffAttempts: 60,
|
||||||
backoffMin: 5000,
|
backoffMin: 5000,
|
||||||
backoffMax: 10000,
|
backoffMax: 10000,
|
||||||
});
|
});
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
"ssh2": "^0.8.9",
|
"ssh2": "^0.8.9",
|
||||||
"svg-captcha": "^1.4.0",
|
"svg-captcha": "^1.4.0",
|
||||||
"tencentcloud-sdk-nodejs": "^4.0.44",
|
"tencentcloud-sdk-nodejs": "^4.0.44",
|
||||||
|
"tencentcloud-sdk-nodejs-dnspod": "^4.0.866",
|
||||||
"typeorm": "^0.3.11"
|
"typeorm": "^0.3.11"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -0,0 +1,84 @@
|
||||||
|
import {Autowire, HttpClient, ILogger} from "@certd/pipeline";
|
||||||
|
import {AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions} from "@certd/plugin-cert";
|
||||||
|
import {TencentAccess} from "../access";
|
||||||
|
import tencentcloud from 'tencentcloud-sdk-nodejs/index';
|
||||||
|
|
||||||
|
const DnspodClient = tencentcloud.dnspod.v20210323.Client;
|
||||||
|
@IsDnsProvider({
|
||||||
|
name: 'tencent',
|
||||||
|
title: '腾讯云',
|
||||||
|
desc: '腾讯云域名DNS解析提供者',
|
||||||
|
accessType: 'tencent',
|
||||||
|
})
|
||||||
|
export class TencentDnsProvider extends AbstractDnsProvider {
|
||||||
|
@Autowire()
|
||||||
|
http!: HttpClient;
|
||||||
|
|
||||||
|
@Autowire()
|
||||||
|
access!: TencentAccess;
|
||||||
|
@Autowire()
|
||||||
|
logger!: ILogger;
|
||||||
|
|
||||||
|
client!: any;
|
||||||
|
|
||||||
|
endpoint = 'dnspod.tencentcloudapi.com';
|
||||||
|
|
||||||
|
async onInstance() {
|
||||||
|
|
||||||
|
const clientConfig = {
|
||||||
|
credential: this.access,
|
||||||
|
region: "",
|
||||||
|
profile: {
|
||||||
|
httpProfile: {
|
||||||
|
endpoint: this.endpoint,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// 实例化要请求产品的client对象,clientProfile是可选的
|
||||||
|
this.client = new DnspodClient(clientConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
async createRecord(options: CreateRecordOptions): Promise<any> {
|
||||||
|
const { fullRecord, value, type,domain } = options;
|
||||||
|
this.logger.info('添加域名解析:', fullRecord, value);
|
||||||
|
const rr = fullRecord.replace('.' + domain, '');
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
"Domain": domain,
|
||||||
|
"RecordType": type,
|
||||||
|
"RecordLine": "默认",
|
||||||
|
"Value": value,
|
||||||
|
"SubDomain": rr
|
||||||
|
};
|
||||||
|
|
||||||
|
const ret = await this.client.CreateRecord(params)
|
||||||
|
/*
|
||||||
|
{
|
||||||
|
"RecordId": 162,
|
||||||
|
"RequestId": "ab4f1426-ea15-42ea-8183-dc1b44151166"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
this.logger.info(
|
||||||
|
'添加域名解析成功:',
|
||||||
|
fullRecord,
|
||||||
|
value,
|
||||||
|
JSON.stringify(ret)
|
||||||
|
);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeRecord(options: RemoveRecordOptions<any>) {
|
||||||
|
const { fullRecord, value, domain,record } = options;
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
"Domain": domain,
|
||||||
|
"RecordId": record.RecordId
|
||||||
|
};
|
||||||
|
const ret = await this.client.DeleteRecord(params)
|
||||||
|
this.logger.info('删除域名解析成功:', fullRecord, value);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
new TencentDnsProvider();
|
Loading…
Reference in New Issue