diff --git a/containers/l7.go b/containers/l7.go index f4782eea..2d1c7c50 100644 --- a/containers/l7.go +++ b/containers/l7.go @@ -68,7 +68,10 @@ func (s L7Stats) get(protocol l7.Protocol, destination, actualDestination netadd case l7.ProtocolRabbitmq, l7.ProtocolNats: labels = append(labels, "method") case l7.ProtocolHTTP: - method, path := l7.ParseHttp(r.Payload) + method, path, payload := l7.ParseHttpAndRest(r.Payload) + if r.Status == l7.StatusFailed { + constLabels["payload"] = payload + } constLabels["path"] = path constLabels["method"] = method hOpts := L7Latency[protocol] diff --git a/ebpftracer/l7/http.go b/ebpftracer/l7/http.go index 00047b51..dea68e04 100644 --- a/ebpftracer/l7/http.go +++ b/ebpftracer/l7/http.go @@ -2,6 +2,9 @@ package l7 import ( "bytes" + "encoding/base64" + "regexp" + "strings" ) func ParseHttp(payload []byte) (string, string) { @@ -18,3 +21,58 @@ func ParseHttp(payload []byte) (string, string) { } return string(method), string(uri) } + +func ParseHttpAndRest(payload []byte) (string, string, string) { + method, rest, ok := bytes.Cut(payload, space) + if !ok { + return "", "", "" + } + if !isHttpMethod(string(method)) { + return "", "", "" + } + uri, rest, ok := bytes.Cut(rest, space) + if !ok { + uri = append(uri, []byte("...")...) + } + return string(method), string(uri), SanitizeString(string(rest)) +} + +func SanitizeString(input string) string { + // Regular expression patterns to match various sensitive data formats + sensitivePatterns := []*regexp.Regexp{ + // Authorization header (Bearer or Basic) + // Example: Authorization: Basic c3FhXzdhODNiZTRjY2Y0M2E2NzFhMTI0ODViYmMyY2I4ZGU4MDk0MDQyMzE6 + // Reason: Matches common formats for authorization tokens. + regexp.MustCompile(`(?i)Authorization: (Bearer|Basic)\s+[a-zA-Z0-9\-_\.=]+`), + + // API key + // Example: ApiKey abcdef1234567890 + // Reason: Matches common formats for API keys. + regexp.MustCompile(`(?i)ApiKey\s+[a-zA-Z0-9\-_\.=]+`), + + // JWT token + // Example: JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... + // Reason: Matches common formats for JWT tokens. + regexp.MustCompile(`(?i)JWT\s+[a-zA-Z0-9\-_\.=]+`), + + // OAuth token + // Example: OAuth token1234567890 + // Reason: Matches common formats for OAuth tokens. + regexp.MustCompile(`(?i)OAuth\s+[a-zA-Z0-9\-_\.=]+`), + } + + // Replace sensitive data with placeholder '*' + sanitized := input + for _, pattern := range sensitivePatterns { + sanitized = pattern.ReplaceAllStringFunc(sanitized, func(match string) string { + // Only replace the sensitive part, keeping the structure intact + return strings.Repeat("*", len(match)) + }) + } + + byteData := []byte(sanitized) + + // Encode byte slice to Base64 + base64String := base64.StdEncoding.EncodeToString(byteData) + return base64String +} diff --git a/ebpftracer/l7/l7.go b/ebpftracer/l7/l7.go index 7479eaab..b2c14280 100644 --- a/ebpftracer/l7/l7.go +++ b/ebpftracer/l7/l7.go @@ -119,4 +119,5 @@ type RequestData struct { Method Method StatementId uint32 Payload []byte + PayloadSize uint64 } diff --git a/ebpftracer/tracer.go b/ebpftracer/tracer.go index c16b0900..8c86d93c 100644 --- a/ebpftracer/tracer.go +++ b/ebpftracer/tracer.go @@ -350,6 +350,7 @@ func runEventsReader(name string, r *perf.Reader, ch chan<- Event, typ perfMapTy Duration: time.Duration(v.Duration), Method: l7.Method(v.Method), StatementId: v.StatementId, + PayloadSize: v.PayloadSize, } switch { case v.PayloadSize == 0: