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 "github.com/carlosframework/platform/internal/boxid"
6 "github.com/carlosframework/platform/internal/release"
7)
8
9type EnrollmentRequest struct {
10 AttemptID string
11 ConfirmationID string
12 Reference string
13 Namespace string
14 Label string
15 Region string
16 Pool string
17 AWSRegion string
18 TofuInstanceID string
19 ExistingReference bool
20 Operator string
21}
22
23// Enroll uses operator-approved configuration, not values in the identity
24// request. H16/H17's worker confirmation producer belongs to region HA spec 4.
25func (d Directory) Enroll(ctx context.Context, sg release.Signer, o Observed, v boxid.Verifier, in EnrollmentRequest, raw []byte) (Observed, error) {
26 return d.enroll(ctx, sg, o, v, in, raw, false)
27}
28func (d Directory) enroll(ctx context.Context, sg release.Signer, o Observed, v boxid.Verifier, in EnrollmentRequest, raw []byte, automatic bool) (Observed, error) {
29 if (!automatic && in.Operator == "") || in.AWSRegion == "" || in.Reference == "" {
30 return Observed{}, ErrRoster
31 }
32 referenced, err := d.Referenced(ctx, in.Reference)
33 if err != nil {
34 return Observed{}, err
35 }
36 in.ExistingReference = in.ExistingReference || referenced
37 if automatic && referenced {
38 return Observed{}, ErrRoster
39 }
40 if in.ExistingReference && in.TofuInstanceID == "" {
41 return Observed{}, ErrRoster
42 }
43 expect := boxid.Expect{Box: in.Reference, AWSRegion: in.AWSRegion, TofuInstanceID: in.TofuInstanceID}
44 for ref, b := range o.Roster.Boxes {
45 expect.Roster = append(expect.Roster, boxid.Enrolled{Box: ref, Cloud: b.Cloud})
46 }
47 evidence, err := v.Enroll(raw, expect)
48 if err != nil {
49 return Observed{}, err
50 }
51 cloud := evidence.Cloud
52 if old, exists := o.Roster.Boxes[in.Reference]; exists {
53 if old.Cloud == cloud && old.EvidenceSHA256 == evidence.RecordSHA256 && old.Namespace == in.Namespace && old.Region == in.Region && old.Pool == in.Pool {
54 return o, nil
55 }
56 return Observed{}, ErrRoster
57 }
58 enrollment, err := d.enrollmentNonce(ctx, in, raw)
59 if err != nil {
60 return Observed{}, err
61 }
62 r := Clone(o.Roster)
63 if automatic {
64 a, ok := r.EnrollmentAttempts[in.Reference]
65 if !ok || a.Consumed || a.AttemptID != in.AttemptID || a.ConfirmationID != in.ConfirmationID {
66 return Observed{}, ErrRoster
67 }
68 a.Consumed = true
69 r.EnrollmentAttempts[in.Reference] = a
70 }
71 box := Box{Enrollment: enrollment, Namespace: in.Namespace, BoxID: in.Reference, Label: in.Label, Region: in.Region, Pool: in.Pool, Cloud: cloud, EvidenceSHA256: evidence.RecordSHA256, State: "active", LossIDs: []string{}}
72 if automatic {
73 // A box the group launched takes the group's role in this same
74 // write (region HA spec 2 §7, A11-1): a replacement for an
75 // excluded group is never placeable, even for a moment.
76 g := r.Regions[in.Region]
77 box.Group, box.Role = g.GroupName, g.Role
78 }
79 r.Boxes[in.Reference] = box
80 return d.Replace(ctx, sg, o, r)
81}
82
83func (d Directory) EnrollAWS(ctx context.Context, sg release.Signer, o Observed, in EnrollmentRequest, raw []byte) (Observed, error) {
84 region, ok := o.Roster.Regions[in.Region]
85 if !ok || region.Account == "" || region.AWSRegion == "" {
86 return Observed{}, ErrRoster
87 }
88 if err := validateScope(o.Roster, Scope{Namespace: in.Namespace, Regions: []string{in.Region}, Pools: []string{in.Pool}}); err != nil {
89 return Observed{}, err
90 }
91 certs, err := boxid.EmbeddedCerts()
92 if err != nil {
93 return Observed{}, err
94 }
95 in.AWSRegion = region.AWSRegion
96 return d.Enroll(ctx, sg, o, boxid.Verifier{Account: region.Account, Certs: certs}, in, raw)
97}
98