mirror of
https://github.com/certd/certd.git
synced 2026-04-14 20:40:53 +08:00
perf: 支持腾讯云teo dns解析
This commit is contained in:
@@ -13,7 +13,7 @@ import { CnameRecordEntity, CnameRecordStatusType } from "../entity/cname-record
|
||||
import { createDnsProvider, IDnsProvider } from "@certd/plugin-cert";
|
||||
import { CnameProvider, CnameRecord } from "@certd/pipeline";
|
||||
import { cache, http, isDev, logger, utils } from "@certd/basic";
|
||||
import { getAuthoritativeDnsResolver, walkTxtRecord } from "@certd/acme-client";
|
||||
import { getAuthoritativeDnsResolver, createChallengeFn } from "@certd/acme-client";
|
||||
import { CnameProviderService } from "./cname-provider-service.js";
|
||||
import { CnameProviderEntity } from "../entity/cname-provider.js";
|
||||
import { CommonDnsProvider } from "./common-provider.js";
|
||||
@@ -241,6 +241,8 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
|
||||
* @param id
|
||||
*/
|
||||
async verify(id: number) {
|
||||
|
||||
const {walkTxtRecord} = createChallengeFn({logger});
|
||||
const bean = await this.info(id);
|
||||
if (!bean) {
|
||||
throw new ValidateException(`CnameRecord:${id} 不存在`);
|
||||
@@ -416,6 +418,7 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
|
||||
|
||||
async checkRepeatAcmeChallengeRecords(acmeRecordDomain: string, targetCnameDomain: string) {
|
||||
|
||||
|
||||
let dnsResolver = null;
|
||||
try {
|
||||
dnsResolver = await getAuthoritativeDnsResolver(acmeRecordDomain);
|
||||
@@ -460,6 +463,9 @@ export class CnameRecordService extends BaseService<CnameRecordEntity> {
|
||||
//如果权威服务器中查不到txt,无需继续检查
|
||||
return;
|
||||
}
|
||||
|
||||
const {walkTxtRecord} = createChallengeFn({logger});
|
||||
|
||||
if (cnameRecords.length > 0) {
|
||||
// 从cname记录中获取txt记录
|
||||
// 对比是否存在,如果不存在于cname中获取的txt中,说明本体有创建多余的txt记录
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
import './dnspod-dns-provider.js';
|
||||
import './tencent-dns-provider.js';
|
||||
import './teo-dns-provider.js';
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert';
|
||||
import { TencentAccess } from '@certd/plugin-lib';
|
||||
|
||||
@IsDnsProvider({
|
||||
name: 'tencent-eo',
|
||||
title: '腾讯云EO DNS',
|
||||
desc: '腾讯云EO DNS解析提供者',
|
||||
accessType: 'tencent',
|
||||
icon: 'svg:icon-tencentcloud',
|
||||
})
|
||||
export class TencentEoDnsProvider extends AbstractDnsProvider {
|
||||
access!: TencentAccess;
|
||||
|
||||
client!: any;
|
||||
|
||||
|
||||
async onInstance() {
|
||||
this.access = this.ctx.access as TencentAccess
|
||||
const clientConfig = {
|
||||
credential: this.access,
|
||||
region: '',
|
||||
profile: {
|
||||
httpProfile: {
|
||||
endpoint: this.access.buildEndpoint("teo.tencentcloudapi.com"),
|
||||
},
|
||||
},
|
||||
};
|
||||
const teosdk = await import('tencentcloud-sdk-nodejs/tencentcloud/services/teo/v20220901/index.js');
|
||||
const TeoClient = teosdk.v20220901.Client;
|
||||
// 实例化要请求产品的client对象,clientProfile是可选的
|
||||
this.client = new TeoClient(clientConfig);
|
||||
}
|
||||
|
||||
|
||||
async getZoneId(domain: string) {
|
||||
|
||||
const params = {
|
||||
"Filters": [
|
||||
{
|
||||
"Name": "zone-name",
|
||||
"Values": [
|
||||
domain
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
const res = await this.client.DescribeZones(params);
|
||||
if (res.Zones && res.Zones.length > 0) {
|
||||
return res.Zones[0].ZoneId;
|
||||
}
|
||||
throw new Error('未找到对应的ZoneId');
|
||||
}
|
||||
|
||||
async createRecord(options: CreateRecordOptions): Promise<any> {
|
||||
const { fullRecord, value, type, domain } = options;
|
||||
this.logger.info('添加域名解析:', fullRecord, value);
|
||||
|
||||
const zoneId = await this.getZoneId(domain);
|
||||
const params = {
|
||||
"ZoneId": zoneId,
|
||||
"Name": fullRecord,
|
||||
"Type": type,
|
||||
"Content": value
|
||||
};
|
||||
|
||||
try {
|
||||
const ret = await this.client.CreateDnsRecord(params);
|
||||
this.logger.info('添加域名解析成功:', fullRecord, value, JSON.stringify(ret));
|
||||
/*
|
||||
{
|
||||
"RecordId": 162,
|
||||
"RequestId": "ab4f1426-ea15-42ea-8183-dc1b44151166"
|
||||
}
|
||||
*/
|
||||
return {
|
||||
RecordId: ret.RecordId,
|
||||
ZoneId: zoneId,
|
||||
};
|
||||
} catch (e: any) {
|
||||
if (e?.code === 'ResourceInUse.DuplicateName') {
|
||||
this.logger.info('域名解析已存在,无需重复添加:', fullRecord, value);
|
||||
return await this.findRecord({
|
||||
...options,
|
||||
zoneId,
|
||||
});
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
async findRecord(options: CreateRecordOptions & { zoneId: string }): Promise<any> {
|
||||
|
||||
const { zoneId } = options;
|
||||
const params = {
|
||||
"ZoneId": zoneId,
|
||||
"Filters": [
|
||||
{
|
||||
"Name": "name",
|
||||
"Values": [
|
||||
options.fullRecord
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "content",
|
||||
"Values": [
|
||||
options.value
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "type",
|
||||
"Values": [
|
||||
options.type
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
const ret = await this.client.DescribeRecordFilterList(params);
|
||||
if (ret.DnsRecords && ret.DnsRecords.length > 0) {
|
||||
this.logger.info('已存在解析记录:', ret.DnsRecords);
|
||||
return ret.DnsRecords[0];
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
async removeRecord(options: RemoveRecordOptions<any>) {
|
||||
const { fullRecord, value } = options.recordReq;
|
||||
const record = options.recordRes;
|
||||
if (!record) {
|
||||
this.logger.info('解析记录recordId为空,不执行删除', fullRecord, value);
|
||||
}
|
||||
|
||||
const params = {
|
||||
"ZoneId": record.ZoneId,
|
||||
"RecordIds": [
|
||||
record.RecordId
|
||||
]
|
||||
};
|
||||
|
||||
const ret = await this.client.DeleteDnsRecords(params);
|
||||
this.logger.info('删除域名解析成功:', fullRecord, value);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
new TencentEoDnsProvider();
|
||||
Reference in New Issue
Block a user