carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1// Package boxid is the evidence a platform box presents to be enrolled in
2// the roster (region HA spec 1 §5.1, ruling H11): the box's own AWS-signed
3// instance identity document, published once under its box reference. The
4// record grants nothing by itself. Enrollment verifies it (Verifier.Enroll)
5// and copies the proven account, region and instance id into the roster
6// entry's cloud field; from then on the roster, never this record, is what
7// binds a reference to an instance.
8package boxid
9
10import (
11 "bytes"
12 "context"
13 "encoding/json"
14 "errors"
15 "fmt"
16
17 "github.com/carlosframework/platform/internal/controlname"
18 "github.com/carlosframework/platform/internal/release"
19)
20
21const Prefix = "control/boxes/"
22
23// ValidBox reports whether ref can be a box reference: one DNS label, so
24// it can never contain "." or "/" and no two references share a key.
25func ValidBox(ref string) bool { return controlname.ValidLabel(ref) }
26
27// Key is where a box's record lives. Callers check ValidBox first.
28func Key(box string) string { return Prefix + box + ".json" }
29
30type Record struct {
31 V int `json:"v"`
32 Box string `json:"box"`
33 IdentityDocument string `json:"identity_document"`
34 IdentitySignature string `json:"identity_signature"`
35 WrittenAt string `json:"written_at"`
36}
37
38// Publish writes a box's record create-only. Writing the same bytes again
39// succeeds; a different record for the same box is ErrCASConflict, because
40// a record is never replaced.
41func Publish(ctx context.Context, s release.Store, rec Record) error {
42 if !ValidBox(rec.Box) {
43 return fmt.Errorf("boxid: %q is not a box reference", rec.Box)
44 }
45 body, err := json.Marshal(rec)
46 if err != nil {
47 return fmt.Errorf("boxid: marshal: %w", err)
48 }
49 _, err = s.Put(ctx, Key(rec.Box), body, "")
50 if !errors.Is(err, release.ErrCASConflict) {
51 return err
52 }
53 cur, _, gerr := s.Get(ctx, Key(rec.Box))
54 if gerr != nil {
55 return fmt.Errorf("boxid: %s exists and cannot be read: %w", rec.Box, gerr)
56 }
57 if bytes.Equal(cur, body) {
58 return nil
59 }
60 return fmt.Errorf("boxid: %s already has a different record: %w", rec.Box, release.ErrCASConflict)
61}
62
63// Load returns the exact bytes of a box's record, which is what enrollment
64// verifies and hashes. A missing record is os.ErrNotExist-wrapped.
65func Load(ctx context.Context, s release.Store, box string) ([]byte, error) {
66 if !ValidBox(box) {
67 return nil, fmt.Errorf("%w: %q is not a box reference", ErrUnverified, box)
68 }
69 raw, _, err := s.Get(ctx, Key(box))
70 return raw, err
71}
72