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 "crypto/ed25519"
5 "crypto/sha256"
6 "encoding/hex"
7 "encoding/json"
8 "github.com/carlosframework/platform/internal/hostactors"
9 "github.com/carlosframework/platform/internal/hostclaim"
10 "github.com/carlosframework/platform/internal/hostevidence"
11 "github.com/carlosframework/platform/internal/release"
12 "strings"
13 "testing"
14 "time"
15)
16
17func TestPlan13RecoveryHomeReceipt(t *testing.T) {
18 t.Parallel()
19 for _, bad := range []string{"", "session", "stamp", "enrollment", "signature", "operation", "region", "digest", "unbound", "roster-name"} {
20 t.Run(bad, func(t *testing.T) {
21 f, o, h := plan12Handover(t, hostclaim.KindRestoring, "stop")
22 o.Claim.Op.Intent["to"] = "@home"
23 o.Claim.Op.Intent["home_region"] = "uk"
24 if bad == "unbound" {
25 delete(o.Claim.Op.Intent, "home_region")
26 }
27 key := ed25519.NewKeyFromSeed([]byte(strings.Repeat("b", 32)))
28 en := strings.Repeat("a", 32)
29 d := hostactors.Directory{Store: f.claims, PublicKey: f.signer.Public().(ed25519.PublicKey), Bucket: "bucket"}
30 roster := hostactors.Roster{HomeRegion: "uk", V: 1, Revision: 1, DeploymentBucket: "bucket", Boxes: map[string]hostactors.Box{"box-2": {Enrollment: en, BoxID: "box-2", Label: "box-2", Namespace: "platform", Region: "uk", Pool: "default", State: "active", Cloud: hostactors.Cloud{Provider: "aws", Account: "123", Region: "eu-west-2", InstanceID: "i-target"}, EvidenceSHA256: strings.Repeat("d", 64), CensusPublicKey: key.Public().(ed25519.PublicKey)}}, Consoles: map[string]hostactors.Console{}, Holds: map[string]hostactors.Reservation{}, Activations: map[string]hostactors.Reservation{}}
31 if bad == "roster-name" {
32 b := roster.Boxes["box-2"]
33 b.Region = "ie"
34 roster.Boxes["box-2"] = b
35 }
36 wire, _ := release.SignRootEnvelope(release.RootSigner(f.signer), roster)
37 if _, err := f.claims.Put(t.Context(), hostactors.Key, wire, ""); err != nil {
38 t.Fatal(err)
39 }
40 r := StopReceipt{V: 1, ID: "stop", Kind: "stopped", Host: o.Host, Incarnation: o.Claim.Holder.Incarnation, InstallationStamp: 2, WriterSession: 2, OperationID: "m1", Phase: "releasing", ObligationID: "writer-session-2", Box: "box-2", Region: "uk", Enrollment: en, EvidenceAt: time.Now(), RequestLimitNS: int64(2 * time.Minute), ClaimGen: 1, FenceID: "fence", InventorySHA256: strings.Repeat("e", 64), LocalJournalSHA256: strings.Repeat("f", 64), ProducerDrainDigest: strings.Repeat("a", 64), CgroupIdentities: []string{"root-role"}}
41 switch bad {
42 case "session":
43 r.WriterSession++
44 case "stamp":
45 r.InstallationStamp++
46 case "enrollment":
47 r.Enrollment = strings.Repeat("e", 32)
48 case "operation":
49 r.OperationID = "other"
50 case "region":
51 r.Region = "ie"
52 }
53 body, _ := json.Marshal(r)
54 receiptKey := stopEvidenceKey(o.Host, "m1", "box-2", "stop")
55 sum := sha256.Sum256(body)
56 signer := key
57 if bad == "signature" {
58 signer = f.signer
59 }
60 if err := hostevidence.Publish(t.Context(), f.claims, signer, receiptKey, body); err != nil {
61 t.Fatal(err)
62 }
63 h.Directory = d
64 o.Claim.Op.Journal["target_stop_receipt"] = receiptKey
65 o.Claim.Op.Journal["target_stop_sha256"] = hex.EncodeToString(sum[:])
66 o.Claim.Op.Journal[hostclaim.JournalTargetStamp] = "2"
67 // Remove the unsigned report path: the receipt alone must suffice.
68 delete(o.Claim.Op.Journal, hostclaim.JournalEvidenceTarget)
69 if bad == "digest" {
70 o.Claim.Op.Journal["target_stop_sha256"] = strings.Repeat("0", 64)
71 }
72 err := h.recoveryEvidence(t.Context(), o)
73 stored, _, readErr := f.claims.Get(t.Context(), receiptKey)
74 if readErr != nil || string(stored) != string(body) {
75 t.Fatal("receipt bytes changed")
76 }
77 if (err == nil) != (bad == "") {
78 t.Fatal(bad, err)
79 }
80 })
81 }
82}
83
84func TestPlan13HomeRecoveryFenceBinding(t *testing.T) {
85 t.Parallel()
86 for _, home := range []string{"uk", "", "ie"} {
87 _, o, h := plan12Handover(t, hostclaim.KindRestoring, "fence")
88 o.Claim.Op.Intent["to"] = "@home"
89 o.Claim.Op.Intent["home_region"] = home
90 h.FenceAuthority = plan12FenceAuthority{home: "uk"}
91 err := h.recoveryEvidence(t.Context(), o)
92 if (err == nil) != (home == "uk") {
93 t.Fatal(home, err)
94 }
95 }
96}
97