63 lines
2.5 KiB
Go
63 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"slices"
|
|
"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")
|
|
}
|
|
}
|