package release import ( "bytes" "encoding/base64" "encoding/json" "errors" "math" "reflect" "strings" "testing" "time" "github.com/carlosframework/platform/internal/maintenanceguard" ) func workerTestRef(b byte) maintenanceguard.Reference { return maintenanceguard.Reference{ID: base64.RawURLEncoding.EncodeToString(bytes.Repeat([]byte{b}, 32)), Digest: strings.Repeat("ab", 32)} } func workerTestHead() WorkerHead { return WorkerHead{Schema: 1, Kind: "maintenance-worker", Deployment: "https://console.example.com", Account: "bds", Box: "annie-welding", PhysicalIdentity: strings.Repeat("cd", 32), Generation: 1, Revision: 1, TokenHash: strings.Repeat("ef", 32), Status: "active", Placement: "eu", Candidate: workerTestRef(1), Open: []maintenanceguard.Reference{workerTestRef(2)}} } func workerTestAssignment() WorkerAssignmentState { return WorkerAssignmentState{Schema: 1, Kind: "maintenance-assignment", Identity: WorkerAssignmentIdentity{Assignment: workerTestRef(2), Deployment: "https://console.example.com", Box: "annie-welding", Generation: 1, Account: "bds", App: "home", Host: "home.example.com", Operation: workerTestRef(3).ID, Request: workerTestRef(4).ID, Attempt: workerTestRef(5).ID}, Revision: 1, Expires: 2000000000} } func TestWorkerControlRoundTripAndTypeSeparation(t *testing.T) { priv, pub := testKeys(t) head := workerTestHead() head.Generation = math.MaxInt64 head.Revision = math.MaxInt64 wire, err := SignWorkerHead(RootSigner(priv), head) if err != nil { t.Fatal(err) } got, err := VerifyWorkerHead(pub, wire) if err != nil || !reflect.DeepEqual(got, head) { t.Fatalf("head round trip: %v", err) } if _, err = VerifyWorkerAssignment(pub, wire); !errors.Is(err, ErrWorkerControl) { t.Fatal("head accepted as assignment") } state := workerTestAssignment() refs := []*maintenanceguard.Reference{&head.Candidate, &head.Open[0]} state.Preflight = refs[0] state.Execution = refs[1] state.Disabled = true wire, err = SignWorkerAssignment(RootSigner(priv), state) if err != nil { t.Fatal(err) } gotState, err := VerifyWorkerAssignment(pub, wire) if err != nil || !reflect.DeepEqual(gotState, state) { t.Fatalf("assignment round trip: %v", err) } if _, err = VerifyWorkerHead(pub, wire); !errors.Is(err, ErrWorkerControl) { t.Fatal("assignment accepted as head") } _, otherPub := testKeys(t) if _, err = VerifyWorkerAssignment(otherPub, wire); !errors.Is(err, ErrWorkerControl) { t.Fatal("wrong root accepted") } if _, err = VerifyWorkerAssignment(nil, wire); !errors.Is(err, ErrWorkerControl) { t.Fatal("missing root accepted") } wire[len(wire)/2] ^= 1 if _, err = VerifyWorkerAssignment(pub, wire); !errors.Is(err, ErrWorkerControl) { t.Fatal("tampered wire accepted") } } func TestWorkerControlRefusesNonRootSigner(t *testing.T) { _, _, scoped := scopedFixture(t, []string{"canary"}, time.Hour) for _, sg := range []Signer{{}, scoped} { if _, err := SignWorkerHead(sg, workerTestHead()); !errors.Is(err, ErrWorkerControl) { t.Fatal("head signed without root") } if _, err := SignWorkerAssignment(sg, workerTestAssignment()); !errors.Is(err, ErrWorkerControl) { t.Fatal("assignment signed without root") } } } func TestWorkerControlRefusesSignedMalformedPayload(t *testing.T) { priv, pub := testKeys(t) headRaw, _ := json.Marshal(workerTestHead()) stateRaw, _ := json.Marshal(workerTestAssignment()) for name, mutate := range map[string]func(string) string{ "duplicate": func(s string) string { return strings.Replace(s, `"schema":1`, `"schema":1,"schema":1`, 1) }, "alias": func(s string) string { return strings.Replace(s, `"schema":1`, `"Schema":1`, 1) }, "unknown": func(s string) string { return strings.Replace(s, `"schema":1`, `"schema":1,"extension":true`, 1) }, "float": func(s string) string { return strings.Replace(s, `"schema":1`, `"schema":1.0`, 1) }, "overflow": func(s string) string { return strings.Replace(s, `"revision":1`, `"revision":9223372036854775808`, 1) }, "trailing": func(s string) string { return s + ` {}` }, "escaped-alias": func(s string) string { return strings.Replace(s, `"schema":1`, `"\u0073chema":1`, 1) }, "invalid-utf8": func(s string) string { return strings.Replace(s, "console", string([]byte{255}), 1) }, "surrogate": func(s string) string { return strings.Replace(s, "console", `\ud800`, 1) }, } { t.Run(name, func(t *testing.T) { for _, raw := range [][]byte{headRaw, stateRaw} { wire, err := signRootPayload(RootSigner(priv), []byte(mutate(string(raw)))) if err != nil { t.Fatal(err) } if _, err = VerifyWorkerHead(pub, wire); !errors.Is(err, ErrWorkerControl) { t.Fatal("malformed head accepted") } if _, err = VerifyWorkerAssignment(pub, wire); !errors.Is(err, ErrWorkerControl) { t.Fatal("malformed assignment accepted") } } }) } for _, raw := range []string{ strings.Replace(string(stateRaw), `"disabled":false,`, "", 1), strings.TrimSuffix(string(stateRaw), "}") + `,"execution":null}`, strings.Replace(string(headRaw), `"open":[`+mustWorkerJSON(t, workerTestRef(2))+`]`, `"open":null`, 1), } { wire, err := signRootPayload(RootSigner(priv), []byte(raw)) if err != nil { t.Fatal(err) } if _, err = VerifyWorkerHead(pub, wire); !errors.Is(err, ErrWorkerControl) { t.Fatal("missing/null field accepted as head") } if _, err = VerifyWorkerAssignment(pub, wire); !errors.Is(err, ErrWorkerControl) { t.Fatal("missing/null field accepted as assignment") } } } func mustWorkerJSON(t *testing.T, v any) string { t.Helper() raw, err := json.Marshal(v) if err != nil { t.Fatal(err) } return string(raw) } func TestWorkerControlRefusesInvalidHeadScope(t *testing.T) { priv, pub := testKeys(t) for name, change := range map[string]func(*WorkerHead){ "http": func(h *WorkerHead) { h.Deployment = "http://console.example.com" }, "path": func(h *WorkerHead) { h.Deployment += "/" }, "user": func(h *WorkerHead) { h.Deployment = "https://owner@console.example.com" }, "box-path": func(h *WorkerHead) { h.Box = "../other" }, "zero-generation": func(h *WorkerHead) { h.Generation = 0 }, "zero-revision": func(h *WorkerHead) { h.Revision = 0 }, "token": func(h *WorkerHead) { h.TokenHash = "bad" }, "physical-identity": func(h *WorkerHead) { h.PhysicalIdentity = "bad" }, "unknown-state": func(h *WorkerHead) { h.Status = "enabled" }, "duplicate-assignment": func(h *WorkerHead) { h.Open = append(h.Open, h.Open[0]) }, "overflow-open": func(h *WorkerHead) { for i := byte(3); i < 11; i++ { h.Open = append(h.Open, workerTestRef(i)) } }, "detached-open": func(h *WorkerHead) { h.Status = "detached" }, "null-open": func(h *WorkerHead) { h.Open = nil }, } { t.Run(name, func(t *testing.T) { h := workerTestHead() change(&h) if _, err := SignWorkerHead(RootSigner(priv), h); !errors.Is(err, ErrWorkerControl) { t.Fatal("invalid head signed") } wire, err := signRootPayload(RootSigner(priv), []byte(mustWorkerJSON(t, h))) if err != nil { t.Fatal(err) } if _, err = VerifyWorkerHead(pub, wire); !errors.Is(err, ErrWorkerControl) { t.Fatal("invalid signed head accepted") } }) } } func TestWorkerControlRejectsWrapperAmbiguityAndOversize(t *testing.T) { priv, pub := testKeys(t) wire, err := SignWorkerHead(RootSigner(priv), workerTestHead()) if err != nil { t.Fatal(err) } var compact bytes.Buffer if err = json.Compact(&compact, wire); err != nil { t.Fatal(err) } s := compact.String() for _, raw := range []string{ strings.Replace(s, `"payload":`, `"Payload":`, 1), strings.TrimSuffix(s, "}") + `,"grant":null}`, strings.TrimSuffix(s, "}") + `,"extra":0}`, s + strings.Repeat(" ", MaxWorkerControlBytes), `null`, } { if _, err := VerifyWorkerHead(pub, []byte(raw)); !errors.Is(err, ErrWorkerControl) { t.Fatal("malformed wrapper accepted") } } big, err := signRootPayload(RootSigner(priv), bytes.Repeat([]byte(" "), MaxWorkerControlBytes)) if err != nil { t.Fatal(err) } if _, err = VerifyWorkerHead(pub, big); !errors.Is(err, ErrWorkerControl) { t.Fatal("oversize payload accepted") } } func TestWorkerControlRefusesInvalidAssignmentScope(t *testing.T) { priv, pub := testKeys(t) for name, change := range map[string]func(*WorkerAssignmentState){ "kind": func(s *WorkerAssignmentState) { s.Kind = "maintenance-worker" }, "schema": func(s *WorkerAssignmentState) { s.Schema = 2 }, "assignment-digest": func(s *WorkerAssignmentState) { s.Identity.Assignment.Digest = "bad" }, "deployment": func(s *WorkerAssignmentState) { s.Identity.Deployment = "https://console.example.com/#fragment" }, "box": func(s *WorkerAssignmentState) { s.Identity.Box = "../other" }, "generation": func(s *WorkerAssignmentState) { s.Identity.Generation = 0 }, "account": func(s *WorkerAssignmentState) { s.Identity.Account = "../bds" }, "app": func(s *WorkerAssignmentState) { s.Identity.App = "../home" }, "host": func(s *WorkerAssignmentState) { s.Identity.Host = "https://home.example.com" }, "operation": func(s *WorkerAssignmentState) { s.Identity.Operation = "bad" }, "request": func(s *WorkerAssignmentState) { s.Identity.Request = "bad" }, "attempt": func(s *WorkerAssignmentState) { s.Identity.Attempt = "bad" }, "revision": func(s *WorkerAssignmentState) { s.Revision = 0 }, "expiry": func(s *WorkerAssignmentState) { s.Expires = 0 }, "preflight": func(s *WorkerAssignmentState) { s.Preflight = &maintenanceguard.Reference{} }, "compatibility": func(s *WorkerAssignmentState) { s.Compatibility = &maintenanceguard.Reference{} }, "execution": func(s *WorkerAssignmentState) { s.Execution = &maintenanceguard.Reference{} }, "resume": func(s *WorkerAssignmentState) { s.Resume = &maintenanceguard.Reference{} }, } { t.Run(name, func(t *testing.T) { state := workerTestAssignment() change(&state) if _, err := SignWorkerAssignment(RootSigner(priv), state); !errors.Is(err, ErrWorkerControl) { t.Fatal("invalid assignment signed") } wire, err := signRootPayload(RootSigner(priv), []byte(mustWorkerJSON(t, state))) if err != nil { t.Fatal(err) } if _, err = VerifyWorkerAssignment(pub, wire); !errors.Is(err, ErrWorkerControl) { t.Fatal("invalid signed assignment accepted") } }) } }