-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Endpoint] EMT-67: add kql support for endpoint list #56328
Changes from 4 commits
bdac93c
10b6194
0d68763
ac6590f
e255699
ac0a0f7
046e0bc
93cc54d
6d436b6
a8a8c85
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,16 +26,26 @@ export function registerEndpointRoutes(router: IRouter, endpointAppContext: Endp | |
validate: { | ||
body: schema.nullable( | ||
schema.object({ | ||
paging_properties: schema.arrayOf( | ||
schema.oneOf([ | ||
// the number of results to return for this request per page | ||
schema.object({ | ||
page_size: schema.number({ defaultValue: 10, min: 1, max: 10000 }), | ||
}), | ||
// the index of the page to return | ||
schema.object({ page_index: schema.number({ defaultValue: 0, min: 0 }) }), | ||
]) | ||
paging_properties: schema.nullable( | ||
schema.arrayOf( | ||
schema.oneOf([ | ||
/** | ||
* the number of results to return for this request per page | ||
*/ | ||
schema.object({ | ||
page_size: schema.number({ defaultValue: 10, min: 1, max: 10000 }), | ||
}), | ||
/** | ||
* the index of the first result in the page in the total matching set | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does not seem to be the correct description based on the current implementation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated. |
||
*/ | ||
schema.object({ page_index: schema.number({ defaultValue: 0, min: 0 }) }), | ||
]) | ||
) | ||
), | ||
/** | ||
* filter to be applied, it could be a kql expression or discrete filter to be implemented | ||
*/ | ||
filters: schema.nullable(schema.oneOf([schema.string()])), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also - we have talked about having other types of filtering possible in the future. Should this param be named something else other than There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry - just remember another thing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am sure you are right about this. But there are many licenses and license has to be configured at the plugin level using license plugin. And we also have to know what the minimum level of license, basic e.t.c. And what features should be free or licensed. Do you want us to move take offline? and not address it here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sound good @nnamdifrankie . I just did quick check around KQL and it seems that its available at all levels - its the AutoComplete functionality that seems to only be enabled for Basic license and above (ref: https://www.elastic.co/guide/en/kibana/current/kuery-query.html#kuery-query), so I don't think you need any checks here |
||
}) | ||
), | ||
}, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,10 @@ | |
import { KibanaRequest } from 'kibana/server'; | ||
import { EndpointAppConstants } from '../../../common/types'; | ||
import { EndpointAppContext } from '../../types'; | ||
import { | ||
fromKueryExpression, | ||
toElasticsearchQuery, | ||
} from '../../../../../../src/plugins/data/common/es_query/kuery/ast'; | ||
|
||
export const kibanaRequestToEndpointListQuery = async ( | ||
request: KibanaRequest<any, any, any>, | ||
|
@@ -14,9 +18,7 @@ export const kibanaRequestToEndpointListQuery = async ( | |
const pagingProperties = await getPagingProperties(request, endpointAppContext); | ||
return { | ||
body: { | ||
query: { | ||
match_all: {}, | ||
}, | ||
query: buildQueryBody(request), | ||
collapse: { | ||
field: 'host.id.keyword', | ||
inner_hits: { | ||
|
@@ -66,6 +68,15 @@ async function getPagingProperties( | |
}; | ||
} | ||
|
||
function buildQueryBody(request: KibanaRequest<any, any, any>): Record<string, any> { | ||
if (request?.body?.filters && typeof request.body.filters === 'string') { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm new to the ? operator - very cool. Could this be shortened to just |
||
return toElasticsearchQuery(fromKueryExpression(request.body.filters)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this the KQL translation magic here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is using function from the AST (Abstract Syntax Tree) Module to transform the text to an elastic query. Not magical, just classic language syntax tree transformation. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm going to be using this function too, for the alert list page... let's think about pulling this out into a common location? |
||
} | ||
return { | ||
match_all: {}, | ||
}; | ||
} | ||
|
||
export const kibanaRequestToEndpointFetchQuery = ( | ||
request: KibanaRequest<any, any, any>, | ||
endpointAppContext: EndpointAppContext | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,7 +40,7 @@ export default function({ getService }: FtrProviderContext) { | |
expect(body.request_page_index).to.eql(0); | ||
}); | ||
|
||
it('endpoints api should return page based on params passed.', async () => { | ||
it('endpoints api should return page based on paging properties passed.', async () => { | ||
const { body } = await supertest | ||
.post('/api/endpoint/endpoints') | ||
.set('kbn-xsrf', 'xxx') | ||
|
@@ -102,6 +102,40 @@ export default function({ getService }: FtrProviderContext) { | |
.expect(400); | ||
expect(body.message).to.contain('Value is [0] but it must be equal to or greater than [1]'); | ||
}); | ||
|
||
it('endpoints api should return page based on filters passed.', async () => { | ||
const { body } = await supertest | ||
.post('/api/endpoint/endpoints') | ||
.set('kbn-xsrf', 'xxx') | ||
.send({ filters: 'not host.ip:10.101.149.26' }) | ||
.expect(200); | ||
expect(body.total).to.eql(2); | ||
expect(body.endpoints.length).to.eql(2); | ||
expect(body.request_page_size).to.eql(10); | ||
expect(body.request_page_index).to.eql(0); | ||
}); | ||
|
||
it('endpoints api should return page based on filters and paging passed.', async () => { | ||
const { body } = await supertest | ||
.post('/api/endpoint/endpoints') | ||
.set('kbn-xsrf', 'xxx') | ||
.send({ | ||
paging_properties: [ | ||
{ | ||
page_size: 1, | ||
}, | ||
{ | ||
page_index: 1, | ||
}, | ||
], | ||
filters: 'not host.ip:10.101.149.26', | ||
}) | ||
.expect(200); | ||
expect(body.total).to.eql(2); | ||
expect(body.endpoints.length).to.eql(1); | ||
expect(body.request_page_size).to.eql(1); | ||
expect(body.request_page_index).to.eql(1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we have any testing around the actual set of endpoints returned and ensuring its the expected set for the requested |
||
}); | ||
}); | ||
}); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're also using paging_properties and filters for alert list, so let's consider moving this schema out to a common location...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@madirey I have a refactor ticket coming behind this and can move it then, if this is fine with you. I think we should share only things we strongly feel are really generic, such that other paths in the system does not consume non relevant changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure @nnamdifrankie , we can refactor once both endpoints are integrated too, might be easier that way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@madirey I see your point now, since it one app we cannot have different names for the same thing. Thanks for the input. Once we merge let work together to merge some of the properties.