package broker import "testing" // A node-scoped seat's tool carries the node (novox/hq ADR 0132, design 33 ยง4): two nodes holding one // node-scoped seat derive two addresses, and a user of the seat may publish any node's. func TestTwoNodesHoldingOneNodeSeatDeriveTwoToolAddresses(t *testing.T) { seat := Seat{Name: "node-dns-resolver", Scope: "node", Serves: []string{"lookup"}} one, _ := PermissionsFor(Principal{Kind: KindModule, Node: "one", Module: "dnsmasq", Holds: []Seat{seat}, PasswordHash: "x"}) two, _ := PermissionsFor(Principal{Kind: KindModule, Node: "two", Module: "dnsmasq", Holds: []Seat{seat}, PasswordHash: "x"}) has(t, one.Subscribe, "mesh.seat.node-dns-resolver.tool.lookup.one") has(t, two.Subscribe, "mesh.seat.node-dns-resolver.tool.lookup.two") hasNot(t, one.Subscribe, "mesh.seat.node-dns-resolver.tool.lookup") hasNot(t, one.Subscribe, "mesh.seat.node-dns-resolver.tool.lookup.two") user, _ := PermissionsFor(Principal{Kind: KindModule, Node: "three", Module: "asker", Uses: []Seat{seat}, PasswordHash: "x"}) has(t, user.Publish, "mesh.seat.node-dns-resolver.tool.lookup.*") } // A mesh-scoped seat's tool stays flat: nothing about it changes. func TestAMeshSeatsToolIsAddressedToTheSeatAlone(t *testing.T) { seat := Seat{Name: "git", Scope: "mesh", Serves: []string{"list_repos"}} holder, _ := PermissionsFor(Principal{Kind: KindModule, Node: "one", Module: "gitea", Holds: []Seat{seat}, PasswordHash: "x"}) has(t, holder.Subscribe, "mesh.seat.git.tool.list_repos") user, _ := PermissionsFor(Principal{Kind: KindModule, Node: "two", Module: "asker", Uses: []Seat{seat}, PasswordHash: "x"}) has(t, user.Publish, "mesh.seat.git.tool.list_repos") } // The controller serves its own seat's verbs and may answer them (novox/hq ADR 0154). func TestTheControllerServesItsSeatsToolsAndMayAnswer(t *testing.T) { perms, err := PermissionsFor(Principal{Kind: KindController, PasswordHash: "x"}) if err != nil { t.Fatal(err) } has(t, perms.Subscribe, "mesh.seat.mesh-controller.tool.>") if !perms.AllowResponses { t.Fatal("the controller serves tools and may not answer one") } } // A grant to every tool reaches a role's tools too, and a role's tool is granted by name. func TestAGrantReachesARolesTools(t *testing.T) { all, _ := PermissionsFor(Principal{Kind: KindModule, Node: "desk", Module: "mesh-console", Invokes: []string{"*"}, PasswordHash: "x"}) has(t, all.Publish, "mesh.seat.*.tool.>") one, err := PermissionsFor(Principal{Kind: KindPerson, Module: "jo", Invokes: []string{"seat:mesh-controller.status"}, PasswordHash: "x"}) if err != nil { t.Fatal(err) } has(t, one.Publish, "mesh.seat.mesh-controller.tool.status") hasNot(t, one.Publish, "mesh.seat.mesh-controller.tool.push") hasNot(t, one.Publish, "mesh.mod.*.tool.>") if _, err := PermissionsFor(Principal{Kind: KindPerson, Module: "jo", Invokes: []string{"seat:mesh-controller"}, PasswordHash: "x"}); err == nil { t.Fatal("a role grant naming no verb was accepted") } }