新增PVE部署

This commit is contained in:
net909 2025-03-02 14:59:02 +08:00
parent 12d8017df5
commit 36622e6642
5 changed files with 151 additions and 6 deletions

View File

@ -490,7 +490,7 @@ class Cert extends BaseController
return json(['code' => 0, 'msg' => '添加DNS记录成功请等待DNS生效后点击验证']);
}
}catch(Exception $e){
return json(['code' => -1, 'msg' => $e->getMessage()]);
return json(['code' => -1, 'msg' => $e->getMessage(), 'trace' => $e->getTrace()]);
}
}
@ -668,7 +668,7 @@ class Cert extends BaseController
$service->process(true);
return json(['code' => 0, 'msg' => 'SSL证书部署任务执行成功']);
}catch(Exception $e){
return json(['code' => -1, 'msg' => $e->getMessage()]);
return json(['code' => -1, 'msg' => $e->getMessage(), 'trace' => $e->getTrace()]);
}
}

View File

@ -521,6 +521,51 @@ class DeployHelper
],
],
],
'proxmox' => [
'name' => 'Proxmox VE',
'class' => 1,
'icon' => 'proxmox.ico',
'note' => '在“权限->API令牌”添加令牌不要选特权分离',
'tasknote' => '',
'inputs' => [
'url' => [
'name' => '面板地址',
'type' => 'input',
'placeholder' => 'Proxmox VE 面板地址',
'note' => '填写规则如https://192.168.1.100:8006 ,不要带其他后缀',
'required' => true,
],
'api_user' => [
'name' => 'API令牌ID',
'type' => 'input',
'placeholder' => '用户!令牌名称',
'required' => true,
],
'api_key' => [
'name' => 'API令牌密钥',
'type' => 'input',
'placeholder' => '',
'required' => true,
],
'proxy' => [
'name' => '使用代理服务器',
'type' => 'radio',
'options' => [
'0' => '否',
'1' => '是',
],
'value' => '0'
],
],
'taskinputs' => [
'node' => [
'name' => '节点名称',
'type' => 'input',
'placeholder' => '要部署证书的节点',
'required' => true,
],
],
],
'aliyun' => [
'name' => '阿里云',
'class' => 2,

View File

@ -0,0 +1,98 @@
<?php
namespace app\lib\deploy;
use app\lib\DeployInterface;
use Exception;
class proxmox implements DeployInterface
{
private $logger;
private $url;
private $api_user;
private $api_key;
private $proxy;
public function __construct($config)
{
$this->url = rtrim($config['url'], '/');
$this->api_user = $config['api_user'];
$this->api_key = $config['api_key'];
$this->proxy = $config['proxy'] == 1;
}
public function check()
{
if (empty($this->url) || empty($this->api_user) || empty($this->api_key)) throw new Exception('必填内容不能为空');
$path = '/api2/json/access';
$this->send_request($path);
}
public function deploy($fullchain, $privatekey, $config, &$info)
{
if (empty($config['node'])) throw new Exception('节点名称不能为空');
$cert_hash = openssl_x509_fingerprint($fullchain, 'sha256');
if (!$cert_hash) throw new Exception('证书解析失败');
$path = '/api2/json/nodes/' . $config['node'] . '/certificates/info';
$list = $this->send_request($path);
foreach ($list as $item) {
$fingerprint = strtolower(str_replace(':', '', $item['fingerprint']));
if ($fingerprint == $cert_hash) {
$this->log('节点:' . $config['node'] . ' 证书已存在');
return;
}
}
$path = '/api2/json/nodes/' . $config['node'] . '/certificates/custom';
$params = [
'certificates' => $fullchain,
'key' => $privatekey,
'force' => 1,
'restart' => 1,
];
$this->send_request($path, $params);
$this->log('节点:' . $config['node'] . ' 证书部署成功!');
}
private function send_request($path, $params = null)
{
$url = $this->url . $path;
$headers = ['Authorization: PVEAPIToken=' . $this->api_user . '=' . $this->api_key];
$post = $params ? http_build_query($params) : null;
$response = curl_client($url, $post, null, null, $headers, $this->proxy);
if ($response['code'] == 200) {
$result = json_decode($response['body'], true);
if (isset($result['data'])) {
return $result['data'];
} elseif (isset($result['errors'])) {
if (is_array($result['errors'])) {
$result['errors'] = implode(';', $result['errors']);
}
throw new Exception($result['errors']);
} else {
throw new Exception('返回数据解析失败');
}
} else {
$header = getSubstr($response['header'], ' ', "\r\n");
if ($header) {
throw new Exception($header);
} else {
throw new Exception('请求失败(httpCode=' . $response['code'] . ')');
}
}
}
public function setLogger($func)
{
$this->logger = $func;
}
private function log($txt)
{
if ($this->logger) {
call_user_func($this->logger, $txt);
}
}
}

View File

@ -37,6 +37,7 @@ class synology implements DeployInterface
'api' => 'SYNO.API.Auth',
'version' => 6,
'method' => 'login',
'session' => 'webui',
'account' => $this->username,
'passwd' => $this->password,
'format' => 'sid',
@ -55,6 +56,7 @@ class synology implements DeployInterface
public function deploy($fullchain, $privatekey, $config, &$info)
{
$this->login();
$certInfo = openssl_x509_parse($fullchain, true);
if (!$certInfo) throw new Exception('证书解析失败');
@ -66,12 +68,12 @@ class synology implements DeployInterface
'_sid' => $this->token['sid'],
'SynoToken' => $this->token['synotoken'],
];
$response = curl_client($url, http_build_query($params), null, null, null, $this->proxy);
$response = curl_client($url . '?' . http_build_query($params), null, null, $this->proxy);
$result = json_decode($response['body'], true);
if (isset($result['success']) && $result['success']) {
$this->log('获取证书列表成功');
} elseif(isset($result['error'])) {
throw new Exception('获取证书列表失败:' . $result['error']);
throw new Exception('获取证书列表失败:' . json_encode($result['error']));
} else {
throw new Exception('获取证书列表失败(httpCode=' . $response['code'] . ')');
}
@ -118,7 +120,7 @@ class synology implements DeployInterface
if (isset($result['success']) && $result['success']) {
$this->log('证书ID:'.$id.'更新成功!');
} elseif(isset($result['error'])) {
throw new Exception('证书ID:'.$id.'更新失败:' . $result['error']);
throw new Exception('证书ID:'.$id.'更新失败:' . json_encode($result['error']));
} else {
throw new Exception('证书ID:'.$id.'更新失败(httpCode=' . $response['code'] . ')');
}
@ -126,7 +128,7 @@ class synology implements DeployInterface
if (isset($result['success']) && $result['success']) {
$this->log('证书上传成功!');
} elseif(isset($result['error'])) {
throw new Exception('证书上传失败:' . $result['error']);
throw new Exception('证书上传失败:' . json_encode($result['error']));
} else {
throw new Exception('证书上传失败(httpCode=' . $response['code'] . ')');
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB