feat(client,cmd,mobile): connect securely via client.Connect(caPath)

client.Connect is the single migration seam: a non-empty caPath connects with
TLS pinned to the bus CA plus nkey auth (matching enforce + bus-tls), an empty
caPath keeps the legacy plaintext dev connection; control-plane requests are
signed either way. worker and chat gain a --ca flag; the gomobile NewSession
gains a caPath parameter so the Android app bundles ca.crt and connects
securely. Every peer now flows through one code path.

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 2ccd11b68c
commit 74c8d4f941
4 changed files with 41 additions and 17 deletions
+13 -12
View File
@@ -27,11 +27,12 @@ import (
func main() {
var (
natsURL = flag.String("nats-url", "nats://127.0.0.1:4250", "NATS url")
ctrlURL = flag.String("ctrl-url", "http://127.0.0.1:8470", "membershipd control-plane url")
roomSub = flag.String("room", "proc.test.ticks", "room subject to subscribe to")
idFile = flag.String("id-file", "./local_files/chat.id", "identity file path")
demoEnc = flag.Bool("demo-encrypted", false, "run the encrypted forward-secrecy demo")
natsURL = flag.String("nats-url", "nats://127.0.0.1:4250", "NATS url")
ctrlURL = flag.String("ctrl-url", "http://127.0.0.1:8470", "membershipd control-plane url")
roomSub = flag.String("room", "proc.test.ticks", "room subject to subscribe to")
idFile = flag.String("id-file", "./local_files/chat.id", "identity file path")
demoEnc = flag.Bool("demo-encrypted", false, "run the encrypted forward-secrecy demo")
caFile = flag.String("ca", "", "path to the bus CA cert (ca.crt); set to connect with TLS + nkey to a secured bus")
)
flag.Parse()
@@ -39,19 +40,19 @@ func main() {
log.SetPrefix("[chat] ")
if *demoEnc {
runEncryptedDemo(*natsURL, *ctrlURL)
runEncryptedDemo(*natsURL, *ctrlURL, *caFile)
return
}
runSimple(*natsURL, *ctrlURL, *roomSub, *idFile)
runSimple(*natsURL, *ctrlURL, *roomSub, *idFile, *caFile)
}
// runSimple subscribes to a cleartext subject and prints messages live.
func runSimple(natsURL, ctrlURL, roomSub, idFile string) {
func runSimple(natsURL, ctrlURL, roomSub, idFile, caFile string) {
id, err := client.LoadOrCreateIdentity(idFile)
if err != nil {
log.Fatalf("identity: %v", err)
}
c, err := client.New(natsURL, ctrlURL, id)
c, err := client.Connect(natsURL, ctrlURL, id, caFile)
if err != nil {
log.Fatalf("connect: %v", err)
}
@@ -91,7 +92,7 @@ func shortID(id string) string {
}
// runEncryptedDemo proves E2E encryption + forward secrecy end-to-end.
func runEncryptedDemo(natsURL, ctrlURL string) {
func runEncryptedDemo(natsURL, ctrlURL, caFile string) {
log.Printf("=== encrypted forward-secrecy demo ===")
pass := true
check := func(name string, ok bool) {
@@ -109,10 +110,10 @@ func runEncryptedDemo(natsURL, ctrlURL string) {
idB, err := newEphemeralIdentity()
must(err, "generate B identity")
a, err := client.New(natsURL, ctrlURL, idA)
a, err := client.Connect(natsURL, ctrlURL, idA, caFile)
must(err, "connect A")
defer a.Close()
b, err := client.New(natsURL, ctrlURL, idB)
b, err := client.Connect(natsURL, ctrlURL, idB, caFile)
must(err, "connect B")
defer b.Close()
+2 -1
View File
@@ -23,6 +23,7 @@ func main() {
ctrlURL = flag.String("ctrl-url", "http://127.0.0.1:8470", "membershipd control-plane url")
roomSub = flag.String("room", "proc.test.ticks", "room subject to publish to")
idFile = flag.String("id-file", "./local_files/worker.id", "identity file path")
caFile = flag.String("ca", "", "path to the bus CA cert (ca.crt); set to connect with TLS + nkey to a secured bus")
)
flag.Parse()
@@ -33,7 +34,7 @@ func main() {
if err != nil {
log.Fatalf("identity: %v", err)
}
c, err := client.New(*natsURL, *ctrlURL, id)
c, err := client.Connect(*natsURL, *ctrlURL, id, *caFile)
if err != nil {
log.Fatalf("connect: %v", err)
}