@certd/plugin-plus 1.24.3 → 1.24.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/bundle.cjs +1 -1
- package/dist/bundle.mjs +1 -1
- package/dist/d/aliyun/plugins/deploy-to-dcdn/index.d.ts +23 -0
- package/dist/d/baota/lib/client.d.ts +3 -3
- package/dist/d/index.d.ts +1 -0
- package/dist/d/synology/access.d.ts +10 -0
- package/dist/d/synology/client.d.ts +30 -0
- package/dist/d/synology/index.d.ts +3 -0
- package/dist/d/synology/plugins/index.d.ts +1 -0
- package/dist/d/synology/plugins/plugin-deploy-to-panel.d.ts +11 -0
- package/package.json +8 -6
- package/rollup.config.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.24.4](https://github.com/certd/certd/compare/v1.24.3...v1.24.4) (2024-09-09)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @certd/plugin-plus
|
|
9
|
+
|
|
6
10
|
## [1.24.3](https://github.com/certd/certd/compare/v1.24.2...v1.24.3) (2024-09-06)
|
|
7
11
|
|
|
8
12
|
**Note:** Version bump only for package @certd/plugin-plus
|
package/dist/bundle.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e=require("@certd/pipeline"),t=require("@certd/plugin-cert"),s=require("node:crypto"),o=require("node:path"),n=require("https-proxy-agent");function r(){if(!e.isPlus())throw new Error("此插件仅供专业版中使用")}class i extends e.AbstractTaskPlugin{setCtx(e){super.setCtx(e),r()}}function a(e,t,s,o){var n,r=arguments.length,i=r<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,s):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,s,o);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(i=(r<3?n(i):r>3?n(t,s,i):n(t,s))||i);return r>3&&i&&Object.defineProperty(t,s,i),i}function c(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}"function"==typeof SuppressedError&&SuppressedError;class p{access;http;constructor(e,t){this.access=e,this.http=t}getRequestToken(){const e=(new Date).getTime(),t=e+this.getMd5(this.access.apiSecret);return{request_token:this.getMd5(t),request_time:e}}getMd5(e){return s.createHash("md5").update(e).digest("hex")}async doRequest(e,t,s){const o=this.getRequestToken();console.log("token",o);const n={...o,...s};let r=`${this.access.panelUrl}${e}`;t&&(r=`${r}?action=${t}`);const i=await this.http.request({url:r,method:"post",headers:{"Content-Type":"application/x-www-form-urlencoded"},data:n});if(!i.status)throw new Error(i.msg);return i}}exports.BaotaDeployPanelCertPlugin=class extends i{cert;accessId;async onInstance(){}async execute(){const{cert:e,accessId:s}=this,o=new t.CertReader(e),n=await this.accessService.getById(s),r=this.ctx.http,i=new p(n,r),a=await i.doRequest("/config","SavePanelSSL",{privateKey:o.key,certPem:o.crt});this.logger.info(a?.msg)}},a([e.TaskInput({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),c("design:type",Object)],exports.BaotaDeployPanelCertPlugin.prototype,"cert",void 0),a([e.TaskInput({title:"宝塔授权",helper:"baota的接口密钥,目前测试宝塔面板本身开启ssl之后,API接口就不能用了",component:{name:"pi-access-selector",type:"baota"},required:!0}),c("design:type",String)],exports.BaotaDeployPanelCertPlugin.prototype,"accessId",void 0),exports.BaotaDeployPanelCertPlugin=a([e.IsTaskPlugin({name:"BaotaDeployPanelCert",title:"宝塔面板证书部署",group:e.pluginGroups.other.key,desc:"部署宝塔面板本身的ssl证书",default:{strategy:{runStrategy:e.RunStrategy.SkipWhenSucceed}},needPlus:!0})],exports.BaotaDeployPanelCertPlugin),new exports.BaotaDeployPanelCertPlugin,exports.BaotaDeployWebSiteCertPlugin=class extends i{siteName;isReverseProxy=!1;cert;accessId;async onInstance(){}async execute(){const{cert:e,accessId:s}=this,o=new t.CertReader(e),n=await this.accessService.getById(s),r=this.ctx.http,i=new p(n,r);if(this.logger.info(`siteName:${this.siteName}`),this.isReverseProxy){const e=await i.doRequest("/mod/proxy/com/set_ssl",null,{site_name:this.siteName,key:o.key,csr:o.crt});this.logger.info(e?.msg)}else{const e=await i.doRequest("/site","SetSSL",{type:0,siteName:this.siteName,key:o.key,csr:o.crt});this.logger.info(e?.msg)}}},a([e.TaskInput({title:"网站域名",component:{name:"a-input"},helper:"登录面板->网站->网站名/域名/项目名称",required:!0}),c("design:type",String)],exports.BaotaDeployWebSiteCertPlugin.prototype,"siteName",void 0),a([e.TaskInput({title:"是否反向代理",value:!1,component:{name:"a-switch",vModel:"checked"},helper:"该项目类型是反向代理还是其他项目",required:!0}),c("design:type",Object)],exports.BaotaDeployWebSiteCertPlugin.prototype,"isReverseProxy",void 0),a([e.TaskInput({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),c("design:type",Object)],exports.BaotaDeployWebSiteCertPlugin.prototype,"cert",void 0),a([e.TaskInput({title:"宝塔授权",helper:"baota的接口密钥",component:{name:"pi-access-selector",type:"baota"},required:!0}),c("design:type",String)],exports.BaotaDeployWebSiteCertPlugin.prototype,"accessId",void 0),exports.BaotaDeployWebSiteCertPlugin=a([e.IsTaskPlugin({name:"BaotaDeployWebSiteCert",title:"宝塔网站证书部署",group:e.pluginGroups.other.key,desc:"部署宝塔管理的站点的ssl证书",default:{strategy:{runStrategy:e.RunStrategy.SkipWhenSucceed}},needPlus:!0})],exports.BaotaDeployWebSiteCertPlugin),new exports.BaotaDeployWebSiteCertPlugin,exports.BaotaAccess=class{panelUrl="";apiSecret=""},a([e.AccessInput({title:"宝塔URL地址",component:{placeholder:"http://192.168.42.237:41896"},helper:"宝塔面板的url地址,例如:http://192.168.42.237:41896",required:!0}),c("design:type",Object)],exports.BaotaAccess.prototype,"panelUrl",void 0),a([e.AccessInput({title:"接口密钥",component:{placeholder:"接口密钥"},helper:"宝塔面板设置->面板设置->API接口->接口配置->接口密钥。\n必须要加IP白名单,你可以先运行一次,报错之后会打印IP,将IP加入白名单之后再次运行即可",required:!0,encrypt:!0}),c("design:type",Object)],exports.BaotaAccess.prototype,"apiSecret",void 0),exports.BaotaAccess=a([e.IsAccess({name:"baota",title:"baota授权",desc:""})],exports.BaotaAccess),new exports.BaotaAccess,exports.YidunDeployToCDNPlugin=class extends i{certId;domain;cert;accessId;async onInstance(){}async execute(){const{domain:e,certId:s,cert:o}=this;if(!e&&!s)throw new Error("证书ID和网站域名必须填写一个");const n=new t.CertReader(o);s>0?await this.updateByCertId(n,s):await this.updateByDomain(n)}async updateByCertId(e,t){this.logger.info(`更新证书,证书ID:${t}`);const s=`http://user.yiduncdn.com/v1/certs/${t}`;await this.doRequest(s,"PUT",{cert:e.crt,key:e.key})}async doRequest(e,t,s){const o=await this.accessService.getById(this.accessId),{apiKey:n,apiSecret:r}=o,i=this.ctx.http,a=await i.request({url:e,method:t,headers:{"api-key":n,"api-secret":r},data:s});if(0!=a.code)throw new Error(a.msg);return a}async updateByDomain(e){const t=await this.doRequest("http://user.yiduncdn.com/v1/sites","GET",{domain:this.domain});if(0===t.data.length)throw new Error(`未找到域名相关站点:${this.domain}`);let s=null;for(const e of t.data)e.domain===this.domain&&(s=e);if(!s)throw new Error(`未找到域名匹配的站点:${this.domain}`);if(s.https_listen?.cert){const t=s.https_listen.cert;await this.updateByCertId(e,t)}else{this.logger.info(`创建证书,域名:${this.domain}`);const t="http://user.yiduncdn.com/v1/certs",o=this.domain+"_"+(new Date).getTime();await this.doRequest(t,"POST",{name:o,type:"custom",cert:e.crt,key:e.key});const n=(await this.doRequest(t,"GET",{name:o})).data[0].id,r="http://user.yiduncdn.com/v1/sites";await this.doRequest(r,"PUT",{id:s.id,https_listen:{cert:n}})}}},a([e.TaskInput({title:"证书ID",component:{name:"a-input-number",vModel:"value"},helper:"证书ID,在证书管理页面查看,每条记录都有证书id"}),c("design:type",Number)],exports.YidunDeployToCDNPlugin.prototype,"certId",void 0),a([e.TaskInput({title:"网站域名",component:{name:"a-input",vModel:"value"},helper:"网站域名和证书ID选填其中一个,填了证书ID,则忽略网站域名"}),c("design:type",Number)],exports.YidunDeployToCDNPlugin.prototype,"domain",void 0),a([e.TaskInput({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),c("design:type",Object)],exports.YidunDeployToCDNPlugin.prototype,"cert",void 0),a([e.TaskInput({title:"易盾授权",helper:"易盾CDN授权",component:{name:"pi-access-selector",type:"yidun"},required:!0}),c("design:type",String)],exports.YidunDeployToCDNPlugin.prototype,"accessId",void 0),exports.YidunDeployToCDNPlugin=a([e.IsTaskPlugin({name:"YidunDeployToCDN",title:"部署证书到易盾CDN",group:e.pluginGroups.cdn.key,desc:"http://user.yiduncdn.com/",default:{strategy:{runStrategy:e.RunStrategy.SkipWhenSucceed}},needPlus:!0})],exports.YidunDeployToCDNPlugin),new exports.YidunDeployToCDNPlugin,exports.YidunAccess=class{apiKey="";apiSecret=""},a([e.AccessInput({title:"api_key",component:{placeholder:"api_key"},helper:"http://user.yiduncdn.com/console/index.html#/account/config/api,点击开启后获取",required:!0,encrypt:!0}),c("design:type",Object)],exports.YidunAccess.prototype,"apiKey",void 0),a([e.AccessInput({title:"api_secret",component:{placeholder:"api_secret"},helper:"http://user.yiduncdn.com/console/index.html#/account/config/api,点击开启后获取",required:!0,encrypt:!0}),c("design:type",Object)],exports.YidunAccess.prototype,"apiSecret",void 0),exports.YidunAccess=a([e.IsAccess({name:"yidun",title:"易盾云授权",desc:"user.yiduncdn.com"})],exports.YidunAccess),new exports.YidunAccess,exports.FtpAccess=class{host;port;user;password;secure=!1},a([e.AccessInput({title:"host",component:{placeholder:"ip / 域名",name:"a-input",vModel:"value"},helper:"FTP地址",required:!0}),c("design:type",String)],exports.FtpAccess.prototype,"host",void 0),a([e.AccessInput({title:"host",value:21,component:{placeholder:"21",name:"a-input-number",vModel:"value"},helper:"FTP端口",required:!0}),c("design:type",String)],exports.FtpAccess.prototype,"port",void 0),a([e.AccessInput({title:"user",component:{placeholder:"用户名"},helper:"FTP用户名",required:!0}),c("design:type",String)],exports.FtpAccess.prototype,"user",void 0),a([e.AccessInput({title:"password",component:{placeholder:"密码",component:{name:"a-input-password",vModel:"value"}},encrypt:!0,helper:"FTP密码",required:!0}),c("design:type",String)],exports.FtpAccess.prototype,"password",void 0),a([e.AccessInput({title:"secure",value:!1,component:{name:"a-switch",vModel:"checked"},helper:"是否使用SSL",required:!0}),c("design:type",Boolean)],exports.FtpAccess.prototype,"secure",void 0),exports.FtpAccess=a([e.IsAccess({name:"ftp",title:"FTP授权",desc:""})],exports.FtpAccess),new exports.FtpAccess,exports.UploadCertToFTPPlugin=class extends i{crtPath;keyPath;pfxPath;derPath;cert;accessId;async onInstance(){}async execute(){const{cert:e,accessId:s}=this,o=new t.CertReader(e);let n=null;const r=async({reader:e,tmpCrtPath:t,tmpKeyPath:o,tmpDerPath:r,tmpPfxPath:i})=>{const a=(await import("basic-ftp")).Client;n=new a,n.ftp.verbose=!0,this.logger.info("开始连接FTP");const c=await this.accessService.getById(s);await n.access(c),this.logger.info("FTP连接成功"),await this.doUpload(n,t,this.crtPath),await this.doUpload(n,o,this.keyPath),await this.doUpload(n,i,this.pfxPath),await this.doUpload(n,r,this.derPath)};try{await o.readCertFile({logger:this.logger,handle:r})}finally{n&&n.close()}this.logger.info("执行完成")}async doUpload(e,t,s){if(!s)return;const n=o.dirname(s);this.logger.info(`确保目录存在:${n}`),await e.ensureDir(n),this.logger.info(`开始上传文件${t} -> ${s}`),await e.uploadFrom(t,s)}},a([e.TaskInput({title:"PEM证书保存路径",helper:"需要有写入权限,路径要包含证书文件名,文件名不能用*?!等特殊符号",component:{placeholder:"/test/cert.pem"}}),c("design:type",String)],exports.UploadCertToFTPPlugin.prototype,"crtPath",void 0),a([e.TaskInput({title:"私钥保存路径",helper:"需要有写入权限,路径要包含私钥文件名,文件名不能用*?!等特殊符号",component:{placeholder:"/test/cert.key"}}),c("design:type",String)],exports.UploadCertToFTPPlugin.prototype,"keyPath",void 0),a([e.TaskInput({title:"PFX证书保存路径",helper:"需要有写入权限,路径要包含文件名,文件名不能用*?!等特殊符号",component:{placeholder:"/test/cert.pfx"}}),c("design:type",String)],exports.UploadCertToFTPPlugin.prototype,"pfxPath",void 0),a([e.TaskInput({title:"DER证书保存路径",helper:"需要有写入权限,路径要包含文件名,文件名不能用*?!等特殊符号\n.der和.cer是相同的东西,改个后缀名即可",component:{placeholder:"/test/cert.der 或 /test/cert.cer"}}),c("design:type",String)],exports.UploadCertToFTPPlugin.prototype,"derPath",void 0),a([e.TaskInput({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector",type:"CertApply"},required:!0}),c("design:type",Object)],exports.UploadCertToFTPPlugin.prototype,"cert",void 0),a([e.TaskInput({title:"FTP授权",component:{name:"pi-access-selector",type:"ftp"},required:!0}),c("design:type",String)],exports.UploadCertToFTPPlugin.prototype,"accessId",void 0),exports.UploadCertToFTPPlugin=a([e.IsTaskPlugin({name:"UploadCertToFTP",title:"上传证书到FTP",group:e.pluginGroups.host.key,desc:"将证书上传到FTP服务器",default:{strategy:{runStrategy:e.RunStrategy.SkipWhenSucceed}},needPlus:!0})],exports.UploadCertToFTPPlugin),new exports.UploadCertToFTPPlugin,exports.CdnflyDeployToCDNPlugin=class extends i{url;certId;domain;cert;accessId;async onInstance(){}async execute(){const{domain:e,certId:s,cert:o}=this;if(!e&&!s)throw new Error("证书ID和网站域名必须填写一个");const n=new t.CertReader(o);s>0?await this.updateByCertId(n,s):await this.updateByDomain(n)}async updateByCertId(e,t){this.logger.info(`更新证书,证书ID:${t}`);const s=`${this.url}/v1/certs/${t}`;await this.doRequest(s,"PUT",{cert:e.crt,key:e.key})}async doRequest(e,t,s){const o=await this.accessService.getById(this.accessId),{apiKey:n,apiSecret:r}=o,i=this.ctx.http,a=await i.request({url:e,method:t,headers:{"api-key":n,"api-secret":r},data:s});if(0!=a.code)throw new Error(a.msg);return a}async updateByDomain(e){const t=`${this.url}/v1/sites`,s=await this.doRequest(t,"GET",{domain:this.domain});if(0===s.data.length)throw new Error(`未找到域名相关站点:${this.domain}`);let o=null;for(const e of s.data)e.domain===this.domain&&(o=e);if(!o)throw new Error(`未找到域名匹配的站点:${this.domain}`);if(o.https_listen?.cert){const t=o.https_listen.cert;await this.updateByCertId(e,t)}else{this.logger.info(`创建证书,域名:${this.domain}`);const t=`${this.url}/v1/certs`,s=this.domain+"_"+(new Date).getTime();await this.doRequest(t,"POST",{name:s,type:"custom",cert:e.crt,key:e.key});const n=(await this.doRequest(t,"GET",{name:s})).data[0].id,r=`${this.url}/v1/sites`;await this.doRequest(r,"PUT",{id:o.id,https_listen:{cert:n}})}}},a([e.TaskInput({title:"cdnfly系统网址",component:{name:"a-input",vModel:"value"},helper:"例如:http://demo.cdnfly.cn"}),c("design:type",String)],exports.CdnflyDeployToCDNPlugin.prototype,"url",void 0),a([e.TaskInput({title:"证书ID",component:{name:"a-input-number",vModel:"value"},helper:"证书ID,在证书管理页面查看,每条记录都有证书id"}),c("design:type",Number)],exports.CdnflyDeployToCDNPlugin.prototype,"certId",void 0),a([e.TaskInput({title:"网站域名",component:{name:"a-input",vModel:"value"},helper:"网站域名和证书ID选填其中一个,填了证书ID,则忽略网站域名"}),c("design:type",Number)],exports.CdnflyDeployToCDNPlugin.prototype,"domain",void 0),a([e.TaskInput({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),c("design:type",Object)],exports.CdnflyDeployToCDNPlugin.prototype,"cert",void 0),a([e.TaskInput({title:"cdnfly授权",helper:"cdnfly授权",component:{name:"pi-access-selector",type:"cdnfly"},required:!0}),c("design:type",String)],exports.CdnflyDeployToCDNPlugin.prototype,"accessId",void 0),exports.CdnflyDeployToCDNPlugin=a([e.IsTaskPlugin({name:"CdnflyDeployToCDN",title:"部署证书到cdnfly",group:e.pluginGroups.cdn.key,desc:"cdnfly",default:{strategy:{runStrategy:e.RunStrategy.SkipWhenSucceed}},needPlus:!0})],exports.CdnflyDeployToCDNPlugin),new exports.CdnflyDeployToCDNPlugin,exports.CdnflyAccess=class{apiKey="";apiSecret=""},a([e.AccessInput({title:"api_key",component:{placeholder:"api_key"},helper:"登录cdnfly控制台->账户中心->Api密钥,点击开启后获取",required:!0,encrypt:!0}),c("design:type",Object)],exports.CdnflyAccess.prototype,"apiKey",void 0),a([e.AccessInput({title:"api_secret",component:{placeholder:"api_secret"},helper:"登录cdnfly控制台->账户中心->Api密钥,点击开启后获取",required:!0,encrypt:!0}),c("design:type",Object)],exports.CdnflyAccess.prototype,"apiSecret",void 0),exports.CdnflyAccess=a([e.IsAccess({name:"cdnfly",title:"cdnfly授权",desc:""})],exports.CdnflyAccess),new exports.CdnflyAccess,exports.DeployCertToAliyunOSS=class extends i{region;bucket;domainName;certName;cert;accessId;async onInstance(){}async execute(){this.logger.info("开始部署证书到阿里云OSS");const e=await this.accessService.getById(this.accessId);this.logger.info(`bucket: ${this.bucket}, region: ${this.region}, domainName: ${this.domainName}`);const t=await this.getClient(e);await this.doRequest(t,{}),this.logger.info("部署完成")}async getClient(e){return new((await import("ali-oss")).default)({accessKeyId:e.accessKeyId,accessKeySecret:e.accessKeySecret,region:this.region,authorizationV4:!0,bucket:this.bucket})}async doRequest(e,t){t=e._bucketRequestParams("POST",this.bucket,{cname:"",comp:"add"});const s=`\n <BucketCnameConfiguration>\n <Cname>\n <Domain>${this.domainName}</Domain>\n <CertificateConfiguration>\n <PrivateKey>${this.cert.key}</PrivateKey>\n <Certificate>${this.cert.crt}</Certificate>\n </CertificateConfiguration>\n </Cname>\n</BucketCnameConfiguration>`;t.content=s,t.mime="xml",t.successStatuses=[200];const o=await e.request(t);return this.checkRet(o),o}checkRet(e){if(null!=e.code)throw new Error("执行失败:"+e.Message)}},a([e.TaskInput({title:"大区",component:{name:"a-auto-complete",vModel:"value",options:[{value:"oss-cn-shanghai"},{value:"oss-cn-nanjing"},{value:"oss-cn-fuzhou"},{value:"oss-cn-wuhan"},{value:"oss-cn-qingdao"},{value:"oss-cn-beijing"},{value:"oss-cn-zhangjiakou"},{value:"oss-cn-huhehaote"},{value:"oss-cn-wulanchabu"},{value:"oss-cn-shenzhen"},{value:"oss-cn-heyuan"},{value:"oss-cn-guangzhou"},{value:"oss-cn-chengdu"},{value:"oss-cn-hongkong"},{value:"oss-us-west-1"},{value:"oss-us-east-1"},{value:"oss-ap-northeast-1"},{value:"oss-ap-northeast-2"},{value:"oss-ap-southeast-1"},{value:"oss-ap-southeast-2"},{value:"oss-ap-southeast-3"},{value:"oss-ap-southeast-5"},{value:"oss-ap-southeast-6"},{value:"oss-ap-southeast-7"},{value:"oss-ap-south-1"},{value:"oss-eu-central-1"},{value:"oss-eu-west-1"},{value:"oss-me-east-1"},{value:"oss-rg-china-mainland"}]},required:!0}),c("design:type",String)],exports.DeployCertToAliyunOSS.prototype,"region",void 0),a([e.TaskInput({title:"Bucket",helper:"存储桶名称"}),c("design:type",String)],exports.DeployCertToAliyunOSS.prototype,"bucket",void 0),a([e.TaskInput({title:"绑定的域名",helper:"你在阿里云OSS上绑定的域名,比如:certd.docmirror.cn",required:!0}),c("design:type",String)],exports.DeployCertToAliyunOSS.prototype,"domainName",void 0),a([e.TaskInput({title:"证书名称",helper:"上传后将以此名称作为前缀备注"}),c("design:type",String)],exports.DeployCertToAliyunOSS.prototype,"certName",void 0),a([e.TaskInput({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector",from:"CertApply"},required:!0}),c("design:type",Object)],exports.DeployCertToAliyunOSS.prototype,"cert",void 0),a([e.TaskInput({title:"Access授权",helper:"阿里云授权AccessKeyId、AccessKeySecret",component:{name:"pi-access-selector",type:"aliyun"},required:!0}),c("design:type",String)],exports.DeployCertToAliyunOSS.prototype,"accessId",void 0),exports.DeployCertToAliyunOSS=a([e.IsTaskPlugin({name:"DeployCertToAliyunOSS",title:"部署证书至阿里云OSS",group:e.pluginGroups.aliyun.key,desc:"自动部署域名证书至阿里云OSS",needPlus:!0,default:{strategy:{runStrategy:e.RunStrategy.SkipWhenSucceed}}})],exports.DeployCertToAliyunOSS),new exports.DeployCertToAliyunOSS,exports.AliyunAccess=class{accessKeyId="";accessKeySecret=""},a([e.AccessInput({title:"accessKeyId",component:{placeholder:"accessKeyId"},helper:"登录阿里云控制台->AccessKey管理页面获取。",required:!0}),c("design:type",Object)],exports.AliyunAccess.prototype,"accessKeyId",void 0),a([e.AccessInput({title:"accessKeySecret",component:{placeholder:"accessKeySecret"},required:!0,encrypt:!0,helper:"注意:证书申请需要dns解析权限;其他阿里云插件,需要对应的权限,比如证书上传需要证书管理权限;嫌麻烦就用主账号的全量权限的accessKey"}),c("design:type",Object)],exports.AliyunAccess.prototype,"accessKeySecret",void 0),exports.AliyunAccess=a([e.IsAccess({name:"aliyun",title:"阿里云授权",desc:""})],exports.AliyunAccess),new exports.AliyunAccess;exports.AbstractPlusTaskPlugin=i,exports.AliyunClient=class{client;logger;agent;constructor(e){this.logger=e.logger;const t=process.env.HTTPS_PROXY;t&&(this.logger.info(`use proxy:${t}`),this.agent=new n.HttpsProxyAgent(t))}async getSdk(){return(await import("@alicloud/pop-core")).default}async init(e){const t=await this.getSdk();return this.client=new t(e),this.client}async request(e,t,s={}){return s.agent=this.agent,await this.client.request(e,t,s)}},exports.mustPlus=r;
|
|
1
|
+
"use strict";var e=require("@certd/pipeline"),t=require("@certd/plugin-cert"),s=require("node:crypto"),o=require("node:path"),n=require("https-proxy-agent"),r=require("querystring"),i=require("fs"),a=require("form-data");function c(){if(!e.isPlus())throw new Error("此插件仅供专业版中使用")}class p extends e.AbstractTaskPlugin{setCtx(e){super.setCtx(e),c()}}function l(e,t,s,o){var n,r=arguments.length,i=r<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,s):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,s,o);else for(var a=e.length-1;a>=0;a--)(n=e[a])&&(i=(r<3?n(i):r>3?n(t,s,i):n(t,s))||i);return r>3&&i&&Object.defineProperty(t,s,i),i}function d(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}"function"==typeof SuppressedError&&SuppressedError;class u{access;http;constructor(e,t){this.access=e,this.http=t}getRequestToken(){const e=(new Date).getTime(),t=e+this.getMd5(this.access.apiSecret);return{request_token:this.getMd5(t),request_time:e}}getMd5(e){return s.createHash("md5").update(e).digest("hex")}async doRequest(e,t,s){const o=this.getRequestToken();console.log("token",o);const n={...o,...s};let r=`${this.access.panelUrl}${e}`;t&&(r=`${r}?action=${t}`);const i=await this.http.request({url:r,method:"post",headers:{"Content-Type":"application/x-www-form-urlencoded"},data:n});if(!i.status)throw new Error(i.msg);return i}}exports.BaotaDeployPanelCertPlugin=class extends p{cert;accessId;async onInstance(){}async execute(){const{cert:e,accessId:s}=this,o=new t.CertReader(e),n=await this.accessService.getById(s),r=this.ctx.http,i=new u(n,r),a=await i.doRequest("/config","SavePanelSSL",{privateKey:o.key,certPem:o.crt});this.logger.info(a?.msg)}},l([e.TaskInput({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),d("design:type",Object)],exports.BaotaDeployPanelCertPlugin.prototype,"cert",void 0),l([e.TaskInput({title:"宝塔授权",helper:"baota的接口密钥,目前测试宝塔面板本身开启ssl之后,API接口就不能用了",component:{name:"pi-access-selector",type:"baota"},required:!0}),d("design:type",String)],exports.BaotaDeployPanelCertPlugin.prototype,"accessId",void 0),exports.BaotaDeployPanelCertPlugin=l([e.IsTaskPlugin({name:"BaotaDeployPanelCert",title:"宝塔面板证书部署",group:e.pluginGroups.other.key,desc:"部署宝塔面板本身的ssl证书",default:{strategy:{runStrategy:e.RunStrategy.SkipWhenSucceed}},needPlus:!0})],exports.BaotaDeployPanelCertPlugin),new exports.BaotaDeployPanelCertPlugin,exports.BaotaDeployWebSiteCertPlugin=class extends p{siteName;isReverseProxy=!1;cert;accessId;async onInstance(){}async execute(){const{cert:e,accessId:s}=this,o=new t.CertReader(e),n=await this.accessService.getById(s),r=this.ctx.http,i=new u(n,r);if(this.logger.info(`siteName:${this.siteName}`),this.isReverseProxy){const e=await i.doRequest("/mod/proxy/com/set_ssl",null,{site_name:this.siteName,key:o.key,csr:o.crt});this.logger.info(e?.msg)}else{const e=await i.doRequest("/site","SetSSL",{type:0,siteName:this.siteName,key:o.key,csr:o.crt});this.logger.info(e?.msg)}}},l([e.TaskInput({title:"网站域名",component:{name:"a-input"},helper:"登录面板->网站->网站名/域名/项目名称",required:!0}),d("design:type",String)],exports.BaotaDeployWebSiteCertPlugin.prototype,"siteName",void 0),l([e.TaskInput({title:"是否反向代理",value:!1,component:{name:"a-switch",vModel:"checked"},helper:"该项目类型是反向代理还是其他项目",required:!0}),d("design:type",Object)],exports.BaotaDeployWebSiteCertPlugin.prototype,"isReverseProxy",void 0),l([e.TaskInput({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),d("design:type",Object)],exports.BaotaDeployWebSiteCertPlugin.prototype,"cert",void 0),l([e.TaskInput({title:"宝塔授权",helper:"baota的接口密钥",component:{name:"pi-access-selector",type:"baota"},required:!0}),d("design:type",String)],exports.BaotaDeployWebSiteCertPlugin.prototype,"accessId",void 0),exports.BaotaDeployWebSiteCertPlugin=l([e.IsTaskPlugin({name:"BaotaDeployWebSiteCert",title:"宝塔网站证书部署",group:e.pluginGroups.other.key,desc:"部署宝塔管理的站点的ssl证书",default:{strategy:{runStrategy:e.RunStrategy.SkipWhenSucceed}},needPlus:!0})],exports.BaotaDeployWebSiteCertPlugin),new exports.BaotaDeployWebSiteCertPlugin,exports.BaotaAccess=class{panelUrl="";apiSecret=""},l([e.AccessInput({title:"宝塔URL地址",component:{placeholder:"http://192.168.42.237:41896"},helper:"宝塔面板的url地址,例如:http://192.168.42.237:41896",required:!0}),d("design:type",Object)],exports.BaotaAccess.prototype,"panelUrl",void 0),l([e.AccessInput({title:"接口密钥",component:{placeholder:"接口密钥"},helper:"宝塔面板设置->面板设置->API接口->接口配置->接口密钥。\n必须要加IP白名单,你可以先运行一次,报错之后会打印IP,将IP加入白名单之后再次运行即可",required:!0,encrypt:!0}),d("design:type",Object)],exports.BaotaAccess.prototype,"apiSecret",void 0),exports.BaotaAccess=l([e.IsAccess({name:"baota",title:"baota授权",desc:""})],exports.BaotaAccess),new exports.BaotaAccess,exports.YidunDeployToCDNPlugin=class extends p{certId;domain;cert;accessId;async onInstance(){}async execute(){const{domain:e,certId:s,cert:o}=this;if(!e&&!s)throw new Error("证书ID和网站域名必须填写一个");const n=new t.CertReader(o);s>0?await this.updateByCertId(n,s):await this.updateByDomain(n)}async updateByCertId(e,t){this.logger.info(`更新证书,证书ID:${t}`);const s=`http://user.yiduncdn.com/v1/certs/${t}`;await this.doRequest(s,"PUT",{cert:e.crt,key:e.key})}async doRequest(e,t,s){const o=await this.accessService.getById(this.accessId),{apiKey:n,apiSecret:r}=o,i=this.ctx.http,a=await i.request({url:e,method:t,headers:{"api-key":n,"api-secret":r},data:s});if(0!=a.code)throw new Error(a.msg);return a}async updateByDomain(e){const t=await this.doRequest("http://user.yiduncdn.com/v1/sites","GET",{domain:this.domain});if(0===t.data.length)throw new Error(`未找到域名相关站点:${this.domain}`);let s=null;for(const e of t.data)e.domain===this.domain&&(s=e);if(!s)throw new Error(`未找到域名匹配的站点:${this.domain}`);if(s.https_listen?.cert){const t=s.https_listen.cert;await this.updateByCertId(e,t)}else{this.logger.info(`创建证书,域名:${this.domain}`);const t="http://user.yiduncdn.com/v1/certs",o=this.domain+"_"+(new Date).getTime();await this.doRequest(t,"POST",{name:o,type:"custom",cert:e.crt,key:e.key});const n=(await this.doRequest(t,"GET",{name:o})).data[0].id,r="http://user.yiduncdn.com/v1/sites";await this.doRequest(r,"PUT",{id:s.id,https_listen:{cert:n}})}}},l([e.TaskInput({title:"证书ID",component:{name:"a-input-number",vModel:"value"},helper:"证书ID,在证书管理页面查看,每条记录都有证书id"}),d("design:type",Number)],exports.YidunDeployToCDNPlugin.prototype,"certId",void 0),l([e.TaskInput({title:"网站域名",component:{name:"a-input",vModel:"value"},helper:"网站域名和证书ID选填其中一个,填了证书ID,则忽略网站域名"}),d("design:type",Number)],exports.YidunDeployToCDNPlugin.prototype,"domain",void 0),l([e.TaskInput({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),d("design:type",Object)],exports.YidunDeployToCDNPlugin.prototype,"cert",void 0),l([e.TaskInput({title:"易盾授权",helper:"易盾CDN授权",component:{name:"pi-access-selector",type:"yidun"},required:!0}),d("design:type",String)],exports.YidunDeployToCDNPlugin.prototype,"accessId",void 0),exports.YidunDeployToCDNPlugin=l([e.IsTaskPlugin({name:"YidunDeployToCDN",title:"部署证书到易盾CDN",group:e.pluginGroups.cdn.key,desc:"http://user.yiduncdn.com/",default:{strategy:{runStrategy:e.RunStrategy.SkipWhenSucceed}},needPlus:!0})],exports.YidunDeployToCDNPlugin),new exports.YidunDeployToCDNPlugin,exports.YidunAccess=class{apiKey="";apiSecret=""},l([e.AccessInput({title:"api_key",component:{placeholder:"api_key"},helper:"http://user.yiduncdn.com/console/index.html#/account/config/api,点击开启后获取",required:!0,encrypt:!0}),d("design:type",Object)],exports.YidunAccess.prototype,"apiKey",void 0),l([e.AccessInput({title:"api_secret",component:{placeholder:"api_secret"},helper:"http://user.yiduncdn.com/console/index.html#/account/config/api,点击开启后获取",required:!0,encrypt:!0}),d("design:type",Object)],exports.YidunAccess.prototype,"apiSecret",void 0),exports.YidunAccess=l([e.IsAccess({name:"yidun",title:"易盾云授权",desc:"user.yiduncdn.com"})],exports.YidunAccess),new exports.YidunAccess,exports.FtpAccess=class{host;port;user;password;secure=!1},l([e.AccessInput({title:"host",component:{placeholder:"ip / 域名",name:"a-input",vModel:"value"},helper:"FTP地址",required:!0}),d("design:type",String)],exports.FtpAccess.prototype,"host",void 0),l([e.AccessInput({title:"host",value:21,component:{placeholder:"21",name:"a-input-number",vModel:"value"},helper:"FTP端口",required:!0}),d("design:type",String)],exports.FtpAccess.prototype,"port",void 0),l([e.AccessInput({title:"user",component:{placeholder:"用户名"},helper:"FTP用户名",required:!0}),d("design:type",String)],exports.FtpAccess.prototype,"user",void 0),l([e.AccessInput({title:"password",component:{placeholder:"密码",component:{name:"a-input-password",vModel:"value"}},encrypt:!0,helper:"FTP密码",required:!0}),d("design:type",String)],exports.FtpAccess.prototype,"password",void 0),l([e.AccessInput({title:"secure",value:!1,component:{name:"a-switch",vModel:"checked"},helper:"是否使用SSL",required:!0}),d("design:type",Boolean)],exports.FtpAccess.prototype,"secure",void 0),exports.FtpAccess=l([e.IsAccess({name:"ftp",title:"FTP授权",desc:""})],exports.FtpAccess),new exports.FtpAccess,exports.UploadCertToFTPPlugin=class extends p{crtPath;keyPath;pfxPath;derPath;cert;accessId;async onInstance(){}async execute(){const{cert:e,accessId:s}=this,o=new t.CertReader(e);let n=null;const r=async({reader:e,tmpCrtPath:t,tmpKeyPath:o,tmpDerPath:r,tmpPfxPath:i})=>{const a=(await import("basic-ftp")).Client;n=new a,n.ftp.verbose=!0,this.logger.info("开始连接FTP");const c=await this.accessService.getById(s);await n.access(c),this.logger.info("FTP连接成功"),await this.doUpload(n,t,this.crtPath),await this.doUpload(n,o,this.keyPath),await this.doUpload(n,i,this.pfxPath),await this.doUpload(n,r,this.derPath)};try{await o.readCertFile({logger:this.logger,handle:r})}finally{n&&n.close()}this.logger.info("执行完成")}async doUpload(e,t,s){if(!s)return;const n=o.dirname(s);this.logger.info(`确保目录存在:${n}`),await e.ensureDir(n),this.logger.info(`开始上传文件${t} -> ${s}`),await e.uploadFrom(t,s)}},l([e.TaskInput({title:"PEM证书保存路径",helper:"需要有写入权限,路径要包含证书文件名,文件名不能用*?!等特殊符号",component:{placeholder:"/test/cert.pem"}}),d("design:type",String)],exports.UploadCertToFTPPlugin.prototype,"crtPath",void 0),l([e.TaskInput({title:"私钥保存路径",helper:"需要有写入权限,路径要包含私钥文件名,文件名不能用*?!等特殊符号",component:{placeholder:"/test/cert.key"}}),d("design:type",String)],exports.UploadCertToFTPPlugin.prototype,"keyPath",void 0),l([e.TaskInput({title:"PFX证书保存路径",helper:"需要有写入权限,路径要包含文件名,文件名不能用*?!等特殊符号",component:{placeholder:"/test/cert.pfx"}}),d("design:type",String)],exports.UploadCertToFTPPlugin.prototype,"pfxPath",void 0),l([e.TaskInput({title:"DER证书保存路径",helper:"需要有写入权限,路径要包含文件名,文件名不能用*?!等特殊符号\n.der和.cer是相同的东西,改个后缀名即可",component:{placeholder:"/test/cert.der 或 /test/cert.cer"}}),d("design:type",String)],exports.UploadCertToFTPPlugin.prototype,"derPath",void 0),l([e.TaskInput({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector",type:"CertApply"},required:!0}),d("design:type",Object)],exports.UploadCertToFTPPlugin.prototype,"cert",void 0),l([e.TaskInput({title:"FTP授权",component:{name:"pi-access-selector",type:"ftp"},required:!0}),d("design:type",String)],exports.UploadCertToFTPPlugin.prototype,"accessId",void 0),exports.UploadCertToFTPPlugin=l([e.IsTaskPlugin({name:"UploadCertToFTP",title:"上传证书到FTP",group:e.pluginGroups.host.key,desc:"将证书上传到FTP服务器",default:{strategy:{runStrategy:e.RunStrategy.SkipWhenSucceed}},needPlus:!0})],exports.UploadCertToFTPPlugin),new exports.UploadCertToFTPPlugin,exports.CdnflyDeployToCDNPlugin=class extends p{url;certId;domain;cert;accessId;async onInstance(){}async execute(){const{domain:e,certId:s,cert:o}=this;if(!e&&!s)throw new Error("证书ID和网站域名必须填写一个");const n=new t.CertReader(o);s>0?await this.updateByCertId(n,s):await this.updateByDomain(n)}async updateByCertId(e,t){this.logger.info(`更新证书,证书ID:${t}`);const s=`${this.url}/v1/certs/${t}`;await this.doRequest(s,"PUT",{cert:e.crt,key:e.key})}async doRequest(e,t,s){const o=await this.accessService.getById(this.accessId),{apiKey:n,apiSecret:r}=o,i=this.ctx.http,a=await i.request({url:e,method:t,headers:{"api-key":n,"api-secret":r},data:s});if(0!=a.code)throw new Error(a.msg);return a}async updateByDomain(e){const t=`${this.url}/v1/sites`,s=await this.doRequest(t,"GET",{domain:this.domain});if(0===s.data.length)throw new Error(`未找到域名相关站点:${this.domain}`);let o=null;for(const e of s.data)e.domain===this.domain&&(o=e);if(!o)throw new Error(`未找到域名匹配的站点:${this.domain}`);if(o.https_listen?.cert){const t=o.https_listen.cert;await this.updateByCertId(e,t)}else{this.logger.info(`创建证书,域名:${this.domain}`);const t=`${this.url}/v1/certs`,s=this.domain+"_"+(new Date).getTime();await this.doRequest(t,"POST",{name:s,type:"custom",cert:e.crt,key:e.key});const n=(await this.doRequest(t,"GET",{name:s})).data[0].id,r=`${this.url}/v1/sites`;await this.doRequest(r,"PUT",{id:o.id,https_listen:{cert:n}})}}},l([e.TaskInput({title:"cdnfly系统网址",component:{name:"a-input",vModel:"value"},helper:"例如:http://demo.cdnfly.cn"}),d("design:type",String)],exports.CdnflyDeployToCDNPlugin.prototype,"url",void 0),l([e.TaskInput({title:"证书ID",component:{name:"a-input-number",vModel:"value"},helper:"证书ID,在证书管理页面查看,每条记录都有证书id"}),d("design:type",Number)],exports.CdnflyDeployToCDNPlugin.prototype,"certId",void 0),l([e.TaskInput({title:"网站域名",component:{name:"a-input",vModel:"value"},helper:"网站域名和证书ID选填其中一个,填了证书ID,则忽略网站域名"}),d("design:type",Number)],exports.CdnflyDeployToCDNPlugin.prototype,"domain",void 0),l([e.TaskInput({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),d("design:type",Object)],exports.CdnflyDeployToCDNPlugin.prototype,"cert",void 0),l([e.TaskInput({title:"cdnfly授权",helper:"cdnfly授权",component:{name:"pi-access-selector",type:"cdnfly"},required:!0}),d("design:type",String)],exports.CdnflyDeployToCDNPlugin.prototype,"accessId",void 0),exports.CdnflyDeployToCDNPlugin=l([e.IsTaskPlugin({name:"CdnflyDeployToCDN",title:"部署证书到cdnfly",group:e.pluginGroups.cdn.key,desc:"cdnfly",default:{strategy:{runStrategy:e.RunStrategy.SkipWhenSucceed}},needPlus:!0})],exports.CdnflyDeployToCDNPlugin),new exports.CdnflyDeployToCDNPlugin,exports.CdnflyAccess=class{apiKey="";apiSecret=""},l([e.AccessInput({title:"api_key",component:{placeholder:"api_key"},helper:"登录cdnfly控制台->账户中心->Api密钥,点击开启后获取",required:!0,encrypt:!0}),d("design:type",Object)],exports.CdnflyAccess.prototype,"apiKey",void 0),l([e.AccessInput({title:"api_secret",component:{placeholder:"api_secret"},helper:"登录cdnfly控制台->账户中心->Api密钥,点击开启后获取",required:!0,encrypt:!0}),d("design:type",Object)],exports.CdnflyAccess.prototype,"apiSecret",void 0),exports.CdnflyAccess=l([e.IsAccess({name:"cdnfly",title:"cdnfly授权",desc:""})],exports.CdnflyAccess),new exports.CdnflyAccess,exports.DeployCertToAliyunOSS=class extends p{region;bucket;domainName;certName;cert;accessId;async onInstance(){}async execute(){this.logger.info("开始部署证书到阿里云OSS");const e=await this.accessService.getById(this.accessId);this.logger.info(`bucket: ${this.bucket}, region: ${this.region}, domainName: ${this.domainName}`);const t=await this.getClient(e);await this.doRequest(t,{}),this.logger.info("部署完成")}async getClient(e){return new((await import("ali-oss")).default)({accessKeyId:e.accessKeyId,accessKeySecret:e.accessKeySecret,region:this.region,authorizationV4:!0,bucket:this.bucket})}async doRequest(e,t){t=e._bucketRequestParams("POST",this.bucket,{cname:"",comp:"add"});const s=`\n <BucketCnameConfiguration>\n <Cname>\n <Domain>${this.domainName}</Domain>\n <CertificateConfiguration>\n <PrivateKey>${this.cert.key}</PrivateKey>\n <Certificate>${this.cert.crt}</Certificate>\n </CertificateConfiguration>\n </Cname>\n</BucketCnameConfiguration>`;t.content=s,t.mime="xml",t.successStatuses=[200];const o=await e.request(t);return this.checkRet(o),o}checkRet(e){if(null!=e.code)throw new Error("执行失败:"+e.Message)}},l([e.TaskInput({title:"大区",component:{name:"a-auto-complete",vModel:"value",options:[{value:"oss-cn-shanghai"},{value:"oss-cn-nanjing"},{value:"oss-cn-fuzhou"},{value:"oss-cn-wuhan"},{value:"oss-cn-qingdao"},{value:"oss-cn-beijing"},{value:"oss-cn-zhangjiakou"},{value:"oss-cn-huhehaote"},{value:"oss-cn-wulanchabu"},{value:"oss-cn-shenzhen"},{value:"oss-cn-heyuan"},{value:"oss-cn-guangzhou"},{value:"oss-cn-chengdu"},{value:"oss-cn-hongkong"},{value:"oss-us-west-1"},{value:"oss-us-east-1"},{value:"oss-ap-northeast-1"},{value:"oss-ap-northeast-2"},{value:"oss-ap-southeast-1"},{value:"oss-ap-southeast-2"},{value:"oss-ap-southeast-3"},{value:"oss-ap-southeast-5"},{value:"oss-ap-southeast-6"},{value:"oss-ap-southeast-7"},{value:"oss-ap-south-1"},{value:"oss-eu-central-1"},{value:"oss-eu-west-1"},{value:"oss-me-east-1"},{value:"oss-rg-china-mainland"}]},required:!0}),d("design:type",String)],exports.DeployCertToAliyunOSS.prototype,"region",void 0),l([e.TaskInput({title:"Bucket",helper:"存储桶名称"}),d("design:type",String)],exports.DeployCertToAliyunOSS.prototype,"bucket",void 0),l([e.TaskInput({title:"绑定的域名",helper:"你在阿里云OSS上绑定的域名,比如:certd.docmirror.cn",required:!0}),d("design:type",String)],exports.DeployCertToAliyunOSS.prototype,"domainName",void 0),l([e.TaskInput({title:"证书名称",helper:"上传后将以此名称作为前缀备注"}),d("design:type",String)],exports.DeployCertToAliyunOSS.prototype,"certName",void 0),l([e.TaskInput({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector",from:"CertApply"},required:!0}),d("design:type",Object)],exports.DeployCertToAliyunOSS.prototype,"cert",void 0),l([e.TaskInput({title:"Access授权",helper:"阿里云授权AccessKeyId、AccessKeySecret",component:{name:"pi-access-selector",type:"aliyun"},required:!0}),d("design:type",String)],exports.DeployCertToAliyunOSS.prototype,"accessId",void 0),exports.DeployCertToAliyunOSS=l([e.IsTaskPlugin({name:"DeployCertToAliyunOSS",title:"部署证书至阿里云OSS",group:e.pluginGroups.aliyun.key,desc:"自动部署域名证书至阿里云OSS",needPlus:!0,default:{strategy:{runStrategy:e.RunStrategy.SkipWhenSucceed}}})],exports.DeployCertToAliyunOSS),new exports.DeployCertToAliyunOSS,exports.AliyunAccess=class{accessKeyId="";accessKeySecret=""},l([e.AccessInput({title:"accessKeyId",component:{placeholder:"accessKeyId"},helper:"登录阿里云控制台->AccessKey管理页面获取。",required:!0}),d("design:type",Object)],exports.AliyunAccess.prototype,"accessKeyId",void 0),l([e.AccessInput({title:"accessKeySecret",component:{placeholder:"accessKeySecret"},required:!0,encrypt:!0,helper:"注意:证书申请需要dns解析权限;其他阿里云插件,需要对应的权限,比如证书上传需要证书管理权限;嫌麻烦就用主账号的全量权限的accessKey"}),d("design:type",Object)],exports.AliyunAccess.prototype,"accessKeySecret",void 0),exports.AliyunAccess=l([e.IsAccess({name:"aliyun",title:"阿里云授权",desc:""})],exports.AliyunAccess),new exports.AliyunAccess;class y{access;http;logger;token;constructor(e,t,s){this.access=e,this.http=t,this.logger=s}async doLogin(){const e=this.access,t=await this.http.request({url:`${e.baseUrl}/webapi/entry.cgi`,method:"GET",params:{api:"SYNO.API.Auth",version:6,method:"login",account:e.username,passwd:e.password,session:"Certd",format:"sid",enable_syno_token:"yes"}});if(!t.success)throw new Error(`登录失败: ${t.error}`);return this.logger.info("登录成功"),this.token=t.data,this.token}async doRequest(e){const t=this.token.sid,s=e.method||"POST",o={...e.apiParams,_sid:t,...e.params,SynoToken:this.token.synotoken},n=await this.http.request({url:`${this.access.baseUrl}/webapi/entry.cgi?${r.stringify(o)}`,method:s,data:e.data,headers:e.headers});if(!n.success)throw new Error(`API 调用失败: ${JSON.stringify(n.error)}`);return n.data}async getCertList(){return this.logger.info("获取证书列表"),await this.doRequest({method:"GET",apiParams:{api:"SYNO.Core.Certificate.CRT",version:1,method:"list"}})}async getInfo(){return this.logger.info("获取信息"),await this.doRequest({method:"GET",apiParams:{api:"SYNO.API.Info",version:1,method:"query"}})}}exports.SynologyDeployToPanel=class extends p{certName;cert;accessId;async onInstance(){}async execute(){const e=await this.accessService.getById(this.accessId),t=new y(e,this.ctx.http,this.ctx.logger);await t.doLogin();const s=(await t.getCertList()).certificates.find((e=>e.desc===this.certName||e.subject.common_name===this.certName));if(!s)throw new Error(`未找到证书: ${this.certName}`);this.logger.info(`找到证书: ${s.id}`),await this.updateCertToPanel(t,s)}async updateCertToPanel(e,s){this.logger.info(`更新证书:${s.id}`);return new t.CertReader(this.cert).readCertFile({logger:this.logger,handle:async t=>{const o=new a,{tmpCrtPath:n,tmpKeyPath:r}=t;return this.logger.info(`上传证书:${n},${r}`),o.append("key",i.createReadStream(r)),o.append("cert",i.createReadStream(n)),o.append("id",s.id),o.append("desc",s.desc),console.log(JSON.stringify(o.getHeaders())),await e.doRequest({method:"POST",apiParams:{api:"SYNO.Core.Certificate",version:1,method:"import"},data:o,headers:{...o.getHeaders()}})}})}},l([e.TaskInput({title:"证书描述/域名",component:{name:"a-input",vModel:"value",placeholder:"请输入证书描述或者证书域名"},required:!0,helper:"证书描述或者证书域名,默认证书域名为synology\n建议给证书设置描述,查找证书更准确"}),d("design:type",String)],exports.SynologyDeployToPanel.prototype,"certName",void 0),l([e.TaskInput({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),d("design:type",Object)],exports.SynologyDeployToPanel.prototype,"cert",void 0),l([e.TaskInput({title:"群晖授权",helper:"群晖登录授权",component:{name:"pi-access-selector",type:"synology"},required:!0}),d("design:type",String)],exports.SynologyDeployToPanel.prototype,"accessId",void 0),exports.SynologyDeployToPanel=l([e.IsTaskPlugin({name:"SynologyDeployToPanel",title:"部署证书到群晖面板",group:e.pluginGroups.other.key,desc:"Synology",default:{strategy:{runStrategy:e.RunStrategy.SkipWhenSucceed}},needPlus:!0})],exports.SynologyDeployToPanel),new exports.SynologyDeployToPanel,exports.SynologyAccess=class{baseUrl="";username="";password="";apiVersion},l([e.AccessInput({title:"群晖面板的url",component:{placeholder:"https://yourdomain:5006"},helper:"群晖面板的访问地址,例如:https://yourdomain:5006",required:!0}),d("design:type",Object)],exports.SynologyAccess.prototype,"baseUrl",void 0),l([e.AccessInput({title:"账号",component:{placeholder:"账号"},helper:"群晖面板登录账号",required:!0}),d("design:type",Object)],exports.SynologyAccess.prototype,"username",void 0),l([e.AccessInput({title:"密码",component:{placeholder:"密码"},helper:"群晖面板登录密码",required:!0,encrypt:!0}),d("design:type",Object)],exports.SynologyAccess.prototype,"password",void 0),l([e.AccessInput({title:"Api版本",component:{placeholder:"可选"},helper:"群晖的api版本,默认6.0.2"}),d("design:type",Object)],exports.SynologyAccess.prototype,"apiVersion",void 0),exports.SynologyAccess=l([e.IsAccess({name:"synology",title:"群晖登录授权",desc:""})],exports.SynologyAccess),new exports.SynologyAccess,exports.AbstractPlusTaskPlugin=p,exports.AliyunClient=class{client;logger;agent;constructor(e){this.logger=e.logger;const t=process.env.HTTPS_PROXY;t&&(this.logger.info(`use proxy:${t}`),this.agent=new n.HttpsProxyAgent(t))}async getSdk(){return(await import("@alicloud/pop-core")).default}async init(e){const t=await this.getSdk();return this.client=new t(e),this.client}async request(e,t,s={}){return s.agent=this.agent,await this.client.request(e,t,s)}},exports.SynologyClient=y,exports.mustPlus=c;
|
package/dist/bundle.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isPlus as e,AbstractTaskPlugin as t,TaskInput as s,IsTaskPlugin as o,pluginGroups as i,RunStrategy as n,AccessInput as a,IsAccess as r}from"@certd/pipeline";import{CertReader as c}from"@certd/plugin-cert";import p from"node:crypto";import d from"node:path";import{HttpsProxyAgent as l}from"https-proxy-agent";function u(){if(!e())throw new Error("此插件仅供专业版中使用")}class h extends t{setCtx(e){super.setCtx(e),u()}}function y(e,t,s,o){var i,n=arguments.length,a=n<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,s):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(e,t,s,o);else for(var r=e.length-1;r>=0;r--)(i=e[r])&&(a=(n<3?i(a):n>3?i(t,s,a):i(t,s))||a);return n>3&&a&&Object.defineProperty(t,s,a),a}function m(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}"function"==typeof SuppressedError&&SuppressedError;class g{access;http;constructor(e,t){this.access=e,this.http=t}getRequestToken(){const e=(new Date).getTime(),t=e+this.getMd5(this.access.apiSecret);return{request_token:this.getMd5(t),request_time:e}}getMd5(e){return p.createHash("md5").update(e).digest("hex")}async doRequest(e,t,s){const o=this.getRequestToken();console.log("token",o);const i={...o,...s};let n=`${this.access.panelUrl}${e}`;t&&(n=`${n}?action=${t}`);const a=await this.http.request({url:n,method:"post",headers:{"Content-Type":"application/x-www-form-urlencoded"},data:i});if(!a.status)throw new Error(a.msg);return a}}let v=class extends h{cert;accessId;async onInstance(){}async execute(){const{cert:e,accessId:t}=this,s=new c(e),o=await this.accessService.getById(t),i=this.ctx.http,n=new g(o,i),a=await n.doRequest("/config","SavePanelSSL",{privateKey:s.key,certPem:s.crt});this.logger.info(a?.msg)}};y([s({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),m("design:type",Object)],v.prototype,"cert",void 0),y([s({title:"宝塔授权",helper:"baota的接口密钥,目前测试宝塔面板本身开启ssl之后,API接口就不能用了",component:{name:"pi-access-selector",type:"baota"},required:!0}),m("design:type",String)],v.prototype,"accessId",void 0),v=y([o({name:"BaotaDeployPanelCert",title:"宝塔面板证书部署",group:i.other.key,desc:"部署宝塔面板本身的ssl证书",default:{strategy:{runStrategy:n.SkipWhenSucceed}},needPlus:!0})],v),new v;let f=class extends h{siteName;isReverseProxy=!1;cert;accessId;async onInstance(){}async execute(){const{cert:e,accessId:t}=this,s=new c(e),o=await this.accessService.getById(t),i=this.ctx.http,n=new g(o,i);if(this.logger.info(`siteName:${this.siteName}`),this.isReverseProxy){const e=await n.doRequest("/mod/proxy/com/set_ssl",null,{site_name:this.siteName,key:s.key,csr:s.crt});this.logger.info(e?.msg)}else{const e=await n.doRequest("/site","SetSSL",{type:0,siteName:this.siteName,key:s.key,csr:s.crt});this.logger.info(e?.msg)}}};y([s({title:"网站域名",component:{name:"a-input"},helper:"登录面板->网站->网站名/域名/项目名称",required:!0}),m("design:type",String)],f.prototype,"siteName",void 0),y([s({title:"是否反向代理",value:!1,component:{name:"a-switch",vModel:"checked"},helper:"该项目类型是反向代理还是其他项目",required:!0}),m("design:type",Object)],f.prototype,"isReverseProxy",void 0),y([s({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),m("design:type",Object)],f.prototype,"cert",void 0),y([s({title:"宝塔授权",helper:"baota的接口密钥",component:{name:"pi-access-selector",type:"baota"},required:!0}),m("design:type",String)],f.prototype,"accessId",void 0),f=y([o({name:"BaotaDeployWebSiteCert",title:"宝塔网站证书部署",group:i.other.key,desc:"部署宝塔管理的站点的ssl证书",default:{strategy:{runStrategy:n.SkipWhenSucceed}},needPlus:!0})],f),new f;let w=class{panelUrl="";apiSecret=""};y([a({title:"宝塔URL地址",component:{placeholder:"http://192.168.42.237:41896"},helper:"宝塔面板的url地址,例如:http://192.168.42.237:41896",required:!0}),m("design:type",Object)],w.prototype,"panelUrl",void 0),y([a({title:"接口密钥",component:{placeholder:"接口密钥"},helper:"宝塔面板设置->面板设置->API接口->接口配置->接口密钥。\n必须要加IP白名单,你可以先运行一次,报错之后会打印IP,将IP加入白名单之后再次运行即可",required:!0,encrypt:!0}),m("design:type",Object)],w.prototype,"apiSecret",void 0),w=y([r({name:"baota",title:"baota授权",desc:""})],w),new w;let S=class extends h{certId;domain;cert;accessId;async onInstance(){}async execute(){const{domain:e,certId:t,cert:s}=this;if(!e&&!t)throw new Error("证书ID和网站域名必须填写一个");const o=new c(s);t>0?await this.updateByCertId(o,t):await this.updateByDomain(o)}async updateByCertId(e,t){this.logger.info(`更新证书,证书ID:${t}`);const s=`http://user.yiduncdn.com/v1/certs/${t}`;await this.doRequest(s,"PUT",{cert:e.crt,key:e.key})}async doRequest(e,t,s){const o=await this.accessService.getById(this.accessId),{apiKey:i,apiSecret:n}=o,a=this.ctx.http,r=await a.request({url:e,method:t,headers:{"api-key":i,"api-secret":n},data:s});if(0!=r.code)throw new Error(r.msg);return r}async updateByDomain(e){const t=await this.doRequest("http://user.yiduncdn.com/v1/sites","GET",{domain:this.domain});if(0===t.data.length)throw new Error(`未找到域名相关站点:${this.domain}`);let s=null;for(const e of t.data)e.domain===this.domain&&(s=e);if(!s)throw new Error(`未找到域名匹配的站点:${this.domain}`);if(s.https_listen?.cert){const t=s.https_listen.cert;await this.updateByCertId(e,t)}else{this.logger.info(`创建证书,域名:${this.domain}`);const t="http://user.yiduncdn.com/v1/certs",o=this.domain+"_"+(new Date).getTime();await this.doRequest(t,"POST",{name:o,type:"custom",cert:e.crt,key:e.key});const i=(await this.doRequest(t,"GET",{name:o})).data[0].id,n="http://user.yiduncdn.com/v1/sites";await this.doRequest(n,"PUT",{id:s.id,https_listen:{cert:i}})}}};y([s({title:"证书ID",component:{name:"a-input-number",vModel:"value"},helper:"证书ID,在证书管理页面查看,每条记录都有证书id"}),m("design:type",Number)],S.prototype,"certId",void 0),y([s({title:"网站域名",component:{name:"a-input",vModel:"value"},helper:"网站域名和证书ID选填其中一个,填了证书ID,则忽略网站域名"}),m("design:type",Number)],S.prototype,"domain",void 0),y([s({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),m("design:type",Object)],S.prototype,"cert",void 0),y([s({title:"易盾授权",helper:"易盾CDN授权",component:{name:"pi-access-selector",type:"yidun"},required:!0}),m("design:type",String)],S.prototype,"accessId",void 0),S=y([o({name:"YidunDeployToCDN",title:"部署证书到易盾CDN",group:i.cdn.key,desc:"http://user.yiduncdn.com/",default:{strategy:{runStrategy:n.SkipWhenSucceed}},needPlus:!0})],S),new S;let I=class{apiKey="";apiSecret=""};y([a({title:"api_key",component:{placeholder:"api_key"},helper:"http://user.yiduncdn.com/console/index.html#/account/config/api,点击开启后获取",required:!0,encrypt:!0}),m("design:type",Object)],I.prototype,"apiKey",void 0),y([a({title:"api_secret",component:{placeholder:"api_secret"},helper:"http://user.yiduncdn.com/console/index.html#/account/config/api,点击开启后获取",required:!0,encrypt:!0}),m("design:type",Object)],I.prototype,"apiSecret",void 0),I=y([r({name:"yidun",title:"易盾云授权",desc:"user.yiduncdn.com"})],I),new I;let P=class{host;port;user;password;secure=!1};y([a({title:"host",component:{placeholder:"ip / 域名",name:"a-input",vModel:"value"},helper:"FTP地址",required:!0}),m("design:type",String)],P.prototype,"host",void 0),y([a({title:"host",value:21,component:{placeholder:"21",name:"a-input-number",vModel:"value"},helper:"FTP端口",required:!0}),m("design:type",String)],P.prototype,"port",void 0),y([a({title:"user",component:{placeholder:"用户名"},helper:"FTP用户名",required:!0}),m("design:type",String)],P.prototype,"user",void 0),y([a({title:"password",component:{placeholder:"密码",component:{name:"a-input-password",vModel:"value"}},encrypt:!0,helper:"FTP密码",required:!0}),m("design:type",String)],P.prototype,"password",void 0),y([a({title:"secure",value:!1,component:{name:"a-switch",vModel:"checked"},helper:"是否使用SSL",required:!0}),m("design:type",Boolean)],P.prototype,"secure",void 0),P=y([r({name:"ftp",title:"FTP授权",desc:""})],P),new P;let k=class extends h{crtPath;keyPath;pfxPath;derPath;cert;accessId;async onInstance(){}async execute(){const{cert:e,accessId:t}=this,s=new c(e);let o=null;const i=async({reader:e,tmpCrtPath:s,tmpKeyPath:i,tmpDerPath:n,tmpPfxPath:a})=>{const r=(await import("basic-ftp")).Client;o=new r,o.ftp.verbose=!0,this.logger.info("开始连接FTP");const c=await this.accessService.getById(t);await o.access(c),this.logger.info("FTP连接成功"),await this.doUpload(o,s,this.crtPath),await this.doUpload(o,i,this.keyPath),await this.doUpload(o,a,this.pfxPath),await this.doUpload(o,n,this.derPath)};try{await s.readCertFile({logger:this.logger,handle:i})}finally{o&&o.close()}this.logger.info("执行完成")}async doUpload(e,t,s){if(!s)return;const o=d.dirname(s);this.logger.info(`确保目录存在:${o}`),await e.ensureDir(o),this.logger.info(`开始上传文件${t} -> ${s}`),await e.uploadFrom(t,s)}};y([s({title:"PEM证书保存路径",helper:"需要有写入权限,路径要包含证书文件名,文件名不能用*?!等特殊符号",component:{placeholder:"/test/cert.pem"}}),m("design:type",String)],k.prototype,"crtPath",void 0),y([s({title:"私钥保存路径",helper:"需要有写入权限,路径要包含私钥文件名,文件名不能用*?!等特殊符号",component:{placeholder:"/test/cert.key"}}),m("design:type",String)],k.prototype,"keyPath",void 0),y([s({title:"PFX证书保存路径",helper:"需要有写入权限,路径要包含文件名,文件名不能用*?!等特殊符号",component:{placeholder:"/test/cert.pfx"}}),m("design:type",String)],k.prototype,"pfxPath",void 0),y([s({title:"DER证书保存路径",helper:"需要有写入权限,路径要包含文件名,文件名不能用*?!等特殊符号\n.der和.cer是相同的东西,改个后缀名即可",component:{placeholder:"/test/cert.der 或 /test/cert.cer"}}),m("design:type",String)],k.prototype,"derPath",void 0),y([s({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector",type:"CertApply"},required:!0}),m("design:type",Object)],k.prototype,"cert",void 0),y([s({title:"FTP授权",component:{name:"pi-access-selector",type:"ftp"},required:!0}),m("design:type",String)],k.prototype,"accessId",void 0),k=y([o({name:"UploadCertToFTP",title:"上传证书到FTP",group:i.host.key,desc:"将证书上传到FTP服务器",default:{strategy:{runStrategy:n.SkipWhenSucceed}},needPlus:!0})],k),new k;let q=class extends h{url;certId;domain;cert;accessId;async onInstance(){}async execute(){const{domain:e,certId:t,cert:s}=this;if(!e&&!t)throw new Error("证书ID和网站域名必须填写一个");const o=new c(s);t>0?await this.updateByCertId(o,t):await this.updateByDomain(o)}async updateByCertId(e,t){this.logger.info(`更新证书,证书ID:${t}`);const s=`${this.url}/v1/certs/${t}`;await this.doRequest(s,"PUT",{cert:e.crt,key:e.key})}async doRequest(e,t,s){const o=await this.accessService.getById(this.accessId),{apiKey:i,apiSecret:n}=o,a=this.ctx.http,r=await a.request({url:e,method:t,headers:{"api-key":i,"api-secret":n},data:s});if(0!=r.code)throw new Error(r.msg);return r}async updateByDomain(e){const t=`${this.url}/v1/sites`,s=await this.doRequest(t,"GET",{domain:this.domain});if(0===s.data.length)throw new Error(`未找到域名相关站点:${this.domain}`);let o=null;for(const e of s.data)e.domain===this.domain&&(o=e);if(!o)throw new Error(`未找到域名匹配的站点:${this.domain}`);if(o.https_listen?.cert){const t=o.https_listen.cert;await this.updateByCertId(e,t)}else{this.logger.info(`创建证书,域名:${this.domain}`);const t=`${this.url}/v1/certs`,s=this.domain+"_"+(new Date).getTime();await this.doRequest(t,"POST",{name:s,type:"custom",cert:e.crt,key:e.key});const i=(await this.doRequest(t,"GET",{name:s})).data[0].id,n=`${this.url}/v1/sites`;await this.doRequest(n,"PUT",{id:o.id,https_listen:{cert:i}})}}};y([s({title:"cdnfly系统网址",component:{name:"a-input",vModel:"value"},helper:"例如:http://demo.cdnfly.cn"}),m("design:type",String)],q.prototype,"url",void 0),y([s({title:"证书ID",component:{name:"a-input-number",vModel:"value"},helper:"证书ID,在证书管理页面查看,每条记录都有证书id"}),m("design:type",Number)],q.prototype,"certId",void 0),y([s({title:"网站域名",component:{name:"a-input",vModel:"value"},helper:"网站域名和证书ID选填其中一个,填了证书ID,则忽略网站域名"}),m("design:type",Number)],q.prototype,"domain",void 0),y([s({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),m("design:type",Object)],q.prototype,"cert",void 0),y([s({title:"cdnfly授权",helper:"cdnfly授权",component:{name:"pi-access-selector",type:"cdnfly"},required:!0}),m("design:type",String)],q.prototype,"accessId",void 0),q=y([o({name:"CdnflyDeployToCDN",title:"部署证书到cdnfly",group:i.cdn.key,desc:"cdnfly",default:{strategy:{runStrategy:n.SkipWhenSucceed}},needPlus:!0})],q),new q;let b=class{apiKey="";apiSecret=""};y([a({title:"api_key",component:{placeholder:"api_key"},helper:"登录cdnfly控制台->账户中心->Api密钥,点击开启后获取",required:!0,encrypt:!0}),m("design:type",Object)],b.prototype,"apiKey",void 0),y([a({title:"api_secret",component:{placeholder:"api_secret"},helper:"登录cdnfly控制台->账户中心->Api密钥,点击开启后获取",required:!0,encrypt:!0}),m("design:type",Object)],b.prototype,"apiSecret",void 0),b=y([r({name:"cdnfly",title:"cdnfly授权",desc:""})],b),new b;let C=class extends h{region;bucket;domainName;certName;cert;accessId;async onInstance(){}async execute(){this.logger.info("开始部署证书到阿里云OSS");const e=await this.accessService.getById(this.accessId);this.logger.info(`bucket: ${this.bucket}, region: ${this.region}, domainName: ${this.domainName}`);const t=await this.getClient(e);await this.doRequest(t,{}),this.logger.info("部署完成")}async getClient(e){return new((await import("ali-oss")).default)({accessKeyId:e.accessKeyId,accessKeySecret:e.accessKeySecret,region:this.region,authorizationV4:!0,bucket:this.bucket})}async doRequest(e,t){t=e._bucketRequestParams("POST",this.bucket,{cname:"",comp:"add"});const s=`\n <BucketCnameConfiguration>\n <Cname>\n <Domain>${this.domainName}</Domain>\n <CertificateConfiguration>\n <PrivateKey>${this.cert.key}</PrivateKey>\n <Certificate>${this.cert.crt}</Certificate>\n </CertificateConfiguration>\n </Cname>\n</BucketCnameConfiguration>`;t.content=s,t.mime="xml",t.successStatuses=[200];const o=await e.request(t);return this.checkRet(o),o}checkRet(e){if(null!=e.code)throw new Error("执行失败:"+e.Message)}};y([s({title:"大区",component:{name:"a-auto-complete",vModel:"value",options:[{value:"oss-cn-shanghai"},{value:"oss-cn-nanjing"},{value:"oss-cn-fuzhou"},{value:"oss-cn-wuhan"},{value:"oss-cn-qingdao"},{value:"oss-cn-beijing"},{value:"oss-cn-zhangjiakou"},{value:"oss-cn-huhehaote"},{value:"oss-cn-wulanchabu"},{value:"oss-cn-shenzhen"},{value:"oss-cn-heyuan"},{value:"oss-cn-guangzhou"},{value:"oss-cn-chengdu"},{value:"oss-cn-hongkong"},{value:"oss-us-west-1"},{value:"oss-us-east-1"},{value:"oss-ap-northeast-1"},{value:"oss-ap-northeast-2"},{value:"oss-ap-southeast-1"},{value:"oss-ap-southeast-2"},{value:"oss-ap-southeast-3"},{value:"oss-ap-southeast-5"},{value:"oss-ap-southeast-6"},{value:"oss-ap-southeast-7"},{value:"oss-ap-south-1"},{value:"oss-eu-central-1"},{value:"oss-eu-west-1"},{value:"oss-me-east-1"},{value:"oss-rg-china-mainland"}]},required:!0}),m("design:type",String)],C.prototype,"region",void 0),y([s({title:"Bucket",helper:"存储桶名称"}),m("design:type",String)],C.prototype,"bucket",void 0),y([s({title:"绑定的域名",helper:"你在阿里云OSS上绑定的域名,比如:certd.docmirror.cn",required:!0}),m("design:type",String)],C.prototype,"domainName",void 0),y([s({title:"证书名称",helper:"上传后将以此名称作为前缀备注"}),m("design:type",String)],C.prototype,"certName",void 0),y([s({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector",from:"CertApply"},required:!0}),m("design:type",Object)],C.prototype,"cert",void 0),y([s({title:"Access授权",helper:"阿里云授权AccessKeyId、AccessKeySecret",component:{name:"pi-access-selector",type:"aliyun"},required:!0}),m("design:type",String)],C.prototype,"accessId",void 0),C=y([o({name:"DeployCertToAliyunOSS",title:"部署证书至阿里云OSS",group:i.aliyun.key,desc:"自动部署域名证书至阿里云OSS",needPlus:!0,default:{strategy:{runStrategy:n.SkipWhenSucceed}}})],C),new C;let x=class{accessKeyId="";accessKeySecret=""};y([a({title:"accessKeyId",component:{placeholder:"accessKeyId"},helper:"登录阿里云控制台->AccessKey管理页面获取。",required:!0}),m("design:type",Object)],x.prototype,"accessKeyId",void 0),y([a({title:"accessKeySecret",component:{placeholder:"accessKeySecret"},required:!0,encrypt:!0,helper:"注意:证书申请需要dns解析权限;其他阿里云插件,需要对应的权限,比如证书上传需要证书管理权限;嫌麻烦就用主账号的全量权限的accessKey"}),m("design:type",Object)],x.prototype,"accessKeySecret",void 0),x=y([r({name:"aliyun",title:"阿里云授权",desc:""})],x),new x;class R{client;logger;agent;constructor(e){this.logger=e.logger;const t=process.env.HTTPS_PROXY;t&&(this.logger.info(`use proxy:${t}`),this.agent=new l(t))}async getSdk(){return(await import("@alicloud/pop-core")).default}async init(e){const t=await this.getSdk();return this.client=new t(e),this.client}async request(e,t,s={}){return s.agent=this.agent,await this.client.request(e,t,s)}}export{h as AbstractPlusTaskPlugin,x as AliyunAccess,R as AliyunClient,w as BaotaAccess,v as BaotaDeployPanelCertPlugin,f as BaotaDeployWebSiteCertPlugin,b as CdnflyAccess,q as CdnflyDeployToCDNPlugin,C as DeployCertToAliyunOSS,P as FtpAccess,k as UploadCertToFTPPlugin,I as YidunAccess,S as YidunDeployToCDNPlugin,u as mustPlus};
|
|
1
|
+
import{isPlus as e,AbstractTaskPlugin as t,TaskInput as s,IsTaskPlugin as o,pluginGroups as i,RunStrategy as r,AccessInput as n,IsAccess as a}from"@certd/pipeline";import{CertReader as c}from"@certd/plugin-cert";import p from"node:crypto";import d from"node:path";import{HttpsProxyAgent as l}from"https-proxy-agent";import h from"querystring";import u from"fs";import y from"form-data";function m(){if(!e())throw new Error("此插件仅供专业版中使用")}class g extends t{setCtx(e){super.setCtx(e),m()}}function f(e,t,s,o){var i,r=arguments.length,n=r<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,s):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,s,o);else for(var a=e.length-1;a>=0;a--)(i=e[a])&&(n=(r<3?i(n):r>3?i(t,s,n):i(t,s))||n);return r>3&&n&&Object.defineProperty(t,s,n),n}function v(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}"function"==typeof SuppressedError&&SuppressedError;class w{access;http;constructor(e,t){this.access=e,this.http=t}getRequestToken(){const e=(new Date).getTime(),t=e+this.getMd5(this.access.apiSecret);return{request_token:this.getMd5(t),request_time:e}}getMd5(e){return p.createHash("md5").update(e).digest("hex")}async doRequest(e,t,s){const o=this.getRequestToken();console.log("token",o);const i={...o,...s};let r=`${this.access.panelUrl}${e}`;t&&(r=`${r}?action=${t}`);const n=await this.http.request({url:r,method:"post",headers:{"Content-Type":"application/x-www-form-urlencoded"},data:i});if(!n.status)throw new Error(n.msg);return n}}let S=class extends g{cert;accessId;async onInstance(){}async execute(){const{cert:e,accessId:t}=this,s=new c(e),o=await this.accessService.getById(t),i=this.ctx.http,r=new w(o,i),n=await r.doRequest("/config","SavePanelSSL",{privateKey:s.key,certPem:s.crt});this.logger.info(n?.msg)}};f([s({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),v("design:type",Object)],S.prototype,"cert",void 0),f([s({title:"宝塔授权",helper:"baota的接口密钥,目前测试宝塔面板本身开启ssl之后,API接口就不能用了",component:{name:"pi-access-selector",type:"baota"},required:!0}),v("design:type",String)],S.prototype,"accessId",void 0),S=f([o({name:"BaotaDeployPanelCert",title:"宝塔面板证书部署",group:i.other.key,desc:"部署宝塔面板本身的ssl证书",default:{strategy:{runStrategy:r.SkipWhenSucceed}},needPlus:!0})],S),new S;let I=class extends g{siteName;isReverseProxy=!1;cert;accessId;async onInstance(){}async execute(){const{cert:e,accessId:t}=this,s=new c(e),o=await this.accessService.getById(t),i=this.ctx.http,r=new w(o,i);if(this.logger.info(`siteName:${this.siteName}`),this.isReverseProxy){const e=await r.doRequest("/mod/proxy/com/set_ssl",null,{site_name:this.siteName,key:s.key,csr:s.crt});this.logger.info(e?.msg)}else{const e=await r.doRequest("/site","SetSSL",{type:0,siteName:this.siteName,key:s.key,csr:s.crt});this.logger.info(e?.msg)}}};f([s({title:"网站域名",component:{name:"a-input"},helper:"登录面板->网站->网站名/域名/项目名称",required:!0}),v("design:type",String)],I.prototype,"siteName",void 0),f([s({title:"是否反向代理",value:!1,component:{name:"a-switch",vModel:"checked"},helper:"该项目类型是反向代理还是其他项目",required:!0}),v("design:type",Object)],I.prototype,"isReverseProxy",void 0),f([s({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),v("design:type",Object)],I.prototype,"cert",void 0),f([s({title:"宝塔授权",helper:"baota的接口密钥",component:{name:"pi-access-selector",type:"baota"},required:!0}),v("design:type",String)],I.prototype,"accessId",void 0),I=f([o({name:"BaotaDeployWebSiteCert",title:"宝塔网站证书部署",group:i.other.key,desc:"部署宝塔管理的站点的ssl证书",default:{strategy:{runStrategy:r.SkipWhenSucceed}},needPlus:!0})],I),new I;let P=class{panelUrl="";apiSecret=""};f([n({title:"宝塔URL地址",component:{placeholder:"http://192.168.42.237:41896"},helper:"宝塔面板的url地址,例如:http://192.168.42.237:41896",required:!0}),v("design:type",Object)],P.prototype,"panelUrl",void 0),f([n({title:"接口密钥",component:{placeholder:"接口密钥"},helper:"宝塔面板设置->面板设置->API接口->接口配置->接口密钥。\n必须要加IP白名单,你可以先运行一次,报错之后会打印IP,将IP加入白名单之后再次运行即可",required:!0,encrypt:!0}),v("design:type",Object)],P.prototype,"apiSecret",void 0),P=f([a({name:"baota",title:"baota授权",desc:""})],P),new P;let q=class extends g{certId;domain;cert;accessId;async onInstance(){}async execute(){const{domain:e,certId:t,cert:s}=this;if(!e&&!t)throw new Error("证书ID和网站域名必须填写一个");const o=new c(s);t>0?await this.updateByCertId(o,t):await this.updateByDomain(o)}async updateByCertId(e,t){this.logger.info(`更新证书,证书ID:${t}`);const s=`http://user.yiduncdn.com/v1/certs/${t}`;await this.doRequest(s,"PUT",{cert:e.crt,key:e.key})}async doRequest(e,t,s){const o=await this.accessService.getById(this.accessId),{apiKey:i,apiSecret:r}=o,n=this.ctx.http,a=await n.request({url:e,method:t,headers:{"api-key":i,"api-secret":r},data:s});if(0!=a.code)throw new Error(a.msg);return a}async updateByDomain(e){const t=await this.doRequest("http://user.yiduncdn.com/v1/sites","GET",{domain:this.domain});if(0===t.data.length)throw new Error(`未找到域名相关站点:${this.domain}`);let s=null;for(const e of t.data)e.domain===this.domain&&(s=e);if(!s)throw new Error(`未找到域名匹配的站点:${this.domain}`);if(s.https_listen?.cert){const t=s.https_listen.cert;await this.updateByCertId(e,t)}else{this.logger.info(`创建证书,域名:${this.domain}`);const t="http://user.yiduncdn.com/v1/certs",o=this.domain+"_"+(new Date).getTime();await this.doRequest(t,"POST",{name:o,type:"custom",cert:e.crt,key:e.key});const i=(await this.doRequest(t,"GET",{name:o})).data[0].id,r="http://user.yiduncdn.com/v1/sites";await this.doRequest(r,"PUT",{id:s.id,https_listen:{cert:i}})}}};f([s({title:"证书ID",component:{name:"a-input-number",vModel:"value"},helper:"证书ID,在证书管理页面查看,每条记录都有证书id"}),v("design:type",Number)],q.prototype,"certId",void 0),f([s({title:"网站域名",component:{name:"a-input",vModel:"value"},helper:"网站域名和证书ID选填其中一个,填了证书ID,则忽略网站域名"}),v("design:type",Number)],q.prototype,"domain",void 0),f([s({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),v("design:type",Object)],q.prototype,"cert",void 0),f([s({title:"易盾授权",helper:"易盾CDN授权",component:{name:"pi-access-selector",type:"yidun"},required:!0}),v("design:type",String)],q.prototype,"accessId",void 0),q=f([o({name:"YidunDeployToCDN",title:"部署证书到易盾CDN",group:i.cdn.key,desc:"http://user.yiduncdn.com/",default:{strategy:{runStrategy:r.SkipWhenSucceed}},needPlus:!0})],q),new q;let k=class{apiKey="";apiSecret=""};f([n({title:"api_key",component:{placeholder:"api_key"},helper:"http://user.yiduncdn.com/console/index.html#/account/config/api,点击开启后获取",required:!0,encrypt:!0}),v("design:type",Object)],k.prototype,"apiKey",void 0),f([n({title:"api_secret",component:{placeholder:"api_secret"},helper:"http://user.yiduncdn.com/console/index.html#/account/config/api,点击开启后获取",required:!0,encrypt:!0}),v("design:type",Object)],k.prototype,"apiSecret",void 0),k=f([a({name:"yidun",title:"易盾云授权",desc:"user.yiduncdn.com"})],k),new k;let b=class{host;port;user;password;secure=!1};f([n({title:"host",component:{placeholder:"ip / 域名",name:"a-input",vModel:"value"},helper:"FTP地址",required:!0}),v("design:type",String)],b.prototype,"host",void 0),f([n({title:"host",value:21,component:{placeholder:"21",name:"a-input-number",vModel:"value"},helper:"FTP端口",required:!0}),v("design:type",String)],b.prototype,"port",void 0),f([n({title:"user",component:{placeholder:"用户名"},helper:"FTP用户名",required:!0}),v("design:type",String)],b.prototype,"user",void 0),f([n({title:"password",component:{placeholder:"密码",component:{name:"a-input-password",vModel:"value"}},encrypt:!0,helper:"FTP密码",required:!0}),v("design:type",String)],b.prototype,"password",void 0),f([n({title:"secure",value:!1,component:{name:"a-switch",vModel:"checked"},helper:"是否使用SSL",required:!0}),v("design:type",Boolean)],b.prototype,"secure",void 0),b=f([a({name:"ftp",title:"FTP授权",desc:""})],b),new b;let C=class extends g{crtPath;keyPath;pfxPath;derPath;cert;accessId;async onInstance(){}async execute(){const{cert:e,accessId:t}=this,s=new c(e);let o=null;const i=async({reader:e,tmpCrtPath:s,tmpKeyPath:i,tmpDerPath:r,tmpPfxPath:n})=>{const a=(await import("basic-ftp")).Client;o=new a,o.ftp.verbose=!0,this.logger.info("开始连接FTP");const c=await this.accessService.getById(t);await o.access(c),this.logger.info("FTP连接成功"),await this.doUpload(o,s,this.crtPath),await this.doUpload(o,i,this.keyPath),await this.doUpload(o,n,this.pfxPath),await this.doUpload(o,r,this.derPath)};try{await s.readCertFile({logger:this.logger,handle:i})}finally{o&&o.close()}this.logger.info("执行完成")}async doUpload(e,t,s){if(!s)return;const o=d.dirname(s);this.logger.info(`确保目录存在:${o}`),await e.ensureDir(o),this.logger.info(`开始上传文件${t} -> ${s}`),await e.uploadFrom(t,s)}};f([s({title:"PEM证书保存路径",helper:"需要有写入权限,路径要包含证书文件名,文件名不能用*?!等特殊符号",component:{placeholder:"/test/cert.pem"}}),v("design:type",String)],C.prototype,"crtPath",void 0),f([s({title:"私钥保存路径",helper:"需要有写入权限,路径要包含私钥文件名,文件名不能用*?!等特殊符号",component:{placeholder:"/test/cert.key"}}),v("design:type",String)],C.prototype,"keyPath",void 0),f([s({title:"PFX证书保存路径",helper:"需要有写入权限,路径要包含文件名,文件名不能用*?!等特殊符号",component:{placeholder:"/test/cert.pfx"}}),v("design:type",String)],C.prototype,"pfxPath",void 0),f([s({title:"DER证书保存路径",helper:"需要有写入权限,路径要包含文件名,文件名不能用*?!等特殊符号\n.der和.cer是相同的东西,改个后缀名即可",component:{placeholder:"/test/cert.der 或 /test/cert.cer"}}),v("design:type",String)],C.prototype,"derPath",void 0),f([s({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector",type:"CertApply"},required:!0}),v("design:type",Object)],C.prototype,"cert",void 0),f([s({title:"FTP授权",component:{name:"pi-access-selector",type:"ftp"},required:!0}),v("design:type",String)],C.prototype,"accessId",void 0),C=f([o({name:"UploadCertToFTP",title:"上传证书到FTP",group:i.host.key,desc:"将证书上传到FTP服务器",default:{strategy:{runStrategy:r.SkipWhenSucceed}},needPlus:!0})],C),new C;let T=class extends g{url;certId;domain;cert;accessId;async onInstance(){}async execute(){const{domain:e,certId:t,cert:s}=this;if(!e&&!t)throw new Error("证书ID和网站域名必须填写一个");const o=new c(s);t>0?await this.updateByCertId(o,t):await this.updateByDomain(o)}async updateByCertId(e,t){this.logger.info(`更新证书,证书ID:${t}`);const s=`${this.url}/v1/certs/${t}`;await this.doRequest(s,"PUT",{cert:e.crt,key:e.key})}async doRequest(e,t,s){const o=await this.accessService.getById(this.accessId),{apiKey:i,apiSecret:r}=o,n=this.ctx.http,a=await n.request({url:e,method:t,headers:{"api-key":i,"api-secret":r},data:s});if(0!=a.code)throw new Error(a.msg);return a}async updateByDomain(e){const t=`${this.url}/v1/sites`,s=await this.doRequest(t,"GET",{domain:this.domain});if(0===s.data.length)throw new Error(`未找到域名相关站点:${this.domain}`);let o=null;for(const e of s.data)e.domain===this.domain&&(o=e);if(!o)throw new Error(`未找到域名匹配的站点:${this.domain}`);if(o.https_listen?.cert){const t=o.https_listen.cert;await this.updateByCertId(e,t)}else{this.logger.info(`创建证书,域名:${this.domain}`);const t=`${this.url}/v1/certs`,s=this.domain+"_"+(new Date).getTime();await this.doRequest(t,"POST",{name:s,type:"custom",cert:e.crt,key:e.key});const i=(await this.doRequest(t,"GET",{name:s})).data[0].id,r=`${this.url}/v1/sites`;await this.doRequest(r,"PUT",{id:o.id,https_listen:{cert:i}})}}};f([s({title:"cdnfly系统网址",component:{name:"a-input",vModel:"value"},helper:"例如:http://demo.cdnfly.cn"}),v("design:type",String)],T.prototype,"url",void 0),f([s({title:"证书ID",component:{name:"a-input-number",vModel:"value"},helper:"证书ID,在证书管理页面查看,每条记录都有证书id"}),v("design:type",Number)],T.prototype,"certId",void 0),f([s({title:"网站域名",component:{name:"a-input",vModel:"value"},helper:"网站域名和证书ID选填其中一个,填了证书ID,则忽略网站域名"}),v("design:type",Number)],T.prototype,"domain",void 0),f([s({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),v("design:type",Object)],T.prototype,"cert",void 0),f([s({title:"cdnfly授权",helper:"cdnfly授权",component:{name:"pi-access-selector",type:"cdnfly"},required:!0}),v("design:type",String)],T.prototype,"accessId",void 0),T=f([o({name:"CdnflyDeployToCDN",title:"部署证书到cdnfly",group:i.cdn.key,desc:"cdnfly",default:{strategy:{runStrategy:r.SkipWhenSucceed}},needPlus:!0})],T),new T;let R=class{apiKey="";apiSecret=""};f([n({title:"api_key",component:{placeholder:"api_key"},helper:"登录cdnfly控制台->账户中心->Api密钥,点击开启后获取",required:!0,encrypt:!0}),v("design:type",Object)],R.prototype,"apiKey",void 0),f([n({title:"api_secret",component:{placeholder:"api_secret"},helper:"登录cdnfly控制台->账户中心->Api密钥,点击开启后获取",required:!0,encrypt:!0}),v("design:type",Object)],R.prototype,"apiSecret",void 0),R=f([a({name:"cdnfly",title:"cdnfly授权",desc:""})],R),new R;let x=class extends g{region;bucket;domainName;certName;cert;accessId;async onInstance(){}async execute(){this.logger.info("开始部署证书到阿里云OSS");const e=await this.accessService.getById(this.accessId);this.logger.info(`bucket: ${this.bucket}, region: ${this.region}, domainName: ${this.domainName}`);const t=await this.getClient(e);await this.doRequest(t,{}),this.logger.info("部署完成")}async getClient(e){return new((await import("ali-oss")).default)({accessKeyId:e.accessKeyId,accessKeySecret:e.accessKeySecret,region:this.region,authorizationV4:!0,bucket:this.bucket})}async doRequest(e,t){t=e._bucketRequestParams("POST",this.bucket,{cname:"",comp:"add"});const s=`\n <BucketCnameConfiguration>\n <Cname>\n <Domain>${this.domainName}</Domain>\n <CertificateConfiguration>\n <PrivateKey>${this.cert.key}</PrivateKey>\n <Certificate>${this.cert.crt}</Certificate>\n </CertificateConfiguration>\n </Cname>\n</BucketCnameConfiguration>`;t.content=s,t.mime="xml",t.successStatuses=[200];const o=await e.request(t);return this.checkRet(o),o}checkRet(e){if(null!=e.code)throw new Error("执行失败:"+e.Message)}};f([s({title:"大区",component:{name:"a-auto-complete",vModel:"value",options:[{value:"oss-cn-shanghai"},{value:"oss-cn-nanjing"},{value:"oss-cn-fuzhou"},{value:"oss-cn-wuhan"},{value:"oss-cn-qingdao"},{value:"oss-cn-beijing"},{value:"oss-cn-zhangjiakou"},{value:"oss-cn-huhehaote"},{value:"oss-cn-wulanchabu"},{value:"oss-cn-shenzhen"},{value:"oss-cn-heyuan"},{value:"oss-cn-guangzhou"},{value:"oss-cn-chengdu"},{value:"oss-cn-hongkong"},{value:"oss-us-west-1"},{value:"oss-us-east-1"},{value:"oss-ap-northeast-1"},{value:"oss-ap-northeast-2"},{value:"oss-ap-southeast-1"},{value:"oss-ap-southeast-2"},{value:"oss-ap-southeast-3"},{value:"oss-ap-southeast-5"},{value:"oss-ap-southeast-6"},{value:"oss-ap-southeast-7"},{value:"oss-ap-south-1"},{value:"oss-eu-central-1"},{value:"oss-eu-west-1"},{value:"oss-me-east-1"},{value:"oss-rg-china-mainland"}]},required:!0}),v("design:type",String)],x.prototype,"region",void 0),f([s({title:"Bucket",helper:"存储桶名称"}),v("design:type",String)],x.prototype,"bucket",void 0),f([s({title:"绑定的域名",helper:"你在阿里云OSS上绑定的域名,比如:certd.docmirror.cn",required:!0}),v("design:type",String)],x.prototype,"domainName",void 0),f([s({title:"证书名称",helper:"上传后将以此名称作为前缀备注"}),v("design:type",String)],x.prototype,"certName",void 0),f([s({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector",from:"CertApply"},required:!0}),v("design:type",Object)],x.prototype,"cert",void 0),f([s({title:"Access授权",helper:"阿里云授权AccessKeyId、AccessKeySecret",component:{name:"pi-access-selector",type:"aliyun"},required:!0}),v("design:type",String)],x.prototype,"accessId",void 0),x=f([o({name:"DeployCertToAliyunOSS",title:"部署证书至阿里云OSS",group:i.aliyun.key,desc:"自动部署域名证书至阿里云OSS",needPlus:!0,default:{strategy:{runStrategy:r.SkipWhenSucceed}}})],x),new x;let O=class{accessKeyId="";accessKeySecret=""};f([n({title:"accessKeyId",component:{placeholder:"accessKeyId"},helper:"登录阿里云控制台->AccessKey管理页面获取。",required:!0}),v("design:type",Object)],O.prototype,"accessKeyId",void 0),f([n({title:"accessKeySecret",component:{placeholder:"accessKeySecret"},required:!0,encrypt:!0,helper:"注意:证书申请需要dns解析权限;其他阿里云插件,需要对应的权限,比如证书上传需要证书管理权限;嫌麻烦就用主账号的全量权限的accessKey"}),v("design:type",Object)],O.prototype,"accessKeySecret",void 0),O=f([a({name:"aliyun",title:"阿里云授权",desc:""})],O),new O;class ${client;logger;agent;constructor(e){this.logger=e.logger;const t=process.env.HTTPS_PROXY;t&&(this.logger.info(`use proxy:${t}`),this.agent=new l(t))}async getSdk(){return(await import("@alicloud/pop-core")).default}async init(e){const t=await this.getSdk();return this.client=new t(e),this.client}async request(e,t,s={}){return s.agent=this.agent,await this.client.request(e,t,s)}}class D{access;http;logger;token;constructor(e,t,s){this.access=e,this.http=t,this.logger=s}async doLogin(){const e=this.access,t=await this.http.request({url:`${e.baseUrl}/webapi/entry.cgi`,method:"GET",params:{api:"SYNO.API.Auth",version:6,method:"login",account:e.username,passwd:e.password,session:"Certd",format:"sid",enable_syno_token:"yes"}});if(!t.success)throw new Error(`登录失败: ${t.error}`);return this.logger.info("登录成功"),this.token=t.data,this.token}async doRequest(e){const t=this.token.sid,s=e.method||"POST",o={...e.apiParams,_sid:t,...e.params,SynoToken:this.token.synotoken},i=await this.http.request({url:`${this.access.baseUrl}/webapi/entry.cgi?${h.stringify(o)}`,method:s,data:e.data,headers:e.headers});if(!i.success)throw new Error(`API 调用失败: ${JSON.stringify(i.error)}`);return i.data}async getCertList(){return this.logger.info("获取证书列表"),await this.doRequest({method:"GET",apiParams:{api:"SYNO.Core.Certificate.CRT",version:1,method:"list"}})}async getInfo(){return this.logger.info("获取信息"),await this.doRequest({method:"GET",apiParams:{api:"SYNO.API.Info",version:1,method:"query"}})}}let N=class extends g{certName;cert;accessId;async onInstance(){}async execute(){const e=await this.accessService.getById(this.accessId),t=new D(e,this.ctx.http,this.ctx.logger);await t.doLogin();const s=(await t.getCertList()).certificates.find((e=>e.desc===this.certName||e.subject.common_name===this.certName));if(!s)throw new Error(`未找到证书: ${this.certName}`);this.logger.info(`找到证书: ${s.id}`),await this.updateCertToPanel(t,s)}async updateCertToPanel(e,t){this.logger.info(`更新证书:${t.id}`);return new c(this.cert).readCertFile({logger:this.logger,handle:async s=>{const o=new y,{tmpCrtPath:i,tmpKeyPath:r}=s;return this.logger.info(`上传证书:${i},${r}`),o.append("key",u.createReadStream(r)),o.append("cert",u.createReadStream(i)),o.append("id",t.id),o.append("desc",t.desc),console.log(JSON.stringify(o.getHeaders())),await e.doRequest({method:"POST",apiParams:{api:"SYNO.Core.Certificate",version:1,method:"import"},data:o,headers:{...o.getHeaders()}})}})}};f([s({title:"证书描述/域名",component:{name:"a-input",vModel:"value",placeholder:"请输入证书描述或者证书域名"},required:!0,helper:"证书描述或者证书域名,默认证书域名为synology\n建议给证书设置描述,查找证书更准确"}),v("design:type",String)],N.prototype,"certName",void 0),f([s({title:"域名证书",helper:"请选择前置任务输出的域名证书",component:{name:"pi-output-selector"},required:!0}),v("design:type",Object)],N.prototype,"cert",void 0),f([s({title:"群晖授权",helper:"群晖登录授权",component:{name:"pi-access-selector",type:"synology"},required:!0}),v("design:type",String)],N.prototype,"accessId",void 0),N=f([o({name:"SynologyDeployToPanel",title:"部署证书到群晖面板",group:i.other.key,desc:"Synology",default:{strategy:{runStrategy:r.SkipWhenSucceed}},needPlus:!0})],N),new N;let j=class{baseUrl="";username="";password="";apiVersion};f([n({title:"群晖面板的url",component:{placeholder:"https://yourdomain:5006"},helper:"群晖面板的访问地址,例如:https://yourdomain:5006",required:!0}),v("design:type",Object)],j.prototype,"baseUrl",void 0),f([n({title:"账号",component:{placeholder:"账号"},helper:"群晖面板登录账号",required:!0}),v("design:type",Object)],j.prototype,"username",void 0),f([n({title:"密码",component:{placeholder:"密码"},helper:"群晖面板登录密码",required:!0,encrypt:!0}),v("design:type",Object)],j.prototype,"password",void 0),f([n({title:"Api版本",component:{placeholder:"可选"},helper:"群晖的api版本,默认6.0.2"}),v("design:type",Object)],j.prototype,"apiVersion",void 0),j=f([a({name:"synology",title:"群晖登录授权",desc:""})],j),new j;export{g as AbstractPlusTaskPlugin,O as AliyunAccess,$ as AliyunClient,P as BaotaAccess,S as BaotaDeployPanelCertPlugin,I as BaotaDeployWebSiteCertPlugin,R as CdnflyAccess,T as CdnflyDeployToCDNPlugin,x as DeployCertToAliyunOSS,b as FtpAccess,j as SynologyAccess,D as SynologyClient,N as SynologyDeployToPanel,C as UploadCertToFTPPlugin,k as YidunAccess,q as YidunDeployToCDNPlugin,m as mustPlus};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type RPCClient from "@alicloud/pop-core";
|
|
2
|
+
import { AliyunAccess } from "../../access/index.js";
|
|
3
|
+
import { AbstractPlusTaskPlugin } from "../../../lib";
|
|
4
|
+
export declare class DeployCertToAliyunDCDN extends AbstractPlusTaskPlugin {
|
|
5
|
+
domainName: string;
|
|
6
|
+
certName: string;
|
|
7
|
+
cert: string;
|
|
8
|
+
accessId: string;
|
|
9
|
+
onInstance(): Promise<void>;
|
|
10
|
+
execute(): Promise<void>;
|
|
11
|
+
getClient(access: AliyunAccess): Promise<RPCClient>;
|
|
12
|
+
buildParams(): Promise<{
|
|
13
|
+
RegionId: string;
|
|
14
|
+
DomainName: string;
|
|
15
|
+
ServerCertificateStatus: string;
|
|
16
|
+
CertName: string;
|
|
17
|
+
CertType: string;
|
|
18
|
+
ServerCertificate: any;
|
|
19
|
+
PrivateKey: any;
|
|
20
|
+
}>;
|
|
21
|
+
doRequest(client: RPCClient, params: any): Promise<void>;
|
|
22
|
+
checkRet(ret: any): void;
|
|
23
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { AxiosInstance } from "axios";
|
|
2
1
|
import { BaotaAccess } from "../access.js";
|
|
2
|
+
import { HttpClient } from "@certd/pipeline";
|
|
3
3
|
export declare class BaotaClient {
|
|
4
4
|
access: BaotaAccess;
|
|
5
|
-
http:
|
|
6
|
-
constructor(access: BaotaAccess, http:
|
|
5
|
+
http: HttpClient;
|
|
6
|
+
constructor(access: BaotaAccess, http: HttpClient);
|
|
7
7
|
getRequestToken(): {
|
|
8
8
|
request_token: string;
|
|
9
9
|
request_time: number;
|
package/dist/d/index.d.ts
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { SynologyAccess } from "./access";
|
|
2
|
+
import { HttpClient, ILogger } from "@certd/pipeline";
|
|
3
|
+
export type SynologyAccessToken = {
|
|
4
|
+
sid: string;
|
|
5
|
+
synotoken: string;
|
|
6
|
+
};
|
|
7
|
+
export type SynologyRequest = {
|
|
8
|
+
method?: string;
|
|
9
|
+
apiParams: {
|
|
10
|
+
api: string;
|
|
11
|
+
version: number;
|
|
12
|
+
method: string;
|
|
13
|
+
};
|
|
14
|
+
params?: any;
|
|
15
|
+
data?: any;
|
|
16
|
+
form?: any;
|
|
17
|
+
headers?: any;
|
|
18
|
+
useSynoToken?: boolean;
|
|
19
|
+
};
|
|
20
|
+
export declare class SynologyClient {
|
|
21
|
+
access: SynologyAccess;
|
|
22
|
+
http: HttpClient;
|
|
23
|
+
logger: ILogger;
|
|
24
|
+
token: SynologyAccessToken;
|
|
25
|
+
constructor(access: SynologyAccess, http: HttpClient, logger: ILogger);
|
|
26
|
+
doLogin(): Promise<SynologyAccessToken>;
|
|
27
|
+
doRequest(req: SynologyRequest): Promise<any>;
|
|
28
|
+
getCertList(): Promise<any>;
|
|
29
|
+
getInfo(): Promise<any>;
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./plugin-deploy-to-panel.js";
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CertInfo } from "@certd/plugin-cert";
|
|
2
|
+
import { AbstractPlusTaskPlugin } from "../../lib/index.js";
|
|
3
|
+
import { SynologyClient } from "../client";
|
|
4
|
+
export declare class SynologyDeployToPanel extends AbstractPlusTaskPlugin {
|
|
5
|
+
certName: string;
|
|
6
|
+
cert: CertInfo;
|
|
7
|
+
accessId: string;
|
|
8
|
+
onInstance(): Promise<void>;
|
|
9
|
+
execute(): Promise<void>;
|
|
10
|
+
updateCertToPanel(client: SynologyClient, certItem: any): Promise<void>;
|
|
11
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@certd/plugin-plus",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.24.
|
|
4
|
+
"version": "1.24.4",
|
|
5
5
|
"main": "./dist/bundle.mjs",
|
|
6
6
|
"module": "./dist/bundle.mjs",
|
|
7
7
|
"types": "./dist/d/index.d.ts",
|
|
@@ -14,15 +14,15 @@
|
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@alicloud/pop-core": "^1.7.10",
|
|
17
|
-
"@certd/pipeline": "^1.24.
|
|
18
|
-
"@certd/plugin-cert": "^1.24.
|
|
17
|
+
"@certd/pipeline": "^1.24.4",
|
|
18
|
+
"@certd/plugin-cert": "^1.24.4",
|
|
19
19
|
"@rollup/plugin-json": "^6.0.0",
|
|
20
20
|
"@rollup/plugin-terser": "^0.4.3",
|
|
21
21
|
"@rollup/plugin-typescript": "^11.0.0",
|
|
22
22
|
"@types/ali-oss": "^6.16.11",
|
|
23
23
|
"@types/chai": "^4.3.10",
|
|
24
24
|
"@types/mocha": "^10.0.7",
|
|
25
|
-
"@types/node": "
|
|
25
|
+
"@types/node": "^18",
|
|
26
26
|
"ali-oss": "^6.21.0",
|
|
27
27
|
"basic-ftp": "^5.0.5",
|
|
28
28
|
"chai": "4.3.10",
|
|
@@ -32,14 +32,16 @@
|
|
|
32
32
|
"eslint-plugin-import": "^2.27.5",
|
|
33
33
|
"eslint-plugin-node": "^11.1.0",
|
|
34
34
|
"eslint-plugin-prettier": "^4.2.1",
|
|
35
|
+
"form-data": "^4.0.0",
|
|
35
36
|
"mocha": "^10.2.0",
|
|
36
37
|
"rollup": "^3.7.4",
|
|
37
38
|
"ts-node": "^10.9.1",
|
|
38
39
|
"tslib": "^2.5.2",
|
|
39
40
|
"typescript": "^5.0.4"
|
|
40
41
|
},
|
|
41
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "6fe2d2c3288b698e9cbdc91725abcbb072278fab",
|
|
42
43
|
"dependencies": {
|
|
43
|
-
"https-proxy-agent": "^7.0.5"
|
|
44
|
+
"https-proxy-agent": "^7.0.5",
|
|
45
|
+
"syno": "^2.2.0"
|
|
44
46
|
}
|
|
45
47
|
}
|
package/rollup.config.mjs
CHANGED
|
@@ -35,5 +35,5 @@ export default {
|
|
|
35
35
|
},
|
|
36
36
|
}),
|
|
37
37
|
],
|
|
38
|
-
external: ["vue", "lodash-es", "dayjs", "log4js", "@midwayjs/core", "@certd/pipeline", "axios", "basic-ftp","@alicloud/pop-core","ali-oss","https-proxy-agent"],
|
|
38
|
+
external: ["vue", "lodash-es", "dayjs", "log4js", "@midwayjs/core", "@certd/pipeline", "axios", "basic-ftp","@alicloud/pop-core","ali-oss","https-proxy-agent","form-data","syno"],
|
|
39
39
|
};
|