mirror of https://github.com/certd/certd
perf: 支持上传证书到华为云CCM
parent
75c4f9dea8
commit
cfd3b66be9
|
@ -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:// URL(Windows 必需)
|
||||||
|
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)
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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:
|
||||||
|
#
|
|
@ -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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue