carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package hostbox
2
3import (
4 "errors"
5 "path/filepath"
6 "testing"
7
8 "github.com/carlosframework/platform/internal/registry"
9)
10
11func TestPlan9Fix2InventoryNamespace(t *testing.T) {
12 data := t.TempDir()
13 row := registry.Route{Host: "app.example", DBPath: filepath.Join(data, "instances", "app.example", "app.example.db"), ClaimOwnership: registry.ClaimOwnership{ClaimIncarnation: "inc", ClaimStamp: 1, ClaimOwner: "owner", ClaimRowID: "row"}}
14 base := StopInventory{Host: row.Host, Incarnation: row.ClaimIncarnation, InstallationStamp: row.ClaimStamp, Complete: true}
15 for _, tc := range []struct {
16 name, kind, root, path, id string
17 want bool
18 }{
19 {"state parent itself", "path", "data", "instances/app.example", "", true},
20 {"child", "path", "data", "instances/app.example/app.example.db", "", true},
21 {"nested child", "path", "data", "instances/app.example/sub/file", "", true},
22 {"sibling host dir", "path", "data", "instances/other.example", "", false},
23 {"sibling host file", "path", "data", "instances/other.example/other.example.db", "", false},
24 {"prefix sibling child", "path", "data", "instances/app.example-other/app.example.db", "", false},
25 {"not clean dot", "path", "data", "instances/app.example/./x", "", false},
26 {"not clean double slash", "path", "data", "instances/app.example//x", "", false},
27 {"not clean trailing slash", "path", "data", "instances/app.example/x/", "", false},
28 {"traversal back in", "path", "data", "instances/app.example/../app.example/x", "", false},
29 {"traversal out", "path", "data", "../x", "", false},
30 {"absolute", "path", "data", "/instances/app.example/x", "", false},
31 {"absolute data path", "path", "data", filepath.ToSlash(filepath.Join(data, "instances", "app.example", "x")), "", false},
32 {"root registry db", "path", "data", "registry.db", "", false},
33 {"root registry db-wal", "path", "data", "registry.db-wal", "", false},
34 {"root registry db-shm", "path", "data", "registry.db-shm", "", false},
35 {"root registry db-journal", "path", "data", "registry.db-journal", "", false},
36 {"flat db name under nested", "path", "data", "app.example.db", "", false},
37 {"route", "route", "registry", "app.example", "row", true},
38 {"timer", "timer", "registry", "app.example/daily", "timer", true},
39 {"foreign state", "path", "data", "instances/other.example", "", false},
40 {"prefix sibling", "path", "data", "instances/app.example-other", "", false},
41 {"data root", "path", "data", ".", "", false},
42 {"escape", "path", "data", "instances/app.example/../other.example", "", false},
43 {"foreign route", "route", "registry", "other.example", "row", false},
44 {"foreign row id", "route", "registry", "app.example", "other-row", false},
45 {"foreign timer", "timer", "registry", "other.example/daily", "timer", false},
46 {"unit", "path", "units", "carlos-edge.service.d/guard.conf", "", false},
47 {"binary", "path", "opt", "carlos", "", false},
48 {"unknown kind", "unit-state", "data", "instances/app.example", "", false},
49 } {
50 t.Run(tc.name, func(t *testing.T) {
51 in := base
52 in.Entries = []StopInventoryEntry{{Kind: tc.kind, ManagedRoot: tc.root, RelativePath: filepath.FromSlash(tc.path), RowIdentity: tc.id, Ownership: "owner", Materialization: "materialized"}}
53 err := ValidateAgentInventory(in, &row, data)
54 if (err == nil) != tc.want {
55 t.Fatalf("allowed=%v: %v", tc.want, err)
56 }
57 if !tc.want && !errors.Is(err, ErrTypedInventory) {
58 t.Fatalf("rejection is not ErrTypedInventory: %v", err)
59 }
60 })
61 }
62 // A missing row can record the initial route intent, but grants no path authority.
63 base.Entries = []StopInventoryEntry{{Kind: "route", ManagedRoot: "registry", RelativePath: row.Host, RowIdentity: "new-row", Ownership: "owner", Materialization: "intended"}}
64 if err := ValidateAgentInventory(base, nil, data); err != nil {
65 t.Fatal(err)
66 }
67 base.Entries[0] = StopInventoryEntry{Kind: "path", ManagedRoot: "data", RelativePath: "instances/app.example", Ownership: "owner", Materialization: "intended"}
68 if err := ValidateAgentInventory(base, nil, data); err == nil {
69 t.Fatal("missing row granted path authority")
70 }
71 row.DBPath = filepath.Join(data, row.Host+".db")
72 for _, name := range []string{row.Host + ".db", row.Host + ".db-wal", row.Host + ".db-shm", row.Host + ".db-journal"} {
73 base.Entries[0].RelativePath = name
74 if err := ValidateAgentInventory(base, &row, data); err != nil {
75 t.Fatalf("legacy %s: %v", name, err)
76 }
77 }
78 for _, name := range []string{
79 ".", ".hostclaims",
80 row.Host, row.Host + "/" + row.Host + ".db", row.Host + "/child",
81 row.Host + "-other", row.Host + ".db-other", row.Host + ".db/", "./" + row.Host + ".db",
82 "../" + row.Host + ".db", "/" + row.Host + ".db", filepath.ToSlash(filepath.Join(data, row.Host+".db")),
83 "other.example.db", "other.example", "instances/other.example", "instances/other.example/other.example.db",
84 "registry.db", "registry.db-wal", "registry.db-shm", "registry.db-journal",
85 } {
86 base.Entries[0].RelativePath = filepath.FromSlash(name)
87 if err := ValidateAgentInventory(base, &row, data); !errors.Is(err, ErrTypedInventory) {
88 t.Fatalf("legacy accepted foreign %s: %v", name, err)
89 }
90 }
91}
92
93func TestPlan9Fix2InventoryRegistryDBAtRootRefused(t *testing.T) {
94 data := t.TempDir()
95 row := registry.Route{Host: "app.example", ClaimOwnership: registry.ClaimOwnership{ClaimIncarnation: "inc", ClaimStamp: 1, ClaimOwner: "owner", ClaimRowID: "row"}}
96 for _, dbPath := range []string{
97 filepath.Join(data, "app.example.db"),
98 filepath.Join(data, "instances", "app.example", "app.example.db"),
99 } {
100 row.DBPath = dbPath
101 for _, name := range []string{"registry.db", "registry.db-wal", "registry.db-shm", "registry.db-journal"} {
102 in := StopInventory{Host: row.Host, Incarnation: "inc", InstallationStamp: 1, Entries: []StopInventoryEntry{{Kind: "path", ManagedRoot: "data", RelativePath: name, Ownership: "owner", Materialization: "materialized"}}}
103 if err := ValidateAgentInventory(in, &row, data); !errors.Is(err, ErrTypedInventory) {
104 t.Fatalf("db %s accepted %s: %v", dbPath, name, err)
105 }
106 }
107 }
108 row.Host = "registry"
109 row.DBPath = filepath.Join(data, "registry.db")
110 for _, name := range []string{"registry.db", "registry.db-wal", "registry.db-shm", "registry.db-journal"} {
111 in := StopInventory{Host: row.Host, Incarnation: "inc", InstallationStamp: 1, Entries: []StopInventoryEntry{{Kind: "path", ManagedRoot: "data", RelativePath: name, Ownership: "owner", Materialization: "materialized"}}}
112 if err := ValidateAgentInventory(in, &row, data); !errors.Is(err, ErrTypedInventory) {
113 t.Fatalf("colliding host accepted %s: %v", name, err)
114 }
115 }
116}
117
118func TestPlan9Fix2AgentCannotChooseNamespaceThroughRegistryDBPath(t *testing.T) {
119 data := t.TempDir()
120 row := registry.Route{Host: "app.example", ClaimOwnership: registry.ClaimOwnership{ClaimIncarnation: "inc", ClaimStamp: 1, ClaimOwner: "owner", ClaimRowID: "row"}}
121 for _, parent := range []string{"instances/other.example", ".parked/other", ".hostexec", "hostguard", ".hostclaims", ".instances", "registry.db-backup"} {
122 t.Run(parent, func(t *testing.T) {
123 row.DBPath = filepath.Join(data, filepath.FromSlash(parent), "app.example.db")
124 in := StopInventory{Host: row.Host, Incarnation: "inc", InstallationStamp: 1, Entries: []StopInventoryEntry{{Kind: "path", ManagedRoot: "data", RelativePath: filepath.FromSlash(parent), Ownership: "owner", Materialization: "materialized"}}}
125 if err := ValidateAgentInventory(in, &row, data); !errors.Is(err, ErrTypedInventory) {
126 t.Fatalf("agent chose root namespace %s through DBPath: %v", parent, err)
127 }
128 })
129 }
130 row.Host = "hostguard"
131 row.DBPath = filepath.Join(data, "hostguard.db")
132 in := StopInventory{Host: row.Host, Incarnation: "inc", InstallationStamp: 1, Entries: []StopInventoryEntry{{Kind: "path", ManagedRoot: "data", RelativePath: "hostguard", Ownership: "owner", Materialization: "materialized"}}}
133 if err := ValidateAgentInventory(in, &row, data); !errors.Is(err, ErrTypedInventory) {
134 t.Fatalf("flat hostname selected root hostguard namespace: %v", err)
135 }
136 row.Host = "instances"
137 row.DBPath = filepath.Join(data, "instances.db")
138 in.Host = row.Host
139 in.Entries[0].RelativePath = "instances/other.example"
140 if err := ValidateAgentInventory(in, &row, data); !errors.Is(err, ErrTypedInventory) {
141 t.Fatalf("flat hostname selected shared instances namespace: %v", err)
142 }
143}
144