auto_cert.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package cert
  2. import (
  3. "github.com/0xJacky/Nginx-UI/internal/logger"
  4. "github.com/0xJacky/Nginx-UI/internal/notification"
  5. "github.com/0xJacky/Nginx-UI/model"
  6. "github.com/pkg/errors"
  7. "runtime"
  8. "strings"
  9. "time"
  10. )
  11. func AutoObtain() {
  12. defer func() {
  13. if err := recover(); err != nil {
  14. buf := make([]byte, 1024)
  15. runtime.Stack(buf, false)
  16. logger.Error("AutoCert Recover", err, string(buf))
  17. }
  18. }()
  19. logger.Info("AutoCert Worker Started")
  20. autoCertList := model.GetAutoCertList()
  21. for _, certModel := range autoCertList {
  22. renew(certModel)
  23. }
  24. logger.Info("AutoCert Worker End")
  25. }
  26. func renew(certModel *model.Cert) {
  27. confName := certModel.Filename
  28. log := &Logger{}
  29. log.SetCertModel(certModel)
  30. defer log.Exit()
  31. if len(certModel.Filename) == 0 {
  32. log.Error(errors.New("filename is empty"))
  33. return
  34. }
  35. if len(certModel.Domains) == 0 {
  36. log.Error(errors.New("domains list is empty, " +
  37. "try to reopen auto-cert for this config:" + confName))
  38. notification.Error("Renew Certificate Error", confName)
  39. return
  40. }
  41. if certModel.SSLCertificatePath == "" {
  42. log.Error(errors.New("ssl certificate path is empty, " +
  43. "try to reopen auto-cert for this config:" + confName))
  44. notification.Error("Renew Certificate Error", confName)
  45. return
  46. }
  47. cert, err := GetCertInfo(certModel.SSLCertificatePath)
  48. if err != nil {
  49. // Get certificate info error, ignore this certificate
  50. log.Error(errors.Wrap(err, "get certificate info error"))
  51. notification.Error("Renew Certificate Error", strings.Join(certModel.Domains, ", "))
  52. return
  53. }
  54. if time.Now().Sub(cert.NotBefore).Hours()/24 < 7 {
  55. // not between 1 week, ignore this certificate
  56. return
  57. }
  58. // after 1 mo, reissue certificate
  59. logChan := make(chan string, 1)
  60. errChan := make(chan error, 1)
  61. // support SAN certification
  62. payload := &ConfigPayload{
  63. ServerName: certModel.Domains,
  64. ChallengeMethod: certModel.ChallengeMethod,
  65. DNSCredentialID: certModel.DnsCredentialID,
  66. KeyType: certModel.GetKeyType(),
  67. }
  68. // errChan will be closed inside IssueCert
  69. go IssueCert(payload, logChan, errChan)
  70. go func() {
  71. for logString := range logChan {
  72. log.Info(strings.TrimSpace(logString))
  73. }
  74. }()
  75. // block, unless errChan closed
  76. for err := range errChan {
  77. log.Error(err)
  78. notification.Error("Renew Certificate Error", strings.Join(payload.ServerName, ", "))
  79. return
  80. }
  81. notification.Success("Renew Certificate Success", strings.Join(payload.ServerName, ", "))
  82. }