fix(certmanager): use hostname as server cert CN instead of a random Bose domain

domains[0] was non-deterministic (Go map iteration) and could resolve to
any domain in the list including Bose-owned domains. Adds CommonName field
to CertificateManager, defaulting to "localhost", set to the device hostname
at startup. All Bose domains remain in the SAN where clients actually look.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Tobias Gesellchen
2026-05-03 21:15:48 +02:00
co-authored by Claude Sonnet 4.6
parent 84585b8034
commit f6e733de6b
3 changed files with 19 additions and 6 deletions
+8 -2
View File
@@ -387,7 +387,7 @@ func main() {
config.domains = getDomains(config.serverURL, config.httpsServerURL, hostname)
cm := initCertificateManager(config.dataDir)
cm := initCertificateManager(config.dataDir, config.hostname)
sm := setup.NewManager(config.serverURL, ds, cm)
sm.MgmtUsername = config.mgmtUsername
sm.MgmtPassword = config.mgmtPassword
@@ -469,12 +469,14 @@ func main() {
// TLS cert generation can be slow on constrained hardware; run it in the
// background so the HTTP server is available immediately.
log.Printf("HTTPS setup running in background; %s will be available shortly", config.httpsServerURL)
go func() {
tlsConfig, err := cm.GetServerTLSConfig(config.domains)
if err != nil {
log.Printf("Warning: Failed to setup TLS: %v", err)
return
}
startHTTPSServer(config.httpsAddr, r, tlsConfig, config.httpsServerURL)
}()
@@ -510,6 +512,7 @@ type serviceConfig struct {
bindAddr string
addr string
dataDir string
hostname string
serverURL string
httpsServerURL string
httpsAddr string
@@ -621,6 +624,7 @@ func loadConfig(c *cli.Context) serviceConfig {
bindAddr: bindAddr,
addr: addr,
dataDir: dataDir,
hostname: hostname,
serverURL: serverURL,
httpsServerURL: httpsServerURL,
httpsAddr: httpsAddr,
@@ -812,8 +816,10 @@ func initDataStore(dataDir string) *datastore.DataStore {
return ds
}
func initCertificateManager(dataDir string) *certmanager.CertificateManager {
func initCertificateManager(dataDir, hostname string) *certmanager.CertificateManager {
cm := certmanager.NewCertificateManager(filepath.Join(dataDir, "certs"))
cm.CommonName = hostname
if err := cm.EnsureCA(); err != nil {
log.Printf("Warning: Failed to ensure CA: %v", err)
}
+8 -2
View File
@@ -17,7 +17,8 @@ import (
// CertificateManager handles CA and certificate generation.
type CertificateManager struct {
CertsDir string
CertsDir string
CommonName string // CN for generated server certs; defaults to "localhost" if empty
}
// NewCertificateManager creates a new CertificateManager.
@@ -255,11 +256,16 @@ func (cm *CertificateManager) GenerateCertificate(domains []string) ([]byte, []b
}
}
cn := cm.CommonName
if cn == "" {
cn = "localhost"
}
template := x509.Certificate{
SerialNumber: serialNumber,
Subject: pkix.Name{
Organization: []string{"AfterTouch"},
CommonName: domains[0],
CommonName: cn,
},
NotBefore: notBefore,
NotAfter: notAfter,
+3 -2
View File
@@ -16,6 +16,7 @@ func TestCertificateManager(t *testing.T) {
defer os.RemoveAll(tempDir)
cm := NewCertificateManager(filepath.Join(tempDir, "certs"))
cm.CommonName = "test.local"
// Test CA generation
if err := cm.EnsureCA(); err != nil {
@@ -67,8 +68,8 @@ func TestCertificateManager(t *testing.T) {
t.Fatalf("Failed to parse certificate: %v", err)
}
if cert.Subject.CommonName != domains[0] {
t.Errorf("Expected CommonName %s, got %s", domains[0], cert.Subject.CommonName)
if cert.Subject.CommonName != cm.CommonName {
t.Errorf("Expected CommonName %s, got %s", cm.CommonName, cert.Subject.CommonName)
}
// Check DNS names