A seat's protocol lives in the store (migration 0047; seeded additively), a served verb carries its description and schema, holding a mesh seat requires serving its verbs, a node-scoped seat's tool carries the node, and the control plane serves status, nodes, node, modules, seats, builds, plan, assign, unassign, push, build and tools on its seat by running the same commands (novox/hq ADR 0132, ADR 0154, design 33). A grant of * reaches a role's tools; seat:<seat>.<verb> grants one.
58 lines
2.9 KiB
Go
58 lines
2.9 KiB
Go
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")
|
|
}
|
|
}
|