Fix PBS discovery causing auth failures

Increases confidence score for PBS when receiving 401/403 responses to avoid unnecessary probing of other endpoints that trigger auth failure logs.

Fixes #741
This commit is contained in:
courtmanr@gmail.com 2025-11-23 00:08:54 +00:00
parent 6034ba69ea
commit 8ab370d4c0
2 changed files with 50 additions and 9 deletions

View file

@ -51,13 +51,13 @@ type DiscoveryResult struct {
// friendlyPhaseName converts technical phase names to user-friendly descriptions
func friendlyPhaseName(phase string) string {
friendlyNames := map[string]string{
"lxc_container_network": "Container network",
"docker_bridge_network": "Docker bridge network",
"docker_container_network": "Docker container network",
"host_local_network": "Local network",
"inferred_gateway_network": "Gateway network",
"extra_targets": "Additional targets",
"proxmox_cluster_network": "Proxmox cluster network",
"lxc_container_network": "Container network",
"docker_bridge_network": "Docker bridge network",
"docker_container_network": "Docker container network",
"host_local_network": "Local network",
"inferred_gateway_network": "Gateway network",
"extra_targets": "Additional targets",
"proxmox_cluster_network": "Proxmox cluster network",
}
if friendly, ok := friendlyNames[phase]; ok {
@ -1193,9 +1193,12 @@ func (s *Scanner) applyPBSHeuristics(ctx context.Context, address string, result
}
case http.StatusUnauthorized, http.StatusForbidden:
if versionFinding.ProductGuess == productPBS {
result.addConfidence(productPBS, "auth headers indicated PBS", 0.45, true)
result.addConfidence(productPBS, "auth headers indicated PBS", 0.55, true)
} else {
result.addConfidence(productPBS, "version endpoint on PBS port requires auth", 0.35, true)
// High confidence: Port 8007 + api2/json/version exists (even if auth required) is a very strong signal.
// We bump this to ensure we cross the threshold and avoid probing other endpoints (status/datastore)
// which would generate "authentication failure" logs on the server.
result.addConfidence(productPBS, "version endpoint on PBS port requires auth", 0.55, true)
}
default:
if result.Reachable && result.ProductScores[productPBS] < 0.25 {

View file

@ -427,3 +427,41 @@ func TestDiscoverServersCancelledContext(t *testing.T) {
t.Fatalf("expected no servers on cancelled context")
}
}
func TestPBSDiscoveryWithUnauthorizedVersion(t *testing.T) {
// Handler that simulates PBS requiring auth for version endpoint
// and NOT providing any helpful headers initially to test the port+auth heuristic
pbsHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/api2/json/version" {
w.WriteHeader(http.StatusUnauthorized)
return
}
http.NotFound(w, r)
})
server := startTLSServerOn(t, "127.0.0.1:8007", pbsHandler)
_ = server
scanner := newTestScanner(&http.Client{
Timeout: 500 * time.Millisecond,
Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
})
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
// Probe port 8007
probe := scanner.ProbeProxmoxService(ctx, "127.0.0.1", 8007)
if probe == nil {
t.Fatal("ProbeProxmoxService returned nil")
}
if !probe.Positive {
t.Errorf("Expected positive identification for PBS on port 8007 with 401 version response, got negative. Score: %f", probe.PrimaryScore)
}
if probe.PrimaryProduct != ProductPBS {
t.Errorf("Expected product %q, got %q", ProductPBS, probe.PrimaryProduct)
}
}