The catalogue's mesh-provisioner-client declares only provisioner-broker: the client speaks on the bus as itself. module issue refused it for lacking a broker, assign minted nothing, and push refused it for lacking an account, so no machine could run the client (issue 917).
93 lines
3.7 KiB
Go
93 lines
3.7 KiB
Go
package main
|
|
|
|
import (
|
|
"slices"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/novox/mesh-controller/internal/broker"
|
|
"github.com/novox/mesh-controller/internal/catalogue"
|
|
"github.com/novox/mesh-controller/internal/inventory"
|
|
)
|
|
|
|
func aProvisioner() catalogue.Manifest {
|
|
return catalogue.Manifest{Module: "mesh-provisioner", Version: "1",
|
|
DefinesSeats: []catalogue.SeatDeclaration{{Name: broker.NodeProvisionerSeat, Scope: catalogue.ScopeNode,
|
|
Serves: []catalogue.Verb{{Name: "get"}}}},
|
|
Claims: []catalogue.Claim{{Name: broker.NodeProvisionerSeat, Scope: catalogue.ScopeNode}},
|
|
OwnSecrets: catalogue.OwnSecrets{"broker": {Path: "/run/mesh-provisioner/broker"},
|
|
broker.ProvisionerSecret: {Path: "/run/mesh-provisioner/client"}},
|
|
}
|
|
}
|
|
|
|
// A machine's provisioner client is issued an account of its own, under its own name, sealed to the machine as the
|
|
// module's own secret its service reads (novox/hq ADR 0349 clause 11, design 57 P3); until it is, a push refuses
|
|
// to invent one, as it does for a module's `broker`.
|
|
func TestTheProvisionerClientsAccountIsIssuedForItsServiceAndNeverInvented(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
inv := open.inventory
|
|
m := aProvisioner()
|
|
register(t, open, m)
|
|
if _, err := assign(ctx, open, "laptop", m.Module); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := busCredentialIssued(ctx, inv, "laptop", m.Module, broker.ProvisionerSecret); err == nil {
|
|
t.Fatal("a push would seal a placeholder for the client's account before it was issued")
|
|
}
|
|
|
|
if err := issueProvisionerClient(ctx, inv, m, "laptop", broker.Broker{Fingerprint: "ab"}, "10.0.0.1:4222"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, minted, err := inv.BusUserHash(ctx, "provisioner.laptop"); err != nil || !minted {
|
|
t.Fatalf("the client's account is not minted: %v %v", minted, err)
|
|
}
|
|
states, err := inv.SecretsOf(ctx, "laptop", m.Module)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !slices.ContainsFunc(states, func(s inventory.SecretState) bool { return s.Name == broker.ProvisionerSecret }) {
|
|
t.Fatalf("the client's account is not sealed to the machine for its service: %+v", states)
|
|
}
|
|
if err := busCredentialIssued(ctx, inv, "laptop", m.Module, broker.ProvisionerSecret); err != nil {
|
|
t.Fatalf("an issued client account is refused: %v", err)
|
|
}
|
|
if !runsTheProvisionerClient(m) {
|
|
t.Fatal("the module is not read as running the client")
|
|
}
|
|
unread := m
|
|
unread.OwnSecrets = catalogue.OwnSecrets{"broker": {Path: "/run/broker"}}
|
|
if runsTheProvisionerClient(unread) {
|
|
t.Fatal("a module with nowhere to read the client's account is read as running it")
|
|
}
|
|
}
|
|
|
|
// A module that runs the client and declares no broker of its own, as the catalogue's mesh-provisioner-client does,
|
|
// may be issued: the client's account alone (issue 917). Before, `module issue` refused it for having no broker,
|
|
// while a push refused it for having no account, so no machine could run the client.
|
|
func TestAClientWithoutABrokerOfItsOwnMayBeIssued(t *testing.T) {
|
|
if err := mayIssue(aClientModule()); err != nil {
|
|
t.Fatalf("the client alone is refused an account: %v", err)
|
|
}
|
|
neither := aBot("bot", false)
|
|
if err := mayIssue(neither); err == nil {
|
|
t.Fatal("a module with nowhere to read any account may be issued one")
|
|
}
|
|
}
|
|
|
|
// Assigning the client tries to issue the client's account, as assigning any module issues its broker (issue 917):
|
|
// without a bus to issue on, the line says so and names the verb, never nothing.
|
|
func TestAssigningTheClientIssuesItsAccount(t *testing.T) {
|
|
open := aMesh(t)
|
|
ctx := t.Context()
|
|
client := aClientModule()
|
|
register(t, open, client)
|
|
out, err := assign(ctx, open, "laptop", client.Module)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(out, "bus credential") {
|
|
t.Fatalf("assigning the client said nothing of its account:\n%s", out)
|
|
}
|
|
}
|