Delete a forwarded opening the way ufw accepts it, and read a fresh machine's resolver as not in use — both measured on a lab machine (hq ADR 0100)
This commit is contained in:
@@ -180,9 +180,17 @@ func (f *fakeUFW) run(_ context.Context, name string, args ...string) (string, e
|
||||
case args[0] == "disable":
|
||||
f.active = false
|
||||
return "Firewall stopped and disabled on system startup\n", nil
|
||||
case args[0] == "delete":
|
||||
case args[0] == "delete" && len(args) > 1 && args[1] == "route":
|
||||
// As the real ufw answers it (captured in testdata/ufw-delete.txt): a route rule is
|
||||
// deleted with `route delete`, never `delete route`.
|
||||
return "", errors.New("ERROR: Invalid syntax")
|
||||
case args[0] == "delete", args[0] == "route" && len(args) > 1 && args[1] == "delete":
|
||||
rest := args[1:]
|
||||
if args[0] == "route" {
|
||||
rest = append([]string{"route"}, args[2:]...)
|
||||
}
|
||||
for i, r := range f.rules {
|
||||
if strings.Join(words(r), "\x00") == strings.Join(args[1:], "\x00") {
|
||||
if strings.Join(words(r), "\x00") == strings.Join(rest, "\x00") {
|
||||
f.rules = append(f.rules[:i], f.rules[i+1:]...)
|
||||
return "Rule deleted\n", nil
|
||||
}
|
||||
@@ -333,3 +341,86 @@ func TestDetectingTheFoundFirewall(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The fixtures below were captured from a real ufw 0.36.2 on a lab machine, not written by hand:
|
||||
// ufw prints a rule back in its own shorter form, so the mark in the comment is the only thing the
|
||||
// host relies on.
|
||||
|
||||
func TestTheMarksAreReadFromWhatUfwReallyPrints(t *testing.T) {
|
||||
raw, err := os.ReadFile("testdata/ufw-show-added.txt")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
run := func(ctx context.Context, name string, args ...string) (string, error) { return string(raw), nil }
|
||||
rules, err := added(context.Background(), run)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(rules) != 7 {
|
||||
t.Fatalf("read %d rules, want 7: %q", len(rules), rules)
|
||||
}
|
||||
marked := 0
|
||||
for _, r := range rules {
|
||||
if strings.HasPrefix(comment(r), "mesh-host ") {
|
||||
marked++
|
||||
}
|
||||
}
|
||||
if marked != 5 {
|
||||
t.Errorf("read %d marked rules, want 5", marked)
|
||||
}
|
||||
if !markedFor(comment(rules[5]), "adoption.opening-tcp-8443-forwarded") {
|
||||
t.Errorf("the forwarded rule from the mesh lost its mark: %q", rules[5])
|
||||
}
|
||||
}
|
||||
|
||||
func TestEveryRealRuleIsDeletedInTheFormUfwAccepts(t *testing.T) {
|
||||
raw, err := os.ReadFile("testdata/ufw-show-added.txt")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
run := func(ctx context.Context, name string, args ...string) (string, error) { return string(raw), nil }
|
||||
rules, _ := added(context.Background(), run)
|
||||
// Each of these was run on the lab machine and answered "Rule deleted" (testdata/ufw-delete.txt).
|
||||
want := map[string]string{
|
||||
"allow 5671/tcp comment 'mesh-host adoption.opening-tcp-5671-incoming 1a2b3c4d'": "delete allow 5671/tcp comment|mesh-host adoption.opening-tcp-5671-incoming 1a2b3c4d",
|
||||
"allow in on mesh0 to any port 5432 proto tcp comment 'mesh-host adoption.opening-tcp-5432-incoming deadbeef'": "delete allow in on mesh0 to any port 5432 proto tcp comment|mesh-host adoption.opening-tcp-5432-incoming deadbeef",
|
||||
"route allow 80/tcp comment 'mesh-host adoption.opening-tcp-8081-forwarded 0badf00d'": "route delete allow 80/tcp comment|mesh-host adoption.opening-tcp-8081-forwarded 0badf00d",
|
||||
"route allow in on mesh0 to any port 443 proto tcp comment 'mesh-host adoption.opening-tcp-8443-forwarded cafe0001'": "route delete allow in on mesh0 to any port 443 proto tcp comment|mesh-host adoption.opening-tcp-8443-forwarded cafe0001",
|
||||
}
|
||||
seen := 0
|
||||
for _, r := range rules {
|
||||
w, ok := want[r]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
seen++
|
||||
d := deletion(r)
|
||||
got := strings.Join(d[:len(d)-1], " ") + "|" + d[len(d)-1]
|
||||
if got != w {
|
||||
t.Errorf("deleting %q\n got %s\n want %s", r, got, w)
|
||||
}
|
||||
}
|
||||
if seen != len(want) {
|
||||
t.Errorf("matched %d of %d captured rules", seen, len(want))
|
||||
}
|
||||
}
|
||||
|
||||
func TestARealUfwRulesetIsUfw(t *testing.T) {
|
||||
raw, err := os.ReadFile("testdata/ufw-active.nft")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
status, err := os.ReadFile("testdata/ufw-status-active.txt")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !statusActive(string(status)) {
|
||||
t.Fatal("the captured status does not read as active")
|
||||
}
|
||||
if refusing := Refusing(string(raw), true); len(refusing) > 0 {
|
||||
t.Errorf("a machine with ufw active and nothing else read as refusing in %v", refusing)
|
||||
}
|
||||
if refusing := Refusing(string(raw), false); len(refusing) == 0 {
|
||||
t.Error("ufw's drop chains, with ufw not known to be active, read as refusing nothing")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user