Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 35 additions & 20 deletions pkg/containerwatcher/v2/tracers/httpparse.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,43 +78,58 @@ func GetPacketDirection(syscall string) (consts.NetworkDirection, error) {
}

func ParseHttpRequest(data []byte) (*http.Request, error) {
bufReader := bufio.NewReader(bytes.NewReader(data))
// Find header/body boundary
headerEnd := bytes.Index(data, []byte("\r\n\r\n"))
if headerEnd == -1 {
headerEnd = bytes.Index(data, []byte("\n\n"))
if headerEnd == -1 {
return fallbackReadRequest(data)
}
headerEnd += 2
} else {
headerEnd += 4
}

// Parse headers only
bufReader := bufio.NewReader(bytes.NewReader(data[:headerEnd]))
req, err := http.ReadRequest(bufReader)
if err != nil {
return fallbackReadRequest(data)
}

body, err := io.ReadAll(req.Body)
if err != nil {
return nil, err
}

req.Body.Close()

req.Body = io.NopCloser(bytes.NewReader(body))
// Set body directly without re-reading
bodyData := data[headerEnd:]
req.ContentLength = int64(len(bodyData))
req.Body = io.NopCloser(bytes.NewReader(bodyData))

return req, nil
}

func ParseHttpResponse(data []byte, req *http.Request) (*http.Response, error) {
resp, err := readResponse(data, req)
if err != nil {
resp, err = fallbackReadResponse(data, req)
if err != nil {
return nil, err
// Find header/body boundary
headerEnd := bytes.Index(data, []byte("\r\n\r\n"))
if headerEnd == -1 {
headerEnd = bytes.Index(data, []byte("\n\n"))
if headerEnd == -1 {
return fallbackReadResponse(data, req)
}
headerEnd += 2
} else {
headerEnd += 4
}

body, err := io.ReadAll(resp.Body)
if err != nil && err != io.ErrUnexpectedEOF {
return nil, err
// Parse headers only
bufReader := bufio.NewReader(bytes.NewReader(data[:headerEnd]))
resp, err := http.ReadResponse(bufReader, req)
if err != nil {
return fallbackReadResponse(data, req)
}

// Set body directly without re-reading
bodyData := data[headerEnd:]
resp.Body.Close()

resp.Body = io.NopCloser(bytes.NewReader(body))
resp.ContentLength = int64(len(body))
resp.Body = io.NopCloser(bytes.NewReader(bodyData))
resp.ContentLength = int64(len(bodyData))
resp.TransferEncoding = nil
resp.Header.Del("Transfer-Encoding")
resp.Header.Del("Content-Length")
Expand Down
11 changes: 6 additions & 5 deletions pkg/rulemanager/cel/cel.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func NewCEL(objectCache objectcache.ObjectCache, cfg config.Config) (*CEL, error
}

c.evalContextPool.New = func() interface{} {
return make(map[string]any, 1)
return make(map[string]any, 2)
}

return c, nil
Expand Down Expand Up @@ -117,8 +117,11 @@ func (c *CEL) getOrCreateProgram(expression string) (cel.Program, error) {
}

func (c *CEL) EvaluateRule(event *events.EnrichedEvent, expressions []typesv1.RuleExpression) (bool, error) {
obj, _ := xcel.NewObject(event.Event.(utils.CelEvent)) // FIXME put safety check here
eventType := event.Event.GetEventType()
input := map[string]any{"event": obj, "eventType": string(eventType)}

for _, expression := range expressions {
eventType := event.Event.GetEventType()
if expression.EventType != eventType {
continue
}
Expand All @@ -127,9 +130,7 @@ func (c *CEL) EvaluateRule(event *events.EnrichedEvent, expressions []typesv1.Ru
if err != nil {
return false, err
}

obj, _ := xcel.NewObject(event.Event.(utils.CelEvent)) // FIXME put safety check here
out, _, err := program.Eval(map[string]any{"event": obj, "eventType": string(eventType)})
out, _, err := program.Eval(input)
if err != nil {
return false, err
}
Expand Down
4 changes: 3 additions & 1 deletion pkg/rulemanager/ruleadapters/adapters/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ func ConvertToMap(e utils.EnrichEvent) map[string]interface{} {
//k8s["node"] = e.K8s.Node
k8s["namespace"] = e.GetNamespace()
k8s["podName"] = e.GetPod()
k8s["podLabels"] = e.GetPodLabels()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, we'll anyway remove the ToMap

//k8s["podLabels"] = e.GetPodLabels()

k8s["containerName"] = e.GetContainer()
k8s["hostNetwork"] = e.GetHostNetwork()

Expand Down
2 changes: 1 addition & 1 deletion pkg/rulemanager/ruleadapters/adapters/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import "sync"
// for the number of keys in your event maps.
var mapPool = sync.Pool{
New: func() interface{} {
return make(map[string]interface{}, 32)
return make(map[string]interface{}, 5)
},
}

Expand Down
15 changes: 9 additions & 6 deletions pkg/rulemanager/rulepolicy.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,20 @@ func RuleAppliesToContext(rule *typesv1.Rule, contextInfo contextdetection.Conte
currentContext = contextInfo.Context()
}

var contextTags []string
var hasContextTags bool
for _, tag := range rule.Tags {
if ctx, found := strings.CutPrefix(tag, "context:"); found {
contextTags = append(contextTags, ctx)
if ctx == string(currentContext) {
return true
}
hasContextTags = true
}
}

if len(contextTags) > 0 {
return slices.Contains(contextTags, string(currentContext))
// No context specified in tags: default to kubernetes only (backward compatible)
if !hasContextTags {
return currentContext == contextdetection.Kubernetes
}

// No context specified in tags: default to kubernetes only (backward compatible)
return currentContext == contextdetection.Kubernetes
return false
}
19 changes: 3 additions & 16 deletions pkg/utils/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,22 @@ import (
)

func parseStringToMap(s string) map[string]string {
result := make(map[string]string)

// 1. Split the string by the comma delimiter to get key-value pairs
pairs := strings.Split(s, ",")
result := make(map[string]string, len(pairs)/2)

for _, pair := range pairs {
// Trim any leading/trailing whitespace from the pair
pair = strings.TrimSpace(pair)
if pair == "" {
continue // Skip empty pairs that could result from multiple commas
continue
}

// 2. Split each pair by the equals sign delimiter.
// We use SplitN(pair, "=", 2) to ensure that only the first
// equals sign is treated as the delimiter, allowing values to
// contain equals signs (though not the case in the example).
parts := strings.SplitN(pair, "=", 2)

if len(parts) != 2 {
// Handle malformed pairs (e.g., "key" or "key=value=extra")
logger.L().Debug("Malformed key-value pair", helpers.String("pair", pair))
continue
}

// Trim whitespace from key and value and add to the map
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])

result[key] = value
result[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
}

return result
Expand Down
Loading