control_test.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package nebula
  2. import (
  3. "net"
  4. "net/netip"
  5. "reflect"
  6. "testing"
  7. "github.com/slackhq/nebula/cert"
  8. "github.com/slackhq/nebula/test"
  9. "github.com/stretchr/testify/assert"
  10. )
  11. func TestControl_GetHostInfoByVpnIp(t *testing.T) {
  12. //TODO: CERT-V2 with multiple certificate versions we have a problem with this test
  13. // Some certs versions have different characteristics and each version implements their own Copy() func
  14. // which means this is not a good place to test for exposing memory
  15. l := test.NewLogger()
  16. // Special care must be taken to re-use all objects provided to the hostmap and certificate in the expectedInfo object
  17. // To properly ensure we are not exposing core memory to the caller
  18. hm := newHostMap(l)
  19. hm.preferredRanges.Store(&[]netip.Prefix{})
  20. remote1 := netip.MustParseAddrPort("0.0.0.100:4444")
  21. remote2 := netip.MustParseAddrPort("[1:2:3:4:5:6:7:8]:4444")
  22. ipNet := net.IPNet{
  23. IP: remote1.Addr().AsSlice(),
  24. Mask: net.IPMask{255, 255, 255, 0},
  25. }
  26. ipNet2 := net.IPNet{
  27. IP: remote2.Addr().AsSlice(),
  28. Mask: net.IPMask{255, 255, 255, 0},
  29. }
  30. remotes := NewRemoteList([]netip.Addr{netip.IPv4Unspecified()}, nil)
  31. remotes.unlockedPrependV4(netip.IPv4Unspecified(), netAddrToProtoV4AddrPort(remote1.Addr(), remote1.Port()))
  32. remotes.unlockedPrependV6(netip.IPv4Unspecified(), netAddrToProtoV6AddrPort(remote2.Addr(), remote2.Port()))
  33. vpnIp, ok := netip.AddrFromSlice(ipNet.IP)
  34. assert.True(t, ok)
  35. crt := &dummyCert{}
  36. hi := &HostInfo{
  37. remotes: remotes,
  38. ConnectionState: &ConnectionState{
  39. peerCert: &cert.CachedCertificate{Certificate: crt},
  40. },
  41. remoteIndexId: 200,
  42. localIndexId: 201,
  43. vpnAddrs: []netip.Addr{vpnIp},
  44. relayState: RelayState{
  45. relays: nil,
  46. relayForByAddr: map[netip.Addr]*Relay{},
  47. relayForByIdx: map[uint32]*Relay{},
  48. },
  49. }
  50. hi.remote.Store(&remote1)
  51. hm.unlockedAddHostInfo(hi, &Interface{})
  52. vpnIp2, ok := netip.AddrFromSlice(ipNet2.IP)
  53. assert.True(t, ok)
  54. hi2 := &HostInfo{
  55. remotes: remotes,
  56. ConnectionState: &ConnectionState{
  57. peerCert: nil,
  58. },
  59. remoteIndexId: 200,
  60. localIndexId: 201,
  61. vpnAddrs: []netip.Addr{vpnIp2},
  62. relayState: RelayState{
  63. relays: nil,
  64. relayForByAddr: map[netip.Addr]*Relay{},
  65. relayForByIdx: map[uint32]*Relay{},
  66. },
  67. }
  68. hi2.remote.Store(&remote1)
  69. hm.unlockedAddHostInfo(hi2, &Interface{})
  70. c := Control{
  71. state: StateReady,
  72. f: &Interface{
  73. hostMap: hm,
  74. },
  75. l: test.NewLogger(),
  76. }
  77. thi := c.GetHostInfoByVpnAddr(vpnIp, false)
  78. expectedInfo := ControlHostInfo{
  79. VpnAddrs: []netip.Addr{vpnIp},
  80. LocalIndex: 201,
  81. RemoteIndex: 200,
  82. RemoteAddrs: []netip.AddrPort{remote2, remote1},
  83. Cert: crt.Copy(),
  84. MessageCounter: 0,
  85. CurrentRemote: remote1,
  86. CurrentRelaysToMe: []netip.Addr{},
  87. CurrentRelaysThroughMe: []netip.Addr{},
  88. }
  89. // Make sure we don't have any unexpected fields
  90. assertFields(t, []string{"VpnAddrs", "LocalIndex", "RemoteIndex", "RemoteAddrs", "Cert", "MessageCounter", "CurrentRemote", "CurrentRelaysToMe", "CurrentRelaysThroughMe"}, thi)
  91. assert.Equal(t, &expectedInfo, thi)
  92. test.AssertDeepCopyEqual(t, &expectedInfo, thi)
  93. // Make sure we don't panic if the host info doesn't have a cert yet
  94. assert.NotPanics(t, func() {
  95. thi = c.GetHostInfoByVpnAddr(vpnIp2, false)
  96. })
  97. }
  98. func assertFields(t *testing.T, expected []string, actualStruct any) {
  99. val := reflect.ValueOf(actualStruct).Elem()
  100. fields := make([]string, val.NumField())
  101. for i := 0; i < val.NumField(); i++ {
  102. fields[i] = val.Type().Field(i).Name
  103. }
  104. assert.Equal(t, expected, fields)
  105. }