mirror of
https://github.com/certd/certd.git
synced 2026-04-03 14:10:54 +08:00
Compare commits
4 Commits
d1a65922d7
...
6b29972399
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b29972399 | ||
|
|
0fcd3c09fd | ||
|
|
af503442b8 | ||
|
|
c875971b71 |
@@ -78,10 +78,10 @@ export default defineComponent({
|
||||
async function emitValue(value) {
|
||||
const userId = userStore.userInfo.id;
|
||||
const isEnterprice = projectStore.isEnterprise;
|
||||
if (pipeline.value) {
|
||||
if (pipeline?.value) {
|
||||
if (isEnterprice) {
|
||||
const projectId = projectStore.currentProjectId;
|
||||
if (pipeline.value.projectId !== projectId) {
|
||||
if (pipeline?.value?.projectId !== projectId) {
|
||||
message.error(`对不起,您不能修改其他项目流水线的授权`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ async function emitValue(value: any) {
|
||||
const isEnterprice = projectStore.isEnterprise;
|
||||
if (isEnterprice) {
|
||||
const projectId = projectStore.currentProjectId;
|
||||
if (pipeline.value.projectId !== projectId) {
|
||||
if (pipeline?.value?.projectId !== projectId) {
|
||||
message.error(`对不起,您不能修改其他项目流水线的${props.addonType}设置`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -136,12 +136,12 @@ async function emitValue(value: any) {
|
||||
|
||||
if (isEnterprice) {
|
||||
const projectId = projectStore.currentProjectId;
|
||||
if (pipeline.value.projectId !== projectId) {
|
||||
if (pipeline?.value?.projectId !== projectId) {
|
||||
message.error("对不起,您不能修改其他项目流水线的通知");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (pipeline.value.userId !== userId) {
|
||||
if (pipeline?.value?.userId !== userId) {
|
||||
message.error("对不起,您不能修改他人流水线的通知");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -44,4 +44,5 @@
|
||||
// export * from './plugin-lib/index.js'
|
||||
// export * from './plugin-plus/index.js'
|
||||
// export * from './plugin-cert/index.js'
|
||||
// export * from './plugin-zenlayer/index.js'
|
||||
// export * from './plugin-zenlayer/index.js'
|
||||
export * from './plugin-dnsmgr/index.js'
|
||||
144
packages/ui/certd-server/src/plugins/plugin-dnsmgr/access.ts
Normal file
144
packages/ui/certd-server/src/plugins/plugin-dnsmgr/access.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
import { AccessInput, BaseAccess, IsAccess, Pager, PageRes, PageSearch } from '@certd/pipeline';
|
||||
import { DomainRecord } from '@certd/plugin-lib';
|
||||
|
||||
@IsAccess({
|
||||
name: 'dnsmgr',
|
||||
title: '彩虹DNS',
|
||||
icon: 'clarity:plugin-line',
|
||||
desc: '彩虹DNS管理系统授权',
|
||||
})
|
||||
export class DnsmgrAccess extends BaseAccess {
|
||||
@AccessInput({
|
||||
title: '系统地址',
|
||||
component: {
|
||||
name: "a-input",
|
||||
allowClear: true,
|
||||
placeholder: 'https://dnsmgr.example.com',
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
endpoint = '';
|
||||
|
||||
@AccessInput({
|
||||
title: '用户ID',
|
||||
component: {
|
||||
name: "a-input",
|
||||
allowClear: true,
|
||||
placeholder: '123456',
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
uid = '';
|
||||
|
||||
@AccessInput({
|
||||
title: 'API密钥',
|
||||
required: true,
|
||||
encrypt: true,
|
||||
})
|
||||
key = '';
|
||||
|
||||
@AccessInput({
|
||||
title: "测试",
|
||||
component: {
|
||||
name: "api-test",
|
||||
action: "TestRequest"
|
||||
},
|
||||
helper: "点击测试接口是否正常"
|
||||
})
|
||||
testRequest = true;
|
||||
|
||||
async onTestRequest() {
|
||||
await this.GetDomainList({});
|
||||
return "ok";
|
||||
}
|
||||
|
||||
async GetDomainList(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
||||
this.ctx.logger.info(`获取域名列表,req:${JSON.stringify(req)}`);
|
||||
const pager = new Pager(req);
|
||||
const resp = await this.doRequest({
|
||||
url: '/api/domain',
|
||||
data: {
|
||||
offset: pager.getOffset(),
|
||||
limit: pager.pageSize,
|
||||
kw: req.searchKey,
|
||||
},
|
||||
});
|
||||
const total = resp?.total || 0;
|
||||
let list = resp?.rows?.map((item: any) => {
|
||||
return {
|
||||
domain: item.name,
|
||||
...item,
|
||||
};
|
||||
});
|
||||
return {
|
||||
total,
|
||||
list,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
async createDnsRecord(domainId: string, record: string, value: string, type: string, domain: string) {
|
||||
this.ctx.logger.info(`创建DNS记录:${record} ${type} ${value}`);
|
||||
const resp = await this.doRequest({
|
||||
url: `/api/record/add/${domainId}`,
|
||||
data: {
|
||||
name: record.replace(`.${domain}`, ''),
|
||||
type,
|
||||
value,
|
||||
line: 'default',
|
||||
ttl: 600,
|
||||
},
|
||||
});
|
||||
return resp;
|
||||
}
|
||||
|
||||
async getDnsRecords(domainId: string, type?: string, name?: string, value?: string) {
|
||||
this.ctx.logger.info(`获取DNS记录列表:domainId=${domainId}, type=${type}, name=${name}`);
|
||||
const resp = await this.doRequest({
|
||||
url: `/api/record/data/${domainId}`,
|
||||
data: {
|
||||
type,
|
||||
subdomain: name,
|
||||
value,
|
||||
},
|
||||
});
|
||||
return resp;
|
||||
}
|
||||
|
||||
async deleteDnsRecord(domainId: string, recordId: string) {
|
||||
this.ctx.logger.info(`删除DNS记录:domainId=${domainId}, recordId=${recordId}`);
|
||||
const resp = await this.doRequest({
|
||||
url: `/api/record/delete/${domainId}`,
|
||||
data: {
|
||||
recordid: recordId,
|
||||
},
|
||||
});
|
||||
return resp;
|
||||
}
|
||||
|
||||
async doRequest(req: { url: string; data?: any }) {
|
||||
const timestamp = Math.floor(Date.now() / 1000);
|
||||
const sign = this.ctx.utils.hash.md5(`${this.uid}${timestamp}${this.key}`);
|
||||
const url = `${this.endpoint}${req.url}`;
|
||||
|
||||
const res = await this.ctx.http.request({
|
||||
url,
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
data: {
|
||||
uid: this.uid,
|
||||
timestamp,
|
||||
sign,
|
||||
...req.data,
|
||||
},
|
||||
});
|
||||
|
||||
if (res.code !== undefined && res.code !== 0) {
|
||||
throw new Error(res.msg || '请求失败');
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import { AbstractDnsProvider, CreateRecordOptions, DomainRecord, IsDnsProvider, RemoveRecordOptions } from '@certd/plugin-cert';
|
||||
import { DnsmgrAccess } from './access.js';
|
||||
import { PageRes, PageSearch } from '@certd/pipeline';
|
||||
|
||||
type DnsmgrRecord = {
|
||||
domainId: string;
|
||||
name: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
@IsDnsProvider({
|
||||
name: 'dnsmgr',
|
||||
title: '彩虹DNS',
|
||||
desc: '彩虹DNS管理系统',
|
||||
icon: 'clarity:plugin-line',
|
||||
accessType: 'dnsmgr',
|
||||
order: 99,
|
||||
})
|
||||
export class DnsmgrDnsProvider extends AbstractDnsProvider<DnsmgrRecord> {
|
||||
access!: DnsmgrAccess;
|
||||
|
||||
async onInstance() {
|
||||
this.access = this.ctx.access as DnsmgrAccess;
|
||||
this.logger.debug('access', this.access);
|
||||
}
|
||||
|
||||
async createRecord(options: CreateRecordOptions): Promise<any> {
|
||||
const { fullRecord, value, type, domain } = options;
|
||||
this.logger.info('添加域名解析:', fullRecord, value, type, domain);
|
||||
|
||||
const domainList = await this.access.GetDomainList({ searchKey: domain });
|
||||
const domainInfo = domainList.list?.find((item: any) => item.name === domain);
|
||||
|
||||
if (!domainInfo) {
|
||||
throw new Error(`未找到域名:${domain}`);
|
||||
}
|
||||
|
||||
const name = fullRecord.replace(`.${domain}`, '');
|
||||
const res = await this.access.createDnsRecord(domainInfo.id, fullRecord, value, type, domain);
|
||||
return { domainId: domainInfo.id, name, value,res };
|
||||
}
|
||||
|
||||
async removeRecord(options: RemoveRecordOptions<DnsmgrRecord>): Promise<void> {
|
||||
const { fullRecord, value } = options.recordReq;
|
||||
const record = options.recordRes;
|
||||
this.logger.info('删除域名解析:', fullRecord, value, record);
|
||||
|
||||
if (record && record.domainId) {
|
||||
const records = await this.access.getDnsRecords(record.domainId, 'TXT', record.name, record.value);
|
||||
if (records && records.rows && records.rows.length > 0) {
|
||||
const recordToDelete = records.rows[0];
|
||||
await this.access.deleteDnsRecord(record.domainId, recordToDelete.RecordId);
|
||||
}
|
||||
}
|
||||
|
||||
this.logger.info('删除域名解析成功:', fullRecord, value);
|
||||
}
|
||||
|
||||
async getDomainListPage(req: PageSearch): Promise<PageRes<DomainRecord>> {
|
||||
const res = await this.access.GetDomainList(req);
|
||||
res.list = res.list?.map((item: any) => {
|
||||
return {
|
||||
id: item.id,
|
||||
domain: item.name,
|
||||
};
|
||||
});
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
new DnsmgrDnsProvider();
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from './access.js';
|
||||
export * from './dns-provider.js';
|
||||
@@ -1,7 +1,7 @@
|
||||
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
|
||||
import dayjs from 'dayjs';
|
||||
import { TencentAccess } from '../../../plugin-lib/tencent/index.js';
|
||||
import { CertApplyPluginNames} from '@certd/plugin-cert';
|
||||
import { CertApplyPluginNames, CertInfo } from '@certd/plugin-cert';
|
||||
@IsTaskPlugin({
|
||||
name: 'DeployCertToTencentCLB',
|
||||
title: '腾讯云-部署到CLB',
|
||||
@@ -15,6 +15,31 @@ import { CertApplyPluginNames} from '@certd/plugin-cert';
|
||||
},
|
||||
})
|
||||
export class DeployCertToTencentCLB extends AbstractTaskPlugin {
|
||||
|
||||
@TaskInput({
|
||||
title: '域名证书',
|
||||
helper: '请选择前置任务输出的域名证书',
|
||||
component: {
|
||||
name: 'output-selector',
|
||||
from: [...CertApplyPluginNames, 'UploadCertToTencent'],
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
cert!: string | CertInfo;
|
||||
|
||||
|
||||
|
||||
@TaskInput({
|
||||
title: 'Access提供者',
|
||||
helper: 'access授权',
|
||||
component: {
|
||||
name: 'access-selector',
|
||||
type: 'tencent',
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
accessId!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: '大区',
|
||||
component: {
|
||||
@@ -46,14 +71,10 @@ export class DeployCertToTencentCLB extends AbstractTaskPlugin {
|
||||
})
|
||||
region!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: '证书名称前缀',
|
||||
})
|
||||
certName!: string;
|
||||
|
||||
|
||||
@TaskInput({
|
||||
title: '负载均衡ID',
|
||||
helper: '如果没有配置,则根据域名匹配负载均衡下的监听器(根据域名匹配时暂时只支持前100个)',
|
||||
required: true,
|
||||
})
|
||||
loadBalancerId!: string;
|
||||
@@ -78,26 +99,10 @@ export class DeployCertToTencentCLB extends AbstractTaskPlugin {
|
||||
domain!: string | string[];
|
||||
|
||||
@TaskInput({
|
||||
title: '域名证书',
|
||||
helper: '请选择前置任务输出的域名证书',
|
||||
component: {
|
||||
name: 'output-selector',
|
||||
from: [...CertApplyPluginNames],
|
||||
},
|
||||
required: true,
|
||||
title: '证书名称前缀',
|
||||
})
|
||||
cert!: any;
|
||||
certName!: string;
|
||||
|
||||
@TaskInput({
|
||||
title: 'Access提供者',
|
||||
helper: 'access授权',
|
||||
component: {
|
||||
name: 'access-selector',
|
||||
type: 'tencent',
|
||||
},
|
||||
required: true,
|
||||
})
|
||||
accessId!: string;
|
||||
|
||||
client: any;
|
||||
async onInstance() {
|
||||
@@ -234,12 +239,23 @@ export class DeployCertToTencentCLB extends AbstractTaskPlugin {
|
||||
return name + '-' + dayjs().format('YYYYMMDD-HHmmss');
|
||||
}
|
||||
buildProps() {
|
||||
const certId = this.cert as string;
|
||||
const certInfo = this.cert as CertInfo;
|
||||
if (typeof this.cert === 'string') {
|
||||
return {
|
||||
Certificate: {
|
||||
CertId: certId,
|
||||
},
|
||||
LoadBalancerId: this.loadBalancerId,
|
||||
ListenerId: this.listenerId,
|
||||
};
|
||||
}
|
||||
return {
|
||||
Certificate: {
|
||||
SSLMode: 'UNIDIRECTIONAL', // 单向认证
|
||||
CertName: this.appendTimeSuffix(this.certName || this.cert.domain),
|
||||
CertKey: this.cert.key,
|
||||
CertContent: this.cert.crt,
|
||||
CertName: this.appendTimeSuffix(this.certName || "certd"),
|
||||
CertKey: certInfo.key,
|
||||
CertContent: certInfo.crt,
|
||||
},
|
||||
LoadBalancerId: this.loadBalancerId,
|
||||
ListenerId: this.listenerId,
|
||||
|
||||
Reference in New Issue
Block a user