more
This commit is contained in:
1 parent
2237fbda55
commit
5076036709
11 files changed
+299
-8
No files matched your search
@@ -51,6 +51,7 @@ type Collector struct {
|
||||
sourceMaps *sourcemaps.Resolver
|
||||
kubeWatcher *kube.Watcher
|
||||
prometheus *prometheus.Client
|
||||
honeypot HoneypotRecorder
|
||||
|
||||
// Optional capabilities of the configured store (ClickHouse implements
|
||||
// all of them); nil when unsupported, and the API falls back to the
|
||||
@@ -109,6 +110,17 @@ func (c *Collector) SetIngestKey(key string) {
|
||||
c.ingestKey = key
|
||||
}
|
||||
|
||||
// HoneypotRecorder receives suspicious request observations extracted from
|
||||
// telemetry. It is intentionally a small interface so the collector does not
|
||||
// depend on the HTTP honeypot implementation.
|
||||
type HoneypotRecorder interface {
|
||||
RecordTelemetry(ip, path string) bool
|
||||
}
|
||||
|
||||
func (c *Collector) SetHoneypotRecorder(recorder HoneypotRecorder) {
|
||||
c.honeypot = recorder
|
||||
}
|
||||
|
||||
// SetStatsQuerier enables the aggregate stats endpoints (error trends,
|
||||
// release comparisons) when a store supporting them is configured.
|
||||
func (c *Collector) SetStatsQuerier(q storage.StatsQuerier) {
|
||||
@@ -353,6 +365,7 @@ func (c *Collector) ConsumeTraces(ctx context.Context, td ptrace.Traces) error {
|
||||
|
||||
// Store and broadcast raw bytes as json.RawMessage to avoid unsafe interface{} usage
|
||||
c.addToHistory(websocket.DataTypeTraces, buf)
|
||||
recordSuspiciousTraceIPs(c.honeypot, td)
|
||||
if extractSpanErrors(c.issues, td, time.Now().UnixNano()) {
|
||||
c.notifyIssues()
|
||||
}
|
||||
@@ -398,6 +411,7 @@ func (c *Collector) ConsumeLogs(ctx context.Context, ld plog.Logs) error {
|
||||
|
||||
// Store and broadcast raw bytes as json.RawMessage to avoid unsafe interface{} usage
|
||||
c.addToHistory(websocket.DataTypeLogs, buf)
|
||||
recordSuspiciousLogIPs(c.honeypot, ld)
|
||||
if extractLogErrors(c.issues, ld, time.Now().UnixNano()) {
|
||||
c.notifyIssues()
|
||||
}
|
||||
|
||||
@@ -44,6 +44,42 @@ func extractSpanErrors(tracker *issues.Tracker, td ptrace.Traces, timestamp int6
|
||||
return found
|
||||
}
|
||||
|
||||
func recordSuspiciousTraceIPs(recorder HoneypotRecorder, td ptrace.Traces) {
|
||||
if recorder == nil {
|
||||
return
|
||||
}
|
||||
resourceSpans := td.ResourceSpans()
|
||||
for i := 0; i < resourceSpans.Len(); i++ {
|
||||
rs := resourceSpans.At(i)
|
||||
scopeSpans := rs.ScopeSpans()
|
||||
for j := 0; j < scopeSpans.Len(); j++ {
|
||||
spans := scopeSpans.At(j).Spans()
|
||||
for k := 0; k < spans.Len(); k++ {
|
||||
span := spans.At(k)
|
||||
_ = recorder.RecordTelemetry(sourceIP(span.Attributes(), rs.Resource().Attributes()), httpRoute(span.Attributes()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func recordSuspiciousLogIPs(recorder HoneypotRecorder, ld plog.Logs) {
|
||||
if recorder == nil {
|
||||
return
|
||||
}
|
||||
resourceLogs := ld.ResourceLogs()
|
||||
for i := 0; i < resourceLogs.Len(); i++ {
|
||||
rl := resourceLogs.At(i)
|
||||
scopeLogs := rl.ScopeLogs()
|
||||
for j := 0; j < scopeLogs.Len(); j++ {
|
||||
records := scopeLogs.At(j).LogRecords()
|
||||
for k := 0; k < records.Len(); k++ {
|
||||
record := records.At(k)
|
||||
_ = recorder.RecordTelemetry(sourceIP(record.Attributes(), rl.Resource().Attributes()), httpRoute(record.Attributes()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// extractLogErrors scans logs for error/fatal severity records and records
|
||||
// one issue occurrence per error found. It reports whether any error was
|
||||
// seen, so the caller can notify live clients.
|
||||
@@ -131,23 +167,27 @@ func logSample(record plog.LogRecord, res pcommon.Resource, timestamp int64, tit
|
||||
// its resource.
|
||||
func sourceIP(attrs, resource pcommon.Map) string {
|
||||
ip := firstAttr(attrs,
|
||||
"http.request.header.x-real-ip",
|
||||
"http.request.header.x_real_ip",
|
||||
"http.request.header.x-forwarded-for",
|
||||
"http.request.header.x_forwarded_for",
|
||||
"client.address",
|
||||
"client.ip",
|
||||
"http.client_ip",
|
||||
"net.peer.ip",
|
||||
"network.peer.address",
|
||||
"http.request.header.x-real-ip",
|
||||
"http.request.header.x-forwarded-for",
|
||||
"http.request.header.x_real_ip",
|
||||
"http.request.header.x_forwarded_for",
|
||||
"net.peer.ip",
|
||||
)
|
||||
if ip == "" {
|
||||
ip = firstAttr(resource,
|
||||
"http.request.header.x-real-ip",
|
||||
"http.request.header.x_real_ip",
|
||||
"http.request.header.x-forwarded-for",
|
||||
"http.request.header.x_forwarded_for",
|
||||
"client.address",
|
||||
"client.ip",
|
||||
"http.client_ip",
|
||||
"net.peer.ip",
|
||||
"network.peer.address",
|
||||
"net.peer.ip",
|
||||
)
|
||||
}
|
||||
return strings.TrimSpace(strings.SplitN(ip, ",", 2)[0])
|
||||
|
||||
Reference in new issue
Block a user