fix: Normalize wildcard domain paths for certbot cert storage
Certbot stores wildcard certs under the base domain (e.g., *.example.com → /etc/letsencrypt/live/example.com/), but the path helpers were using the raw wildcard domain. This caused deploy hooks to reference nonexistent paths, silently failing and leaving certs unrenewable.
This commit is contained in:
@@ -164,19 +164,26 @@ func parseCertOutput(output string, status *CertStatus) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// certName returns the name certbot uses to store a certificate.
|
||||||
|
// Certbot strips the "*." prefix from wildcard domains, so
|
||||||
|
// *.example.com is stored under "example.com".
|
||||||
|
func certName(domain string) string {
|
||||||
|
return strings.TrimPrefix(domain, "*.")
|
||||||
|
}
|
||||||
|
|
||||||
// CertPath returns the fullchain.pem path for a domain.
|
// CertPath returns the fullchain.pem path for a domain.
|
||||||
func CertPath(domain string) string {
|
func CertPath(domain string) string {
|
||||||
return fmt.Sprintf("/etc/letsencrypt/live/%s/fullchain.pem", domain)
|
return fmt.Sprintf("/etc/letsencrypt/live/%s/fullchain.pem", certName(domain))
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyPath returns the privkey.pem path for a domain.
|
// KeyPath returns the privkey.pem path for a domain.
|
||||||
func KeyPath(domain string) string {
|
func KeyPath(domain string) string {
|
||||||
return fmt.Sprintf("/etc/letsencrypt/live/%s/privkey.pem", domain)
|
return fmt.Sprintf("/etc/letsencrypt/live/%s/privkey.pem", certName(domain))
|
||||||
}
|
}
|
||||||
|
|
||||||
// HAProxyCertPath returns the combined PEM path for HAProxy TLS termination.
|
// HAProxyCertPath returns the combined PEM path for HAProxy TLS termination.
|
||||||
func HAProxyCertPath(domain string) string {
|
func HAProxyCertPath(domain string) string {
|
||||||
return fmt.Sprintf("/etc/haproxy/certs/%s.pem", domain)
|
return fmt.Sprintf("/etc/haproxy/certs/%s.pem", certName(domain))
|
||||||
}
|
}
|
||||||
|
|
||||||
// BuildHAProxyCert concatenates fullchain.pem + privkey.pem into a single PEM
|
// BuildHAProxyCert concatenates fullchain.pem + privkey.pem into a single PEM
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func TestHAProxyCertPath(t *testing.T) {
|
|||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{"example.com", "/etc/haproxy/certs/example.com.pem"},
|
{"example.com", "/etc/haproxy/certs/example.com.pem"},
|
||||||
{"*.example.com", "/etc/haproxy/certs/*.example.com.pem"},
|
{"*.example.com", "/etc/haproxy/certs/example.com.pem"},
|
||||||
{"sub.example.com", "/etc/haproxy/certs/sub.example.com.pem"},
|
{"sub.example.com", "/etc/haproxy/certs/sub.example.com.pem"},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@@ -34,15 +34,31 @@ func TestHAProxyCertPath(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCertPaths(t *testing.T) {
|
func TestCertPaths(t *testing.T) {
|
||||||
domain := "example.com"
|
tests := []struct {
|
||||||
certPath := CertPath(domain)
|
domain string
|
||||||
keyPath := KeyPath(domain)
|
wantCert string
|
||||||
|
wantKey string
|
||||||
if certPath != "/etc/letsencrypt/live/example.com/fullchain.pem" {
|
}{
|
||||||
t.Errorf("CertPath = %q", certPath)
|
{
|
||||||
|
"example.com",
|
||||||
|
"/etc/letsencrypt/live/example.com/fullchain.pem",
|
||||||
|
"/etc/letsencrypt/live/example.com/privkey.pem",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"*.example.com",
|
||||||
|
"/etc/letsencrypt/live/example.com/fullchain.pem",
|
||||||
|
"/etc/letsencrypt/live/example.com/privkey.pem",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
if keyPath != "/etc/letsencrypt/live/example.com/privkey.pem" {
|
for _, tt := range tests {
|
||||||
t.Errorf("KeyPath = %q", keyPath)
|
certPath := CertPath(tt.domain)
|
||||||
|
keyPath := KeyPath(tt.domain)
|
||||||
|
if certPath != tt.wantCert {
|
||||||
|
t.Errorf("CertPath(%q) = %q, want %q", tt.domain, certPath, tt.wantCert)
|
||||||
|
}
|
||||||
|
if keyPath != tt.wantKey {
|
||||||
|
t.Errorf("KeyPath(%q) = %q, want %q", tt.domain, keyPath, tt.wantKey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user