148 lines
5.4 KiB
Go
148 lines
5.4 KiB
Go
package main
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func manifest(t *testing.T, root, module, body string) {
|
|
t.Helper()
|
|
dir := filepath.Join(root, "modules", module)
|
|
if err := os.MkdirAll(dir, 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(dir, "module.json"), []byte(body), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func check(t *testing.T, root string) []Finding {
|
|
t.Helper()
|
|
found, err := Check(root)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return found
|
|
}
|
|
|
|
// only asserts exactly one finding, of the rule, naming the module and the resource (issue 1024).
|
|
func only(t *testing.T, found []Finding, rule int, module, id string) {
|
|
t.Helper()
|
|
if len(found) != 1 || found[0].Rule != rule || found[0].Module != module || found[0].ID != id || found[0].Why == "" {
|
|
t.Fatalf("found %+v; want one finding of rule %d for %s/%s with a reason", found, rule, module, id)
|
|
}
|
|
}
|
|
|
|
func dir(id, path, rest string) string {
|
|
return `{"id":"` + id + `","type":"directory","path":"` + path + `"` + rest + `}`
|
|
}
|
|
|
|
func mod(name string, resources ...string) string {
|
|
return `{"module":"` + name + `","resources":[` + strings.Join(resources, ",") + `]}`
|
|
}
|
|
|
|
func TestMissingOrUnknownValueIsRefused(t *testing.T) {
|
|
root := t.TempDir()
|
|
manifest(t, root, "a", mod("a", dir("d", "/var/lib/a", "")))
|
|
only(t, check(t, root), 1, "a", "d")
|
|
|
|
root = t.TempDir()
|
|
manifest(t, root, "a", mod("a", `{"id":"z","type":"archive","path":"/opt/a","unknown":"delete"}`))
|
|
only(t, check(t, root), 1, "a", "z")
|
|
}
|
|
|
|
func TestMoveOutOutsideAHomeIsRefused(t *testing.T) {
|
|
root := t.TempDir()
|
|
manifest(t, root, "a", mod("a", dir("d", "/etc/a.d", `,"unknown":"move-out"`)))
|
|
only(t, check(t, root), 2, "a", "d")
|
|
}
|
|
|
|
func TestMoveOutUnderAHomeIsAllowed(t *testing.T) {
|
|
root := t.TempDir()
|
|
manifest(t, root, "a", mod("a",
|
|
dir("d", "${machine:account-home}/.config/a", `,"unknown":"move-out"`),
|
|
dir("e", "${dir:d}/sub", `,"unknown":"move-out"`),
|
|
dir("f", "${machine:agent-home}/x", `,"unknown":"move-out"`),
|
|
dir("g", "/var/lib/a", `,"unknown":"program"`),
|
|
dir("h", "${machine:account-home}/.ssh", `,"unknown":"module"`)))
|
|
if found := check(t, root); len(found) != 0 {
|
|
t.Fatalf("refused %+v", found)
|
|
}
|
|
}
|
|
|
|
func TestBadKnowsIsRefused(t *testing.T) {
|
|
for _, knows := range []string{`[""]`, `["/abs"]`, `["a/../b"]`, `["./a"]`, `["a//b"]`, `["a","a"]`, `["a","a/"]`} {
|
|
root := t.TempDir()
|
|
manifest(t, root, "a", mod("a", dir("d", "${machine:account-home}/.config/a", `,"unknown":"move-out","knows":`+knows)))
|
|
only(t, check(t, root), 3, "a", "d")
|
|
}
|
|
root := t.TempDir()
|
|
manifest(t, root, "a", mod("a", dir("d", "${machine:account-home}/.config/a", `,"unknown":"move-out","knows":["forge.credentials","kept/"]`)))
|
|
if found := check(t, root); len(found) != 0 {
|
|
t.Fatalf("refused %+v", found)
|
|
}
|
|
}
|
|
|
|
func TestAnotherModulesPathInsideADirectoryIsRefused(t *testing.T) {
|
|
root := t.TempDir()
|
|
manifest(t, root, "owner", mod("owner", dir("ssh", "${machine:account-home}/.ssh", `,"unknown":"module"`)))
|
|
manifest(t, root, "intruder", mod("intruder", `{"id":"f","type":"file","path":"${machine:account-home}/.ssh/config.d/20"}`))
|
|
manifest(t, root, "viahome", mod("viahome", `{"id":"g","type":"file","path":"${machine:agent-home}/.ssh/x"}`))
|
|
manifest(t, root, "facty", `{"module":"facty","facts":{"hosts":{"path":".ssh/config.d/00","home":true}}}`)
|
|
manifest(t, root, "outside", mod("outside", `{"id":"o","type":"file","path":"${machine:account-home}/.sshrc"}`))
|
|
got := map[string]int{}
|
|
for _, f := range check(t, root) {
|
|
if f.Rule != 4 || f.Why == "" {
|
|
t.Fatalf("finding %+v", f)
|
|
}
|
|
got[f.Module]++
|
|
}
|
|
if len(got) != 3 || got["intruder"] != 1 || got["viahome"] != 1 || got["facty"] != 1 {
|
|
t.Fatalf("refused %v; want intruder, viahome, facty", got)
|
|
}
|
|
}
|
|
|
|
func TestDirReferencesAreResolvedPerModule(t *testing.T) {
|
|
root := t.TempDir()
|
|
manifest(t, root, "owner", mod("owner", dir("base", "${machine:account-home}/.config/o", `,"unknown":"move-out"`)))
|
|
manifest(t, root, "other", mod("other",
|
|
dir("base", "${machine:account-home}/.config/p", `,"unknown":"move-out"`),
|
|
`{"id":"f","type":"file","path":"${dir:base}/x"}`))
|
|
if found := check(t, root); len(found) != 0 {
|
|
t.Fatalf("refused %+v", found)
|
|
}
|
|
manifest(t, root, "third", mod("third",
|
|
dir("d", "${machine:account-home}/.config/t", `,"unknown":"move-out"`),
|
|
`{"id":"f","type":"file","path":"${dir:d}/../o/x"}`))
|
|
only(t, check(t, root), 4, "third", "f")
|
|
}
|
|
|
|
func TestAnArchiveIsNotAContainerAndSameModuleIsFine(t *testing.T) {
|
|
root := t.TempDir()
|
|
manifest(t, root, "a", mod("a",
|
|
`{"id":"arc","type":"archive","path":"/opt/a","unknown":"program"}`,
|
|
dir("d", "/opt/a2", `,"unknown":"program"`),
|
|
`{"id":"f","type":"file","path":"/opt/a2/x"}`))
|
|
manifest(t, root, "b", mod("b", `{"id":"f","type":"file","path":"/opt/a/x"}`))
|
|
if found := check(t, root); len(found) != 0 {
|
|
t.Fatalf("refused %+v", found)
|
|
}
|
|
}
|
|
|
|
// Issue 1484: a directory the mesh places for a module (no path, `place`) is that module's own: another module's
|
|
// directory of the same id, and a path under it, are not inside it.
|
|
func TestPlacedDirectoriesOfTwoModulesAreTheirOwn(t *testing.T) {
|
|
root := t.TempDir()
|
|
for _, name := range []string{"first", "second"} {
|
|
manifest(t, root, name, mod(name,
|
|
`{"id":"state","type":"directory","place":".","unknown":"program"}`,
|
|
dir("ssh", "${dir:state}/.ssh", `,"unknown":"program"`),
|
|
`{"id":"conf","type":"file","path":"${dir:ssh}/config"}`))
|
|
}
|
|
if found := check(t, root); len(found) != 0 {
|
|
t.Fatalf("refused %+v", found)
|
|
}
|
|
}
|