//go:build unix package hostguard import ( "context" "encoding/json" "errors" "os" "testing" ) func TestPlan14RetiredInstallationEnumeration(t *testing.T) { for _, oldFormat := range []bool{false, true} { t.Run(map[bool]string{false: "retained", true: "old-cleared-stamp"}[oldFormat], func(t *testing.T) { f, target, captured := fenceFixture(t) store := &rootTestStore{dir: t.TempDir()} f.g.Root = NewRootAuthority(store) f.obs.Claim.Holder.Account, f.obs.Claim.Holder.App = "bab", "app" in := RootInstallation{Host: target.Host, Incarnation: captured.Incarnation, Stamp: captured.Stamp, Account: "bab", App: "app", Record: "record", Box: target.Box, Enrollment: target.Enrollment, Migration: 1, InventoryRevision: 7, Artifacts: InstallationArtifacts{Schema: 1, StateDirectory: true, Timers: "kept"}} if err := f.g.EstablishRoot(t.Context(), in, allow); err != nil { t.Fatal(err) } if retired, err := f.g.Root.HostRetired(t.Context(), target.Host); err != nil || retired { t.Fatal("active host marked retired", retired, err) } if err := f.g.RetireInstallationWith(t.Context(), target.Host, captured, allow, func() error { return os.ErrPermission }); !errors.Is(err, os.ErrPermission) { t.Fatal(err) } if oldFormat { raw, err := store.Read(target.Host + ".json") if err != nil { t.Fatal(err) } var r rootRecord if err := json.Unmarshal(raw, &r); err != nil { t.Fatal(err) } r.Installation.Stamp = 0 raw, _ = json.Marshal(r) if err := store.Write(target.Host+".json", raw); err != nil { t.Fatal(err) } } f.g.Root = NewRootAuthority(&rootTestStore{dir: store.dir}) if retired, err := f.g.Root.HostRetired(t.Context(), target.Host); err != nil || !retired { t.Fatal("retired host unavailable", retired, err) } for _, enumerate := range []func(context.Context) ([]FenceView, error){f.g.Root.MigrationInstallations, f.g.Root.GenerationInstallations} { views, err := enumerate(t.Context()) if err != nil || len(views) != 1 || views[0].Installation != in { t.Fatal("retired inventory lost", views, err) } if err := views[0].admit(target.Host, captured, target.Session); err == nil { t.Fatal("retired view admitted") } } if err := f.g.With(t.Context(), target.Host, captured, allow, func() error { t.Fatal("retired execution"); return nil }); err == nil { t.Fatal("retired execution admitted") } if err := f.g.RetireInstallationWith(t.Context(), target.Host, captured, allow, func() error { return nil }); err != nil { t.Fatal("cleanup retry", err) } }) } }