93 lines
4.0 KiB
Go
93 lines
4.0 KiB
Go
package inventory
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/novox/mesh-controller/internal/broker"
|
|
"github.com/novox/mesh-controller/internal/catalogue"
|
|
)
|
|
|
|
// Reading the bus's user list out of the mesh's records, against a real store.
|
|
//
|
|
// What each of these is about is a user that would be **missing or wrong in a way nothing reports**:
|
|
// the server reads whatever file it is given, and a module whose user is absent fails on its first
|
|
// publish with an authorisation error that says nothing about a missing assignment.
|
|
|
|
func theSeatDeclarer() catalogue.Manifest {
|
|
return catalogue.Manifest{
|
|
Module: "telegram", Version: "1",
|
|
DefinesSeats: []catalogue.SeatDeclaration{{
|
|
Name: "telegram-sender", Accepts: []string{"send"}, Emits: []string{"delivered"},
|
|
}},
|
|
Claims: []catalogue.Claim{{Name: "telegram-sender", Scope: catalogue.ScopeMesh}},
|
|
}
|
|
}
|
|
|
|
// A module assigned to a machine becomes a user with the authority its manifest declared — and the
|
|
// protocol of a seat declared by a *different* module, which is the whole reason a seat exists.
|
|
|
|
// A machine holding a live token gets an enrolment user; one whose token is spent or expired does
|
|
// not. **An enrolment user outliving its token is a right to join that nobody issued.**
|
|
|
|
// A module assigned and absent from the catalogue is refused rather than composed with no authority.
|
|
//
|
|
// **The catalogue refuses to forget an assigned module, so this is the second line and not the
|
|
// first** — and it earns its place there: relying on another package's invariant is how a rule ends
|
|
// up enforced by nothing. Checked against the derivation directly, because the situation cannot be
|
|
// reached through the store.
|
|
func TestAnAssignmentWithNoManifestDerivesNoAuthority(t *testing.T) {
|
|
// What BusRecords would have produced had it composed a ghost: a module with nothing declared.
|
|
users, err := broker.Users(broker.Records{
|
|
Nodes: []string{"one"},
|
|
Assigned: map[string][]broker.Declared{"one": {{Module: "ghost"}}},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
perms, err := broker.PermissionsFor(users[len(users)-1])
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// Its inbox and its ack subject, and nothing it could say. That is a module which starts,
|
|
// connects, and is refused by the server on its first publish — an authorisation error that
|
|
// says nothing about a missing manifest, which is why BusRecords names it instead.
|
|
for _, p := range perms.Publish {
|
|
if strings.HasPrefix(p, "mesh.mod.ghost.event.") {
|
|
t.Fatalf("a module with no manifest was granted %s", p)
|
|
}
|
|
}
|
|
}
|
|
|
|
func granted(all []string, one string) bool {
|
|
for _, s := range all {
|
|
if s == one {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// **A token is an account on the bus, or it is a string nothing accepts** (novox/hq 04-ISSUES/146).
|
|
//
|
|
// The composed list names an enrolment user for every machine with a live token, and nothing minted
|
|
// a credential for it — so the composer left it out as a user with no password, and every enrolment
|
|
// since the mesh moved to this bus was refused by the server before the mesh heard of it. Nothing
|
|
// caught it because nothing had enrolled since.
|
|
//
|
|
// The password cannot be minted, because it is the token's own secret: the machine will present
|
|
// exactly that string. So this checks the two halves that make the account usable — that a row
|
|
// exists under the name the composer asks for, and that the secret handed out is what that row
|
|
// accepts.
|
|
|
|
// The module holding mesh-broker is the bus, and its user is the bus's own: granted the snapshot API
|
|
// for the night's backup and nothing else, whatever tools it declares (novox/hq ADR 0235). Another
|
|
// module on the same machine is granted none of it.
|
|
|
|
// The bar's holder reads the state the modules beside it offer in its blocks (novox/hq ADR 0255),
|
|
// without naming them: granted on the machine where both are, and nowhere else.
|
|
|
|
// A module running the machine's provisioner client gives that machine a client account of its own, apart from the
|
|
// module's and the tool runner's (novox/hq ADR 0349 clause 11, design 57 P3); one with nowhere to read the account
|
|
// gives none.
|