package delivery_test import ( "context" "net" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "sneak.berlin/go/webhooker/internal/delivery" ) func TestIsBlockedIP_PrivateRanges(t *testing.T) { t.Parallel() tests := []struct { name string ip string blocked bool }{ {"loopback 127.0.0.1", "127.0.0.1", true}, {"loopback 127.0.0.2", "127.0.0.2", true}, {"loopback 127.255.255.255", "127.255.255.255", true}, {"10.0.0.0", "10.0.0.0", true}, {"10.0.0.1", "10.0.0.1", true}, {"10.255.255.255", "10.255.255.255", true}, {"172.16.0.1", "172.16.0.1", true}, {"172.31.255.255", "172.31.255.255", true}, {"172.15.255.255", "172.15.255.255", false}, {"172.32.0.0", "172.32.0.0", false}, {"192.168.0.1", "192.168.0.1", true}, {"192.168.255.255", "192.168.255.255", true}, {"169.254.0.1", "169.254.0.1", true}, {"169.254.169.254", "169.254.169.254", true}, {"8.8.8.8", "8.8.8.8", false}, {"1.1.1.1", "1.1.1.1", false}, {"93.184.216.34", "93.184.216.34", false}, {"::1", "::1", true}, {"fd00::1", "fd00::1", true}, {"fc00::1", "fc00::1", true}, {"fe80::1", "fe80::1", true}, { "2607:f8b0:4004:800::200e", "2607:f8b0:4004:800::200e", false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { t.Parallel() ip := net.ParseIP(tt.ip) require.NotNil(t, ip, "failed to parse IP %s", tt.ip, ) assert.Equal(t, tt.blocked, delivery.ExportIsBlockedIP(ip), "isBlockedIP(%s) = %v, want %v", tt.ip, delivery.ExportIsBlockedIP(ip), tt.blocked, ) }) } } func TestValidateTargetURL_Blocked(t *testing.T) { t.Parallel() blockedURLs := []string{ "http://127.0.0.1/hook", "http://127.0.0.1:8080/hook", "https://10.0.0.1/hook", "http://192.168.1.1/webhook", "http://172.16.0.1/api", "http://169.254.169.254/latest/meta-data/", "http://[::1]/hook", "http://[fc00::1]/hook", "http://[fe80::1]/hook", "http://0.0.0.0/hook", } for _, u := range blockedURLs { t.Run(u, func(t *testing.T) { t.Parallel() err := delivery.ValidateTargetURL( context.Background(), u, ) assert.Error(t, err, "URL %s should be blocked", u, ) }) } } func TestValidateTargetURL_Allowed(t *testing.T) { t.Parallel() allowedURLs := []string{ "https://example.com/hook", "http://93.184.216.34/webhook", "https://hooks.slack.com/services/T00/B00/xxx", } for _, u := range allowedURLs { t.Run(u, func(t *testing.T) { t.Parallel() err := delivery.ValidateTargetURL( context.Background(), u, ) assert.NoError(t, err, "URL %s should be allowed", u, ) }) } } func TestValidateTargetURL_InvalidScheme(t *testing.T) { t.Parallel() err := delivery.ValidateTargetURL( context.Background(), "ftp://example.com/hook", ) require.Error(t, err) assert.Contains(t, err.Error(), "unsupported URL scheme", ) } func TestValidateTargetURL_EmptyHost(t *testing.T) { t.Parallel() err := delivery.ValidateTargetURL( context.Background(), "http:///path", ) assert.Error(t, err) } func TestValidateTargetURL_InvalidURL(t *testing.T) { t.Parallel() err := delivery.ValidateTargetURL( context.Background(), "://invalid", ) assert.Error(t, err) } func TestBlockedNetworks_Initialized(t *testing.T) { t.Parallel() nets := delivery.ExportBlockedNetworks() assert.NotEmpty(t, nets, "blockedNetworks should be initialized", ) assert.GreaterOrEqual(t, len(nets), 8, "should have at least 8 blocked network ranges", ) }