package apply import ( "context" "encoding/json" "os" "strings" "testing" "github.com/novox/mesh-host/internal/declaration" "github.com/novox/mesh-host/internal/identity" "github.com/novox/mesh-host/internal/store" ) // A file the mesh delivers without being able to read. // // Everything else in a declaration is visible to whatever carried it: the message is signed, so // it cannot be forged, and signing does not make it unreadable. A password in `content` is a // password the broker sees — the transitive trust this design refuses everywhere else. func sealedTo(t *testing.T, key identity.SealingKey, value string) string { t.Helper() sealed, err := identity.Seal(key.Public, []byte(value)) if err != nil { t.Fatal(err) } return sealed } func opener(key identity.SealingKey) Unseal { return func(sealed string) ([]byte, error) { return key.Unseal(sealed) } } func sealedFile(t *testing.T, path, sealed string) *declaration.Declaration { t.Helper() raw := map[string]any{"declaration": 1, "resources": []map[string]any{ {"id": "creds", "type": "file", "path": path, "sealed": sealed}, }} body, _ := json.Marshal(raw) d, err := declaration.Parse(body) if err != nil { t.Fatal(err) } return d } func TestASealedFileIsOpenedAndWritten(t *testing.T) { key, err := identity.GenerateSealingKey() if err != nil { t.Fatal(err) } dir := t.TempDir() path := dir + "/db.json" d := sealedFile(t, path, sealedTo(t, key, `{"password":"hunter2"}`)) report, _, err := Apply(context.Background(), archHost(t), d, store.State{}, store.OriginCarried, noServices, nil, opener(key)) if err != nil { t.Fatal(err) } if !report.Changed() { t.Fatal("nothing changed") } on, err := os.ReadFile(path) if err != nil { t.Fatal(err) } if string(on) != `{"password":"hunter2"}` { t.Fatalf("the file holds %q", on) } } func TestASecretIsNotWorldReadableByDefault(t *testing.T) { // An ordinary file defaults to 0644, which for a credential is the whole problem. The default // differs because the consequence differs; an explicit mode still wins, since a module may // need its own user to read it and only the module knows which. key, _ := identity.GenerateSealingKey() dir := t.TempDir() path := dir + "/db.json" d := sealedFile(t, path, sealedTo(t, key, "secret")) if _, _, err := Apply(context.Background(), archHost(t), d, store.State{}, store.OriginCarried, noServices, nil, opener(key)); err != nil { t.Fatal(err) } info, err := os.Stat(path) if err != nil { t.Fatal(err) } if info.Mode().Perm() != 0o600 { t.Fatalf("a credential landed mode %o", info.Mode().Perm()) } } func TestSomethingSealedToAnotherNodeIsRefused(t *testing.T) { // Refused, not skipped, and refused before anything is written. A machine that quietly does // not apply the one resource carrying a credential looks configured and cannot connect. mine, _ := identity.GenerateSealingKey() theirs, _ := identity.GenerateSealingKey() dir := t.TempDir() path := dir + "/db.json" d := sealedFile(t, path, sealedTo(t, theirs, "not for you")) _, _, err := Apply(context.Background(), archHost(t), d, store.State{}, store.OriginCarried, noServices, nil, opener(mine)) if err == nil { t.Fatal("a file sealed to another node was applied") } if _, statErr := os.Stat(path); statErr == nil { t.Fatal("something was written before the failure") } } func TestANodeWithNoSealingKeyRefusesRatherThanSkipping(t *testing.T) { key, _ := identity.GenerateSealingKey() dir := t.TempDir() d := sealedFile(t, dir+"/db.json", sealedTo(t, key, "secret")) _, _, err := Apply(context.Background(), archHost(t), d, store.State{}, store.OriginCarried, noServices, nil, nil) if err == nil { t.Fatal("a sealed file was skipped by a node that cannot open one") } if !strings.Contains(err.Error(), "sealing key") { t.Fatalf("the failure does not say why: %v", err) } } func TestTheSecretIsNeverInWhatTheMeshIsToldBack(t *testing.T) { // The node reports what it applied, and that report goes over the same broker the sealing was // for. A digest is a fact about the file; the file is not. key, _ := identity.GenerateSealingKey() dir := t.TempDir() d := sealedFile(t, dir+"/db.json", sealedTo(t, key, "hunter2")) report, state, err := Apply(context.Background(), archHost(t), d, store.State{}, store.OriginCarried, noServices, nil, opener(key)) if err != nil { t.Fatal(err) } said, _ := json.Marshal(report) kept, _ := json.Marshal(state) for what, blob := range map[string][]byte{"the report": said, "the node's state": kept} { if strings.Contains(string(blob), "hunter2") { t.Fatalf("%s carries the secret in plain text:\n%s", what, blob) } } } func TestASealedFileStillNoticesAHandEdit(t *testing.T) { // Drift detection must survive not holding the plaintext. It does, because what is recorded // is a digest of what was written rather than what was written. key, _ := identity.GenerateSealingKey() dir := t.TempDir() path := dir + "/db.json" d := sealedFile(t, path, sealedTo(t, key, "hunter2")) _, state, err := Apply(context.Background(), archHost(t), d, store.State{}, store.OriginCarried, noServices, nil, opener(key)) if err != nil { t.Fatal(err) } if err := os.WriteFile(path, []byte("meddled"), 0o600); err != nil { t.Fatal(err) } again, _, err := Apply(context.Background(), archHost(t), d, state, store.OriginCarried, noServices, nil, opener(key)) if err != nil { t.Fatal(err) } if !again.Changed() { t.Fatal("a hand-edited credential was left as it was found") } on, _ := os.ReadFile(path) if string(on) != "hunter2" { t.Fatalf("it was not put back: %q", on) } } func TestContentAndSealedTogetherIsRefused(t *testing.T) { // Otherwise nobody can tell by looking whether what landed on the machine was the secret or // the placeholder. _, err := declaration.Parse([]byte(`{"declaration":1,"resources":[ {"id":"f","type":"file","path":"/etc/x","content":"a","sealed":"b"}]}`)) if err == nil { t.Fatal("a file that is both literal and sealed was accepted") } if !strings.Contains(err.Error(), "exactly once") { t.Fatalf("unhelpful refusal: %v", err) } }