package main import ( "fmt" cs "fn-registry/functions/cybersecurity" "github.com/enmanuel/unibus/pkg/busauth" "github.com/nats-io/nats.go" "github.com/nats-io/nats.go/jetstream" server "github.com/nats-io/nats-server/v2/server" ) // connectInternalJS opens a privileged JetStream client from membershipd to its // OWN embedded NATS server. This is the resolution of the "bootstrap cycle" // (issue 0006a/c): the service needs JetStream to create the replicated nonce // bucket and the control-plane KV, but under enforce the data plane only accepts // allowlisted clients confined to their rooms. The connection therefore // authenticates with the process's ephemeral internal identity — the identity the // authenticator was built to recognize (NewNkeyAuthenticatorACLInternal) and // grant full permissions — without ever appearing in the user allowlist. // // It uses the in-process transport (nats.InProcessServer), a Go pipe inside the // process, so it bypasses TLS entirely: no CA wiring is needed for this // self-connection even when the public data plane is TLS-only. useNkey mirrors // whether the embedded server enforces auth: under enforce the internal identity // presents its nkey; without enforce the server accepts an unauthenticated // in-process client and the nkey is omitted. // // The caller owns the returned connection and must Close it on shutdown (after // the JetStream context is no longer used). func connectInternalJS(ns *server.Server, internalID cs.Identity, useNkey bool) (*nats.Conn, jetstream.JetStream, error) { opts := []nats.Option{ nats.Name("membershipd-internal"), nats.InProcessServer(ns), } if useNkey { pub, sign, err := busauth.ClientNkey(internalID.SignPriv) if err != nil { return nil, nil, fmt.Errorf("internal nkey: %w", err) } opts = append(opts, nats.Nkey(pub, sign)) } // The URL is ignored for an in-process connection; the InProcessServer option // supplies the transport. nc, err := nats.Connect("", opts...) if err != nil { return nil, nil, fmt.Errorf("connect internal nats: %w", err) } js, err := jetstream.New(nc) if err != nil { nc.Close() return nil, nil, fmt.Errorf("internal jetstream: %w", err) } return nc, js, nil } // connectExternalJS opens a JetStream client to an EXTERNAL NATS the operator // runs (membershipd started with --nats-url). Unlike the embedded path there is // no in-process transport and no internal identity: the external server enforces // its own auth, so membershipd connects as a plain client (optionally TLS-pinned // to the bus CA). It is best-effort and intended for an operator-managed cluster; // the standard unibus deploy uses the embedded server (connectInternalJS). func connectExternalJS(natsURL, caPath string) (*nats.Conn, jetstream.JetStream, error) { opts := []nats.Option{nats.Name("membershipd-internal")} if caPath != "" { tlsCfg, err := busauth.LoadCATLSConfig(caPath) if err != nil { return nil, nil, fmt.Errorf("load CA %q: %w", caPath, err) } opts = append(opts, nats.Secure(tlsCfg)) } nc, err := nats.Connect(natsURL, opts...) if err != nil { return nil, nil, fmt.Errorf("connect external nats %q: %w", natsURL, err) } js, err := jetstream.New(nc) if err != nil { nc.Close() return nil, nil, fmt.Errorf("external jetstream: %w", err) } return nc, js, nil }