nginx-ui/internal/cert/revoke.go
2025-04-10 16:16:06 +08:00

105 lines
2.7 KiB
Go

package cert
import (
"log"
"os"
"time"
"github.com/0xJacky/Nginx-UI/internal/transport"
"github.com/go-acme/lego/v4/lego"
legolog "github.com/go-acme/lego/v4/log"
"github.com/pkg/errors"
"github.com/uozi-tech/cosy/logger"
cSettings "github.com/uozi-tech/cosy/settings"
)
// RevokeCert revokes a certificate and provides log messages through channels
func RevokeCert(payload *ConfigPayload, logChan chan string, errChan chan error) {
defer func() {
if err := recover(); err != nil {
logger.Error(err)
}
}()
// Initialize a channel writer to receive logs
cw := NewChannelWriter()
defer close(errChan)
defer close(cw.Ch)
// Initialize a logger
l := log.New(os.Stderr, "", log.LstdFlags)
l.SetOutput(cw)
// Hijack the logger of lego
oldLogger := legolog.Logger
legolog.Logger = l
// Restore the original logger
defer func() {
legolog.Logger = oldLogger
}()
// Start a goroutine to fetch and process logs from channel
go func() {
for msg := range cw.Ch {
logChan <- string(msg)
}
}()
// Create client for communication with CA server
l.Println("[INFO] [Nginx UI] Preparing for certificate revocation")
user, err := payload.GetACMEUser()
if err != nil {
errChan <- errors.Wrap(err, "get ACME user error")
return
}
config := lego.NewConfig(user)
config.CADirURL = user.CADir
// Skip TLS check if proxy is configured
if config.HTTPClient != nil {
t, err := transport.NewTransport(
transport.WithProxy(user.Proxy))
if err != nil {
errChan <- errors.Wrap(err, "create transport error")
return
}
config.HTTPClient.Transport = t
}
config.Certificate.KeyType = payload.GetKeyType()
// Create the client
client, err := lego.NewClient(config)
if err != nil {
errChan <- errors.Wrap(err, "create client error")
return
}
revoke(payload, client, l, errChan)
// If the revoked certificate was used for the server itself, reload server TLS certificate
if payload.GetCertificatePath() == cSettings.ServerSettings.SSLCert &&
payload.GetCertificateKeyPath() == cSettings.ServerSettings.SSLKey {
l.Println("[INFO] [Nginx UI] Certificate was used for server, reloading server TLS certificate")
ReloadServerTLSCertificate()
}
l.Println("[INFO] [Nginx UI] Revocation completed")
// Wait for logs to be written
time.Sleep(2 * time.Second)
}
// revoke implements the internal certificate revocation logic
func revoke(payload *ConfigPayload, client *lego.Client, l *log.Logger, errChan chan error) {
l.Println("[INFO] [Nginx UI] Revoking certificate")
err := client.Certificate.Revoke(payload.Resource.Certificate)
if err != nil {
errChan <- errors.Wrap(err, "revoke certificate error")
return
}
l.Println("[INFO] [Nginx UI] Certificate successfully revoked")
return
}