A tool's grant covers the machine-addressed subject, and a credential names the seats its module claims (ADR 0159) #185
@@ -584,16 +584,25 @@ func issueOnTheNewBus(ctx context.Context, inv *inventory.Inventory, m catalogue
|
||||
// (`rollout mint`, design 28 task 5.2) rather than the one in this process's environment.
|
||||
func issueWith(ctx context.Context, inv *inventory.Inventory, m catalogue.Manifest,
|
||||
node, busAddress string, known broker.Broker, reachable, user, password string) error {
|
||||
// The seats this module claims, with the verbs each promises (novox/hq ADR 0159): the runtime
|
||||
// serves a claimed seat's verbs with its tools of the same name, and the bus admits only the
|
||||
// holder's subscription — so the runtime tries each claim and the grant decides. Written here
|
||||
// because this file is the one thing the mesh writes that the runtime reads before it speaks.
|
||||
claims, err := claimsFor(ctx, inv, m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
held, err := json.Marshal(struct {
|
||||
URL string `json:"url"`
|
||||
Fingerprint string `json:"fingerprint,omitempty"`
|
||||
Node string `json:"node"`
|
||||
Module string `json:"module"`
|
||||
User string `json:"user"`
|
||||
Password string `json:"password"`
|
||||
URL string `json:"url"`
|
||||
Fingerprint string `json:"fingerprint,omitempty"`
|
||||
Node string `json:"node"`
|
||||
Module string `json:"module"`
|
||||
User string `json:"user"`
|
||||
Password string `json:"password"`
|
||||
Claims []seatClaimed `json:"claims,omitempty"`
|
||||
}{
|
||||
URL: "nats://" + reachable, Fingerprint: known.Fingerprint,
|
||||
Node: node, Module: m.Module, User: user, Password: password,
|
||||
Node: node, Module: m.Module, User: user, Password: password, Claims: claims,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -680,3 +689,36 @@ func namesNoInstallation(m catalogue.Manifest) error {
|
||||
"on purpose under %s with its reason, or take it out:\n - %s",
|
||||
m.Module, catalogue.NamesOnPurpose, strings.Join(named, "\n - "))
|
||||
}
|
||||
|
||||
// seatClaimed is one seat a module claims, as its runtime needs it: the name, the scope (a
|
||||
// node-scoped seat's verb carries the machine, design 33 §4) and the verbs the seat promises.
|
||||
type seatClaimed struct {
|
||||
Seat string `json:"seat"`
|
||||
Scope string `json:"scope"`
|
||||
Serves []string `json:"serves,omitempty"`
|
||||
}
|
||||
|
||||
// claimsFor joins a module's claims with the seats' protocols from the mesh's records.
|
||||
func claimsFor(ctx context.Context, inv *inventory.Inventory, m catalogue.Manifest) ([]seatClaimed, error) {
|
||||
if len(m.Claims) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
seats, err := inv.Seats(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
byName := map[string]catalogue.Seat{}
|
||||
for _, s := range seats {
|
||||
byName[s.Name] = s
|
||||
}
|
||||
var out []seatClaimed
|
||||
for _, c := range m.Claims {
|
||||
claimed := seatClaimed{Seat: c.Name, Scope: c.At()}
|
||||
if s, known := byName[c.Name]; known {
|
||||
claimed.Scope = s.Scope
|
||||
claimed.Serves = catalogue.VerbNames(s.Serves)
|
||||
}
|
||||
out = append(out, claimed)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
@@ -91,3 +91,16 @@ func TestADeclaredInvokeReachesTheComposedUser(t *testing.T) {
|
||||
}
|
||||
has(t, perms.Publish, "mesh.mod.*.tool.>")
|
||||
}
|
||||
|
||||
// A module's tool is addressed two ways (novox/hq ADR 0159): to whichever instance answers, and to
|
||||
// the instance on one machine. A grant for the tool covers both and nothing wider.
|
||||
func TestInvokingAToolMayAddressTheMachineToo(t *testing.T) {
|
||||
got, err := invokedSubjects([]string{"postgres.postgres_query"})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
want := []string{"mesh.mod.postgres.tool.postgres_query", "mesh.mod.postgres.tool.postgres_query.*"}
|
||||
if len(got) != 2 || got[0] != want[0] || got[1] != want[1] {
|
||||
t.Fatalf("the grant is %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -660,7 +660,10 @@ func invokedSubjects(invokes []string) ([]string, error) {
|
||||
return nil, fmt.Errorf(
|
||||
"%q does not name a tool: one invokes <module>.<tool>, seat:<seat>.<verb>, or * for every one", t)
|
||||
}
|
||||
out = append(out, "mesh.mod."+module+".tool."+tool)
|
||||
// Both ways a module's tool is addressed (novox/hq ADR 0159): to whichever instance
|
||||
// answers, and to the instance on one machine, which is the same subject with the machine
|
||||
// as its last token.
|
||||
out = append(out, "mesh.mod."+module+".tool."+tool, "mesh.mod."+module+".tool."+tool+".*")
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user