Files
unibus/pkg/busauth/tls.go
T
egutierrez 2786ae2dde feat(busauth,client): pin the bus CA over TLS
busauth.LoadCATLSConfig turns a ca.crt path into a *tls.Config trusting only
that private CA (clients must pin it; the system roots would reject a
self-signed server cert). busauth.ServerTLSConfig loads the server keypair.
client.Options gains TLS; NewWithOptions calls nats.Secure when set, so the
data-plane connection is encrypted and the server pinned.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 12:44:13 +02:00

38 lines
1.4 KiB
Go

package busauth
import (
"crypto/tls"
"crypto/x509"
"fmt"
"os"
)
// LoadCATLSConfig builds a *tls.Config that trusts ONLY the given CA certificate
// (PEM file), for a bus client pinning the project's self-signed CA. Because the
// bus uses a private CA rather than a public one, clients must pin it explicitly;
// trusting the system roots would reject the server cert. This is the single
// helper every client (Go peers, the mobile binding, the gateway) uses to turn a
// ca.crt path into a connection config.
func LoadCATLSConfig(caPEMPath string) (*tls.Config, error) {
pem, err := os.ReadFile(caPEMPath)
if err != nil {
return nil, fmt.Errorf("busauth: read CA %q: %w", caPEMPath, err)
}
pool := x509.NewCertPool()
if !pool.AppendCertsFromPEM(pem) {
return nil, fmt.Errorf("busauth: CA %q contains no valid PEM certificate", caPEMPath)
}
return &tls.Config{RootCAs: pool, MinVersion: tls.VersionTLS12}, nil
}
// ServerTLSConfig loads the bus NATS server's certificate and private key (PEM
// files) into a *tls.Config to present to clients. The private key never leaves
// the host; only the CA cert travels to clients.
func ServerTLSConfig(certPEMPath, keyPEMPath string) (*tls.Config, error) {
cert, err := tls.LoadX509KeyPair(certPEMPath, keyPEMPath)
if err != nil {
return nil, fmt.Errorf("busauth: load server keypair: %w", err)
}
return &tls.Config{Certificates: []tls.Certificate{cert}, MinVersion: tls.VersionTLS12}, nil
}