Skip to content

Commit

Permalink
[SIEM] [Detection Engine] Changes find_statuses route HTTP met… (#63508)
Browse files Browse the repository at this point in the history
* changes http method for find_statuses route from GET to POST

* fix test string formatting

* update sample shell script for find statuses route

* adds e2e test for find statuses
  • Loading branch information
dhurley14 authored Apr 16, 2020
1 parent 4b7895a commit ebcb502
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -501,10 +501,8 @@ describe('Detections Rules API', () => {
test('check parameter url, query', async () => {
await getRuleStatusById({ id: 'mySuperRuleId', signal: abortCtrl.signal });
expect(fetchMock).toHaveBeenCalledWith('/api/detection_engine/rules/_find_statuses', {
query: {
ids: '["mySuperRuleId"]',
},
method: 'GET',
body: '{"ids":["mySuperRuleId"]}',
method: 'POST',
signal: abortCtrl.signal,
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,8 @@ export const getRuleStatusById = async ({
signal: AbortSignal;
}): Promise<RuleStatusResponse> =>
KibanaServices.get().http.fetch<RuleStatusResponse>(DETECTION_ENGINE_RULES_STATUS_URL, {
method: 'GET',
query: { ids: JSON.stringify([id]) },
method: 'POST',
body: JSON.stringify({ ids: [id] }),
signal,
});

Expand All @@ -289,8 +289,8 @@ export const getRulesStatusByIds = async ({
const res = await KibanaServices.get().http.fetch<RuleStatusResponse>(
DETECTION_ENGINE_RULES_STATUS_URL,
{
method: 'GET',
query: { ids: JSON.stringify(ids) },
method: 'POST',
body: JSON.stringify({ ids }),
signal,
}
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,9 +254,9 @@ export const getFindResultWithMultiHits = ({

export const ruleStatusRequest = () =>
requestMock.create({
method: 'get',
method: 'post',
path: `${DETECTION_ENGINE_RULES_URL}/_find_statuses`,
query: { ids: ['someId'] },
body: { ids: ['someId'] },
});

export const getImportRulesRequest = (hapiStream?: HapiReadableStream) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ describe('find_statuses', () => {
describe('request validation', () => {
test('disallows singular id query param', async () => {
const request = requestMock.create({
method: 'get',
method: 'post',
path: `${DETECTION_ENGINE_RULES_URL}/_find_statuses`,
query: { id: ['someId'] },
body: { id: ['someId'] },
});
const result = server.validate(request);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ import {
} from '../utils';

export const findRulesStatusesRoute = (router: IRouter) => {
router.get(
router.post(
{
path: `${DETECTION_ENGINE_RULES_URL}/_find_statuses`,
validate: {
query: buildRouteValidation<FindRulesStatusesRequestParams>(findRulesStatusesSchema),
body: buildRouteValidation<FindRulesStatusesRequestParams>(findRulesStatusesSchema),
},
options: {
tags: ['access:siem'],
},
},
async (context, request, response) => {
const { query } = request;
const { body } = request;
const siemResponse = buildSiemResponse(response);
const alertsClient = context.alerting?.getAlertsClient();
const savedObjectsClient = context.core.savedObjects.client;
Expand All @@ -50,7 +50,7 @@ export const findRulesStatusesRoute = (router: IRouter) => {
}
*/
try {
const statuses = await query.ids.reduce<Promise<RuleStatusResponse | {}>>(
const statuses = await body.ids.reduce<Promise<RuleStatusResponse | {}>>(
async (acc, id) => {
const lastFiveErrorsForId = await savedObjectsClient.find<
IRuleSavedAttributesSavedObjectAttributes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ set -e
./check_env_variables.sh


# Example: ./find_rules_statuses_by_ids.sh '["12345","6789abc"]'
# Example: ./find_rules_statuses_by_ids.sh [\"12345\",\"6789abc\"]
curl -g -k \
-s \
-H 'Content-Type: application/json' \
-H 'kbn-xsrf: 123' \
-u ${ELASTICSEARCH_USERNAME}:${ELASTICSEARCH_PASSWORD} \
-X GET "${KIBANA_URL}${SPACE_URL}/api/detection_engine/rules/_find_statuses?ids=$1" \
-X POST "${KIBANA_URL}${SPACE_URL}/api/detection_engine/rules/_find_statuses" \
-d "{\"ids\": $1}" \
| jq .
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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 expect from '@kbn/expect';

import { DETECTION_ENGINE_RULES_URL } from '../../../../legacy/plugins/siem/common/constants';
import { FtrProviderContext } from '../../common/ftr_provider_context';
import {
createSignalsIndex,
deleteAllAlerts,
deleteSignalsIndex,
deleteAllRulesStatuses,
getSimpleRule,
} from './utils';

// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext): void => {
const supertest = getService('supertest');
const es = getService('legacyEs');

describe('find_statuses', () => {
beforeEach(async () => {
await createSignalsIndex(supertest);
});

afterEach(async () => {
await deleteSignalsIndex(supertest);
await deleteAllAlerts(es);
await deleteAllRulesStatuses(es);
});

it('should return an empty find statuses body correctly if no statuses are loaded', async () => {
const { body } = await supertest
.post(`${DETECTION_ENGINE_RULES_URL}/_find_statuses`)
.set('kbn-xsrf', 'true')
.send({ ids: [] })
.expect(200);

expect(body).to.eql({});
});

it('should return a single rule status when a single rule is loaded from a find status with defaults added', async () => {
// add a single rule
const { body: resBody } = await supertest
.post(DETECTION_ENGINE_RULES_URL)
.set('kbn-xsrf', 'true')
.send(getSimpleRule())
.expect(200);

await new Promise(resolve => setTimeout(resolve, 1000)).then(async () => {
// query the single rule from _find
const { body } = await supertest
.post(`${DETECTION_ENGINE_RULES_URL}/_find_statuses`)
.set('kbn-xsrf', 'true')
.send({ ids: [resBody.id] })
.expect(200);

// expected result for status should be 'going to run' or 'succeeded
expect(['succeeded', 'going to run']).to.contain(body[resBody.id].current_status.status);
});
});
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default ({ loadTestFile }: FtrProviderContext): void => {
loadTestFile(require.resolve('./delete_rules_bulk'));
loadTestFile(require.resolve('./export_rules'));
loadTestFile(require.resolve('./find_rules'));
loadTestFile(require.resolve('./find_statuses'));
loadTestFile(require.resolve('./get_prepackaged_rules_status'));
loadTestFile(require.resolve('./import_rules'));
loadTestFile(require.resolve('./read_rules'));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,19 @@ export const deleteAllAlerts = async (es: any): Promise<void> => {
});
};

/**
* Remove all rules statuses from the .kibana index
* @param es The ElasticSearch handle
*/
export const deleteAllRulesStatuses = async (es: any): Promise<void> => {
await es.deleteByQuery({
index: '.kibana',
q: 'type:siem-detection-engine-rule-status',
waitForCompletion: true,
refresh: 'wait_for',
});
};

/**
* Creates the signals index for use inside of beforeEach blocks of tests
* @param supertest The supertest client library
Expand Down

0 comments on commit ebcb502

Please sign in to comment.