Skip to content

Commit

Permalink
[Security Solution][Endpoint][Response Actions] Do fuzzy search on gi…
Browse files Browse the repository at this point in the history
…ven usernames for Actions Log (elastic#141239)

* Do fuzzy search on given usernames

fixes elastic/security-team/issues/4724
refs elastic/pull/140975

* Allow `match` searches on the API

Do fuzzy search via the request

review suggestions
  • Loading branch information
ashokaditya authored Sep 22, 2022
1 parent b026d2c commit 15fc5b7
Show file tree
Hide file tree
Showing 5 changed files with 360 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ describe('useGetEndpointActionList hook', () => {
page: 2,
pageSize: 20,
startDate: 'now-5d',
userIds: ['elastic', 'citsale'],
userIds: ['*elastic*', '*citsale*'],
},
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ export const useGetEndpointActionList = (
): UseQueryResult<ActionListApiResponse, IHttpFetchError<ErrorType>> => {
const http = useHttp();

// prepend and append * to userIds for fuzzy search
let userIds = query.userIds;
if (typeof query.userIds === 'string') {
userIds = `*${query.userIds}*`;
} else if (Array.isArray(query.userIds)) {
userIds = query.userIds.map((userId) => `*${userId}*`);
}

return useQuery<ActionListApiResponse, IHttpFetchError<ErrorType>>({
queryKey: ['get-action-list', query],
...options,
Expand All @@ -37,7 +45,7 @@ export const useGetEndpointActionList = (
pageSize: query.pageSize,
startDate: query.startDate,
statuses: query.statuses,
userIds: query.userIds,
userIds,
},
});
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,53 +225,171 @@ describe('When using `getActionList()', () => {
startDate: 'now-10d',
endDate: 'now',
commands: ['isolate', 'unisolate', 'get-file'],
userIds: ['elastic'],
userIds: ['*elastic*'],
});

expect(esClient.search).toHaveBeenNthCalledWith(
1,
expect.objectContaining({
{
body: {
query: {
bool: {
filter: [
{
term: {
input_type: 'endpoint',
},
},
{
term: {
type: 'INPUT_ACTION',
},
},
must: [
{
range: {
'@timestamp': {
gte: 'now-10d',
},
bool: {
filter: [
{
term: {
input_type: 'endpoint',
},
},
{
term: {
type: 'INPUT_ACTION',
},
},
{
range: {
'@timestamp': {
gte: 'now-10d',
},
},
},
{
range: {
'@timestamp': {
lte: 'now',
},
},
},
{
terms: {
'data.command': ['isolate', 'unisolate', 'get-file'],
},
},
{
terms: {
agents: ['123'],
},
},
],
},
},
{
range: {
'@timestamp': {
lte: 'now',
},
},
},
{
terms: {
'data.command': ['isolate', 'unisolate', 'get-file'],
bool: {
should: [
{
query_string: {
fields: ['user_id'],
query: '*elastic*',
},
},
],
minimum_should_match: 1,
},
},
],
},
},
sort: [
{
'@timestamp': {
order: 'desc',
},
},
],
},
from: 0,
index: '.logs-endpoint.actions-default',
size: 20,
},
{ ignore: [404], meta: true }
);
});

it('should call search with exact usernames when no wildcards are present', async () => {
// mock metadataService.findHostMetadataForFleetAgents resolved value
(endpointAppContextService.getEndpointMetadataService as jest.Mock) = jest
.fn()
.mockReturnValue({
findHostMetadataForFleetAgents: jest.fn().mockResolvedValue([]),
});
await getActionList({
esClient,
logger,
metadataService: endpointAppContextService.getEndpointMetadataService(),
pageSize: 10,
startDate: 'now-1d',
endDate: 'now',
userIds: ['elastic', 'kibana'],
});

expect(esClient.search).toHaveBeenNthCalledWith(
1,
{
body: {
query: {
bool: {
must: [
{
terms: {
user_id: ['elastic'],
bool: {
filter: [
{
term: {
input_type: 'endpoint',
},
},
{
term: {
type: 'INPUT_ACTION',
},
},
{
range: {
'@timestamp': {
gte: 'now-1d',
},
},
},
{
range: {
'@timestamp': {
lte: 'now',
},
},
},
],
},
},
{
terms: {
agents: ['123'],
bool: {
should: [
{
bool: {
should: [
{
match: {
user_id: 'elastic',
},
},
],
minimum_should_match: 1,
},
},
{
bool: {
should: [
{
match: {
user_id: 'kibana',
},
},
],
minimum_should_match: 1,
},
},
],
minimum_should_match: 1,
},
},
],
Expand All @@ -287,12 +405,9 @@ describe('When using `getActionList()', () => {
},
from: 0,
index: '.logs-endpoint.actions-default',
size: 20,
}),
expect.objectContaining({
ignore: [404],
meta: true,
})
size: 10,
},
{ ignore: [404], meta: true }
);
});

Expand Down
Loading

0 comments on commit 15fc5b7

Please sign in to comment.