|
|
@@ -28,6 +28,14 @@ import (
|
|
|
"github.com/go-acme/lego/v4/registration"
|
|
|
)
|
|
|
|
|
|
+// http01Port is the port for HTTP-01 challenge server
|
|
|
+// Nginx on port 80 should proxy .well-known/acme-challenge/ requests to this port
|
|
|
+var http01Port = "8082"
|
|
|
+
|
|
|
+func SetHTTP01Port(port string) {
|
|
|
+ http01Port = port
|
|
|
+}
|
|
|
+
|
|
|
type ACMEAccount struct {
|
|
|
Email string
|
|
|
PrivateKey crypto.PrivateKey
|
|
|
@@ -79,7 +87,9 @@ func GetACMECertificate(cert *config.Certificate, cfg *config.Config) error {
|
|
|
return fmt.Errorf("failed to set DNS-01 provider: %v", err)
|
|
|
}
|
|
|
} else {
|
|
|
- if err := client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "80")); err != nil {
|
|
|
+ // Use HTTP-01 challenge with the configured port
|
|
|
+ // Nginx on port 80 proxies .well-known/acme-challenge/ to this port
|
|
|
+ if err := client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", http01Port)); err != nil {
|
|
|
return fmt.Errorf("failed to set HTTP-01 provider: %v", err)
|
|
|
}
|
|
|
}
|
|
|
@@ -145,22 +155,33 @@ func RenewCertificate(cert *config.Certificate, cfg *config.Config) error {
|
|
|
return fmt.Errorf("failed to set DNS-01 provider: %v", err)
|
|
|
}
|
|
|
} else {
|
|
|
- if err := client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", "80")); err != nil {
|
|
|
+ // Use HTTP-01 challenge with the configured port
|
|
|
+ if err := client.Challenge.SetHTTP01Provider(http01.NewProviderServer("", http01Port)); err != nil {
|
|
|
return fmt.Errorf("failed to set HTTP-01 provider: %v", err)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // Load existing certificate files for renewal
|
|
|
+ certDir := filepath.Join(cfg.CertDir, sanitizeDomain(cert.Domain))
|
|
|
+ existingCert, err := os.ReadFile(filepath.Join(certDir, "fullchain.pem"))
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("failed to read existing certificate for renewal: %v", err)
|
|
|
+ }
|
|
|
+ existingKey, err := os.ReadFile(filepath.Join(certDir, "privkey.pem"))
|
|
|
+ if err != nil {
|
|
|
+ return fmt.Errorf("failed to read existing private key for renewal: %v", err)
|
|
|
+ }
|
|
|
+
|
|
|
certRes, err := client.Certificate.Renew(certificate.Resource{
|
|
|
Domain: cert.Domain,
|
|
|
CertURL: cert.CertURL,
|
|
|
- PrivateKey: nil,
|
|
|
- Certificate: nil,
|
|
|
+ PrivateKey: existingKey,
|
|
|
+ Certificate: existingCert,
|
|
|
}, true, false, "")
|
|
|
if err != nil {
|
|
|
return fmt.Errorf("failed to renew certificate: %v", err)
|
|
|
}
|
|
|
|
|
|
- certDir := filepath.Join(cfg.CertDir, sanitizeDomain(cert.Domain))
|
|
|
os.MkdirAll(certDir, 0700)
|
|
|
os.WriteFile(filepath.Join(certDir, "fullchain.pem"), certRes.Certificate, 0644)
|
|
|
os.WriteFile(filepath.Join(certDir, "privkey.pem"), certRes.PrivateKey, 0600)
|
|
|
@@ -186,6 +207,34 @@ func GetCertFilesPaths(domain string, cfg *config.Config) (fullchain, privkey, c
|
|
|
filepath.Join(dir, "chain.pem")
|
|
|
}
|
|
|
|
|
|
+// GetCertFileContents reads and returns certificate file contents
|
|
|
+func GetCertFileContents(domain string, cfg *config.Config) (fullchain, privkey, chain string) {
|
|
|
+ fc, pk, ch := GetCertFilesPaths(domain, cfg)
|
|
|
+
|
|
|
+ data, err := os.ReadFile(fc)
|
|
|
+ if err != nil {
|
|
|
+ fullchain = ""
|
|
|
+ } else {
|
|
|
+ fullchain = string(data)
|
|
|
+ }
|
|
|
+
|
|
|
+ data, err = os.ReadFile(pk)
|
|
|
+ if err != nil {
|
|
|
+ privkey = ""
|
|
|
+ } else {
|
|
|
+ privkey = string(data)
|
|
|
+ }
|
|
|
+
|
|
|
+ data, err = os.ReadFile(ch)
|
|
|
+ if err != nil {
|
|
|
+ chain = ""
|
|
|
+ } else {
|
|
|
+ chain = string(data)
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
func getOrCreateAccount(email, provider, dir string) (*ACMEAccount, error) {
|
|
|
keyFile := filepath.Join(dir, "account.key")
|
|
|
regFile := filepath.Join(dir, "registration.json")
|
|
|
@@ -293,7 +342,7 @@ func getDNSProvider(cert *config.Certificate) (challenge.Provider, error) {
|
|
|
return provider, nil
|
|
|
|
|
|
default:
|
|
|
- return nil, fmt.Errorf("unsupported DNS provider: %s", dnsCfg.Provider)
|
|
|
+ return nil, fmt.Errorf("unsupported DNS provider: %s", cert.DNSProvider)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -318,6 +367,6 @@ func sanitizeDomain(domain string) string {
|
|
|
}
|
|
|
|
|
|
// lego User interface implementation
|
|
|
-func (a *ACMEAccount) GetEmail() string { return a.Email }
|
|
|
+func (a *ACMEAccount) GetEmail() string { return a.Email }
|
|
|
func (a *ACMEAccount) GetRegistration() *registration.Resource { return a.Registration }
|
|
|
-func (a *ACMEAccount) GetPrivateKey() crypto.PrivateKey { return a.PrivateKey }
|
|
|
+func (a *ACMEAccount) GetPrivateKey() crypto.PrivateKey { return a.PrivateKey }
|