diff --git a/cmd/mesh-controller/foundation_scope_test.go b/cmd/mesh-controller/foundation_scope_test.go deleted file mode 100644 index 9ff8591..0000000 --- a/cmd/mesh-controller/foundation_scope_test.go +++ /dev/null @@ -1,33 +0,0 @@ -package main - -// The broker opening belongs only on the node that listens on it (novox/hq: it leaked onto -// every enrolled node's declaration, opening a from-anywhere hole for a port nothing there -// serves). foundationPortsFor is the scope. - -import ( - "testing" - - "github.com/novox/mesh-controller/internal/catalogue" -) - -func TestTheBrokerHostGetsTheFoundationOpening(t *testing.T) { - broker := catalogue.Manifest{Module: "lavinmq", Listens: []catalogue.Listening{ - {Port: 5671, Protocol: "tcp", From: "mesh"}, - {Port: 5672, Protocol: "tcp", From: "mesh"}, - }} - got := foundationPortsFor(5671, []catalogue.Manifest{broker}) - if len(got) != 1 || got[0] != 5671 { - t.Fatalf("the node that listens on the broker port keeps it; got %v", got) - } -} - -func TestANodeThatOnlyDialsTheBrokerGetsNoOpening(t *testing.T) { - // ace's set: things that reach the broker as a client, none listening on 5671. - ace := []catalogue.Manifest{ - {Module: "plex", Listens: []catalogue.Listening{{Port: 32400, Protocol: "tcp", From: "anywhere"}}}, - {Module: "postgres", Listens: []catalogue.Listening{{Port: 5432, Protocol: "tcp", From: "mesh"}}}, - } - if got := foundationPortsFor(5671, ace); got != nil { - t.Fatalf("a node that only dials out opens nothing for the broker; got %v", got) - } -} diff --git a/cmd/mesh-controller/plan.go b/cmd/mesh-controller/plan.go index 4eb5873..4300808 100644 --- a/cmd/mesh-controller/plan.go +++ b/cmd/mesh-controller/plan.go @@ -16,8 +16,6 @@ import ( "github.com/novox/mesh-controller/internal/inventory" "github.com/novox/mesh-controller/internal/licences" "github.com/novox/mesh-controller/internal/overlay" - "net" - "strconv" ) // working out what one machine should be. @@ -648,25 +646,12 @@ func renderingFor(ctx context.Context, open *stores, node string, names[name] = at } - // The ports the mesh itself needs open, which no module declares. Read from the broker this - // control plane was told about rather than written down twice: the address a node is handed in - // its token and the port its machine must accept on are the same fact. - // - // **Only on the node that listens on it** (novox/hq issue: the broker opening leaked onto - // every node). The opening exists to WIDEN the broker's port to from-anywhere — a machine - // enrolling is not on the mesh yet, so the broker's own `from: mesh` listen would refuse its - // first dial. That widening belongs on the broker's host and nowhere else: a node that only - // dials out needs no incoming rule, and an opening for a port nothing here listens on is a - // from-anywhere hole for a dead port. So the foundation port is kept only when a module - // resolved onto THIS node actually listens on it. + // **The bus is never public** (novox/hq ADR 0169). It was a foundation port — widened from the + // broker's own `from: mesh` to from-anywhere on the broker's host, so a machine could enrol + // before it had an address on the private network. A machine joins through the tunnel now, and + // every link to the bus crosses it, so its reach is what the `nats` module declares: the mesh. + // Nothing the mesh itself needs is opened beyond what a module declares. var foundation []int - if b, err := broker.FromEnvironment(); err == nil { - if _, port, err := net.SplitHostPort(b.Address); err == nil { - if n, err := strconv.Atoi(port); err == nil { - foundation = foundationPortsFor(n, plan.Modules) - } - } - } // And, for a module that keeps them, every operator-sealed secret in the mesh — the vault's // copy, outside the store (novox/hq ADR 0085, amended). Read only; nothing here mints. The @@ -1380,23 +1365,6 @@ func composeBusUsers(ctx context.Context, inv *inventory.Inventory, return broker.ComposeAccounts(filled) } -// foundationPortsFor is the broker port, kept only when a module resolved onto this node listens -// on it (novox/hq issue: the broker opening leaked onto every node). The foundation opening -// exists to WIDEN the broker's `from: mesh` port to from-anywhere, because a machine enrolling is -// not on the mesh yet and its first dial would be refused. That widening belongs on the broker's -// host alone: a node that only dials out needs no incoming rule, and an opening for a port -// nothing here listens on is a from-anywhere hole for a dead port. -func foundationPortsFor(brokerPort int, modules []catalogue.Manifest) []int { - for _, m := range modules { - for _, l := range m.Listens { - if l.Port == brokerPort { - return []int{brokerPort} - } - } - } - return nil -} - // providerModuleOf is which module answers a need on the providing node: the one in this node's // own set when the provider is here, else the one the catalogue says offers it. func providerModuleOf(resolved catalogue.Resolution, open *stores, ctx context.Context, n catalogue.Needed) string { diff --git a/internal/catalogue/the_bus_is_never_public_test.go b/internal/catalogue/the_bus_is_never_public_test.go new file mode 100644 index 0000000..84371ca --- /dev/null +++ b/internal/catalogue/the_bus_is_never_public_test.go @@ -0,0 +1,23 @@ +package catalogue + +import ( + "regexp" + "testing" +) + +// The bus is never public (novox/hq ADR 0169). Its port is what the bus module declares, the mesh, +// and the control plane adds no opening of its own: a machine joins through the tunnel, so the +// broker's host is filtered like any other. Before this, the broker port was a foundation port and +// rendered from anywhere beside its from-the-mesh rule. +func TestTheBusPortIsReachedFromTheMeshAlone(t *testing.T) { + rules := []Rule{{Port: 4222, Protocol: "tcp", From: FromMesh, Because: []string{"nats"}, + Why: []string{"the mesh bus"}}} + out := AsNftables(rules, []string{"10.10.0.1", "10.10.0.2"}, true, nil, []string{"eth0"}, "mesh0") + + if !regexp.MustCompile(`ip saddr \{ 10\.10\.0\.1, 10\.10\.0\.2 \} tcp dport 4222 accept`).MatchString(out) { + t.Fatalf("the bus is not reachable from the mesh:\n%s", out) + } + if regexp.MustCompile(`(?m)^\s*tcp dport 4222 accept`).MatchString(out) { + t.Fatalf("the bus is reachable from anywhere:\n%s", out) + } +}