Archived
Ask a node's engine for a fresh setuid search at the terminal (hq issue 361)
After the operator removes by hand what the last search found, no apply says so and nothing searched again until the next day. node setuid-search <node> signs the ask as a hand-over is, under its own context, on a subject only the node's engine hears and only the controller may publish.
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
package link
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ed25519"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
|
||||
"github.com/novox/mesh-controller/internal/broker"
|
||||
"github.com/novox/mesh-controller/internal/testbus"
|
||||
)
|
||||
|
||||
// A fresh setuid search is asked of the machine on its own subject, signed under its own context — never a
|
||||
// hand-over's — naming no path, and the engine's answer comes back (novox/hq issue 361). The engine holds the
|
||||
// same subject and context (mesh-host internal/link, TestTheSetuidSearchAskKeepsItsSubjectAndContext).
|
||||
func TestASetuidSearchIsAskedOfTheMachineSignedUnderItsOwnContext(t *testing.T) {
|
||||
if broker.AskSetuidSearchSubject("laptop") != "mesh.node.laptop.ask.setuid-search" ||
|
||||
SetuidSearchContext != "novox-mesh setuid-search v1\n" {
|
||||
t.Fatalf("the subject %q, the context %q", broker.AskSetuidSearchSubject("laptop"), SetuidSearchContext)
|
||||
}
|
||||
conn, err := nats.Connect(testbus.URL(t))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(conn.Close)
|
||||
signer, public := testSigner(t)
|
||||
var heard HandOverAsk
|
||||
engine, err := conn.Subscribe(broker.AskSetuidSearchSubject("laptop"), func(msg *nats.Msg) {
|
||||
var signed SignedHandOver
|
||||
_ = json.Unmarshal(msg.Data, &signed)
|
||||
if ed25519.Verify(public, append([]byte(HandOverContext), signed.Ask...), signed.Signature) ||
|
||||
!ed25519.Verify(public, append([]byte(SetuidSearchContext), signed.Ask...), signed.Signature) {
|
||||
_ = msg.Respond([]byte(`{"refused":"not signed as a setuid search"}`))
|
||||
return
|
||||
}
|
||||
_ = json.Unmarshal(signed.Ask, &heard)
|
||||
body, _ := json.Marshal(HandOverAnswer{Said: "a new search starts, asked by " + heard.By})
|
||||
_ = msg.Respond(body)
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { _ = engine.Unsubscribe() })
|
||||
a, err := AskSetuidSearch(context.Background(), conn, signer, "laptop", "jo", 5*time.Second)
|
||||
if err != nil || a.Said != "a new search starts, asked by jo" {
|
||||
t.Fatalf("answered %+v, %v", a, err)
|
||||
}
|
||||
if heard.Node != "laptop" || heard.Path != "" || heard.Nonce == "" || heard.Expires.IsZero() {
|
||||
t.Fatalf("the engine heard %+v", heard)
|
||||
}
|
||||
if _, err := AskSetuidSearch(context.Background(), conn, signer, "anchor", "jo", 5*time.Second); err == nil ||
|
||||
!strings.Contains(err.Error(), "no search was started") {
|
||||
t.Fatalf("a machine with no engine listening: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user