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)
7
8type MigrationDeny struct {
9 Incarnation string
10 Stamp, Session uint64
11}
12
13func migrationDenied(denies []MigrationDeny, c Captured, session uint64) bool {
14 for _, d := range denies {
15 if d.Incarnation == c.Incarnation && c.Stamp <= d.Stamp && session <= d.Session {
16 return true
17 }
18 }
19 return false
20}
21
22// RetainMigrationDeny adds only refusal authority. The offline root collector
23// supplies the independently observed installation; this method grants no work.
24func (a *RootAuthority) RetainMigrationDeny(ctx context.Context, in RootInstallation, session uint64) error {
25 if a == nil || a.store == nil || validateFileHost(in.Host) != nil || in.Incarnation == "" || in.Stamp == 0 || in.Migration == 0 || in.Account == "" || in.App == "" || in.Record == "" || in.Box == "" || in.Enrollment == "" || session == 0 {
26 return ErrInvalidInput
27 }
28 unlock, err := a.store.Lock(ctx, in.Host+".lock")
29 if err != nil {
30 return err
31 }
32 defer unlock()
33 r, err := a.read(in.Host)
34 if errors.Is(err, ErrNoRecord) {
35 r = record{V: 1, Host: in.Host, Incarnation: in.Incarnation, ActiveStamp: in.Stamp, root: true, installation: in}
36 } else if err != nil {
37 return err
38 }
39 if r.installation.Host != in.Host || r.installation.Incarnation != in.Incarnation || r.installation.Stamp != in.Stamp || r.installation.Account != in.Account || r.installation.App != in.App || r.installation.Record != in.Record || r.installation.Box != in.Box || r.installation.Enrollment != in.Enrollment || r.installation.Migration != in.Migration {
40 return ErrRecordIncarnation
41 }
42 for i, d := range r.migrationDenies {
43 if d.Incarnation == in.Incarnation && d.Stamp == in.Stamp {
44 if session > r.migrationDenies[i].Session {
45 r.migrationDenies[i].Session = session
46 }
47 return a.write(r)
48 }
49 }
50 r.migrationDenies = append(r.migrationDenies, MigrationDeny{Incarnation: in.Incarnation, Stamp: in.Stamp, Session: session})
51 return a.write(r)
52}
53
54// CompleteMigrationInventory binds the checked inventory only after root has
55// retained its own completed stop receipt for this denied session.
56func (a *RootAuthority) CompleteMigrationInventory(ctx context.Context, target FenceTarget, revision uint64, artifacts InstallationArtifacts, previous ...uint64) error {
57 if target.validate(target.Host) != nil || revision == 0 || artifacts.Schema != 1 {
58 return ErrInvalidInput
59 }
60 unlock, err := a.store.Lock(ctx, target.Host+".lock")
61 if err != nil {
62 return err
63 }
64 defer unlock()
65 r, err := a.read(target.Host)
66 if err != nil {
67 return err
68 }
69 captured := Captured{Incarnation: target.Incarnation, Stamp: target.Stamp}
70 if r.Incarnation != target.Incarnation || r.ActiveStamp != target.Stamp || !migrationDenied(r.migrationDenies, captured, target.Session) {
71 return ErrFenceTarget
72 }
73 completed := false
74 for _, receipt := range r.FenceJournal {
75 if receipt.Target == target {
76 completed = true
77 }
78 }
79 prior := revision
80 if len(previous) > 1 || len(previous) == 1 && (previous[0] == 0 || previous[0] == ^uint64(0) || previous[0]+1 != revision) {
81 return ErrInvalidInput
82 }
83 if len(previous) == 1 {
84 prior = previous[0]
85 }
86 if !completed || r.installation.InventoryRevision != 0 && r.installation.InventoryRevision != revision && r.installation.InventoryRevision != prior {
87 return ErrFenceTarget
88 }
89 r.installation.InventoryRevision = revision
90 r.installation.Artifacts = artifacts
91 return a.write(r)
92}
93
94func migrationAdmissionDenied(denies []MigrationDeny, receipts []FenceReceipt, c Captured, session uint64) bool {
95 if migrationDenied(denies, c, session) {
96 return true
97 }
98 for _, d := range denies {
99 if d.Incarnation != c.Incarnation || d.Stamp != c.Stamp {
100 continue
101 }
102 stopped := false
103 for _, r := range receipts {
104 if r.Target.Incarnation == d.Incarnation && r.Target.Stamp == d.Stamp && r.Target.Session == d.Session {
105 stopped = true
106 }
107 }
108 if !stopped {
109 return true
110 }
111 }
112 return false
113}
114