package main import ( "regexp" "strings" "testing" "github.com/novox/mesh-controller/internal/catalogue" snapshot "github.com/novox/mesh-controller/internal/facts" ) // The facts snapshot (novox/hq to-be 45 §9): composed from the store, every machine under a pseudonym // of its name's length, and nothing of the installation in it — no secret, no address, no name. // aMeshWithSecrets is aMesh with a provider and its consumers, a value given by hand, settings carrying // a password, an address and a machine's name, and a push's worth of credentials made. func aMeshWithSecrets(t *testing.T) (*stores, []string) { t.Helper() open := aMesh(t) ctx := t.Context() register(t, open, catalogue.Manifest{Module: "objects", Version: "1", Provides: []catalogue.Offer{{Name: "s3-bucket", Scope: catalogue.ScopeMesh, Identity: &catalogue.OfferIdentity{Max: 20, In: "an S3 access key"}}}, Receives: map[string]string{"s3-bucket": "/var/lib/mesh/objects/mesh.json"}}) register(t, open, catalogue.Manifest{Module: "files", Version: "1", Requires: []string{"s3-bucket"}, Resources: []map[string]any{{"id": "config", "type": "file", "path": "/etc/files/config.json", "mode": "0600", "content": "{}", "merge": "json"}}}) for _, a := range [][2]string{{"anchor", "objects"}, {"laptop", "files"}} { if _, err := assign(ctx, open, a[0], a[1]); err != nil { t.Fatalf("assign %s %s: %v", a[0], a[1], err) } } secrets := []string{"Hunter2-Is-Not-A-Password-9f8e7d", "0123456789abcdefABCDEF0123456789zz"} if err := open.inventory.SetSettings(ctx, "", "files", map[string]any{ "admin_password": secrets[0], "upstream": "10.77.0.9", "hub": "anchor"}); err != nil { t.Fatal(err) } if err := open.inventory.SetSettings(ctx, "laptop", "files", map[string]any{ "note": "reach me at 192.168.1.135, token " + secrets[1]}); err != nil { t.Fatal(err) } // A push's worth of composition, which makes the pair credential the consumer is sent. gens, err := generators(ctx, open) if err != nil { t.Fatal(err) } for _, node := range []string{"laptop", "anchor"} { if _, _, err := composedAndValidated(ctx, open, node, gens, Allocating); err != nil { t.Fatalf("%s does not compose: %v", node, err) } } issued, err := open.inventory.SecretsFrom(ctx, "anchor") if err != nil || len(issued) == 0 { t.Fatalf("no credential was made for the consumer: %v", err) } for _, s := range issued { // Sealed, never kept plain (ADR 0004): the sealed blobs are what the store holds, and none may leave. secrets = append(secrets, s.ForConsumer, s.ForProvider) } return open, secrets } func TestTheFactsCarryNoSecretNoAddressAndNoName(t *testing.T) { open, secrets := aMeshWithSecrets(t) f, err := gatherFacts(t.Context(), open, "2.11.17") if err != nil { t.Fatal(err) } body, err := f.Encode() if err != nil { t.Fatal(err) } text := string(body) for _, s := range secrets { if s != "" && strings.Contains(text, s) { t.Errorf("a secret is in the snapshot: %q", s) } } for _, leaked := range []string{"anchor", "laptop", "10.77.0.", "192.168.1.135", ".example:51820"} { if strings.Contains(text, leaked) { t.Errorf("%q is in the snapshot", leaked) } } // Every address it carries is a documentation address. for _, a := range regexp.MustCompile(`\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b`).FindAllString(text, -1) { if !strings.HasPrefix(a, "192.0.2.") && !strings.HasPrefix(a, "198.51.100.") && !strings.HasPrefix(a, "203.0.113.") { t.Errorf("%s is an address outside the documentation ranges", a) } } // What a check needs is there: every machine, its length, its modules, its declaration composing. if len(f.Machines) != 2 || f.Longest() != len("laptop") { t.Fatalf("machines %+v, longest %d", f.Machines, f.Longest()) } anchor := snapshot.Pseudonym("machine", "anchor") m, ok := f.Machine(anchor) if !ok || !m.Hub || !strings.Contains(m.Described(), "the hub") || len(m.Name) != len("anchor") { t.Fatalf("the anchor reads as %+v", m) } if !m.Declaration.Composes || m.Declaration.Digest == "" || len(m.Declaration.Resources) == 0 { t.Errorf("the anchor's declaration reads as %+v", m.Declaration) } laptop, _ := f.Machine(snapshot.Pseudonym("machine", "laptop")) if strings.Join(laptop.Assigned, ",") != "files,mesh-wireguard" && !strings.Contains(strings.Join(laptop.Assigned, ","), "files") { t.Errorf("the laptop's assignments read as %v", laptop.Assigned) } var meshWide map[string]any for _, s := range f.Settings { if s.Module == "files" { meshWide = s.Values } } if meshWide["admin_password"] != snapshot.Withheld || meshWide["hub"] != anchor { t.Errorf("the mesh-wide settings read as %v", meshWide) } if f.Versions.Bus != "2.11.17" || f.Versions.Store == "" { t.Errorf("versions read as %+v", f.Versions) } var objects bool for _, mod := range f.Modules { objects = objects || mod.Name == "objects" && len(mod.Manifest) > 0 } if !objects { t.Error("the modules the mesh holds are not in the snapshot") } // And an unchanged mesh is the same content a moment later. again, err := gatherFacts(t.Context(), open, "2.11.17") if err != nil { t.Fatal(err) } a, _ := f.Content() b, _ := again.Content() if a != b { t.Error("two snapshots of an unchanged mesh differ, so it would be written again every ten minutes") } }