package letsencrypt
import (
internalcertapi "envoy-control-plane/internal/pkg/cert/api"
"fmt"
"github.com/go-acme/lego/v4/certificate"
"github.com/go-acme/lego/v4/registration"
)
// ------------------------------------------------------------------------------------------------
// RenewCertificate renews an existing certificate using go-acme/lego.
func (l *LetsEncryptIssuer) RenewCertificate(oldCert *internalcertapi.Certificate, webrootPath string, email string) (*internalcertapi.Certificate, error) {
// FIX 1: Load the ACME Account Private Key from the D-value stored in AccountKey.
acmePrivateKey, err := loadACMEKeyFromDValue(oldCert.AccountKey)
if err != nil {
return nil, fmt.Errorf("failed to load ACME account key: %w", err)
}
// 2. Setup ACME User (LEOptions) with the loaded account key
acmeUser := &LEOptions{
Email: email,
key: acmePrivateKey,
// FIX 2: Provide the Registration URI (KID) to the client for JWS signing.
// ASSUMPTION: The stored oldCert.AccountURL contains the ACME account URI (KID).
Registration: ®istration.Resource{
URI: oldCert.AccountURL,
},
}
// 3. Configure and create the ACME client
client, err := createClient(acmeUser, webrootPath, l.UseStaging)
if err != nil {
return nil, err
}
// 4. Reconstruct the certificate.Resource for renewal
certResource := certificate.Resource{
Domain: oldCert.Domain,
Certificate: oldCert.CertPEM,
// The PrivateKey here is the DOMAIN's old private key.
PrivateKey: oldCert.KeyPEM,
}
// 5. Renew the certificate
newCertResources, err := client.Certificate.Renew(certResource, false, false, "")
if err != nil {
return nil, fmt.Errorf("failed to renew certificate: %w", err)
}
// 6. Map the results
return &internalcertapi.Certificate{
Domain: oldCert.Domain,
CertPEM: newCertResources.Certificate,
// The renewed key (newCertResources.PrivateKey) is the domain's NEW private key.
KeyPEM: newCertResources.PrivateKey,
FullChain: newCertResources.Certificate,
// The ACME account key and URL remain the same.
AccountKey: oldCert.AccountKey,
AccountURL: oldCert.AccountURL,
}, nil
}