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
1 change: 0 additions & 1 deletion containers/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -532,7 +532,6 @@ func ignoreControlPlane(name string) bool {
}
for _, keyword := range keywords {
if strings.Contains(strings.ToLower(name), keyword) {
klog.Warningln("Ignoring control plane ", name)
return true
}
}
Expand Down
53 changes: 13 additions & 40 deletions ebpftracer/l7/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ package l7

import (
"bytes"
"encoding/base64"
"encoding/json"
"errors"
"io"
"log"
"net/http"
"net/url"
"regexp"
"strings"

"github.com/coroot/coroot-node-agent/flags"
Expand Down Expand Up @@ -70,7 +68,11 @@ func ParseHTTPRequest(data []byte) (*http.Request, error) {
var header = http.Header{}
var host = ""
headerLines := bytes.Split(headers, []byte("\n"))

sensitiveHeaders := make(map[string]bool)
sensitiveKeysList := strings.Split(*flags.SensitiveHeader, ",")
for _, key := range sensitiveKeysList {
sensitiveHeaders[strings.ToLower(strings.TrimSpace(key))] = true
}
for _, line := range headerLines {
part1, part2, ok := bytes.Cut(line, []byte(":"))
if !ok {
Expand All @@ -79,8 +81,12 @@ func ParseHTTPRequest(data []byte) (*http.Request, error) {
if strings.HasPrefix(string(part1), "Host") {
host = strings.TrimSpace(string(part2))
}

key := strings.TrimSpace(string(part1))
val := strings.TrimSpace(string(part2))
if sensitiveHeaders[strings.ToLower(key)] {
val = SanitizeString(val)
}
header.Add(key, val)
}
req := &http.Request{
Expand Down Expand Up @@ -125,53 +131,20 @@ func ParseHostFromHttpRequest(input string) (string, error) {

func ConvertHeadersToString(headers http.Header) string {
headerMap := make(map[string][]string)

for key, values := range headers {
var sanitizedValues []string
for _, value := range values {
sanitizedValues = append(sanitizedValues, SanitizeString(value))
}
headerMap[key] = sanitizedValues
headerMap[key] = values
}

jsonString, err := json.Marshal(headerMap)
if err != nil {
return ""
}

return string(jsonString)
}

func SanitizeString(input string) string {
func SanitizeString(value string) string {
if !*flags.SanitizeHeaders {
return input
}
patternList := strings.Split(*flags.SensitiveHeaderPattern, ",")
// Compile regex patterns
var sensitivePatterns []*regexp.Regexp
for _, pattern := range patternList {
// Trim leading and trailing whitespace from the pattern
pattern = strings.TrimSpace(pattern)
if len(pattern) > 0 {
// Compile each pattern and append to the list
sensitivePatterns = append(sensitivePatterns, regexp.MustCompile(pattern))
}
}

// 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
sanitized_string := strings.Repeat("*", min(len(match), 5))
log.Printf("Replacing %s with %s , using pattern %s", match, sanitized_string, pattern)
return sanitized_string
})
return value
}

byteData := []byte(sanitized)

// Encode byte slice to Base64
base64String := base64.StdEncoding.EncodeToString(byteData)
return base64String
return strings.Repeat("*", len(value))
}
9 changes: 8 additions & 1 deletion ebpftracer/l7/l7_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io"
"testing"

"github.com/coroot/coroot-node-agent/flags"
"github.com/stretchr/testify/assert"
"go.mongodb.org/mongo-driver/bson"
)
Expand Down Expand Up @@ -91,12 +92,18 @@ func TestParseMongo(t *testing.T) {
}

func TestParseHost(t *testing.T) {
requestString := "HEAD /1 HTTP/1.1\r\nHost: 127.0.0.1\r\nUser-Agent: curl/8.0.1\r\nAccept: */*\r\n\r\nxzxxxxxxzx"
SanitizeHeaders := "Authorization, cookie"
f := true
flags.SensitiveHeader = &SanitizeHeaders
flags.SanitizeHeaders = &f
requestString := "HEAD /1 HTTP/1.1\r\nHost: 127.0.0.1\r\nUser-Agent: curl/8.0.1\r\nAuthorization: abcd\r\nCookie: abcd\r\nAccept: */*\r\n\r\nxzxxxxxxzx"
req, err := ParseHTTPRequest([]byte(requestString))
assert.Nil(t, nil, err)
assert.Equal(t, "/1", req.URL.Path)
assert.Equal(t, "127.0.0.1", req.Host)
assert.Equal(t, "HEAD", req.Method)
assert.Equal(t, "****", req.Header.Get("Authorization"))
assert.Equal(t, "****", req.Header.Get("Cookie"))
body, err := io.ReadAll(req.Body)
assert.Nil(t, nil, err)
assert.Equal(t, "xzxxxxxxzx", string(body))
Expand Down
10 changes: 5 additions & 5 deletions flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ var (
ApiKey = kingpin.Flag("api-key", "Coroot API key").Envar("API_KEY").String()
ScrapeInterval = kingpin.Flag("scrape-interval", "How often to gather metrics from the agent").Default("15s").Envar("SCRAPE_INTERVAL").Duration()

WalDir = kingpin.Flag("wal-dir", "Path to where the agent stores data (e.g. the metrics Write-Ahead Log)").Default("/tmp/coroot-node-agent").Envar("WAL_DIR").String()
ResolveDns = kingpin.Flag("resolve-dns", "should resolve DNS").Default("true").Envar("RESOLVE_DNS").Bool()
IgnoreControlPlane = kingpin.Flag("ignore-control-plane", "ignore control plane like loki").Default("karpenter,loki,prometheus,grafana,kubelet,etcd,apiserver,victoria").Envar("IGNORE_CONTROL_PLANE").String()
SensitiveHeaderPattern = kingpin.Flag("sensitive-header-patterns", "sanitize headers using patterns").Default("(?i)Authorization: (Bearer|Basic)\\s+[a-zA-Z0-9\\-_\\.\\=]+, (?i)ApiKey\\s+[a-zA-Z0-9\\-_\\.\\=]+, (?i)JWT\\s+[a-zA-Z0-9\\-_\\.\\=]+, (?i)OAuth\\s+[a-zA-Z0-9\\-_\\.\\=]+").Envar("SENSITIVE_HEADER_PATTERN").String()
SanitizeHeaders = kingpin.Flag("sanitize-headers", "should sanitize headers").Default("false").Envar("SANITIZE_HEADERS").Bool()
WalDir = kingpin.Flag("wal-dir", "Path to where the agent stores data (e.g. the metrics Write-Ahead Log)").Default("/tmp/coroot-node-agent").Envar("WAL_DIR").String()
ResolveDns = kingpin.Flag("resolve-dns", "should resolve DNS").Default("true").Envar("RESOLVE_DNS").Bool()
IgnoreControlPlane = kingpin.Flag("ignore-control-plane", "ignore control plane like loki").Default("karpenter,loki,prometheus,grafana,kubelet,etcd,apiserver,victoria").Envar("IGNORE_CONTROL_PLANE").String()
SanitizeHeaders = kingpin.Flag("sanitize-headers", "should sanitize headers").Default("true").Envar("SANITIZE_HEADERS").Bool()
SensitiveHeader = kingpin.Flag("sensitive-headers", "sanitize headers using patterns").Default("Authorization, Cookie, X-Action-Token").Envar("SENSITIVE_HEADERS").String()
)

func GetString(fl *string) string {
Expand Down
1 change: 1 addition & 0 deletions tracing/tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ func (t *Trace) HttpRequest(method, path string, status l7.Status, duration time
attribute.Key("http.request_payload").String(payload),
attribute.Key("http.headers").String(headers),
attribute.Key("http.response").String(response),
attribute.Key("http.path").String(path),
)
}

Expand Down