feat: 域名验证方法支持CNAME间接方式,此方式支持所有域名注册商,且无需提供Access授权,但是需要手动添加cname解析

This commit is contained in:
xiaojunnuo
2024-10-07 03:21:16 +08:00
parent 0c8e83e125
commit f3d35084ed
123 changed files with 2373 additions and 456 deletions
@@ -7,7 +7,7 @@ import { MidwayConfig } from '@midwayjs/core';
// eslint-disable-next-line node/no-extraneous-import
import { FlywayHistory } from '@certd/midway-flyway-js';
import { UserEntity } from '../modules/authority/entity/user.js';
import { UserEntity } from '../modules/sys/authority/entity/user.js';
import { PipelineEntity } from '../modules/pipeline/entity/pipeline.js';
//import { logger } from '../utils/logger';
// load .env file in process.cwd
@@ -67,7 +67,7 @@ const development = {
logging: false,
// 配置实体模型 或者 entities: '/entity',
entities: ['**/modules/*/entity/*.js', ...libServerEntities, ...commercialEntities, PipelineEntity, FlywayHistory, UserEntity],
entities: ['**/modules/**/entity/*.js', ...libServerEntities, ...commercialEntities, PipelineEntity, FlywayHistory, UserEntity],
},
},
},
@@ -3,7 +3,7 @@ import { IMidwayKoaContext, IWebMiddleware, NextFunction } from '@midwayjs/koa';
import jwt from 'jsonwebtoken';
import { Constants } from '@certd/lib-server';
import { logger } from '@certd/pipeline';
import { AuthService } from '../modules/authority/service/auth-service.js';
import { AuthService } from '../modules/sys/authority/service/auth-service.js';
import { SysSettingsService } from '@certd/lib-server';
import { SysPrivateSettings } from '@certd/lib-server';
@@ -1,7 +1,7 @@
import { Autoload, Config, Init, Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
import { IMidwayKoaContext, IWebMiddleware, NextFunction } from '@midwayjs/koa';
import { CommonException } from '@certd/lib-server';
import { UserService } from '../../modules/authority/service/user-service.js';
import { UserService } from '../../modules/sys/authority/service/user-service.js';
import { logger } from '@certd/pipeline';
/**
@@ -1,6 +1,6 @@
import { Autoload, Config, Init, Inject, Scope, ScopeEnum } from '@midwayjs/core';
import { logger } from '@certd/pipeline';
import { UserService } from '../authority/service/user-service.js';
import { UserService } from '../sys/authority/service/user-service.js';
import { PlusService, SysSettingsService } from '@certd/lib-server';
import { nanoid } from 'nanoid';
import { SysInstallInfo, SysPrivateSettings } from '@certd/lib-server';
@@ -13,7 +13,7 @@ export class FileController extends BaseController {
@Inject()
fileService: FileService;
@Post('/upload', { summary: 'sys:settings:view' })
@Post('/upload', { summary: Constants.per.authOnly })
async upload(@Files() files: UploadFileInfo<string>[], @Fields() fields: any) {
console.log('files', files, fields);
const cacheKey = uploadTmpFileCacheKey + nanoid();
@@ -0,0 +1,27 @@
import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core';
import { BaseController, Constants } from '@certd/lib-server';
import { CnameRecordService } from '../service/cname-record-service.js';
import { CnameProviderService } from '../../sys/cname/service/cname-provider-service.js';
/**
* 授权
*/
@Provide()
@Controller('/api/cname/provider')
export class CnameProviderController extends BaseController {
@Inject()
service: CnameRecordService;
@Inject()
providerService: CnameProviderService;
getService(): CnameRecordService {
return this.service;
}
@Post('/list', { summary: Constants.per.authOnly })
async list(@Body(ALL) body: any) {
body.userId = this.ctx.user.id;
const res = await this.providerService.find({});
return this.ok(res);
}
}
@@ -0,0 +1,61 @@
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
import { Constants, CrudController } from '@certd/lib-server';
import { CnameRecordService } from '../service/cname-record-service.js';
/**
* 授权
*/
@Provide()
@Controller('/api/cname/record')
export class CnameRecordController extends CrudController<CnameRecordService> {
@Inject()
service: CnameRecordService;
getService(): CnameRecordService {
return this.service;
}
@Post('/page', { summary: Constants.per.authOnly })
async page(@Body(ALL) body: any) {
body.query = body.query ?? {};
body.query.userId = this.ctx.user.id;
return await super.page(body);
}
@Post('/list', { summary: Constants.per.authOnly })
async list(@Body(ALL) body: any) {
body.userId = this.ctx.user.id;
return super.list(body);
}
@Post('/add', { summary: Constants.per.authOnly })
async add(@Body(ALL) bean: any) {
bean.userId = this.ctx.user.id;
return super.add(bean);
}
@Post('/update', { summary: Constants.per.authOnly })
async update(@Body(ALL) bean: any) {
await this.service.checkUserId(bean.id, this.ctx.user.id);
return super.update(bean);
}
@Post('/info', { summary: Constants.per.authOnly })
async info(@Query('id') id: number) {
await this.service.checkUserId(id, this.ctx.user.id);
return super.info(id);
}
@Post('/delete', { summary: Constants.per.authOnly })
async delete(@Query('id') id: number) {
await this.service.checkUserId(id, this.ctx.user.id);
return super.delete(id);
}
@Post('/getByDomain', { summary: Constants.per.authOnly })
async getByDomain(@Body(ALL) body: { domain: string; createOnNotFound: boolean }) {
const userId = this.ctx.user.id;
const res = await this.service.getByDomain(body.domain, userId, body.createOnNotFound);
return this.ok(res);
}
}
@@ -0,0 +1,41 @@
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
/**
* cname record配置
*/
@Entity('cd_cname_record')
export class CnameRecordEntity {
@PrimaryGeneratedColumn()
id: number;
@Column({ comment: '用户ID', name: 'user_id' })
userId: number;
@Column({ comment: '证书申请域名', length: 100 })
domain: string;
@Column({ comment: '主机记录', name: 'host_record', length: 100 })
hostRecord: string;
@Column({ comment: '记录值', name: 'record_value', length: 200 })
recordValue: string;
@Column({ comment: 'CNAME提供者', name: 'cname_provider_id' })
cnameProviderId: number;
@Column({ comment: '验证状态', length: 20 })
status: string;
@Column({
comment: '创建时间',
name: 'create_time',
default: () => 'CURRENT_TIMESTAMP',
})
createTime: Date;
@Column({
comment: '修改时间',
name: 'update_time',
default: () => 'CURRENT_TIMESTAMP',
})
updateTime: Date;
}
@@ -0,0 +1,133 @@
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { BaseService, ValidateException } from '@certd/lib-server';
import { CnameRecordEntity } from '../entity/cname-record.js';
import { v4 as uuidv4 } from 'uuid';
import { CnameProviderService } from '../../sys/cname/service/cname-provider-service.js';
import { CnameProviderEntity } from '../../sys/cname/entity/cname_provider.js';
import { parseDomain } from '@certd/plugin-cert';
/**
* 授权
*/
@Provide()
@Scope(ScopeEnum.Singleton)
export class CnameRecordService extends BaseService<CnameRecordEntity> {
@InjectEntityModel(CnameRecordEntity)
repository: Repository<CnameRecordEntity>;
@Inject()
cnameProviderService: CnameProviderService;
getRepository() {
return this.repository;
}
/**
* 新增
* @param param 数据
*/
async add(param: any): Promise<CnameRecordEntity> {
if (!param.domain) {
throw new ValidateException('域名不能为空');
}
if (!param.userId) {
throw new ValidateException('userId不能为空');
}
if (param.domain.startsWith('*.')) {
param.domain = param.domain.substring(2);
}
const info = await this.getRepository().findOne({ where: { domain: param.domain } });
if (info) {
return info;
}
let cnameProvider: CnameProviderEntity = null;
if (!param.cnameProviderId) {
//获取默认的cnameProviderId
cnameProvider = await this.cnameProviderService.getByPriority();
if (cnameProvider == null) {
throw new ValidateException('找不到CNAME服务,请先联系管理员添加CNAME服务');
}
} else {
cnameProvider = await this.cnameProviderService.info(param.cnameProviderId);
}
this.cnameProviderChanged(param, cnameProvider);
param.status = 'cname';
const { id } = await super.add(param);
return await this.info(id);
}
private cnameProviderChanged(param: any, cnameProvider: CnameProviderEntity) {
param.cnameProviderId = cnameProvider.id;
const realDomain = parseDomain(param.domain);
const prefix = param.domain.replace(realDomain, '');
let hostRecord = `_acme-challenge.${prefix}`;
if (hostRecord.endsWith('.')) {
hostRecord = hostRecord.substring(0, hostRecord.length - 1);
}
param.hostRecord = hostRecord;
const cnameKey = uuidv4().replaceAll('-', '');
param.recordValue = `${cnameKey}.${cnameProvider.domain}`;
}
async update(param: any) {
if (!param.id) {
throw new ValidateException('id不能为空');
}
const old = await this.info(param.id);
if (!old) {
throw new ValidateException('数据不存在');
}
if (old.domain !== param.domain) {
throw new ValidateException('域名不允许修改');
}
if (old.cnameProviderId !== param.cnameProviderId) {
const cnameProvider = await this.cnameProviderService.info(param.cnameProviderId);
this.cnameProviderChanged(param, cnameProvider);
param.status = 'cname';
}
return await super.update(param);
}
async validate(id: number) {
const info = await this.info(id);
if (info.status === 'success') {
return true;
}
//开始校验
// 1. dnsProvider
// 2. 添加txt记录
// 3. 检查原域名是否有cname记录
}
async getByDomain(domain: string, userId: number, createOnNotFound = true) {
if (!domain) {
throw new ValidateException('domain不能为空');
}
if (userId == null) {
throw new ValidateException('userId不能为空');
}
let record = await this.getRepository().findOne({ where: { domain, userId } });
if (record == null) {
if (createOnNotFound) {
record = await this.add({ domain, userId });
} else {
throw new ValidateException(`找不到${domain}的CNAME记录`);
}
}
const provider = await this.cnameProviderService.info(record.cnameProviderId);
if (provider == null) {
throw new ValidateException(`找不到${domain}的CNAME服务`);
}
return {
...record,
cnameProvider: provider,
};
}
}
@@ -1,8 +1,8 @@
import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core';
import { BaseController } from '@certd/lib-server';
import { Constants } from '@certd/lib-server';
import { UserService } from '../../authority/service/user-service.js';
import { UserEntity } from '../../authority/entity/user.js';
import { UserService } from '../../sys/authority/service/user-service.js';
import { UserEntity } from '../../sys/authority/entity/user.js';
import { SysSettingsService } from '@certd/lib-server';
/**
@@ -1,9 +1,9 @@
import { Config, Inject, Provide } from '@midwayjs/core';
import { UserService } from '../../authority/service/user-service.js';
import { UserService } from '../../sys/authority/service/user-service.js';
import jwt from 'jsonwebtoken';
import { CommonException } from '@certd/lib-server';
import { RoleService } from '../../authority/service/role-service.js';
import { UserEntity } from '../../authority/entity/user.js';
import { RoleService } from '../../sys/authority/service/role-service.js';
import { UserEntity } from '../../sys/authority/entity/user.js';
import { SysSettingsService } from '@certd/lib-server';
import { SysPrivateSettings } from '@certd/lib-server';
@@ -1,7 +1,7 @@
import { ALL, Body, Controller, Inject, Post, Provide } from '@midwayjs/core';
import { BaseController, Constants } from '@certd/lib-server';
import { UserService } from '../../authority/service/user-service.js';
import { RoleService } from '../../authority/service/role-service.js';
import { UserService } from '../../sys/authority/service/user-service.js';
import { RoleService } from '../../sys/authority/service/role-service.js';
/**
*/
@@ -1,12 +1,4 @@
import {
ALL,
Body,
Controller,
Inject,
Post,
Provide,
Query,
} from '@midwayjs/core';
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
import { CrudController } from '@certd/lib-server';
import { Constants } from '@certd/lib-server';
import { UserSettingsService } from '../service/user-settings-service.js';
@@ -8,7 +8,7 @@ import { HistoryLogEntity } from '../entity/history-log.js';
import { PipelineService } from '../service/pipeline-service.js';
import * as fs from 'fs';
import { logger } from '@certd/pipeline';
import { AuthService } from '../../authority/service/auth-service.js';
import { AuthService } from '../../sys/authority/service/auth-service.js';
import { SysSettingsService } from '@certd/lib-server';
import { In } from 'typeorm';
@@ -4,7 +4,7 @@ import { PipelineService } from '../service/pipeline-service.js';
import { PipelineEntity } from '../entity/pipeline.js';
import { Constants } from '@certd/lib-server';
import { HistoryService } from '../service/history-service.js';
import { AuthService } from '../../authority/service/auth-service.js';
import { AuthService } from '../../sys/authority/service/auth-service.js';
import { SysSettingsService } from '@certd/lib-server';
/**
@@ -0,0 +1,14 @@
import { IAccessService } from '@certd/pipeline';
export class AccessGetter implements IAccessService {
userId: number;
getter: <T>(id: any, userId?: number) => Promise<T>;
constructor(userId: number, getter: (id: any, userId: number) => Promise<any>) {
this.userId = userId;
this.getter = getter;
}
async getById<T = any>(id: any) {
return await this.getter<T>(id, this.userId);
}
}
@@ -1,18 +1,17 @@
import { Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { BaseService } from '@certd/lib-server';
import { BaseService, PermissionException, ValidateException } from '@certd/lib-server';
import { AccessEntity } from '../entity/access.js';
import { AccessDefine, accessRegistry, IAccessService, newAccess } from '@certd/pipeline';
import { AccessDefine, accessRegistry, newAccess } from '@certd/pipeline';
import { EncryptService } from './encrypt-service.js';
import { ValidateException } from '@certd/lib-server';
/**
* 授权
*/
@Provide()
@Scope(ScopeEnum.Singleton)
export class AccessService extends BaseService<AccessEntity> implements IAccessService {
export class AccessService extends BaseService<AccessEntity> {
@InjectEntityModel(AccessEntity)
repository: Repository<AccessEntity>;
@@ -102,11 +101,14 @@ export class AccessService extends BaseService<AccessEntity> implements IAccessS
return await super.update(param);
}
async getById(id: any): Promise<any> {
async getById(id: any, userId?: number): Promise<any> {
const entity = await this.info(id);
if (entity == null) {
throw new Error(`该授权配置不存在,请确认是否已被删除:id=${id}`);
}
if (userId !== entity.userId) {
throw new PermissionException('您对该授权无访问权限');
}
// const access = accessRegistry.get(entity.type);
const setting = this.decryptAccessEntity(entity);
const input = {
@@ -0,0 +1,14 @@
import { CnameRecord, ICnameProxyService } from '@certd/pipeline';
export class CnameProxyService implements ICnameProxyService {
userId: number;
getter: <T>(domain: string, userId?: number) => Promise<T>;
constructor(userId: number, getter: (domain: string, userId: number) => Promise<any>) {
this.userId = userId;
this.getter = getter;
}
getByDomain(domain: string): Promise<CnameRecord> {
return this.getter<CnameRecord>(domain, this.userId);
}
}
@@ -16,7 +16,10 @@ import { HistoryLogService } from './history-log-service.js';
import { logger } from '@certd/pipeline';
import { EmailService } from '../../basic/service/email-service.js';
import { NeedVIPException } from '@certd/lib-server';
import { UserService } from '../../authority/service/user-service.js';
import { UserService } from '../../sys/authority/service/user-service.js';
import { AccessGetter } from './access-getter.js';
import { CnameRecordService } from '../../cname/service/cname-record-service.js';
import { CnameProxyService } from './cname-proxy-service.js';
const runningTasks: Map<string | number, Executor> = new Map();
const freeCount = 10;
@@ -34,6 +37,8 @@ export class PipelineService extends BaseService<PipelineEntity> {
@Inject()
accessService: AccessService;
@Inject()
cnameRecordService: CnameRecordService;
@Inject()
storageService: StorageService;
@Inject()
historyService: HistoryService;
@@ -341,11 +346,14 @@ export class PipelineService extends BaseService<PipelineEntity> {
id: userId,
role: userIsAdmin ? 'admin' : 'user',
};
const accessGetter = new AccessGetter(userId, this.accessService.getById.bind(this.accessService));
const cnameProxyService = new CnameProxyService(userId, this.cnameRecordService.getByDomain.bind(this.cnameRecordService));
const executor = new Executor({
user,
pipeline,
onChanged,
accessService: this.accessService,
accessService: accessGetter,
cnameProxyService,
storage: new DbStorage(userId, this.storageService),
emailService: this.emailService,
fileRootDir: this.certdConfig.fileRootDir,
@@ -14,7 +14,7 @@ import { UserRoleEntity } from '../entity/user-role.js';
import bcrypt from 'bcryptjs';
import { SysSettingsService } from '@certd/lib-server';
import { SysInstallInfo } from '@certd/lib-server';
import { RandomUtil } from '../../../utils/random.js';
import { RandomUtil } from '../../../../utils/random.js';
/**
*
@@ -0,0 +1,66 @@
import { ALL, Body, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
import { CrudController } from '@certd/lib-server';
import { CnameProviderService } from '../service/cname-provider-service.js';
import { merge } from 'lodash-es';
/**
* 授权
*/
@Provide()
@Controller('/api/sys/cname/provider')
export class CnameRecordController extends CrudController<CnameProviderService> {
@Inject()
service: CnameProviderService;
getService(): CnameProviderService {
return this.service;
}
@Post('/page', { summary: 'sys:settings:view' })
async page(@Body(ALL) body: any) {
body.query = body.query ?? {};
return await super.page(body);
}
@Post('/list', { summary: 'sys:settings:view' })
async list(@Body(ALL) body: any) {
return super.list(body);
}
@Post('/add', { summary: 'sys:settings:edit' })
async add(@Body(ALL) bean: any) {
const def: any = {
isDefault: false,
disabled: false,
};
merge(bean, def);
return super.add(bean);
}
@Post('/update', { summary: 'sys:settings:edit' })
async update(@Body(ALL) bean: any) {
return super.update(bean);
}
@Post('/info', { summary: 'sys:settings:view' })
async info(@Query('id') id: number) {
return super.info(id);
}
@Post('/delete', { summary: 'sys:settings:edit' })
async delete(@Query('id') id: number) {
return super.delete(id);
}
@Post('/setDefault', { summary: 'sys:settings:edit' })
async setDefault(@Body('id') id: number) {
await this.service.setDefault(id);
return this.ok();
}
@Post('/setDisabled', { summary: 'sys:settings:edit' })
async setDisabled(@Body('id') id: number, @Body('disabled') disabled: boolean) {
await this.service.setDisabled(id, disabled);
return this.ok();
}
}
@@ -0,0 +1,35 @@
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
/**
* cname配置
*/
@Entity('cd_cname_provider')
export class CnameProviderEntity {
@PrimaryGeneratedColumn()
id: number;
@Column({ comment: '域名', length: 100 })
domain: string;
@Column({ comment: 'DNS提供商类型', name: 'dns_provider_type', length: 20 })
dnsProviderType: string;
@Column({ comment: 'DNS授权Id', name: 'access_id' })
accessId: number;
@Column({ comment: '是否默认', name: 'is_default' })
isDefault: boolean;
@Column({ comment: '是否禁用', name: 'disabled' })
disabled: boolean;
@Column({ comment: '备注', length: 200 })
remark: string;
@Column({
comment: '创建时间',
name: 'create_time',
default: () => 'CURRENT_TIMESTAMP',
})
createTime: Date;
@Column({
comment: '修改时间',
name: 'update_time',
default: () => 'CURRENT_TIMESTAMP',
})
updateTime: Date;
}
@@ -0,0 +1,85 @@
import { Provide, Scope, ScopeEnum } from '@midwayjs/core';
import { InjectEntityModel } from '@midwayjs/typeorm';
import { Repository } from 'typeorm';
import { BaseService, ValidateException } from '@certd/lib-server';
import { CnameProviderEntity } from '../entity/cname_provider.js';
/**
* 授权
*/
@Provide()
@Scope(ScopeEnum.Singleton)
export class CnameProviderService extends BaseService<CnameProviderEntity> {
@InjectEntityModel(CnameProviderEntity)
repository: Repository<CnameProviderEntity>;
getRepository() {
return this.repository;
}
async getDefault() {
return await this.repository.findOne({ where: { isDefault: true } });
}
/**
* 新增
* @param param 数据
*/
async add(param: any) {
const def = await this.getDefault();
if (!def) {
param.isDefault = true;
}
const res = await super.add(param);
if (param.isDefault) {
await this.setDefault(res.id);
}
return res;
}
/**
* 修改
* @param param 数据
*/
async update(param: any) {
await super.update(param);
if (param.isDefault) {
await this.setDefault(param.id);
}
}
async delete(ids: any) {
if (!(ids instanceof Array)) {
ids = [ids];
}
for (const id of ids) {
const info = await this.info(id);
if (info.isDefault) {
throw new ValidateException('默认的CNAME服务不能删除,请先修改为非默认值');
}
}
await super.delete(ids);
}
async setDefault(id: number) {
await this.transaction(async em => {
await em.getRepository(CnameProviderEntity).update({ isDefault: true }, { isDefault: false });
await em.getRepository(CnameProviderEntity).update({ id }, { isDefault: true });
});
}
async setDisabled(id: number, disabled: boolean) {
await this.repository.update({ id }, { disabled });
}
async getByPriority() {
const def = await this.getDefault();
if (def) {
return def;
}
const found = await this.repository.findOne({ order: { createTime: 'DESC' } });
if (found) {
return found;
}
return null;
}
}
@@ -4,7 +4,7 @@ import { SysSettingsService } from '@certd/lib-server';
import { SysSettingsEntity } from '../entity/sys-settings.js';
import { SysPublicSettings } from '@certd/lib-server';
import * as _ from 'lodash-es';
import { PipelineService } from '../../pipeline/service/pipeline-service.js';
import { PipelineService } from '../../../pipeline/service/pipeline-service.js';
/**
*/
@@ -17,13 +17,13 @@ export class AliyunDnsProvider extends AbstractDnsProvider {
async onInstance() {
const access: any = this.access;
this.client = new AliyunClient({logger:this.logger})
this.client = new AliyunClient({ logger: this.logger });
await this.client.init({
accessKeyId: access.accessKeyId,
accessKeySecret: access.accessKeySecret,
endpoint: 'https://alidns.aliyuncs.com',
apiVersion: '2015-01-09',
})
});
}
//
// async getDomainList() {
@@ -101,7 +101,6 @@ export class AliyunDnsProvider extends AbstractDnsProvider {
// Line: 'oversea' // 海外
};
const requestOption = {
method: 'POST',
};
@@ -119,7 +118,8 @@ export class AliyunDnsProvider extends AbstractDnsProvider {
}
}
async removeRecord(options: RemoveRecordOptions<any>): Promise<any> {
const { fullRecord, value, record } = options;
const { fullRecord, value } = options.recordReq;
const record = options.recordRes;
const params = {
RegionId: 'cn-hangzhou',
RecordId: record,
@@ -31,7 +31,7 @@ export class DeployCertToAliyunCDN extends AbstractTaskPlugin {
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: ['CertApply', 'CertApplyLego'],
},
required: true,
@@ -42,7 +42,7 @@ export class DeployCertToAliyunCDN extends AbstractTaskPlugin {
title: 'Access授权',
helper: '阿里云授权AccessKeyId、AccessKeySecret',
component: {
name: 'pi-access-selector',
name: 'access-selector',
type: 'aliyun',
},
required: true,
@@ -31,7 +31,7 @@ export class DeployCertToAliyunDCDN extends AbstractTaskPlugin {
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: ['CertApply', 'CertApplyLego'],
},
required: true,
@@ -42,7 +42,7 @@ export class DeployCertToAliyunDCDN extends AbstractTaskPlugin {
title: 'Access授权',
helper: '阿里云授权AccessKeyId、AccessKeySecret',
component: {
name: 'pi-access-selector',
name: 'access-selector',
type: 'aliyun',
},
required: true,
@@ -37,7 +37,7 @@ export class UploadCertToAliyun extends AbstractTaskPlugin {
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: ['CertApply', 'CertApplyLego'],
},
required: true,
@@ -48,7 +48,7 @@ export class UploadCertToAliyun extends AbstractTaskPlugin {
title: 'Access授权',
helper: '阿里云授权AccessKeyId、AccessKeySecret',
component: {
name: 'pi-access-selector',
name: 'access-selector',
type: 'aliyun',
},
required: true,
@@ -1,9 +1,4 @@
import {
AbstractDnsProvider,
CreateRecordOptions,
IsDnsProvider,
RemoveRecordOptions,
} from '@certd/plugin-cert';
import { AbstractDnsProvider, CreateRecordOptions, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert';
import { Autowire, HttpClient, ILogger } from '@certd/pipeline';
import { CloudflareAccess } from './access.js';
@@ -88,9 +83,7 @@ export class CloudflareDnsProvider extends AbstractDnsProvider<CloudflareRecord>
ttl: 60,
});
const record = res.result as CloudflareRecord;
this.logger.info(
`添加域名解析成功:fullRecord=${fullRecord},value=${value}`
);
this.logger.info(`添加域名解析成功:fullRecord=${fullRecord},value=${value}`);
this.logger.info(`dns解析记录:${JSON.stringify(record)}`);
//本接口需要返回本次创建的dns解析记录,这个记录会在删除的时候用到
@@ -101,10 +94,9 @@ export class CloudflareDnsProvider extends AbstractDnsProvider<CloudflareRecord>
* 删除dns解析记录,清理申请痕迹
* @param options
*/
async removeRecord(
options: RemoveRecordOptions<CloudflareRecord>
): Promise<void> {
const { fullRecord, value, record } = options;
async removeRecord(options: RemoveRecordOptions<CloudflareRecord>): Promise<void> {
const { fullRecord, value } = options.recordReq;
const record = options.recordRes;
this.logger.info('删除域名解析:', fullRecord, value);
if (!record) {
this.logger.info('record不存在');
@@ -115,9 +107,7 @@ export class CloudflareDnsProvider extends AbstractDnsProvider<CloudflareRecord>
const recordId = record.id;
const url = `https://api.cloudflare.com/client/v4/zones/${zoneId}/dns_records/${recordId}`;
await this.doRequestApi(url, null, 'delete');
this.logger.info(
`删除域名解析成功:fullRecord=${fullRecord},value=${value}`
);
this.logger.info(`删除域名解析成功:fullRecord=${fullRecord},value=${value}`);
}
}
@@ -54,7 +54,7 @@ export class CloudflareDeployToCDNPlugin extends AbstractTaskPlugin {
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: ['CertApply', 'CertApplyLego'],
},
required: true,
@@ -66,7 +66,7 @@ export class CloudflareDeployToCDNPlugin extends AbstractTaskPlugin {
title: 'demo授权',
helper: 'demoAccess授权',
component: {
name: 'pi-access-selector',
name: 'access-selector',
type: 'plugins',
},
rules: [{ required: true, message: '此项必填' }],
@@ -61,8 +61,9 @@ export class DemoDnsProvider extends AbstractDnsProvider<DemoRecord> {
* @param options
*/
async removeRecord(options: RemoveRecordOptions<DemoRecord>): Promise<void> {
const { fullRecord, value, record } = options;
this.logger.info('删除域名解析:', fullRecord, value, record);
const { fullRecord, value, domain } = options.recordReq;
const record = options.recordRes;
this.logger.info('删除域名解析:', domain, fullRecord, value, record);
//这里调用删除txt dns解析记录接口
//请根据实际接口情况调用,例如:
@@ -53,7 +53,7 @@ export class DemoTestPlugin extends AbstractTaskPlugin {
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: ['CertApply', 'CertApplyLego'],
},
// required: true,
@@ -65,7 +65,7 @@ export class DemoTestPlugin extends AbstractTaskPlugin {
title: 'demo授权',
helper: 'demoAccess授权',
component: {
name: 'pi-access-selector',
name: 'access-selector',
type: 'demo', //固定授权类型
},
// rules: [{ required: true, message: '此项必填' }],
@@ -26,7 +26,7 @@ export class DogeCloudDeployToCDNPlugin extends AbstractTaskPlugin {
title: '证书',
helper: '请选择前置任务输出的域名证书',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: ['CertApply', 'CertApplyLego'],
},
required: true,
@@ -38,7 +38,7 @@ export class DogeCloudDeployToCDNPlugin extends AbstractTaskPlugin {
title: '多吉云授权',
helper: '多吉云AccessKey',
component: {
name: 'pi-access-selector',
name: 'access-selector',
type: 'dogecloud',
},
rules: [{ required: true, message: '此项必填' }],
@@ -66,7 +66,7 @@ export class CopyCertToLocalPlugin extends AbstractTaskPlugin {
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: ['CertApply', 'CertApplyLego'],
},
required: true,
@@ -19,7 +19,7 @@ export class HostShellExecutePlugin extends AbstractTaskPlugin {
title: '主机登录配置',
helper: '登录',
component: {
name: 'pi-access-selector',
name: 'access-selector',
type: 'ssh',
},
required: true,
@@ -65,7 +65,7 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin {
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: ['CertApply', 'CertApplyLego'],
},
required: true,
@@ -76,7 +76,7 @@ export class UploadCertToHostPlugin extends AbstractTaskPlugin {
title: '主机登录配置',
helper: 'access授权',
component: {
name: 'pi-access-selector',
name: 'access-selector',
type: 'ssh',
},
required: true,
@@ -73,8 +73,8 @@ export class HuaweiDnsProvider extends AbstractDnsProvider {
if (records && records.length > 0) {
for (const record of records) {
await this.removeRecord({
record,
...options,
recordRes: record,
recordReq: options,
});
}
}
@@ -101,7 +101,8 @@ export class HuaweiDnsProvider extends AbstractDnsProvider {
}
}
async removeRecord(options: RemoveRecordOptions<any>): Promise<any> {
const { fullRecord, value, record } = options;
const { fullRecord, value } = options.recordReq;
const record = options.recordRes;
const req: ApiRequestOptions = {
url: `${this.dnsEndpoint}/v2/zones/${record.zone_id}/recordsets/${record.id}`,
method: 'DELETE',
@@ -102,10 +102,11 @@ export class JDCloudDnsProvider extends AbstractDnsProvider {
/**
* 删除dns解析记录,清理申请痕迹
* @param opts
* @param options
*/
async removeRecord(opts: RemoveRecordOptions<any>): Promise<void> {
const { record } = opts;
async removeRecord(options: RemoveRecordOptions<any>): Promise<void> {
// const { fullRecord, value, domain } = options.recordReq;
const record = options.recordRes;
const deleteResourceRecord = promisfy(this.service.deleteResourceRecord);
const res: any = await deleteResourceRecord(
{
@@ -36,7 +36,7 @@ export class CustomScriptPlugin extends AbstractTaskPlugin {
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: ['CertApply', 'CertApplyLego'],
},
required: false,
@@ -26,7 +26,7 @@ export class QiniuDeployCertToCDN extends AbstractTaskPlugin {
title: '域名证书',
helper: '请选择前置任务输出的域名证书,或者上传到七牛云的证书id',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: ['CertApply', 'CertApplyLego', 'QiniuCertUpload'],
},
required: true,
@@ -37,7 +37,7 @@ export class QiniuDeployCertToCDN extends AbstractTaskPlugin {
title: 'Access授权',
helper: '七牛云授权',
component: {
name: 'pi-access-selector',
name: 'access-selector',
type: 'qiniu',
},
required: true,
@@ -25,7 +25,7 @@ export class QiniuCertUpload extends AbstractTaskPlugin {
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: ['CertApply', 'CertApplyLego'],
},
required: true,
@@ -36,7 +36,7 @@ export class QiniuCertUpload extends AbstractTaskPlugin {
title: 'Access授权',
helper: '七牛云授权',
component: {
name: 'pi-access-selector',
name: 'access-selector',
type: 'qiniu',
},
required: true,
@@ -86,7 +86,8 @@ export class DnspodDnsProvider extends AbstractDnsProvider {
}
async removeRecord(options: RemoveRecordOptions<any>) {
const { fullRecord, value, record } = options;
const { fullRecord, value } = options.recordReq;
const record = options.recordRes;
const domain = await this.matchDomain(fullRecord);
const ret = await this.doRequest({
@@ -70,8 +70,8 @@ export class TencentDnsProvider extends AbstractDnsProvider {
}
async removeRecord(options: RemoveRecordOptions<any>) {
const { fullRecord, value, domain, record } = options;
const { fullRecord, value, domain } = options.recordReq;
const record = options.recordRes;
const params = {
Domain: domain,
RecordId: record.RecordId,
@@ -18,7 +18,7 @@ export class DeployToCdnPlugin extends AbstractTaskPlugin {
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: ['CertApply', 'CertApplyLego'],
},
required: true,
@@ -29,7 +29,7 @@ export class DeployToCdnPlugin extends AbstractTaskPlugin {
title: 'Access提供者',
helper: 'access 授权',
component: {
name: 'pi-access-selector',
name: 'access-selector',
type: 'tencent',
},
required: true,
@@ -75,7 +75,7 @@ export class DeployToClbPlugin extends AbstractTaskPlugin {
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: ['CertApply', 'CertApplyLego'],
},
required: true,
@@ -86,7 +86,7 @@ export class DeployToClbPlugin extends AbstractTaskPlugin {
title: 'Access提供者',
helper: 'access授权',
component: {
name: 'pi-access-selector',
name: 'access-selector',
type: 'tencent',
},
required: true,
@@ -18,7 +18,7 @@ export class DeployToEOPlugin extends AbstractTaskPlugin {
title: '已上传证书ID',
helper: '请选择前置任务上传到腾讯云的证书',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: 'UploadCertToTencent',
},
required: true,
@@ -29,7 +29,7 @@ export class DeployToEOPlugin extends AbstractTaskPlugin {
title: 'Access提供者',
helper: 'access 授权',
component: {
name: 'pi-access-selector',
name: 'access-selector',
type: 'tencent',
},
required: true,
@@ -21,7 +21,7 @@ export class UploadToTencentPlugin extends AbstractTaskPlugin {
title: 'Access授权',
helper: 'access授权',
component: {
name: 'pi-access-selector',
name: 'access-selector',
type: 'tencent',
},
required: true,
@@ -32,7 +32,7 @@ export class UploadToTencentPlugin extends AbstractTaskPlugin {
title: '域名证书',
helper: '请选择前置任务输出的域名证书',
component: {
name: 'pi-output-selector',
name: 'output-selector',
from: ['CertApply', 'CertApplyLego'],
},
required: true,
@@ -97,7 +97,8 @@ export class WestDnsProvider extends AbstractDnsProvider<westRecord> {
* @param options
*/
async removeRecord(options: RemoveRecordOptions<westRecord>): Promise<void> {
const { fullRecord, value, record, domain } = options;
const { fullRecord, value, domain } = options.recordReq;
const record = options.recordRes;
this.logger.info('删除域名解析:', fullRecord, value, record);
if (!record) {
this.logger.info('record不存在');