revoke.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package cert
  2. import (
  3. "log"
  4. "os"
  5. "runtime"
  6. "time"
  7. "github.com/0xJacky/Nginx-UI/internal/translation"
  8. "github.com/0xJacky/Nginx-UI/internal/transport"
  9. "github.com/go-acme/lego/v4/lego"
  10. legolog "github.com/go-acme/lego/v4/log"
  11. "github.com/pkg/errors"
  12. "github.com/uozi-tech/cosy/logger"
  13. cSettings "github.com/uozi-tech/cosy/settings"
  14. )
  15. // RevokeCert revokes a certificate and provides log messages through channels
  16. func RevokeCert(payload *ConfigPayload, certLogger *Logger, logChan chan string, errChan chan error) {
  17. defer func() {
  18. if err := recover(); err != nil {
  19. buf := make([]byte, 1024)
  20. runtime.Stack(buf, false)
  21. logger.Error(err)
  22. }
  23. }()
  24. // Initialize a channel writer to receive logs
  25. cw := NewChannelWriter()
  26. defer close(errChan)
  27. defer close(cw.Ch)
  28. // Initialize a logger
  29. l := log.New(os.Stderr, "", log.LstdFlags)
  30. l.SetOutput(cw)
  31. // Hijack the logger of lego
  32. oldLogger := legolog.Logger
  33. legolog.Logger = l
  34. // Restore the original logger
  35. defer func() {
  36. legolog.Logger = oldLogger
  37. }()
  38. // Start a goroutine to fetch and process logs from channel
  39. go func() {
  40. for msg := range cw.Ch {
  41. logChan <- string(msg)
  42. }
  43. }()
  44. // Create client for communication with CA server
  45. certLogger.Info(translation.C("[Nginx UI] Preparing for certificate revocation"))
  46. user, err := payload.GetACMEUser()
  47. if err != nil {
  48. errChan <- errors.Wrap(err, "get ACME user error")
  49. return
  50. }
  51. config := lego.NewConfig(user)
  52. config.CADirURL = user.CADir
  53. // Skip TLS check if proxy is configured
  54. if config.HTTPClient != nil {
  55. t, err := transport.NewTransport(
  56. transport.WithProxy(user.Proxy))
  57. if err != nil {
  58. errChan <- errors.Wrap(err, "create transport error")
  59. return
  60. }
  61. config.HTTPClient.Transport = t
  62. }
  63. config.Certificate.KeyType = payload.GetKeyType()
  64. // Create the client
  65. client, err := lego.NewClient(config)
  66. if err != nil {
  67. errChan <- errors.Wrap(err, "create client error")
  68. return
  69. }
  70. revoke(payload, client, certLogger, errChan)
  71. // If the revoked certificate was used for the server itself, reload server TLS certificate
  72. if payload.GetCertificatePath() == cSettings.ServerSettings.SSLCert &&
  73. payload.GetCertificateKeyPath() == cSettings.ServerSettings.SSLKey {
  74. certLogger.Info(translation.C("[Nginx UI] Certificate was used for server, reloading server TLS certificate"))
  75. ReloadServerTLSCertificate()
  76. }
  77. certLogger.Info(translation.C("[Nginx UI] Revocation completed"))
  78. // Wait for logs to be written
  79. time.Sleep(2 * time.Second)
  80. }
  81. // revoke implements the internal certificate revocation logic
  82. func revoke(payload *ConfigPayload, client *lego.Client, l *Logger, errChan chan error) {
  83. l.Info(translation.C("[Nginx UI] Revoking certificate"))
  84. err := client.Certificate.Revoke(payload.Resource.Certificate)
  85. if err != nil {
  86. errChan <- errors.Wrap(err, "revoke certificate error")
  87. return
  88. }
  89. l.Info(translation.C("[Nginx UI] Certificate successfully revoked"))
  90. return
  91. }