package v1 import ( "fmt" "net/http" "github.com/wild-cloud/wild-central/internal/config" ) // CertStatus returns the TLS certificate status for the central domain. func (api *API) CertStatus(w http.ResponseWriter, r *http.Request) { domain := api.getCentralDomain() if domain == "" { respondJSON(w, http.StatusOK, map[string]any{ "configured": false, "message": "No central domain configured", }) return } status := api.certbot.GetStatus(domain) respondJSON(w, http.StatusOK, map[string]any{ "configured": true, "domain": domain, "cert": status, }) } // CertProvision provisions a TLS certificate for the central domain using DNS-01. func (api *API) CertProvision(w http.ResponseWriter, r *http.Request) { domain := api.getCentralDomain() if domain == "" { respondError(w, http.StatusBadRequest, "No central domain configured in global config") return } globalCfg, err := config.LoadGlobalConfig(api.getGlobalConfigPath()) if err != nil { respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to load config: %v", err)) return } email := globalCfg.Operator.Email if email == "" { respondError(w, http.StatusBadRequest, "Operator email not configured") return } // Get Cloudflare API token token := api.getCloudflareToken() if token == "" { respondError(w, http.StatusBadRequest, "Cloudflare API token not configured — set it on the Cloudflare page") return } // Write credentials file for certbot if err := api.certbot.EnsureCredentials(token); err != nil { respondError(w, http.StatusInternalServerError, fmt.Sprintf("Failed to write credentials: %v", err)) return } // Provision the certificate. The deploy hook builds the HAProxy PEM and reloads HAProxy. if err := api.certbot.Provision(domain, email); err != nil { respondError(w, http.StatusInternalServerError, fmt.Sprintf("Certificate provisioning failed: %v", err)) return } // Regenerate HAProxy config to ensure central domain SNI routing is active if _, _, _, err := api.syncHAProxy(); err != nil { respondError(w, http.StatusInternalServerError, fmt.Sprintf("Certificate provisioned but HAProxy config update failed: %v", err)) return } status := api.certbot.GetStatus(domain) respondJSON(w, http.StatusOK, map[string]any{ "message": "Certificate provisioned successfully", "cert": status, }) } // CertRenew renews all certbot-managed certificates. func (api *API) CertRenew(w http.ResponseWriter, r *http.Request) { if err := api.certbot.Renew(); err != nil { respondError(w, http.StatusInternalServerError, fmt.Sprintf("Certificate renewal failed: %v", err)) return } // Rebuild HAProxy PEM for any renewed certs domain := api.getCentralDomain() if domain != "" { _ = api.certbot.BuildHAProxyCert(domain) _, _, _, _ = api.syncHAProxy() } respondJSON(w, http.StatusOK, map[string]string{"message": "Certificates renewed"}) } // getCentralDomain returns the configured central domain or empty string. func (api *API) getCentralDomain() string { globalCfg, err := config.LoadGlobalConfig(api.getGlobalConfigPath()) if err != nil { return "" } return globalCfg.Cloud.Central.Domain }