github.com/crowdsecurity/crowdsec@v1.6.1/pkg/appsec/coraza_logger.go (about) 1 package appsec 2 3 import ( 4 "fmt" 5 "io" 6 7 dbg "github.com/crowdsecurity/coraza/v3/debuglog" 8 log "github.com/sirupsen/logrus" 9 ) 10 11 var DebugRules map[int]bool = map[int]bool{} 12 13 func SetRuleDebug(id int, debug bool) { 14 DebugRules[id] = debug 15 } 16 17 func GetRuleDebug(id int) bool { 18 if val, ok := DebugRules[id]; ok { 19 return val 20 } 21 return false 22 } 23 24 // type ContextField func(Event) Event 25 26 type crzLogEvent struct { 27 fields log.Fields 28 logger *log.Entry 29 muted bool 30 level log.Level 31 } 32 33 func (e *crzLogEvent) Msg(msg string) { 34 if e.muted { 35 return 36 } 37 38 /*this is a hack. As we want to have per-level rule debug but it's not allowed by coraza/modsec, if a rule ID is flagged to be in debug mode, the 39 .Int("rule_id", <ID>) call will set the log_level of the event to debug. However, given the logger is global to the appsec-runner, 40 we are switching forth and back the log level of the logger*/ 41 oldLvl := e.logger.Logger.GetLevel() 42 43 if e.level != oldLvl { 44 e.logger.Logger.SetLevel(e.level) 45 } 46 47 if len(e.fields) == 0 { 48 e.logger.Log(e.level, msg) 49 } else { 50 e.logger.WithFields(e.fields).Log(e.level, msg) 51 } 52 53 if e.level != oldLvl { 54 e.logger.Logger.SetLevel(oldLvl) 55 e.level = oldLvl 56 } 57 } 58 59 func (e *crzLogEvent) Str(key, val string) dbg.Event { 60 if e.muted { 61 return e 62 } 63 e.fields[key] = val 64 return e 65 } 66 67 func (e *crzLogEvent) Err(err error) dbg.Event { 68 if e.muted { 69 return e 70 } 71 e.fields["error"] = err 72 return e 73 } 74 75 func (e *crzLogEvent) Bool(key string, b bool) dbg.Event { 76 if e.muted { 77 return e 78 } 79 e.fields[key] = b 80 return e 81 } 82 83 func (e *crzLogEvent) Int(key string, i int) dbg.Event { 84 if e.muted { 85 //this allows us to have per-rule debug logging 86 if key == "rule_id" && GetRuleDebug(i) { 87 e.muted = false 88 e.fields = map[string]interface{}{} 89 e.level = log.DebugLevel 90 } else { 91 return e 92 } 93 } 94 e.fields[key] = i 95 return e 96 } 97 98 func (e *crzLogEvent) Uint(key string, i uint) dbg.Event { 99 if e.muted { 100 return e 101 } 102 e.fields[key] = i 103 return e 104 } 105 106 func (e *crzLogEvent) Stringer(key string, val fmt.Stringer) dbg.Event { 107 if e.muted { 108 return e 109 } 110 e.fields[key] = val 111 return e 112 } 113 114 func (e crzLogEvent) IsEnabled() bool { 115 return !e.muted 116 } 117 118 type crzLogger struct { 119 logger *log.Entry 120 defaultFields log.Fields 121 logLevel log.Level 122 } 123 124 func NewCrzLogger(logger *log.Entry) crzLogger { 125 return crzLogger{logger: logger, logLevel: logger.Logger.GetLevel()} 126 } 127 128 func (c crzLogger) NewMutedEvt(lvl log.Level) dbg.Event { 129 return &crzLogEvent{muted: true, logger: c.logger, level: lvl} 130 } 131 func (c crzLogger) NewEvt(lvl log.Level) dbg.Event { 132 evt := &crzLogEvent{fields: map[string]interface{}{}, logger: c.logger, level: lvl} 133 if c.defaultFields != nil { 134 for k, v := range c.defaultFields { 135 evt.fields[k] = v 136 } 137 } 138 return evt 139 } 140 141 func (c crzLogger) WithOutput(w io.Writer) dbg.Logger { 142 return c 143 } 144 145 func (c crzLogger) WithLevel(lvl dbg.Level) dbg.Logger { 146 c.logLevel = log.Level(lvl) 147 c.logger.Logger.SetLevel(c.logLevel) 148 return c 149 } 150 151 func (c crzLogger) With(fs ...dbg.ContextField) dbg.Logger { 152 var e dbg.Event = c.NewEvt(c.logLevel) 153 for _, f := range fs { 154 e = f(e) 155 } 156 c.defaultFields = e.(*crzLogEvent).fields 157 return c 158 } 159 160 func (c crzLogger) Trace() dbg.Event { 161 if c.logLevel < log.TraceLevel { 162 return c.NewMutedEvt(log.TraceLevel) 163 } 164 return c.NewEvt(log.TraceLevel) 165 } 166 167 func (c crzLogger) Debug() dbg.Event { 168 if c.logLevel < log.DebugLevel { 169 return c.NewMutedEvt(log.DebugLevel) 170 171 } 172 return c.NewEvt(log.DebugLevel) 173 } 174 175 func (c crzLogger) Info() dbg.Event { 176 if c.logLevel < log.InfoLevel { 177 return c.NewMutedEvt(log.InfoLevel) 178 } 179 return c.NewEvt(log.InfoLevel) 180 } 181 182 func (c crzLogger) Warn() dbg.Event { 183 if c.logLevel < log.WarnLevel { 184 return c.NewMutedEvt(log.WarnLevel) 185 } 186 return c.NewEvt(log.WarnLevel) 187 } 188 189 func (c crzLogger) Error() dbg.Event { 190 if c.logLevel < log.ErrorLevel { 191 return c.NewMutedEvt(log.ErrorLevel) 192 } 193 return c.NewEvt(log.ErrorLevel) 194 }