122 lines
4.5 KiB
Go
122 lines
4.5 KiB
Go
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")
|
|
}
|
|
}
|