From e9515c1ddd2cf847c71e2f46f9cfd9c68d4a0f37 Mon Sep 17 00:00:00 2001 From: Boris Nagaev Date: Wed, 26 Nov 2025 13:54:35 -0300 Subject: [PATCH] aperture: filter empty TLS SAN hostnames Go 1.25 tightened x509 validation and now rejects empty dNSName entries, causing the default self-signed cert generation to fail when ServerName is left unset (`x509: SAN dNSName is malformed`). Filter out empty host names before calling cert.GenCertPair and reuse the same SAN list when renewing, allowing the default config to keep working. Add a unit test that reproduces the failure. --- aperture.go | 12 ++++++++++-- aperture_test.go | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 aperture_test.go diff --git a/aperture.go b/aperture.go index 3df9902..f87c398 100644 --- a/aperture.go +++ b/aperture.go @@ -693,7 +693,15 @@ func getTLSConfig(serverName, baseDir string, autoCert bool) ( // exist). tlsKeyFile := filepath.Join(apertureDir, defaultTLSKeyFilename) tlsCertFile := filepath.Join(apertureDir, defaultTLSCertFilename) - tlsExtraDomains := []string{serverName} + + // Go 1.25 tightened x509 SAN validation and now rejects empty dNSName + // entries (`x509: SAN dNSName is malformed`). When users rely on the + // default config (no server name), we still want to generate a usable + // self-signed cert, so we only append non-empty hostnames. + var tlsExtraDomains []string + if serverName != "" { + tlsExtraDomains = append(tlsExtraDomains, serverName) + } if !fileExists(tlsCertFile) && !fileExists(tlsKeyFile) { log.Infof("Generating TLS certificates...") certBytes, keyBytes, err := cert.GenCertPair( @@ -754,7 +762,7 @@ func getTLSConfig(serverName, baseDir string, autoCert bool) ( log.Infof("Renewing TLS certificates...") certBytes, keyBytes, err := cert.GenCertPair( - selfSignedCertOrganization, nil, nil, false, + selfSignedCertOrganization, nil, tlsExtraDomains, false, selfSignedCertValidity, ) if err != nil { diff --git a/aperture_test.go b/aperture_test.go new file mode 100644 index 0000000..a28e4f3 --- /dev/null +++ b/aperture_test.go @@ -0,0 +1,18 @@ +package aperture + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +// TestGetTLSConfigAllowsEmptyServerName ensures that generating a default +// self-signed TLS cert without a server name succeeds. This used to work +// before Go 1.25 tightened SAN validation, so we rely on Aperture handling it. +func TestGetTLSConfigAllowsEmptyServerName(t *testing.T) { + t.Parallel() + + cfg, err := getTLSConfig("", t.TempDir(), false) + require.NoError(t, err) + require.NotNil(t, cfg) +}