carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package hostactors
2
3import (
4 "context"
5 "crypto/ed25519"
6 "encoding/json"
7 "strings"
8 "testing"
9 "time"
10
11 "github.com/carlosframework/platform/internal/release"
12)
13
14func TestPlan9BindCensusKeyRequiresPublishedFloorAndActiveEnrollment(t *testing.T) {
15 for _, tc := range []string{"published-active", "unpublished", "preparing", "floor-mismatch", "quarantined", "retired", "fenced", "fence-unreadable", "stale-observed", "forged-observed"} {
16 t.Run(tc, func(t *testing.T) {
17 ctx := context.Background()
18 w, _ := plan9Fixture(t, func(r *Roster) {
19 r.Activations = map[string]Reservation{}
20 switch tc {
21 case "unpublished":
22 r.Publication, r.FloorSHA256 = "", ""
23 case "preparing":
24 r.Publication = "preparing"
25 case "floor-mismatch":
26 r.FloorSHA256 = strings.Repeat("f", 64)
27 case "quarantined":
28 plan9Quarantine(r, "b", "loss-b")
29 case "retired":
30 plan9Quarantine(r, "b", "loss-b")
31 b := r.Boxes["b"]
32 b.State = "retired"
33 r.Boxes["b"] = b
34 }
35 })
36 base := w.d.Store
37 switch tc {
38 case "fenced":
39 w.fence(t, "b", "w", w.now.Add(-time.Minute), "terminated")
40 case "fence-unreadable":
41 w.d.Store = brokenFenceStore{w.d.Store}
42 }
43 before, err := w.d.Read(ctx)
44 if err != nil {
45 t.Fatal(err)
46 }
47 pub, key, err := ed25519.GenerateKey(nil)
48 if err != nil {
49 t.Fatal(err)
50 }
51 binding := CensusKeyBinding{Bucket: "bucket", Box: "b", Enrollment: before.Roster.Boxes["b"].Enrollment, PublicKey: pub}
52 raw, err := json.Marshal(binding)
53 if err != nil {
54 t.Fatal(err)
55 }
56 input := before
57 switch tc {
58 case "stale-observed":
59 // A concurrent writer moved the roster after the caller read it.
60 next := Clone(before.Roster)
61 next.RequestLimitNS = 120000000000
62 if _, err := w.d.Replace(ctx, w.sg, before, next); err != nil {
63 t.Fatal(err)
64 }
65 case "forged-observed":
66 // The caller's copy claims b is active while the signed roster
67 // says otherwise; only the signed roster decides.
68 o, err := w.d.Read(ctx)
69 if err != nil {
70 t.Fatal(err)
71 }
72 r := Clone(o.Roster)
73 plan9Quarantine(&r, "b", "loss-b")
74 signed, err := release.SignRootEnvelope(w.sg, r)
75 if err != nil {
76 t.Fatal(err)
77 }
78 etag, err := w.d.Store.Put(ctx, Key, signed, o.ETag)
79 if err != nil {
80 t.Fatal(err)
81 }
82 input = Observed{Roster: before.Roster, ETag: etag}
83 }
84 got, err := w.d.BindCensusKey(ctx, w.sg, input, binding, ed25519.Sign(key, raw))
85 if tc == "published-active" {
86 if err != nil || !ed25519.PublicKey(got.Roster.Boxes["b"].CensusPublicKey).Equal(pub) {
87 t.Fatalf("bind = %v", err)
88 }
89 return
90 }
91 if err == nil {
92 t.Fatalf("%s: census key bound", tc)
93 }
94 after, readErr := (Directory{Store: base, PublicKey: w.d.PublicKey, Bucket: "bucket"}).Read(ctx)
95 if readErr != nil {
96 t.Fatal(readErr)
97 }
98 if len(after.Roster.Boxes["b"].CensusPublicKey) != 0 {
99 t.Fatalf("%s: census key written despite refusal", tc)
100 }
101 })
102 }
103}
104