From abea80e3ab9b1672aebe1c5d5e856693b29931a8 Mon Sep 17 00:00:00 2001 From: xiaojunnuo Date: Mon, 21 Apr 2025 23:39:33 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E6=B7=BB=E5=8A=A0=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=E8=AF=81=E4=B9=A6=E8=87=B3=E7=81=AB=E5=B1=B1=20Live?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 VolcengineDeployToLive 插件,用于将证书部署到火山引擎视频直播 - 新增 VolcengineDeployToVOD 插件,用于将证书部署到火山引擎视频点播 - 更新 ve-client.ts,增加对 Live 和 VOD 服务的支持 --- .../plugin-volcengine/plugins/index.ts | 1 + .../plugins/plugin-deploy-to-live.ts | 144 +++++++++++++ .../plugins/plugin-deploy-to-vod.ts | 199 ++++++++++++++++++ .../plugins/plugin-volcengine/ve-client.ts | 31 ++- 4 files changed, 373 insertions(+), 2 deletions(-) create mode 100644 packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-live.ts create mode 100644 packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vod.ts diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/index.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/index.ts index f1fe8c1e..1f6adb71 100644 --- a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/index.ts @@ -2,3 +2,4 @@ export * from './plugin-deploy-to-cdn.js' export * from './plugin-deploy-to-clb.js' export * from './plugin-upload-to-cert-center.js' export * from './plugin-deploy-to-alb.js' +export * from './plugin-deploy-to-live.js' diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-live.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-live.ts new file mode 100644 index 00000000..908e44f0 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-live.ts @@ -0,0 +1,144 @@ +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; +import { VolcengineAccess } from "../access.js"; +import { VolcengineClient } from "../ve-client.js"; + +@IsTaskPlugin({ + name: "VolcengineDeployToLive", + title: "火山引擎-部署证书至Live", + icon: "svg:icon-volcengine", + group: pluginGroups.volcengine.key, + desc: "部署至火山引擎视频直播", + default: { + strategy: { + runStrategy: RunStrategy.SkipWhenSucceed + } + } +}) +export class VolcengineDeployToLive 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: "volcengine" + }, + required: true + }) + accessId!: string; + + + @TaskInput( + createRemoteSelectInputDefine({ + title: "直播域名", + helper: "选择要部署证书的直播域名", + action: VolcengineDeployToLive.prototype.onGetDomainList.name, + watches: ["certDomains", "accessId"], + required: true + }) + ) + domainList!: string | string[]; + + + async onInstance() { + } + + async execute(): Promise { + this.logger.info("开始部署证书到火山引擎视频直播"); + const service = await this.getLiveService(); + let certId = await this.uploadCert(service); + + + for (const item of this.domainList) { + this.logger.info(`开始部署直播域名${item}证书`); + await service.request({ + action: "BindCert", + body: { + Domain: item, + HTTPS: true, + ChainID: certId + } + }); + this.logger.info(`部署直播域名${item}证书成功`); + } + + this.logger.info("部署完成"); + } + + + private async uploadCert(liveService: any) { + const res = await liveService.request({ + action: "CreateCert", + body: { + Rsa: { + Pubkey: this.cert.crt, + Prikey: this.cert.key + }, + UseWay: "https" + } + }); + + const certId = res.Result.ChainID; + this.logger.info("证书上传成功", certId); + return certId; + } + + + private async getLiveService() { + const access = await this.getAccess(this.accessId); + + const client = new VolcengineClient({ + logger: this.logger, + access, + http: this.http + }); + + return await client.getLiveService(); + } + + async onGetDomainList(data: any) { + if (!this.accessId) { + throw new Error("请选择Access授权"); + } + const service = await this.getLiveService(); + + const res = await service.request({ + action: "ListDomainDetail", + body: { + "PageNum": 1, + "PageSize": 100 + } + }); + + const list = res.Result?.DomainList; + if (!list || list.length === 0) { + throw new Error("找不到直播域名,您也可以手动输入域名"); + } + const options = list.map((item: any) => { + return { + value: item.Domain, + label: `${item.Domain}<${item.Type}>`, + domain: item.Domain + }; + }); + return this.ctx.utils.options.buildGroupOptions(options, this.certDomains); + } +} + +new VolcengineDeployToLive(); diff --git a/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vod.ts b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vod.ts new file mode 100644 index 00000000..6425c8d7 --- /dev/null +++ b/packages/ui/certd-server/src/plugins/plugin-volcengine/plugins/plugin-deploy-to-vod.ts @@ -0,0 +1,199 @@ +import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline"; +import { createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib"; +import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert"; +import { VolcengineAccess } from "../access.js"; +import { VolcengineClient } from "../ve-client.js"; + +@IsTaskPlugin({ + name: "VolcengineDeployToVOD", + title: "火山引擎-部署证书至VOD", + icon: "svg:icon-volcengine", + group: pluginGroups.volcengine.key, + desc: "部署至火山引擎视频点播(暂不可用)", + deprecated:"暂时缺少部署ssl接口", + default: { + strategy: { + runStrategy: RunStrategy.SkipWhenSucceed + } + } +}) +export class VolcengineDeployToVOD extends AbstractTaskPlugin { + @TaskInput({ + title: "域名证书", + helper: "请选择前置任务输出的域名证书", + component: { + name: "output-selector", + from: [...CertApplyPluginNames, "VolcengineUploadToCertCenter"] + }, + required: true + }) + cert!: CertInfo | string; + + @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) + certDomains!: string[]; + + + @TaskInput({ + title: "Access授权", + helper: "火山引擎AccessKeyId、AccessKeySecret", + component: { + name: "access-selector", + type: "volcengine" + }, + required: true + }) + accessId!: string; + + + @TaskInput( + // createRemoteSelectInputDefine({ + // title: "空间名称", + // helper: "选择要部署证书的监听器\n需要在监听器中选择证书中心,进行跨服务访问授权", + // action: VolcengineDeployToVOD.prototype.onGetSpaceList.name, + // watches: ["certDomains", "accessId", "regionId"], + // required: true + // }) + { + title: "空间名称", + required: true + } + ) + spaceName!: string; + + @TaskInput( + createRemoteSelectInputDefine({ + title: "点播域名", + helper: "选择要部署证书的点播域名\n需要先在域名管理页面进行证书中心访问授权(即点击去配置SSL证书)", + action: VolcengineDeployToVOD.prototype.onGetDomainList.name, + watches: ["certDomains", "accessId", "spaceName"], + required: true + }) + ) + domainList!: string | string[]; + + + async onInstance() { + } + + async execute(): Promise { + this.logger.info("开始部署证书到火山引擎VOD"); + const access = await this.getAccess(this.accessId); + let certId = await this.uploadOrGetCertId(access); + + const service = await this.getVodService(); + for (const item of this.domainList) { + this.logger.info(`开始部署点播域名${item}证书`); + await service.request({ + action: "ModifyListenerAttributes", + query: { + ListenerId: item, + CertificateSource: "cert_center", + CertCenterCertificateId: certId + } + }); + this.logger.info(`部署点播域名${item}证书成功`); + } + + this.logger.info("部署完成"); + } + + + private async uploadOrGetCertId(access: VolcengineAccess) { + const certService = await this.getCertService(access); + let certId = this.cert; + if (typeof certId !== "string") { + const certInfo = this.cert as CertInfo; + this.logger.info(`开始上传证书`); + certId = await certService.ImportCertificate({ + certName: this.appendTimeSuffix("certd"), + cert: certInfo + }); + this.logger.info(`上传证书成功:${certId}`); + } else { + this.logger.info(`使用已有证书ID:${certId}`); + } + return certId; + } + + private async getCertService(access: VolcengineAccess) { + const client = new VolcengineClient({ + logger: this.logger, + access, + http: this.http + }); + + return await client.getCertCenterService(); + } + + + private async getVodService(req?: { version?: string }) { + const access = await this.getAccess(this.accessId); + + const client = new VolcengineClient({ + logger: this.logger, + access, + http: this.http + }); + + return await client.getVodService(req); + } + + // async onGetSpaceList(data: any) { + // if (!this.accessId) { + // throw new Error("请选择Access授权"); + // } + // const service = await this.getVodService(); + // + // const res = await service.request({ + // action: "ListSpace", + // method: "GET", + // query: { + // PageSize: 100, + // }, + // }); + // + // const list = res.Result; + // if (!list || list.length === 0) { + // throw new Error("找不到空间,您可以手动填写"); + // } + // return list.map((item: any) => { + // return { + // value: item.SpaceName, + // label: `${item.SpaceName}` + // }; + // }); + // } + + async onGetDomainList(data: any) { + if (!this.accessId) { + throw new Error("请选择Access授权"); + } + const service = await this.getVodService(); + + const res = await service.request({ + action: "ListDomain", + body: { + SpaceName: this.spaceName, + Offset: 100 + } + }); + + const instances = res.Result?.PlayInstanceInfo?.ByteInstances; + if (!instances || instances.length === 0) { + throw new Error("找不到点播域名,您也可以手动输入点播域名"); + } + const list = [] + for (const item of instances) { + for (const domain of item.Domains) { + list.push({ + value: item.Domain, + label: item.Domain, + domain: domain.Domain + }); + } + } + return this.ctx.utils.options.buildGroupOptions(list, this.certDomains); + } +} + +new VolcengineDeployToVOD(); 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 445340df..adcf707a 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 @@ -28,7 +28,7 @@ export class VolcengineClient { service.ImportCertificate = async (body: { certName: string, cert: any }) => { const { certName, cert } = body; - const res = await service.request({ + const res = await service.request({ action: "ImportCertificate", method: "POST", body: { @@ -40,7 +40,7 @@ export class VolcengineClient { } } }); - return res.Result.InstanceId || res.Result.RepeatId + return res.Result.InstanceId || res.Result.RepeatId; }; return service; } @@ -59,6 +59,33 @@ export class VolcengineClient { return service; } + async getLiveService() { + const CommonService = await this.getServiceCls(); + + const service = new CommonService({ + serviceName: "live", + defaultVersion: "2023-01-01" + }); + service.setAccessKeyId(this.opts.access.accessKeyId); + service.setSecretKey(this.opts.access.secretAccessKey); + service.setRegion("cn-north-1"); + + return service; + } + + async getVodService(opts?: { version?: string }) { + const CommonService = await this.getServiceCls(); + + const service = new CommonService({ + serviceName: "vod", + defaultVersion: opts?.version || "2021-01-01" + }); + service.setAccessKeyId(this.opts.access.accessKeyId); + service.setSecretKey(this.opts.access.secretAccessKey); + + return service; + } + async getAlbService(opts: { region?: string }) { const CommonService = await this.getServiceCls();