//go:build linux package provisioner import ( "bytes" "context" "errors" "os" "os/exec" "strings" "testing" "time" "amadan.net/oficina/home/internal/operator" "github.com/go-json-experiment/json" "github.com/go-json-experiment/json/jsontext" ) func planFixture() InstallationPlan { target := func(host, origin string) InstallationTarget { return InstallationTarget{Console: "https://console.example.test", Account: "synthetic-account", App: "oficina/home", Host: host, Origin: origin, Release: strings.Repeat("a", 40), Artifact: strings.Repeat("b", 64), Environment: strings.Repeat("c", 64), DataKey: strings.Repeat("d", 64)} } return InstallationPlan{1, testToken(20), testToken(21), target("credential.example.test", "https://id.example.test"), target("directory.example.test", "https://home.example.test")} } func stateFixture(t *testing.T) (*journal, InstallationPlan) { t.Helper() j := journalFixture(t) p := planFixture() j.now = func() time.Time { return time.Unix(2000000000, 0) } if e := j.enroll(context.Background(), p); e != nil { t.Fatal(e) } return j, p } func snapshot(t *testing.T, j *journal) *installationBook { t.Helper() j.mu.Lock() defer j.mu.Unlock() b, e := j.bookLocked() if e != nil { t.Fatal(e) } return b } func initialization(op string) operator.InitializeInput { return operator.InitializeInput{InputBase: operator.InputBase{Version: 1, Operation: "directory.initialize", OperationID: op}, Generation: testToken(22), Baseline: "operator-attests-never-provisioned"} } func TestInstallationPreparationReplayAndIndependentRoles(t *testing.T) { j, p := stateFixture(t) ctx := context.Background() if e := j.enroll(ctx, p); e != nil { t.Fatal(e) } changed := p changed.Directory.Environment = strings.Repeat("e", 64) if e := j.enroll(ctx, changed); e != ErrRefused { t.Fatal("changed baseline", e) } raw, e := j.prepare(ctx, p.Installation, testToken(23), "directory.initialize", initialization(testToken(23))) if e != nil { t.Fatal(e) } before := snapshot(t, j) req := before.installations[p.Installation].Operations[testToken(23)].Request if req.Authorization().JournalSequence != 2 || req.Authorization().Sequence != 1 { t.Fatal("independent sequences") } if before.installations[p.Installation].Generation != "" || before.installations[p.Installation].Heads["directory"].Sequence != 0 { t.Fatal("preparation advanced authority") } j.now = func() time.Time { return time.Unix(2000001000, 0) } repeated, e := j.prepare(ctx, p.Installation, testToken(23), "directory.initialize", initialization(testToken(23))) if e != nil || !bytes.Equal(raw, repeated) { t.Fatal("exact expired prepared request changed", e) } changedInput := initialization(testToken(23)) changedInput.Generation = testToken(29) if _, e = j.prepare(ctx, p.Installation, testToken(23), "directory.initialize", changedInput); e != ErrRefused { t.Fatal("changed input", e) } if _, e = j.prepare(ctx, p.Installation, testToken(24), "directory.initialize", initialization(testToken(24))); e != ErrRefused { t.Fatal("replaced unresolved attempt", e) } if e = j.markInFlight(ctx, p.Installation, testToken(25), testToken(23)); e != ErrRefused { t.Fatal("expired dispatch", e) } credential, e := j.prepare(ctx, p.Installation, testToken(26), "credential.owner-seed", struct { Version int `json:"version"` }{1}) if e != nil || len(credential) == 0 { t.Fatal("independent credential role", e) } after := snapshot(t, j) if after.installations[p.Installation].Operations[testToken(26)].Request.Authorization().Sequence != 1 || len(after.installations[p.Installation].Heads) != 0 { t.Fatal("role advanced during preparation") } } func TestInstallationAmbiguityNeverReleasesSlot(t *testing.T) { j, p := stateFixture(t) ctx := context.Background() op := testToken(23) if _, e := j.prepare(ctx, p.Installation, op, "directory.initialize", initialization(op)); e != nil { t.Fatal(e) } if e := j.markInFlight(ctx, p.Installation, testToken(24), op); e != nil { t.Fatal(e) } if e := j.markInFlight(ctx, p.Installation, testToken(24), op); e != nil { t.Fatal("event replay", e) } if e := j.transition(ctx, p.Installation, testToken(25), "provisioner.outcome", "in-flight", localTransition{Operation: op, Kind: "ambiguous"}); e != nil { t.Fatal(e) } j.now = func() time.Time { return time.Unix(2000001000, 0) } if e := j.transition(ctx, p.Installation, testToken(26), "provisioner.outcome", "in-flight", localTransition{Operation: op, Kind: "refused"}); e != ErrRefused { t.Fatal("ambiguous became refused", e) } if _, e := j.prepare(ctx, p.Installation, testToken(27), "directory.initialize", initialization(testToken(27))); e != ErrRefused { t.Fatal("replaced ambiguous", e) } } func TestInstallationRefusalRequiresExpiryBeforeReplacement(t *testing.T) { j, p := stateFixture(t) ctx := context.Background() op := testToken(23) if _, e := j.prepare(ctx, p.Installation, op, "directory.initialize", initialization(op)); e != nil { t.Fatal(e) } if e := j.markInFlight(ctx, p.Installation, testToken(24), op); e != nil { t.Fatal(e) } tr := localTransition{Operation: op, Kind: "refused"} if e := j.transition(ctx, p.Installation, testToken(25), "provisioner.outcome", "in-flight", tr); e != ErrRefused { t.Fatal("fresh slot released", e) } j.now = func() time.Time { return time.Unix(2000000300, 0) } if e := j.transition(ctx, p.Installation, testToken(25), "provisioner.outcome", "in-flight", tr); e != nil { t.Fatal(e) } if _, e := j.prepare(ctx, p.Installation, testToken(26), "directory.initialize", initialization(testToken(26))); e != nil { t.Fatal(e) } s := snapshot(t, j).installations[p.Installation] if s.Operations[testToken(26)].Request.Authorization().Sequence != 1 || s.Heads["directory"].Sequence != 0 { t.Fatal("refusal consumed role sequence") } } func TestInstallationExactLargeResultDoesNotAdvanceUntilTransition(t *testing.T) { j, p := stateFixture(t) ctx := context.Background() op := testToken(23) if _, e := j.prepare(ctx, p.Installation, op, "directory.initialize", initialization(op)); e != nil { t.Fatal(e) } if e := j.markInFlight(ctx, p.Installation, testToken(24), op); e != nil { t.Fatal(e) } result := operator.Result{Version: 1, OperationID: op, Outcome: "committed", Generation: testToken(22), Receipt: jsontext.Value(`"x"`)} small, _ := json.Marshal(result, json.Deterministic(true)) result.Receipt = jsontext.Value(`"` + strings.Repeat("x", (64<<10)-len(small)+1) + `"`) exact, e := json.Marshal(result, json.Deterministic(true)) if e != nil || len(exact) != 64<<10 { t.Fatal("boundary", len(exact), e) } record, e := j.append(ctx, p.Installation, testToken(25), "provisioner.result", "in-flight", exact) if e != nil { t.Fatal(e) } s := snapshot(t, j).installations[p.Installation] if s.Generation != "" || s.Heads["directory"].Sequence != 0 { t.Fatal("orphan result advanced") } tr := localTransition{Operation: op, Kind: "accepted", ResultRecord: testToken(25), ResultHead: testToken(99)} if e = j.transition(ctx, p.Installation, testToken(26), "provisioner.outcome", "in-flight", tr); e != ErrRefused { t.Fatal("tampered result reference", e) } tr.ResultHead = hash(record) if e = j.transition(ctx, p.Installation, testToken(26), "provisioner.outcome", "in-flight", tr); e != nil { t.Fatal(e) } if e = j.transition(ctx, p.Installation, testToken(26), "provisioner.outcome", "in-flight", tr); e != nil { t.Fatal("outcome exact replay", e) } s = snapshot(t, j).installations[p.Installation] if s.Generation != testToken(22) || s.Heads["directory"].Sequence != 1 || !bytes.Equal(s.Operations[op].Result, exact) { t.Fatal("accepted result changed") } if _, e = j.prepare(ctx, p.Installation, testToken(27), "directory.seed-team", struct { Generation string `json:"expected_generation"` }{s.Generation}); e != nil { t.Fatal(e) } s = snapshot(t, j).installations[p.Installation] if s.Operations[testToken(27)].Request.Authorization().Previous != s.Heads["directory"].Head { t.Fatal("accepted chain not bound") } } func TestInstallationPreparationCrashBoundaries(t *testing.T) { for _, boundary := range []string{"prepared", "floor", "finalized"} { t.Run(boundary, func(t *testing.T) { j, p := stateFixture(t) ctx := context.Background() stop := errors.New("synthetic crash") j.boundary = func(stage string) error { if stage == boundary { return stop } return nil } if _, e := j.prepare(ctx, p.Installation, testToken(23), "directory.initialize", initialization(testToken(23))); e != stop { t.Fatal(e) } j.close() reopened, e := openJournal(j.dir, j.floor, j.key, false) if e != nil { t.Fatal(e) } defer reopened.close() reopened.now = func() time.Time { return time.Unix(2000001000, 0) } raw, e := reopened.prepare(ctx, p.Installation, testToken(23), "directory.initialize", initialization(testToken(23))) if e != nil || len(raw) == 0 { t.Fatal("recover signed bytes", e) } s := snapshot(t, reopened).installations[p.Installation] if len(s.Operations) != 1 || s.Heads["directory"].Sequence != 0 || s.Operations[testToken(23)].Request.Authorization().JournalSequence != 2 { t.Fatal("crash reserved twice") } }) } } // These subprocesses exercise local custody and journal transitions only. They // do not impersonate a worker or manufacture an authenticated remote outcome. func TestNativeEnrollmentCLIAndProcessDeath(t *testing.T) { if mode := os.Getenv("OFICINA_STATE_CHILD"); mode != "" { state, floor := os.Getenv("OFICINA_STATE_PATH"), os.Getenv("OFICINA_FLOOR_PATH") if mode == "enroll" { if e := Run([]string{"provision", "enroll", "--state", state, "--floor-dir", floor, "--password-fd", "3", "--plan-fd", "4"}, os.Stdout); e != nil { os.Exit(1) } os.Exit(0) } password, e := privatePassword(3) if e != nil { os.Exit(2) } j, e := existingJournal(state, floor, password) clear(password) if e != nil { os.Exit(3) } defer closeExisting(j) j.boundary = func(stage string) error { if stage == mode { os.Exit(72) } return nil } _, e = j.prepare(context.Background(), testToken(20), testToken(23), "directory.initialize", initialization(testToken(23))) if e != nil { os.Exit(4) } os.Exit(5) } for _, boundary := range []string{"prepared", "floor", "finalized"} { t.Run(boundary, func(t *testing.T) { state, floor := persistentDirectory(t), persistentDirectory(t) password := []byte("synthetic-state-private-password") if _, e := Initialize(state, floor, password); e != nil { t.Fatal(e) } plan, _ := canonicalJSON(planFixture()) run := func(mode string) ([]byte, error) { r, w, e := os.Pipe() if e != nil { t.Fatal(e) } pr, pw, e := os.Pipe() if e != nil { t.Fatal(e) } defer r.Close() defer pr.Close() cmd := exec.Command(os.Args[0], "-test.run=^TestNativeEnrollmentCLIAndProcessDeath$") cmd.Env = append(os.Environ(), "OFICINA_STATE_CHILD="+mode, "OFICINA_STATE_PATH="+state, "OFICINA_FLOOR_PATH="+floor) cmd.ExtraFiles = []*os.File{r, pr} var out bytes.Buffer cmd.Stdout = &out cmd.Stderr = &out if e = cmd.Start(); e != nil { t.Fatal(e) } r.Close() pr.Close() _, e = w.Write(password) w.Close() if e != nil { t.Fatal(e) } if mode == "enroll" { if _, e = pw.Write(plan); e != nil { t.Fatal(e) } } pw.Close() e = cmd.Wait() if bytes.Contains(out.Bytes(), password) || bytes.Contains(out.Bytes(), []byte(planFixture().Credential.Host)) { t.Fatal("private output") } return out.Bytes(), e } first, e := run("enroll") if e != nil { t.Fatal("enroll CLI", e) } second, e := run("enroll") if e != nil || !bytes.Equal(first, second) { t.Fatal("plan replay", e) } j, e := existingJournal(state, floor, password) if e != nil { t.Fatal(e) } if _, e = run("enroll"); e == nil { t.Fatal("second process bypassed registry lock") } closeExisting(j) _, e = run(boundary) var exit *exec.ExitError if !errors.As(e, &exit) || exit.ExitCode() != 72 { t.Fatal("process death boundary", e) } reopened, e := existingJournal(state, floor, password) if e != nil { t.Fatal(e) } defer closeExisting(reopened) reopened.now = func() time.Time { return time.Now().Add(time.Hour) } raw, e := reopened.prepare(context.Background(), testToken(20), testToken(23), "directory.initialize", initialization(testToken(23))) if e != nil || len(raw) == 0 { t.Fatal("recover after process death", e) } s := snapshot(t, reopened).installations[testToken(20)] if len(s.Operations) != 1 || s.Heads["directory"].Sequence != 0 { t.Fatal("process crash advanced authority") } }) } } func TestInstallationResultAndAcceptanceCrashBoundaries(t *testing.T) { for _, phase := range []string{"result", "acceptance"} { for _, boundary := range []string{"prepared", "floor", "finalized"} { t.Run(phase+"/"+boundary, func(t *testing.T) { j, p := stateFixture(t) ctx := context.Background() op := testToken(23) if _, e := j.prepare(ctx, p.Installation, op, "directory.initialize", initialization(op)); e != nil { t.Fatal(e) } if e := j.markInFlight(ctx, p.Installation, testToken(24), op); e != nil { t.Fatal(e) } result, _ := json.Marshal(operator.Result{Version: 1, OperationID: op, Outcome: "committed", Generation: testToken(22)}, json.Deterministic(true)) stop := errors.New("synthetic interruption") inject := func() { j.boundary = func(stage string) error { if stage == boundary { return stop } return nil } } if phase == "result" { inject() } record, e := j.append(ctx, p.Installation, testToken(25), "provisioner.result", "in-flight", result) if phase == "result" && e != stop || phase == "acceptance" && e != nil { t.Fatal(e) } if phase == "acceptance" { inject() if e = j.transition(ctx, p.Installation, testToken(26), "provisioner.outcome", "in-flight", localTransition{Operation: op, Kind: "accepted", ResultRecord: testToken(25), ResultHead: hash(record)}); e != stop { t.Fatal(e) } } j.close() reopened, e := openJournal(j.dir, j.floor, j.key, false) if e != nil { t.Fatal(e) } defer reopened.close() b := snapshot(t, reopened) s := b.installations[p.Installation] if phase == "result" && (s.Generation != "" || s.Heads["directory"].Sequence != 0) { t.Fatal("orphan accepted") } if phase == "acceptance" && (s.Generation != testToken(22) || s.Heads["directory"].Sequence != 1) { t.Fatal("accepted event lost") } tr := localTransition{Operation: op, Kind: "accepted", ResultRecord: testToken(25), ResultHead: b.heads[testToken(25)]} if phase == "result" { missing := tr missing.ResultRecord = testToken(30) if e = reopened.transition(ctx, p.Installation, testToken(26), "provisioner.outcome", "in-flight", missing); e != ErrRefused { t.Fatal("missing result accepted", e) } } if e = reopened.transition(ctx, p.Installation, testToken(26), "provisioner.outcome", "in-flight", tr); e != nil { t.Fatal("exact acceptance recovery", e) } if snapshot(t, reopened).installations[p.Installation].Heads["directory"].Sequence != 1 { t.Fatal("accepted twice") } }) } } } func TestInstallationRestoredOldJournalCannotForgetAcceptedHead(t *testing.T) { j, p := stateFixture(t) ctx := context.Background() op := testToken(23) if _, e := j.prepare(ctx, p.Installation, op, "directory.initialize", initialization(op)); e != nil { t.Fatal(e) } if _, e := j.db.Exec("PRAGMA wal_checkpoint(TRUNCATE)"); e != nil { t.Fatal(e) } path := j.dir.file.Name() + "/registry.db" old, e := os.ReadFile(path) if e != nil { t.Fatal(e) } if e = j.markInFlight(ctx, p.Installation, testToken(24), op); e != nil { t.Fatal(e) } result, _ := json.Marshal(operator.Result{Version: 1, OperationID: op, Outcome: "committed", Generation: testToken(22)}, json.Deterministic(true)) record, e := j.append(ctx, p.Installation, testToken(25), "provisioner.result", "in-flight", result) if e != nil { t.Fatal(e) } if e = j.transition(ctx, p.Installation, testToken(26), "provisioner.outcome", "in-flight", localTransition{Operation: op, Kind: "accepted", ResultRecord: testToken(25), ResultHead: hash(record)}); e != nil { t.Fatal(e) } j.close() if e = os.WriteFile(path, old, 0600); e != nil { t.Fatal(e) } reopened, e := openJournal(j.dir, j.floor, j.key, false) if reopened != nil { reopened.close() } if e != ErrRefused { t.Fatal("old snapshot reset role authority", e) } } func TestInstallationPrivatePlanAndRequestStayEncrypted(t *testing.T) { j, p := stateFixture(t) input := operator.OwnerInput{InputBase: operator.InputBase{Version: 1, Operation: "credential.owner-seed", OperationID: testToken(23)}, Directory: p.Directory.Origin, TeamID: 1, TeamSQID: "Uk", Address: "native-state-private-32@example.invalid", ExistingOnly: true} if _, e := j.prepare(context.Background(), p.Installation, testToken(23), "credential.owner-seed", input); e != nil { t.Fatal(e) } for _, suffix := range []string{"", "-wal", "-shm"} { raw, e := os.ReadFile(j.dir.file.Name() + "/registry.db" + suffix) if e != nil && !os.IsNotExist(e) { t.Fatal(e) } for _, canary := range []string{input.Address, p.Directory.Host, p.Credential.Host, p.Directory.Environment, p.Directory.Origin} { if bytes.Contains(raw, []byte(canary)) { t.Fatal("private journal plaintext") } } } for _, action := range []string{"accept", "refuse", "complete", "mark-stopped"} { if e := Run([]string{"provision", action}, &bytes.Buffer{}); e != ErrRefused { t.Fatal("CLI manufactured completion", e) } } }