package inventory import ( "context" "testing" "github.com/novox/mesh-controller/internal/catalogue" ) // The move reads every row sealed to a machine as the store holds it (design 57's V3, issue 676): its modules' own // secrets and each pair credential it is an end of, sealed to it, under the vault's name for the row, with its // origin and generation; a row sealed to a key the machine no longer has is said as not current; what moved is kept // once, for both ends of a pair; and the move's start and the copy of the asks are recorded once. func TestTheMoveReadsEveryRowSealedToAMachineAsItIs(t *testing.T) { inv := fresh(t) ctx := context.Background() opens := map[string]func(string) ([]byte, bool){} for _, n := range []string{"consumer", "provider"} { node, err := inv.AddNode(ctx, n) if err != nil { t.Fatal(err) } key, open := aSealingKey(t) opens[n] = open if err := inv.RecordSealingKey(ctx, node.ID, key); err != nil { t.Fatal(err) } } if err := inv.RegisterModule(ctx, catalogue.Manifest{Module: "gitea", Version: "1", Requires: []string{"postgres-database"}, Secrets: map[string]string{"postgres-database": "/run/pg"}}, Source{}); err != nil { t.Fatal(err) } if err := inv.RegisterModule(ctx, catalogue.Manifest{Module: "postgres", Version: "1"}, Source{}); err != nil { t.Fatal(err) } if _, err := inv.SecretForModule(ctx, "provider", "postgres", "superuser"); err != nil { t.Fatal(err) } if _, err := inv.SecretFor(ctx, "postgres-database", "consumer", "gitea", "provider", ""); err != nil { t.Fatal(err) } provider, err := inv.SecretsToMoveFrom(ctx, "provider") if err != nil { t.Fatal(err) } consumer, err := inv.SecretsToMoveFrom(ctx, "consumer") if err != nil { t.Fatal(err) } if len(provider) != 2 || len(consumer) != 1 { t.Fatalf("the provider has %d rows, the consumer %d: %+v %+v", len(provider), len(consumer), provider, consumer) } own := provider[0] if own.Secret != "own/provider/postgres/superuser" || !own.Own() || own.Origin != "made" || !own.Current || own.Moved != nil || own.MadeAt.IsZero() { t.Errorf("the own secret: %+v", own) } pair := provider[1] if pair.Secret != "pair/provider/postgres-database/consumer/gitea" || pair.Own() || pair.Provider != "provider" || pair.Consumer != "consumer" || pair.ConsumerModule != "gitea" || !pair.Current { t.Errorf("the pair from the provider's end: %+v", pair) } // Each end is handed what was sealed to it, and it opens there to the same value. atProvider, ok1 := opens["provider"](pair.Sealed) atConsumer, ok2 := opens["consumer"](consumer[0].Sealed) if !ok1 || !ok2 || string(atProvider) != string(atConsumer) { t.Fatal("the two ends of the pair were not each handed what was sealed to them") } if _, ok := opens["provider"](own.Sealed); !ok { t.Fatal("the own secret does not open with its machine's key") } // Moved by one end, the row is moved for both, and the first record stands. if err := inv.RecordSecretMoved(ctx, consumer[0], 1); err != nil { t.Fatal(err) } if err := inv.RecordSecretMoved(ctx, pair, 2); err != nil { t.Fatal(err) } provider, _ = inv.SecretsToMoveFrom(ctx, "provider") if m := provider[1].Moved; m == nil || m.Node != "consumer" || m.Generation != 1 || m.Digest != consumer[0].Digest || m.Digest != provider[1].Digest { t.Errorf("the pair as moved: %+v", m) } if provider[0].Moved != nil { t.Error("the own secret reads as moved") } // A machine that rejoined has a key its old rows were not sealed to. node, _ := inv.NodeByName(ctx, "provider") key, _ := aSealingKey(t) if err := inv.RecordSealingKey(ctx, node.ID, key); err != nil { t.Fatal(err) } provider, _ = inv.SecretsToMoveFrom(ctx, "provider") if provider[0].Current { t.Error("a row sealed to the machine's earlier key reads as current") } if _, started, _ := inv.SecretMoveStarted(ctx); started { t.Fatal("the move reads as started before it was") } first, err := inv.StartSecretMove(ctx, "jochen") if err != nil || first.StartedBy != "jochen" || first.AsksMovedAt != nil { t.Fatalf("started %+v, %v", first, err) } again, _ := inv.StartSecretMove(ctx, "someone else") if again.StartedBy != "jochen" || !again.StartedAt.Equal(first.StartedAt) { t.Errorf("a second start replaced the first: %+v", again) } if err := inv.RecordAsksMoved(ctx); err != nil { t.Fatal(err) } if m, _, _ := inv.SecretMoveStarted(ctx); m.AsksMovedAt == nil { t.Error("the copy of the asks was not recorded") } if _, err := inv.SecretsToMoveFrom(ctx, "nowhere"); err == nil { t.Error("a machine the mesh does not know was read") } }