nicfinder_test.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package nicfinder
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "regexp"
  7. "testing"
  8. "github.com/slackhq/nebula/test"
  9. "github.com/stretchr/testify/assert"
  10. )
  11. type allowAll struct{}
  12. func (allowAll) Allow(netip.Addr) bool { return true }
  13. func (allowAll) AllowName(string) bool { return true }
  14. type testAllowList struct {
  15. bannedName *regexp.Regexp
  16. bannedAddr netip.Addr
  17. }
  18. func (l *testAllowList) Allow(addr netip.Addr) bool {
  19. return addr != l.bannedAddr
  20. }
  21. func (l *testAllowList) AllowName(n string) bool {
  22. return !l.bannedName.MatchString(n)
  23. }
  24. func newTestAllowList(bannedName string) *testAllowList {
  25. return &testAllowList{
  26. bannedName: regexp.MustCompile(bannedName),
  27. }
  28. }
  29. func TestAllowedAddr(t *testing.T) {
  30. ctx, l := context.Background(), test.NewLogger()
  31. allowed := func(filter Filter, addrs []net.Addr) []netip.Addr {
  32. var out []netip.Addr
  33. for _, rawAddr := range addrs {
  34. if addr, ok := allowedAddr(ctx, l, filter, rawAddr); ok {
  35. out = append(out, addr)
  36. }
  37. }
  38. return out
  39. }
  40. addrs := []net.Addr{
  41. &net.IPNet{IP: net.ParseIP("127.0.0.1"), Mask: net.CIDRMask(8, 32)},
  42. &net.IPNet{IP: net.ParseIP("::1"), Mask: net.CIDRMask(128, 128)},
  43. &net.IPNet{IP: net.ParseIP("10.0.0.5"), Mask: net.CIDRMask(24, 32)},
  44. &net.IPNet{IP: net.ParseIP("169.254.10.10"), Mask: net.CIDRMask(16, 32)},
  45. &net.IPNet{IP: net.ParseIP("fe80::1"), Mask: net.CIDRMask(64, 128)},
  46. &net.IPAddr{IP: net.ParseIP("fd00::5")},
  47. &net.IPNet{},
  48. otherAddr{},
  49. nil,
  50. }
  51. // Loopback, link local and anything without an IP are dropped, and IPv4 comes back unmapped
  52. // even though net.ParseIP hands over a 16 byte slice.
  53. assert.Equal(t, []netip.Addr{
  54. netip.MustParseAddr("10.0.0.5"),
  55. netip.MustParseAddr("fd00::5"),
  56. }, allowed(allowAll{}, addrs))
  57. // The filter sees the unmapped form and can drop a single address.
  58. al := newTestAllowList("none")
  59. al.bannedAddr = netip.MustParseAddr("10.0.0.5")
  60. assert.Equal(t, []netip.Addr{netip.MustParseAddr("fd00::5")}, allowed(al, addrs))
  61. }
  62. // otherAddr is a net.Addr that is neither *net.IPNet nor *net.IPAddr. netlink.Addr is one such
  63. // type: it satisfies net.Addr through an embedded *net.IPNet, and passing it directly once
  64. // silently produced no addresses.
  65. type otherAddr struct{}
  66. func (otherAddr) Network() string { return "other" }
  67. func (otherAddr) String() string { return "other" }
  68. // hostFilter counts AllowName calls and can reject every name or every address.
  69. type hostFilter struct {
  70. rejectNames bool
  71. rejectAddrs bool
  72. asked map[string]int
  73. }
  74. func (f *hostFilter) Allow(netip.Addr) bool { return !f.rejectAddrs }
  75. func (f *hostFilter) AllowName(name string) bool {
  76. f.asked[name]++
  77. return !f.rejectNames
  78. }
  79. // Runs this platform's localAddrs against the host and checks it honors the whole filter.
  80. func TestLocalAddrsAppliesFilter(t *testing.T) {
  81. ctx, l := context.Background(), test.NewLogger()
  82. f := &hostFilter{asked: map[string]int{}}
  83. all, err := localAddrs(ctx, l, f)
  84. if len(f.asked) == 0 {
  85. t.Skipf("no interfaces to enumerate here: %v", err)
  86. }
  87. for name, n := range f.asked {
  88. assert.Equal(t, 1, n, "AllowName asked %d times for %s", n, name)
  89. }
  90. // Loopback and link-local never come back, whatever the filter says.
  91. for _, addr := range all {
  92. assert.False(t, addr.IsLoopback() || addr.IsLinkLocalUnicast(), "%s", addr)
  93. }
  94. none, _ := localAddrs(ctx, l, &hostFilter{rejectNames: true, asked: map[string]int{}})
  95. assert.Empty(t, none, "addresses got past a filter that rejects every interface name")
  96. none, _ = localAddrs(ctx, l, &hostFilter{rejectAddrs: true, asked: map[string]int{}})
  97. assert.Empty(t, none, "addresses got past a filter that rejects every address")
  98. }