package busauth import ( "crypto/ecdsa" "crypto/elliptic" "crypto/rand" "crypto/x509" "crypto/x509/pkix" "encoding/pem" "math/big" "os" "path/filepath" "testing" "time" ) // writeSelfSigned writes a self-signed cert + key PEM pair to dir and returns // their paths. It is enough to exercise both LoadCATLSConfig (reads the cert as // a CA) and ServerTLSConfig (reads the cert+key as a server keypair). func writeSelfSigned(t *testing.T, dir string) (certPath, keyPath string) { t.Helper() key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) if err != nil { t.Fatalf("key: %v", err) } tmpl := &x509.Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{CommonName: "unibus-tls-test"}, NotBefore: time.Now().Add(-time.Hour), NotAfter: time.Now().Add(time.Hour), IsCA: true, KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature, BasicConstraintsValid: true, } der, err := x509.CreateCertificate(rand.Reader, tmpl, tmpl, &key.PublicKey, key) if err != nil { t.Fatalf("cert: %v", err) } certPath = filepath.Join(dir, "cert.pem") keyPath = filepath.Join(dir, "key.pem") certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: der}) if err := os.WriteFile(certPath, certPEM, 0o644); err != nil { t.Fatalf("write cert: %v", err) } keyDER, err := x509.MarshalECPrivateKey(key) if err != nil { t.Fatalf("marshal key: %v", err) } keyPEM := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: keyDER}) if err := os.WriteFile(keyPath, keyPEM, 0o600); err != nil { t.Fatalf("write key: %v", err) } return certPath, keyPath } // Golden: a valid CA PEM loads into a config with a non-empty RootCAs pool, and // a valid keypair loads into a config presenting one certificate. func TestLoadTLSConfigsGolden(t *testing.T) { dir := t.TempDir() certPath, keyPath := writeSelfSigned(t, dir) caCfg, err := LoadCATLSConfig(certPath) if err != nil { t.Fatalf("LoadCATLSConfig: %v", err) } if caCfg.RootCAs == nil { t.Fatalf("expected a populated RootCAs pool") } srvCfg, err := ServerTLSConfig(certPath, keyPath) if err != nil { t.Fatalf("ServerTLSConfig: %v", err) } if len(srvCfg.Certificates) != 1 { t.Fatalf("expected exactly one server certificate, got %d", len(srvCfg.Certificates)) } } // Error path: missing file, and a file that is not valid PEM. func TestLoadTLSConfigsErrors(t *testing.T) { if _, err := LoadCATLSConfig("/no/such/ca.crt"); err == nil { t.Fatalf("expected error for missing CA file") } dir := t.TempDir() junk := filepath.Join(dir, "junk.crt") if err := os.WriteFile(junk, []byte("not a pem"), 0o644); err != nil { t.Fatalf("write junk: %v", err) } if _, err := LoadCATLSConfig(junk); err == nil { t.Fatalf("expected error for non-PEM CA file") } if _, err := ServerTLSConfig("/no/such/server.crt", "/no/such/server.key"); err == nil { t.Fatalf("expected error for missing server keypair") } }