mirror of
https://github.com/netbirdio/netbird.git
synced 2024-11-26 18:13:40 +01:00
4424162bce
* Add status anonymization * Add OS/arch to the status command * Use human-friendly last-update status messages * Add debug bundle command to collect (anonymized) logs * Add debug log level command * And debug for a certain time span command
224 lines
6.9 KiB
Go
224 lines
6.9 KiB
Go
package anonymize_test
|
|
|
|
import (
|
|
"net/netip"
|
|
"regexp"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/netbirdio/netbird/client/anonymize"
|
|
)
|
|
|
|
func TestAnonymizeIP(t *testing.T) {
|
|
startIPv4 := netip.MustParseAddr("198.51.100.0")
|
|
startIPv6 := netip.MustParseAddr("100::")
|
|
anonymizer := anonymize.NewAnonymizer(startIPv4, startIPv6)
|
|
|
|
tests := []struct {
|
|
name string
|
|
ip string
|
|
expect string
|
|
}{
|
|
{"Well known", "8.8.8.8", "8.8.8.8"},
|
|
{"First Public IPv4", "1.2.3.4", "198.51.100.0"},
|
|
{"Second Public IPv4", "4.3.2.1", "198.51.100.1"},
|
|
{"Repeated IPv4", "1.2.3.4", "198.51.100.0"},
|
|
{"Private IPv4", "192.168.1.1", "192.168.1.1"},
|
|
{"First Public IPv6", "2607:f8b0:4005:805::200e", "100::"},
|
|
{"Second Public IPv6", "a::b", "100::1"},
|
|
{"Repeated IPv6", "2607:f8b0:4005:805::200e", "100::"},
|
|
{"Private IPv6", "fe80::1", "fe80::1"},
|
|
{"In Range IPv4", "198.51.100.2", "198.51.100.2"},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
ip := netip.MustParseAddr(tc.ip)
|
|
anonymizedIP := anonymizer.AnonymizeIP(ip)
|
|
if anonymizedIP.String() != tc.expect {
|
|
t.Errorf("%s: expected %s, got %s", tc.name, tc.expect, anonymizedIP)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAnonymizeDNSLogLine(t *testing.T) {
|
|
anonymizer := anonymize.NewAnonymizer(netip.Addr{}, netip.Addr{})
|
|
testLog := `2024-04-23T20:01:11+02:00 TRAC client/internal/dns/local.go:25: received question: dns.Question{Name:"example.com", Qtype:0x1c, Qclass:0x1}`
|
|
|
|
result := anonymizer.AnonymizeDNSLogLine(testLog)
|
|
require.NotEqual(t, testLog, result)
|
|
assert.NotContains(t, result, "example.com")
|
|
}
|
|
|
|
func TestAnonymizeDomain(t *testing.T) {
|
|
anonymizer := anonymize.NewAnonymizer(netip.Addr{}, netip.Addr{})
|
|
tests := []struct {
|
|
name string
|
|
domain string
|
|
expectPattern string
|
|
shouldAnonymize bool
|
|
}{
|
|
{
|
|
"General Domain",
|
|
"example.com",
|
|
`^anon-[a-zA-Z0-9]+\.domain$`,
|
|
true,
|
|
},
|
|
{
|
|
"Subdomain",
|
|
"sub.example.com",
|
|
`^sub\.anon-[a-zA-Z0-9]+\.domain$`,
|
|
true,
|
|
},
|
|
{
|
|
"Protected Domain",
|
|
"netbird.io",
|
|
`^netbird\.io$`,
|
|
false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
result := anonymizer.AnonymizeDomain(tc.domain)
|
|
if tc.shouldAnonymize {
|
|
assert.Regexp(t, tc.expectPattern, result, "The anonymized domain should match the expected pattern")
|
|
assert.NotContains(t, result, tc.domain, "The original domain should not be present in the result")
|
|
} else {
|
|
assert.Equal(t, tc.domain, result, "Protected domains should not be anonymized")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAnonymizeURI(t *testing.T) {
|
|
anonymizer := anonymize.NewAnonymizer(netip.Addr{}, netip.Addr{})
|
|
tests := []struct {
|
|
name string
|
|
uri string
|
|
regex string
|
|
}{
|
|
{
|
|
"HTTP URI with Port",
|
|
"http://example.com:80/path",
|
|
`^http://anon-[a-zA-Z0-9]+\.domain:80/path$`,
|
|
},
|
|
{
|
|
"HTTP URI without Port",
|
|
"http://example.com/path",
|
|
`^http://anon-[a-zA-Z0-9]+\.domain/path$`,
|
|
},
|
|
{
|
|
"Opaque URI with Port",
|
|
"stun:example.com:80?transport=udp",
|
|
`^stun:anon-[a-zA-Z0-9]+\.domain:80\?transport=udp$`,
|
|
},
|
|
{
|
|
"Opaque URI without Port",
|
|
"stun:example.com?transport=udp",
|
|
`^stun:anon-[a-zA-Z0-9]+\.domain\?transport=udp$`,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
result := anonymizer.AnonymizeURI(tc.uri)
|
|
assert.Regexp(t, regexp.MustCompile(tc.regex), result, "URI should match expected pattern")
|
|
require.NotContains(t, result, "example.com", "Original domain should not be present")
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAnonymizeSchemeURI(t *testing.T) {
|
|
anonymizer := anonymize.NewAnonymizer(netip.Addr{}, netip.Addr{})
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expect string
|
|
}{
|
|
{"STUN URI in text", "Connection made via stun:example.com", `Connection made via stun:anon-[a-zA-Z0-9]+\.domain`},
|
|
{"TURN URI in log", "Failed attempt turn:some.example.com:3478?transport=tcp: retrying", `Failed attempt turn:some.anon-[a-zA-Z0-9]+\.domain:3478\?transport=tcp: retrying`},
|
|
{"HTTPS URI in message", "Visit https://example.com for more", `Visit https://anon-[a-zA-Z0-9]+\.domain for more`},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
result := anonymizer.AnonymizeSchemeURI(tc.input)
|
|
assert.Regexp(t, tc.expect, result, "The anonymized output should match expected pattern")
|
|
require.NotContains(t, result, "example.com", "Original domain should not be present")
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestAnonymizString_MemorizedDomain(t *testing.T) {
|
|
anonymizer := anonymize.NewAnonymizer(netip.Addr{}, netip.Addr{})
|
|
domain := "example.com"
|
|
anonymizedDomain := anonymizer.AnonymizeDomain(domain)
|
|
|
|
sampleString := "This is a test string including the domain example.com which should be anonymized."
|
|
|
|
firstPassResult := anonymizer.AnonymizeString(sampleString)
|
|
secondPassResult := anonymizer.AnonymizeString(firstPassResult)
|
|
|
|
assert.Contains(t, firstPassResult, anonymizedDomain, "The domain should be anonymized in the first pass")
|
|
assert.NotContains(t, firstPassResult, domain, "The original domain should not appear in the first pass output")
|
|
|
|
assert.Equal(t, firstPassResult, secondPassResult, "The second pass should not further anonymize the string")
|
|
}
|
|
|
|
func TestAnonymizeString_DoubleURI(t *testing.T) {
|
|
anonymizer := anonymize.NewAnonymizer(netip.Addr{}, netip.Addr{})
|
|
domain := "example.com"
|
|
anonymizedDomain := anonymizer.AnonymizeDomain(domain)
|
|
|
|
sampleString := "Check out our site at https://example.com for more info."
|
|
|
|
firstPassResult := anonymizer.AnonymizeString(sampleString)
|
|
secondPassResult := anonymizer.AnonymizeString(firstPassResult)
|
|
|
|
assert.Contains(t, firstPassResult, "https://"+anonymizedDomain, "The URI should be anonymized in the first pass")
|
|
assert.NotContains(t, firstPassResult, "https://example.com", "The original URI should not appear in the first pass output")
|
|
|
|
assert.Equal(t, firstPassResult, secondPassResult, "The second pass should not further anonymize the URI")
|
|
}
|
|
|
|
func TestAnonymizeString_IPAddresses(t *testing.T) {
|
|
anonymizer := anonymize.NewAnonymizer(anonymize.DefaultAddresses())
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expect string
|
|
}{
|
|
{
|
|
name: "IPv4 Address",
|
|
input: "Error occurred at IP 122.138.1.1",
|
|
expect: "Error occurred at IP 198.51.100.0",
|
|
},
|
|
{
|
|
name: "IPv6 Address",
|
|
input: "Access attempted from 2001:db8::ff00:42",
|
|
expect: "Access attempted from 100::",
|
|
},
|
|
{
|
|
name: "IPv6 Address with Port",
|
|
input: "Access attempted from [2001:db8::ff00:42]:8080",
|
|
expect: "Access attempted from [100::]:8080",
|
|
},
|
|
{
|
|
name: "Both IPv4 and IPv6",
|
|
input: "IPv4: 142.108.0.1 and IPv6: 2001:db8::ff00:43",
|
|
expect: "IPv4: 198.51.100.1 and IPv6: 100::1",
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
result := anonymizer.AnonymizeString(tc.input)
|
|
assert.Equal(t, tc.expect, result, "IP addresses should be anonymized correctly")
|
|
})
|
|
}
|
|
}
|