From ffd2e8149e3a06bf3eec456ff85dbed793af9e90 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Sat, 21 Mar 2026 23:51:30 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E7=81=AB=E5=B1=B1=E5=BC=95=E6=93=8E?= =?UTF-8?q?=E9=83=A8=E7=BD=B2alb=E8=AF=81=E4=B9=A6=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=83=A8=E7=BD=B2=E6=89=A9=E5=B1=95=E8=AF=81?= =?UTF-8?q?=E4=B9=A6=E4=BB=A5=E5=8F=8A=E5=88=A0=E9=99=A4=E5=B7=B2=E8=BF=87?= =?UTF-8?q?=E6=9C=9F=E6=89=A9=E5=B1=95=E8=AF=81=E4=B9=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugins/plugin-deploy-to-alb.ts | 165 +++++++++++++++++- .../plugins/plugin-volcengine/ve-client.ts | 11 ++ 2 files changed, 167 insertions(+), 9 deletions(-) diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-alb.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-alb.ts index 5fdc0136b..0329d71b5 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-alb.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-alb.ts @@ -3,6 +3,7 @@ import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; import { VolcengineAccess } from "../access.js"; import { VolcengineClient } from "../ve-client.js"; +import dayjs from "dayjs"; @IsTaskPlugin({ name: "VolcengineDeployToALB", @@ -32,6 +33,7 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { certDomains!: string[]; + @TaskInput({ title: "Access授权", helper: "火山引擎AccessKeyId、AccessKeySecret", @@ -126,6 +128,22 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { listenerList!: string | string[]; + @TaskInput({ + title: "证书部署类型", + helper: "选择部署默认证书还是扩展证书", + component: { + name: "a-select", + options: [ + { label: "默认证书", value: "default" }, + { label: "扩展证书", value: "extension" } + ] + }, + value: "default", + required: true + }) + certType!: string; + + async onInstance() { } @@ -149,20 +167,101 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { const service = await this.getAlbService(); for (const listener of this.listenerList) { this.logger.info(`开始部署监听器${listener}证书`); - await service.request({ - action: "ModifyListenerAttributes", - query: { - ListenerId: listener, - CertificateSource: "cert_center", - CertCenterCertificateId: certId - } - }); - this.logger.info(`部署监听器${listener}证书成功`); + if (this.certType === "default") { + // 部署默认证书 + const res = await service.request({ + action: "ModifyListenerAttributes", + query: { + ListenerId: listener, + CertificateSource: "cert_center", + CertCenterCertificateId: certId + } + }); + this.logger.info(`部署监听器${listener}默认证书成功,res:${JSON.stringify(res)}`); + } else { + // 部署扩展证书 + await this.deployExtensionCertificate(service, listener, certId as string); + } + await this.ctx.utils.sleep(5000); } this.logger.info("部署完成"); } + private async deployExtensionCertificate(service: any, listenerId: string, certId: string) { + // 获取监听器当前的扩展证书列表 + const domainExtensions = await this.getListenerDomainExtensions(service, listenerId); + + // 删除过期的扩展证书 + try { + await this.deleteExpiredExtensions(service, listenerId, domainExtensions); + } catch (error) { + this.logger.error(`删除过期扩展证书失败:${error.message ||error}`); + } + + // 新增扩展证书 + const query: any = { + ListenerId: listenerId, + "DomainExtensions.1.Action": "create", + "DomainExtensions.1.CertificateSource": "cert_center", + "DomainExtensions.1.CertCenterCertificateId": certId + }; + + // 如果有证书域名信息,添加到扩展证书中 + if (this.certDomains && this.certDomains.length > 0) { + query["DomainExtensions.1.Domain"] = this.certDomains[0]; + } + + await service.request({ + action: "ModifyListenerAttributes", + query: query + }); + this.logger.info(`部署监听器${listenerId}扩展证书成功`); + } + + private async getListenerDomainExtensions(service: any, listenerId: string): Promise { + const res = await service.request({ + action: "DescribeListenerAttributes", + method: "GET", + query: { + ListenerId: listenerId + } + }); + + return res.Result.DomainExtensions || []; + } + + private async deleteExpiredExtensions(service: any, listenerId: string, domainExtensions: any[]) { + const expiredExtensions = []; + for (const ext of domainExtensions) { + if (!await this.isCertificateExpired(ext)) { + expiredExtensions.push(ext); + } + } + if (expiredExtensions.length === 0) { + this.logger.info(`没有过期的扩展证书,跳过删除`); + return; + } + + const query: any = { + ListenerId: listenerId + }; + expiredExtensions.forEach((ext, index) => { + const idx = index + 1; + query[`DomainExtensions.${idx}.Action`] = "delete"; + query[`DomainExtensions.${idx}.DomainExtensionId`] = ext.DomainExtensionId; + }); + + this.logger.info(`准备删除过期扩展证书,数量:${expiredExtensions.length}个,query:${JSON.stringify(query)}`); + + await service.request({ + action: "ModifyListenerAttributes", + query: query + }); + this.logger.info(`删除${expiredExtensions.length}个过期扩展证书成功`); + await this.ctx.utils.sleep(5000); + } + private async getCertService(access: VolcengineAccess) { const client = new VolcengineClient({ @@ -189,6 +288,54 @@ export class VolcengineDeployToALB extends AbstractTaskPlugin { return service; } + private async isCertificateExpired(extension: any): Promise { + try { + let certificateId: string; + + // 根据证书来源获取证书ID + if (extension.CertificateSource === "cert_center") { + certificateId = extension.CertCenterCertificateId; + } else if (extension.CertificateSource === "alb") { + this.logger.warn(`ALB证书不支持过期检查,跳过`); + return false; + } else if (extension.CertificateSource === "pca_leaf") { + this.logger.warn(`PCA Leaf证书不支持过期检查,跳过`); + return false; + } else { + this.logger.warn(`未知的证书来源: ${extension.CertificateSource},跳过`); + return false; + } + + if (!certificateId) { + this.logger.warn(`证书ID为空,跳过`); + return false; + } + + // 获取证书服务 + const access = await this.getAccess(this.accessId); + const certService = await this.getCertService(access); + + // 获取证书详情 + const certDetail = await certService.GetCertificateDetail(certificateId); + + // 判断证书是否过期 + if (certDetail.NotAfter) { + const expireTime = dayjs(certDetail.NotAfter); + const now = dayjs(); + const isExpired = expireTime.isBefore(now); + if (isExpired) { + this.logger.info(`证书 ${certificateId} 已过期,过期时间: ${expireTime.toISOString()}`); + } + return isExpired; + } + + return false; + } catch (error) { + this.logger.error(`检查证书是否过期失败: ${error.message || error}`); + return false; + } + } + async onGetListenerList(data: any) { if (!this.accessId) { throw new Error("请选择Access授权"); diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts index c1eb2a150..3ee02041d 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/ve-client.ts @@ -42,6 +42,17 @@ export class VolcengineClient { }); return res.Result.InstanceId || res.Result.RepeatId; }; + + service.GetCertificateDetail = async (certificateId: string) => { + const res = await service.request({ + action: "CertificateGetInstance", + method: "POST", + body: { + InstanceId: certificateId + } + }); + return res.Result; + }; return service; }