test(client): secure bus end-to-end (auth + TLS + E2E together)

TestSecureBusEndToEnd boots the server with control-plane enforce, NATS nkey
auth, and TLS all on; two registered peers connect with nkey+TLS, A creates a
Matrix room, invites B, publishes, and B decrypts — proving the three layers
compose. This is the headline golden of issue 0001.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-07 12:49:19 +02:00
parent 6b0916f1fa
commit 04e27518af
+72
View File
@@ -7,13 +7,16 @@ import (
"crypto/tls"
"crypto/x509"
"crypto/x509/pkix"
"encoding/hex"
"encoding/pem"
"math/big"
"net"
"sync"
"testing"
"time"
"github.com/enmanuel/unibus/pkg/client"
"github.com/enmanuel/unibus/pkg/frame"
"github.com/enmanuel/unibus/pkg/membership"
"github.com/enmanuel/unibus/pkg/room"
)
@@ -111,3 +114,72 @@ func TestNatsTLS(t *testing.T) {
t.Fatalf("client without the CA must fail the TLS handshake")
}
}
// TestSecureBusEndToEnd is the headline golden of issue 0001: with ALL three
// layers active at once — control-plane request signing (enforce), NATS nkey
// auth, and TLS — two registered peers run an encrypted room end to end. A
// creates a Matrix-policy room, invites B, A publishes and B decrypts. This
// proves the layers compose: signed HTTP control plane + authenticated,
// encrypted data plane + E2E room content.
func TestSecureBusEndToEnd(t *testing.T) {
serverTLS, caPool := genTestCA(t)
h := bootHarness(t, membership.AuthEnforce, true, serverTLS)
waitHealth(t, h.ctrlURL)
clientTLS := &tls.Config{RootCAs: caPool, MinVersion: tls.VersionTLS12}
secure := func(t *testing.T, handle string) (*client.Client, membership.AuthMode) {
id := mustIdentity(t)
if err := h.store.AddUser(hex.EncodeToString(id.SignPub), handle, membership.RoleMember); err != nil {
t.Fatalf("register %s: %v", handle, err)
}
c, err := client.NewWithOptions(h.natsURL, h.ctrlURL, id, client.Options{UseNkey: true, TLS: clientTLS})
if err != nil {
t.Fatalf("connect %s securely: %v", handle, err)
}
return c, 0
}
a, _ := secure(t, "alice")
defer a.Close()
b, _ := secure(t, "bob")
defer b.Close()
roomID, err := a.CreateRoom("room.secure", room.ModeMatrix)
if err != nil {
t.Fatalf("A create encrypted room over secure bus: %v", err)
}
if err := a.Invite(roomID, b.Endpoint()); err != nil {
t.Fatalf("A invite B: %v", err)
}
if err := b.Join(roomID); err != nil {
t.Fatalf("B join: %v", err)
}
var mu sync.Mutex
var got []string
sub, err := b.Subscribe(roomID, func(_ frame.Frame, plaintext []byte) {
mu.Lock()
got = append(got, string(plaintext))
mu.Unlock()
})
if err != nil {
t.Fatalf("B subscribe: %v", err)
}
defer sub.Unsubscribe()
time.Sleep(150 * time.Millisecond)
const msg = "mensaje sobre bus seguro (auth+TLS+E2E)"
if err := a.Publish(roomID, []byte(msg)); err != nil {
t.Fatalf("A publish: %v", err)
}
if !waitFor(&mu, &got, func(rs []string) bool {
for _, r := range rs {
if r == msg {
return true
}
}
return false
}, 2*time.Second) {
t.Fatalf("B did not receive/decrypt the message over the secured bus; got %v", snapshot(&mu, &got))
}
}