carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package host
2
3import (
4 "crypto/sha256"
5 "encoding/hex"
6 "encoding/json"
7 "os"
8 "os/exec"
9 "path/filepath"
10 "reflect"
11 "syscall"
12 "testing"
13
14 "github.com/carlosframework/platform/internal/hostbox"
15 "golang.org/x/sys/unix"
16)
17
18func TestPlan14PreparedInventoryPrivateView(t *testing.T) {
19 mode := os.Getenv("PLAN14_INVENTORY_VIEW")
20 binary, err := os.Executable()
21 if err != nil {
22 t.Fatal(err)
23 }
24 if mode == "" {
25 root := t.TempDir()
26 cmd := exec.Command("unshare", "--user", "--map-root-user", "--mount", binary, "-test.run=^TestPlan14PreparedInventoryPrivateView$", "-test.v")
27 cmd.Env = append(os.Environ(), "PLAN14_INVENTORY_VIEW=root", "PLAN14_INVENTORY_ROOT="+root)
28 out, err := cmd.CombinedOutput()
29 if err != nil {
30 t.Fatalf("private inventory fixture: %v\n%s", err, out)
31 }
32 t.Log(string(out))
33 return
34 }
35 root := os.Getenv("PLAN14_INVENTORY_ROOT")
36 view := filepath.Join(root, "view")
37 if mode == "root" {
38 for _, name := range []string{"raw", "view", "other"} {
39 if err := os.Mkdir(filepath.Join(root, name), 0700); err != nil {
40 t.Fatal(err)
41 }
42 }
43 if err := unix.Mount(filepath.Join(root, "raw"), view, "", unix.MS_BIND, ""); err != nil {
44 t.Fatal(err)
45 }
46 defer unix.Unmount(view, 0)
47 id, err := hostbox.CaptureInventoryIdentity(root, "view")
48 if err != nil {
49 t.Fatal(err)
50 }
51 e := hostbox.StopInventoryEntry{RelativePath: "view", Device: id.Device, Inode: id.Inode, Type: unix.S_IFDIR, Identity: id}
52 raw, err := json.Marshal(e)
53 if err != nil {
54 t.Fatal(err)
55 }
56 if err := os.WriteFile(filepath.Join(root, "entry.json"), raw, 0600); err != nil {
57 t.Fatal(err)
58 }
59 cmd := exec.Command(binary, "-test.run=^TestPlan14PreparedInventoryPrivateView$", "-test.v")
60 cmd.Env = append(os.Environ(), "PLAN14_INVENTORY_VIEW=private")
61 cmd.SysProcAttr = &syscall.SysProcAttr{Cloneflags: unix.CLONE_NEWNS}
62 out, err := cmd.CombinedOutput()
63 if err != nil {
64 t.Fatalf("private child: %v\n%s", err, out)
65 }
66 t.Log(string(out))
67 if err := hostbox.VerifyInventoryIdentity(root, e); err != nil {
68 t.Fatal("root mount changed", err)
69 }
70 return
71 }
72 raw, err := os.ReadFile(filepath.Join(root, "entry.json"))
73 if err != nil {
74 t.Fatal(err)
75 }
76 var e hostbox.StopInventoryEntry
77 if err := json.Unmarshal(raw, &e); err != nil {
78 t.Fatal(err)
79 }
80 if err := unix.Mount("", "/", "", unix.MS_REC|unix.MS_PRIVATE, ""); err != nil {
81 t.Fatal(err)
82 }
83 if err := unix.Mount(root, root, "", unix.MS_BIND|unix.MS_REC, ""); err != nil {
84 t.Fatal(err)
85 }
86 defer unix.Unmount(root, unix.MNT_DETACH)
87 now, err := hostbox.CaptureInventoryIdentity(root, "view")
88 if err != nil {
89 t.Fatal(err)
90 }
91 t.Logf("root identity=%+v; private identity=%+v", e.Identity, now)
92 if err := hostbox.VerifyInventoryIdentity(root, e); err == nil {
93 t.Fatal("root verifier admitted added ancestor")
94 }
95 if err := verifyPreparedStateIdentity(root, e); err != nil {
96 t.Fatal("private view refused", err)
97 }
98 owner := sha256.Sum256([]byte("view.example\x00inc\x001\x00box"))
99 e.Kind, e.ManagedRoot, e.Materialization, e.Ownership = "path", "data", "materialized", hex.EncodeToString(owner[:])
100 inventory := hostbox.StopInventory{Host: "view.example", Incarnation: "inc", InstallationStamp: 1, Entries: []hostbox.StopInventoryEntry{e}}
101 saved, _ := json.Marshal(inventory)
102 a := ClaimRoleAssembly{ManagedRoots: map[string]string{"data": root}}
103 changedState, err := a.prepareStateInventory(ClaimLaunchInputs{DBPath: filepath.Join(view, "db.sqlite")}, &inventory, hostbox.Actor{Box: "box"})
104 after, _ := json.Marshal(inventory)
105 if err != nil || changedState || !reflect.DeepEqual(saved, after) {
106 t.Fatal("private preparation changed root authority", changedState, err)
107 }
108 oldBoot := e
109 oldBoot.Identity.Boot = "old"
110 if err := verifyPreparedStateIdentity(root, oldBoot); err == nil {
111 t.Fatal("private-view exception crossed reboot")
112 }
113 changed := e
114 changed.Device++
115 if err := verifyPreparedStateIdentity(root, changed); err == nil {
116 t.Fatal("changed entry accepted")
117 }
118 if err := unix.Mount(view, view, "", unix.MS_BIND, ""); err != nil {
119 t.Fatal(err)
120 }
121 if err := verifyPreparedStateIdentity(root, e); err == nil {
122 t.Fatal("substituted view accepted")
123 }
124 if err := unix.Unmount(view, 0); err != nil {
125 t.Fatal(err)
126 }
127 if err := unix.Mount(filepath.Join(root, "other"), view, "", unix.MS_BIND, ""); err != nil {
128 t.Fatal(err)
129 }
130 defer unix.Unmount(view, 0)
131 if err := verifyPreparedStateIdentity(root, e); err == nil {
132 t.Fatal("substituted directory accepted")
133 }
134}
135