| 1 | package hostguard |
| 2 | |
| 3 | import ( |
| 4 | "errors" |
| 5 | "github.com/carlosframework/platform/internal/hostclaim" |
| 6 | "testing" |
| 7 | ) |
| 8 | |
| 9 | func TestPlan14RootInventorySettlement(t *testing.T) { |
| 10 | for _, change := range []string{"exact", "intent", "stamp", "revision", "callback"} { |
| 11 | t.Run(change, func(t *testing.T) { |
| 12 | f, target, captured := fenceFixture(t) |
| 13 | f.obs.Claim.Holder.Account, f.obs.Claim.Holder.App = "bab", "console" |
| 14 | f.g.Root = NewRootAuthority(&rootTestStore{dir: t.TempDir()}) |
| 15 | in := RootInstallation{Host: target.Host, Incarnation: captured.Incarnation, Stamp: captured.Stamp, Account: "bab", App: "console", Record: "record", Box: target.Box, Enrollment: target.Enrollment, Migration: 1, InventoryRevision: 1} |
| 16 | if err := f.g.EstablishRoot(t.Context(), in, allow); err != nil { |
| 17 | t.Fatal(err) |
| 18 | } |
| 19 | in.InventoryRevision++ |
| 20 | if change == "revision" { |
| 21 | in.InventoryRevision++ |
| 22 | } |
| 23 | fault := errors.New("interrupted") |
| 24 | if err := f.g.CommitRootInventory(t.Context(), in, []byte("exact"), allow, nil, func(RootInstallation) error { return fault }); !errors.Is(err, fault) { |
| 25 | t.Fatal(err) |
| 26 | } |
| 27 | // No fresh claim is available. Local settlement cannot clear a denial. |
| 28 | f.obs.Claim = &hostclaim.Claim{} |
| 29 | intent := []byte("exact") |
| 30 | if change == "intent" { |
| 31 | intent = []byte("forged") |
| 32 | } |
| 33 | r, err := f.g.Root.read(target.Host) |
| 34 | if err != nil { |
| 35 | t.Fatal(err) |
| 36 | } |
| 37 | r.quarantined = true |
| 38 | if change == "stamp" { |
| 39 | r.ActiveStamp++ |
| 40 | } |
| 41 | if err := f.g.Root.write(r); err != nil { |
| 42 | t.Fatal(err) |
| 43 | } |
| 44 | calls := 0 |
| 45 | err = f.g.SettleRootInventory(t.Context(), target.Host, intent, func(got RootInstallation) error { |
| 46 | calls++ |
| 47 | if got != in || change == "callback" { |
| 48 | return fault |
| 49 | } |
| 50 | return nil |
| 51 | }) |
| 52 | if (err == nil) != (change == "exact") { |
| 53 | t.Fatal(change, err) |
| 54 | } |
| 55 | if (change == "intent" || change == "revision" || change == "stamp") && calls != 0 { |
| 56 | t.Fatal("unvalidated intent reached effect callback") |
| 57 | } |
| 58 | r, err = f.g.Root.read(target.Host) |
| 59 | if err != nil || !r.quarantined { |
| 60 | t.Fatal("settlement cleared denial", err) |
| 61 | } |
| 62 | pending, e := f.g.Root.PendingInstallations() |
| 63 | if e != nil { |
| 64 | t.Fatal(e) |
| 65 | } |
| 66 | if (len(pending) == 0) != (change == "exact") { |
| 67 | t.Fatal("pending intention changed", pending) |
| 68 | } |
| 69 | }) |
| 70 | } |
| 71 | } |
| 72 | |