| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 | package certimport (	"github.com/0xJacky/Nginx-UI/internal/notification"	"github.com/0xJacky/Nginx-UI/model"	"github.com/0xJacky/Nginx-UI/settings"	"github.com/pkg/errors"	"github.com/uozi-tech/cosy/logger"	"runtime"	"strings"	"time")func AutoCert() {	defer func() {		if err := recover(); err != nil {			buf := make([]byte, 1024)			runtime.Stack(buf, false)			logger.Error("AutoCert Recover", err, string(buf))		}	}()	logger.Info("AutoCert Worker Started")	autoCertList := model.GetAutoCertList()	for _, certModel := range autoCertList {		autoCert(certModel)	}	logger.Info("AutoCert Worker End")}func autoCert(certModel *model.Cert) {	confName := certModel.Filename	log := &Logger{}	log.SetCertModel(certModel)	defer log.Exit()	if len(certModel.Filename) == 0 {		log.Error(ErrCertModelFilenameEmpty)		return	}	if len(certModel.Domains) == 0 {		log.Error(errors.New("domains list is empty, " +			"try to reopen auto-cert for this config:" + confName))		notification.Error("Renew Certificate Error", confName)		return	}	if certModel.SSLCertificatePath == "" {		log.Error(errors.New("ssl certificate path is empty, " +			"try to reopen auto-cert for this config:" + confName))		notification.Error("Renew Certificate Error", confName)		return	}	certInfo, err := GetCertInfo(certModel.SSLCertificatePath)	if err != nil {		// Get certificate info error, ignore this certificate		log.Error(errors.Wrap(err, "get certificate info error"))		notification.Error("Renew Certificate Error", strings.Join(certModel.Domains, ", "))		return	}	if int(time.Now().Sub(certInfo.NotBefore).Hours()/24) < settings.CertSettings.GetCertRenewalInterval() {		// not after settings.ServerSettings.RenewalInterval, ignore		return	}	// after 1 mo, reissue certificate	logChan := make(chan string, 1)	errChan := make(chan error, 1)	// support SAN certification	payload := &ConfigPayload{		CertID:                  certModel.ID,		ServerName:              certModel.Domains,		ChallengeMethod:         certModel.ChallengeMethod,		DNSCredentialID:         certModel.DnsCredentialID,		KeyType:                 certModel.GetKeyType(),		NotBefore:               certInfo.NotBefore,		MustStaple:              certModel.MustStaple,		LegoDisableCNAMESupport: certModel.LegoDisableCNAMESupport,	}	if certModel.Resource != nil {		payload.Resource = &model.CertificateResource{			Resource:          certModel.Resource.Resource,			PrivateKey:        certModel.Resource.PrivateKey,			Certificate:       certModel.Resource.Certificate,			IssuerCertificate: certModel.Resource.IssuerCertificate,			CSR:               certModel.Resource.CSR,		}	}	// errChan will be closed inside IssueCert	go IssueCert(payload, logChan, errChan)	go func() {		for logString := range logChan {			log.Info(strings.TrimSpace(logString))		}	}()	// block, unless errChan closed	for err := range errChan {		log.Error(err)		notification.Error("Renew Certificate Error", strings.Join(payload.ServerName, ", "))		return	}	notification.Success("Renew Certificate Success", strings.Join(payload.ServerName, ", "))	err = SyncToRemoteServer(certModel)	if err != nil {		notification.Error("Sync Certificate Error", err.Error())		return	}	close(logChan)}
 |