153 lines
5.2 KiB
Go
153 lines
5.2 KiB
Go
package main
|
|
|
|
// The tools the TypeScript vault offered, answering as they did: secret_export, secret_holders and
|
|
// secret_verify — none returns a value. And the seat's verb `get`, reached the way the runtime calls it.
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/seal"
|
|
)
|
|
|
|
func toolNamed(t *testing.T, tools []toolDef, name string) toolDef {
|
|
t.Helper()
|
|
for _, tl := range tools {
|
|
if tl.Name == name {
|
|
return tl
|
|
}
|
|
}
|
|
t.Fatalf("no tool %s", name)
|
|
return toolDef{}
|
|
}
|
|
|
|
func TestTheManifestNamesWhatTheBundleServes(t *testing.T) {
|
|
raw, _ := os.ReadFile("../../module.json")
|
|
var m struct {
|
|
Tools []string `json:"tools"`
|
|
Claims []struct {
|
|
Name string `json:"name"`
|
|
Serves []string `json:"serves"`
|
|
} `json:"claims"`
|
|
Emits []string `json:"emits"`
|
|
}
|
|
if err := json.Unmarshal(raw, &m); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
served := map[string]bool{}
|
|
for _, tl := range definitions(&Env{}) {
|
|
served[tl.Name] = true
|
|
}
|
|
for _, name := range m.Tools {
|
|
if !served[name] {
|
|
t.Errorf("the manifest names the tool %s, which the bundle does not serve", name)
|
|
}
|
|
}
|
|
for _, c := range m.Claims {
|
|
for _, verb := range c.Serves {
|
|
if !served[c.Name+"."+verb] {
|
|
t.Errorf("the claim of %s serves %s, which the bundle does not", c.Name, verb)
|
|
}
|
|
}
|
|
}
|
|
for name := range served {
|
|
if !strings.HasPrefix(name, Seat+".") && !contains(m.Tools, name) {
|
|
t.Errorf("the bundle serves %s, which the manifest does not name", name)
|
|
}
|
|
}
|
|
if !contains(m.Emits, ChangedEvent) {
|
|
t.Errorf("the manifest does not say the vault emits %s", ChangedEvent)
|
|
}
|
|
}
|
|
|
|
func TestSecretExportAnswersTheMeshsExport(t *testing.T) {
|
|
root := t.TempDir()
|
|
env := &Env{Root: root}
|
|
export := toolNamed(t, definitions(env), "secret_export")
|
|
got, _ := export.Run(map[string]any{})
|
|
if got.(map[string]any)["available"] != false {
|
|
t.Errorf("no export said %v", got)
|
|
}
|
|
doc := `{"export":1,"operator-key":"b3A=","fingerprint":"sha256:f","kept":[{"node":"g14","module":"dunst","name":"token","kind":"own","origin":"made","sealed":"c2VhbGVk","key":"b3A=","made-at":"2026-10-01T00:00:00Z"}],"unrecoverable":[{"node":"ace","module":"x","name":"y"}]}`
|
|
_ = os.WriteFile(filepath.Join(root, "export.json"), []byte(doc), 0o600)
|
|
got, _ = export.Run(map[string]any{})
|
|
a := got.(map[string]any)
|
|
if a["available"] != true || a["count"] != 1 || a["operator-key"] != "b3A=" {
|
|
t.Errorf("the export said %v", a)
|
|
}
|
|
got, _ = export.Run(map[string]any{"sealed": false})
|
|
kept := got.(map[string]any)["kept"].([]map[string]any)
|
|
if _, ok := kept[0]["sealed"]; ok {
|
|
t.Error("sealed=false still returned the blobs")
|
|
}
|
|
}
|
|
|
|
func TestSecretHoldersAndVerifySayFingerprintsOnly(t *testing.T) {
|
|
dir := t.TempDir()
|
|
l, _ := NewLedger(filepath.Join(dir, "ledger"))
|
|
secret := filepath.Join(dir, "s")
|
|
_ = os.WriteFile(secret, []byte("the-value"), 0o600)
|
|
receives := filepath.Join(dir, "mesh.json")
|
|
doc, _ := json.Marshal(map[string]any{"given": []map[string]string{{"from": "redis", "node": "anchor", "as": "anchor-redis", "secret": secret}}})
|
|
_ = os.WriteFile(receives, doc, 0o600)
|
|
_, _, _ = l.Record("anchor-redis", "anchor", "the-value", time.Now())
|
|
env := &Env{Ledger: l, Receives: receives}
|
|
|
|
holders, _ := toolNamed(t, definitions(env), "secret_holders").Run(map[string]any{})
|
|
verify, _ := toolNamed(t, definitions(env), "secret_verify").Run(map[string]any{"as": "anchor-redis", "fingerprint": Fingerprint("the-value")})
|
|
unknown, _ := toolNamed(t, definitions(env), "secret_verify").Run(map[string]any{"as": "nobody"})
|
|
for _, answer := range []any{holders, verify, unknown} {
|
|
raw, _ := json.Marshal(answer)
|
|
if strings.Contains(string(raw), "the-value") {
|
|
t.Errorf("a tool returned the value: %s", raw)
|
|
}
|
|
}
|
|
v := verify.(map[string]any)
|
|
if v["ok"] != true || v["deliveredMatchesRecorded"] != true || v["givenMatchesRecorded"] != true {
|
|
t.Errorf("verify said %v", v)
|
|
}
|
|
h := holders.(map[string]any)
|
|
if h["count"] != 1 {
|
|
t.Errorf("holders said %v", h)
|
|
}
|
|
if unknown.(map[string]any)["known"] != false {
|
|
t.Errorf("an unknown login said %v", unknown)
|
|
}
|
|
}
|
|
|
|
// The seat's verb, called as the runtime calls it: the caller is the one the runtime proved, never an
|
|
// argument.
|
|
func TestTheGetVerbTakesItsCallerFromTheRuntime(t *testing.T) {
|
|
v := newVault(t, AllowList{"g14.node-provisioner": {"pair/postgres/gitea"}})
|
|
if _, err := v.Put("pair/postgres/gitea", "x", "the test"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
asker, _ := seal.GenerateKeyPair()
|
|
get := toolNamed(t, definitions(&Env{Vault: v.Vault}), Seat+".get")
|
|
// No runtime proved a caller here, so the call is unproven whatever the arguments say.
|
|
if _, err := get.Run(map[string]any{"name": "pair/postgres/gitea", "public_key": asker.PublicKey, "caller": "g14.node-provisioner"}); err == nil {
|
|
t.Error("get answered a caller named in its arguments")
|
|
}
|
|
answer, err := get.runAs("g14.node-provisioner", map[string]any{"name": "pair/postgres/gitea", "public_key": asker.PublicKey})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
a := answer.(Answer)
|
|
if got, err := seal.Open(a.Sealed, asker.PrivateKey); err != nil || got != "x" {
|
|
t.Errorf("%q %v", got, err)
|
|
}
|
|
}
|
|
|
|
func contains(list []string, s string) bool {
|
|
for _, x := range list {
|
|
if x == s {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|