From cc633a4a915ed59339af6ea79e7779dff2afed04 Mon Sep 17 00:00:00 2001 From: Jonathan Buttner <56361221+jonathan-buttner@users.noreply.github.com> Date: Mon, 5 Oct 2020 10:11:28 -0400 Subject: [PATCH] [Security Solution] Adding tests for dns pipeline in the endpoint package (#79177) * Adding tests for dns pipeline in the endpoint package * Adding test to make sure non dns events are ingested correctly * Bring the docker container with the new endpoint package Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../common/endpoint/types/index.ts | 5 +- .../endpoint/pipeline/dns/data.json.gz | Bin 0 -> 1256 bytes .../ingest_manager_api_integration/config.ts | 2 +- .../apis/package.ts | 74 ++++++++++++++++++ 4 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 x-pack/test/functional/es_archives/endpoint/pipeline/dns/data.json.gz diff --git a/x-pack/plugins/security_solution/common/endpoint/types/index.ts b/x-pack/plugins/security_solution/common/endpoint/types/index.ts index abb0ccee8d90..0054c1f1abdd 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/index.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/index.ts @@ -718,7 +718,10 @@ export type SafeEndpointEvent = Partial<{ forwarded_ip: ECSField; }>; dns: Partial<{ - question: Partial<{ name: ECSField }>; + question: Partial<{ + name: ECSField; + type: ECSField; + }>; }>; process: Partial<{ entity_id: ECSField; diff --git a/x-pack/test/functional/es_archives/endpoint/pipeline/dns/data.json.gz b/x-pack/test/functional/es_archives/endpoint/pipeline/dns/data.json.gz new file mode 100644 index 0000000000000000000000000000000000000000..5caab4767dbec92b37150a272b3a7e0f1b232db3 GIT binary patch literal 1256 zcmVQOZ*BnXS6gr5MihR}udsM()!3Tx6&$TpHjv$H zV@L`lB4rf~_5cpX+w~EtNdx zmX5{30|`>G@(5qxtM7^3PH@eQ&sQJusOEAW_M=bUC=(YFp+{#zC}6`xrlA)xKjaF1 zpdn9`kn$;u$FfHUBn|jlDPd{ses=>azjJ>=6HX?Pu%#ju$r#B9x3Oj$$i{|(bFf$kc{#!RjZ>+th?4>V4E z7K&|4sVJJItsUvip7l2OiRP2|n&GJ(&gl{P{Ygv_oVG+6r zZ91JQL&k;yRa`bH6>P7=KW|)DFV1Us@b1)0-`(tFMBS~7axKA%p`hI&(11XEZc%M_ zTs8xPR*$^rwSImW;=|4)5_eS~=o1^K(Opcls!=cBOP6puWbqv2{wfr5H5Qw-uX!by zFk$D_C*{o}xU9-We9>xNf4)x6x)r@$^?%DAdX|?Q0{~=3vkK%kCd^BNXHQikiV*IOWz$z0}9#G4aD=O;Co@Z8Mtf_rd)lGF^Sp}_VJ29+U3W7ge z%*?j&{?1Q`yKMp?d-=h5`Pr}eilkVweK>ZZBfBDEpJdZsx`F1iX#yxBUB4H!82xxI`H2MB7zGrLvIMRrKBAI{Q4;7$SRkPDSQ6(! z!pAG66>{frTblZOBrO3O;9B~VCU9RQ;C17EeZY%%l0fi~>_hR0#iG52wio+1htXbM zHappZfC~w~cnc9Y|8QGwV;}6?e)=+Lv`7AJt;@Ujow;+0P_x~|7wsYL-Z;FgHb&j{ z*{FHbMcqXQ*4A(}zG${xknK#Hr#fofpX-gqaOzY)d?nzAUTY3F-9%G+J;!%rmaqY@dqaA9sesZp z*%8_=h(%dOSVe}pGjC}^-=Mp@gZ{pB_wpU+E=xJI zJljrEH@h95CByhYh7V-;K!%?u!)ke(4Xdhw%LtXrmQhwMwaAIlh7t>HTapZELOq|z zF`P;o%U~QUaHu>bTUO>|#F%h*@{;@zX-jFiLj { + describe('network processors', () => { + let networkIndexData: InsertedEvents; + + after(async () => { + await resolver.deleteData(networkIndexData); + }); + + it('handles events without the `network.protocol` field being defined', async () => { + const eventWithoutNetworkObject = generator.generateEvent(); + // ensure that `network.protocol` does not exist in the event to test that the pipeline handles those type of events + delete eventWithoutNetworkObject.network; + + // this call will fail if the pipeline fails + networkIndexData = await resolver.insertEvents([eventWithoutNetworkObject], networkIndex); + const eventWithBothIPs = await searchForID( + networkIndexData.eventsInfo[0]._id + ); + + // ensure that the event was inserted into ES + expect(eventWithBothIPs.body.hits.hits[0]._source.event?.id).to.be( + eventWithoutNetworkObject.event?.id + ); + }); + }); + + describe('dns processor', () => { + before(async () => { + await esArchiver.load('endpoint/pipeline/dns', { useCreate: true }); + }); + + after(async () => { + await deleteEventsStream(getService); + }); + + it('does not set dns.question.type if it is already populated', async () => { + // this id comes from the es archive file endpoint/pipeline/dns + const id = 'LrLSOVHVsFY94TAi++++++eF'; + const { body }: { body: ResolverPaginatedEvents } = await supertest + .post(`/api/endpoint/resolver/events?limit=1`) + .set('kbn-xsrf', 'xxx') + .send({ + filter: `event.id:"${id}"`, + }) + .expect(200); + expect(body.events.length).to.eql(1); + expect((body.events[0] as SafeEndpointEvent).dns?.question?.name).to.eql('www.google.com'); + expect((body.events[0] as SafeEndpointEvent).dns?.question?.type).to.eql('INVALID_VALUE'); + }); + + it('sets dns.question.type if it is not populated', async () => { + // this id comes from the es archive file endpoint/pipeline/dns + const id = 'LrLSOVHVsFY94TAi++++++eP'; + const { body }: { body: ResolverPaginatedEvents } = await supertest + .post(`/api/endpoint/resolver/events?limit=1`) + .set('kbn-xsrf', 'xxx') + .send({ + filter: `event.id:"${id}"`, + }) + .expect(200); + expect(body.events.length).to.eql(1); + expect((body.events[0] as SafeEndpointEvent).dns?.question?.name).to.eql('www.aol.com'); + // This value is parsed out of the message field in the event. type 28 = AAAA + expect((body.events[0] as SafeEndpointEvent).dns?.question?.type).to.eql('AAAA'); + }); + }); + describe('ingested processor', () => { let event: Event; let genData: InsertedEvents; @@ -92,6 +165,7 @@ export default function ({ getService }: FtrProviderContext) { const eventWithSourceOnly = generator.generateEvent({ extensions: { source: { ip: '8.8.8.8' } }, }); + networkIndexData = await resolver.insertEvents( [eventWithBothIPs, eventWithSourceOnly], networkIndex