Merge branch 'v2-dev' of https://github.com/certd/certd into v2-dev

This commit is contained in:
xiaojunnuo
2026-01-30 17:15:39 +08:00
6 changed files with 284 additions and 76 deletions

View File

@@ -177,39 +177,40 @@ export function createAxiosService({ logger }: { logger: ILogger }) {
},
(error: any) => {
const status = error.response?.status;
let message = "";
switch (status) {
case 400:
error.message = "请求错误";
message = "请求错误";
break;
case 401:
error.message = "认证/登录失败";
message = "认证/登录失败";
break;
case 403:
error.message = "拒绝访问";
message = "拒绝访问";
break;
case 404:
error.message = `请求地址出错`;
message = `请求地址出错`;
break;
case 408:
error.message = "请求超时";
message = "请求超时";
break;
case 500:
error.message = "服务器内部错误";
message = "服务器内部错误";
break;
case 501:
error.message = "服务未实现";
message = "服务未实现";
break;
case 502:
error.message = "网关错误";
message = "网关错误";
break;
case 503:
error.message = "服务不可用";
message = "服务不可用";
break;
case 504:
error.message = "网关超时";
message = "网关超时";
break;
case 505:
error.message = "HTTP版本不受支持";
message = "HTTP版本不受支持";
break;
case 302:
//重定向
@@ -217,9 +218,12 @@ export function createAxiosService({ logger }: { logger: ILogger }) {
default:
break;
}
if (status) {
message += ` [${status}] `;
}
const errorCode = error.code;
let errorMessage = null;
let errorMessage = "";
if (errorCode === "ECONNABORTED") {
errorMessage = "请求连接终止";
} else if (errorCode === "ETIMEDOUT") {
@@ -231,14 +235,17 @@ export function createAxiosService({ logger }: { logger: ILogger }) {
} else if (errorCode === "ENOTFOUND") {
errorMessage = "请求地址不存在";
}
if (errorMessage) {
if (error.message) {
errorMessage += `,${error.message}`;
}
error.message = errorMessage;
if (errorCode) {
errorMessage += ` [${errorCode}] `;
}
logger.error(`请求出错:${errorMessage} status:${error.response?.status || error.code},statusText:${error.response?.statusText || error.code},url:${error.config?.url},method:${error.config?.method}`);
if (message) {
errorMessage += `,${message}`;
}
if (error.message) {
errorMessage += `(${error.message})`;
}
error.message = errorMessage;
logger.error(`请求出错:${errorMessage} status:${status},statusText:${error.response?.statusText || error.code},url:${error.config?.url},method:${error.config?.method}`);
logger.error("返回数据:", JSON.stringify(error.response?.data));
if (error.response?.data) {
const message = error.response.data.message || error.response.data.msg || error.response.data.error;

View File

@@ -63,8 +63,10 @@
"@certd/plugin-plus": "^1.38.3",
"@certd/plus-core": "^1.38.3",
"@google-cloud/publicca": "^1.3.0",
"@huaweicloud/huaweicloud-sdk-cdn": "^3.1.120",
"@huaweicloud/huaweicloud-sdk-core": "^3.1.120",
"@huaweicloud/huaweicloud-sdk-cdn": "^3.1.185",
"@huaweicloud/huaweicloud-sdk-core": "^3.1.185",
"@huaweicloud/huaweicloud-sdk-elb": "^3.1.185",
"@huaweicloud/huaweicloud-sdk-iam": "^3.1.185",
"@koa/cors": "^5.0.0",
"@midwayjs/bootstrap": "3.20.11",
"@midwayjs/cache": "3.14.0",

View File

@@ -1,3 +1,4 @@
import { resetLogConfigure } from '@certd/basic';
import { IsAccess, AccessInput, BaseAccess } from '@certd/pipeline';
@IsAccess({
@@ -26,6 +27,26 @@ export class HuaweiAccess extends BaseAccess {
encrypt: true,
})
accessKeySecret = '';
async getProjectList() {
const endpoint = "https://iam.cn-north-4.myhuaweicloud.com";
const { BasicCredentials } = await import('@huaweicloud/huaweicloud-sdk-core');
const iam = await import('@huaweicloud/huaweicloud-sdk-iam/v3/public-api.js');
//恢复华为云把log4j的config改了的问题
resetLogConfigure();
const credentials: any = new BasicCredentials().withAk(this.accessKeyId).withSk(this.accessKeySecret)
const client = iam.IamClient.newBuilder()
.withCredential(credentials)
.withEndpoint(endpoint)
.build();
const request = new iam.KeystoneListAuthProjectsRequest();
const result = await client.keystoneListAuthProjects(request);
return result.projects;
}
}
new HuaweiAccess();

View File

@@ -0,0 +1,151 @@
import { AbstractTaskPlugin, IsTaskPlugin, PageSearch, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline';
import { HuaweiAccess } from '../../access/index.js';
import { CertInfo } from '@certd/plugin-cert';
import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from '@certd/plugin-lib';
import { resetLogConfigure } from '@certd/basic';
import { CertApplyPluginNames } from '@certd/plugin-cert';
@IsTaskPlugin({
name: 'HauweiDeployCertToELB',
title: '华为云-部署证书至ELB负载均衡',
icon: 'svg:icon-huawei',
group: pluginGroups.huawei.key,
desc: '',
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed,
},
},
})
export class HauweiDeployCertToELB extends AbstractTaskPlugin {
@TaskInput({
title: '域名证书',
helper: '请选择前置任务输出的域名证书\n如果你选择使用ccm证书ID则需要在[域名管理页面右上角开启SCM授权](https://console.huaweicloud.com/cdn/#/cdn/domain)',
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;
@TaskInput(
createRemoteSelectInputDefine({
title: '项目ID',
helper: '请选择项目',
typeName: 'HauweiDeployCertToELB',
action: HauweiDeployCertToELB.prototype.onGetProjectList.name,
multi:false
})
)
projectId!: string;
@TaskInput(
createRemoteSelectInputDefine({
title: 'ELB已有证书',
helper: '请选择域名或输入域名',
typeName: 'HauweiDeployCertToELB',
action: HauweiDeployCertToELB.prototype.onGetCertList.name,
search: true,
})
)
certIds!: string[];
async execute(): Promise<void> {
if (!this.cert) {
throw new Error('域名证书不能为空');
}
this.logger.info('开始部署证书到华为云ELB');
const { elb, client } = await this.getElbClient();
for (const certId of this.certIds) {
this.logger.info('开始更新ELB证书证书ID' + certId);
let request = new elb.UpdateCertificateRequest(certId);
const certificate = new elb.UpdateCertificateOption()
.withCertificate(this.cert.crt)
.withPrivateKey(this.cert.key);
const body = new elb.UpdateCertificateRequestBody()
.withCertificate(certificate);
request.withBody(body);
await client.updateCertificate(request);
this.logger.info('更新ELB证书完成证书ID' + certId );
await this.ctx.utils.sleep(2000);
}
this.logger.info('更新ELB证书完成');
}
async onGetProjectList() {
const access = await this.getAccess<HuaweiAccess>(this.accessId);
const projects = await access.getProjectList();
return projects.map(project => {
return {
value: project.id+"_"+project.name,
label: `${project.name}(${project.id})`,
};
});
}
async getElbClient() {
if (!this.projectId) {
throw new Error('项目ID不能为空');
}
const access = await this.getAccess<HuaweiAccess>(this.accessId);
const { BasicCredentials } = await import('@huaweicloud/huaweicloud-sdk-core');
const elb = await import('@huaweicloud/huaweicloud-sdk-elb/v3/public-api.js');
//恢复华为云把log4j的config改了的问题
resetLogConfigure();
const projectArr = this.projectId.split("_");
const projectId = projectArr[0];
const region = projectArr[1];
const credentials: any = new BasicCredentials().withAk(access.accessKeyId).withSk(access.accessKeySecret).withProjectId(projectId);
const client = elb.ElbClient.newBuilder().withCredential(credentials).withEndpoint('https://elb.'+region+'.myhuaweicloud.com').build();
return {
client,
elb,
};
}
async onGetCertList(data: PageSearch) {
const { client, elb } = await this.getElbClient();
const request = new elb.ListCertificatesRequest();
request.limit = 1000;
if (data.searchKey) {
request.withDomain([data.searchKey]);
}
const result = await client.listCertificates(request);
if (!result || !result.certificates || result.certificates.length === 0) {
throw new Error('未找到ELB证书您可以手动输入');
}
const certs = result.certificates.map(cert => {
return {
value: cert.id,
//@ts-ignore
label: cert.id + '(' + cert.common_name + ')',
domain: cert.domain.split(','),
};
});
return this.ctx.utils.options.buildGroupOptions(certs, this.certDomains);
}
}
new HauweiDeployCertToELB();

View File

@@ -1,3 +1,4 @@
export * from './deploy-to-cdn/index.js'
export * from './upload-to-ccm/index.js'
export * from './deploy-to-obs/index.js'
export * from './deploy-to-elb/index.js'