修改申请证书

pull/135/head
zhangchenhao 2025-05-22 18:47:16 +08:00
parent 7b4c184ade
commit 6f3d4eb81f
6 changed files with 120 additions and 111 deletions

View File

@ -180,6 +180,7 @@ func AddEAB(c *gin.Context) {
Kid string `form:"Kid"`
HmacEncoded string `form:"HmacEncoded"`
CA string `form:"ca"`
Mail string `form:"mail"`
}
err := c.Bind(&form)
if err != nil {
@ -190,6 +191,7 @@ func AddEAB(c *gin.Context) {
form.Kid = strings.TrimSpace(form.Kid)
form.HmacEncoded = strings.TrimSpace(form.HmacEncoded)
form.CA = strings.TrimSpace(form.CA)
form.Mail = strings.TrimSpace(form.Mail)
if form.Name == "" {
public.FailMsg(c, "名称不能为空")
return
@ -206,9 +208,14 @@ func AddEAB(c *gin.Context) {
public.FailMsg(c, "CA不能为空")
return
}
err = access.AddEAB(form.Name, form.Kid, form.HmacEncoded, form.CA)
if form.Mail == "" {
public.FailMsg(c, "Email不能为空")
return
}
err = access.AddEAB(form.Name, form.Kid, form.HmacEncoded, form.CA, form.Mail)
if err != nil {
public.FailMsg(c, err.Error())
return
}
public.SuccessMsg(c, "添加成功")
return
@ -221,6 +228,7 @@ func UpdEAB(c *gin.Context) {
Kid string `form:"Kid"`
HmacEncoded string `form:"HmacEncoded"`
CA string `form:"ca"`
Mail string `form:"mail"`
}
err := c.Bind(&form)
if err != nil {
@ -231,6 +239,7 @@ func UpdEAB(c *gin.Context) {
form.Kid = strings.TrimSpace(form.Kid)
form.HmacEncoded = strings.TrimSpace(form.HmacEncoded)
form.CA = strings.TrimSpace(form.CA)
form.Mail = strings.TrimSpace(form.Mail)
if form.Name == "" {
public.FailMsg(c, "名称不能为空")
return
@ -247,7 +256,11 @@ func UpdEAB(c *gin.Context) {
public.FailMsg(c, "CA不能为空")
return
}
err = access.UpdEAB(form.ID, form.Name, form.Kid, form.HmacEncoded, form.CA)
if form.Mail == "" {
public.FailMsg(c, "mail不能为空")
return
}
err = access.UpdEAB(form.ID, form.Name, form.Kid, form.HmacEncoded, form.CA, form.Mail)
if err != nil {
public.FailMsg(c, err.Error())
}
@ -313,6 +326,7 @@ func TestAccess(c *gin.Context) {
result = deploy.QiniuAPITest(form.ID)
default:
public.FailMsg(c, "不支持测试的提供商")
return
}
if result != nil {
@ -337,7 +351,7 @@ func GetSiteList(c *gin.Context) {
public.FailMsg(c, err.Error())
return
}
var siteList []any
switch form.Type {
case "btpanel":
@ -345,11 +359,11 @@ func GetSiteList(c *gin.Context) {
default:
public.FailMsg(c, "不支持的提供商")
}
if err != nil {
public.FailMsg(c, fmt.Sprintf("获取网站列表失败%v", err))
return
}
public.SuccessData(c, siteList, len(siteList))
}
}

View File

@ -62,7 +62,7 @@ func GetEABList(search string, p, limit int64) ([]map[string]any, int, error) {
return data, int(count), nil
}
func AddEAB(name, Kid, HmacEncoded, ca string) error {
func AddEAB(name, Kid, HmacEncoded, ca, mail string) error {
s, err := GetSqliteEAB()
if err != nil {
return err
@ -76,11 +76,12 @@ func AddEAB(name, Kid, HmacEncoded, ca string) error {
"ca": ca,
"update_time": now,
"create_time": now,
"mail": mail,
})
return err
}
func UpdEAB(id, name, Kid, HmacEncoded, ca string) error {
func UpdEAB(id, name, Kid, HmacEncoded, ca, mail string) error {
s, err := GetSqliteEAB()
if err != nil {
return err
@ -93,6 +94,7 @@ func UpdEAB(id, name, Kid, HmacEncoded, ca string) error {
"HmacEncoded": HmacEncoded,
"ca": ca,
"update_time": now,
"mail": mail,
})
return err
}
@ -113,7 +115,7 @@ func GetEAB(id string) (map[string]interface{}, error) {
if err != nil {
return nil, err
}
s.Close()
defer s.Close()
data, err := s.Where("id = ?", []interface{}{id}).Find()
if err != nil {
return nil, err

View File

@ -92,13 +92,38 @@ func GetDNSProvider(providerName string, creds map[string]string) (challenge.Pro
config.AccessKey = creds["access_key"]
config.SecretKey = creds["secret_key"]
return volcengine.NewDNSProviderConfig(config)
default:
return nil, fmt.Errorf("不支持的 DNS Provider: %s", providerName)
}
}
func GetAcmeClient(db *public.Sqlite, email, algorithm, ca, proxy, eabId string, logger *public.Logger) (*lego.Client, error) {
func GetAcmeClient(db *public.Sqlite, email, algorithm, proxy, eabId string, logger *public.Logger) (*lego.Client, error) {
var (
ca string
eabData map[string]any
err error
)
switch eabId {
case "let", "":
ca = "Let's Encrypt"
default:
eabData, err = access.GetEAB(eabId)
if err != nil {
return nil, err
}
if eabData == nil {
return nil, fmt.Errorf("未找到EAB信息")
}
if eabData["Kid"] == nil {
return nil, fmt.Errorf("Kid不能为空")
}
if eabData["HmacEncoded"] == nil {
return nil, fmt.Errorf("HmacEncoded不能为空")
}
ca = eabData["ca"].(string)
}
user, err := LoadUserFromDB(db, email, ca)
if err != nil {
logger.Debug("acme账号不存在注册新账号")
@ -107,101 +132,54 @@ func GetAcmeClient(db *public.Sqlite, email, algorithm, ca, proxy, eabId string,
Email: email,
key: privateKey,
}
config := lego.NewConfig(user)
config.Certificate.KeyType = AlgorithmMap[algorithm]
config.CADirURL = CADirURLMap[ca]
if proxy != "" {
// 构建代理 HTTP 客户端
proxyURL, err := url.Parse(proxy) // 替换为你的代理地址
if err != nil {
return nil, fmt.Errorf("无效的代理地址: %v", err)
}
httpClient := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(proxyURL),
},
Timeout: 30 * time.Second,
}
config.HTTPClient = httpClient
}
client, err := lego.NewClient(config)
}
config := lego.NewConfig(user)
config.Certificate.KeyType = AlgorithmMap[algorithm]
config.CADirURL = CADirURLMap[ca]
if proxy != "" {
// 构建代理 HTTP 客户端
proxyURL, err := url.Parse(proxy) // 替换为你的代理地址
if err != nil {
return nil, err
return nil, fmt.Errorf("无效的代理地址: %v", err)
}
httpClient := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(proxyURL),
},
Timeout: 30 * time.Second,
}
config.HTTPClient = httpClient
}
client, err := lego.NewClient(config)
if err != nil {
return nil, err
}
if user.Registration == nil {
logger.Debug("正在注册账号:" + email)
var reg *registration.Resource
switch ca {
case "Let's Encrypt":
reg, err = client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
case "zerossl", "google":
// 获取EAB参数
var eabData map[string]any
if eabId == "" {
data, err := access.GetAllEAB(ca)
if err != nil {
return nil, err
}
if len(data) <= 0 {
return nil, fmt.Errorf("未找到EAB信息")
}
eabData = data[0]
} else {
eabData, err = access.GetEAB(eabId)
if err != nil {
return nil, err
}
if eabData == nil {
return nil, fmt.Errorf("未找到EAB信息")
}
}
Kid := eabData["kid"].(string)
if eabData != nil {
Kid := eabData["Kid"].(string)
HmacEncoded := eabData["HmacEncoded"].(string)
reg, err = client.Registration.RegisterWithExternalAccountBinding(registration.RegisterEABOptions{
TermsOfServiceAgreed: true,
Kid: Kid,
HmacEncoded: HmacEncoded,
})
default:
} else {
reg, err = client.Registration.Register(registration.RegisterOptions{TermsOfServiceAgreed: true})
}
if err != nil {
return nil, err
}
user.Registration = reg
err = SaveUserToDB(db, user, ca)
if err != nil {
return nil, err
}
logger.Debug("acme账号注册并保存成功")
return client, nil
} else {
config := lego.NewConfig(user)
config.Certificate.KeyType = AlgorithmMap[algorithm]
config.CADirURL = CADirURLMap[ca]
if proxy != "" {
// 构建代理 HTTP 客户端
proxyURL, err := url.Parse(proxy) // 替换为你的代理地址
if err != nil {
return nil, fmt.Errorf("无效的代理地址: %v", err)
}
httpClient := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(proxyURL),
},
Timeout: 30 * time.Second,
}
config.HTTPClient = httpClient
}
// 初始化 ACME 客户端
client, err := lego.NewClient(config)
if err != nil {
return nil, err
}
return client, nil
}
return client, nil
}
func GetCert(runId string, domainArr []string, endDay int, logger *public.Logger) (map[string]any, error) {
@ -272,7 +250,7 @@ func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
return nil, err
}
defer db.Close()
email, ok := cfg["email"].(string)
if !ok {
return nil, fmt.Errorf("参数错误email")
@ -305,10 +283,6 @@ func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
if !ok {
algorithm = "RSA2048"
}
ca, ok := cfg["ca"].(string)
if !ok {
ca = "Let's Encrypt"
}
proxy, ok := cfg["proxy"].(string)
if !ok {
proxy = ""
@ -322,7 +296,7 @@ func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
default:
eabId = ""
}
var providerID string
switch v := cfg["provider_id"].(type) {
case float64:
@ -348,7 +322,7 @@ func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
return nil, fmt.Errorf("参数错误name_server")
}
}
var skipCheck bool
if cfg["skip_check"] == nil {
// 默认跳过预检查
@ -383,12 +357,12 @@ func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
return nil, fmt.Errorf("参数错误skip_check")
}
}
domainArr := strings.Split(domains, ",")
for i := range domainArr {
domainArr[i] = strings.TrimSpace(domainArr[i])
}
// 获取上次申请的证书
runId, ok := cfg["_runId"].(string)
if !ok {
@ -402,7 +376,7 @@ func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
}
logger.Debug("正在申请证书,域名: " + domains)
// 创建 ACME 客户端
client, err := GetAcmeClient(db, email, algorithm, ca, proxy, eabId, logger)
client, err := GetAcmeClient(db, email, algorithm, proxy, eabId, logger)
if err != nil {
return nil, err
}
@ -421,13 +395,13 @@ func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
if err != nil {
return nil, err
}
// DNS 验证
provider, err := GetDNSProvider(providerStr, providerConfig)
if err != nil {
return nil, fmt.Errorf("创建 DNS provider 失败: %v", err)
}
if skipCheck {
// 跳过预检查
err = client.Challenge.SetDNS01Provider(provider,
@ -444,7 +418,7 @@ func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
if err != nil {
return nil, err
}
// fmt.Println(strings.Split(domains, ","))
request := certificate.ObtainRequest{
Domains: domainArr,
@ -454,18 +428,18 @@ func Apply(cfg map[string]any, logger *public.Logger) (map[string]any, error) {
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

View File

@ -31,6 +31,14 @@ func Deploy(cfg map[string]any, logger *public.Logger) error {
cfg["resource_type"] = "cos"
logger.Debug("部署到腾讯云COS...")
return DeployToTX(cfg)
case "tencentcloud-waf":
cfg["resource_type"] = "waf"
logger.Debug("部署到腾讯云WAF...")
return DeployToTX(cfg)
case "tencentcloud-teo":
cfg["resource_type"] = "teo"
logger.Debug("部署到腾讯云EdgeOne...")
return DeployToTX(cfg)
case "1panel":
logger.Debug("部署到1Panel...")
return Deploy1panel(cfg)

View File

@ -29,6 +29,7 @@ func UploadToTX(client *ssl.Client, key, cert string) (string, error) {
request := ssl.NewUploadCertificateRequest()
request.CertificatePublicKey = common.StringPtr(cert)
request.CertificatePrivateKey = common.StringPtr(key)
request.Repeatable = common.BoolPtr(false)
// 返回的resp是一个UploadCertificateResponse的实例与请求对象对应
response, err := client.UploadCertificate(request)
if _, ok := err.(*errors.TencentCloudSDKError); ok {
@ -53,7 +54,7 @@ func DeployToTX(cfg map[string]any) error {
if !ok {
return fmt.Errorf("证书错误cert")
}
var providerID string
switch v := cfg["provider_id"].(type) {
case float64:
@ -83,26 +84,35 @@ func DeployToTX(cfg map[string]any) error {
region = r
}
client := ClientTencentcloud(providerConfig["secret_id"], providerConfig["secret_key"], region)
// 上传证书
certificateId, err := UploadToTX(client, strings.TrimSpace(keyPem), strings.TrimSpace(certPem))
if err != nil {
return err
}
// fmt.Println(certificateId)
request := ssl.NewDeployCertificateInstanceRequest()
request.CertificateId = common.StringPtr(certificateId)
if cfg["resource_type"] == "cdn" {
resourceType := cfg["resource_type"].(string)
switch resourceType {
case "cdn", "waf", "teo":
domain, ok := cfg["domain"].(string)
if !ok {
return fmt.Errorf("参数错误domain")
}
request.InstanceIdList = common.StringPtrs([]string{domain})
request.ResourceType = common.StringPtr("cdn")
}
if cfg["resource_type"] == "cos" {
domain = strings.TrimSpace(domain)
domainArray := strings.Split(domain, ",")
if len(domainArray) == 0 {
return fmt.Errorf("参数错误domain")
}
for i, d := range domainArray {
domainArray[i] = strings.TrimSpace(d)
}
request.InstanceIdList = common.StringPtrs(domainArray)
request.ResourceType = common.StringPtr(resourceType)
case "cos":
domain, ok := cfg["domain"].(string)
if !ok {
return fmt.Errorf("参数错误domain")
@ -118,7 +128,7 @@ func DeployToTX(cfg map[string]any) error {
request.InstanceIdList = common.StringPtrs([]string{fmt.Sprintf("%s|%s|%s", region, bucket, domain)})
request.ResourceType = common.StringPtr("cos")
}
// 返回的resp是一个DeployCertificateInstanceResponse的实例与请求对象对应
response, err := client.DeployCertificateInstance(request)
if _, ok := err.(*errors.TencentCloudSDKError); ok {

View File

@ -187,7 +187,8 @@ func init() {
HmacEncoded TEXT not null,
ca TEXT not null,
create_time TEXT,
update_time TEXT
update_time TEXT,
mail TEXT not null
);
`)