route-proxy: placement is read through the module assigner's client, and a bus address is said without its credential by the proxy's own helper (N-1, ADR 0634 §4; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
// A message that says where the proxy could not connect never carries the account's password.
|
||||
func TestABusAddressIsSaidWithoutItsCredential(t *testing.T) {
|
||||
for in, want := range map[string]string{
|
||||
"nats://route-proxy:secret@127.0.0.1:4222": "nats://127.0.0.1:4222",
|
||||
"route-proxy:secret@127.0.0.1:4222": "127.0.0.1:4222",
|
||||
"nats://u:a@b@127.0.0.1:4222": "nats://127.0.0.1:4222", // the password holds an at-sign
|
||||
"nats://127.0.0.1:4222": "nats://127.0.0.1:4222",
|
||||
"127.0.0.1:4222": "127.0.0.1:4222",
|
||||
} {
|
||||
if got := bareAddress(in); got != want {
|
||||
t.Errorf("bareAddress(%q) = %q, want %q", in, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,11 +10,10 @@ import (
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
"git.novox.be/novox/mesh-contracts/provisioning/go/clients/meshprovisionerclient"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/announce"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
"git.novox.be/novox/mesh-sdk/go/membership"
|
||||
"git.novox.be/novox/mesh-sdk/go/process"
|
||||
|
||||
"route-proxy/contract"
|
||||
@@ -35,8 +34,8 @@ func keptStates() []announce.State {
|
||||
// **The routes are the seat mesh-provisioner's plans, alone** (issue 774, research 072 row 34): every plan's entry
|
||||
// naming this proxy as a route's provider, followed, so a route added or withdrawn reaches a running proxy without a
|
||||
// restart, and said on the bus as it changes (contract.EventServed, EventWithdrawn, EventRefused). **Who is inside**
|
||||
// is every node's address on the private network as the seat mesh-placement decides it (mesh-sdk
|
||||
// delivery.InsideAddresses), which is who may be served an internal name; until it is read, an internal name is
|
||||
// is every node's address on the private network as the seat mesh-placement decides it (the module assigner's
|
||||
// client, InsideAddresses), which is who may be served an internal name; until it is read, an internal name is
|
||||
// served to this machine alone.
|
||||
|
||||
// follow connects with the credential in path, follows the plans and the placement, and retries the connection for
|
||||
@@ -59,7 +58,7 @@ func followOnce(path string, held *table) error {
|
||||
}
|
||||
conn, err := process.Connect(account, nats.Name(account.Node+"."+account.Module))
|
||||
if err != nil {
|
||||
return fmt.Errorf("connecting to the bus at %s: %w", membership.BareAddress(account.URL), err)
|
||||
return fmt.Errorf("connecting to the bus at %s: %w", bareAddress(account.URL), err)
|
||||
}
|
||||
// What this proxy keeps, said on the bus (novox/hq ADR 0495; issue 774): the names it serves and the names it
|
||||
// refused, readable by any module granted a read of them; the provider helper's entries, read by the machines'
|
||||
@@ -75,8 +74,8 @@ func followOnce(path string, held *table) error {
|
||||
}
|
||||
}
|
||||
// Who is inside first, so the first table is served to the machines it is meant for.
|
||||
if err := followInside(conn.Read(delivery.PlacementRead), held); err != nil {
|
||||
log.Printf("cannot follow %s, so an internal name is served to this machine alone: %v", delivery.PlacementRead, err)
|
||||
if err := followInside(conn.Read(meshmoduleassignerclient.PlacementRead), held); err != nil {
|
||||
log.Printf("cannot follow %s, so an internal name is served to this machine alone: %v", meshmoduleassignerclient.PlacementRead, err)
|
||||
}
|
||||
if err := followPlans(conn.Read(meshprovisionerclient.PlansRead), newPlanned(account.Node, say), held, say); err != nil {
|
||||
conn.Close()
|
||||
@@ -160,14 +159,14 @@ func sortedNames(m map[string]contract.Event) []string {
|
||||
}
|
||||
|
||||
// followInside follows the seat mesh-placement's state and serves an internal name to every node's address on the
|
||||
// private network it decides, each time it changes (mesh-sdk delivery.InsideAddresses; research 072 rows 33 and 34:
|
||||
// private network it decides, each time it changes (the module assigner client's InsideAddresses; research 072 rows 33 and 34:
|
||||
// the membership that carried them went with the assignments stream). A key that does not read keeps who is inside
|
||||
// as it was.
|
||||
func followInside(placement planWatch, held *table) error {
|
||||
keys := delivery.NewPlacementKeys()
|
||||
keys := meshmoduleassignerclient.NewKeys()
|
||||
var read atomic.Bool
|
||||
apply := func() {
|
||||
inside, err := sourcesOf(delivery.InsideAddresses(keys.All()))
|
||||
inside, err := sourcesOf(meshmoduleassignerclient.InsideAddresses(keys.All()))
|
||||
if err != nil {
|
||||
log.Printf("the placement says an address that is not one, so who is inside stays as it was: %v", err)
|
||||
return
|
||||
@@ -192,3 +191,19 @@ func followInside(placement planWatch, held *table) error {
|
||||
apply()
|
||||
return nil
|
||||
}
|
||||
|
||||
// bareAddress is a bus address without the credential it may carry, `[scheme://]user:password@host:port`, for a message
|
||||
// that says where the proxy could not connect: the password is never written in a log. It splits on the last at-sign,
|
||||
// so a password holding one stays out whole. (Its only reader is this proxy: it was the SDK's membership package's,
|
||||
// which keeps the runtime's read of its own membership and nothing else.)
|
||||
func bareAddress(address string) string {
|
||||
at := strings.LastIndex(address, "@")
|
||||
if at < 0 {
|
||||
return address
|
||||
}
|
||||
scheme := ""
|
||||
if i := strings.Index(address[:at], "://"); i >= 0 {
|
||||
scheme = address[:i+3]
|
||||
}
|
||||
return scheme + address[at+1:]
|
||||
}
|
||||
|
||||
@@ -15,8 +15,9 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"git.novox.be/novox/mesh-contracts/placement/go/clients/meshmoduleassignerclient"
|
||||
seat "git.novox.be/novox/mesh-contracts/placement/go/seats/meshmoduleassigner"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
"git.novox.be/novox/mesh-sdk/go/delivery"
|
||||
|
||||
"route-proxy/contract"
|
||||
)
|
||||
@@ -305,7 +306,7 @@ func TestThePlansAreServedAndThePlacementSaysWhoIsInside(t *testing.T) {
|
||||
if code, _ := askFrom(held, "admin.anchor.internal", "10.10.0.7:1"); code != http.StatusNotFound {
|
||||
t.Errorf("before the placement is read, a machine of the mesh was served an internal-only name: %d", code)
|
||||
}
|
||||
laptop, err := delivery.PlacementValues(delivery.Placement{Node: "laptop", Decided: delivery.NodeDecided{Address: "10.10.0.7"}})
|
||||
laptop, err := meshmoduleassignerclient.PlacementValues(seat.Placement{V: meshmoduleassignerclient.Version, Node: "laptop", Decided: seat.NodeDecided{Address: "10.10.0.7"}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user