Guard HTTP to HTTPS IP certificate staging

This commit is contained in:
Codex committed 2026-10-26 15:37:11 +08:00
1 parent d3699abb18
commit 3c76d2d118
3 files changed
+30 -2

No files matched your search

+18
View File
@@ -172,6 +172,24 @@ func (s *Server) setTLSDomain(c *gin.Context) {
c.JSON(http.StatusConflict, gin.H{"error": err.Error()})
return
}
// A plain HTTP site can stage HTTPS on the same host before a certificate
// exists. The explicit activation action sets up HTTP-01, issues the
// certificate and only then replaces the live site.
if actual.Scheme == "http" && scheme == "https" && actual.Domain == strings.ToLower(strings.TrimSpace(req.Domain)) && !nginxgateway.CertificateReady(actual.Domain) {
if !tlsservice.ValidDomain(actual.Domain) {
if err := nginxgateway.CheckIPCertificateSupport(actual.Domain); err != nil {
c.JSON(http.StatusPreconditionFailed, gin.H{"error": err.Error()})
return
}
}
if err := tlsservice.ConfigurePublicEntry(service.BaseDir(), scheme, req.Domain, port); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
store.Audit(c.GetString("username"), "tls_domain_staged", newBase, "待签发证书并启用 HTTPS")
c.JSON(http.StatusOK, gin.H{"status": tlsservice.Status(), "site_activation_required": true})
return
}
authPort, err := authGatewayPort(newBase)
if err != nil {
c.JSON(http.StatusConflict, gin.H{"error": err.Error()})
+10
View File
@@ -348,6 +348,16 @@ func certificateExists(domain string) bool {
!time.Now().Before(leaf.NotBefore) && time.Now().Before(leaf.NotAfter)
}
// CertificateReady checks that the installed leaf is valid for the target host.
func CertificateReady(host string) bool { return certificateExists(host) }
// CheckIPCertificateSupport fails before changing a live site when the
// Certbot service cannot issue and renew a short-lived IP certificate.
func CheckIPCertificateSupport(host string) error {
_, err := ipCertificateArgs(host)
return err
}
func ipCertificateArgs(domain string) ([]string, error) {
// The scheduled systemd service on supported hosts must use the same Certbot
// binary as interactive issuance, or six-day certificates may expire.