上传证书返回sha256、修改工作流上传节点支持使用本地证书、修改证书续签逻辑新增比对证书域名、修复ssh部署不填写执行前后命令就会报错的bug

pull/79/head^2
zhangchenhao 2025-05-10 15:38:06 +08:00
parent 2fe8b6475f
commit 5e53e5db8c
6 changed files with 135 additions and 77 deletions

View File

@ -50,12 +50,12 @@ func UploadCert(c *gin.Context) {
public.FailMsg(c, "类型不能为空") public.FailMsg(c, "类型不能为空")
return return
} }
err = cert.UploadCert(form.Key, form.Cert) sha256, err := cert.UploadCert(form.Key, form.Cert)
if err != nil { if err != nil {
public.FailMsg(c, err.Error()) public.FailMsg(c, err.Error())
return return
} }
public.SuccessMsg(c, "添加成功") public.SuccessData(c, sha256, 0)
return return
} }

View File

@ -84,6 +84,10 @@ func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
default: default:
return nil, fmt.Errorf("参数错误provider_id") return nil, fmt.Errorf("参数错误provider_id")
} }
domainArr := strings.Split(domains, ",")
for i := range domainArr {
domainArr[i] = strings.TrimSpace(domainArr[i])
}
// 获取上次申请的证书 // 获取上次申请的证书
runId, ok := cfg["_runId"].(string) runId, ok := cfg["_runId"].(string)
@ -114,11 +118,17 @@ func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
var maxDays float64 var maxDays float64
var maxItem map[string]any var maxItem map[string]any
for i := range certs { for i := range certs {
if !public.ContainsAllIgnoreBRepeats(strings.Split(certs[i]["domains"].(string), ","), domainArr) {
continue
}
endTimeStr, ok := certs[i]["end_time"].(string) endTimeStr, ok := certs[i]["end_time"].(string)
if !ok { if !ok {
continue continue
} }
endTime, _ := time.Parse(layout, endTimeStr) endTime, err := time.Parse(layout, endTimeStr)
if err != nil {
continue
}
diff := endTime.Sub(time.Now()).Hours() / 24 diff := endTime.Sub(time.Now()).Hours() / 24
if diff > maxDays { if diff > maxDays {
maxDays = diff maxDays = diff
@ -134,7 +144,7 @@ func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
if int(maxDays) > cfgEnd { if int(maxDays) > cfgEnd {
// 证书未过期,直接返回 // 证书未过期,直接返回
logger.Debug(fmt.Sprintf("上次证书申请成功,剩余天数:%d 大于%d天已跳过申请复用此证书", int(maxDays), cfgEnd)) logger.Debug(fmt.Sprintf("上次证书申请成功,域名:%s,剩余天数:%d 大于%d天已跳过申请复用此证书", certObj["domains"], int(maxDays), cfgEnd))
return map[string]any{ return map[string]any{
"cert": certObj["cert"], "cert": certObj["cert"],
"key": certObj["key"], "key": certObj["key"],
@ -218,7 +228,7 @@ func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
// fmt.Println(strings.Split(domains, ",")) // fmt.Println(strings.Split(domains, ","))
request := certificate.ObtainRequest{ request := certificate.ObtainRequest{
Domains: strings.Split(domains, ","), Domains: domainArr,
Bundle: true, Bundle: true,
} }
certObj, err := client.Certificate.Obtain(request) certObj, err := client.Certificate.Obtain(request)
@ -237,7 +247,7 @@ func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
"issuerCert": issuerCertStr, "issuerCert": issuerCertStr,
} }
err = cert.SaveCert("workflow", keyStr, certStr, issuerCertStr, runId) _, err = cert.SaveCert("workflow", keyStr, certStr, issuerCertStr, runId)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -104,22 +104,22 @@ func AddCert(source, key, cert, issuer, issuerCert, domains, sha256, historyId,
return nil return nil
} }
func SaveCert(source, key, cert, issuerCert, historyId string) error { func SaveCert(source, key, cert, issuerCert, historyId string) (string, error) {
if err := public.ValidateSSLCertificate(cert, key); err != nil { if err := public.ValidateSSLCertificate(cert, key); err != nil {
return err return "", err
} }
certObj, err := public.ParseCertificate([]byte(cert)) certObj, err := public.ParseCertificate([]byte(cert))
if err != nil { if err != nil {
return fmt.Errorf("解析证书失败: %v", err) return "", fmt.Errorf("解析证书失败: %v", err)
} }
// SHA256 // SHA256
sha256, err := public.GetSHA256(cert) sha256, err := public.GetSHA256(cert)
if err != nil { if err != nil {
return fmt.Errorf("获取 SHA256 失败: %v", err) return "", fmt.Errorf("获取 SHA256 失败: %v", err)
} }
if d, _ := GetCert(sha256); d != nil { if d, _ := GetCert(sha256); d != nil {
return nil return sha256, nil
} }
domainSet := make(map[string]bool) domainSet := make(map[string]bool)
@ -152,17 +152,17 @@ func SaveCert(source, key, cert, issuerCert, historyId string) error {
err = AddCert(source, key, cert, caName, issuerCert, domainList, sha256, historyId, startTime, endTime, endDay) err = AddCert(source, key, cert, caName, issuerCert, domainList, sha256, historyId, startTime, endTime, endDay)
if err != nil { if err != nil {
return fmt.Errorf("保存证书失败: %v", err) return "", fmt.Errorf("保存证书失败: %v", err)
} }
return nil return sha256, nil
} }
func UploadCert(key, cert string) error { func UploadCert(key, cert string) (string, error) {
err := SaveCert("upload", key, cert, "", "") sha256, err := SaveCert("upload", key, cert, "", "")
if err != nil { if err != nil {
return fmt.Errorf("保存证书失败: %v", err) return sha256, fmt.Errorf("保存证书失败: %v", err)
} }
return nil return sha256, nil
} }
func DelCert(id string) error { func DelCert(id string) error {

View File

@ -133,11 +133,11 @@ func DeploySSH(cfg map[string]any) error {
} }
beforeCmd, ok := cfg["beforeCmd"].(string) beforeCmd, ok := cfg["beforeCmd"].(string)
if !ok { if !ok {
return fmt.Errorf("参数错误beforeCmd") beforeCmd = ""
} }
afterCmd, ok := cfg["afterCmd"].(string) afterCmd, ok := cfg["afterCmd"].(string)
if !ok { if !ok {
return fmt.Errorf("参数错误afterCmd") afterCmd = ""
} }
providerData, err := access.GetAccess(providerID) providerData, err := access.GetAccess(providerID)
if err != nil { if err != nil {

View File

@ -8,6 +8,7 @@ import (
"ALLinSSL/backend/public" "ALLinSSL/backend/public"
"errors" "errors"
"fmt" "fmt"
"strconv"
) )
// var executors map[string]func(map[string]any) (any, error) // var executors map[string]func(map[string]any) (any, error)
@ -67,28 +68,54 @@ func deploy(params map[string]any) (any, error) {
func upload(params map[string]any) (any, error) { func upload(params map[string]any) (any, error) {
logger := params["logger"].(*public.Logger) logger := params["logger"].(*public.Logger)
logger.Info("=============上传证书=============") logger.Info("=============上传证书=============")
// 判断证书id走本地还是走旧上传应在之后的迭代中移除旧代码
if params["cert_id"] == nil {
keyStr, ok := params["key"].(string)
if !ok {
logger.Error("上传的密钥有误")
logger.Info("=============上传失败=============")
return nil, errors.New("上传的密钥有误")
}
certStr, ok := params["cert"].(string)
if !ok {
logger.Error("上传的证书有误")
logger.Info("=============上传失败=============")
return nil, errors.New("上传的证书有误")
}
_, err := cert.UploadCert(keyStr, certStr)
if err != nil {
logger.Error(err.Error())
logger.Info("=============上传失败=============")
return nil, err
}
logger.Info("=============上传成功=============")
keyStr, ok := params["key"].(string) return params, nil
if !ok { } else {
logger.Error("上传的密钥有误") certId := ""
logger.Info("=============上传失败=============") switch v := params["cert_id"].(type) {
return nil, errors.New("上传的密钥有误") case float64:
certId = strconv.Itoa(int(v))
case string:
certId = v
default:
logger.Info("=============上传证书获取失败=============")
return nil, errors.New("证书 ID 类型错误")
}
certObj, err := cert.GetCert(certId)
if err != nil {
logger.Error(err.Error())
logger.Info("=============上传证书获取失败=============")
return nil, err
}
if certObj == nil {
logger.Error("证书不存在")
logger.Info("=============上传证书获取失败=============")
return nil, errors.New("证书不存在")
}
logger.Debug(fmt.Sprintf("证书 ID: %s", certId))
return certObj, nil
} }
certStr, ok := params["cert"].(string)
if !ok {
logger.Error("上传的证书有误")
logger.Info("=============上传失败=============")
return nil, errors.New("上传的证书有误")
}
err := cert.UploadCert(keyStr, certStr)
if err != nil {
logger.Error(err.Error())
logger.Info("=============上传失败=============")
return nil, err
}
logger.Info("=============上传成功=============")
return params, nil
} }
func notify(params map[string]any) (any, error) { func notify(params map[string]any) (any, error) {

View File

@ -179,3 +179,24 @@ func GetPublicIP() (string, error) {
return string(body), nil return string(body), nil
} }
func ContainsAllIgnoreBRepeats(a, b []string) bool {
// 构建 A 的集合
setA := make(map[string]struct{})
for _, item := range a {
setA[item] = struct{}{}
}
// 遍历 B 的唯一元素,判断是否在 A 中
seen := make(map[string]struct{})
for _, item := range b {
if _, checked := seen[item]; checked {
continue
}
seen[item] = struct{}{}
if _, ok := setA[item]; !ok {
return false
}
}
return true
}