Add files via upload

This commit is contained in:
zhangch-dev
2025-05-06 18:51:53 +08:00
committed by GitHub
parent 0ccc0620f3
commit e7b5ac85e1
52 changed files with 7266 additions and 0 deletions

View File

@@ -0,0 +1,245 @@
package apply
import (
"ALLinSSL/backend/internal/access"
"ALLinSSL/backend/internal/cert"
"ALLinSSL/backend/public"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"encoding/json"
"fmt"
"github.com/go-acme/lego/v4/certcrypto"
"github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/challenge/dns01"
"github.com/go-acme/lego/v4/lego"
"github.com/go-acme/lego/v4/providers/dns/alidns"
"github.com/go-acme/lego/v4/providers/dns/tencentcloud"
"github.com/go-acme/lego/v4/registration"
"strconv"
"strings"
"time"
)
func GetSqlite() (*public.Sqlite, error) {
s, err := public.NewSqlite("data/data.db", "")
if err != nil {
return nil, err
}
s.Connect()
s.TableName = "_accounts"
return s, nil
}
func GetDNSProvider(providerName string, creds map[string]string) (challenge.Provider, error) {
switch providerName {
case "tencentcloud":
config := tencentcloud.NewDefaultConfig()
config.SecretID = creds["secret_id"]
config.SecretKey = creds["secret_key"]
return tencentcloud.NewDNSProviderConfig(config)
// case "cloudflare":
// config := cloudflare.NewDefaultConfig()
// config.AuthToken = creds["CLOUDFLARE_API_TOKEN"]
// return cloudflare.NewDNSProviderConfig(config)
case "aliyun":
config := alidns.NewDefaultConfig()
config.APIKey = creds["access_key"]
config.SecretKey = creds["access_secret"]
return alidns.NewDNSProviderConfig(config)
default:
return nil, fmt.Errorf("不支持的 DNS Provider: %s", providerName)
}
}
func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
db, err := GetSqlite()
if err != nil {
return nil, err
}
defer db.Close()
email, ok := cfg["email"].(string)
if !ok {
return nil, fmt.Errorf("参数错误email")
}
domains, ok := cfg["domains"].(string)
if !ok {
return nil, fmt.Errorf("参数错误domains")
}
providerStr, ok := cfg["provider"].(string)
if !ok {
return nil, fmt.Errorf("参数错误provider")
}
var providerID string
switch v := cfg["provider_id"].(type) {
case float64:
providerID = strconv.Itoa(int(v))
case string:
providerID = v
default:
return nil, fmt.Errorf("参数错误provider_id")
}
// 获取上次申请的证书
runId, ok := cfg["_runId"].(string)
if !ok {
return nil, fmt.Errorf("参数错误_runId")
}
if runId != "" {
s, err := public.NewSqlite("data/data.db", "")
if err != nil {
return nil, err
}
s.Connect()
s.TableName = "workflow_history"
defer s.Close()
// 查询 workflowId
wh, err := s.Where("id=?", []interface{}{runId}).Select()
if err != nil {
return nil, err
}
if len(wh) > 0 {
s.TableName = "cert"
certs, err := s.Where("workflow_id=?", []interface{}{wh[0]["workflow_id"]}).Select()
if err != nil {
return nil, err
}
if len(certs) > 0 {
layout := "2006-01-02 15:04:05"
var maxDays float64
var maxItem map[string]any
for i := range certs {
endTimeStr, ok := certs[i]["end_time"].(string)
if !ok {
continue
}
endTime, _ := time.Parse(layout, endTimeStr)
diff := endTime.Sub(time.Now()).Hours() / 24
if diff > maxDays {
maxDays = diff
maxItem = certs[i]
}
}
certObj := maxItem
// 判断证书是否过期
cfgEnd, ok := cfg["end_day"].(int)
if !ok || cfgEnd <= 0 {
cfgEnd = 30
}
if int(maxDays) > cfgEnd {
// 证书未过期,直接返回
logger.Debug(fmt.Sprintf("上次证书申请成功,剩余天数:%d 大于%d天已跳过申请复用此证书", int(maxDays), cfgEnd))
return map[string]any{
"cert": certObj["cert"],
"key": certObj["key"],
"issuerCert": certObj["issuer_cert"],
}, nil
}
}
}
}
logger.Debug("正在申请证书,域名: " + domains)
user, err := LoadUserFromDB(db, email)
if err != nil {
logger.Debug("acme账号不存在注册新账号")
privateKey, _ := ecdsa.GenerateKey(elliptic.P384(), rand.Reader)
user = &MyUser{
Email: email,
key: privateKey,
}
config := lego.NewConfig(user)
config.Certificate.KeyType = certcrypto.EC384
client, err := lego.NewClient(config)
if err != nil {
return nil, err
}
logger.Debug("正在注册账号:" + email)
reg, err := client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
if err != nil {
return nil, err
}
user.Registration = reg
err = SaveUserToDB(db, user)
if err != nil {
return nil, err
}
logger.Debug("账号注册并保存成功")
}
// 初始化 ACME 客户端
client, err := lego.NewClient(lego.NewConfig(user))
if err != nil {
return nil, err
}
// 获取 DNS 验证提供者
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
}
// DNS 验证
provider, err := GetDNSProvider(providerStr, providerConfig)
if err != nil {
return nil, fmt.Errorf("创建 DNS provider 失败: %v", err)
}
err = client.Challenge.SetDNS01Provider(provider,
dns01.WrapPreCheck(func(domain, fqdn, value string, check dns01.PreCheckFunc) (bool, error) {
// 跳过预检查
return true, nil
}),
dns01.AddRecursiveNameservers([]string{
"8.8.8.8:53",
"1.1.1.1:53",
}))
if err != nil {
return nil, err
}
// fmt.Println(strings.Split(domains, ","))
request := certificate.ObtainRequest{
Domains: strings.Split(domains, ","),
Bundle: true,
}
certObj, err := client.Certificate.Obtain(request)
if err != nil {
return nil, err
}
certStr := string(certObj.Certificate)
keyStr := string(certObj.PrivateKey)
issuerCertStr := string(certObj.IssuerCertificate)
// 保存证书和私钥
data := map[string]any{
"cert": certStr,
"key": keyStr,
"issuerCert": issuerCertStr,
}
err = cert.SaveCert("workflow", keyStr, certStr, issuerCertStr, runId)
if err != nil {
return nil, err
}
return data, nil
}