perf: 新增部署1panel面板证书插件

This commit is contained in:
xiaojunnuo
2026-01-05 00:20:18 +08:00
parent 8374a4f5bf
commit 4243622414
5 changed files with 244 additions and 8 deletions

View File

@@ -1,5 +1,5 @@
# 任务插件
`109` 款任务插件
`110` 款任务插件
## 1. 证书申请
| 序号 | 名称 | 说明 |
@@ -63,10 +63,11 @@
| 12.| **K8S-Ingress 证书部署** | 部署证书到k8s的Ingress |
| 13.| **K8S-Apply自定义yaml** | apply自定义yaml到k8s |
| 14.| **1Panel-部署证书到1Panel** | 更新1Panel的证书 |
| 15.| **Plesk-部署Plesk网站证书** | |
| 16.| **雷池-更新证书** | 更新长亭雷池WAF的证书 |
| 17.| **lucky-更新Lucky证书** | |
| 18.| **uniCloud-部署到服务空间** | 部署到服务空间 |
| 15.| **1Panel-部署面板证书** | 更新1Panel的面板证书 |
| 16.| **Plesk-部署Plesk网站证书** | |
| 17.| **雷池-更新证书** | 更新长亭雷池WAF的证书 |
| 18.| **lucky-更新Lucky证书** | |
| 19.| **uniCloud-部署到服务空间** | 部署到服务空间 |
## 5. 阿里云
| 序号 | 名称 | 说明 |

View File

@@ -15,19 +15,21 @@ input:
required: true
encrypt: false
publicKey:
title: 公钥
title: 证书公钥
component:
name: a-textarea
rows: 3
placeholder: MIIBIjANBg...
placeholder: '-----BEGIN CERTIFICATE-----'
helper: 微信商户平台—>账户设置—>API安全—>验证商户身份—>商户API证书—>管理证书—>apiclient_cert.pem
required: true
encrypt: true
privateKey:
title: 私钥
component:
placeholder: MIIEvQIBADANB...
placeholder: '-----BEGIN PRIVATE KEY-----'
name: a-textarea
rows: 3
helper: 证书私钥 apiclient_key.pem
required: true
encrypt: true
key:

View File

@@ -0,0 +1,77 @@
showRunStrategy: false
default:
strategy:
runStrategy: 1
name: 1PanelDeployToPanel
title: 1Panel-部署面板证书
icon: svg:icon-onepanel
desc: 更新1Panel的面板证书
group: panel
needPlus: false
input:
cert:
title: 域名证书
helper: 请选择前置任务输出的域名证书
component:
name: output-selector
from:
- ':cert:'
required: true
order: 0
certDomains:
title: 当前证书域名
component:
name: cert-domains-getter
mergeScript: |2-
return {
component:{
inputKey: ctx.compute(({form})=>{
return form.cert
}),
}
}
template: false
required: true
order: 0
accessId:
title: 1Panel授权
helper: 1Panel授权
component:
name: access-selector
type: 1panel
required: true
order: 0
currentNode:
title: 1Panel节点
component:
name: remote-select
vModel: value
mode: tags
type: plugin
typeName: OnePanelDeployToPanelPlugin
action: onGetNodes
search: false
pager: false
watches:
- certDomains
- accessId
value: local
required: true
mergeScript: |2-
return {
component:{
form: ctx.compute(({form})=>{
return form
})
},
}
helper: 要更新的1Panel证书的节点信息目前只有v2存在此概念
order: 0
output: {}
pluginType: deploy
type: builtIn
scriptFilePath: /plugins/plugin-plus/1panel/plugins/deploy-to-panel.js

View File

