mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-08-24 00:14:39 +00:00
Scope cluster TLS fingerprints to their own endpoints (#1199)
This commit is contained in:
parent
2acf2e9ef9
commit
ffaeea18d6
2 changed files with 47 additions and 7 deletions
|
|
@ -586,13 +586,13 @@ func ensureClusterEndpointURL(raw string) string {
|
|||
return "https://" + net.JoinHostPort(value, "8006")
|
||||
}
|
||||
|
||||
func clusterEndpointEffectiveURL(endpoint config.ClusterEndpoint, verifySSL bool, baseFingerprint string) string {
|
||||
// When TLS hostname verification is required (VerifySSL=true and no fingerprint),
|
||||
// prefer hostname over IP to ensure certificate CN/SAN validation works correctly.
|
||||
// When TLS is not verified (VerifySSL=false) or a fingerprint is provided (which
|
||||
// bypasses hostname checks), prefer IP to reduce DNS lookups (refs #620).
|
||||
hasFingerprint := strings.TrimSpace(endpoint.Fingerprint) != "" || strings.TrimSpace(baseFingerprint) != ""
|
||||
requiresHostnameForTLS := verifySSL && !hasFingerprint
|
||||
func clusterEndpointEffectiveURL(endpoint config.ClusterEndpoint, verifySSL bool, _ string) string {
|
||||
// A fingerprint only applies to the specific endpoint it was captured from.
|
||||
// The primary node's fingerprint must not be treated as valid for every
|
||||
// cluster member, otherwise we incorrectly route to per-node IPs while
|
||||
// pinning the wrong certificate. Refs: #1199
|
||||
hasEndpointFingerprint := strings.TrimSpace(endpoint.Fingerprint) != ""
|
||||
requiresHostnameForTLS := verifySSL && !hasEndpointFingerprint
|
||||
|
||||
// Use EffectiveIP() which prefers user-specified IPOverride over auto-discovered IP
|
||||
effectiveIP := endpoint.EffectiveIP()
|
||||
|
|
|
|||
|
|
@ -173,6 +173,11 @@ func TestClusterEndpointEffectiveURL(t *testing.T) {
|
|||
t.Fatalf("per-endpoint fingerprint should allow IP override, got %q", got)
|
||||
}
|
||||
|
||||
endpoint.Fingerprint = ""
|
||||
if got := clusterEndpointEffectiveURL(endpoint, true, "cluster-base-fingerprint"); got != "https://node.local:8006" {
|
||||
t.Fatalf("base fingerprint must not force IP routing for other cluster nodes, got %q", got)
|
||||
}
|
||||
|
||||
endpoint = config.ClusterEndpoint{}
|
||||
if got := clusterEndpointEffectiveURL(endpoint, true, ""); got != "" {
|
||||
t.Fatalf("empty endpoint = %q, want empty", got)
|
||||
|
|
@ -209,3 +214,38 @@ func TestBuildClusterClientEndpoints_PrefersOverrideWhenEndpointFingerprintPrese
|
|||
t.Fatalf("expected fingerprint to follow effective endpoint URL, got %q", fingerprints["https://10.15.2.11:8006"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildClusterClientEndpoints_FallsBackToMainHostWhenOnlyBaseFingerprintExists(t *testing.T) {
|
||||
pve := config.PVEInstance{
|
||||
Name: "cluster-a",
|
||||
Host: "https://cluster-a.example.com:8006",
|
||||
Fingerprint: "cluster-base-fp",
|
||||
VerifySSL: true,
|
||||
IsCluster: true,
|
||||
ClusterName: "cluster-a",
|
||||
ClusterEndpoints: []config.ClusterEndpoint{
|
||||
{
|
||||
NodeName: "node1",
|
||||
Host: "node1",
|
||||
IP: "10.15.5.11",
|
||||
},
|
||||
{
|
||||
NodeName: "node2",
|
||||
Host: "node2",
|
||||
IP: "10.15.5.12",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
endpoints, fingerprints := buildClusterClientEndpoints(pve)
|
||||
|
||||
if len(endpoints) != 1 {
|
||||
t.Fatalf("expected only the main host fallback endpoint, got %d", len(endpoints))
|
||||
}
|
||||
if endpoints[0] != "https://cluster-a.example.com:8006" {
|
||||
t.Fatalf("expected main host fallback, got %q", endpoints[0])
|
||||
}
|
||||
if len(fingerprints) != 0 {
|
||||
t.Fatalf("expected no per-endpoint fingerprints, got %v", fingerprints)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue