mirror of https://github.com/1Panel-dev/1Panel
appstorecrontabdatabasedockerdocker-composedocker-containerdocker-imagedocker-uifilemanagerlamplnmppanel
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
624 lines
18 KiB
624 lines
18 KiB
package service |
|
|
|
import ( |
|
"context" |
|
"crypto" |
|
"crypto/x509" |
|
"encoding/pem" |
|
"fmt" |
|
"github.com/1Panel-dev/1Panel/backend/app/dto/request" |
|
"github.com/1Panel-dev/1Panel/backend/app/dto/response" |
|
"github.com/1Panel-dev/1Panel/backend/app/model" |
|
"github.com/1Panel-dev/1Panel/backend/app/repo" |
|
"github.com/1Panel-dev/1Panel/backend/buserr" |
|
"github.com/1Panel-dev/1Panel/backend/constant" |
|
"github.com/1Panel-dev/1Panel/backend/global" |
|
"github.com/1Panel-dev/1Panel/backend/i18n" |
|
"github.com/1Panel-dev/1Panel/backend/utils/cmd" |
|
"github.com/1Panel-dev/1Panel/backend/utils/common" |
|
"github.com/1Panel-dev/1Panel/backend/utils/files" |
|
"github.com/1Panel-dev/1Panel/backend/utils/ssl" |
|
"github.com/go-acme/lego/v4/certcrypto" |
|
legoLogger "github.com/go-acme/lego/v4/log" |
|
"github.com/jinzhu/gorm" |
|
"log" |
|
"os" |
|
"path" |
|
"strconv" |
|
"strings" |
|
"time" |
|
) |
|
|
|
type WebsiteSSLService struct { |
|
} |
|
|
|
type IWebsiteSSLService interface { |
|
Page(search request.WebsiteSSLSearch) (int64, []response.WebsiteSSLDTO, error) |
|
GetSSL(id uint) (*response.WebsiteSSLDTO, error) |
|
Search(req request.WebsiteSSLSearch) ([]response.WebsiteSSLDTO, error) |
|
Create(create request.WebsiteSSLCreate) (request.WebsiteSSLCreate, error) |
|
GetDNSResolve(req request.WebsiteDNSReq) ([]response.WebsiteDNSRes, error) |
|
GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO, error) |
|
Delete(ids []uint) error |
|
Update(update request.WebsiteSSLUpdate) error |
|
Upload(req request.WebsiteSSLUpload) error |
|
ObtainSSL(apply request.WebsiteSSLApply) error |
|
SyncForRestart() error |
|
DownloadFile(id uint) (*os.File, error) |
|
} |
|
|
|
func NewIWebsiteSSLService() IWebsiteSSLService { |
|
return &WebsiteSSLService{} |
|
} |
|
|
|
func (w WebsiteSSLService) Page(search request.WebsiteSSLSearch) (int64, []response.WebsiteSSLDTO, error) { |
|
var ( |
|
result []response.WebsiteSSLDTO |
|
) |
|
total, sslList, err := websiteSSLRepo.Page(search.Page, search.PageSize, commonRepo.WithOrderBy("created_at desc")) |
|
if err != nil { |
|
return 0, nil, err |
|
} |
|
for _, model := range sslList { |
|
result = append(result, response.WebsiteSSLDTO{ |
|
WebsiteSSL: model, |
|
LogPath: path.Join(constant.SSLLogDir, fmt.Sprintf("%s-ssl-%d.log", model.PrimaryDomain, model.ID)), |
|
}) |
|
} |
|
return total, result, err |
|
} |
|
|
|
func (w WebsiteSSLService) GetSSL(id uint) (*response.WebsiteSSLDTO, error) { |
|
var res response.WebsiteSSLDTO |
|
websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(id)) |
|
if err != nil { |
|
return nil, err |
|
} |
|
res.WebsiteSSL = *websiteSSL |
|
return &res, nil |
|
} |
|
|
|
func (w WebsiteSSLService) Search(search request.WebsiteSSLSearch) ([]response.WebsiteSSLDTO, error) { |
|
var ( |
|
opts []repo.DBOption |
|
result []response.WebsiteSSLDTO |
|
) |
|
opts = append(opts, commonRepo.WithOrderBy("created_at desc")) |
|
if search.AcmeAccountID != "" { |
|
acmeAccountID, err := strconv.ParseUint(search.AcmeAccountID, 10, 64) |
|
if err != nil { |
|
return nil, err |
|
} |
|
opts = append(opts, websiteSSLRepo.WithByAcmeAccountId(uint(acmeAccountID))) |
|
} |
|
sslList, err := websiteSSLRepo.List(opts...) |
|
if err != nil { |
|
return nil, err |
|
} |
|
for _, sslModel := range sslList { |
|
result = append(result, response.WebsiteSSLDTO{ |
|
WebsiteSSL: sslModel, |
|
}) |
|
} |
|
return result, err |
|
} |
|
|
|
func (w WebsiteSSLService) Create(create request.WebsiteSSLCreate) (request.WebsiteSSLCreate, error) { |
|
if create.Nameserver1 != "" && !common.IsValidIP(create.Nameserver1) { |
|
return create, buserr.New("ErrParseIP") |
|
} |
|
if create.Nameserver2 != "" && !common.IsValidIP(create.Nameserver2) { |
|
return create, buserr.New("ErrParseIP") |
|
} |
|
var res request.WebsiteSSLCreate |
|
acmeAccount, err := websiteAcmeRepo.GetFirst(commonRepo.WithByID(create.AcmeAccountID)) |
|
if err != nil { |
|
return res, err |
|
} |
|
websiteSSL := model.WebsiteSSL{ |
|
Status: constant.SSLInit, |
|
Provider: create.Provider, |
|
AcmeAccountID: acmeAccount.ID, |
|
PrimaryDomain: create.PrimaryDomain, |
|
ExpireDate: time.Now(), |
|
KeyType: create.KeyType, |
|
PushDir: create.PushDir, |
|
Description: create.Description, |
|
Nameserver1: create.Nameserver1, |
|
Nameserver2: create.Nameserver2, |
|
SkipDNS: create.SkipDNS, |
|
DisableCNAME: create.DisableCNAME, |
|
ExecShell: create.ExecShell, |
|
} |
|
if create.ExecShell { |
|
websiteSSL.Shell = create.Shell |
|
} |
|
if create.PushDir { |
|
fileOP := files.NewFileOp() |
|
if !fileOP.Stat(create.Dir) { |
|
_ = fileOP.CreateDir(create.Dir, 0755) |
|
} |
|
websiteSSL.Dir = create.Dir |
|
} |
|
|
|
var domains []string |
|
if create.OtherDomains != "" { |
|
otherDomainArray := strings.Split(create.OtherDomains, "\n") |
|
for _, domain := range otherDomainArray { |
|
if !common.IsValidDomain(domain) { |
|
err = buserr.WithName("ErrDomainFormat", domain) |
|
return res, err |
|
} |
|
domains = append(domains, domain) |
|
} |
|
} |
|
websiteSSL.Domains = strings.Join(domains, ",") |
|
|
|
if create.Provider == constant.DNSAccount || create.Provider == constant.Http { |
|
websiteSSL.AutoRenew = create.AutoRenew |
|
} |
|
if create.Provider == constant.DNSAccount { |
|
dnsAccount, err := websiteDnsRepo.GetFirst(commonRepo.WithByID(create.DnsAccountID)) |
|
if err != nil { |
|
return res, err |
|
} |
|
websiteSSL.DnsAccountID = dnsAccount.ID |
|
} |
|
|
|
if err := websiteSSLRepo.Create(context.TODO(), &websiteSSL); err != nil { |
|
return res, err |
|
} |
|
create.ID = websiteSSL.ID |
|
go func() { |
|
if create.Provider != constant.DnsManual { |
|
if err = w.ObtainSSL(request.WebsiteSSLApply{ |
|
ID: websiteSSL.ID, |
|
}); err != nil { |
|
global.LOG.Errorf("obtain ssl failed, err: %v", err) |
|
} |
|
} |
|
}() |
|
return create, nil |
|
} |
|
|
|
func (w WebsiteSSLService) ObtainSSL(apply request.WebsiteSSLApply) error { |
|
var ( |
|
err error |
|
websiteSSL *model.WebsiteSSL |
|
acmeAccount *model.WebsiteAcmeAccount |
|
dnsAccount *model.WebsiteDnsAccount |
|
) |
|
|
|
websiteSSL, err = websiteSSLRepo.GetFirst(commonRepo.WithByID(apply.ID)) |
|
if err != nil { |
|
return err |
|
} |
|
acmeAccount, err = websiteAcmeRepo.GetFirst(commonRepo.WithByID(websiteSSL.AcmeAccountID)) |
|
if err != nil { |
|
return err |
|
} |
|
client, err := ssl.NewAcmeClient(acmeAccount) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
switch websiteSSL.Provider { |
|
case constant.DNSAccount: |
|
dnsAccount, err = websiteDnsRepo.GetFirst(commonRepo.WithByID(websiteSSL.DnsAccountID)) |
|
if err != nil { |
|
return err |
|
} |
|
if err = client.UseDns(ssl.DnsType(dnsAccount.Type), dnsAccount.Authorization, *websiteSSL); err != nil { |
|
return err |
|
} |
|
case constant.Http: |
|
appInstall, err := getAppInstallByKey(constant.AppOpenresty) |
|
if err != nil { |
|
if gorm.IsRecordNotFoundError(err) { |
|
return buserr.New("ErrOpenrestyNotFound") |
|
} |
|
return err |
|
} |
|
if err := client.UseHTTP(path.Join(appInstall.GetPath(), "root")); err != nil { |
|
return err |
|
} |
|
case constant.DnsManual: |
|
if err := client.UseManualDns(); err != nil { |
|
return err |
|
} |
|
} |
|
|
|
domains := []string{websiteSSL.PrimaryDomain} |
|
if websiteSSL.Domains != "" { |
|
domains = append(domains, strings.Split(websiteSSL.Domains, ",")...) |
|
} |
|
|
|
var privateKey crypto.PrivateKey |
|
if websiteSSL.PrivateKey == "" { |
|
privateKey, err = certcrypto.GeneratePrivateKey(ssl.KeyType(websiteSSL.KeyType)) |
|
if err != nil { |
|
return err |
|
} |
|
} else { |
|
block, _ := pem.Decode([]byte(websiteSSL.PrivateKey)) |
|
if block == nil { |
|
return buserr.New("invalid PEM block") |
|
} |
|
var privKey crypto.PrivateKey |
|
keyType := ssl.KeyType(websiteSSL.KeyType) |
|
switch keyType { |
|
case certcrypto.EC256, certcrypto.EC384: |
|
privKey, err = x509.ParseECPrivateKey(block.Bytes) |
|
if err != nil { |
|
return nil |
|
} |
|
case certcrypto.RSA2048, certcrypto.RSA3072, certcrypto.RSA4096: |
|
privKey, err = x509.ParsePKCS1PrivateKey(block.Bytes) |
|
if err != nil { |
|
return nil |
|
} |
|
} |
|
privateKey = privKey |
|
} |
|
|
|
websiteSSL.Status = constant.SSLApply |
|
err = websiteSSLRepo.Save(websiteSSL) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
go func() { |
|
logFile, _ := os.OpenFile(path.Join(constant.SSLLogDir, fmt.Sprintf("%s-ssl-%d.log", websiteSSL.PrimaryDomain, websiteSSL.ID)), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0666) |
|
defer logFile.Close() |
|
logger := log.New(logFile, "", log.LstdFlags) |
|
legoLogger.Logger = logger |
|
startMsg := i18n.GetMsgWithMap("ApplySSLStart", map[string]interface{}{"domain": strings.Join(domains, ","), "type": i18n.GetMsgByKey(websiteSSL.Provider)}) |
|
if websiteSSL.Provider == constant.DNSAccount { |
|
startMsg = startMsg + i18n.GetMsgWithMap("DNSAccountName", map[string]interface{}{"name": dnsAccount.Name, "type": dnsAccount.Type}) |
|
} |
|
legoLogger.Logger.Println(startMsg) |
|
resource, err := client.ObtainSSL(domains, privateKey) |
|
if err != nil { |
|
handleError(websiteSSL, err) |
|
return |
|
} |
|
websiteSSL.PrivateKey = string(resource.PrivateKey) |
|
websiteSSL.Pem = string(resource.Certificate) |
|
websiteSSL.CertURL = resource.CertURL |
|
certBlock, _ := pem.Decode(resource.Certificate) |
|
cert, err := x509.ParseCertificate(certBlock.Bytes) |
|
if err != nil { |
|
handleError(websiteSSL, err) |
|
return |
|
} |
|
websiteSSL.ExpireDate = cert.NotAfter |
|
websiteSSL.StartDate = cert.NotBefore |
|
websiteSSL.Type = cert.Issuer.CommonName |
|
websiteSSL.Organization = cert.Issuer.Organization[0] |
|
websiteSSL.Status = constant.SSLReady |
|
legoLogger.Logger.Println(i18n.GetMsgWithMap("ApplySSLSuccess", map[string]interface{}{"domain": strings.Join(domains, ",")})) |
|
saveCertificateFile(websiteSSL, logger) |
|
|
|
if websiteSSL.ExecShell { |
|
workDir := constant.DataDir |
|
if websiteSSL.PushDir { |
|
workDir = websiteSSL.Dir |
|
} |
|
legoLogger.Logger.Println(i18n.GetMsgByKey("ExecShellStart")) |
|
if err = cmd.ExecShellWithTimeOut(websiteSSL.Shell, workDir, logger, 30*time.Minute); err != nil { |
|
legoLogger.Logger.Println(i18n.GetMsgWithMap("ErrExecShell", map[string]interface{}{"err": err.Error()})) |
|
} else { |
|
legoLogger.Logger.Println(i18n.GetMsgByKey("ExecShellSuccess")) |
|
} |
|
} |
|
|
|
err = websiteSSLRepo.Save(websiteSSL) |
|
if err != nil { |
|
return |
|
} |
|
|
|
websites, _ := websiteRepo.GetBy(websiteRepo.WithWebsiteSSLID(websiteSSL.ID)) |
|
if len(websites) > 0 { |
|
for _, website := range websites { |
|
legoLogger.Logger.Println(i18n.GetMsgWithMap("ApplyWebSiteSSLLog", map[string]interface{}{"name": website.PrimaryDomain})) |
|
if err := createPemFile(website, *websiteSSL); err != nil { |
|
legoLogger.Logger.Println(i18n.GetMsgWithMap("ErrUpdateWebsiteSSL", map[string]interface{}{"name": website.PrimaryDomain, "err": err.Error()})) |
|
} |
|
} |
|
nginxInstall, err := getAppInstallByKey(constant.AppOpenresty) |
|
if err != nil { |
|
return |
|
} |
|
if err := opNginx(nginxInstall.ContainerName, constant.NginxReload); err != nil { |
|
legoLogger.Logger.Println(i18n.GetMsgByKey(constant.ErrSSLApply)) |
|
return |
|
} |
|
legoLogger.Logger.Println(i18n.GetMsgByKey("ApplyWebSiteSSLSuccess")) |
|
} |
|
}() |
|
|
|
return nil |
|
} |
|
|
|
func handleError(websiteSSL *model.WebsiteSSL, err error) { |
|
if websiteSSL.Status == constant.SSLInit || websiteSSL.Status == constant.SSLError { |
|
websiteSSL.Status = constant.Error |
|
} else { |
|
websiteSSL.Status = constant.SSLApplyError |
|
} |
|
websiteSSL.Message = err.Error() |
|
legoLogger.Logger.Println(i18n.GetErrMsg("ApplySSLFailed", map[string]interface{}{"domain": websiteSSL.PrimaryDomain, "detail": err.Error()})) |
|
_ = websiteSSLRepo.Save(websiteSSL) |
|
} |
|
|
|
func (w WebsiteSSLService) GetDNSResolve(req request.WebsiteDNSReq) ([]response.WebsiteDNSRes, error) { |
|
acmeAccount, err := websiteAcmeRepo.GetFirst(commonRepo.WithByID(req.AcmeAccountID)) |
|
if err != nil { |
|
return nil, err |
|
} |
|
|
|
client, err := ssl.NewAcmeClient(acmeAccount) |
|
if err != nil { |
|
return nil, err |
|
} |
|
resolves, err := client.GetDNSResolve(req.Domains) |
|
if err != nil { |
|
return nil, err |
|
} |
|
var res []response.WebsiteDNSRes |
|
for k, v := range resolves { |
|
res = append(res, response.WebsiteDNSRes{ |
|
Domain: k, |
|
Key: v.Key, |
|
Value: v.Value, |
|
Err: v.Err, |
|
}) |
|
} |
|
return res, nil |
|
} |
|
|
|
func (w WebsiteSSLService) GetWebsiteSSL(websiteId uint) (response.WebsiteSSLDTO, error) { |
|
var res response.WebsiteSSLDTO |
|
website, err := websiteRepo.GetFirst(commonRepo.WithByID(websiteId)) |
|
if err != nil { |
|
return res, err |
|
} |
|
websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(website.WebsiteSSLID)) |
|
if err != nil { |
|
return res, err |
|
} |
|
res.WebsiteSSL = *websiteSSL |
|
return res, nil |
|
} |
|
|
|
func (w WebsiteSSLService) Delete(ids []uint) error { |
|
var names []string |
|
for _, id := range ids { |
|
if websites, _ := websiteRepo.GetBy(websiteRepo.WithWebsiteSSLID(id)); len(websites) > 0 { |
|
oldSSL, _ := websiteSSLRepo.GetFirst(commonRepo.WithByID(id)) |
|
if oldSSL.ID > 0 { |
|
names = append(names, oldSSL.PrimaryDomain) |
|
} |
|
continue |
|
} |
|
sslSetting, _ := settingRepo.Get(settingRepo.WithByKey("SSL")) |
|
if sslSetting.Value == "enable" { |
|
sslID, _ := settingRepo.Get(settingRepo.WithByKey("SSLID")) |
|
idValue, _ := strconv.Atoi(sslID.Value) |
|
if idValue > 0 && uint(idValue) == id { |
|
return buserr.New("ErrDeleteWithPanelSSL") |
|
} |
|
} |
|
_ = websiteSSLRepo.DeleteBy(commonRepo.WithByID(id)) |
|
} |
|
if len(names) > 0 { |
|
return buserr.WithName("ErrSSLCannotDelete", strings.Join(names, ",")) |
|
} |
|
return nil |
|
} |
|
|
|
func (w WebsiteSSLService) Update(update request.WebsiteSSLUpdate) error { |
|
websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(update.ID)) |
|
if err != nil { |
|
return err |
|
} |
|
updateParams := make(map[string]interface{}) |
|
updateParams["primary_domain"] = update.PrimaryDomain |
|
updateParams["description"] = update.Description |
|
updateParams["provider"] = update.Provider |
|
updateParams["push_dir"] = update.PushDir |
|
updateParams["disable_cname"] = update.DisableCNAME |
|
updateParams["skip_dns"] = update.SkipDNS |
|
updateParams["nameserver1"] = update.Nameserver1 |
|
updateParams["nameserver2"] = update.Nameserver2 |
|
updateParams["exec_shell"] = update.ExecShell |
|
if update.ExecShell { |
|
updateParams["shell"] = update.Shell |
|
} else { |
|
updateParams["shell"] = "" |
|
} |
|
|
|
if websiteSSL.Provider != constant.SelfSigned { |
|
acmeAccount, err := websiteAcmeRepo.GetFirst(commonRepo.WithByID(update.AcmeAccountID)) |
|
if err != nil { |
|
return err |
|
} |
|
updateParams["acme_account_id"] = acmeAccount.ID |
|
} |
|
|
|
if update.PushDir { |
|
fileOP := files.NewFileOp() |
|
if !fileOP.Stat(update.Dir) { |
|
_ = fileOP.CreateDir(update.Dir, 0755) |
|
} |
|
updateParams["dir"] = update.Dir |
|
} |
|
var domains []string |
|
if update.OtherDomains != "" { |
|
otherDomainArray := strings.Split(update.OtherDomains, "\n") |
|
for _, domain := range otherDomainArray { |
|
if !common.IsValidDomain(domain) { |
|
return buserr.WithName("ErrDomainFormat", domain) |
|
} |
|
domains = append(domains, domain) |
|
} |
|
} |
|
updateParams["domains"] = strings.Join(domains, ",") |
|
if update.Provider == constant.DNSAccount || update.Provider == constant.Http || update.Provider == constant.SelfSigned { |
|
updateParams["auto_renew"] = update.AutoRenew |
|
} else { |
|
updateParams["auto_renew"] = false |
|
} |
|
if update.Provider == constant.DNSAccount { |
|
dnsAccount, err := websiteDnsRepo.GetFirst(commonRepo.WithByID(update.DnsAccountID)) |
|
if err != nil { |
|
return err |
|
} |
|
updateParams["dns_account_id"] = dnsAccount.ID |
|
} |
|
return websiteSSLRepo.SaveByMap(websiteSSL, updateParams) |
|
} |
|
|
|
func (w WebsiteSSLService) Upload(req request.WebsiteSSLUpload) error { |
|
websiteSSL := &model.WebsiteSSL{ |
|
Provider: constant.Manual, |
|
Description: req.Description, |
|
Status: constant.SSLReady, |
|
} |
|
var err error |
|
if req.SSLID > 0 { |
|
websiteSSL, err = websiteSSLRepo.GetFirst(commonRepo.WithByID(req.SSLID)) |
|
if err != nil { |
|
return err |
|
} |
|
websiteSSL.Description = req.Description |
|
} |
|
if req.Type == "local" { |
|
fileOp := files.NewFileOp() |
|
if !fileOp.Stat(req.PrivateKeyPath) { |
|
return buserr.New("ErrSSLKeyNotFound") |
|
} |
|
if !fileOp.Stat(req.CertificatePath) { |
|
return buserr.New("ErrSSLCertificateNotFound") |
|
} |
|
if content, err := fileOp.GetContent(req.PrivateKeyPath); err != nil { |
|
return err |
|
} else { |
|
websiteSSL.PrivateKey = string(content) |
|
} |
|
if content, err := fileOp.GetContent(req.CertificatePath); err != nil { |
|
return err |
|
} else { |
|
websiteSSL.Pem = string(content) |
|
} |
|
} else { |
|
websiteSSL.PrivateKey = req.PrivateKey |
|
websiteSSL.Pem = req.Certificate |
|
} |
|
|
|
privateKeyCertBlock, _ := pem.Decode([]byte(websiteSSL.PrivateKey)) |
|
if privateKeyCertBlock == nil { |
|
return buserr.New("ErrSSLKeyFormat") |
|
} |
|
|
|
var ( |
|
cert *x509.Certificate |
|
pemData = []byte(websiteSSL.Pem) |
|
) |
|
for { |
|
certBlock, reset := pem.Decode(pemData) |
|
if certBlock == nil { |
|
break |
|
} |
|
cert, err = x509.ParseCertificate(certBlock.Bytes) |
|
if err != nil { |
|
return err |
|
} |
|
if len(cert.DNSNames) > 0 || len(cert.IPAddresses) > 0 { |
|
break |
|
} |
|
pemData = reset |
|
} |
|
if pemData == nil { |
|
return buserr.New("ErrSSLCertificateFormat") |
|
} |
|
|
|
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 |
|
} |
|
|
|
var domains []string |
|
if len(cert.DNSNames) > 0 { |
|
websiteSSL.PrimaryDomain = cert.DNSNames[0] |
|
domains = cert.DNSNames[1:] |
|
} |
|
if len(cert.IPAddresses) > 0 { |
|
if websiteSSL.PrimaryDomain == "" { |
|
websiteSSL.PrimaryDomain = cert.IPAddresses[0].String() |
|
for _, ip := range cert.IPAddresses[1:] { |
|
domains = append(domains, ip.String()) |
|
} |
|
} else { |
|
for _, ip := range cert.IPAddresses { |
|
domains = append(domains, ip.String()) |
|
} |
|
} |
|
} |
|
websiteSSL.Domains = strings.Join(domains, ",") |
|
|
|
if websiteSSL.ID > 0 { |
|
if err := UpdateSSLConfig(*websiteSSL); err != nil { |
|
return err |
|
} |
|
return websiteSSLRepo.Save(websiteSSL) |
|
} |
|
return websiteSSLRepo.Create(context.Background(), websiteSSL) |
|
} |
|
|
|
func (w WebsiteSSLService) DownloadFile(id uint) (*os.File, error) { |
|
websiteSSL, err := websiteSSLRepo.GetFirst(commonRepo.WithByID(id)) |
|
if err != nil { |
|
return nil, err |
|
} |
|
fileOp := files.NewFileOp() |
|
dir := path.Join(global.CONF.System.BaseDir, "1panel/tmp/ssl", websiteSSL.PrimaryDomain) |
|
if fileOp.Stat(dir) { |
|
if err = fileOp.DeleteDir(dir); err != nil { |
|
return nil, err |
|
} |
|
} |
|
if err = fileOp.CreateDir(dir, 0666); err != nil { |
|
return nil, err |
|
} |
|
if err = fileOp.WriteFile(path.Join(dir, "fullchain.pem"), strings.NewReader(websiteSSL.Pem), 0644); err != nil { |
|
return nil, err |
|
} |
|
if err = fileOp.WriteFile(path.Join(dir, "privkey.pem"), strings.NewReader(websiteSSL.PrivateKey), 0644); err != nil { |
|
return nil, err |
|
} |
|
fileName := websiteSSL.PrimaryDomain + ".zip" |
|
if err = fileOp.Compress([]string{path.Join(dir, "fullchain.pem"), path.Join(dir, "privkey.pem")}, dir, fileName, files.SdkZip, ""); err != nil { |
|
return nil, err |
|
} |
|
return os.Open(path.Join(dir, fileName)) |
|
} |
|
|
|
func (w WebsiteSSLService) SyncForRestart() error { |
|
sslList, err := websiteSSLRepo.List() |
|
if err != nil { |
|
return err |
|
} |
|
for _, ssl := range sslList { |
|
if ssl.Status == constant.SSLApply { |
|
ssl.Status = constant.SystemRestart |
|
ssl.Message = "System restart causing interrupt" |
|
_ = websiteSSLRepo.Save(&ssl) |
|
} |
|
} |
|
return nil |
|
}
|
|
|