Explorar o código

windows: log fatal and panic errors to event log (#1667)

blotus %!s(int64=3) %!d(string=hai) anos
pai
achega
865ff5c88d
Modificáronse 2 ficheiros con 76 adicións e 0 borrados
  1. 39 0
      cmd/crowdsec/event_log_hook_windows.go
  2. 37 0
      cmd/crowdsec/win_service.go

+ 39 - 0
cmd/crowdsec/event_log_hook_windows.go

@@ -0,0 +1,39 @@
+package main
+
+import (
+	log "github.com/sirupsen/logrus"
+	"golang.org/x/sys/windows/svc/eventlog"
+)
+
+type EventLogHook struct {
+	LogLevels []log.Level
+	evtlog    *eventlog.Log
+}
+
+func (e *EventLogHook) Fire(entry *log.Entry) error {
+	line, err := entry.String()
+	if err != nil {
+		return err
+	}
+	switch entry.Level {
+	case log.PanicLevel:
+		return e.evtlog.Error(300, line)
+	case log.FatalLevel:
+		return e.evtlog.Error(301, line)
+	case log.ErrorLevel:
+		return e.evtlog.Error(302, line)
+	case log.WarnLevel:
+		return e.evtlog.Warning(303, line)
+	case log.InfoLevel:
+		return e.evtlog.Info(304, line)
+	case log.DebugLevel:
+		return e.evtlog.Info(305, line)
+	case log.TraceLevel:
+		return e.evtlog.Info(306, line)
+	}
+	return nil
+}
+
+func (e *EventLogHook) Levels() []log.Level {
+	return e.LogLevels
+}

+ 37 - 0
cmd/crowdsec/win_service.go

@@ -8,13 +8,16 @@
 package main
 package main
 
 
 import (
 import (
+	"syscall"
 	"time"
 	"time"
 
 
 	"github.com/crowdsecurity/crowdsec/pkg/csconfig"
 	"github.com/crowdsecurity/crowdsec/pkg/csconfig"
 	"github.com/crowdsecurity/crowdsec/pkg/types"
 	"github.com/crowdsecurity/crowdsec/pkg/types"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
 	log "github.com/sirupsen/logrus"
 	log "github.com/sirupsen/logrus"
+	"golang.org/x/sys/windows"
 	"golang.org/x/sys/windows/svc"
 	"golang.org/x/sys/windows/svc"
+	"golang.org/x/sys/windows/svc/eventlog"
 )
 )
 
 
 type crowdsec_winservice struct {
 type crowdsec_winservice struct {
@@ -61,6 +64,40 @@ func (m *crowdsec_winservice) Execute(args []string, r <-chan svc.ChangeRequest,
 }
 }
 
 
 func runService(name string) error {
 func runService(name string) error {
+
+	//All the calls to logging before the logger is configured are pretty much useless, but we keep them for clarity
+	err := eventlog.InstallAsEventCreate("CrowdSec", eventlog.Error|eventlog.Warning|eventlog.Info)
+	if err != nil {
+		if errno, ok := err.(syscall.Errno); ok {
+			if errno == windows.ERROR_ACCESS_DENIED {
+				log.Warnf("Access denied when installing event source, running as non-admin ?")
+			} else {
+				log.Warnf("Failed to install event log: %s (%d)", err, errno)
+			}
+		} else {
+			log.Warnf("Failed to install event log: %s", err)
+		}
+	}
+
+	//Let's use our source even if we could not install it:
+	// - It could have been created earlier
+	// - No permission to create it (e.g. running as non-admin when working on crowdsec)
+	//It will still work, windows will just display some additional errors in the event log
+	evtlog, err := eventlog.Open("CrowdSec")
+
+	if err == nil {
+		//Send panic and fatal to event log, as they can happen before the logger is configured.
+		log.AddHook(&EventLogHook{
+			LogLevels: []log.Level{
+				log.PanicLevel,
+				log.FatalLevel,
+			},
+			evtlog: evtlog,
+		})
+	} else {
+		log.Warnf("Failed to open event log: %s", err)
+	}
+
 	cConfig, err := csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI)
 	cConfig, err := csconfig.NewConfig(flags.ConfigFile, flags.DisableAgent, flags.DisableAPI)
 	if err != nil {
 	if err != nil {
 		return err
 		return err