package main import ( "context" "io/fs" "os" "path/filepath" "testing" "git.novox.be/novox/mesh-sdk/go/forgekey" ) // npmAsUmask077 installs as npm does under a umask of 077: node_modules with a package whose folders are 0700, its // file 0600 and its program 0700. func npmAsUmask077(f *fakeNpm) forgekey.Runner { return func(ctx context.Context, env []string, name string, args ...string) forgekey.Ran { ran := f.run(ctx, env, name, args...) for i, a := range args { if a == "--prefix" { pkg := filepath.Join(args[i+1], "node_modules", "typescript", "bin") os.MkdirAll(pkg, 0o700) os.WriteFile(filepath.Join(args[i+1], "node_modules", "typescript", "package.json"), []byte("{}"), 0o600) os.WriteFile(filepath.Join(pkg, "tsc"), []byte("#!/bin/sh\n"), 0o700) } } return ran } } // checkOpen fails unless every folder from the cache's toolchain down lets others enter and read it and every file lets // others read it, a program others run, and nothing lets anyone but the owner write. func checkOpen(t *testing.T, tc Toolchain) { t.Helper() root := filepath.Join(tc.Paths.Cache, "toolchain") err := filepath.WalkDir(root, func(p string, d fs.DirEntry, err error) error { if err != nil { return err } info, err := d.Info() if err != nil { return err } mode := info.Mode().Perm() switch { case mode&0o022 != 0: t.Errorf("%s is %o: writable by others than its owner", p, mode) case d.IsDir() && mode&0o005 != 0o005: t.Errorf("%s is %o: others may not enter and read it", p, mode) case !d.IsDir() && mode&0o004 == 0: t.Errorf("%s is %o: others may not read it", p, mode) case !d.IsDir() && mode&0o100 != 0 && mode&0o001 == 0: t.Errorf("%s is %o: a program others may not run", p, mode) } return nil }) if err != nil { t.Fatal(err) } } // 1891 (ADR 0533 §2): a toolchain the module installs can be read by the other build module's integration level: // its folders 0755 and its files 0644 (programs 0755), whatever umask npm ran under, and writable by its owner alone. func TestAnInstalledToolchainIsReadableByOthersAndWritableByItsOwnerAlone(t *testing.T) { fake := &fakeNpm{} tc := toolchainIn(t, fake) tc.Run = npmAsUmask077(fake) if err := tc.Ensure(context.Background(), "v1"); err != nil { t.Fatal(err) } checkOpen(t, tc) } // 1891 (ADR 0533 §2): a toolchain installed before this release, shut to its owner, is opened by the next Ensure // without installing it again. func TestAToolchainInstalledShutIsOpenedWithoutAnInstall(t *testing.T) { fake := &fakeNpm{} tc := toolchainIn(t, fake) dir := tc.Paths.Dir("v1") os.MkdirAll(filepath.Join(dir, "node_modules", "esbuild", "bin"), 0o700) os.WriteFile(filepath.Join(dir, "node_modules", "esbuild", "bin", "esbuild"), []byte("x"), 0o700) os.WriteFile(filepath.Join(dir, "package-lock.json"), []byte("{}"), 0o600) os.WriteFile(filepath.Join(dir, installedMark), []byte("v1\n"), 0o600) os.Chmod(filepath.Join(tc.Paths.Cache, "toolchain"), 0o700) if err := tc.Ensure(context.Background(), "v1"); err != nil { t.Fatal(err) } if len(fake.calls) != 0 { t.Errorf("npm ran %d times for a toolchain already there", len(fake.calls)) } checkOpen(t, tc) } // 1891 (ADR 0533 §2): the cache directory lets other accounts enter it and not list it, so the toolchains beneath it // can be reached by their path and the npm cache beside them (0700) cannot. func TestTheCacheDirectoryIsEnteredByOthersNotListed(t *testing.T) { r := resource(t, readManifest(t), "cache") if r["mode"] != "0711" { t.Errorf("the cache directory's mode is %v, want 0711", r["mode"]) } }