perf: 支持上传证书到华为云CCM

pull/409/head
xiaojunnuo 2025-04-14 23:31:59 +08:00
parent 75c4f9dea8
commit cfd3b66be9
4 changed files with 255 additions and 0 deletions

View File

@ -0,0 +1,53 @@
// 扫描目录,列出文件,然后加载为模块
import { join } from 'path';
import fs from 'fs'
import { pathToFileURL } from "node:url";
import path from 'path'
function scanDir(dir) {
const files = fs.readdirSync(dir);
const result = [];
// 扫描目录及子目录
for (const file of files) {
if (file.includes("index.js")) {
continue;
}
const filePath = join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
result.push(...scanDir(filePath));
} else {
if (!file.endsWith(".js")) {
continue;
}
result.push(filePath);
}
}
return result
}
export default async function loadModules(dir) {
const files = scanDir(dir);
const modules = {}
for (const file of files) {
try {
// 转换为 file:// URLWindows 必需)
const moduleUrl = pathToFileURL(file).href
const module = await import(moduleUrl)
// 如果模块有默认导出,优先使用
modules[file] = module.default || module
} catch (err) {
console.error(`加载模块 ${file} 失败:`, err)
}
}
return modules;
}
const modules = await loadModules('./dist/plugins');
for (const key in modules) {
console.log(key)
}

View File

@ -0,0 +1,59 @@
//@ts-ignore
import { HcClient } from "@huaweicloud/huaweicloud-sdk-core/HcClient";
export class HuaweiCcmClient {
//@ts-ignore
hcClient: HcClient;
//@ts-ignore
constructor(client: HcClient) {
this.hcClient = client;
}
/**
*/
importCertificate(req: {
name: string,
certificate: string,
private_key: string,
duplicate_check: boolean,
}) {
const options: any = {
method: "POST",
url: "/v3/scm/certificates/import",
pathParams: {},
queryParams: {},
contentType: "application/json",
headers: {
"Content-Type": "application/json"
},
/**
* name
* string
* 3~63, ,,线,线,
*
* certificate
* string
* ,certificate_chain,使\n\r\n
*
* certificate_chain
* string
* ,,certificate使\n\r\n
*
* private_key
* string
*
* ,使\n\r\n
*
* duplicate_check
*/
data: {
...req
}
};
// @ts-ignore
options["responseHeaders"] = ["X-Request-Id"];
return this.hcClient.sendRequest(options);
}
}

View File

@ -0,0 +1,61 @@
name: HuaweiUploadToCCM
title: 华为-上传证书至CCM
desc: 上传证书至华为云CCM
type: plugin
pluginType: deploy
author: certd
version: 1.0.0
icon: 'svg:icon-huawei'
group: huawei
default:
strategy:
runStrategy: 1,
input: # 插件的输入参数
cert:
title: 前置任务证书
helper: 请选择前置任务产生的证书 # 帮助说明
component:
name: output-selector # 输入组件名称
vModel: modelValue # 组件参数
from:
- ApplyCert
- ApplyCertLego
- ApplyCertUpload
required: true
certDomains:
title: 当前证书域名
component:
name: cert-domains-getter
mergeScript: |
return {
component:{
inputKey: ctx.compute(({form})=>{
return form.cert
}),
}
}
required: true
accessId:
title: Access授权
helper: xxxx的授权
component:
name: access-selector # 授权选择组件名称
type: aliyun # 授权类型
required: true
key1:
title: 输入示例1
required: false
key2:
title: 可选项
component:
name: a-select
vMode: value
options:
- value: "1"
label: 选项1
- value: "2"
label: 选项2
required: false
#output: # 输出参数,一般插件都不需要配置此项
# outputName:
#

View File

@ -0,0 +1,82 @@
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput, TaskOutput } from "@certd/pipeline";
import { HuaweiAccess } from "../../access/index.js";
import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert";
import { createCertDomainGetterInputDefine } from "@certd/plugin-lib";
import { resetLogConfigure } from "@certd/basic";
@IsTaskPlugin({
name: 'HauweiUploadToCCM',
title: '华为云-上传证书至CCM',
icon: 'svg:icon-huawei',
group: pluginGroups.huawei.key,
desc: '上传证书到华为云CCM',
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed,
},
},
})
export class HauweiUploadToCCM extends AbstractTaskPlugin {
@TaskInput({
title: "域名证书",
helper: "请选择前置任务输出的域名证书",
component: {
name: "output-selector",
from: [...CertApplyPluginNames]
},
required: true
})
cert!: CertInfo;
@TaskInput(createCertDomainGetterInputDefine({ props: { required: false } }))
certDomains!: string[];
@TaskInput({
title: "Access授权",
helper: "华为云授权AccessKeyId、AccessKeySecret",
component: {
name: "access-selector",
type: "huawei"
},
required: true
})
accessId!: string;
@TaskOutput({
title: '华为云CertId',
})
huaweiCertId!: string;
async execute(): Promise<void> {
this.logger.info("开始部署证书到华为云CCM");
const { client } = await this.getCcmClient();
const res = await client.importCertificate({
name: this.appendTimeSuffix("certd"),
certificate: this.cert.crt,
private_key: this.cert.key,
duplicate_check: false
});
this.huaweiCertId = res.certificate_id;
this.logger.info(`上传证书到华为云ccm完成,certificate_id:${this.huaweiCertId}`);
}
async getCcmClient() {
const access = await this.getAccess<HuaweiAccess>(this.accessId);
const { BasicCredentials } = await import("@huaweicloud/huaweicloud-sdk-core");
const { ClientBuilder } = await import("@huaweicloud/huaweicloud-sdk-core/ClientBuilder.js");
//@ts-ignore
const {HuaweiCcmClient} = await import("./ccm-client.js")
//恢复华为云把log4j的config改了的问题
resetLogConfigure();
const credentials = new BasicCredentials().withAk(access.accessKeyId).withSk(access.accessKeySecret);
const client = new ClientBuilder((hcClient) => {
return new HuaweiCcmClient(hcClient);
}).withCredential(credentials).withEndpoint("https://scm.cn-north-4.myhuaweicloud.com").build();
return {
client
};
}
}