mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-10 02:25:56 +00:00
fix(monitoring): preserve custom bridge link evidence
Limit automatic Docker bridge filtering to the generated br-<12 hex> convention so custom management bridges such as br-mgmt remain eligible for host association. Keep docker-prefixed and non-global-unicast exclusions intact. Change-source: pulse-maintainer
This commit is contained in:
@@ -21,10 +21,12 @@ Host ingestion must not create a host-to-PVE or reciprocal PVE-to-agent link
|
||||
solely from a shared host-local network address. Uniqueness among monitored
|
||||
PVE nodes does not establish uniqueness across unrelated agent hosts.
|
||||
Automatic network evidence excludes loopback, unspecified, multicast and
|
||||
link-local IPs, and interfaces named lo or prefixed docker/br-. This changes
|
||||
association evidence only: enrollment, token binding, removal, re-enrollment
|
||||
and command authority remain unchanged. It does not migrate or repair
|
||||
persisted incorrect links.
|
||||
link-local IPs, interfaces named lo or prefixed docker, and Docker-generated
|
||||
bridge names matching `br-` plus a 12-character hexadecimal network ID. Other
|
||||
bridge names remain eligible because they may carry management traffic. This
|
||||
changes association evidence only: enrollment, token binding, removal,
|
||||
re-enrollment and command authority remain unchanged. It does not migrate or
|
||||
repair persisted incorrect links.
|
||||
|
||||
Verification: `TestApplyHostReportDoesNotLinkUnrelatedDockerBridge` in
|
||||
`internal/monitoring/monitor_host_agents_test.go` ingests repeated synthetic
|
||||
|
||||
@@ -19,14 +19,15 @@
|
||||
|
||||
### Host-local addresses are not PVE identity
|
||||
|
||||
Automatic host/PVE network matching excludes non-global-unicast addresses
|
||||
and lo/docker*/br-* interfaces from both reported-host and provider-node
|
||||
address inventories. A Docker bridge address seen on only one PVE node can
|
||||
still exist on an unrelated NAS; provider-only owner counts cannot make it
|
||||
machine identity. Management bridges such as vmbr0, unnamed legacy interfaces,
|
||||
private IPv4 and IPv6/ULA remain eligible. Explicit unicast report-IP hints
|
||||
remain eligible independently of inferred interface evidence. No blanket
|
||||
private-subnet exclusion is permitted.
|
||||
Automatic host/PVE network matching excludes non-global-unicast addresses,
|
||||
lo/docker* interfaces and Docker-generated `br-` plus 12-hex-character bridge
|
||||
names from both reported-host and provider-node address inventories. A Docker
|
||||
bridge address seen on only one PVE node can still exist on an unrelated NAS;
|
||||
provider-only owner counts cannot make it machine identity. Management bridges
|
||||
such as vmbr0 and br-mgmt, unnamed legacy interfaces, private IPv4 and IPv6/ULA
|
||||
remain eligible. Explicit unicast report-IP hints remain eligible independently
|
||||
of inferred interface evidence. No blanket private-subnet exclusion is
|
||||
permitted.
|
||||
|
||||
Verification in `internal/monitoring/monitor_host_agents_test.go`:
|
||||
`TestFindLinkedProxmoxEntityWithHints_RejectsHostLocalNetworkIdentity` covers
|
||||
|
||||
@@ -4400,11 +4400,27 @@ func normalizeAgentLinkIP(address string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Do not discard all bridges: Proxmox management addresses commonly use vmbr0.
|
||||
// Explicit report-IP and endpoint hints remain usable for routable addresses.
|
||||
// Do not discard all bridges: Proxmox management addresses commonly use vmbr0,
|
||||
// and operators may use names such as br-mgmt. Docker's automatically named
|
||||
// user-defined bridges use br- followed by the first 12 hex characters of the
|
||||
// network ID. Explicit report-IP and endpoint hints remain usable for routable
|
||||
// addresses.
|
||||
func isHostLocalAgentLinkInterface(name string) bool {
|
||||
name = strings.ToLower(strings.TrimSpace(name))
|
||||
return name == "lo" || strings.HasPrefix(name, "docker") || strings.HasPrefix(name, "br-")
|
||||
if name == "lo" || strings.HasPrefix(name, "docker") {
|
||||
return true
|
||||
}
|
||||
|
||||
bridgeID, found := strings.CutPrefix(name, "br-")
|
||||
if !found || len(bridgeID) != 12 {
|
||||
return false
|
||||
}
|
||||
for _, character := range bridgeID {
|
||||
if (character < '0' || character > '9') && (character < 'a' || character > 'f') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func collectReportedHostIPs(
|
||||
|
||||
@@ -5691,7 +5691,7 @@ func TestApplyHostReportPreservesPoolOnlyUnraidCount(t *testing.T) {
|
||||
func TestFindLinkedProxmoxEntityWithHints_RejectsHostLocalNetworkIdentity(t *testing.T) {
|
||||
for _, tc := range []struct{ name, nic, address string }{
|
||||
{"docker", "docker0", "172.17.0.1/16"},
|
||||
{"custom docker bridge", "br-123abc", "192.0.2.1/24"},
|
||||
{"generated docker bridge", "br-0123456789ab", "192.0.2.1/24"},
|
||||
{"loopback", "lo", "127.0.0.1/8"},
|
||||
{"IPv6 loopback", "lo", "::1/128"},
|
||||
{"link local", "eth0", "169.254.1.2/16"},
|
||||
@@ -5726,8 +5726,10 @@ func TestAgentLinkNetworkIdentityFiltering(t *testing.T) {
|
||||
{"IPv6 management", "vmbr0", "2001:db8::10/64", true},
|
||||
{"ULA management", "eth0", "fd00::10/64", true},
|
||||
{"unnamed legacy interface", "", "192.0.2.10", true},
|
||||
{"custom management bridge", "br-mgmt", "192.0.2.10", true},
|
||||
{"docker", "docker0", "172.17.0.1/16", false},
|
||||
{"custom docker", "br-abc", "192.0.2.1/24", false},
|
||||
{"generated docker", "br-0123456789ab", "192.0.2.1/24", false},
|
||||
{"non-hex bridge", "br-0123456789ag", "192.0.2.1/24", true},
|
||||
{"loopback", "eth0", "127.1.2.3/8", false},
|
||||
{"IPv6 unspecified", "eth0", "::", false},
|
||||
{"multicast", "eth0", "224.0.0.1", false},
|
||||
|
||||
Reference in New Issue
Block a user