-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[SIEM][Detection Engine] Adds critical missing status route to prepac…
…kaged rules (#55080) ## Summary * Fixes a critical bug where the missing status for the REST route was missing * Fixes a bug with the 400 not being used for the missing index in some cases * Changes create and update to NO LONGER allow immutable to be passed * Fixes a bug with the add prepackaged schema to where you could use `immutable: false`. Now it is required to be missing or set to `immutable: true` within it. * Cleans up unit tests To use the critical bug missing status for the REST route: ```ts GET /api/detection_engine/rules/prepackaged/_status ``` And you will get back: ```ts { "rules_installed": 252, "rules_not_installed": 87, "rules_not_updated": 0 } ``` See the script: ```ts get_prepackaged_rules_status.sh ``` for more details ### Checklist Use ~~strikethroughs~~ to remove checklist items you don't feel are applicable to this PR. ~~- [ ] This was checked for cross-browser compatibility, [including a check against IE11](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility)~~ ~~- [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/master/packages/kbn-i18n/README.md)~~ ~~- [ ] [Documentation](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#writing-documentation) was added for features that require explanation or tutorials~~ - [x] [Unit or functional tests](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) were updated or added to match the most common scenarios ~~- [ ] This was checked for [keyboard-only and screenreader accessibility](https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Accessibility_testing_checklist)~~ ### For maintainers ~~- [ ] This was checked for breaking API changes and was [labeled appropriately](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#release-notes-process)~~ - [x] This includes a feature addition or change that requires a release note and was [labeled appropriately](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#release-notes-process)
- Loading branch information
1 parent
40ec30a
commit 6559224
Showing
38 changed files
with
788 additions
and
312 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
138 changes: 138 additions & 0 deletions
138
...plugins/siem/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License; | ||
* you may not use this file except in compliance with the Elastic License. | ||
*/ | ||
|
||
import { | ||
createMockServer, | ||
createMockServerWithoutActionClientDecoration, | ||
createMockServerWithoutAlertClientDecoration, | ||
createMockServerWithoutActionOrAlertClientDecoration, | ||
getMockEmptyIndex, | ||
getMockNonEmptyIndex, | ||
} from '../__mocks__/_mock_server'; | ||
import { createRulesRoute } from './create_rules_route'; | ||
import { | ||
getFindResult, | ||
getResult, | ||
createActionResult, | ||
addPrepackagedRulesRequest, | ||
getFindResultWithSingleHit, | ||
} from '../__mocks__/request_responses'; | ||
|
||
jest.mock('../../rules/get_prepackaged_rules', () => { | ||
return { | ||
getPrepackagedRules: () => { | ||
return [ | ||
{ | ||
rule_id: 'rule-1', | ||
output_index: '.siem-signals', | ||
risk_score: 50, | ||
description: 'some description', | ||
from: 'now-5m', | ||
to: 'now', | ||
index: ['index-1'], | ||
name: 'some-name', | ||
severity: 'severity', | ||
interval: '5m', | ||
type: 'query', | ||
version: 2, // set one higher than the mocks which is set to 1 to trigger updates | ||
}, | ||
]; | ||
}, | ||
}; | ||
}); | ||
|
||
import { addPrepackedRulesRoute } from './add_prepackaged_rules_route'; | ||
|
||
describe('add_prepackaged_rules_route', () => { | ||
let { server, alertsClient, actionsClient, elasticsearch } = createMockServer(); | ||
|
||
beforeEach(() => { | ||
jest.resetAllMocks(); | ||
({ server, alertsClient, actionsClient, elasticsearch } = createMockServer()); | ||
elasticsearch.getCluster = getMockNonEmptyIndex(); | ||
|
||
addPrepackedRulesRoute(server); | ||
}); | ||
|
||
describe('status codes with actionClient and alertClient', () => { | ||
test('returns 200 when creating a with a valid actionClient and alertClient', async () => { | ||
alertsClient.find.mockResolvedValue(getFindResult()); | ||
alertsClient.get.mockResolvedValue(getResult()); | ||
actionsClient.create.mockResolvedValue(createActionResult()); | ||
alertsClient.create.mockResolvedValue(getResult()); | ||
const { statusCode } = await server.inject(addPrepackagedRulesRequest()); | ||
expect(statusCode).toBe(200); | ||
}); | ||
|
||
test('returns 404 if actionClient is not available on the route', async () => { | ||
const { serverWithoutActionClient } = createMockServerWithoutActionClientDecoration(); | ||
createRulesRoute(serverWithoutActionClient); | ||
const { statusCode } = await serverWithoutActionClient.inject(addPrepackagedRulesRequest()); | ||
expect(statusCode).toBe(404); | ||
}); | ||
|
||
test('returns 404 if alertClient is not available on the route', async () => { | ||
const { serverWithoutAlertClient } = createMockServerWithoutAlertClientDecoration(); | ||
createRulesRoute(serverWithoutAlertClient); | ||
const { statusCode } = await serverWithoutAlertClient.inject(addPrepackagedRulesRequest()); | ||
expect(statusCode).toBe(404); | ||
}); | ||
|
||
test('returns 404 if alertClient and actionClient are both not available on the route', async () => { | ||
const { | ||
serverWithoutActionOrAlertClient, | ||
} = createMockServerWithoutActionOrAlertClientDecoration(); | ||
createRulesRoute(serverWithoutActionOrAlertClient); | ||
const { statusCode } = await serverWithoutActionOrAlertClient.inject( | ||
addPrepackagedRulesRequest() | ||
); | ||
expect(statusCode).toBe(404); | ||
}); | ||
}); | ||
|
||
describe('validation', () => { | ||
test('it returns a 400 if the index does not exist', async () => { | ||
elasticsearch.getCluster = getMockEmptyIndex(); | ||
alertsClient.find.mockResolvedValue(getFindResult()); | ||
alertsClient.get.mockResolvedValue(getResult()); | ||
actionsClient.create.mockResolvedValue(createActionResult()); | ||
alertsClient.create.mockResolvedValue(getResult()); | ||
const { payload } = await server.inject(addPrepackagedRulesRequest()); | ||
expect(JSON.parse(payload)).toEqual({ | ||
error: 'Bad Request', | ||
message: | ||
'Pre-packaged rules cannot be installed until the space index is created: .siem-signals-default', | ||
statusCode: 400, | ||
}); | ||
}); | ||
}); | ||
|
||
describe('payload', () => { | ||
test('1 rule is installed and 0 are updated when find results are empty', async () => { | ||
alertsClient.find.mockResolvedValue(getFindResult()); | ||
alertsClient.get.mockResolvedValue(getResult()); | ||
actionsClient.create.mockResolvedValue(createActionResult()); | ||
alertsClient.create.mockResolvedValue(getResult()); | ||
const { payload } = await server.inject(addPrepackagedRulesRequest()); | ||
expect(JSON.parse(payload)).toEqual({ | ||
rules_installed: 1, | ||
rules_updated: 0, | ||
}); | ||
}); | ||
|
||
test('1 rule is updated and 0 are installed when we return a single find and the versions are different', async () => { | ||
alertsClient.find.mockResolvedValue(getFindResultWithSingleHit()); | ||
alertsClient.get.mockResolvedValue(getResult()); | ||
actionsClient.create.mockResolvedValue(createActionResult()); | ||
alertsClient.create.mockResolvedValue(getResult()); | ||
const { payload } = await server.inject(addPrepackagedRulesRequest()); | ||
expect(JSON.parse(payload)).toEqual({ | ||
rules_installed: 0, | ||
rules_updated: 1, | ||
}); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.