package process import ( "crypto/sha256" "crypto/tls" "crypto/x509" "encoding/hex" "errors" "fmt" "github.com/nats-io/nats.go" ) // Conn is one process's own connection to the bus (novox/hq ADR 0436 clause 4): dialled with the account // the controller delivered, pinned to its fingerprint, on its own inbox prefix. It offers no Serve and no // way to serve a tool — a process reaches the bus only as itself, and never answers a call. type Conn struct { nc *nats.Conn account Account } // Connect dials the bus with account: pinned to its fingerprint when it carries one (refused with any // other certificate), authenticated as its user and password, on the inbox prefix _INBOX. and no // other. Ported from mesh-controller internal/broker/jetstream.go:106-132 (DialPinned, // PinnedToFingerprint) since this package may not import the controller. func Connect(account Account, opts ...nats.Option) (*Conn, error) { all := []nats.Option{ nats.CustomInboxPrefix(account.InboxPrefix()), nats.UserInfo(account.User, account.Password), } if account.Fingerprint != "" { all = append(all, nats.Secure(pinnedToFingerprint(account.Fingerprint))) } all = append(all, opts...) nc, err := nats.Connect(account.URL, all...) if err != nil { return nil, fmt.Errorf("connecting the process account %s: %w", account.User, err) } return &Conn{nc: nc, account: account}, nil } // Close ends the connection. func (c *Conn) Close() { c.nc.Close() } // pinnedToFingerprint accepts exactly the certificate with this SHA-256 and no other — the leaf alone, its // name and chain deliberately not consulted, as mesh-controller's own pin does (jetstream.go:116-132). func pinnedToFingerprint(want string) *tls.Config { return &tls.Config{ InsecureSkipVerify: true, //nolint:gosec // replaced by the pin below, which is stricter MinVersion: tls.VersionTLS12, VerifyPeerCertificate: func(rawCerts [][]byte, _ [][]*x509.Certificate) error { if len(rawCerts) == 0 { return errors.New("the bus presented no certificate") } sum := sha256.Sum256(rawCerts[0]) got := "sha256:" + hex.EncodeToString(sum[:]) if got != want { return fmt.Errorf("the bus presented a certificate this mesh does not know (%s…), expected %s…", got[:23], want[:23]) } return nil }, } }