carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package hostguard
2
3import (
4 "context"
5 "errors"
6 "github.com/carlosframework/platform/internal/hostclaim"
7 "testing"
8 "time"
9)
10
11func TestPlan14RootRebind(t *testing.T) {
12 for _, failure := range []string{"none", "admission", "revision", "identity", "record", "box", "enrollment", "missing", "before commit", "crash"} {
13 t.Run(failure, func(t *testing.T) {
14 f, target, captured := fenceFixture(t)
15 store := &rootTestStore{dir: t.TempDir()}
16 f.g.Root = NewRootAuthority(store)
17 f.obs.Claim.Holder.Account, f.obs.Claim.Holder.App = "bab", "app"
18 old := RootInstallation{Host: target.Host, Incarnation: captured.Incarnation, Stamp: captured.Stamp, Account: "bab", App: "app", Record: "record", Box: target.Box, Enrollment: target.Enrollment, Migration: 1, InventoryRevision: 3}
19 if err := f.g.EstablishRoot(t.Context(), old, allow); err != nil {
20 t.Fatal(err)
21 }
22 if _, err := f.g.BeginFence(t.Context(), target); err != nil {
23 t.Fatal(err)
24 }
25 at := time.Now().UTC()
26 if err := f.g.CompleteFence(t.Context(), target, []byte("retained receipt"), at, func(context.Context, FenceTarget, []byte, time.Time) error { return nil }); err != nil {
27 t.Fatal(err)
28 }
29 before, _ := store.Read(target.Host + ".json")
30 next := old
31 next.Stamp++
32 next.InventoryRevision = 1
33 f.obs.Claim.Holder.Stamp = next.Stamp
34 f.obs.Claim.Holder.Session = next.Stamp
35 revision := old.InventoryRevision
36 if failure == "revision" {
37 revision++
38 }
39 if failure == "identity" {
40 next.Account = "other"
41 }
42 if failure == "record" {
43 next.Record = "other"
44 }
45 if failure == "box" {
46 next.Box = "other"
47 }
48 if failure == "enrollment" {
49 next.Enrollment = "other"
50 }
51 if failure == "missing" {
52 captured.Incarnation = "missing"
53 }
54 calls, effects := 0, 0
55 crash := errors.New("crash")
56 check := func(*hostclaim.Claim) error {
57 calls++
58 if failure == "admission" || failure == "before commit" && calls == 2 {
59 return ErrFenced
60 }
61 return nil
62 }
63 commit := func() error {
64 if failure == "crash" {
65 return crash
66 }
67 effects++
68 return nil
69 }
70 err := f.g.RebindRootInventory(t.Context(), captured, revision, next, []byte("intent"), check, commit)
71 if failure == "crash" {
72 if !errors.Is(err, crash) {
73 t.Fatal(err)
74 }
75 if _, err := f.g.Root.View(t.Context(), target.Host, captured); !errors.Is(err, ErrFenced) {
76 t.Fatal("pending allowed", err)
77 }
78 f.g.Root = NewRootAuthority(store)
79 err = f.g.RebindRootInventory(t.Context(), captured, revision, next, []byte("intent"), allow, func() error { effects++; return nil })
80 }
81 if failure != "none" && failure != "crash" {
82 if err == nil || effects != 0 {
83 t.Fatal("refusal bypass", err, effects)
84 }
85 if failure != "before commit" {
86 after, _ := store.Read(target.Host + ".json")
87 if string(after) != string(before) {
88 t.Fatal("refusal changed root")
89 }
90 }
91 return
92 }
93 if err != nil || effects != 1 {
94 t.Fatal(err, effects)
95 }
96 if err = f.g.RebindRootInventory(context.Background(), captured, revision, next, []byte("intent"), allow, func() error { t.Fatal("replay effect"); return nil }); err != nil {
97 t.Fatal(err)
98 }
99 view, err := f.g.Root.View(t.Context(), target.Host, Captured{Incarnation: next.Incarnation, Stamp: next.Stamp})
100 if err != nil || view.Installation != next || view.Pending == nil || *view.Pending != target || len(view.Retired) != 1 || view.Retired[0] != captured || len(view.Receipts) != 1 || view.Receipts[0].Target != target || string(view.Receipts[0].Bytes) != "retained receipt" || !view.Receipts[0].EvidenceAt.Equal(at) {
101 t.Fatal("lost denials", view, err)
102 }
103 })
104 }
105}
106