diff --git a/changes/issue-5595-duplicate-hosts-vuln-webhook b/changes/issue-5595-duplicate-hosts-vuln-webhook new file mode 100644 index 0000000000..8d059a2800 --- /dev/null +++ b/changes/issue-5595-duplicate-hosts-vuln-webhook @@ -0,0 +1 @@ +* Fixed an issue with duplicated hosts being sent in the vulnerability webhook payload. diff --git a/server/datastore/mysql/software.go b/server/datastore/mysql/software.go index 856048635d..6b349a7018 100644 --- a/server/datastore/mysql/software.go +++ b/server/datastore/mysql/software.go @@ -976,7 +976,7 @@ func (ds *Datastore) CalculateHostsPerSoftware(ctx context.Context, updatedAt ti // matching hosts. func (ds *Datastore) HostsByCPEs(ctx context.Context, cpes []string) ([]*fleet.HostShort, error) { queryStmt := ` - SELECT + SELECT DISTINCT h.id, h.hostname FROM diff --git a/server/datastore/mysql/software_test.go b/server/datastore/mysql/software_test.go index 4a69738a37..0b92f31c0c 100644 --- a/server/datastore/mysql/software_test.go +++ b/server/datastore/mysql/software_test.go @@ -36,6 +36,7 @@ func TestSoftware(t *testing.T) { {"ListVulnerableSoftwareBySource", testListVulnerableSoftwareBySource}, {"DeleteVulnerabilitiesByCPECVE", testDeleteVulnerabilitiesByCPECVE}, {"HostsByCVE", testHostsByCVE}, + {"HostsByCPEs", testHostsByCPEs}, {"UpdateHostSoftware", testUpdateHostSoftware}, {"ListSoftwareByHostIDShort", testListSoftwareByHostIDShort}, } @@ -1170,6 +1171,34 @@ func testHostsByCVE(t *testing.T, ds *Datastore) { require.Equal(t, hosts[0].Hostname, "host2") } +func testHostsByCPEs(t *testing.T, ds *Datastore) { + ctx := context.Background() + + hosts, err := ds.HostsByCPEs(ctx, []string{"cpe_foo_chrome_3"}) + require.NoError(t, err) + require.Len(t, hosts, 0) + + insertVulnSoftwareForTest(t, ds) + + hosts, err = ds.HostsByCPEs(ctx, []string{"cpe_foo_chrome_3"}) + require.NoError(t, err) + require.Len(t, hosts, 2) + require.Equal(t, hosts[0].Hostname, "host1") + require.Equal(t, hosts[1].Hostname, "host2") + + hosts, err = ds.HostsByCPEs(ctx, []string{"cpe_bar_rpm"}) + require.NoError(t, err) + require.Len(t, hosts, 1) + require.Equal(t, hosts[0].Hostname, "host2") + + // Duplicates should not be returned if cpes are found on the same host ie host2 should only appear once + hosts, err = ds.HostsByCPEs(ctx, []string{"cpe_foo_chrome_3", "cpe_bar_rpm"}) + require.NoError(t, err) + require.Len(t, hosts, 2) + require.Equal(t, hosts[0].Hostname, "host1") + require.Equal(t, hosts[1].Hostname, "host2") +} + func testUpdateHostSoftware(t *testing.T, ds *Datastore) { ctx := context.Background()