revoke.go 2.7 KB

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