From 0e8339c70190890d449099e1d26e5ed06ff135fb Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Tue, 3 Jun 2025 17:39:52 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E9=98=BF=E9=87=8C=E4=BA=91CLB=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E9=83=A8=E7=BD=B2=E5=88=B0=E6=89=A9=E5=B1=95=E5=9F=9F?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/deploy-to-slb/index.ts | 252 +++++++++++++++--- 1 file changed, 211 insertions(+), 41 deletions(-) diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-slb/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-slb/index.ts index 4c9bce66..b8cc60e2 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-slb/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-slb/index.ts @@ -1,13 +1,21 @@ -import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import { CertInfo } from '@certd/plugin-cert'; -import { AliyunAccess, AliyunClient, AliyunSslClient, CasCertInfo, createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from '@certd/plugin-lib'; -import { CertApplyPluginNames} from '@certd/plugin-cert'; +import {AbstractTaskPlugin, IsTaskPlugin, PageReq, pluginGroups, RunStrategy, TaskInput} from '@certd/pipeline'; +import {CertInfo} from '@certd/plugin-cert'; +import { + AliyunAccess, + AliyunClient, + AliyunSslClient, + CasCertInfo, + createCertDomainGetterInputDefine, + createRemoteSelectInputDefine +} from '@certd/plugin-lib'; +import {CertApplyPluginNames} from '@certd/plugin-cert'; + @IsTaskPlugin({ name: 'AliyunDeployCertToSLB', - title: '阿里云-部署至SLB(传统负载均衡)', + title: '阿里云-部署至CLB(传统负载均衡)', icon: 'svg:icon-aliyun', group: pluginGroups.aliyun.key, - desc: '部署证书到阿里云SLB(传统负载均衡)', + desc: '部署证书到阿里云CLB(传统负载均衡)', needPlus: false, default: { strategy: { @@ -27,9 +35,27 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { }) cert!: CertInfo | number; - @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) + @TaskInput(createCertDomainGetterInputDefine({props: {required: false}})) certDomains!: string[]; + + @TaskInput({ + title: '证书接入点', + helper: '不会选就保持默认即可', + value: 'cas.aliyuncs.com', + component: { + name: 'a-select', + options: [ + {value: 'cas.aliyuncs.com', label: '中国大陆'}, + {value: 'cas.ap-southeast-1.aliyuncs.com', label: '新加坡'}, + {value: 'cas.eu-central-1.aliyuncs.com', label: '德国(法兰克福)'}, + ], + }, + required: true, + }) + casEndpoint!: string; + + @TaskInput({ title: 'Access授权', helper: '阿里云授权AccessKeyId、AccessKeySecret', @@ -41,10 +67,11 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { }) accessId!: string; + + @TaskInput( createRemoteSelectInputDefine({ title: 'LB所在地区', - typeName: 'AliyunDeployCertToSLB', multi: false, action: AliyunDeployCertToSLB.prototype.onGetRegionList.name, watches: ['accessId'], @@ -56,7 +83,6 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { createRemoteSelectInputDefine({ title: '负载均衡列表', helper: '要部署证书的负载均衡ID', - typeName: 'AliyunDeployCertToSLB', action: AliyunDeployCertToSLB.prototype.onGetLoadBalanceList.name, watches: ['regionId'], }) @@ -67,33 +93,59 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { createRemoteSelectInputDefine({ title: '监听器列表', helper: '要部署证书的监听器列表', - typeName: 'AliyunDeployCertToSLB', action: AliyunDeployCertToSLB.prototype.onGetListenerList.name, watches: ['loadBalancers'], }) ) listeners!: string[]; - @TaskInput({ - title: '证书接入点', - helper: '不会选就保持默认即可', - value: 'cas.aliyuncs.com', - component: { - name: 'a-select', - options: [ - { value: 'cas.aliyuncs.com', label: '中国大陆' }, - { value: 'cas.ap-southeast-1.aliyuncs.com', label: '新加坡' }, - { value: 'cas.eu-central-1.aliyuncs.com', label: '德国(法兰克福)' }, - ], - }, - required: true, - }) - casEndpoint!: string; - async onInstance() {} + @TaskInput({ + title: "部署默认证书", + value: true, + component: { + name: "a-switch", + vModel: "checked" + } + } + ) + deployDefault!: boolean; + + @TaskInput({ + title: "部署扩展证书", + value: false, + component: { + name: "a-switch", + vModel: "checked" + } + } + ) + deployExtension!: boolean; + + + @TaskInput( + createRemoteSelectInputDefine({ + title: '扩展域名列表', + helper: '要部署扩展域名列表', + action: AliyunDeployCertToSLB.prototype.onGetExtensionDomainList.name, + watches: ['listeners','deployExtension'], + mergeScript:` + return { + show: ctx.compute(({form})=>{ + return form.deployExtension; + }) + } + ` + }) + ) + extensionDomains!: string[]; + + + async onInstance() { + } async getLBClient(access: AliyunAccess, region: string) { - const client = new AliyunClient({ logger: this.logger }); + const client = new AliyunClient({logger: this.logger}); const version = '2014-05-15'; await client.init({ accessKeyId: access.accessKeyId, @@ -106,30 +158,76 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { } async execute(): Promise { - this.logger.info(`开始部署证书到阿里云(slb)`); + this.logger.info(`开始部署证书到阿里云(clb)`); const access = await this.getAccess(this.accessId); const client = await this.getLBClient(access, this.regionId); const aliyunCert = await this.getAliyunCertId(access); const slbServerCertId = await this.uploadServerCert(client, aliyunCert); - for (const listener of this.listeners) { - const arr = listener.split('_'); - const loadBalanceId = arr[0]; - const port = arr[2]; - const params = { - RegionId: this.regionId, - LoadBalancerId: loadBalanceId, - ListenerPort: parseInt(port), - ServerCertificateId: slbServerCertId, - }; - const res = await client.request('SetLoadBalancerHTTPSListenerAttribute', params); - this.checkRet(res); - this.logger.info(`部署${listener}监听器证书成功`, JSON.stringify(res)); + if (this.deployDefault!==false) { + this.logger.info("部署监听器默认证书") + for (const listener of this.listeners) { + const {port, loadBalanceId} = this.resolveListenerKey(listener) + const params = { + RegionId: this.regionId, + LoadBalancerId: loadBalanceId, + ListenerPort: port, + ServerCertificateId: slbServerCertId, + }; + + const res = await client.request('SetLoadBalancerHTTPSListenerAttribute', params); + this.checkRet(res); + this.logger.info(`部署${listener}监听器证书成功`, JSON.stringify(res)); + } + } + + if (this.deployExtension) { + this.logger.info("部署监听器扩展域名证书") + + const clientV2 = this.getCLBClientV2(access); + for (const domainStr of this.extensionDomains) { + const {extensionDomainId} = this.resolveListenerKey(domainStr) + const res = await clientV2.doRequest({ + action: "SetDomainExtensionAttribute", + // 接口版本 + version: "2014-05-15", + data: { + query: { + RegionId: this.regionId, + DomainExtensionId: extensionDomainId, + ServerCertificateId: slbServerCertId + } + } + }) + this.logger.info(`部署扩展域名${extensionDomainId}证书成功`, JSON.stringify(res)) + } } this.logger.info('执行完成'); } + getCLBClientV2(access: AliyunAccess) { + return access.getClient("slb.aliyuncs.com") + } + + resolveListenerKey(listener: string) { + const arr = listener.split('_'); + const loadBalanceId = arr[0]; + const protocol = arr[1]; + const port = arr[2]; + let extensionDomainId = undefined; + if (arr.length > 3) { + extensionDomainId = arr[3]; + } + + return { + loadBalanceId, + port: parseInt(port), + extensionDomainId: extensionDomainId, + protocol: protocol + } + } + async uploadServerCert(client: any, aliyunCert: CasCertInfo) { const params = { RegionId: this.regionId, @@ -248,6 +346,78 @@ export class AliyunDeployCertToSLB extends AbstractTaskPlugin { }); } + async onGetExtensionDomainList(data: PageReq) { + if (!this.accessId) { + throw new Error('请先选择Access授权'); + } + if (!this.regionId) { + throw new Error('请先选择地区'); + } + if (!this.listeners && this.listeners.length == 0) { + throw new Error('请先选择监听器'); + } + const access = await this.getAccess(this.accessId); + + const allDomains: any[] = [] + for (const ls of this.listeners) { + const {port, loadBalanceId, protocol} = this.resolveListenerKey(ls) + const domains = await this.doGetExtensionDomainList({ + access, + loadBalancerId: loadBalanceId, + listenerPort: port, + listenerProtocol: protocol, + }); + allDomains.push(...domains) + } + + return this.ctx.utils.options.buildGroupOptions(allDomains, this.certDomains) + + } + + + async doGetExtensionDomainList(data: { + loadBalancerId: string, + listenerPort: number, + listenerProtocol: string, + access: AliyunAccess + }) { + const {loadBalancerId, listenerPort, listenerProtocol, access} = data; + const client = access.getClient("slb.aliyuncs.com") + + let queries = { + RegionId: this.regionId, + LoadBalancerId: loadBalancerId, + ListenerPort: listenerPort + }; + + const res = await client.doRequest({ + // 接口名称 + action: "DescribeDomainExtensions", + // 接口版本 + version: "2014-05-15", + data: { + query: queries, + } + }) + + this.checkRet(res); + const list = res?.DomainExtensions.DomainExtension; + if (!list || list.length === 0) { + return [] + } + + return list.map((i: any) => { + const value = `${loadBalancerId}_${listenerProtocol ?? "HTTPS"}_${listenerPort}_${i.DomainExtensionId}`; + const label = `${i.DomainExtensionId}<${i.Domain}>`; + return { + value: value, + label: label, + domain:i.Domain + }; + }); + } + + checkRet(ret: any) { if (ret.Code != null) { throw new Error(ret.Message);