allinssl/backend/internal/cert/deploy/1panel.go

272 lines
7.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package deploy
import (
"ALLinSSL/backend/app/dto/response"
"ALLinSSL/backend/internal/access"
"bytes"
"crypto/md5"
"crypto/tls"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strconv"
"time"
)
func generateToken(timestamp string, apiKey string) string {
tokenMd5 := md5.Sum([]byte("1panel" + apiKey + timestamp))
tokenMd5Hex := hex.EncodeToString(tokenMd5[:])
return tokenMd5Hex
}
// method provider_id url data
func Request1panel(data *map[string]any, method, providerID, requestUrl string) (map[string]any, error) {
providerData, err := access.GetAccess(providerID)
if err != nil {
return nil, err
}
providerConfigStr, ok := providerData["config"].(string)
if !ok {
return nil, fmt.Errorf("api配置错误")
}
// 解析 JSON 配置
var providerConfig map[string]string
err = json.Unmarshal([]byte(providerConfigStr), &providerConfig)
if err != nil {
return nil, err
}
timestamp := fmt.Sprintf("%d", time.Now().Unix())
token := generateToken(timestamp, providerConfig["api_key"])
// data, requestUrl, method := GetDeploy1PBody(cfg, Type)
if requestUrl == "" || data == nil {
return nil, fmt.Errorf("不支持的部署类型")
}
// 编码为 JSON
jsonData, err := json.Marshal(data)
if err != nil {
return nil, err
}
parsedURL, err := url.Parse(providerConfig["url"])
if err != nil {
return nil, err
}
baseURL := fmt.Sprintf("%s://%s/", parsedURL.Scheme, parsedURL.Host)
req, err := http.NewRequest(method, baseURL+requestUrl, bytes.NewBuffer(jsonData))
if err != nil {
// fmt.Println(err)
return nil, err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36")
req.Header.Set("1Panel-Timestamp", timestamp)
req.Header.Set("1Panel-Token", token)
// 自定义 Transport跳过 SSL 证书验证
ignoreSsl := false
if providerConfig["ignore_ssl"] == "1" {
ignoreSsl = true
}
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: ignoreSsl},
}
client := &http.Client{Transport: tr}
resp, err := client.Do(req)
if err != nil {
// fmt.Println(err)
return nil, fmt.Errorf("请求1panel失败: %v", err)
}
body, _ := io.ReadAll(resp.Body)
defer resp.Body.Close()
var res map[string]interface{}
err = json.Unmarshal(body, &res)
if err != nil {
return nil, fmt.Errorf("解析返回值失败: %v", err)
}
code, ok := res["code"].(float64)
if !ok {
return nil, fmt.Errorf("请求失败")
}
if code != 200 {
msg, ok := res["message"].(string)
if !ok {
return nil, fmt.Errorf("请求失败")
}
return nil, fmt.Errorf("请求失败: %s", msg)
}
return res, nil
}
func Deploy1panel(cfg map[string]any) error {
cert, ok := cfg["certificate"].(map[string]any)
if !ok {
return fmt.Errorf("证书不存在")
}
var providerID string
switch v := cfg["provider_id"].(type) {
case float64:
providerID = strconv.Itoa(int(v))
case string:
providerID = v
default:
return fmt.Errorf("参数错误provider_id")
}
// 设置证书
keyPem, ok := cert["key"].(string)
if !ok {
return fmt.Errorf("证书错误key")
}
certPem, ok := cert["cert"].(string)
if !ok {
return fmt.Errorf("证书错误cert")
}
data := map[string]interface{}{
"cert": certPem,
"key": keyPem,
"ssl": "enable",
"sslType": "import-paste",
}
_, err := Request1panel(&data, "POST", providerID, "api/v1/settings/ssl/update")
if err != nil {
return fmt.Errorf("证书部署失败: %v", err)
}
return nil
}
func Deploy1panelSite(cfg map[string]any) error {
cert, ok := cfg["certificate"].(map[string]any)
if !ok {
return fmt.Errorf("证书不存在")
}
var providerID string
switch v := cfg["provider_id"].(type) {
case float64:
providerID = strconv.Itoa(int(v))
case string:
providerID = v
default:
return fmt.Errorf("参数错误provider_id")
}
siteId, ok := cfg["site_id"].(string)
if !ok {
return fmt.Errorf("参数错误site_id")
}
// 设置证书
keyPem, ok := cert["key"].(string)
if !ok {
return fmt.Errorf("证书错误key")
}
certPem, ok := cert["cert"].(string)
if !ok {
return fmt.Errorf("证书错误cert")
}
// 获取网站参数
siteData, err := Request1panel(&map[string]any{}, "GET", providerID, fmt.Sprintf("api/v1/websites/%s/https", siteId))
if err != nil {
return fmt.Errorf("获取网站参数失败: %v", err)
}
//
websiteId, err := strconv.Atoi(siteId)
if err != nil {
return fmt.Errorf("获取网站参数失败: %v", err)
}
siteData, ok = siteData["data"].(map[string]any)
if !ok {
return fmt.Errorf("获取网站参数失败: data")
}
var SSLProtocol []any
if siteData["SSLProtocol"] == nil {
SSLProtocol = []any{"TLSv1.3", "TLSv1.2", "TLSv1.1", "TLSv1"}
} else {
SSLProtocol, ok = siteData["SSLProtocol"].([]any)
if !ok {
return fmt.Errorf("获取网站参数失败: data.SSLProtocol")
}
}
algorithm, ok := siteData["algorithm"].(string)
if !ok {
return fmt.Errorf("获取网站参数失败: data.algorithm")
}
hsts, ok := siteData["hsts"].(bool)
if !ok {
return fmt.Errorf("获取网站参数失败: data.hsts")
}
httpConfig, ok := siteData["httpConfig"].(string)
if !ok {
return fmt.Errorf("获取网站参数失败: data.httpConfig")
}
if httpConfig == "" {
httpConfig = "HTTPToHTTPS"
}
data := map[string]any{
"SSLProtocol": SSLProtocol,
// "acmeAccountId": siteData["SSL"].(map[string]any)["acmeAccountId"].(float64),
"algorithm": algorithm,
"certificate": certPem,
"privateKey": keyPem,
// "certificatePath": "",
// "privateKeyPath": "",
"enable": true,
"hsts": hsts,
"httpConfig": httpConfig,
"importType": "paste",
"type": "manual",
"websiteId": websiteId,
}
_, err = Request1panel(&data, "POST", providerID, fmt.Sprintf("api/v1/websites/%s/https", siteId))
return err
}
func OnePanelAPITest(providerID string) error {
data := map[string]interface{}{}
_, err := Request1panel(&data, "GET", providerID, "api/v1/settings/upgrade")
if err != nil {
return fmt.Errorf("测试请求失败: %v", err)
}
return nil
}
func OnePanelSiteList(providerID string) ([]response.AccessSiteList, error) {
data := map[string]any{
"name": "",
"order": "null",
"orderBy": "created_at",
"page": 1,
"pageSize": 1000,
"websiteGroupId": 0,
}
siteList, err := Request1panel(&data, "POST", providerID, "api/v1/websites/search")
if err != nil {
return nil, fmt.Errorf("获取网站列表失败 %v", err)
}
var result []response.AccessSiteList
sites, ok := siteList["data"].(map[string]any)["items"].([]any)
if !ok {
return nil, fmt.Errorf("获取网站列表失败: data.items")
}
for _, site := range sites {
siteMap, ok := site.(map[string]any)
if !ok {
return nil, fmt.Errorf("获取网站列表失败: site")
}
siteId := strconv.FormatFloat(siteMap["id"].(float64), 'f', -1, 64)
result = append(result, response.AccessSiteList{Id: siteId, SiteName: siteMap["alias"].(string), Domain: []string{}})
}
return result, nil
}