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 "errors"
5 "fmt"
6 "strings"
7
8 "github.com/carlosframework/platform/internal/registry"
9)
10
11// FleetIdentity is a fleet box's resolved identity: which fleet it belongs
12// to, and which of that fleet's boxes IT is.
13//
14// Label is the operator-chosen fleet_boxes.label — the channel identity the
15// edge actually dials ("<Fleet>/<Label>", edge.fleetChannelFor) — and
16// deliberately NEVER status.Label(machineID). That hashed value is the
17// PUBLIC status page's opaque pseudonym, chosen specifically so a customer's
18// machine id can never be recovered from a feed anyone can view; a fleet
19// box's real identity is a name an operator picked when they ran
20// `carlos fleets add-box`, and nothing else on the platform (the edge's
21// tunnel hub, the registry's fleet_boxes table, a fleet binding object) ever
22// refers to a box any other way. Using the hashed pseudonym here would
23// publish bindings the edge could never dial back.
24type FleetIdentity struct {
25 Fleet string
26 Label string
27}
28
29// errNotFleetBox is resolveFleetIdentity's sentinel for "this agent isn't a
30// fleet box at all" (CARLOS_FLEET unset) — distinct from an invalid
31// identity, which callers must treat very differently: the former is every
32// platform box today (silent, expected), the latter is a fleet box
33// misconfigured badly enough that it must refuse to arm its fleet
34// machinery rather than run under a label nothing else in the system would
35// recognize.
36var errNotFleetBox = errors.New("host: CARLOS_FLEET is not set")
37
38// resolveFleetIdentity reads CARLOS_FLEET and CARLOS_FLEET_BOX (falling
39// back to CARLOS_TUNNEL_NAME, since a fleet box's tunnel name already has
40// the "<fleet>/<label>" shape tunnel_client.go dials with) and validates
41// both halves with registry.ValidTunnelName — the exact grammar
42// fleet_boxes.label, Route.Tunnel, and a fleet name in Route.Region
43// ("fleet/<name>", registry.FleetPlacement) all already share, so a value
44// this accepts is guaranteed usable everywhere else in the system that
45// stores or parses one.
46//
47// Returns (_, errNotFleetBox) when CARLOS_FLEET is unset — the ordinary,
48// silent, every-platform-box-today case; callers must not log anything for
49// it. Any OTHER non-nil error names a genuine misconfiguration (an invalid
50// fleet name, or a box label that isn't set and can't be derived/doesn't
51// validate) — callers must refuse to arm whatever fleet-box behavior they
52// gate on this, loudly, rather than fall back to guessing an identity.
53func resolveFleetIdentity(getenv func(string) string) (FleetIdentity, error) {
54 fleet := strings.TrimSpace(getenv("CARLOS_FLEET"))
55 if fleet == "" {
56 return FleetIdentity{}, errNotFleetBox
57 }
58 if !registry.ValidTunnelName(fleet) {
59 return FleetIdentity{}, fmt.Errorf("CARLOS_FLEET=%q is not a valid fleet name", fleet)
60 }
61
62 label := strings.TrimSpace(getenv("CARLOS_FLEET_BOX"))
63 if label == "" {
64 // A fleet box's CARLOS_TUNNEL_NAME is minted as "<fleet>/<label>"
65 // (plan doc: "FleetChannelAuth: channel name '<fleet>/<label>'"), so
66 // stripping this fleet's own prefix recovers the label without a
67 // second env var in the common case. CutPrefix — not TrimPrefix — is
68 // load-bearing here (fix round 2, Opus re-review): TrimPrefix
69 // no-ops when CARLOS_TUNNEL_NAME doesn't actually carry this exact
70 // prefix, silently leaving the WHOLE tunnel name behind as the
71 // "label" — and a bare legacy tunnel name (CARLOS_TUNNEL_NAME=
72 // "pi-box", no "/" at all — the live shape in today's runbook)
73 // still passes ValidTunnelName, so that silent fallback would have
74 // published a Box the edge could never dial: fleetChannelFor's rule
75 // 1 checks hub.State(fleet+"/"+boxLabel), but the hub only ever
76 // knows this box's channel by its RAW CARLOS_TUNNEL_NAME — "pi-box",
77 // not "pi/pi-box". A fleet box's channel MUST be "<fleet>/<label>"
78 // for FleetChannelAuth to key it at all, so a tunnel name missing
79 // that exact prefix is refused here rather than silently accepted.
80 tunnelName := strings.TrimSpace(getenv("CARLOS_TUNNEL_NAME"))
81 derived, ok := strings.CutPrefix(tunnelName, fleet+"/")
82 if !ok {
83 return FleetIdentity{}, fmt.Errorf(
84 "fleet box label could not be derived from CARLOS_TUNNEL_NAME=%q (want the %q prefix) — set CARLOS_FLEET_BOX explicitly",
85 tunnelName, fleet+"/")
86 }
87 label = derived
88 }
89 if label == "" || !registry.ValidTunnelName(label) {
90 return FleetIdentity{}, fmt.Errorf(
91 "fleet box label %q is invalid — set CARLOS_FLEET_BOX, or CARLOS_TUNNEL_NAME=%s/<label>",
92 label, fleet)
93 }
94 return FleetIdentity{Fleet: fleet, Label: label}, nil
95}
96