fix: Resolve issue where bulk certificate setup creates duplicate server certificates (#11371)

This commit is contained in:
CityFun 2025-12-17 13:52:10 +08:00 committed by GitHub
parent 1f6cd6f4e9
commit 4fcf3e11cd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 76 additions and 57 deletions

View file

@ -3,9 +3,7 @@ package service
import (
"bytes"
"context"
"crypto/x509"
"encoding/base64"
"encoding/pem"
"errors"
"fmt"
"net"
@ -975,64 +973,10 @@ func (w WebsiteService) OpWebsiteHTTPS(ctx context.Context, req request.WebsiteH
websiteSSL = *websiteModel
}
if req.Type == constant.SSLManual {
var (
certificate string
privateKey string
)
switch req.ImportType {
case "paste":
certificate = req.Certificate
privateKey = req.PrivateKey
case "local":
fileOp := files.NewFileOp()
if !fileOp.Stat(req.PrivateKeyPath) {
return nil, buserr.New("ErrSSLKeyNotFound")
}
if !fileOp.Stat(req.CertificatePath) {
return nil, buserr.New("ErrSSLCertificateNotFound")
}
if content, err := fileOp.GetContent(req.PrivateKeyPath); err != nil {
return nil, err
} else {
privateKey = string(content)
}
if content, err := fileOp.GetContent(req.CertificatePath); err != nil {
return nil, err
} else {
certificate = string(content)
}
}
privateKeyCertBlock, _ := pem.Decode([]byte(privateKey))
if privateKeyCertBlock == nil {
return nil, buserr.New("ErrSSLKeyFormat")
}
certBlock, _ := pem.Decode([]byte(certificate))
if certBlock == nil {
return nil, buserr.New("ErrSSLCertificateFormat")
}
cert, err := x509.ParseCertificate(certBlock.Bytes)
websiteSSL, err = getManualWebsiteSSL(req)
if err != nil {
return nil, err
}
websiteSSL.ExpireDate = cert.NotAfter
websiteSSL.StartDate = cert.NotBefore
websiteSSL.Type = cert.Issuer.CommonName
if len(cert.Issuer.Organization) > 0 {
websiteSSL.Organization = cert.Issuer.Organization[0]
} else {
websiteSSL.Organization = cert.Issuer.CommonName
}
if len(cert.DNSNames) > 0 {
websiteSSL.PrimaryDomain = cert.DNSNames[0]
websiteSSL.Domains = strings.Join(cert.DNSNames, ",")
}
websiteSSL.Provider = constant.Manual
websiteSSL.PrivateKey = privateKey
websiteSSL.Pem = certificate
websiteSSL.Status = constant.SSLReady
res.SSL = websiteSSL
}

View file

@ -91,6 +91,17 @@ func (w WebsiteService) BatchSetHttps(ctx context.Context, req request.BatchWebs
HttpsPorts: req.HttpsPorts,
Http3: req.Http3,
}
if req.Type == constant.SSLManual {
websiteSSL, err := getManualWebsiteSSL(websiteHttpsOp)
if err != nil {
return err
}
if err = websiteSSLRepo.Create(ctx, &websiteSSL); err != nil {
return err
}
websiteHttpsOp.Type = constant.SSLExisted
websiteHttpsOp.WebsiteSSLID = websiteSSL.ID
}
opWebsiteTask := func(t *task.Task) error {
for _, web := range websites {
if web.Type == constant.Stream {

View file

@ -2,7 +2,9 @@ package service
import (
"context"
"crypto/x509"
"encoding/json"
"encoding/pem"
"fmt"
"log"
"net"
@ -1707,3 +1709,65 @@ func getNginxUpstreamServers(upstreamServers []*components.UpstreamServer) []dto
}
return servers
}
func getManualWebsiteSSL(req request.WebsiteHTTPSOp) (model.WebsiteSSL, error) {
var websiteSSL model.WebsiteSSL
var (
certificate string
privateKey string
)
switch req.ImportType {
case "paste":
certificate = req.Certificate
privateKey = req.PrivateKey
case "local":
fileOp := files.NewFileOp()
if !fileOp.Stat(req.PrivateKeyPath) {
return websiteSSL, buserr.New("ErrSSLKeyNotFound")
}
if !fileOp.Stat(req.CertificatePath) {
return websiteSSL, buserr.New("ErrSSLCertificateNotFound")
}
if content, err := fileOp.GetContent(req.PrivateKeyPath); err != nil {
return websiteSSL, err
} else {
privateKey = string(content)
}
if content, err := fileOp.GetContent(req.CertificatePath); err != nil {
return websiteSSL, err
} else {
certificate = string(content)
}
}
privateKeyCertBlock, _ := pem.Decode([]byte(privateKey))
if privateKeyCertBlock == nil {
return websiteSSL, buserr.New("ErrSSLKeyFormat")
}
certBlock, _ := pem.Decode([]byte(certificate))
if certBlock == nil {
return websiteSSL, buserr.New("ErrSSLCertificateFormat")
}
cert, err := x509.ParseCertificate(certBlock.Bytes)
if err != nil {
return websiteSSL, err
}
websiteSSL.ExpireDate = cert.NotAfter
websiteSSL.StartDate = cert.NotBefore
websiteSSL.Type = cert.Issuer.CommonName
if len(cert.Issuer.Organization) > 0 {
websiteSSL.Organization = cert.Issuer.Organization[0]
} else {
websiteSSL.Organization = cert.Issuer.CommonName
}
if len(cert.DNSNames) > 0 {
websiteSSL.PrimaryDomain = cert.DNSNames[0]
websiteSSL.Domains = strings.Join(cert.DNSNames, ",")
}
websiteSSL.Provider = constant.Manual
websiteSSL.PrivateKey = privateKey
websiteSSL.Pem = certificate
websiteSSL.Status = constant.SSLReady
return websiteSSL, nil
}