package main import ( "os" "path/filepath" "strings" "testing" ) func catalogue(t *testing.T, files map[string]string) string { t.Helper() root := t.TempDir() for p, c := range files { full := filepath.Join(root, p) if err := os.MkdirAll(filepath.Dir(full), 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(full, []byte(c), 0o644); err != nil { t.Fatal(err) } } return root } const owner = `{"module":"power","resources":[{"id":"d","type":"directory","path":"/run/mesh-power"}]}` func TestAModuleReadingAnothersStateIsFound(t *testing.T) { root := catalogue(t, map[string]string{ "modules/power/module.json": owner, "modules/power/cmd/power/draw.go": `const f = "/run/mesh-power/draw"`, "modules/bar/module.json": `{"module":"bar","resources":[{"id":"x","type":"file","path":"/etc/x","content":"cat /run/mesh-power/draw"}]}`, "modules/other/module.json": `{"module":"other"}`, "modules/other/files/bin/read": "#!/bin/sh\ncat /run/mesh-power\n", "modules/other/README.md": "it once read /run/mesh-power/draw", "modules/other/cmd/x/x_test.go": `"/run/mesh-power"`, "modules/near/module.json": `{"module":"near","resources":[{"id":"y","type":"file","path":"/etc/y","content":"/run/mesh-power-other/x"}]}`, }) found, err := Check(root) if err != nil { t.Fatal(err) } var got []string for _, f := range found { got = append(got, f.Module+" "+f.File) } want := []string{"bar modules/bar/module.json", "other modules/other/files/bin/read"} if strings.Join(got, "|") != strings.Join(want, "|") { t.Fatalf("found %v, want %v", got, want) } if !strings.Contains(found[0].String(), "power's") { t.Fatalf("%s", found[0]) } } func TestACatalogueWhereEachKeepsToItsOwnIsClean(t *testing.T) { root := catalogue(t, map[string]string{ "modules/power/module.json": owner, "modules/power/cmd/power/draw.go": `const f = "/run/mesh-power/draw"`, }) if found, err := Check(root); err != nil || len(found) != 0 { t.Fatalf("%v %v", found, err) } } func TestEtcAndUsrLocalLibAreAModulesTooButNotInsideAContainer(t *testing.T) { root := catalogue(t, map[string]string{ "modules/power/module.json": `{"module":"power","resources":[{"id":"m","type":"directory","path":"/etc/mesh-power/moments"},` + `{"id":"s","type":"archive","path":"/usr/local/lib/mesh-power"}]}`, "modules/reader/module.json": `{"module":"reader"}`, "modules/reader/cmd/r/r.go": `const a, b = "/etc/mesh-power/moments/after-wake", "/usr/local/lib/mesh-power/bin/x"`, // A container that mounts something at that path inside itself names its own world. "modules/boxed/module.json": `{"module":"boxed","resources":[{"id":"c","type":"container",` + `"volumes":["/srv/boxed:/etc/mesh-power/moments",{"source":"/srv/b","target":"/usr/local/lib/mesh-power"}]}]}`, // A binary says what its source says. "modules/boxed/bin/tool": "\x00\x01/etc/mesh-power/moments\x00", }) found, err := Check(root) if err != nil { t.Fatal(err) } var got []string for _, f := range found { got = append(got, f.Module+" "+f.Path) } want := []string{"reader /etc/mesh-power/moments", "reader /usr/local/lib/mesh-power"} if strings.Join(got, "|") != strings.Join(want, "|") { t.Fatalf("found %v, want %v", got, want) } } func TestSharedPathsPassAndKnownFindingsOnlyShrink(t *testing.T) { found := []Finding{ {Module: "dns", File: "modules/dns/module.json", Path: "/etc/hosts", Owner: "hostname"}, {Module: "laptop", File: "modules/laptop/k.go", Path: "/etc/triggers", Owner: "keys"}, {Module: "new", File: "modules/new/n.go", Path: "/run/mesh-power", Owner: "power"}, } shared := map[string]bool{"/etc/hosts": true} known := map[string]bool{ "laptop /etc/triggers modules/laptop/k.go": true, "old /run/x modules/old/o.go": true, } refused, gone := Judge(found, shared, known) if len(refused) != 1 || refused[0].Module != "new" { t.Fatalf("refused %v", refused) } if len(gone) != 1 || gone[0] != "old /run/x modules/old/o.go" { t.Fatalf("gone %v", gone) } } func TestADropInDirectoryIsNoModulesButItsFilesAre(t *testing.T) { root := catalogue(t, map[string]string{ "modules/memory/module.json": `{"module":"memory","resources":[{"id":"d","type":"directory","path":"/etc/sysctl.d"},` + `{"id":"f","type":"file","path":"/etc/sysctl.d/90-memory.conf"}]}`, "modules/other/module.json": `{"module":"other","resources":[{"id":"f","type":"file","path":"/etc/sysctl.d/80-other.conf"}]}`, "modules/other/cmd/o/o.go": `const a, b = "/etc/sysctl.d", "/etc/sysctl.d/90-memory.conf"`, }) found, err := Check(root) if err != nil { t.Fatal(err) } if len(found) != 1 || found[0].Path != "/etc/sysctl.d/90-memory.conf" || found[0].Module != "other" { t.Fatalf("%v", found) } } func TestAListGrowsOnlyWithAReasonTheDiffShows(t *testing.T) { base := map[string]bool{"/etc/hosts": true} now := map[string]bool{"/etc/hosts": true, "/etc/a": true, "/etc/b": true} why := map[string]string{"/etc/a": "because", "/etc/b": "allow: every program reads it"} got := Grown("shared", now, why, base) if len(got) != 1 || !strings.Contains(got[0], `"/etc/a"`) { t.Fatalf("%v", got) } }