diff --git a/packages/core/basic/src/utils/util.request.ts b/packages/core/basic/src/utils/util.request.ts index ca0ed173d..2a509d5db 100644 --- a/packages/core/basic/src/utils/util.request.ts +++ b/packages/core/basic/src/utils/util.request.ts @@ -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; diff --git a/packages/ui/certd-server/package.json b/packages/ui/certd-server/package.json index 0b656564b..37e09f942 100644 --- a/packages/ui/certd-server/package.json +++ b/packages/ui/certd-server/package.json @@ -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", diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/access/huawei-access.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/access/huawei-access.ts index eeaaa5c62..439050a59 100644 --- a/packages/ui/certd-server/src/plugins/plugin-huawei/access/huawei-access.ts +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/access/huawei-access.ts @@ -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(); diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-elb/index.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-elb/index.ts new file mode 100644 index 000000000..859fbfcc3 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/deploy-to-elb/index.ts @@ -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 { + 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(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(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(); diff --git a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/index.ts index fdf6ded9d..596d341a8 100644 --- a/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-huawei/plugins/index.ts @@ -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' diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0eec0f826..5ab942e3d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,7 +49,7 @@ importers: packages/core/acme-client: dependencies: '@certd/basic': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../basic '@peculiar/x509': specifier: ^1.11.0 @@ -213,10 +213,10 @@ importers: packages/core/pipeline: dependencies: '@certd/basic': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../basic '@certd/plus-core': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../pro/plus-core dayjs: specifier: ^1.11.7 @@ -412,7 +412,7 @@ importers: packages/libs/lib-k8s: dependencies: '@certd/basic': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/basic '@kubernetes/client-node': specifier: 0.21.0 @@ -452,19 +452,19 @@ importers: packages/libs/lib-server: dependencies: '@certd/acme-client': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/pipeline '@certd/plugin-lib': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../plugins/plugin-lib '@certd/plus-core': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../pro/plus-core '@midwayjs/cache': specifier: 3.14.0 @@ -610,16 +610,16 @@ importers: packages/plugins/plugin-cert: dependencies: '@certd/acme-client': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/pipeline '@certd/plugin-lib': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../plugin-lib psl: specifier: ^1.9.0 @@ -683,16 +683,16 @@ importers: specifier: ^3.964.0 version: 3.964.0(aws-crt@1.26.2) '@certd/acme-client': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/pipeline '@certd/plus-core': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../pro/plus-core '@kubernetes/client-node': specifier: 0.21.0 @@ -783,16 +783,16 @@ importers: packages/pro/commercial-core: dependencies: '@certd/basic': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/basic '@certd/lib-server': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../libs/lib-server '@certd/pipeline': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/pipeline '@certd/plus-core': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../plus-core '@midwayjs/core': specifier: 3.20.11 @@ -865,16 +865,16 @@ importers: packages/pro/plugin-plus: dependencies: '@certd/basic': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/basic '@certd/pipeline': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/pipeline '@certd/plugin-lib': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../plugins/plugin-lib '@certd/plus-core': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../plus-core crypto-js: specifier: ^4.2.0 @@ -950,7 +950,7 @@ importers: packages/pro/plus-core: dependencies: '@certd/basic': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/basic dayjs: specifier: ^1.11.7 @@ -1246,10 +1246,10 @@ importers: version: 0.1.3(zod@3.24.4) devDependencies: '@certd/lib-iframe': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../libs/lib-iframe '@certd/pipeline': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/pipeline '@rollup/plugin-commonjs': specifier: ^25.0.7 @@ -1438,56 +1438,62 @@ importers: specifier: ^3.964.0 version: 3.964.0(aws-crt@1.26.2) '@certd/acme-client': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/acme-client '@certd/basic': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/basic '@certd/commercial-core': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../pro/commercial-core '@certd/cv4pve-api-javascript': specifier: ^8.4.2 version: 8.4.2 '@certd/jdcloud': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../libs/lib-jdcloud '@certd/lib-huawei': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../libs/lib-huawei '@certd/lib-k8s': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../libs/lib-k8s '@certd/lib-server': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../libs/lib-server '@certd/midway-flyway-js': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../libs/midway-flyway-js '@certd/pipeline': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../core/pipeline '@certd/plugin-cert': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../plugins/plugin-cert '@certd/plugin-lib': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../plugins/plugin-lib '@certd/plugin-plus': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../pro/plugin-plus '@certd/plus-core': - specifier: ^1.38.1 + specifier: ^1.38.3 version: link:../../pro/plus-core '@google-cloud/publicca': specifier: ^1.3.0 version: 1.3.0(encoding@0.1.13) '@huaweicloud/huaweicloud-sdk-cdn': - specifier: ^3.1.120 - version: 3.1.149 + specifier: ^3.1.185 + version: 3.1.185 '@huaweicloud/huaweicloud-sdk-core': - specifier: ^3.1.120 - version: 3.1.149 + specifier: ^3.1.185 + version: 3.1.185 + '@huaweicloud/huaweicloud-sdk-elb': + specifier: ^3.1.185 + version: 3.1.185 + '@huaweicloud/huaweicloud-sdk-iam': + specifier: ^3.1.185 + version: 3.1.185 '@koa/cors': specifier: ^5.0.0 version: 5.0.0 @@ -3407,11 +3413,17 @@ packages: '@httptoolkit/websocket-stream@6.0.1': resolution: {integrity: sha512-A0NOZI+Glp3Xgcz6Na7i7o09+/+xm2m0UCU8gdtM2nIv6/cjLmhMZMqehSpTlgbx9omtLmV8LVqOskPEyWnmZQ==} - '@huaweicloud/huaweicloud-sdk-cdn@3.1.149': - resolution: {integrity: sha512-orvtJRgJA/KKCmu6jLKxjMLhdxuKEOyeAakQCi3kwgWcbbeQUbRbr+2iMKLqXdM4lCrbOlfe06uqEtC/AG9ZRA==} + '@huaweicloud/huaweicloud-sdk-cdn@3.1.185': + resolution: {integrity: sha512-n4X0TDXpBFUbLFNkHbHbADETT4CG1Z8GgxDyQQrZHVMR3cUS2FnB8IJV1h34MToIB2D68u9ftOBrIjpnfgxIcg==} - '@huaweicloud/huaweicloud-sdk-core@3.1.149': - resolution: {integrity: sha512-5fY87f/z46L4jzB6YPpc3Qq6gt49C4J0//0AV7ELuOfmtstzbuS0O5UmBuTurTtAtsbPgW+08jn42N8Aqa2gGw==} + '@huaweicloud/huaweicloud-sdk-core@3.1.185': + resolution: {integrity: sha512-gSrJ5lFR0mqm5lQxTpSJ+ZIQTI5fzmM7a80ot4zvZ5Ll8T4HfcpcvEgDb/Q6VyZfPEApHo70CsreUe4PHGe8jQ==} + + '@huaweicloud/huaweicloud-sdk-elb@3.1.185': + resolution: {integrity: sha512-GKtB/cntti5coam7WBgjhNPzhpr9WdZz5EB2NZO5mFtdQ106ztQa8uIxt04PumFC71nQaC0LbAlAK7JrHVGjrw==} + + '@huaweicloud/huaweicloud-sdk-iam@3.1.185': + resolution: {integrity: sha512-uZFsGyFCVYET5RxBW6nwM53ooKmggdkZAOFu8ZHvuVl3chOxPAt35jrEpznvUk7iApIn5XSC62t4DAKIslPFcg==} '@humanwhocodes/config-array@0.11.14': resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} @@ -15137,14 +15149,14 @@ snapshots: - bufferutil - utf-8-validate - '@huaweicloud/huaweicloud-sdk-cdn@3.1.149': + '@huaweicloud/huaweicloud-sdk-cdn@3.1.185': dependencies: - '@huaweicloud/huaweicloud-sdk-core': 3.1.149 + '@huaweicloud/huaweicloud-sdk-core': 3.1.185 transitivePeerDependencies: - debug - supports-color - '@huaweicloud/huaweicloud-sdk-core@3.1.149': + '@huaweicloud/huaweicloud-sdk-core@3.1.185': dependencies: axios: 1.9.0(debug@4.4.3) form-data: 4.0.2 @@ -15159,6 +15171,20 @@ snapshots: - debug - supports-color + '@huaweicloud/huaweicloud-sdk-elb@3.1.185': + dependencies: + '@huaweicloud/huaweicloud-sdk-core': 3.1.185 + transitivePeerDependencies: + - debug + - supports-color + + '@huaweicloud/huaweicloud-sdk-iam@3.1.185': + dependencies: + '@huaweicloud/huaweicloud-sdk-core': 3.1.185 + transitivePeerDependencies: + - debug + - supports-color + '@humanwhocodes/config-array@0.11.14': dependencies: '@humanwhocodes/object-schema': 2.0.3 @@ -19945,13 +19971,13 @@ snapshots: resolve: 1.22.10 semver: 6.3.1 - eslint-plugin-prettier@3.4.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@7.32.0)(prettier@2.8.8): + eslint-plugin-prettier@3.4.1(eslint-config-prettier@8.10.0(eslint@7.32.0))(eslint@7.32.0)(prettier@2.8.8): dependencies: eslint: 7.32.0 prettier: 2.8.8 prettier-linter-helpers: 1.0.0 optionalDependencies: - eslint-config-prettier: 8.10.0(eslint@8.57.0) + eslint-config-prettier: 8.10.0(eslint@7.32.0) eslint-plugin-prettier@4.2.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@8.57.0)(prettier@2.8.8): dependencies: @@ -22351,7 +22377,7 @@ snapshots: eslint: 7.32.0 eslint-config-prettier: 8.10.0(eslint@7.32.0) eslint-plugin-node: 11.1.0(eslint@7.32.0) - eslint-plugin-prettier: 3.4.1(eslint-config-prettier@8.10.0(eslint@8.57.0))(eslint@7.32.0)(prettier@2.8.8) + eslint-plugin-prettier: 3.4.1(eslint-config-prettier@8.10.0(eslint@7.32.0))(eslint@7.32.0)(prettier@2.8.8) execa: 5.1.1 inquirer: 7.3.3 json5: 2.2.3