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 "os"
5 "path/filepath"
6 "testing"
7
8 "github.com/carlosframework/platform/internal/hostclaim"
9 "github.com/carlosframework/platform/internal/hostguard"
10)
11
12func TestPlan14RootLaunchRefusesReplacedAgentFence(t *testing.T) {
13 for _, attack := range []string{"honest", "delete", "rename", "replace lock", "forge", "receipt replay"} {
14 t.Run(attack, func(t *testing.T) {
15 f := newLaunchFixture(t, servingOp())
16 f.claims.set(func(c *hostclaim.Claim) {
17 c.Holder.Account = "bab"
18 c.Holder.App = "app"
19 c.Holder.Admissions = []hostclaim.AdmissionRecord{{Box: f.target.Box, Region: f.target.Region, Session: f.target.Session, Generation: c.Holder.Generation}}
20 })
21 guard := f.root.Guard
22 guard.Root = hostguard.NewRootAuthority(&rollbackDisk{dir: t.TempDir()})
23 in := hostguard.RootInstallation{Host: f.target.Host, Account: "bab", App: "app", Record: "record", Incarnation: f.target.Incarnation, Stamp: f.target.Stamp, Box: f.target.Box, Enrollment: f.target.Enrollment, Migration: 1}
24 if err := guard.EstablishRoot(t.Context(), in, func(*hostclaim.Claim) error { return nil }); err != nil {
25 t.Fatal(err)
26 }
27 f.root.Guard = guard
28 if attack == "honest" {
29 if _, err := f.root.Serve(t.Context(), f.peer, f.req); err != nil {
30 t.Fatal(err)
31 }
32 if n, _ := f.units.counts(); n != 1 {
33 t.Fatalf("honest launch count: %d", n)
34 }
35 return
36 }
37 if attack == "receipt replay" {
38 if _, err := f.root.Serve(t.Context(), f.peer, f.req); err != nil {
39 t.Fatal(err)
40 }
41 }
42 target := f.target
43 target.FenceID = "root-fence"
44 if _, err := guard.BeginFence(t.Context(), target); err != nil {
45 t.Fatal(err)
46 }
47 path := filepath.Join(guard.DataDir, "hostguard", target.Host+".json")
48 switch attack {
49 case "delete":
50 if err := os.Remove(path); err != nil {
51 t.Fatal(err)
52 }
53 case "rename":
54 if err := os.Rename(filepath.Dir(path), filepath.Dir(path)+".old"); err != nil {
55 t.Fatal(err)
56 }
57 case "replace lock":
58 if err := os.Rename(guard.LockDir, guard.LockDir+".old"); err != nil {
59 t.Fatal(err)
60 }
61 if err := os.Mkdir(guard.LockDir, 0700); err != nil {
62 t.Fatal(err)
63 }
64 case "forge":
65 if err := os.WriteFile(path, []byte(`{"v":1,"host":"shop.example","incarnation":"inc-1","active_stamp":11}`), 0600); err != nil {
66 t.Fatal(err)
67 }
68 }
69 before, _ := f.units.counts()
70 if _, err := f.root.Serve(t.Context(), f.peer, f.req); err == nil {
71 t.Fatal("root launch bypassed fence")
72 }
73 if n, _ := f.units.counts(); n != before {
74 t.Fatal("fenced launch started a unit")
75 }
76 pending, err := guard.PendingFences(t.Context())
77 if err != nil || len(pending) != 1 || pending[0] != target {
78 t.Fatalf("lost root recovery target: %+v %v", pending, err)
79 }
80 })
81 }
82}
83