carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux && rootrunner
2
3package host
4
5import (
6 "encoding/json"
7 "os"
8 "path/filepath"
9 "testing"
10
11 "github.com/carlosframework/platform/internal/hostbox"
12 "github.com/carlosframework/platform/internal/rootparticipation"
13 "github.com/carlosframework/platform/internal/rootstate"
14)
15
16func TestPlan14GenerationInventoryCheckedRootReader(t *testing.T) {
17 dir := generationRootRunnerDir(t)
18 censusPath, fencesPath, journalPath := filepath.Join(dir, "census"), filepath.Join(dir, "fences"), filepath.Join(dir, "journals.db")
19 census, err := rootstate.Open(censusPath, true, false)
20 if err != nil {
21 t.Fatal(err)
22 }
23 defer census.Close()
24 fences, err := rootstate.Open(fencesPath, true, false)
25 if err != nil {
26 t.Fatal(err)
27 }
28 fences.Close()
29 c := rootparticipation.Census{Schema: 1, Box: "runner", Enrollment: "runner-en", Migration: 1, Revision: 1, LaunchRevision: 1, Complete: true}
30 raw, err := json.Marshal(c)
31 if err != nil {
32 t.Fatal(err)
33 }
34 if err := census.Write("census.json", raw); err != nil {
35 t.Fatal(err)
36 }
37 journal, err := hostbox.OpenLaunchJournal(journalPath)
38 if err != nil {
39 t.Fatal(err)
40 }
41 service, err := hostbox.NewJournalService(journal)
42 if err != nil {
43 t.Fatal(err)
44 }
45 in := hostbox.StopInventory{Complete: true, Host: "retained.example", Incarnation: "inc", InstallationStamp: 2, Box: c.Box, Enrollment: c.Enrollment, DirectoryRevision: "1"}
46 if err := service.Inventory.WriteStopInventory(t.Context(), in); err != nil {
47 t.Fatal(err)
48 }
49 journal.Close()
50 got, err := generationInventoryAt(t.Context(), censusPath, fencesPath, journalPath)
51 if err != nil || got.Census != c || len(got.Installations) != 0 || len(got.Launches) != 0 || len(got.Payloads) != 1 || got.Payloads[0].Revision != 1 || got.Payloads[0].Inventory.Host != in.Host {
52 t.Fatalf("checked snapshot: %+v %v", got, err)
53 }
54 // An independently discovered payload without its installation cannot be
55 // certified, even though the payload itself has Complete set.
56 if err := generationPayloadBindings(got.Payloads, nil); err == nil {
57 t.Fatal("orphan payload granted completeness")
58 }
59 for _, attack := range []string{"writable-db", "service-db", "symlink-db", "writable-wal", "service-wal", "missing-db", "missing-census"} {
60 t.Run(attack, func(t *testing.T) {
61 switch attack {
62 case "writable-db":
63 if err := os.Chmod(journalPath, 0666); err != nil {
64 t.Fatal(err)
65 }
66 defer os.Chmod(journalPath, 0600)
67 case "service-db":
68 if err := os.Chown(journalPath, 65534, 65534); err != nil {
69 t.Fatal(err)
70 }
71 defer os.Chown(journalPath, 0, 0)
72 case "symlink-db":
73 if err := os.Rename(journalPath, journalPath+".saved"); err != nil {
74 t.Fatal(err)
75 }
76 defer func() { os.Remove(journalPath); os.Rename(journalPath+".saved", journalPath) }()
77 if err := os.Symlink(journalPath+".saved", journalPath); err != nil {
78 t.Fatal(err)
79 }
80 case "writable-wal", "service-wal":
81 wal := journalPath + "-wal"
82 if err := os.WriteFile(wal, []byte("hostile"), 0600); err != nil {
83 t.Fatal(err)
84 }
85 defer os.Remove(wal)
86 if attack == "writable-wal" {
87 if err := os.Chmod(wal, 0666); err != nil {
88 t.Fatal(err)
89 }
90 } else {
91 if err := os.Chown(wal, 65534, 65534); err != nil {
92 t.Fatal(err)
93 }
94 }
95 case "missing-db":
96 if err := os.Rename(journalPath, journalPath+".saved"); err != nil {
97 t.Fatal(err)
98 }
99 defer os.Rename(journalPath+".saved", journalPath)
100 case "missing-census":
101 if err := census.Remove("census.json"); err != nil {
102 t.Fatal(err)
103 }
104 defer census.Write("census.json", raw)
105 }
106 if _, err := generationInventoryAt(t.Context(), censusPath, fencesPath, journalPath); err == nil {
107 t.Fatal("hostile source accepted")
108 }
109 })
110 }
111}
112
113func generationRootRunnerDir(t *testing.T) string {
114 t.Helper()
115 if os.Geteuid() != 0 {
116 t.Fatal("designated runner must execute as root")
117 }
118 dir, err := os.MkdirTemp("/var/lib", "plan14-generation-")
119 if err != nil {
120 t.Fatal(err)
121 }
122 t.Cleanup(func() {
123 if err := os.RemoveAll(dir); err != nil {
124 t.Error(err)
125 }
126 })
127 if err := os.Chmod(dir, 0755); err != nil {
128 t.Fatal(err)
129 }
130 check, err := rootstate.Open(dir, false, true)
131 if err != nil {
132 t.Fatal(err)
133 }
134 check.Close()
135 return dir
136}
137