mirror of https://github.com/certd/certd
fix: 修复aliyun域名超过100个找不到域名的bug
parent
ebf2a820cc
commit
5b1494b3ce
|
@ -176,21 +176,31 @@ module.exports = async function(client, userOpts) {
|
||||||
await challengeFunc(authz);
|
await challengeFunc(authz);
|
||||||
});
|
});
|
||||||
|
|
||||||
log('开始challenge');
|
|
||||||
let promise = Promise.resolve();
|
// let promise = Promise.resolve();
|
||||||
function runPromisesSerially(tasks) {
|
// function runPromisesSerially(tasks) {
|
||||||
tasks.forEach((task) => {
|
// tasks.forEach((task) => {
|
||||||
promise = promise.then(task);
|
// promise = promise.then(task);
|
||||||
});
|
// });
|
||||||
return promise;
|
// return promise;
|
||||||
|
// }
|
||||||
|
|
||||||
|
function runPromiseParallel(tasks) {
|
||||||
|
return Promise.all(tasks.map((task) => task()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await runPromisesSerially(challengePromises);
|
log('开始challenge');
|
||||||
|
await runPromiseParallel(challengePromises);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
log('challenge失败');
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
await runPromisesSerially(clearTasks);
|
log('清理challenge痕迹');
|
||||||
|
await runPromiseParallel(clearTasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try {
|
// try {
|
||||||
|
|
|
@ -20,7 +20,8 @@
|
||||||
"@certd/acme-client": "workspace:^1.20.10",
|
"@certd/acme-client": "workspace:^1.20.10",
|
||||||
"@certd/pipeline": "workspace:^1.20.10",
|
"@certd/pipeline": "workspace:^1.20.10",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"node-forge": "^0.10.0"
|
"node-forge": "^0.10.0",
|
||||||
|
"psl": "^1.9.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@alicloud/cs20151215": "^3.0.3",
|
"@alicloud/cs20151215": "^3.0.3",
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
"@types/lodash": "^4.14.186",
|
"@types/lodash": "^4.14.186",
|
||||||
"@types/mocha": "^10.0.0",
|
"@types/mocha": "^10.0.0",
|
||||||
"@types/node-forge": "^1.3.0",
|
"@types/node-forge": "^1.3.0",
|
||||||
|
"@types/psl": "^1.1.3",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
||||||
"@typescript-eslint/parser": "^5.38.1",
|
"@typescript-eslint/parser": "^5.38.1",
|
||||||
"chai": "^4.3.6",
|
"chai": "^4.3.6",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Registrable } from "@certd/pipeline";
|
import { HttpClient, IAccess, ILogger, Registrable } from "@certd/pipeline";
|
||||||
|
|
||||||
export type DnsProviderDefine = Registrable & {
|
export type DnsProviderDefine = Registrable & {
|
||||||
accessType: string;
|
accessType: string;
|
||||||
|
@ -11,13 +11,21 @@ export type CreateRecordOptions = {
|
||||||
fullRecord: string;
|
fullRecord: string;
|
||||||
type: string;
|
type: string;
|
||||||
value: any;
|
value: any;
|
||||||
|
domain: string;
|
||||||
};
|
};
|
||||||
export type RemoveRecordOptions = CreateRecordOptions & {
|
export type RemoveRecordOptions = CreateRecordOptions & {
|
||||||
record: any;
|
record: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type DnsProviderContext = {
|
||||||
|
access: IAccess;
|
||||||
|
logger: ILogger;
|
||||||
|
http: HttpClient;
|
||||||
|
};
|
||||||
|
|
||||||
export interface IDnsProvider {
|
export interface IDnsProvider {
|
||||||
onInstance(): Promise<void>;
|
onInstance(): Promise<void>;
|
||||||
createRecord(options: CreateRecordOptions): Promise<any>;
|
createRecord(options: CreateRecordOptions): Promise<any>;
|
||||||
removeRecord(options: RemoveRecordOptions): Promise<any>;
|
removeRecord(options: RemoveRecordOptions): Promise<any>;
|
||||||
|
setCtx(ctx: DnsProviderContext): void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { CreateRecordOptions, DnsProviderContext, IDnsProvider, RemoveRecordOptions } from "./api";
|
||||||
|
|
||||||
|
export abstract class AbstractDnsProvider implements IDnsProvider {
|
||||||
|
ctx!: DnsProviderContext;
|
||||||
|
|
||||||
|
setCtx(ctx: DnsProviderContext) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract createRecord(options: CreateRecordOptions): Promise<any>;
|
||||||
|
|
||||||
|
abstract onInstance(): Promise<void>;
|
||||||
|
|
||||||
|
abstract removeRecord(options: RemoveRecordOptions): Promise<any>;
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
export * from "./api";
|
export * from "./api";
|
||||||
export * from "./registry";
|
export * from "./registry";
|
||||||
export * from "./decorator";
|
export * from "./decorator";
|
||||||
|
export * from "./base";
|
||||||
|
|
|
@ -5,6 +5,8 @@ import { Challenge } from "@certd/acme-client/types/rfc8555";
|
||||||
import { Logger } from "log4js";
|
import { Logger } from "log4js";
|
||||||
import { IContext } from "@certd/pipeline";
|
import { IContext } from "@certd/pipeline";
|
||||||
import { IDnsProvider } from "../../dns-provider";
|
import { IDnsProvider } from "../../dns-provider";
|
||||||
|
import psl from "psl";
|
||||||
|
|
||||||
export type CertInfo = {
|
export type CertInfo = {
|
||||||
crt: string;
|
crt: string;
|
||||||
key: string;
|
key: string;
|
||||||
|
@ -65,33 +67,43 @@ export class AcmeService {
|
||||||
return key.toString();
|
return key.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parseDomain(fullDomain: string) {
|
||||||
|
const parsed = psl.parse(fullDomain) as psl.ParsedDomain;
|
||||||
|
if (parsed.error) {
|
||||||
|
throw new Error(`解析${fullDomain}域名失败:` + JSON.stringify(parsed.error));
|
||||||
|
}
|
||||||
|
return parsed.domain as string;
|
||||||
|
}
|
||||||
async challengeCreateFn(authz: any, challenge: any, keyAuthorization: string, dnsProvider: IDnsProvider) {
|
async challengeCreateFn(authz: any, challenge: any, keyAuthorization: string, dnsProvider: IDnsProvider) {
|
||||||
this.logger.info("Triggered challengeCreateFn()");
|
this.logger.info("Triggered challengeCreateFn()");
|
||||||
|
|
||||||
/* http-01 */
|
/* http-01 */
|
||||||
|
const fullDomain = authz.identifier.value;
|
||||||
if (challenge.type === "http-01") {
|
if (challenge.type === "http-01") {
|
||||||
const filePath = `/var/www/html/.well-known/acme-challenge/${challenge.token}`;
|
const filePath = `/var/www/html/.well-known/acme-challenge/${challenge.token}`;
|
||||||
const fileContents = keyAuthorization;
|
const fileContents = keyAuthorization;
|
||||||
|
|
||||||
this.logger.info(`Creating challenge response for ${authz.identifier.value} at path: ${filePath}`);
|
this.logger.info(`Creating challenge response for ${fullDomain} at path: ${filePath}`);
|
||||||
|
|
||||||
/* Replace this */
|
/* Replace this */
|
||||||
this.logger.info(`Would write "${fileContents}" to path "${filePath}"`);
|
this.logger.info(`Would write "${fileContents}" to path "${filePath}"`);
|
||||||
// await fs.writeFileAsync(filePath, fileContents);
|
// await fs.writeFileAsync(filePath, fileContents);
|
||||||
} else if (challenge.type === "dns-01") {
|
} else if (challenge.type === "dns-01") {
|
||||||
/* dns-01 */
|
/* dns-01 */
|
||||||
const dnsRecord = `_acme-challenge.${authz.identifier.value}`;
|
const dnsRecord = `_acme-challenge.${fullDomain}`;
|
||||||
const recordValue = keyAuthorization;
|
const recordValue = keyAuthorization;
|
||||||
|
|
||||||
this.logger.info(`Creating TXT record for ${authz.identifier.value}: ${dnsRecord}`);
|
this.logger.info(`Creating TXT record for ${fullDomain}: ${dnsRecord}`);
|
||||||
|
|
||||||
/* Replace this */
|
/* Replace this */
|
||||||
this.logger.info(`Would create TXT record "${dnsRecord}" with value "${recordValue}"`);
|
this.logger.info(`Would create TXT record "${dnsRecord}" with value "${recordValue}"`);
|
||||||
|
|
||||||
|
const domain = this.parseDomain(fullDomain);
|
||||||
|
this.logger.info("解析到域名domain=", domain);
|
||||||
return await dnsProvider.createRecord({
|
return await dnsProvider.createRecord({
|
||||||
fullRecord: dnsRecord,
|
fullRecord: dnsRecord,
|
||||||
type: "TXT",
|
type: "TXT",
|
||||||
value: recordValue,
|
value: recordValue,
|
||||||
|
domain,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,28 +123,33 @@ export class AcmeService {
|
||||||
this.logger.info("Triggered challengeRemoveFn()");
|
this.logger.info("Triggered challengeRemoveFn()");
|
||||||
|
|
||||||
/* http-01 */
|
/* http-01 */
|
||||||
|
const fullDomain = authz.identifier.value;
|
||||||
if (challenge.type === "http-01") {
|
if (challenge.type === "http-01") {
|
||||||
const filePath = `/var/www/html/.well-known/acme-challenge/${challenge.token}`;
|
const filePath = `/var/www/html/.well-known/acme-challenge/${challenge.token}`;
|
||||||
|
|
||||||
this.logger.info(`Removing challenge response for ${authz.identifier.value} at path: ${filePath}`);
|
this.logger.info(`Removing challenge response for ${fullDomain} at path: ${filePath}`);
|
||||||
|
|
||||||
/* Replace this */
|
/* Replace this */
|
||||||
this.logger.info(`Would remove file on path "${filePath}"`);
|
this.logger.info(`Would remove file on path "${filePath}"`);
|
||||||
// await fs.unlinkAsync(filePath);
|
// await fs.unlinkAsync(filePath);
|
||||||
} else if (challenge.type === "dns-01") {
|
} else if (challenge.type === "dns-01") {
|
||||||
const dnsRecord = `_acme-challenge.${authz.identifier.value}`;
|
const dnsRecord = `_acme-challenge.${fullDomain}`;
|
||||||
const recordValue = keyAuthorization;
|
const recordValue = keyAuthorization;
|
||||||
|
|
||||||
this.logger.info(`Removing TXT record for ${authz.identifier.value}: ${dnsRecord}`);
|
this.logger.info(`Removing TXT record for ${fullDomain}: ${dnsRecord}`);
|
||||||
|
|
||||||
/* Replace this */
|
/* Replace this */
|
||||||
this.logger.info(`Would remove TXT record "${dnsRecord}" with value "${recordValue}"`);
|
this.logger.info(`Would remove TXT record "${dnsRecord}" with value "${recordValue}"`);
|
||||||
|
|
||||||
|
const domain = this.parseDomain(fullDomain);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await dnsProvider.removeRecord({
|
await dnsProvider.removeRecord({
|
||||||
fullRecord: dnsRecord,
|
fullRecord: dnsRecord,
|
||||||
type: "TXT",
|
type: "TXT",
|
||||||
value: keyAuthorization,
|
value: keyAuthorization,
|
||||||
record: recordItem,
|
record: recordItem,
|
||||||
|
domain,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.error("删除解析记录出错:", e);
|
this.logger.error("删除解析记录出错:", e);
|
||||||
|
|
|
@ -1,21 +1,10 @@
|
||||||
import {
|
import { AbstractTaskPlugin, Decorator, HttpClient, IAccessService, IContext, IsTaskPlugin, RunStrategy, Step, TaskInput, TaskOutput } from "@certd/pipeline";
|
||||||
AbstractTaskPlugin,
|
|
||||||
Decorator,
|
|
||||||
HttpClient,
|
|
||||||
IAccessService,
|
|
||||||
IContext,
|
|
||||||
IsTaskPlugin,
|
|
||||||
RunStrategy,
|
|
||||||
Step,
|
|
||||||
TaskInput,
|
|
||||||
TaskOutput
|
|
||||||
} from "@certd/pipeline";
|
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import {AcmeService, CertInfo} from "./acme";
|
import { AcmeService, CertInfo } from "./acme";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import {Logger} from "log4js";
|
import { Logger } from "log4js";
|
||||||
import {DnsProviderDefine, dnsProviderRegistry} from "../../dns-provider";
|
import { DnsProviderContext, DnsProviderDefine, dnsProviderRegistry } from "../../dns-provider";
|
||||||
import {CertReader} from "./cert-reader";
|
import { CertReader } from "./cert-reader";
|
||||||
import JSZip from "jszip";
|
import JSZip from "jszip";
|
||||||
|
|
||||||
export { CertReader };
|
export { CertReader };
|
||||||
|
@ -242,8 +231,9 @@ export class CertApplyPlugin extends AbstractTaskPlugin {
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const dnsProvider: IDnsProvider = new DnsProviderClass();
|
const dnsProvider: IDnsProvider = new DnsProviderClass();
|
||||||
const context = { access, logger: this.logger, http: this.http };
|
const context: DnsProviderContext = { access, logger: this.logger, http: this.http };
|
||||||
Decorator.inject(dnsProviderDefine.autowire, dnsProvider, context);
|
Decorator.inject(dnsProviderDefine.autowire, dnsProvider, context);
|
||||||
|
dnsProvider.setCtx(context);
|
||||||
await dnsProvider.onInstance();
|
await dnsProvider.onInstance();
|
||||||
|
|
||||||
const cert = await this.acme.order({
|
const cert = await this.acme.order({
|
||||||
|
|
|
@ -26,10 +26,10 @@
|
||||||
"@ant-design/icons-vue": "^6.1.0",
|
"@ant-design/icons-vue": "^6.1.0",
|
||||||
"@aws-sdk/client-s3": "^3.383.0",
|
"@aws-sdk/client-s3": "^3.383.0",
|
||||||
"@aws-sdk/s3-request-presigner": "^3.383.0",
|
"@aws-sdk/s3-request-presigner": "^3.383.0",
|
||||||
"@fast-crud/fast-crud": "^1.20.2",
|
"@fast-crud/fast-crud": "^1.21.0",
|
||||||
"@fast-crud/fast-extends": "^1.20.2",
|
"@fast-crud/fast-extends": "^1.21.0",
|
||||||
"@fast-crud/ui-antdv4": "^1.20.2",
|
"@fast-crud/ui-antdv4": "^1.21.0",
|
||||||
"@fast-crud/ui-interface": "^1.20.2",
|
"@fast-crud/ui-interface": "^1.21.0",
|
||||||
"@iconify/vue": "^4.1.1",
|
"@iconify/vue": "^4.1.1",
|
||||||
"@soerenmartius/vue3-clipboard": "^0.1.2",
|
"@soerenmartius/vue3-clipboard": "^0.1.2",
|
||||||
"ant-design-vue": "^4.1.2",
|
"ant-design-vue": "^4.1.2",
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
import Core from '@alicloud/pop-core';
|
import Core from "@alicloud/pop-core";
|
||||||
import _ from 'lodash';
|
import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert";
|
||||||
import {
|
import { Autowire, ILogger } from "@certd/pipeline";
|
||||||
CreateRecordOptions,
|
import { AliyunAccess } from "../access";
|
||||||
IDnsProvider,
|
|
||||||
IsDnsProvider,
|
|
||||||
RemoveRecordOptions,
|
|
||||||
} from '@certd/plugin-cert';
|
|
||||||
import { Autowire, ILogger } from '@certd/pipeline';
|
|
||||||
import { AliyunAccess } from '../access';
|
|
||||||
|
|
||||||
@IsDnsProvider({
|
@IsDnsProvider({
|
||||||
name: 'aliyun',
|
name: 'aliyun',
|
||||||
|
@ -15,7 +9,7 @@ import { AliyunAccess } from '../access';
|
||||||
desc: '阿里云DNS解析提供商',
|
desc: '阿里云DNS解析提供商',
|
||||||
accessType: 'aliyun',
|
accessType: 'aliyun',
|
||||||
})
|
})
|
||||||
export class AliyunDnsProvider implements IDnsProvider {
|
export class AliyunDnsProvider extends AbstractDnsProvider{
|
||||||
client: any;
|
client: any;
|
||||||
@Autowire()
|
@Autowire()
|
||||||
access!: AliyunAccess;
|
access!: AliyunAccess;
|
||||||
|
@ -30,71 +24,71 @@ export class AliyunDnsProvider implements IDnsProvider {
|
||||||
apiVersion: '2015-01-09',
|
apiVersion: '2015-01-09',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
//
|
||||||
async getDomainList() {
|
// async getDomainList() {
|
||||||
const params = {
|
// const params = {
|
||||||
RegionId: 'cn-hangzhou',
|
// RegionId: 'cn-hangzhou',
|
||||||
PageSize: 100,
|
// PageSize: 100,
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
const requestOption = {
|
// const requestOption = {
|
||||||
method: 'POST',
|
// method: 'POST',
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
const ret = await this.client.request(
|
// const ret = await this.client.request(
|
||||||
'DescribeDomains',
|
// 'DescribeDomains',
|
||||||
params,
|
// params,
|
||||||
requestOption
|
// requestOption
|
||||||
);
|
// );
|
||||||
return ret.Domains.Domain;
|
// return ret.Domains.Domain;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
async matchDomain(dnsRecord: string) {
|
// async matchDomain(dnsRecord: string) {
|
||||||
const list = await this.getDomainList();
|
// const list = await this.getDomainList();
|
||||||
let domain = null;
|
// let domain = null;
|
||||||
const domainList = [];
|
// const domainList = [];
|
||||||
for (const item of list) {
|
// for (const item of list) {
|
||||||
domainList.push(item.DomainName);
|
// domainList.push(item.DomainName);
|
||||||
if (_.endsWith(dnsRecord, item.DomainName)) {
|
// if (_.endsWith(dnsRecord, item.DomainName)) {
|
||||||
domain = item.DomainName;
|
// domain = item.DomainName;
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (!domain) {
|
// if (!domain) {
|
||||||
throw new Error(
|
// throw new Error(
|
||||||
`can not find Domain :${dnsRecord} ,list: ${JSON.stringify(domainList)}`
|
// `can not find Domain :${dnsRecord} ,list: ${JSON.stringify(domainList)}`
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
return domain;
|
// return domain;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
async getRecords(domain: string, rr: string, value: string) {
|
// async getRecords(domain: string, rr: string, value: string) {
|
||||||
const params: any = {
|
// const params: any = {
|
||||||
RegionId: 'cn-hangzhou',
|
// RegionId: 'cn-hangzhou',
|
||||||
DomainName: domain,
|
// DomainName: domain,
|
||||||
RRKeyWord: rr,
|
// RRKeyWord: rr,
|
||||||
ValueKeyWord: undefined,
|
// ValueKeyWord: undefined,
|
||||||
};
|
// };
|
||||||
if (value) {
|
// if (value) {
|
||||||
params.ValueKeyWord = value;
|
// params.ValueKeyWord = value;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
const requestOption = {
|
// const requestOption = {
|
||||||
method: 'POST',
|
// method: 'POST',
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
const ret = await this.client.request(
|
// const ret = await this.client.request(
|
||||||
'DescribeDomainRecords',
|
// 'DescribeDomainRecords',
|
||||||
params,
|
// params,
|
||||||
requestOption
|
// requestOption
|
||||||
);
|
// );
|
||||||
return ret.DomainRecords.Record;
|
// return ret.DomainRecords.Record;
|
||||||
}
|
// }
|
||||||
|
|
||||||
async createRecord(options: CreateRecordOptions): Promise<any> {
|
async createRecord(options: CreateRecordOptions): Promise<any> {
|
||||||
const { fullRecord, value, type } = options;
|
const { fullRecord, value, type,domain } = options;
|
||||||
this.logger.info('添加域名解析:', fullRecord, value);
|
this.logger.info('添加域名解析:', fullRecord, value,domain);
|
||||||
const domain = await this.matchDomain(fullRecord);
|
// const domain = await this.matchDomain(fullRecord);
|
||||||
const rr = fullRecord.replace('.' + domain, '');
|
const rr = fullRecord.replace('.' + domain, '');
|
||||||
|
|
||||||
const params = {
|
const params = {
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
import _ from 'lodash';
|
import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from "@certd/plugin-cert";
|
||||||
import {
|
import { Autowire, HttpClient, ILogger } from "@certd/pipeline";
|
||||||
CreateRecordOptions,
|
import { CloudflareAccess } from "./access";
|
||||||
IDnsProvider,
|
|
||||||
IsDnsProvider,
|
|
||||||
RemoveRecordOptions,
|
|
||||||
} from '@certd/plugin-cert';
|
|
||||||
import { Autowire, ILogger } from '@certd/pipeline';
|
|
||||||
import { CloudflareAccess } from './access';
|
|
||||||
|
|
||||||
// TODO 这里注册一个dnsProvider
|
// TODO 这里注册一个dnsProvider
|
||||||
@IsDnsProvider({
|
@IsDnsProvider({
|
||||||
|
@ -15,50 +9,41 @@ import { CloudflareAccess } from './access';
|
||||||
desc: 'cloudflare dns provider示例',
|
desc: 'cloudflare dns provider示例',
|
||||||
accessType: 'cloudflare',
|
accessType: 'cloudflare',
|
||||||
})
|
})
|
||||||
export class CloudflareDnsProvider implements IDnsProvider {
|
export class CloudflareDnsProvider extends AbstractDnsProvider{
|
||||||
@Autowire()
|
@Autowire()
|
||||||
|
logger! : ILogger;
|
||||||
access!: CloudflareAccess;
|
access!: CloudflareAccess;
|
||||||
@Autowire()
|
http!: HttpClient;
|
||||||
logger!: ILogger;
|
|
||||||
|
|
||||||
async onInstance() {
|
async onInstance() {
|
||||||
const access: any = this.access;
|
//一些初始化的操作
|
||||||
this.logger.debug('access', access);
|
this.access = this.ctx.access as CloudflareAccess;
|
||||||
//初始化的操作
|
this.http = this.ctx.http
|
||||||
//...
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDomainList(): Promise<any[]> {
|
|
||||||
// TODO 这里你要实现一个获取域名列表的方法
|
|
||||||
const access = this.access;
|
|
||||||
this.logger.debug('access', access);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
async matchDomain(dnsRecord: string): Promise<any> {
|
|
||||||
const domainList = await this.getDomainList();
|
|
||||||
let domainRecord = null;
|
|
||||||
for (const item of domainList) {
|
|
||||||
//TODO 根据域名去匹配账户中是否有该域名, 这里不一定是item.name 具体要看你要实现的平台的接口而定
|
|
||||||
if (_.endsWith(dnsRecord + '.', item.name)) {
|
|
||||||
domainRecord = item;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!domainRecord) {
|
|
||||||
this.logger.info('账户中域名列表:', domainList);
|
|
||||||
this.logger.error('找不到域名,请确认账户中是否真的有此域名');
|
|
||||||
throw new Error('can not find Domain:' + dnsRecord);
|
|
||||||
}
|
|
||||||
return domainRecord;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* curl --request POST \
|
||||||
|
* --url https://api.cloudflare.com/client/v4/zones/zone_id/dns_records \
|
||||||
|
* --header 'Content-Type: application/json' \
|
||||||
|
* --header 'X-Auth-Email: ' \
|
||||||
|
* --data '{
|
||||||
|
* "content": "198.51.100.4",
|
||||||
|
* "name": "example.com",
|
||||||
|
* "proxied": false,
|
||||||
|
* "type": "A",
|
||||||
|
* "comment": "Domain verification record",
|
||||||
|
* "tags": [
|
||||||
|
* "owner:dns-team"
|
||||||
|
* ],
|
||||||
|
* "ttl": 60
|
||||||
|
* }'
|
||||||
|
*/
|
||||||
async createRecord(options: CreateRecordOptions): Promise<any> {
|
async createRecord(options: CreateRecordOptions): Promise<any> {
|
||||||
const { fullRecord, value, type } = options;
|
const { fullRecord, value, type,domain } = options;
|
||||||
this.logger.info('添加域名解析:', fullRecord, value, type);
|
this.logger.info('添加域名解析:', fullRecord, value, type,domain);
|
||||||
//先确定账户中是否有该域名
|
|
||||||
const domainRecord = await this.matchDomain(fullRecord);
|
this.http.post('https://api.cloudflare.com/client/v4/zones/zone_id/dns_records')
|
||||||
this.logger.debug('matchDomain:', domainRecord);
|
|
||||||
//TODO 然后调用接口,创建txt类型的dns解析记录
|
//TODO 然后调用接口,创建txt类型的dns解析记录
|
||||||
// .. 这里调用对应平台的后台接口
|
// .. 这里调用对应平台的后台接口
|
||||||
const access = this.access;
|
const access = this.access;
|
||||||
|
|
|
@ -28,37 +28,10 @@ export class DemoDnsProvider implements IDnsProvider {
|
||||||
//...
|
//...
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDomainList(): Promise<any[]> {
|
|
||||||
// TODO 这里你要实现一个获取域名列表的方法
|
|
||||||
const access = this.access;
|
|
||||||
this.logger.debug('access', access);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
async matchDomain(dnsRecord: string): Promise<any> {
|
|
||||||
const domainList = await this.getDomainList();
|
|
||||||
let domainRecord = null;
|
|
||||||
for (const item of domainList) {
|
|
||||||
//TODO 根据域名去匹配账户中是否有该域名, 这里不一定是item.name 具体要看你要实现的平台的接口而定
|
|
||||||
if (_.endsWith(dnsRecord + '.', item.name)) {
|
|
||||||
domainRecord = item;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!domainRecord) {
|
|
||||||
this.logger.info('账户中域名列表:', domainList);
|
|
||||||
this.logger.error('找不到域名,请确认账户中是否真的有此域名');
|
|
||||||
throw new Error('can not find Domain:' + dnsRecord);
|
|
||||||
}
|
|
||||||
return domainRecord;
|
|
||||||
}
|
|
||||||
|
|
||||||
async createRecord(options: CreateRecordOptions): Promise<any> {
|
async createRecord(options: CreateRecordOptions): Promise<any> {
|
||||||
const { fullRecord, value, type } = options;
|
const { fullRecord, value, type,domain } = options;
|
||||||
this.logger.info('添加域名解析:', fullRecord, value, type);
|
this.logger.info('添加域名解析:', fullRecord, value, type,domain);
|
||||||
//先确定账户中是否有该域名
|
|
||||||
const domainRecord = await this.matchDomain(fullRecord);
|
|
||||||
this.logger.debug('matchDomain:', domainRecord);
|
|
||||||
//TODO 然后调用接口,创建txt类型的dns解析记录
|
//TODO 然后调用接口,创建txt类型的dns解析记录
|
||||||
// .. 这里调用对应平台的后台接口
|
// .. 这里调用对应平台的后台接口
|
||||||
const access = this.access;
|
const access = this.access;
|
||||||
|
|
Loading…
Reference in New Issue