mirror of
https://gitee.com/mirrors/AllinSSL.git
synced 2026-03-08 07:41:10 +08:00
【调整】插件支持动态参数和参数类型
【调整】获取证书列表支持状态过滤 【新增】dns提供商腾讯云eo
This commit is contained in:
@@ -408,3 +408,26 @@ func GetPlugins(c *gin.Context) {
|
||||
public.SuccessData(c, data, len(data))
|
||||
return
|
||||
}
|
||||
|
||||
func GetPluginRawMetadata(c *gin.Context) {
|
||||
var form struct {
|
||||
Name string `form:"name"`
|
||||
}
|
||||
err := c.Bind(&form)
|
||||
if err != nil {
|
||||
public.FailMsg(c, err.Error())
|
||||
return
|
||||
}
|
||||
form.Name = strings.TrimSpace(form.Name)
|
||||
if form.Name == "" {
|
||||
public.FailMsg(c, "插件名称不能为空")
|
||||
return
|
||||
}
|
||||
data, err := plugin.GetPluginRawMetadata(form.Name)
|
||||
if err != nil {
|
||||
public.FailMsg(c, err.Error())
|
||||
return
|
||||
}
|
||||
public.SuccessData(c, data, 0)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -14,13 +14,14 @@ func GetCertList(c *gin.Context) {
|
||||
Search string `form:"search"`
|
||||
Page int64 `form:"p"`
|
||||
Limit int64 `form:"limit"`
|
||||
Status int64 `form:"status"`
|
||||
}
|
||||
err := c.Bind(&form)
|
||||
if err != nil {
|
||||
public.FailMsg(c, err.Error())
|
||||
return
|
||||
}
|
||||
certList, count, err := cert.GetList(form.Search, form.Page, form.Limit)
|
||||
certList, count, err := cert.GetList(form.Search, form.Page, form.Limit, form.Status)
|
||||
if err != nil {
|
||||
public.FailMsg(c, err.Error())
|
||||
return
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
"github.com/go-acme/lego/v4/providers/dns/cloudflare"
|
||||
"github.com/go-acme/lego/v4/providers/dns/cloudns"
|
||||
"github.com/go-acme/lego/v4/providers/dns/constellix"
|
||||
"github.com/go-acme/lego/v4/providers/dns/edgeone"
|
||||
"github.com/go-acme/lego/v4/providers/dns/gcore"
|
||||
"github.com/go-acme/lego/v4/providers/dns/godaddy"
|
||||
"github.com/go-acme/lego/v4/providers/dns/huaweicloud"
|
||||
@@ -234,8 +235,12 @@ func GetDNSProvider(providerName string, creds map[string]string, httpClient *ht
|
||||
}
|
||||
config.PropagationTimeout = maxWait
|
||||
return bt.NewDNSProviderConfig(config)
|
||||
//case "edgeone":
|
||||
//config :=
|
||||
case "edgeone":
|
||||
config := edgeone.NewDefaultConfig()
|
||||
config.SecretID = creds["secret_id"]
|
||||
config.SecretKey = creds["secret_key"]
|
||||
config.PropagationTimeout = maxWait
|
||||
return edgeone.NewDNSProviderConfig(config)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("不支持的 DNS Provider: %s", providerName)
|
||||
|
||||
@@ -17,7 +17,7 @@ func GetSqlite() (*public.Sqlite, error) {
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func GetList(search string, p, limit int64) ([]map[string]any, int, error) {
|
||||
func GetList(search string, p, limit, status int64) ([]map[string]any, int, error) {
|
||||
var data []map[string]any
|
||||
var count int64
|
||||
s, err := GetSqlite()
|
||||
@@ -35,13 +35,30 @@ func GetList(search string, p, limit int64) ([]map[string]any, int, error) {
|
||||
}
|
||||
}
|
||||
|
||||
if search != "" {
|
||||
count, err = s.Where("domains like ?", []interface{}{"%" + search + "%"}).Count()
|
||||
data, err = s.Where("domains like ?", []interface{}{"%" + search + "%"}).Limit(limits).Order("end_time", "esc").Select()
|
||||
} else {
|
||||
count, err = s.Count()
|
||||
data, err = s.Order("end_time", "esc").Limit(limits).Select()
|
||||
// 获取当前时间
|
||||
now := time.Now()
|
||||
// 转换为字符串格式
|
||||
nowStr := now.Format("2006-01-02 15:04:05")
|
||||
// 30 天后的时间
|
||||
nowPlus30Days := now.AddDate(0, 0, 30)
|
||||
nowPlus30DaysStr := nowPlus30Days.Format("2006-01-02 15:04:05")
|
||||
|
||||
filterSql := "1=1 "
|
||||
// status: -1 已过期 0/其它 全部 1 即将过期 2 正常
|
||||
if status == -1 {
|
||||
filterSql += "and end_time <= '" + nowStr + "'"
|
||||
} else if status == 1 {
|
||||
filterSql += "and end_time > '" + nowStr + "' AND end_time <= '" + nowPlus30DaysStr + "'"
|
||||
} else if status == 2 {
|
||||
filterSql += "and end_time > '" + nowPlus30DaysStr + "'"
|
||||
}
|
||||
|
||||
if search != "" {
|
||||
filterSql += "and domains like '%" + search + "%'"
|
||||
}
|
||||
count, err = s.Where(filterSql, []interface{}{}).Count()
|
||||
data, err = s.Where(filterSql, []interface{}{}).Order("end_time", "esc").Limit(limits).Select()
|
||||
|
||||
if err != nil {
|
||||
return data, 0, err
|
||||
}
|
||||
@@ -170,7 +187,7 @@ func DelCert(id string) error {
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
_, err = s.Where("id=?", []interface{}{id}).Delete()
|
||||
_, err = s.Where("id in (?)", []interface{}{id}).Delete()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -18,20 +18,28 @@ var (
|
||||
pluginRegistry = map[string]PluginMetadata{}
|
||||
)
|
||||
|
||||
type ConfigParam struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"` // 数据类型:string/number/boolean/enum
|
||||
Description string `json:"description"`
|
||||
Required bool `json:"required"`
|
||||
Options []map[string]any `json:"options,omitempty"` // 可选枚举值
|
||||
}
|
||||
|
||||
type ActionInfo struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Params map[string]any `json:"params,omitempty"` // 可选参数
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Params []ConfigParam `json:"params,omitempty"` // 可选参数
|
||||
}
|
||||
|
||||
type PluginMetadata struct {
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Version string `json:"version"`
|
||||
Author string `json:"author"`
|
||||
Actions []ActionInfo `json:"actions"`
|
||||
Config map[string]any `json:"config,omitempty"` // 可选配置
|
||||
Path string // 插件路径
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Version string `json:"version"`
|
||||
Author string `json:"author"`
|
||||
Actions []ActionInfo `json:"actions"`
|
||||
Config []ConfigParam `json:"config,omitempty"` // 可选配置
|
||||
Path string // 插件路径
|
||||
}
|
||||
|
||||
type Request struct {
|
||||
@@ -54,7 +62,7 @@ func scanPlugins(dir string) ([]PluginMetadata, error) {
|
||||
}
|
||||
meta, err := getMetadata(path)
|
||||
if err != nil {
|
||||
fmt.Println("插件无效:", path, "错误:", err)
|
||||
//fmt.Println("插件无效:", path, "错误:", err)
|
||||
return nil
|
||||
}
|
||||
meta.Path = path
|
||||
@@ -89,6 +97,83 @@ func getMetadata(path string) (PluginMetadata, error) {
|
||||
var meta PluginMetadata
|
||||
raw, _ := json.Marshal(resp.Result)
|
||||
if err := json.Unmarshal(raw, &meta); err != nil {
|
||||
var metaMap map[string]any
|
||||
if err := json.Unmarshal(raw, &metaMap); err == nil {
|
||||
|
||||
name, ok := metaMap["name"].(string)
|
||||
if !ok || name == "" {
|
||||
return PluginMetadata{}, fmt.Errorf("元数据缺失字段: name")
|
||||
}
|
||||
meta.Name = name
|
||||
description, ok := metaMap["description"].(string)
|
||||
if !ok || description == "" {
|
||||
return PluginMetadata{}, fmt.Errorf("元数据缺失字段: description")
|
||||
}
|
||||
meta.Description = description
|
||||
version, ok := metaMap["version"].(string)
|
||||
if !ok || version == "" {
|
||||
return PluginMetadata{}, fmt.Errorf("元数据缺失字段: version")
|
||||
}
|
||||
meta.Version = version
|
||||
author, ok := metaMap["author"].(string)
|
||||
if !ok || author == "" {
|
||||
return PluginMetadata{}, fmt.Errorf("元数据缺失字段: author")
|
||||
}
|
||||
meta.Author = author
|
||||
|
||||
metaMapConfig, ok := metaMap["config"].(map[string]any)
|
||||
if !ok {
|
||||
return PluginMetadata{}, fmt.Errorf("元数据缺失字段: config")
|
||||
}
|
||||
config := ConfigParam{
|
||||
Type: "string",
|
||||
Required: true,
|
||||
}
|
||||
// 遍历 map 键值对
|
||||
for key, value := range metaMapConfig {
|
||||
config.Name = key
|
||||
config.Description = value.(string)
|
||||
meta.Config = append(meta.Config, config)
|
||||
}
|
||||
actions, ok := metaMap["actions"].([]any)
|
||||
if !ok || len(actions) == 0 {
|
||||
return PluginMetadata{}, fmt.Errorf("元数据缺失字段: actions")
|
||||
}
|
||||
for _, a := range actions {
|
||||
actionMap, ok := a.(map[string]any)
|
||||
if !ok {
|
||||
return PluginMetadata{}, fmt.Errorf("元数据 actions 格式错误")
|
||||
}
|
||||
action := ActionInfo{}
|
||||
name, ok := actionMap["name"].(string)
|
||||
if !ok || name == "" {
|
||||
return PluginMetadata{}, fmt.Errorf("元数据缺失字段: action.name")
|
||||
}
|
||||
action.Name = name
|
||||
description, ok := actionMap["description"].(string)
|
||||
if !ok || description == "" {
|
||||
return PluginMetadata{}, fmt.Errorf("元数据缺失字段: action.description")
|
||||
}
|
||||
action.Description = description
|
||||
|
||||
paramsMap, ok := actionMap["params"].(map[string]any)
|
||||
if ok {
|
||||
for key, value := range paramsMap {
|
||||
param := ConfigParam{
|
||||
Name: key,
|
||||
Type: "string",
|
||||
Description: value.(string),
|
||||
Required: true,
|
||||
}
|
||||
action.Params = append(action.Params, param)
|
||||
}
|
||||
}
|
||||
meta.Actions = append(meta.Actions, action)
|
||||
return meta, nil
|
||||
}
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
}
|
||||
return PluginMetadata{}, fmt.Errorf("元数据解析失败: %w", err)
|
||||
}
|
||||
|
||||
@@ -99,6 +184,37 @@ func getMetadata(path string) (PluginMetadata, error) {
|
||||
return meta, nil
|
||||
}
|
||||
|
||||
// GetPluginRawMetadata 获取原始元数据
|
||||
func GetPluginRawMetadata(name string) (map[string]interface{}, error) {
|
||||
plugin, ok := pluginRegistry[name]
|
||||
if !ok {
|
||||
return nil, ErrPluginNotFound
|
||||
}
|
||||
path := plugin.Path
|
||||
|
||||
req := Request{Action: "get_metadata"}
|
||||
data, _ := json.Marshal(req)
|
||||
|
||||
cmd := exec.Command(path)
|
||||
cmd.Stdin = bytes.NewReader(data)
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
|
||||
if err := cmd.Run(); err != nil {
|
||||
return nil, fmt.Errorf("运行失败: %w", err)
|
||||
}
|
||||
|
||||
var resp Response
|
||||
if err := json.Unmarshal(out.Bytes(), &resp); err != nil {
|
||||
return nil, fmt.Errorf("输出无效: %w", err)
|
||||
}
|
||||
if resp.Status != "success" {
|
||||
return nil, fmt.Errorf("插件响应错误: %s", resp.Message)
|
||||
}
|
||||
|
||||
return resp.Result, nil
|
||||
}
|
||||
|
||||
func CallPlugin(name, action string, params map[string]interface{}, logger *public.Logger) (*Response, error) {
|
||||
// 第一次尝试
|
||||
resp, err := tryCallPlugin(name, action, params, logger)
|
||||
|
||||
@@ -79,7 +79,7 @@ func DeployToTX(cfg map[string]any) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
region := ""
|
||||
region := "ap-beijing"
|
||||
if r, ok := cfg["region"].(string); ok {
|
||||
region = r
|
||||
}
|
||||
@@ -117,10 +117,6 @@ func DeployToTX(cfg map[string]any) error {
|
||||
if !ok {
|
||||
return fmt.Errorf("参数错误:domain")
|
||||
}
|
||||
region, ok := cfg["region"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("参数错误:region")
|
||||
}
|
||||
bucket, ok := cfg["bucket"].(string)
|
||||
if !ok {
|
||||
return fmt.Errorf("参数错误:bucket")
|
||||
|
||||
@@ -193,20 +193,17 @@ func Restart() {
|
||||
}
|
||||
|
||||
func GetVersion() (map[string]string, error) {
|
||||
version := "v1.1.1"
|
||||
version := "v1.1.2"
|
||||
update := "0"
|
||||
newVersionObj, err := http.Get("https://download.allinssl.com/version.json")
|
||||
newVersionObj, err := http.Get("https://allinssl.bt.com/version.json")
|
||||
if err != nil {
|
||||
newVersionObj, err = http.Get("https://node1.allinssl.com/version.json")
|
||||
if err != nil {
|
||||
return map[string]string{
|
||||
"version": version,
|
||||
"new_version": version,
|
||||
"update": update,
|
||||
"log": "",
|
||||
"date": "",
|
||||
}, nil
|
||||
}
|
||||
return map[string]string{
|
||||
"version": version,
|
||||
"new_version": version,
|
||||
"update": update,
|
||||
"log": "",
|
||||
"date": "",
|
||||
}, nil
|
||||
}
|
||||
defer newVersionObj.Body.Close()
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ func Register(r *gin.Engine) {
|
||||
// 插件先放这里
|
||||
access.POST("/get_plugin_actions", api.GetPluginActions)
|
||||
access.POST("/get_plugins", api.GetPlugins)
|
||||
access.POST("/get_plugin_raw_metadata", api.GetPluginRawMetadata)
|
||||
}
|
||||
// acme账户
|
||||
acmeAccount := v1.Group("/acme_account")
|
||||
|
||||
@@ -7,11 +7,14 @@ import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"encoding/gob"
|
||||
"fmt"
|
||||
"github.com/gin-contrib/gzip"
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-contrib/sessions/memstore"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/tjfoc/gmsm/gmtls"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -54,7 +57,45 @@ func RunServer(ctx context.Context, r *gin.Engine) error {
|
||||
defer close(errchan)
|
||||
err := srv.ListenAndServeTLS("data/https/cert.pem", "data/https/key.pem")
|
||||
if err != nil {
|
||||
errchan <- err
|
||||
// 读取 SM2 证书和密钥(PEM 格式)
|
||||
certPem, err := os.ReadFile("data/https/cert.pem")
|
||||
midCertPem, err := os.ReadFile("data/https/mid_cert.pem")
|
||||
|
||||
keyPem, err := os.ReadFile("data/https/key.pem")
|
||||
midKeyPem, err := os.ReadFile("data/https/mid_key.pem")
|
||||
|
||||
tlsCert, err := gmtls.X509KeyPair(certPem, keyPem)
|
||||
midcert, err := gmtls.X509KeyPair(midCertPem, midKeyPem)
|
||||
if err != nil {
|
||||
errchan <- fmt.Errorf("无法加载国密证书和私钥: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
tlsConfig := &gmtls.Config{
|
||||
Certificates: []gmtls.Certificate{tlsCert, midcert}, // 使用国密证书和加密证书
|
||||
MinVersion: gmtls.VersionGMSSL,
|
||||
MaxVersion: gmtls.VersionGMSSL,
|
||||
GMSupport: &gmtls.GMSupport{
|
||||
WorkMode: gmtls.ModeGMSSLOnly,
|
||||
}, // 启用 GM/T 0024 协议
|
||||
CipherSuites: []uint16{
|
||||
gmtls.GMTLS_SM2_WITH_SM4_SM3, // 明确指定国密套件
|
||||
},
|
||||
GetConfigForClient: func(chi *gmtls.ClientHelloInfo) (*gmtls.Config, error) {
|
||||
fmt.Printf("客户端 Hello 协议版本: %x, 支持 cipher suites: %+v\n", chi.SupportedVersions, chi.CipherSuites)
|
||||
return nil, nil
|
||||
},
|
||||
}
|
||||
//srv.TLSConfig = tlsConfig
|
||||
ln, err := gmtls.Listen("tcp", ":"+public.Port, tlsConfig)
|
||||
if err != nil {
|
||||
errchan <- fmt.Errorf("无法启动国密 HTTPS 服务器: %v", err)
|
||||
return
|
||||
}
|
||||
err = http.Serve(ln, r)
|
||||
if err != nil {
|
||||
errchan <- err
|
||||
}
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user