diff --git a/server/datastore/mysql/software.go b/server/datastore/mysql/software.go index ce9a9488d0..9e33a83c32 100644 --- a/server/datastore/mysql/software.go +++ b/server/datastore/mysql/software.go @@ -509,18 +509,30 @@ func (ds *Datastore) AllCPEs(ctx context.Context) ([]string, error) { // provided cpes. It returns the number of new rows inserted or an error. If // the CVE already existed for all CPEs, it would return 0, nil. func (ds *Datastore) InsertCVEForCPE(ctx context.Context, cve string, cpes []string) (int64, error) { - values := strings.TrimSuffix(strings.Repeat("((SELECT id FROM software_cpe WHERE cpe=?),?),", len(cpes)), ",") - sql := fmt.Sprintf(`INSERT IGNORE INTO software_cve (cpe_id, cve) VALUES %s`, values) - var args []interface{} + var totalCount int64 for _, cpe := range cpes { - args = append(args, cpe, cve) + var ids []uint + err := sqlx.Select(ds.writer, &ids, `SELECT id FROM software_cpe WHERE cpe=?`, cpe) + if err != nil { + return 0, err + } + + values := strings.TrimSuffix(strings.Repeat("(?,?),", len(ids)), ",") + sql := fmt.Sprintf(`INSERT IGNORE INTO software_cve (cpe_id, cve) VALUES %s`, values) + + var args []interface{} + for _, id := range ids { + args = append(args, id, cve) + } + res, err := ds.writer.ExecContext(ctx, sql, args...) + if err != nil { + return 0, ctxerr.Wrap(ctx, err, "insert software cve") + } + count, _ := res.RowsAffected() + totalCount += count } - res, err := ds.writer.ExecContext(ctx, sql, args...) - if err != nil { - return 0, ctxerr.Wrap(ctx, err, "insert software cve") - } - count, _ := res.RowsAffected() - return count, nil + + return totalCount, nil } func (ds *Datastore) ListSoftware(ctx context.Context, opt fleet.SoftwareListOptions) ([]fleet.Software, error) { diff --git a/server/datastore/mysql/software_test.go b/server/datastore/mysql/software_test.go index 795f286fe8..3028a8dd6f 100644 --- a/server/datastore/mysql/software_test.go +++ b/server/datastore/mysql/software_test.go @@ -197,16 +197,19 @@ func testSoftwareInsertCVEs(t *testing.T, ds *Datastore) { host := test.NewHost(t, ds, "host1", "", "host1key", "host1uuid", time.Now()) software := []fleet.Software{ - {Name: "foo", Version: "0.0.1", Source: "chrome_extensions"}, + {Name: "foo", Version: "0.0.1", Source: "deb_packages", Release: "1"}, + {Name: "foo", Version: "0.0.1", Source: "deb_packages", Release: "2"}, {Name: "foo", Version: "0.0.3", Source: "chrome_extensions"}, } require.NoError(t, ds.UpdateHostSoftware(context.Background(), host.ID, software)) require.NoError(t, ds.LoadHostSoftware(context.Background(), host)) require.NoError(t, ds.AddCPEForSoftware(context.Background(), host.Software[0], "somecpe")) + require.NoError(t, ds.AddCPEForSoftware(context.Background(), host.Software[1], "somecpe")) count, err := ds.InsertCVEForCPE(context.Background(), "cve-123-123-132", []string{"somecpe"}) require.NoError(t, err) - assert.Equal(t, int64(1), count) + // inserts one per release + assert.Equal(t, int64(2), count) // run again for the same CPE, should not create any new row count, err = ds.InsertCVEForCPE(context.Background(), "cve-123-123-132", []string{"somecpe"})