internal/honeypot/http/https.go

package http

import (
	"context"
	"crypto/tls"
	"fmt"
	"net/http"

	"honeypot/internal/logger"
	tlscert "honeypot/internal/tls"
)

// startHTTPSServer starts an HTTPS server that serves the same content as the HTTP server.
func (h *httpHoneypot) startHTTPSServer(ctx context.Context, mux *http.ServeMux, port uint16, selfSignedCert *tls.Certificate) error {
	// selfSignedCert should already be generated and passed in from Start()
	// This ensures all HTTPS servers share the same certificate to avoid serial number conflicts

	tlsConfig, err := h.createTLSConfig(selfSignedCert, ctx)
	if err != nil {
		return err
	}
	if tlsConfig == nil {
		return nil // No TLS config available
	}

	httpsServer := h.createServer(mux, port, tlsConfig)

	h.logServerStart(ctx, port, "https")
	h.setupGracefulShutdown(ctx, httpsServer)

	if err := httpsServer.ListenAndServeTLS("", ""); err != nil && err != http.ErrServerClosed {
		logger.LogError(h.logger, HoneypotType, "https_server_failed", err, nil)
		return err
	}

	logger.LogInfo(h.logger, HoneypotType, "honeypot shutdown complete", []any{
		"port", port,
	})
	return nil
}

// generateSelfSignedCert generates a self-signed TLS certificate.
// Always generates a certificate to use as fallback for IP addresses and missing server names.
func (h *httpHoneypot) generateSelfSignedCert(ctx context.Context) (*tls.Certificate, error) {
	cert, err := tlscert.GenerateSelfSignedCert(h.config.ListenAddr, h.config.CertConfig, h.logger)
	if err != nil {
		return nil, err
	}
	logger.LogInfo(h.logger, HoneypotType, "generated self-signed TLS certificate", nil)
	return cert, nil
}

// createTLSConfig creates the TLS configuration based on available certificates.
// selfSignedCert is always generated, so it should never be nil.
func (h *httpHoneypot) createTLSConfig(selfSignedCert *tls.Certificate, ctx context.Context) (*tls.Config, error) {
	if selfSignedCert == nil {
		logger.LogError(h.logger, HoneypotType, "no_tls_config", nil, []any{
			"message", "HTTPS port is set but certificate generation failed",
		})
		return nil, fmt.Errorf("self-signed certificate generation failed")
	}

	logger.LogInfo(h.logger, HoneypotType, "using self-signed certificate for TLS", nil)
	return &tls.Config{
		Certificates: []tls.Certificate{*selfSignedCert},
		MinVersion:   tls.VersionTLS12,
	}, nil
}