@@ -0,0 +1,155 @@
import { AbstractTaskPlugin, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline";
import { CertApplyPluginNames, CertInfo } from "@certd/plugin-cert";
import { OnePanelAccess } from "../access.js";
import { CertReader, createCertDomainGetterInputDefine, createRemoteSelectInputDefine } from "@certd/plugin-lib";
import { OnePanelClient } from "../client.js";
@IsTaskPlugin({
name: "1PanelDeployToPanel",
title: "1Panel-部署面板证书",
icon: "svg:icon-onepanel",
desc: "更新1Panel的面板证书",
group: pluginGroups.panel.key,
default: {
strategy: {
runStrategy: RunStrategy.SkipWhenSucceed,
},
},
needPlus: false,
})
export class OnePanelDeployToPanelPlugin extends AbstractTaskPlugin {
//证书选择,此项必须要有
@TaskInput({
title: "域名证书",
helper: "请选择前置任务输出的域名证书",
component: {
name: "output-selector",
from: [...CertApplyPluginNames],
},
required: true,
})
cert!: CertInfo;
@TaskInput(createCertDomainGetterInputDefine())
certDomains!: string[];
//授权选择框
@TaskInput({
title: "1Panel授权",
helper: "1Panel授权",
component: {
name: "access-selector",
type: "1panel",
},
required: true,
})
accessId!: string;
@TaskInput(
createRemoteSelectInputDefine({
title: "1Panel节点",
helper: "要更新的1Panel证书的节点信息目前只有v2存在此概念",
typeName: "OnePanelDeployToPanelPlugin",
action: OnePanelDeployToPanelPlugin.prototype.onGetNodes.name,
value: "local",
required: true,
})
)
currentNode!: string;
access: OnePanelAccess;
async onInstance() {
this.access = await this.getAccess(this.accessId);
}
//http://xxx:xxxx/1panel/swagger/index.html#/App/get_apps__key
async execute(): Promise<void> {
const client = new OnePanelClient({
access: this.access,
http: this.http,
logger: this.logger,
utils: this.ctx.utils,
});
const certReader = new CertReader(this.cert);
const domain = certReader.getMainDomain();
if (this.access.apiVersion === "v1") {
const uploadRes = await client.doRequest({
// api/v1/settings/ssl/update
url: `/api/v1/settings/ssl/update`,
method: "post",
data: {
cert: this.cert.crt,
key: this.cert.key,
domain: domain,
ssl: "enable",
sslID: null,
sslType: "import-paste",
},
currentNode: this.currentNode,
});
console.log("uploadRes", JSON.stringify(uploadRes));
} else {
const uploadRes = await client.doRequest({
// api/v2/core/settings/ssl/update
url: `/api/v2/core/settings/ssl/update`,
method: "post",
data: {
cert: this.cert.crt,
key: this.cert.key,
domain: domain,
ssl: "Enable",
sslID: null,
sslType: "import-paste",
},
currentNode: this.currentNode,
});
console.log("uploadRes", JSON.stringify(uploadRes));
}
await this.ctx.utils.sleep(10000);
this.logger.info(`证书更新完成`);
}
isNeedUpdate(certRes: any) {
if (certRes.pem === this.cert.crt && certRes.key === this.cert.key) {
this.logger.info(`证书(id:${certRes.id})已经是最新的了,不需要更新`);
return false;
}
return true;
}
async onGetNodes() {
const options = [{ label: "主节点", value: "local" }];
if (this.access.apiVersion === "v1") {
return options;
}
if (!this.access) {
throw new Error("请先选择授权");
}
const client = new OnePanelClient({
access: this.access,
http: this.http,
logger: this.logger,
utils: this.ctx.utils,
});
const resp = await client.doRequest({
url: `/api/${this.access.apiVersion}/core/nodes/list`,
method: "post",
data: {},
});
// console.log('resp', resp)
return [...options, ...(resp?.map(item => ({ label: `${item.addr}(${item.name})`, value: item.name })) || [])];
}
}
new OnePanelDeployToPanelPlugin();

View File

@@ -1 +1,2 @@
export * from "./deploy-to-website.js";
export * from "./deploy-to-panel.js";