Bugfix Problem Metrics
All checks were successful
release-tag / release-image (push) Successful in 5m59s
All checks were successful
release-tag / release-image (push) Successful in 5m59s
This commit is contained in:
94
main.go
94
main.go
@@ -1688,6 +1688,7 @@ func main() {
|
|||||||
s.templates = tmpl
|
s.templates = tmpl
|
||||||
|
|
||||||
go s.runSOCLoop()
|
go s.runSOCLoop()
|
||||||
|
go s.runBaselineLoop()
|
||||||
go s.runDetectionLoop()
|
go s.runDetectionLoop()
|
||||||
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
@@ -1756,6 +1757,53 @@ func (s *server) runSOCLoop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *server) runBaselineLoop() {
|
||||||
|
ticker := time.NewTicker(s.cfg.DetectionInterval)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
s.runBaselineOnce()
|
||||||
|
|
||||||
|
for range ticker.C {
|
||||||
|
s.runBaselineOnce()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *server) runBaselineOnce() {
|
||||||
|
if !s.cfg.BaselineEnabled {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
rules := []struct {
|
||||||
|
name string
|
||||||
|
timeout time.Duration
|
||||||
|
fn func(context.Context) error
|
||||||
|
}{
|
||||||
|
{"baseline_anomaly", 120 * time.Second, s.detector.runBaselineAnomalyRule},
|
||||||
|
{"baseline_update", 120 * time.Second, s.detector.runBaselineUpdate},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rule := range rules {
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), rule.timeout)
|
||||||
|
err := rule.fn(ctx)
|
||||||
|
cancel()
|
||||||
|
|
||||||
|
dur := time.Since(start)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
s.logger.Printf("baseline rule %s error after %s: %v", rule.name, dur, err)
|
||||||
|
s.detector.ruleErrorsTotal.WithLabelValues(rule.name).Inc()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
s.logger.Printf("baseline rule %s completed in %s", rule.name, dur)
|
||||||
|
|
||||||
|
s.detector.ruleLastRunGauge.WithLabelValues(rule.name).Set(float64(time.Now().Unix()))
|
||||||
|
s.detector.ruleRuntimeHist.WithLabelValues(rule.name).Observe(dur.Seconds())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (s *server) runSOCOnce() {
|
func (s *server) runSOCOnce() {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -3941,17 +3989,18 @@ func (d *detector) runBaselineUpdate(ctx context.Context) error {
|
|||||||
windowEnd := time.Now().UTC()
|
windowEnd := time.Now().UTC()
|
||||||
windowStart := windowEnd.Add(-d.cfg.BaselineWindow)
|
windowStart := windowEnd.Add(-d.cfg.BaselineWindow)
|
||||||
|
|
||||||
|
hour := windowEnd.Hour()
|
||||||
|
dayOfWeek := int(windowEnd.Weekday()+6) % 7 // Go: Sonntag=0, MySQL WEEKDAY: Montag=0
|
||||||
|
|
||||||
rows, err := d.db.QueryContext(ctx, `
|
rows, err := d.db.QueryContext(ctx, `
|
||||||
SELECT
|
SELECT
|
||||||
hostname,
|
hostname,
|
||||||
channel_name,
|
channel_name,
|
||||||
event_id,
|
event_id,
|
||||||
HOUR(ts) AS hour_of_day,
|
|
||||||
WEEKDAY(ts) AS day_of_week,
|
|
||||||
COUNT(*) AS cnt
|
COUNT(*) AS cnt
|
||||||
FROM event_logs
|
FROM event_logs
|
||||||
WHERE ts >= ? AND ts < ?
|
WHERE ts >= ? AND ts < ?
|
||||||
GROUP BY hostname, channel_name, event_id, HOUR(ts), WEEKDAY(ts)
|
GROUP BY hostname, channel_name, event_id
|
||||||
`, windowStart, windowEnd)
|
`, windowStart, windowEnd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -3964,13 +4013,14 @@ GROUP BY hostname, channel_name, event_id, HOUR(ts), WEEKDAY(ts)
|
|||||||
&b.Hostname,
|
&b.Hostname,
|
||||||
&b.Channel,
|
&b.Channel,
|
||||||
&b.EventID,
|
&b.EventID,
|
||||||
&b.Hour,
|
|
||||||
&b.DayOfWeek,
|
|
||||||
&b.Count,
|
&b.Count,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.Hour = hour
|
||||||
|
b.DayOfWeek = dayOfWeek
|
||||||
|
|
||||||
excluded, err := d.isBaselineExcluded(ctx, b.Hostname, b.Channel, b.EventID)
|
excluded, err := d.isBaselineExcluded(ctx, b.Hostname, b.Channel, b.EventID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -3995,6 +4045,12 @@ GROUP BY hostname, channel_name, event_id, HOUR(ts), WEEKDAY(ts)
|
|||||||
return rows.Err()
|
return rows.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mysqlWeekday(t time.Time) int {
|
||||||
|
// MySQL WEEKDAY(): Monday=0 ... Sunday=6
|
||||||
|
// Go Weekday(): Sunday=0 ... Saturday=6
|
||||||
|
return (int(t.UTC().Weekday()) + 6) % 7
|
||||||
|
}
|
||||||
|
|
||||||
func (d *detector) hasConfirmedIncidentInWindow(ctx context.Context, hostname, channel string, eventID uint32, windowStart, windowEnd time.Time) (bool, error) {
|
func (d *detector) hasConfirmedIncidentInWindow(ctx context.Context, hostname, channel string, eventID uint32, windowStart, windowEnd time.Time) (bool, error) {
|
||||||
var count int
|
var count int
|
||||||
|
|
||||||
@@ -4129,35 +4185,34 @@ func (d *detector) runBaselineAnomalyRule(ctx context.Context) error {
|
|||||||
windowEnd := time.Now().UTC()
|
windowEnd := time.Now().UTC()
|
||||||
windowStart := windowEnd.Add(-d.cfg.BaselineWindow)
|
windowStart := windowEnd.Add(-d.cfg.BaselineWindow)
|
||||||
|
|
||||||
|
hour := windowEnd.Hour()
|
||||||
|
dayOfWeek := mysqlWeekday(windowEnd)
|
||||||
|
|
||||||
rows, err := d.db.QueryContext(ctx, `
|
rows, err := d.db.QueryContext(ctx, `
|
||||||
SELECT
|
SELECT
|
||||||
e.hostname,
|
e.hostname,
|
||||||
e.channel_name,
|
e.channel_name,
|
||||||
e.event_id,
|
e.event_id,
|
||||||
HOUR(e.ts) AS hour_of_day,
|
|
||||||
WEEKDAY(e.ts) AS day_of_week,
|
|
||||||
COUNT(*) AS cnt,
|
COUNT(*) AS cnt,
|
||||||
b.avg_count,
|
COALESCE(b.avg_count, 0),
|
||||||
b.stddev_count,
|
COALESCE(b.stddev_count, 0),
|
||||||
b.sample_count
|
COALESCE(b.sample_count, 0)
|
||||||
FROM event_logs e
|
FROM event_logs e
|
||||||
JOIN baseline_event_stats b
|
LEFT JOIN baseline_event_stats b
|
||||||
ON b.hostname = e.hostname
|
ON b.hostname = e.hostname
|
||||||
AND b.channel_name = e.channel_name
|
AND b.channel_name = e.channel_name
|
||||||
AND b.event_id = e.event_id
|
AND b.event_id = e.event_id
|
||||||
AND b.hour_of_day = HOUR(e.ts)
|
AND b.hour_of_day = ?
|
||||||
AND b.day_of_week = WEEKDAY(e.ts)
|
AND b.day_of_week = ?
|
||||||
WHERE e.ts >= ? AND e.ts < ?
|
WHERE e.ts >= ? AND e.ts < ?
|
||||||
GROUP BY
|
GROUP BY
|
||||||
e.hostname,
|
e.hostname,
|
||||||
e.channel_name,
|
e.channel_name,
|
||||||
e.event_id,
|
e.event_id,
|
||||||
HOUR(e.ts),
|
|
||||||
WEEKDAY(e.ts),
|
|
||||||
b.avg_count,
|
b.avg_count,
|
||||||
b.stddev_count,
|
b.stddev_count,
|
||||||
b.sample_count
|
b.sample_count
|
||||||
`, windowStart, windowEnd)
|
`, hour, dayOfWeek, windowStart, windowEnd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -4167,8 +4222,6 @@ GROUP BY
|
|||||||
var host string
|
var host string
|
||||||
var channel string
|
var channel string
|
||||||
var eventID uint32
|
var eventID uint32
|
||||||
var hour int
|
|
||||||
var dayOfWeek int
|
|
||||||
var count int
|
var count int
|
||||||
var avg float64
|
var avg float64
|
||||||
var stddev float64
|
var stddev float64
|
||||||
@@ -4178,8 +4231,6 @@ GROUP BY
|
|||||||
&host,
|
&host,
|
||||||
&channel,
|
&channel,
|
||||||
&eventID,
|
&eventID,
|
||||||
&hour,
|
|
||||||
&dayOfWeek,
|
|
||||||
&count,
|
&count,
|
||||||
&avg,
|
&avg,
|
||||||
&stddev,
|
&stddev,
|
||||||
@@ -4769,9 +4820,6 @@ func (s *server) runDetectionsOnce() {
|
|||||||
{"new_source_ip_for_user", s.detector.runNewSourceIPForUserRule},
|
{"new_source_ip_for_user", s.detector.runNewSourceIPForUserRule},
|
||||||
{"dynamic_rules", s.detector.runDynamicRules},
|
{"dynamic_rules", s.detector.runDynamicRules},
|
||||||
|
|
||||||
{"baseline_anomaly", s.detector.runBaselineAnomalyRule},
|
|
||||||
{"baseline_update", s.detector.runBaselineUpdate},
|
|
||||||
|
|
||||||
{"ueba_admin_new_host", s.detector.runAdminNewHostRule},
|
{"ueba_admin_new_host", s.detector.runAdminNewHostRule},
|
||||||
{"ueba_offhours_login", s.detector.runOffHoursLoginRule},
|
{"ueba_offhours_login", s.detector.runOffHoursLoginRule},
|
||||||
{"ueba_first_privileged_use", s.detector.runFirstTimePrivilegedRule},
|
{"ueba_first_privileged_use", s.detector.runFirstTimePrivilegedRule},
|
||||||
|
|||||||
Reference in New Issue
Block a user