policy_transaction_test.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package routing
  2. import (
  3. "os"
  4. "os/exec"
  5. "path/filepath"
  6. "strings"
  7. "testing"
  8. )
  9. func TestIsolatedPolicyActionsAndExactDeletion(t *testing.T) {
  10. if os.Getenv("DEBTIK_TEST_ISOLATED_NETNS") != "1" {
  11. t.Skip("requires a dedicated network namespace")
  12. }
  13. useTempRouteStores(t)
  14. ip := func(args ...string) string {
  15. t.Helper()
  16. out, err := exec.Command("ip", args...).CombinedOutput()
  17. if err != nil {
  18. t.Fatalf("ip %v: %s %v", args, out, err)
  19. }
  20. return string(out)
  21. }
  22. ip("rule", "add", "pref", "11200", "from", "203.0.113.0/24", "lookup", "main")
  23. m := &RoutingManager{}
  24. for _, tc := range []struct {
  25. priority int
  26. action string
  27. }{{11200, "blackhole"}, {11201, "unreachable"}, {11202, "lookup"}} {
  28. p := PolicyRuleItem{ID: tc.action, Priority: tc.priority, Action: tc.action, SrcAddress: "198.51.100.0/24", Table: "main"}
  29. if err := m.SavePolicyRule(p); err != nil {
  30. t.Fatalf("save %s: %v", tc.action, err)
  31. }
  32. }
  33. listed := m.ListPolicyRules()
  34. seen := map[string]bool{}
  35. unmanaged := false
  36. for _, rule := range listed {
  37. if rule.ID == "blackhole" || rule.ID == "unreachable" || rule.ID == "lookup" {
  38. if rule.Action != rule.ID || rule.IsSystem {
  39. t.Fatalf("incorrect rule: %+v", rule)
  40. }
  41. seen[rule.ID] = true
  42. }
  43. if rule.Priority == 11200 && rule.SrcAddress == "203.0.113.0/24" {
  44. unmanaged = rule.IsSystem
  45. }
  46. }
  47. if len(seen) != 3 || !unmanaged {
  48. t.Fatalf("incorrect mapping: %v unmanaged=%v listed=%+v", seen, unmanaged, listed)
  49. }
  50. if err := m.DeletePolicyRule("blackhole"); err != nil {
  51. t.Fatal(err)
  52. }
  53. show := ip("rule", "show")
  54. if !strings.Contains(show, "from 203.0.113.0/24 lookup main") || strings.Contains(show, "from 198.51.100.0/24 blackhole") {
  55. t.Fatalf("wrong rule deleted: %s", show)
  56. }
  57. if err := m.DeletePolicyRule("rule-11200-254"); err == nil {
  58. t.Fatal("unmanaged rule deletion accepted")
  59. }
  60. for _, id := range []string{"unreachable", "lookup"} {
  61. if err := m.DeletePolicyRule(id); err != nil {
  62. t.Fatal(err)
  63. }
  64. }
  65. }
  66. func TestIsolatedPolicySaveFailureRemovesKernelRule(t *testing.T) {
  67. if os.Getenv("DEBTIK_TEST_ISOLATED_NETNS") != "1" {
  68. t.Skip("requires a dedicated network namespace")
  69. }
  70. useTempRouteStores(t)
  71. bad := filepath.Join(t.TempDir(), "dir")
  72. if err := os.Mkdir(bad, 0700); err != nil {
  73. t.Fatal(err)
  74. }
  75. StaticRoutesStorePath = bad
  76. m := &RoutingManager{}
  77. err := m.SavePolicyRule(PolicyRuleItem{ID: "r", Priority: 11300, Action: "blackhole", SrcAddress: "198.51.100.0/24"})
  78. if err == nil {
  79. t.Fatal("save should fail")
  80. }
  81. out, e := exec.Command("ip", "rule", "show").CombinedOutput()
  82. if e != nil {
  83. t.Fatal(e)
  84. }
  85. if strings.Contains(string(out), "11300:") {
  86. t.Fatalf("kernel rule not rolled back: %s", out)
  87. }
  88. if len(m.policyRules) != 0 {
  89. t.Fatal("memory not restored")
  90. }
  91. }
  92. func TestTableRegistryFailureRestoresMemory(t *testing.T) {
  93. useTempRouteStores(t)
  94. old := RTTableFilePath
  95. t.Cleanup(func() { RTTableFilePath = old })
  96. RTTableFilePath = filepath.Join(t.TempDir(), "missing", "rt_tables")
  97. m := &RoutingManager{}
  98. if err := m.SaveTable(RoutingTableItem{Name: "test", TableID: 501}); err == nil {
  99. t.Fatal("registry failure ignored")
  100. }
  101. if len(m.customTables) != 0 {
  102. t.Fatalf("table not rolled back: %+v", m.customTables)
  103. }
  104. }
  105. func TestTableRejectsReservedAndInvalidNames(t *testing.T) {
  106. useTempRouteStores(t)
  107. old := RTTableFilePath
  108. t.Cleanup(func() { RTTableFilePath = old })
  109. RTTableFilePath = filepath.Join(t.TempDir(), "rt_tables")
  110. m := &RoutingManager{}
  111. for _, table := range []RoutingTableItem{{Name: "main", TableID: 501}, {Name: "bad name", TableID: 502}, {Name: "bad\nentry", TableID: 503}, {Name: "test", TableID: 254}} {
  112. if err := m.SaveTable(table); err == nil {
  113. t.Fatalf("accepted table %+v", table)
  114. }
  115. }
  116. if len(m.customTables) != 0 {
  117. t.Fatal("invalid tables saved")
  118. }
  119. }