//go:build integration package process import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/sha256" "crypto/tls" "crypto/x509" "crypto/x509/pkix" "encoding/hex" "math/big" "testing" "time" "github.com/nats-io/nats-server/v2/server" ) // selfSignedServer is a nats-server with JetStream and TLS, self-signed, for this test alone (mirroring // go/internal/testbus.Start, with a certificate added since testbus has none): a mesh's bus presents its own // certificate in no public trust store, which is exactly what a process pins to (ADR 0436 clause 4). func selfSignedServer(t *testing.T) (url, fingerprint string) { t.Helper() key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { t.Fatal(err) } tmpl := &x509.Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{CommonName: "mesh-sdk-test-bus"}, NotBefore: time.Now().Add(-time.Hour), NotAfter: time.Now().Add(time.Hour), KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, } der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key) if err != nil { t.Fatal(err) } sum := sha256.Sum256(der) fingerprint = "sha256:" + hex.EncodeToString(sum[:]) cert := tls.Certificate{Certificate: [][]byte{der}, PrivateKey: key} opts := &server.Options{Host: "127.0.0.1", Port: server.RANDOM_PORT, JetStream: true, StoreDir: t.TempDir(), NoLog: true, NoSigs: true, TLSConfig: &tls.Config{Certificates: []tls.Certificate{cert}}, Username: "novox.mesh-mail.send", Password: "the-pw"} s, err := server.NewServer(opts) if err != nil { t.Fatalf("a TLS bus for this test could not be made: %v", err) } go s.Start() if !s.ReadyForConnections(10 * time.Second) { s.Shutdown() t.Fatal("a TLS bus for this test did not come up within 10s") } t.Cleanup(func() { s.Shutdown() s.WaitForShutdown() }) return s.ClientURL(), fingerprint } func mailSenderAccount(url, fingerprint string) Account { return Account{URL: url, Fingerprint: fingerprint, Node: "novox", Module: "mesh-mail", User: "novox.mesh-mail.send", Password: "the-pw"} } // 1171/AC3: given a test bus with TLS and the account composed for novox.mesh-mail.send, when the package // connects with the file, then it connects with the inbox prefix _INBOX.novox.mesh-mail.send. func TestConnectPinsTheFingerprintAndSetsTheInboxPrefix(t *testing.T) { url, fingerprint := selfSignedServer(t) account := mailSenderAccount(url, fingerprint) conn, err := Connect(account) if err != nil { t.Fatalf("connecting with the right fingerprint was refused: %v", err) } defer conn.Close() if !conn.nc.IsConnected() { t.Fatal("the connection did not come up") } if got := conn.nc.Opts.InboxPrefix; got != "_INBOX.novox.mesh-mail.send" { t.Errorf("inbox prefix: %q, want %q", got, "_INBOX.novox.mesh-mail.send") } } // 1171/AC3: connecting with a fingerprint that is not the bus's own leaf certificate is refused. func TestConnectRefusesTheWrongFingerprint(t *testing.T) { url, _ := selfSignedServer(t) account := mailSenderAccount(url, "sha256:0000000000000000000000000000000000000000000000000000000000000000") if _, err := Connect(account); err == nil { t.Fatal("connecting with the wrong fingerprint was not refused") } }