fix(cluster): Primary bidirektional in ha_nodes eintragen nach Join
Nach erfolgreichem cluster-join trägt der Joining-Node (utm-2) den Primary per DNS-Lookup in seine lokale ha_nodes ein und lädt nftables neu. Damit ist @peer_ipv4 auf utm-2 sofort mit utm-1's IP befüllt und Port 8443 ist bidirektional offen — der Aggregator auf utm-1 kann utm-2 auf :8443 abklappern. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -60,7 +60,7 @@ import (
|
||||
usersvc "git.netcell-it.de/projekte/edgeguard-native/internal/services/users"
|
||||
)
|
||||
|
||||
var version = "1.1.154"
|
||||
var version = "1.1.155"
|
||||
|
||||
func main() {
|
||||
addr := os.Getenv("EDGEGUARD_API_ADDR")
|
||||
@@ -276,6 +276,9 @@ func main() {
|
||||
"wireguard": wgrender.New(pool, secretsBox).RenderToString,
|
||||
})
|
||||
setupHdl.WithAudit(auditRepo, nodeID)
|
||||
setupHdl.WithClusterSupport(clusterStore, func(ctx context.Context) error {
|
||||
return firewallrender.New(pool).Render(ctx)
|
||||
})
|
||||
usersRepo := usersvc.New(pool)
|
||||
authHdl.WithAudit(auditRepo, nodeID).WithUsers(usersRepo)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"git.netcell-it.de/projekte/edgeguard-native/internal/services/setup"
|
||||
)
|
||||
|
||||
var version = "1.1.154"
|
||||
var version = "1.1.155"
|
||||
|
||||
const usage = `edgeguard-ctl — EdgeGuard CLI
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ import (
|
||||
"git.netcell-it.de/projekte/edgeguard-native/internal/services/tlscerts"
|
||||
)
|
||||
|
||||
var version = "1.1.154"
|
||||
var version = "1.1.155"
|
||||
|
||||
const (
|
||||
// renewTickInterval — how often we re-evaluate expiring certs.
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"git.netcell-it.de/projekte/edgeguard-native/internal/cluster"
|
||||
"git.netcell-it.de/projekte/edgeguard-native/internal/handlers/response"
|
||||
"git.netcell-it.de/projekte/edgeguard-native/internal/models"
|
||||
"git.netcell-it.de/projekte/edgeguard-native/internal/services/audit"
|
||||
"git.netcell-it.de/projekte/edgeguard-native/internal/services/clusterjoin"
|
||||
"git.netcell-it.de/projekte/edgeguard-native/internal/services/setup"
|
||||
@@ -15,10 +22,12 @@ import (
|
||||
// are mounted before SetupGate so they remain reachable while the API
|
||||
// is in setup mode.
|
||||
type SetupHandler struct {
|
||||
Store *setup.Store
|
||||
Audit *audit.Repo
|
||||
NodeID string
|
||||
Version string
|
||||
Store *setup.Store
|
||||
Audit *audit.Repo
|
||||
NodeID string
|
||||
Version string
|
||||
ClusterStore *cluster.Store
|
||||
PeerReloader PeerReloader
|
||||
}
|
||||
|
||||
func NewSetupHandler(store *setup.Store) *SetupHandler {
|
||||
@@ -40,6 +49,15 @@ func (h *SetupHandler) WithVersion(v string) *SetupHandler {
|
||||
return h
|
||||
}
|
||||
|
||||
// WithClusterSupport erlaubt dem JoinCluster-Handler nach dem Join den
|
||||
// Primary in der lokalen ha_nodes zu registrieren + nftables neu zu laden,
|
||||
// damit Port 8443 bidirektional offen ist.
|
||||
func (h *SetupHandler) WithClusterSupport(store *cluster.Store, reloader PeerReloader) *SetupHandler {
|
||||
h.ClusterStore = store
|
||||
h.PeerReloader = reloader
|
||||
return h
|
||||
}
|
||||
|
||||
func (h *SetupHandler) Register(rg *gin.RouterGroup) {
|
||||
g := rg.Group("/setup")
|
||||
g.GET("/status", h.Status)
|
||||
@@ -180,9 +198,55 @@ func (h *SetupHandler) JoinCluster(c *gin.Context) {
|
||||
response.Internal(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Pre-register the primary in our local ha_nodes so its IP lands in
|
||||
// @peer_ipv4 and port 8443 is open bidirectionally.
|
||||
if h.ClusterStore != nil && h.PeerReloader != nil {
|
||||
go h.preRegisterPrimary(body.PrimaryFQDN)
|
||||
}
|
||||
|
||||
response.OK(c, gin.H{
|
||||
"completed": st.Completed,
|
||||
"is_cluster_node": st.IsClusterNode,
|
||||
"fqdn": st.FQDN,
|
||||
})
|
||||
}
|
||||
|
||||
// preRegisterPrimary inserts the primary node into the local ha_nodes with
|
||||
// its resolved IP so nftables @peer_ipv4 allows port 8443 from the primary.
|
||||
func (h *SetupHandler) preRegisterPrimary(primaryFQDN string) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
primaryFQDN = strings.ToLower(strings.TrimSpace(primaryFQDN))
|
||||
|
||||
addrs, err := net.DefaultResolver.LookupHost(ctx, primaryFQDN)
|
||||
if err != nil || len(addrs) == 0 {
|
||||
slog.Warn("setup: could not resolve primary FQDN for pre-registration",
|
||||
"fqdn", primaryFQDN, "error", err)
|
||||
return
|
||||
}
|
||||
ip := addrs[0]
|
||||
|
||||
nodeID := fmt.Sprintf("primary-%x", time.Now().UnixNano())
|
||||
n := models.HANode{
|
||||
ID: nodeID,
|
||||
Name: primaryFQDN,
|
||||
FQDN: primaryFQDN,
|
||||
APIURL: "https://" + primaryFQDN + ":3443",
|
||||
Role: "primary",
|
||||
Status: "online",
|
||||
}
|
||||
n.PublicIP = &ip
|
||||
|
||||
if _, err := h.ClusterStore.UpsertSelf(ctx, n); err != nil {
|
||||
slog.Warn("setup: pre-register primary in ha_nodes failed", "fqdn", primaryFQDN, "error", err)
|
||||
return
|
||||
}
|
||||
if err := h.PeerReloader(ctx); err != nil {
|
||||
slog.Warn("setup: PeerReloader failed after primary pre-register", "error", err)
|
||||
return
|
||||
}
|
||||
slog.Info("setup: primary pre-registered locally, firewall updated",
|
||||
"fqdn", primaryFQDN, "ip", ip)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user