Prove on a real bus the controller asks mesh-config in its own name (issue 925)
mesh/merge-gate head b12755c16313 merged into trunk ead062569ed3 — pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus…
mesh/repo-check head b12755c16313 merged into trunk ead062569ed3 — pass: its merge-check.sh passed
mesh/delivery delivered
mesh/merge-gate head b12755c16313 merged into trunk ead062569ed3 — pass: builds build-agent, mesh-controller, route-proxy → ace, g14, novox, shanks; no bus…
mesh/repo-check head b12755c16313 merged into trunk ead062569ed3 — pass: its merge-check.sh passed
mesh/delivery delivered
This commit is contained in:
@@ -160,3 +160,87 @@ func TestNatsOnlyMeshConfigsAccountPutsToItsBuckets(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// **The controller asks mesh-config's `config` in its own name** (issue 925): on a real server whose users are
|
||||
// composed from records that hold mesh-config on novox serving `config`, the controller's request on
|
||||
// `mesh.seat.mesh-config.call.config.controller` reaches mesh-config's account and its reply reaches the
|
||||
// controller's inbox; the same request under another caller's name is refused by the server.
|
||||
func TestNatsTheControllerAsksMeshConfigInItsOwnName(t *testing.T) {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte("pw"), bcrypt.MinCost)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
seat := Seat{Name: "mesh-config", Scope: "mesh", Serves: []string{"config"}}
|
||||
users, err := Users(Records{Nodes: []string{"novox"}, Assigned: map[string][]Declared{
|
||||
"novox": {{Module: RuntimeModule}, {Module: "mesh-config", RunsAs: "mesh-config", Holds: []Seat{seat}}},
|
||||
}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i := range users {
|
||||
users[i].PasswordHash = string(hash)
|
||||
}
|
||||
accounts, err := ComposeAccounts(users)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
conf := filepath.Join(t.TempDir(), "bus.conf")
|
||||
if err := os.WriteFile(conf, []byte("listen: 127.0.0.1:-1\n"+accounts), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
opts, err := server.ProcessConfigFile(conf)
|
||||
if err != nil {
|
||||
t.Fatalf("the composed accounts do not parse: %v", err)
|
||||
}
|
||||
opts.NoLog, opts.NoSigs = true, true
|
||||
s, err := server.NewServer(opts)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
go s.Start()
|
||||
if !s.ReadyForConnections(10 * time.Second) {
|
||||
t.Fatal("the bus did not come up")
|
||||
}
|
||||
t.Cleanup(s.Shutdown)
|
||||
connect := func(user string) (*nats.Conn, chan error) {
|
||||
t.Helper()
|
||||
refused := make(chan error, 8)
|
||||
nc, err := nats.Connect(s.ClientURL(), nats.UserInfo(user, "pw"), nats.CustomInboxPrefix("_INBOX."+user),
|
||||
nats.ErrorHandler(func(_ *nats.Conn, _ *nats.Subscription, err error) { refused <- err }))
|
||||
if err != nil {
|
||||
t.Fatalf("%s cannot connect: %v", user, err)
|
||||
}
|
||||
t.Cleanup(nc.Close)
|
||||
return nc, refused
|
||||
}
|
||||
owner, _ := connect("novox.mesh-config")
|
||||
subject := CalledSubject("mesh.seat.mesh-config.tool.config", ControllerName)
|
||||
if subject != "mesh.seat.mesh-config.call.config.controller" {
|
||||
t.Fatalf("the subject is %s", subject)
|
||||
}
|
||||
if _, err := owner.Subscribe("mesh.seat.mesh-config.call.config.*", func(m *nats.Msg) {
|
||||
_ = m.Respond([]byte(`{"ok":true}`))
|
||||
}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := owner.Flush(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
controller, refused := connect(ControllerName)
|
||||
reply, err := controller.Request(subject, []byte(`{"action":"set"}`), 5*time.Second)
|
||||
if err != nil || string(reply.Data) != `{"ok":true}` {
|
||||
t.Fatalf("the controller's own-name request got %v (%v), want mesh-config's reply", reply, err)
|
||||
}
|
||||
if err := controller.Publish(CalledSubject("mesh.seat.mesh-config.tool.config", "anchor.node-tools"), nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_ = controller.Flush()
|
||||
select {
|
||||
case err := <-refused:
|
||||
if !errors.Is(err, nats.ErrPermissionViolation) {
|
||||
t.Errorf("the server said %v, want a permissions violation", err)
|
||||
}
|
||||
case <-time.After(3 * time.Second):
|
||||
t.Error("the server did not refuse the controller a request in another's name")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user