mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
fix: query host search by email (#15833)
> 📜 Related issue: https://github.com/fleetdm/fleet/issues/15522 # Checklist for submitter If some of the following don't apply, delete the relevant line. <!-- Note that API documentation changes are now addressed by the product design team. --> - [x] Changes file added for user-visible changes in `changes/` or `orbit/changes/`. See [Changes files](https://fleetdm.com/docs/contributing/committing-changes#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements) - [x] Added/updated tests - [x] Manual QA for all new/changed functionality
This commit is contained in:
parent
d6ee2ac121
commit
1b9b67aa9c
1
changes/15522-query-host-search
Normal file
1
changes/15522-query-host-search
Normal file
@ -0,0 +1 @@
|
|||||||
|
- Fixes bug in searching for hosts by email addresses.
|
@ -2369,7 +2369,7 @@ func (ds *Datastore) SearchHosts(ctx context.Context, filter fleet.TeamFilter, m
|
|||||||
if len(matchQuery) > 0 {
|
if len(matchQuery) > 0 {
|
||||||
// first we'll find the hosts that match the search criteria, to keep thing simple, then we'll query again
|
// first we'll find the hosts that match the search criteria, to keep thing simple, then we'll query again
|
||||||
// to get all the additional data for hosts that match the search criteria by host_id
|
// to get all the additional data for hosts that match the search criteria by host_id
|
||||||
matchingHosts := "SELECT id FROM hosts WHERE TRUE"
|
matchingHosts := "SELECT h.id FROM hosts h WHERE TRUE"
|
||||||
var args []interface{}
|
var args []interface{}
|
||||||
// TODO: should search columns include display_name (requires join to host_display_names)?
|
// TODO: should search columns include display_name (requires join to host_display_names)?
|
||||||
searchHostsQuery, args, matchesEmail := hostSearchLike(matchingHosts, args, matchQuery, hostSearchColumns...)
|
searchHostsQuery, args, matchesEmail := hostSearchLike(matchingHosts, args, matchQuery, hostSearchColumns...)
|
||||||
|
@ -1763,6 +1763,15 @@ func testHostsSearch(t *testing.T, ds *Datastore) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Len(t, hits, 3)
|
assert.Len(t, hits, 3)
|
||||||
assert.Equal(t, []uint{h3.ID, h2.ID, h1.ID}, []uint{hits[0].ID, hits[1].ID, hits[2].ID})
|
assert.Equal(t, []uint{h3.ID, h2.ID, h1.ID}, []uint{hits[0].ID, hits[1].ID, hits[2].ID})
|
||||||
|
|
||||||
|
// Add email to mapping table
|
||||||
|
_, err = ds.writer(context.Background()).ExecContext(context.Background(), `INSERT INTO host_emails (host_id, email, source) VALUES (?, ?, ?)`,
|
||||||
|
hosts[0].ID, "a@b.c", "src1")
|
||||||
|
require.NoError(t, err)
|
||||||
|
// Verify search works
|
||||||
|
hits, err = ds.SearchHosts(context.Background(), filter, "a@b.c")
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, hits, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSearchHostsWildCards(t *testing.T, ds *Datastore) {
|
func testSearchHostsWildCards(t *testing.T, ds *Datastore) {
|
||||||
|
@ -1118,6 +1118,8 @@ var (
|
|||||||
nonacsiiReplace = regexp.MustCompile(`[^[:ascii:]]`)
|
nonacsiiReplace = regexp.MustCompile(`[^[:ascii:]]`)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// hostSearchLike searches hosts based on the given columns plus searching in hosts_emails. Note:
|
||||||
|
// the host from the `hosts` table must be aliased to `h` in `sql`.
|
||||||
func hostSearchLike(sql string, params []interface{}, match string, columns ...string) (string, []interface{}, bool) {
|
func hostSearchLike(sql string, params []interface{}, match string, columns ...string) (string, []interface{}, bool) {
|
||||||
var matchesEmail bool
|
var matchesEmail bool
|
||||||
base, args := searchLike(sql, params, match, columns...)
|
base, args := searchLike(sql, params, match, columns...)
|
||||||
|
@ -6232,6 +6232,22 @@ func (s *integrationTestSuite) TestSearchHosts() {
|
|||||||
s.DoJSON("POST", "/api/latest/fleet/hosts/search", searchHostsRequest{MatchQuery: "foo.local0"}, http.StatusOK, &searchResp)
|
s.DoJSON("POST", "/api/latest/fleet/hosts/search", searchHostsRequest{MatchQuery: "foo.local0"}, http.StatusOK, &searchResp)
|
||||||
require.Len(t, searchResp.Hosts, 1)
|
require.Len(t, searchResp.Hosts, 1)
|
||||||
require.Greater(t, searchResp.Hosts[0].SoftwareUpdatedAt, searchResp.Hosts[0].CreatedAt)
|
require.Greater(t, searchResp.Hosts[0].SoftwareUpdatedAt, searchResp.Hosts[0].CreatedAt)
|
||||||
|
|
||||||
|
mysql.ExecAdhocSQL(t, s.ds, func(db sqlx.ExtContext) error {
|
||||||
|
_, err := db.ExecContext(
|
||||||
|
context.Background(),
|
||||||
|
`INSERT INTO host_emails (host_id, email, source) VALUES (?, ?, ?)`,
|
||||||
|
hosts[0].ID, "a@b.c", "src1")
|
||||||
|
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
|
||||||
|
s.DoJSON("POST", "/api/latest/fleet/hosts/search", searchHostsRequest{MatchQuery: "a@b.c"}, http.StatusOK, &searchResp)
|
||||||
|
require.Len(t, searchResp.Hosts, 1)
|
||||||
|
|
||||||
|
// search for non-existent email, shouldn't get anything back
|
||||||
|
s.DoJSON("POST", "/api/latest/fleet/hosts/search", searchHostsRequest{MatchQuery: "not@found.com"}, http.StatusOK, &searchResp)
|
||||||
|
require.Len(t, searchResp.Hosts, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *integrationTestSuite) TestCountTargets() {
|
func (s *integrationTestSuite) TestCountTargets() {
|
||||||
|
Loading…
Reference in New Issue
Block a user