diff --git a/packages/libs/lib-server/src/system/basic/service/plus-service.ts b/packages/libs/lib-server/src/system/basic/service/plus-service.ts index d480ef6f..2c09fc33 100644 --- a/packages/libs/lib-server/src/system/basic/service/plus-service.ts +++ b/packages/libs/lib-server/src/system/basic/service/plus-service.ts @@ -61,14 +61,36 @@ export class PlusService { const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo); const plusRequestService = await this.getPlusRequestService(); + return await verify({ - subjectId: installInfo.siteId, + subjectId: plusRequestService.subjectId, license: licenseInfo.license, plusRequestService: plusRequestService, bindUrl: installInfo?.bindUrl, }); } + async register() { + const plusRequestService = await this.getPlusRequestService(); + const licenseInfo: SysLicenseInfo = await this.sysSettingsService.getSetting(SysLicenseInfo); + const installInfo: SysInstallInfo = await this.sysSettingsService.getSetting(SysInstallInfo); + if (!licenseInfo?.license) { + //还没有license,注册一个 + const res = await plusRequestService.requestWithoutSign({ + url: '/activation/subject/register', + data: { + appKey: AppKey, + subjectId: installInfo.siteId, + installTime: installInfo.installTime, + }, + }); + if (res.license) { + await this.updateLicense(res.license); + logger.info('站点注册成功'); + } + } + } + async bindUrl(subjectId: string, url: string) { const plusRequestService = await this.getPlusRequestService(); return await plusRequestService.request({ diff --git a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-cdn/index.ts b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-cdn/index.ts index d1821c53..8ea4f304 100644 --- a/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-cdn/index.ts +++ b/packages/ui/certd-server/src/plugins/plugin-aliyun/plugin/deploy-to-cdn/index.ts @@ -1,6 +1,7 @@ import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from '@certd/pipeline'; -import dayjs from 'dayjs'; -import { AliyunAccess, AliyunClient } from "@certd/plugin-plus"; +import { AliyunAccess, AliyunClient, AliyunSslClient, createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from '@certd/plugin-plus'; +import { optionsUtils } from '@certd/basic/dist/utils/util.options.js'; + @IsTaskPlugin({ name: 'DeployCertToAliyunCDN', title: '部署证书至阿里云CDN', @@ -15,29 +16,35 @@ import { AliyunAccess, AliyunClient } from "@certd/plugin-plus"; }) export class DeployCertToAliyunCDN extends AbstractTaskPlugin { @TaskInput({ - title: 'CDN加速域名', - helper: '你在阿里云上配置的CDN加速域名,比如:certd.docmirror.cn', + 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, }) - domainName!: string; - - @TaskInput({ - title: '证书名称', - helper: '上传后将以此名称作为前缀备注', - }) - certName!: string; + endpoint!: string; @TaskInput({ title: '域名证书', helper: '请选择前置任务输出的域名证书', component: { name: 'output-selector', - from: ['CertApply', 'CertApplyLego'], + from: ['CertApply', 'CertApplyLego', 'uploadCertToAliyun'], }, required: true, }) cert!: string; + @TaskInput(createCertDomainGetterInputDefine({ props: { required: false } })) + certDomains!: string[]; + @TaskInput({ title: 'Access授权', helper: '阿里云授权AccessKeyId、AccessKeySecret', @@ -49,47 +56,84 @@ export class DeployCertToAliyunCDN extends AbstractTaskPlugin { }) accessId!: string; + @TaskInput( + createRemoteSelectInputDefine({ + title: 'CDN加速域名', + helper: '你在阿里云上配置的CDN加速域名,比如:certd.docmirror.cn', + typeName: 'DeployCertToAliyunCDN', + action: DeployCertToAliyunCDN.prototype.onGetDomainList.name, + watches: ['certDomains', 'accessId'], + required: true, + }) + ) + domainName!: string | string[]; + + @TaskInput({ + title: '证书名称', + helper: '上传后将以此名称作为前缀备注', + }) + certName!: string; + async onInstance() {} async execute(): Promise { this.logger.info('开始部署证书到阿里云cdn'); - const access = (await this.accessService.getById(this.accessId)) as AliyunAccess; + const access = await this.accessService.getById(this.accessId); + const sslClient = new AliyunSslClient({ + access, + logger: this.logger, + endpoint: this.endpoint || 'cas.aliyuncs.com', + }); + + let certId: any = this.cert; + if (typeof this.cert === 'object') { + certId = await sslClient.uploadCert({ + name: this.appendTimeSuffix('certd'), + cert: this.cert, + }); + } + const client = await this.getClient(access); - const params = await this.buildParams(); - await this.doRequest(client, params); + + if (typeof this.domainName === 'string') { + this.domainName = [this.domainName]; + } + for (const domain of this.domainName) { + await this.SetCdnDomainSSLCertificate(client, { + CertId: certId, + DomainName: domain, + }); + } + this.logger.info('部署完成'); } async getClient(access: AliyunAccess) { - const client = new AliyunClient({logger:this.logger}) + const client = new AliyunClient({ logger: this.logger }); await client.init({ accessKeyId: access.accessKeyId, accessKeySecret: access.accessKeySecret, endpoint: 'https://cdn.aliyuncs.com', apiVersion: '2018-05-10', - }) - return client + }); + return client; } - async buildParams() { - const CertName = (this.certName ?? 'certd') + '-' + dayjs().format('YYYYMMDDHHmmss'); - const cert: any = this.cert; - return { - DomainName: this.domainName, - SSLProtocol: 'on', - CertName: CertName, - CertType: 'upload', - SSLPub: cert.crt, - SSLPri: cert.key, - }; - } - - async doRequest(client: any, params: any) { + async SetCdnDomainSSLCertificate(client: any, params: { CertId: number; DomainName: string }) { const requestOption = { method: 'POST', + formatParams: false, }; - const ret: any = await client.request('SetCdnDomainSSLCertificate', params, requestOption); + + const ret: any = await client.request( + 'SetCdnDomainSSLCertificate', + { + SSLProtocol: 'on', + ...params, + }, + requestOption + ); this.checkRet(ret); - this.logger.info('设置cdn证书成功:', ret.RequestId); + this.logger.info(`设置CDN: ${params.DomainName} 证书成功:`, ret.RequestId); } checkRet(ret: any) { @@ -97,5 +141,39 @@ export class DeployCertToAliyunCDN extends AbstractTaskPlugin { throw new Error('执行失败:' + ret.Message); } } + + async onGetDomainList(data: any) { + if (!this.accessId) { + throw new Error('请选择Access授权'); + } + const access = await this.accessService.getById(this.accessId); + + const client = await this.getClient(access); + + const params = { + // 'DomainName': 'aaa', + PageSize: 500, + }; + + const requestOption = { + method: 'POST', + formatParams: false, + }; + + const res = await client.request('DescribeUserDomains', params, requestOption); + this.checkRet(res); + const pageData = res?.Domains?.PageData; + if (!pageData || pageData.length === 0) { + throw new Error('找不到CDN域名,您可以手动输入'); + } + const options = pageData.map((item: any) => { + return { + value: item.DomainName, + label: item.DomainName, + domain: item.DomainName, + }; + }); + return optionsUtils.buildGroupOptions(options, this.certDomains); + } } new DeployCertToAliyunCDN();