main_test.go 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package nebula
  2. import (
  3. "fmt"
  4. "net/netip"
  5. "os"
  6. "path/filepath"
  7. "testing"
  8. "time"
  9. "github.com/slackhq/nebula/cert"
  10. cert_test "github.com/slackhq/nebula/cert_test"
  11. "github.com/slackhq/nebula/config"
  12. "github.com/slackhq/nebula/test"
  13. "github.com/stretchr/testify/require"
  14. "go.uber.org/goleak"
  15. )
  16. // TestMain_ConfigTestReleasesItsGoroutines pins the rule that Main only leaves goroutines running
  17. // when it hands back a Control to stop them with.
  18. //
  19. // A config test gets no Control, so anything it started had nothing to stop it: the lighthouse
  20. // query worker, and a hostname resolver per dns named static host, ran for the life of the
  21. // process. That matters to every embedder that validates a config in process rather than by
  22. // exec'ing, dnclient and the apple clients included, because they do it on each config load and
  23. // the leak accumulates.
  24. func TestMain_ConfigTestReleasesItsGoroutines(t *testing.T) {
  25. defer goleak.VerifyNone(t, goleak.IgnoreCurrent())
  26. l := test.NewLogger()
  27. dir := t.TempDir()
  28. before := time.Now().Add(-time.Hour)
  29. after := time.Now().Add(time.Hour)
  30. ca, _, caKey, caPEM := cert_test.NewTestCaCert(cert.Version2, cert.Curve_CURVE25519, before, after, nil, nil, nil)
  31. networks := []netip.Prefix{netip.MustParsePrefix("10.0.0.1/24")}
  32. _, _, keyPEM, certPEM := cert_test.NewTestCert(
  33. cert.Version2, cert.Curve_CURVE25519, ca, caKey, "config-test", before, after, networks, nil, nil)
  34. caPath := filepath.Join(dir, "ca.pem")
  35. certPath := filepath.Join(dir, "cert.pem")
  36. keyPath := filepath.Join(dir, "key.pem")
  37. require.NoError(t, os.WriteFile(caPath, caPEM, 0o600))
  38. require.NoError(t, os.WriteFile(certPath, certPEM, 0o600))
  39. require.NoError(t, os.WriteFile(keyPath, keyPEM, 0o600))
  40. // A static host by address, not by name: the query worker is the goroutine under test and a
  41. // hostname would drag a real dns lookup into a unit test.
  42. configBody := fmt.Sprintf(`
  43. pki:
  44. ca: %s
  45. cert: %s
  46. key: %s
  47. static_host_map:
  48. "10.0.0.2": ["192.0.2.1:4242"]
  49. lighthouse:
  50. hosts:
  51. - "10.0.0.2"
  52. listen:
  53. host: 127.0.0.1
  54. port: 0
  55. tun:
  56. disabled: true
  57. firewall:
  58. outbound:
  59. - port: any
  60. proto: any
  61. host: any
  62. inbound:
  63. - port: any
  64. proto: any
  65. host: any
  66. `, caPath, certPath, keyPath)
  67. require.NoError(t, os.WriteFile(filepath.Join(dir, "config.yml"), []byte(configBody), 0o600))
  68. c := config.NewC(l)
  69. require.NoError(t, c.Load(dir))
  70. ctrl, err := Main(c, true, "config-test", l, nil)
  71. require.NoError(t, err)
  72. require.Nil(t, ctrl, "a config test hands back nothing to stop, so it must stop itself")
  73. }