Files
mesh-controller/internal/broker/move_secrets_test.go
T
mesh-tools 97a2d841c7 Land feature 57's controller work on its release branch
The controller plans config, templates and moved providers' provisions,
hands bus accounts to the vault and judges the new manifest words, on the
feature's SDK and node-engine validator (feature 57, config and provisioning).
2026-10-15 21:27:33 +00:00

89 lines
3.4 KiB
Go

package broker
import (
"strings"
"testing"
)
// The move of the secrets into the vault (design 57's V3, issue 676): each machine's node-engine may ask the
// vault's move-in in its own name — the subject that names it, and no other machine's — once the vault's holder
// serves it; it hears the controller's ask to move a value on its own subject; and the controller may copy its
// record of asks with the vault's move-asks. Composed from the records: a vault that serves neither grants nothing.
func TestANodeEngineMayMoveItsSecretsIntoTheVaultInItsOwnName(t *testing.T) {
vault := Declared{Module: "mesh-vault", Holds: []Seat{{Name: "mesh-vault",
Serves: []string{"get", "accept", "secret-ask", "issued", "rotate", "move-in", "move-asks"}}}}
users, err := Users(Records{Nodes: []string{"anchor", "shanks"}, Assigned: map[string][]Declared{"anchor": {vault}}})
if err != nil {
t.Fatal(err)
}
var anchor, controller Principal
for _, u := range users {
switch {
case u.Kind == KindNode && u.Node == "anchor":
anchor = u
case u.Kind == KindController:
controller = u
}
}
p, err := PermissionsFor(anchor)
if err != nil {
t.Fatal(err)
}
if !MayPublish(p, CalledSubject("mesh.seat.mesh-vault.tool.move-in", "node.anchor")) {
t.Error("anchor's node-engine may not ask the vault's move-in in its own name")
}
for _, s := range []string{CalledSubject("mesh.seat.mesh-vault.tool.move-in", "node.shanks"),
CalledSubject("mesh.seat.mesh-vault.tool.move-in", ControllerName),
CalledSubject("mesh.seat.mesh-vault.tool.get", "node.anchor"),
CalledSubject("mesh.seat.mesh-vault.tool.accept", "node.anchor"),
"mesh.seat.mesh-vault.tool.move-in"} {
if MayPublish(p, s) {
t.Errorf("anchor's node-engine may publish %s", s)
}
}
if !MaySubscribe(p, AskMoveSecretSubject("anchor")) || MaySubscribe(p, AskMoveSecretSubject("shanks")) {
t.Error("anchor's node-engine does not hear its own move asks alone")
}
// The vault's holder hears the call naming the node-engine.
held := false
for _, u := range users {
if u.Kind == KindModule && u.Module == "mesh-vault" {
held = true
h, err := PermissionsFor(u)
if err != nil {
t.Fatal(err)
}
if !MaySubscribe(h, CalledSubject("mesh.seat.mesh-vault.tool.move-in", "node.anchor")) {
t.Error("the vault's holder does not hear move-in asked by a node-engine")
}
}
}
if !held {
t.Fatal("no principal holds the vault's seat")
}
c, err := PermissionsFor(controller)
if err != nil {
t.Fatal(err)
}
if !MayPublish(c, CalledSubject("mesh.seat.mesh-vault.tool.move-asks", ControllerName)) {
t.Error("the controller may not copy its record of asks into the vault")
}
if MayPublish(c, CalledSubject("mesh.seat.mesh-vault.tool.move-in", ControllerName)) {
t.Error("the controller may move a value in itself: it opens none")
}
if !MayPublish(c, AskMoveSecretSubject("anchor")) {
t.Error("the controller may not ask a machine's node-engine to move a value")
}
// A vault that serves neither, the running one: no grant for either.
older := Declared{Module: "mesh-vault", Holds: []Seat{{Name: "mesh-vault", Serves: []string{"get"}}}}
users, _ = Users(Records{Nodes: []string{"anchor"}, Assigned: map[string][]Declared{"anchor": {older}}})
for _, u := range users {
p, _ := PermissionsFor(u)
for _, s := range p.Publish {
if strings.Contains(s, "move-in") || strings.Contains(s, "move-asks") {
t.Errorf("%s may publish %s while the vault serves neither", u.Username(), s)
}
}
}
}