package host import ( "context" "errors" "os" "path/filepath" "runtime" "testing" "github.com/carlosframework/platform/internal/registry" "github.com/carlosframework/platform/internal/release" ) func runtimePlatform() string { return runtime.GOOS + "-" + runtime.GOARCH } // Astra I2 #1: the agent cannot persist its mark; the next pass, built the // way production builds it, still refuses the digestless replay. func TestOneRatchetPerProcessSurvivesAFailedPersist(t *testing.T) { if os.Geteuid() == 0 { t.Skip("root can write a 0555 directory") } ctx := context.Background() opt, data := t.TempDir(), t.TempDir() if err := os.MkdirAll(release.EdgeRatchetDir(data), 0o555); err != nil { t.Fatal(err) } store := release.NewDirStore(t.TempDir()) seed, pubB64, _ := release.GenerateKey() priv, _ := release.ParseSigningKey(seed, "t") pub, _ := release.ParsePublicKey(pubB64, "t") ship := func(v string) { m := release.Manifest{Schema: 1, App: "km", Version: v, Kind: "binary", Artifacts: map[string]release.Artifact{runtimePlatform(): {}}} if err := release.Ship(ctx, store, "bab", m, map[string][]byte{runtimePlatform(): []byte(v)}); err != nil { t.Fatal(err) } } ship("v1") if err := release.Promote(ctx, store, priv, "bab", "km", "canary/x", "v1"); err != nil { // legacy pointer t.Fatal(err) } legacy, _, _ := store.Get(ctx, release.ChannelKey("bab", "km", "canary/x")) if err := release.WriteDigestMarker(ctx, store, release.RootSigner(priv), "bab", "t"); err != nil { t.Fatal(err) } ship("v2") if err := release.Promote(ctx, store, priv, "bab", "km", "canary/x", "v2"); err != nil { // with digests t.Fatal(err) } reg, err := registry.Open(filepath.Join(t.TempDir(), "r.db")) if err != nil { t.Fatal(err) } if err := reg.Upsert(registry.Route{Host: "a.example.com", Kind: "instance", App: "km", Account: "bab", Channel: "canary/x"}); err != nil { t.Fatal(err) } off := func(string) string { return "" } pass := func() { opts := []release.PassOption{release.WithDigestRatchet(pointerRatchet(false, opt, data, off))} // the ratchet fastPassOpts arms, looked up fresh each pass if err := release.PassFilter(ctx, reg, store, pub, opt, nil, nil, opts...); err != nil { t.Fatal(err) } } pass() // the digest pointer: its mark cannot be written, so it is refused if v, _ := release.LiveVersion(opt, "a.example.com"); v != "" { t.Fatalf("installed %q on a pointer whose mark was not durable", v) } _, etag, _ := store.Get(ctx, release.ChannelKey("bab", "km", "canary/x")) if _, err := store.Put(ctx, release.ChannelKey("bab", "km", "canary/x"), legacy, etag); err != nil { t.Fatal(err) } pass() // the replay, on a new pass if v, _ := release.LiveVersion(opt, "a.example.com"); v != "" { t.Fatalf("a later pass in the same process installed the digestless replay %q", v) } } func TestPointerRatchetSharesMarksBetweenRootAndTheAgent(t *testing.T) { opt, data := t.TempDir(), t.TempDir() off := func(string) string { return "" } p := &release.ChannelPointer{App: "km", Channel: "stable", Version: "v1", Digest: release.ManifestDigest([]byte("m"))} if err := pointerRatchet(true, opt, data, off).Admit("bab", p); err != nil { t.Fatal(err) } legacy := &release.ChannelPointer{App: "km", Channel: "stable", Version: "v1"} if err := pointerRatchet(false, opt, data, off).Admit("bab", legacy); !errors.Is(err, release.ErrPointerWithoutDigests) { t.Fatalf("the agent ignored root's mark: %v", err) } on := func(k string) string { if k == release.RequirePointerDigestEnv { return "on" } return "" } fresh := &release.ChannelPointer{App: "km", Channel: "beta", Version: "v1"} if err := pointerRatchet(false, opt, data, on).Admit("bab", fresh); !errors.Is(err, release.ErrPointerWithoutDigests) { t.Fatalf("the flag was not read: %v", err) } } // fastPassBox is a box whose fast sweep is built by fastPassOpts, the // production builder: CARLOS_OPT_DIR points release.OptDir() at a temp dir, // and route a.example.com follows bab/km on canary/x. type fastPassBox struct { store release.Store priv []byte opt string data string reg *registry.Registry pub []byte } func newFastPassBox(t *testing.T) *fastPassBox { t.Helper() b := &fastPassBox{store: release.NewDirStore(t.TempDir()), opt: t.TempDir(), data: t.TempDir()} t.Setenv("CARLOS_OPT_DIR", b.opt) seed, pubB64, _ := release.GenerateKey() priv, _ := release.ParseSigningKey(seed, "t") pub, _ := release.ParsePublicKey(pubB64, "t") b.priv, b.pub = priv, pub reg, err := registry.Open(filepath.Join(t.TempDir(), "r.db")) if err != nil { t.Fatal(err) } if err := reg.Upsert(registry.Route{Host: "a.example.com", Kind: "instance", App: "km", Account: "bab", Channel: "canary/x"}); err != nil { t.Fatal(err) } b.reg = reg return b } func (b *fastPassBox) ship(t *testing.T, v string) { t.Helper() m := release.Manifest{Schema: 1, App: "km", Version: v, Kind: "binary", Artifacts: map[string]release.Artifact{runtimePlatform(): {}}} if err := release.Ship(context.Background(), b.store, "bab", m, map[string][]byte{runtimePlatform(): []byte(v)}); err != nil { t.Fatal(err) } } func (b *fastPassBox) promote(t *testing.T, v string) { t.Helper() if err := release.Promote(context.Background(), b.store, b.priv, "bab", "km", "canary/x", v); err != nil { t.Fatal(err) } } // pass runs one fast sweep with fastPassOpts' options, exactly as the agent // builds them each tick. func (b *fastPassBox) pass(t *testing.T) string { t.Helper() opts := fastPassOpts(b.data, func(string, string, error) {}, nil, nil) if err := release.PassFilter(context.Background(), b.reg, b.store, b.pub, b.opt, nil, nil, opts...); err != nil { t.Fatal(err) } v, _ := release.LiveVersion(b.opt, "a.example.com") return v } // Astra r1 #6: the ratchet armed by the production builder. A pointer with // digests is adopted and marks the channel; replaying the saved legacy // pointer is then refused, and the box keeps serving the digest build. // Removing WithDigestRatchet from fastPassOpts fails this test. func TestFastPassOptsRefuseAReplayedLegacyPointer(t *testing.T) { b := newFastPassBox(t) ctx := context.Background() b.ship(t, "v1") b.promote(t, "v1") // legacy: no marker yet legacy, _, err := b.store.Get(ctx, release.ChannelKey("bab", "km", "canary/x")) if err != nil { t.Fatal(err) } if v := b.pass(t); v != "v1" { t.Fatalf("control: the legacy pointer on a fresh box installed %q, want v1", v) } if err := release.WriteDigestMarker(ctx, b.store, release.RootSigner(b.priv), "bab", "t"); err != nil { t.Fatal(err) } b.ship(t, "v2") b.promote(t, "v2") // with digests if v := b.pass(t); v != "v2" { t.Fatalf("the digest pointer installed %q, want v2", v) } _, etag, _ := b.store.Get(ctx, release.ChannelKey("bab", "km", "canary/x")) if _, err := b.store.Put(ctx, release.ChannelKey("bab", "km", "canary/x"), legacy, etag); err != nil { t.Fatal(err) } if v := b.pass(t); v != "v2" { t.Fatalf("fastPassOpts let a replayed legacy pointer install %q", v) } } // CARLOS_REQUIRE_POINTER_DIGEST through the production builder: a fresh box // with the flag on refuses a legacy pointer for a channel it has never seen, // and with the flag off (the control) it installs it. func TestFastPassOptsHonourTheRequireFlagOnAFreshBox(t *testing.T) { for _, on := range []bool{false, true} { b := newFastPassBox(t) if on { t.Setenv(release.RequirePointerDigestEnv, "1") } else { t.Setenv(release.RequirePointerDigestEnv, "") } b.ship(t, "v1") b.promote(t, "v1") got := b.pass(t) switch { case on && got != "": t.Fatalf("flag on: a fresh box installed the legacy pointer's %q", got) case !on && got != "v1": t.Fatalf("control, flag off: installed %q, want v1", got) } } }