From 7e32f934aa3170a0a1197812bd5f2bce65060b2a Mon Sep 17 00:00:00 2001 From: ymao1 Date: Thu, 24 Jun 2021 12:20:16 -0400 Subject: [PATCH 01/25] [Alerting] Using new es client in alerting functional tests (#102349) * Switching to new es client in alerting tests * Fixing types * Updating functional test * Updating functional test * Updating functional test * Fixing error handling * Fixing types * Fixing error handling * Fixing functional tests * Fixing functional tests Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../common/lib/es_test_index_tool.ts | 11 +- .../common/lib/index.ts | 2 +- .../common/lib/task_manager_utils.ts | 20 ++- .../actions/builtin_action_types/es_index.ts | 4 +- .../es_index_preconfigured.ts | 4 +- .../tests/actions/execute.ts | 18 +-- .../tests/alerting/alerts.ts | 126 ++++++++++-------- .../tests/alerting/create.ts | 13 +- .../tests/alerting/delete.ts | 12 +- .../tests/alerting/disable.ts | 12 +- .../tests/alerting/enable.ts | 21 ++- .../tests/alerting/health.ts | 2 +- .../tests/alerting/rbac_legacy.ts | 12 +- .../actions/builtin_action_types/es_index.ts | 4 +- .../preconfigured_alert_history_connector.ts | 12 +- .../spaces_only/tests/actions/enqueue.ts | 7 +- .../spaces_only/tests/actions/execute.ts | 10 +- .../spaces_only/tests/alerting/alerts_base.ts | 26 ++-- .../builtin_alert_types/es_query/alert.ts | 2 +- .../es_query/create_test_data.ts | 2 +- .../index_threshold/alert.ts | 2 +- .../index_threshold/create_test_data.ts | 2 +- .../index_threshold/fields_endpoint.ts | 2 +- .../index_threshold/indices_endpoint.ts | 2 +- .../time_series_query_endpoint.ts | 2 +- .../spaces_only/tests/alerting/create.ts | 13 +- .../spaces_only/tests/alerting/delete.ts | 6 +- .../spaces_only/tests/alerting/disable.ts | 6 +- .../spaces_only/tests/alerting/enable.ts | 13 +- .../event_log/service_api_integration.ts | 4 +- 30 files changed, 206 insertions(+), 166 deletions(-) diff --git a/x-pack/test/alerting_api_integration/common/lib/es_test_index_tool.ts b/x-pack/test/alerting_api_integration/common/lib/es_test_index_tool.ts index 18655f2d72fda..1d5eb43ebe970 100644 --- a/x-pack/test/alerting_api_integration/common/lib/es_test_index_tool.ts +++ b/x-pack/test/alerting_api_integration/common/lib/es_test_index_tool.ts @@ -59,7 +59,10 @@ export class ESTestIndexTool { } async destroy() { - return await this.es.indices.delete({ index: this.index, ignore: [404] }); + const indexExists = (await this.es.indices.exists({ index: this.index })).body; + if (indexExists) { + return await this.es.indices.delete({ index: this.index }); + } } async search(source: string, reference: string) { @@ -90,10 +93,10 @@ export class ESTestIndexTool { async waitForDocs(source: string, reference: string, numDocs: number = 1) { return await this.retry.try(async () => { const searchResult = await this.search(source, reference); - if (searchResult.hits.total.value < numDocs) { - throw new Error(`Expected ${numDocs} but received ${searchResult.hits.total.value}.`); + if (searchResult.body.hits.total.value < numDocs) { + throw new Error(`Expected ${numDocs} but received ${searchResult.body.hits.total.value}.`); } - return searchResult.hits.hits; + return searchResult.body.hits.hits; }); } } diff --git a/x-pack/test/alerting_api_integration/common/lib/index.ts b/x-pack/test/alerting_api_integration/common/lib/index.ts index 242ce7ed8d884..eeb9c88269667 100644 --- a/x-pack/test/alerting_api_integration/common/lib/index.ts +++ b/x-pack/test/alerting_api_integration/common/lib/index.ts @@ -14,7 +14,7 @@ export { getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, } from './alert_utils'; -export { TaskManagerUtils } from './task_manager_utils'; +export { TaskManagerUtils, TaskManagerDoc } from './task_manager_utils'; export * from './test_assertions'; export { checkAAD } from './check_aad'; export { getEventLog } from './get_event_log'; diff --git a/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts b/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts index 73a9d93f7f329..57af1b1bcb035 100644 --- a/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts +++ b/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts @@ -5,6 +5,12 @@ * 2.0. */ +import { SerializedConcreteTaskInstance } from '../../../../plugins/task_manager/server/task'; + +export interface TaskManagerDoc { + type: string; + task: SerializedConcreteTaskInstance; +} export class TaskManagerUtils { private readonly es: any; private readonly retry: any; @@ -39,8 +45,8 @@ export class TaskManagerUtils { }, }, }); - if (searchResult.hits.total.value) { - throw new Error(`Expected 0 tasks but received ${searchResult.hits.total.value}`); + if (searchResult.body.hits.total.value) { + throw new Error(`Expected 0 tasks but received ${searchResult.body.hits.total.value}`); } }); } @@ -77,8 +83,10 @@ export class TaskManagerUtils { }, }, }); - if (searchResult.hits.total.value) { - throw new Error(`Expected 0 non-idle tasks but received ${searchResult.hits.total.value}`); + if (searchResult.body.hits.total.value) { + throw new Error( + `Expected 0 non-idle tasks but received ${searchResult.body.hits.total.value}` + ); } }); } @@ -108,9 +116,9 @@ export class TaskManagerUtils { }, }, }); - if (searchResult.hits.total.value) { + if (searchResult.body.hits.total.value) { throw new Error( - `Expected 0 action_task_params objects but received ${searchResult.hits.total.value}` + `Expected 0 action_task_params objects but received ${searchResult.body.hits.total.value}` ); } }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts index cd60f0cef1710..3db58cb2adc3d 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts @@ -13,7 +13,7 @@ const ES_TEST_INDEX_NAME = 'functional-test-actions-index'; // eslint-disable-next-line import/no-default-export export default function indexTest({ getService }: FtrProviderContext) { - const es = getService('legacyEs'); + const es = getService('es'); const supertest = getService('supertest'); const esDeleteAllIndices = getService('esDeleteAllIndices'); @@ -273,5 +273,5 @@ async function getTestIndexItems(es: any) { index: ES_TEST_INDEX_NAME, }); - return result.hits.hits; + return result.body.hits.hits; } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts index 48f042473c14e..92a5d7d840276 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts @@ -15,7 +15,7 @@ const ES_TEST_INDEX_NAME = 'functional-test-actions-index-preconfigured'; // eslint-disable-next-line import/no-default-export export default function indexTest({ getService }: FtrProviderContext) { - const es = getService('legacyEs'); + const es = getService('es'); const esDeleteAllIndices = getService('esDeleteAllIndices'); const supertest = getService('supertest'); @@ -57,5 +57,5 @@ async function getTestIndexItems(es: any) { index: ES_TEST_INDEX_NAME, }); - return result.hits.hits; + return result.body.hits.hits; } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts index 5c578d2d08dae..9091b96ff335a 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts @@ -23,7 +23,7 @@ const NANOS_IN_MILLIS = 1000 * 1000; export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('legacyEs'); + const es = getService('es'); const retry = getService('retry'); const esTestIndexTool = new ESTestIndexTool(es, retry); @@ -97,8 +97,8 @@ export default function ({ getService }: FtrProviderContext) { 'action:test.index-record', reference ); - expect(searchResult.hits.total.value).to.eql(1); - const indexedRecord = searchResult.hits.hits[0]; + expect(searchResult.body.hits.total.value).to.eql(1); + const indexedRecord = searchResult.body.hits.hits[0]; expect(indexedRecord._source).to.eql({ params: { reference, @@ -250,8 +250,8 @@ export default function ({ getService }: FtrProviderContext) { 'action:test.index-record', reference ); - expect(searchResult.hits.total.value).to.eql(1); - const indexedRecord = searchResult.hits.hits[0]; + expect(searchResult.body.hits.total.value).to.eql(1); + const indexedRecord = searchResult.body.hits.hits[0]; expect(indexedRecord._source).to.eql({ params: { reference, @@ -453,8 +453,8 @@ export default function ({ getService }: FtrProviderContext) { case 'space_1_all_with_restricted_fixture at space1': expect(response.statusCode).to.eql(200); searchResult = await esTestIndexTool.search('action:test.authorization', reference); - expect(searchResult.hits.total.value).to.eql(1); - indexedRecord = searchResult.hits.hits[0]; + expect(searchResult.body.hits.total.value).to.eql(1); + indexedRecord = searchResult.body.hits.hits[0]; expect(indexedRecord._source.state).to.eql({ callClusterSuccess: false, callScopedClusterSuccess: false, @@ -477,8 +477,8 @@ export default function ({ getService }: FtrProviderContext) { case 'superuser at space1': expect(response.statusCode).to.eql(200); searchResult = await esTestIndexTool.search('action:test.authorization', reference); - expect(searchResult.hits.total.value).to.eql(1); - indexedRecord = searchResult.hits.hits[0]; + expect(searchResult.body.hits.total.value).to.eql(1); + indexedRecord = searchResult.body.hits.hits[0]; expect(indexedRecord._source.state).to.eql({ callClusterSuccess: true, callScopedClusterSuccess: true, diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts index b3d83ae22f330..3131649e7c742 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts @@ -7,6 +7,7 @@ import expect from '@kbn/expect'; import { omit } from 'lodash'; +import type { ApiResponse, estypes } from '@elastic/elasticsearch'; import { UserAtSpaceScenarios, Superuser } from '../../scenarios'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { @@ -21,13 +22,18 @@ import { getEventLog, } from '../../../common/lib'; import { IValidatedEvent } from '../../../../../plugins/event_log/server'; +import { + TaskRunning, + TaskRunningStage, +} from '../../../../../plugins/task_manager/server/task_running'; +import { ConcreteTaskInstance } from '../../../../../plugins/task_manager/server'; const NANOS_IN_MILLIS = 1000 * 1000; // eslint-disable-next-line import/no-default-export export default function alertTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('legacyEs'); + const es = getService('es'); const retry = getService('retry'); const supertestWithoutAuth = getService('supertestWithoutAuth'); const esTestIndexTool = new ESTestIndexTool(es, retry); @@ -128,11 +134,11 @@ export default function alertTests({ getService }: FtrProviderContext) { 'alert:test.always-firing', reference ); - expect(alertSearchResult.hits.total.value).to.eql(1); - const alertSearchResultWithoutDates = omit(alertSearchResult.hits.hits[0]._source, [ - 'alertInfo.createdAt', - 'alertInfo.updatedAt', - ]); + expect(alertSearchResult.body.hits.total.value).to.eql(1); + const alertSearchResultWithoutDates = omit( + alertSearchResult.body.hits.hits[0]._source, + ['alertInfo.createdAt', 'alertInfo.updatedAt'] + ); expect(alertSearchResultWithoutDates).to.eql({ source: 'alert:test.always-firing', reference, @@ -171,10 +177,10 @@ export default function alertTests({ getService }: FtrProviderContext) { ruleTypeName: 'Test: Always Firing', }, }); - expect(alertSearchResult.hits.hits[0]._source.alertInfo.createdAt).to.match( + expect(alertSearchResult.body.hits.hits[0]._source.alertInfo.createdAt).to.match( /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/ ); - expect(alertSearchResult.hits.hits[0]._source.alertInfo.updatedAt).to.match( + expect(alertSearchResult.body.hits.hits[0]._source.alertInfo.updatedAt).to.match( /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/ ); @@ -183,8 +189,8 @@ export default function alertTests({ getService }: FtrProviderContext) { 'action:test.index-record', reference ); - expect(actionSearchResult.hits.total.value).to.eql(1); - expect(actionSearchResult.hits.hits[0]._source).to.eql({ + expect(actionSearchResult.body.hits.total.value).to.eql(1); + expect(actionSearchResult.body.hits.hits[0]._source).to.eql({ config: { unencrypted: `This value shouldn't get encrypted`, }, @@ -275,11 +281,11 @@ instanceStateValue: true 'alert:test.always-firing', reference ); - expect(alertSearchResult.hits.total.value).to.eql(1); - const alertSearchResultWithoutDates = omit(alertSearchResult.hits.hits[0]._source, [ - 'alertInfo.createdAt', - 'alertInfo.updatedAt', - ]); + expect(alertSearchResult.body.hits.total.value).to.eql(1); + const alertSearchResultWithoutDates = omit( + alertSearchResult.body.hits.hits[0]._source, + ['alertInfo.createdAt', 'alertInfo.updatedAt'] + ); expect(alertSearchResultWithoutDates).to.eql({ source: 'alert:test.always-firing', reference, @@ -319,10 +325,10 @@ instanceStateValue: true }, }); - expect(alertSearchResult.hits.hits[0]._source.alertInfo.createdAt).to.match( + expect(alertSearchResult.body.hits.hits[0]._source.alertInfo.createdAt).to.match( /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/ ); - expect(alertSearchResult.hits.hits[0]._source.alertInfo.updatedAt).to.match( + expect(alertSearchResult.body.hits.hits[0]._source.alertInfo.updatedAt).to.match( /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/ ); // Ensure only 1 action executed with proper params @@ -330,8 +336,8 @@ instanceStateValue: true 'action:test.index-record', reference ); - expect(actionSearchResult.hits.total.value).to.eql(1); - expect(actionSearchResult.hits.hits[0]._source).to.eql({ + expect(actionSearchResult.body.hits.total.value).to.eql(1); + expect(actionSearchResult.body.hits.hits[0]._source).to.eql({ config: { unencrypted: 'ignored-but-required', }, @@ -410,9 +416,9 @@ instanceStateValue: true reference2 ); - expect(alertSearchResult.hits.total.value).to.be.greaterThan(0); + expect(alertSearchResult.body.hits.total.value).to.be.greaterThan(0); const alertSearchResultInfoWithoutDates = omit( - alertSearchResult.hits.hits[0]._source.alertInfo, + alertSearchResult.body.hits.hits[0]._source.alertInfo, ['createdAt', 'updatedAt'] ); expect(alertSearchResultInfoWithoutDates).to.eql({ @@ -445,16 +451,16 @@ instanceStateValue: true ruleTypeName: 'Test: Always Firing', }); - expect(alertSearchResult.hits.hits[0]._source.alertInfo.createdAt).to.match( + expect(alertSearchResult.body.hits.hits[0]._source.alertInfo.createdAt).to.match( /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/ ); - expect(alertSearchResult.hits.hits[0]._source.alertInfo.updatedAt).to.match( + expect(alertSearchResult.body.hits.hits[0]._source.alertInfo.updatedAt).to.match( /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/ ); }); it('should handle custom retry logic when appropriate', async () => { - const testStart = new Date(); + const testStart = new Date().toISOString(); // We have to provide the test.rate-limit the next runAt, for testing purposes const retryDate = new Date(Date.now() + 60000); @@ -525,8 +531,12 @@ instanceStateValue: true objectRemover.add(space.id, response.body.id, 'rule', 'alerting'); // Wait for the task to be attempted once and idle - const scheduledActionTask = await retry.try(async () => { - const searchResult = await es.search({ + const scheduledActionTask: estypes.SearchHit< + TaskRunning + > = await retry.try(async () => { + const searchResult: ApiResponse< + estypes.SearchResponse> + > = await es.search({ index: '.kibana_task_manager', body: { query: { @@ -559,12 +569,12 @@ instanceStateValue: true }, }, }); - expect(searchResult.hits.total.value).to.eql(1); - return searchResult.hits.hits[0]; + expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.eql(1); + return searchResult.body.hits.hits[0]; }); // Ensure the next runAt is set to the retryDate by custom logic - expect(scheduledActionTask._source.task.runAt).to.eql(retryDate.toISOString()); + expect(scheduledActionTask._source!.task.runAt).to.eql(retryDate.toISOString()); break; default: throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); @@ -620,21 +630,21 @@ instanceStateValue: true // Ensure only 1 document exists with proper params searchResult = await esTestIndexTool.search('alert:test.authorization', reference); - expect(searchResult.hits.total.value).to.eql(1); - expect(searchResult.hits.hits[0]._source.state).to.eql({ + expect(searchResult.body.hits.total.value).to.eql(1); + expect(searchResult.body.hits.hits[0]._source.state).to.eql({ callClusterSuccess: false, callScopedClusterSuccess: false, savedObjectsClientSuccess: false, callClusterError: { - ...searchResult.hits.hits[0]._source.state.callClusterError, + ...searchResult.body.hits.hits[0]._source.state.callClusterError, }, callScopedClusterError: { - ...searchResult.hits.hits[0]._source.state.callScopedClusterError, + ...searchResult.body.hits.hits[0]._source.state.callScopedClusterError, }, savedObjectsClientError: { - ...searchResult.hits.hits[0]._source.state.savedObjectsClientError, + ...searchResult.body.hits.hits[0]._source.state.savedObjectsClientError, output: { - ...searchResult.hits.hits[0]._source.state.savedObjectsClientError.output, + ...searchResult.body.hits.hits[0]._source.state.savedObjectsClientError.output, statusCode: 403, }, }, @@ -651,15 +661,15 @@ instanceStateValue: true // Ensure only 1 document exists with proper params searchResult = await esTestIndexTool.search('alert:test.authorization', reference); - expect(searchResult.hits.total.value).to.eql(1); - expect(searchResult.hits.hits[0]._source.state).to.eql({ + expect(searchResult.body.hits.total.value).to.eql(1); + expect(searchResult.body.hits.hits[0]._source.state).to.eql({ callClusterSuccess: true, callScopedClusterSuccess: true, savedObjectsClientSuccess: false, savedObjectsClientError: { - ...searchResult.hits.hits[0]._source.state.savedObjectsClientError, + ...searchResult.body.hits.hits[0]._source.state.savedObjectsClientError, output: { - ...searchResult.hits.hits[0]._source.state.savedObjectsClientError.output, + ...searchResult.body.hits.hits[0]._source.state.savedObjectsClientError.output, statusCode: 404, }, }, @@ -737,21 +747,21 @@ instanceStateValue: true // Ensure only 1 document with proper params exists searchResult = await esTestIndexTool.search('action:test.authorization', reference); - expect(searchResult.hits.total.value).to.eql(1); - expect(searchResult.hits.hits[0]._source.state).to.eql({ + expect(searchResult.body.hits.total.value).to.eql(1); + expect(searchResult.body.hits.hits[0]._source.state).to.eql({ callClusterSuccess: false, callScopedClusterSuccess: false, savedObjectsClientSuccess: false, callClusterError: { - ...searchResult.hits.hits[0]._source.state.callClusterError, + ...searchResult.body.hits.hits[0]._source.state.callClusterError, }, callScopedClusterError: { - ...searchResult.hits.hits[0]._source.state.callScopedClusterError, + ...searchResult.body.hits.hits[0]._source.state.callScopedClusterError, }, savedObjectsClientError: { - ...searchResult.hits.hits[0]._source.state.savedObjectsClientError, + ...searchResult.body.hits.hits[0]._source.state.savedObjectsClientError, output: { - ...searchResult.hits.hits[0]._source.state.savedObjectsClientError.output, + ...searchResult.body.hits.hits[0]._source.state.savedObjectsClientError.output, statusCode: 403, }, }, @@ -776,15 +786,15 @@ instanceStateValue: true // Ensure only 1 document with proper params exists searchResult = await esTestIndexTool.search('action:test.authorization', reference); - expect(searchResult.hits.total.value).to.eql(1); - expect(searchResult.hits.hits[0]._source.state).to.eql({ + expect(searchResult.body.hits.total.value).to.eql(1); + expect(searchResult.body.hits.hits[0]._source.state).to.eql({ callClusterSuccess: true, callScopedClusterSuccess: true, savedObjectsClientSuccess: false, savedObjectsClientError: { - ...searchResult.hits.hits[0]._source.state.savedObjectsClientError, + ...searchResult.body.hits.hits[0]._source.state.savedObjectsClientError, output: { - ...searchResult.hits.hits[0]._source.state.savedObjectsClientError.output, + ...searchResult.body.hits.hits[0]._source.state.savedObjectsClientError.output, statusCode: 404, }, }, @@ -842,7 +852,7 @@ instanceStateValue: true 'action:test.index-record', reference ); - expect(searchResult.hits.total.value).to.eql(1); + expect(searchResult.body.hits.total.value).to.eql(1); break; default: throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); @@ -921,8 +931,8 @@ instanceStateValue: true 'action:test.index-record', reference ); - expect(searchResult.hits.total.value).to.eql(2); - const messages: string[] = searchResult.hits.hits.map( + expect(searchResult.body.hits.total.value).to.eql(2); + const messages: string[] = searchResult.body.hits.hits.map( (hit: { _source: { params: { message: string } } }) => hit._source.params.message ); expect(messages.sort()).to.eql(['from:default', 'from:other']); @@ -995,8 +1005,8 @@ instanceStateValue: true 'action:test.index-record', reference ); - expect(searchResult.hits.total.value).to.eql(2); - const messages: string[] = searchResult.hits.hits.map( + expect(searchResult.body.hits.total.value).to.eql(2); + const messages: string[] = searchResult.body.hits.hits.map( (hit: { _source: { params: { message: string } } }) => hit._source.params.message ); expect(messages.sort()).to.eql(['from:default:next', 'from:default:prev']); @@ -1058,7 +1068,7 @@ instanceStateValue: true 'action:test.index-record', reference ); - expect(searchResult.hits.total.value).to.eql(2); + expect(searchResult.body.hits.total.value).to.eql(2); break; default: throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); @@ -1116,7 +1126,7 @@ instanceStateValue: true 'action:test.index-record', reference ); - expect(executedActionsResult.hits.total.value).to.eql(0); + expect(executedActionsResult.body.hits.total.value).to.eql(0); break; default: throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); @@ -1174,7 +1184,7 @@ instanceStateValue: true 'action:test.index-record', reference ); - expect(executedActionsResult.hits.total.value).to.eql(0); + expect(executedActionsResult.body.hits.total.value).to.eql(0); break; default: throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); @@ -1233,7 +1243,7 @@ instanceStateValue: true 'action:test.index-record', reference ); - expect(searchResult.hits.total.value).to.eql(1); + expect(searchResult.body.hits.total.value).to.eql(1); break; default: throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts index 70cafe407de29..f481eaded4eb2 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import type { ApiResponse, estypes } from '@elastic/elasticsearch'; import { UserAtSpaceScenarios } from '../../scenarios'; import { checkAAD, @@ -14,13 +15,14 @@ import { getUrlPrefix, ObjectRemover, getProducerUnauthorizedErrorMessage, + TaskManagerDoc, } from '../../../common/lib'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createAlertTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('legacyEs'); + const es = getService('es'); const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('create', () => { @@ -28,11 +30,12 @@ export default function createAlertTests({ getService }: FtrProviderContext) { after(() => objectRemover.removeAll()); - async function getScheduledTask(id: string) { - return await es.get({ + async function getScheduledTask(id: string): Promise { + const scheduledTask: ApiResponse> = await es.get({ id: `task:${id}`, index: '.kibana_task_manager', }); + return scheduledTask.body._source!; } for (const scenario of UserAtSpaceScenarios) { @@ -127,9 +130,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { expect(Date.parse(response.body.created_at)).to.be.greaterThan(0); expect(Date.parse(response.body.updated_at)).to.be.greaterThan(0); - const { _source: taskRecord } = await getScheduledTask( - response.body.scheduled_task_id - ); + const taskRecord = await getScheduledTask(response.body.scheduled_task_id); expect(taskRecord.type).to.eql('task'); expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); expect(JSON.parse(taskRecord.task.params)).to.eql({ diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts index 2cbb16ababd10..d43fb2e7d835f 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/delete.ts @@ -19,7 +19,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createDeleteTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('legacyEs'); + const es = getService('es'); const retry = getService('retry'); const supertestWithoutAuth = getService('supertestWithoutAuth'); @@ -78,7 +78,7 @@ export default function createDeleteTests({ getService }: FtrProviderContext) { await getScheduledTask(createdAlert.scheduled_task_id); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } break; default: @@ -131,7 +131,7 @@ export default function createDeleteTests({ getService }: FtrProviderContext) { await getScheduledTask(createdAlert.scheduled_task_id); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } break; default: @@ -198,7 +198,7 @@ export default function createDeleteTests({ getService }: FtrProviderContext) { await getScheduledTask(createdAlert.scheduled_task_id); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } break; default: @@ -258,7 +258,7 @@ export default function createDeleteTests({ getService }: FtrProviderContext) { await getScheduledTask(createdAlert.scheduled_task_id); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } break; default: @@ -353,7 +353,7 @@ export default function createDeleteTests({ getService }: FtrProviderContext) { await getScheduledTask(createdAlert.scheduled_task_id); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } break; default: diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts index b265451bbd632..66f01000ede5e 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/disable.ts @@ -20,7 +20,7 @@ import { // eslint-disable-next-line import/no-default-export export default function createDisableAlertTests({ getService }: FtrProviderContext) { - const es = getService('legacyEs'); + const es = getService('es'); const retry = getService('retry'); const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); @@ -101,7 +101,7 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte await getScheduledTask(createdAlert.scheduled_task_id); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } // Ensure AAD isn't broken await checkAAD({ @@ -157,7 +157,7 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte await getScheduledTask(createdAlert.scheduled_task_id); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } break; default: @@ -217,7 +217,7 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte await getScheduledTask(createdAlert.scheduled_task_id); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } break; default: @@ -273,7 +273,7 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte await getScheduledTask(createdAlert.scheduled_task_id); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } break; default: @@ -332,7 +332,7 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte await getScheduledTask(createdAlert.scheduled_task_id); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } // Ensure AAD isn't broken await checkAAD({ diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts index 70e286b795720..d836f615e5349 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import type { ApiResponse, estypes } from '@elastic/elasticsearch'; import { UserAtSpaceScenarios } from '../../scenarios'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { @@ -16,11 +17,12 @@ import { ObjectRemover, getConsumerUnauthorizedErrorMessage, getProducerUnauthorizedErrorMessage, + TaskManagerDoc, } from '../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function createEnableAlertTests({ getService }: FtrProviderContext) { - const es = getService('legacyEs'); + const es = getService('es'); const retry = getService('retry'); const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); @@ -30,11 +32,12 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex after(() => objectRemover.removeAll()); - async function getScheduledTask(id: string) { - return await es.get({ + async function getScheduledTask(id: string): Promise { + const scheduledTask: ApiResponse> = await es.get({ id: `task:${id}`, index: '.kibana_task_manager', }); + return scheduledTask.body._source!; } for (const scenario of UserAtSpaceScenarios) { @@ -119,9 +122,7 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex .auth(user.username, user.password) .expect(200); expect(typeof updatedAlert.scheduled_task_id).to.eql('string'); - const { _source: taskRecord } = await getScheduledTask( - updatedAlert.scheduled_task_id - ); + const taskRecord = await getScheduledTask(updatedAlert.scheduled_task_id); expect(taskRecord.type).to.eql('task'); expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); expect(JSON.parse(taskRecord.task.params)).to.eql({ @@ -182,7 +183,7 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex await getScheduledTask(createdAlert.scheduled_task_id); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } break; default: @@ -292,7 +293,7 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex await getScheduledTask(createdAlert.scheduled_task_id); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } break; default: @@ -351,9 +352,7 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex .auth(user.username, user.password) .expect(200); expect(typeof updatedAlert.scheduled_task_id).to.eql('string'); - const { _source: taskRecord } = await getScheduledTask( - updatedAlert.scheduled_task_id - ); + const taskRecord = await getScheduledTask(updatedAlert.scheduled_task_id); expect(taskRecord.type).to.eql('task'); expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); expect(JSON.parse(taskRecord.task.params)).to.eql({ diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/health.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/health.ts index 668de3eb4fb9e..21e5c782d185c 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/health.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/health.ts @@ -20,7 +20,7 @@ import { // eslint-disable-next-line import/no-default-export export default function createFindTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('legacyEs'); + const es = getService('es'); const retry = getService('retry'); const supertestWithoutAuth = getService('supertestWithoutAuth'); const esTestIndexTool = new ESTestIndexTool(es, retry); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts index 2294cbcc95aa4..7bc3353898598 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts @@ -14,7 +14,7 @@ import { setupSpacesAndUsers } from '..'; // eslint-disable-next-line import/no-default-export export default function alertTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('legacyEs'); + const es = getService('es'); const retry = getService('retry'); const esArchiver = getService('esArchiver'); const supertestWithoutAuth = getService('supertestWithoutAuth'); @@ -204,11 +204,11 @@ export default function alertTests({ getService }: FtrProviderContext) { // ensure the alert still runs and that it can schedule actions const numberOfAlertExecutions = ( await esTestIndexTool.search('alert:test.always-firing', reference) - ).hits.total.value; + ).body.hits.total.value; const numberOfActionExecutions = ( await esTestIndexTool.search('action:test.index-record', reference) - ).hits.total.value; + ).body.hits.total.value; // wait for alert to execute and for its action to be scheduled and run await retry.try(async () => { @@ -222,8 +222,10 @@ export default function alertTests({ getService }: FtrProviderContext) { reference ); - expect(alertSearchResult.hits.total.value).to.be.greaterThan(numberOfAlertExecutions); - expect(actionSearchResult.hits.total.value).to.be.greaterThan( + expect(alertSearchResult.body.hits.total.value).to.be.greaterThan( + numberOfAlertExecutions + ); + expect(actionSearchResult.body.hits.total.value).to.be.greaterThan( numberOfActionExecutions ); }); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts index 2496800b8071c..3f4cef25ff65e 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts @@ -13,7 +13,7 @@ const ES_TEST_INDEX_NAME = 'functional-test-actions-index'; // eslint-disable-next-line import/no-default-export export default function indexTest({ getService }: FtrProviderContext) { - const es = getService('legacyEs'); + const es = getService('es'); const supertest = getService('supertest'); const esDeleteAllIndices = getService('esDeleteAllIndices'); @@ -149,5 +149,5 @@ async function getTestIndexItems(es: any) { index: ES_TEST_INDEX_NAME, }); - return result.hits.hits; + return result.body.hits.hits; } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/preconfigured_alert_history_connector.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/preconfigured_alert_history_connector.ts index cf8a0f99d4394..fe0f5d3ecbade 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/preconfigured_alert_history_connector.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/preconfigured_alert_history_connector.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; - +import type { ApiResponse, estypes } from '@elastic/elasticsearch'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { getTestAlertData, ObjectRemover } from '../../../../common/lib'; import { AlertHistoryDefaultIndexName } from '../../../../../../plugins/actions/common'; @@ -17,7 +17,7 @@ const ALERT_HISTORY_OVERRIDE_INDEX = 'kibana-alert-history-not-the-default'; export default function preconfiguredAlertHistoryConnectorTests({ getService, }: FtrProviderContext) { - const es = getService('legacyEs'); + const es = getService('es'); const supertest = getService('supertest'); const retry = getService('retry'); const esDeleteAllIndices = getService('esDeleteAllIndices'); @@ -66,10 +66,10 @@ export default function preconfiguredAlertHistoryConnectorTests({ await waitForStatus(response.body.id, new Set(['active'])); await retry.try(async () => { - const result = await es.search({ + const result: ApiResponse> = await es.search({ index: AlertHistoryDefaultIndexName, }); - const indexedItems = result.hits.hits; + const indexedItems = result.body.hits.hits; expect(indexedItems.length).to.eql(1); const indexedDoc = indexedItems[0]._source; @@ -104,10 +104,10 @@ export default function preconfiguredAlertHistoryConnectorTests({ await waitForStatus(response.body.id, new Set(['active'])); await retry.try(async () => { - const result = await es.search({ + const result: ApiResponse> = await es.search({ index: ALERT_HISTORY_OVERRIDE_INDEX, }); - const indexedItems = result.hits.hits; + const indexedItems = result.body.hits.hits; expect(indexedItems.length).to.eql(1); const indexedDoc = indexedItems[0]._source; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/enqueue.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/enqueue.ts index b6e47df315273..f937e63840937 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/enqueue.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/enqueue.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import type { estypes } from '@elastic/elasticsearch'; import { Spaces } from '../../scenarios'; import { ESTestIndexTool, @@ -18,7 +19,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('legacyEs'); + const es = getService('es'); const retry = getService('retry'); const esTestIndexTool = new ESTestIndexTool(es, retry); @@ -70,7 +71,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('should cleanup task after a failure', async () => { - const testStart = new Date(); + const testStart = new Date().toISOString(); const { body: createdAction } = await supertest .post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`) .set('kbn-xsrf', 'foo') @@ -135,7 +136,7 @@ export default function ({ getService }: FtrProviderContext) { }, }, }); - expect(searchResult.hits.total.value).to.eql(0); + expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.eql(0); }); }); }); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts index 38f3a17f317c2..d765512d6b5f1 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts @@ -22,7 +22,7 @@ const NANOS_IN_MILLIS = 1000 * 1000; // eslint-disable-next-line import/no-default-export export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('legacyEs'); + const es = getService('es'); const retry = getService('retry'); const esTestIndexTool = new ESTestIndexTool(es, retry); @@ -76,8 +76,8 @@ export default function ({ getService }: FtrProviderContext) { expect(response.status).to.eql(200); expect(response.body).to.be.an('object'); const searchResult = await esTestIndexTool.search('action:test.index-record', reference); - expect(searchResult.hits.total.value).to.eql(1); - const indexedRecord = searchResult.hits.hits[0]; + expect(searchResult.body.hits.total.value).to.eql(1); + const indexedRecord = searchResult.body.hits.hits[0]; expect(indexedRecord._source).to.eql({ params: { reference, @@ -211,8 +211,8 @@ export default function ({ getService }: FtrProviderContext) { expect(response.status).to.eql(200); const searchResult = await esTestIndexTool.search('action:test.authorization', reference); - expect(searchResult.hits.total.value).to.eql(1); - const indexedRecord = searchResult.hits.hits[0]; + expect(searchResult.body.hits.total.value).to.eql(1); + const indexedRecord = searchResult.body.hits.hits[0]; expect(indexedRecord._source.state).to.eql({ callClusterSuccess: true, callScopedClusterSuccess: true, diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts_base.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts_base.ts index 2ddea4e3ef299..999135993d069 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts_base.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts_base.ts @@ -7,6 +7,7 @@ import expect from '@kbn/expect'; import { omit } from 'lodash'; +import type { ApiResponse, estypes } from '@elastic/elasticsearch'; import { Response as SupertestResponse } from 'supertest'; import { RecoveredActionGroup } from '../../../../../plugins/alerting/common'; import { Space } from '../../../common/types'; @@ -21,10 +22,15 @@ import { ensureDatetimeIsWithinRange, TaskManagerUtils, } from '../../../common/lib'; +import { + TaskRunning, + TaskRunningStage, +} from '../../../../../plugins/task_manager/server/task_running'; +import { ConcreteTaskInstance } from '../../../../../plugins/task_manager/server'; export function alertTests({ getService }: FtrProviderContext, space: Space) { const supertestWithoutAuth = getService('supertestWithoutAuth'); - const es = getService('legacyEs'); + const es = getService('es'); const retry = getService('retry'); const esTestIndexTool = new ESTestIndexTool(es, retry); const taskManagerUtils = new TaskManagerUtils(es, retry); @@ -292,7 +298,7 @@ instanceStateValue: true await taskManagerUtils.waitForActionTaskParamsToBeCleanedUp(testStart); const actionTestRecord = await esTestIndexTool.search('action:test.index-record', reference); - expect(actionTestRecord.hits.total.value).to.eql(0); + expect(actionTestRecord.body.hits.total.value).to.eql(0); objectRemover.add(space.id, alertId, 'rule', 'alerting'); }); @@ -327,7 +333,7 @@ instanceStateValue: true it('should handle custom retry logic', async () => { // We'll use this start time to query tasks created after this point - const testStart = new Date(); + const testStart = new Date().toISOString(); // We have to provide the test.rate-limit the next runAt, for testing purposes const retryDate = new Date(Date.now() + 60000); @@ -370,8 +376,12 @@ instanceStateValue: true expect(response.statusCode).to.eql(200); objectRemover.add(space.id, response.body.id, 'rule', 'alerting'); - const scheduledActionTask = await retry.try(async () => { - const searchResult = await es.search({ + const scheduledActionTask: estypes.SearchHit< + TaskRunning + > = await retry.try(async () => { + const searchResult: ApiResponse< + estypes.SearchResponse> + > = await es.search({ index: '.kibana_task_manager', body: { query: { @@ -404,10 +414,10 @@ instanceStateValue: true }, }, }); - expect(searchResult.hits.total.value).to.eql(1); - return searchResult.hits.hits[0]; + expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.eql(1); + return searchResult.body.hits.hits[0]; }); - expect(scheduledActionTask._source.task.runAt).to.eql(retryDate.toISOString()); + expect(scheduledActionTask._source!.task.runAt).to.eql(retryDate.toISOString()); }); it('should have proper callCluster and savedObjectsClient authorization for alert type executor', async () => { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/alert.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/alert.ts index ebc03ffb0e952..29f2ed40be790 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/alert.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/alert.ts @@ -32,7 +32,7 @@ const ES_GROUPS_TO_WRITE = 3; export default function alertTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const retry = getService('retry'); - const es = getService('legacyEs'); + const es = getService('es'); const esTestIndexTool = new ESTestIndexTool(es, retry); const esTestIndexToolOutput = new ESTestIndexTool(es, retry, ES_TEST_OUTPUT_INDEX_NAME); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/create_test_data.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/create_test_data.ts index 8c8d8e84132a9..f3c707c58af1c 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/create_test_data.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/create_test_data.ts @@ -54,7 +54,7 @@ async function createEsDocument(es: any, epochMillis: number, testedValue: numbe body: document, }); - if (response.result !== 'created') { + if (response.body.result !== 'created') { throw new Error(`document not created: ${JSON.stringify(response)}`); } } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts index 3d7e391d7530f..6ea4cbf0e96ba 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/alert.ts @@ -31,7 +31,7 @@ const ALERT_INTERVAL_MILLIS = ALERT_INTERVAL_SECONDS * 1000; export default function alertTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const retry = getService('retry'); - const es = getService('legacyEs'); + const es = getService('es'); const esTestIndexTool = new ESTestIndexTool(es, retry); const esTestIndexToolOutput = new ESTestIndexTool(es, retry, ES_TEST_OUTPUT_INDEX_NAME); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/create_test_data.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/create_test_data.ts index 9c36831f61f76..b9faadcd3d4b7 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/create_test_data.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/create_test_data.ts @@ -66,7 +66,7 @@ async function createEsDocument(es: any, epochMillis: number, testedValue: numbe }); // console.log(`writing document to ${ES_TEST_INDEX_NAME}:`, JSON.stringify(document, null, 4)); - if (response.result !== 'created') { + if (response.body.result !== 'created') { throw new Error(`document not created: ${JSON.stringify(response)}`); } } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/fields_endpoint.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/fields_endpoint.ts index 4971a09f9632c..0a48e206e020e 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/fields_endpoint.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/fields_endpoint.ts @@ -17,7 +17,7 @@ const API_URI = 'api/triggers_actions_ui/data/_fields'; export default function fieldsEndpointTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const retry = getService('retry'); - const es = getService('legacyEs'); + const es = getService('es'); const esTestIndexTool = new ESTestIndexTool(es, retry); describe('fields endpoint', () => { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/indices_endpoint.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/indices_endpoint.ts index d994ada5842d3..6d4f4a6aa6cc9 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/indices_endpoint.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/indices_endpoint.ts @@ -18,7 +18,7 @@ const API_URI = 'api/triggers_actions_ui/data/_indices'; export default function indicesEndpointTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const retry = getService('retry'); - const es = getService('legacyEs'); + const es = getService('es'); const esTestIndexTool = new ESTestIndexTool(es, retry); describe('indices endpoint', () => { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/time_series_query_endpoint.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/time_series_query_endpoint.ts index 49fe427e50af4..741f198607c3e 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/time_series_query_endpoint.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/time_series_query_endpoint.ts @@ -51,7 +51,7 @@ const START_DATE_MINUS_2INTERVALS = getStartDate(-2 * INTERVAL_MILLIS); export default function timeSeriesQueryEndpointTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const retry = getService('retry'); - const es = getService('legacyEs'); + const es = getService('es'); const esTestIndexTool = new ESTestIndexTool(es, retry); describe('time_series_query endpoint', () => { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts index 96534c192d67c..6f0f78b6d63ee 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import type { ApiResponse, estypes } from '@elastic/elasticsearch'; import { Spaces } from '../../scenarios'; import { checkAAD, @@ -13,24 +14,26 @@ import { getTestAlertData, ObjectRemover, getConsumerUnauthorizedErrorMessage, + TaskManagerDoc, } from '../../../common/lib'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createAlertTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('legacyEs'); + const es = getService('es'); describe('create', () => { const objectRemover = new ObjectRemover(supertest); after(() => objectRemover.removeAll()); - async function getScheduledTask(id: string) { - return await es.get({ + async function getScheduledTask(id: string): Promise { + const scheduledTask: ApiResponse> = await es.get({ id: `task:${id}`, index: '.kibana_task_manager', }); + return scheduledTask.body._source!; } it('should handle create alert request appropriately', async () => { @@ -96,7 +99,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { expect(Date.parse(response.body.updated_at)).to.eql(Date.parse(response.body.created_at)); expect(typeof response.body.scheduled_task_id).to.be('string'); - const { _source: taskRecord } = await getScheduledTask(response.body.scheduled_task_id); + const taskRecord = await getScheduledTask(response.body.scheduled_task_id); expect(taskRecord.type).to.eql('task'); expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); expect(JSON.parse(taskRecord.task.params)).to.eql({ @@ -328,7 +331,7 @@ export default function createAlertTests({ getService }: FtrProviderContext) { expect(Date.parse(response.body.updatedAt)).to.eql(Date.parse(response.body.createdAt)); expect(typeof response.body.scheduledTaskId).to.be('string'); - const { _source: taskRecord } = await getScheduledTask(response.body.scheduledTaskId); + const taskRecord = await getScheduledTask(response.body.scheduledTaskId); expect(taskRecord.type).to.eql('task'); expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); expect(JSON.parse(taskRecord.task.params)).to.eql({ diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts index 04ae217d47760..0a2df70b6316a 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/delete.ts @@ -13,7 +13,7 @@ import { FtrProviderContext } from '../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function createDeleteTests({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('legacyEs'); + const es = getService('es'); describe('delete', () => { const objectRemover = new ObjectRemover(supertest); @@ -43,7 +43,7 @@ export default function createDeleteTests({ getService }: FtrProviderContext) { await getScheduledTask(createdAlert.scheduledTaskId); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } }); @@ -81,7 +81,7 @@ export default function createDeleteTests({ getService }: FtrProviderContext) { await getScheduledTask(createdAlert.scheduledTaskId); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } }); }); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts index 60749343cf269..7e93cf453929b 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/disable.ts @@ -18,7 +18,7 @@ import { // eslint-disable-next-line import/no-default-export export default function createDisableAlertTests({ getService }: FtrProviderContext) { - const es = getService('legacyEs'); + const es = getService('es'); const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('disable', () => { @@ -48,7 +48,7 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte await getScheduledTask(createdAlert.scheduledTaskId); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } // Ensure AAD isn't broken @@ -93,7 +93,7 @@ export default function createDisableAlertTests({ getService }: FtrProviderConte await getScheduledTask(createdAlert.scheduledTaskId); throw new Error('Should have removed scheduled task'); } catch (e) { - expect(e.status).to.eql(404); + expect(e.meta.statusCode).to.eql(404); } // Ensure AAD isn't broken diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts index f0b0d1f34a277..881931252ed5f 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import type { ApiResponse, estypes } from '@elastic/elasticsearch'; import { Spaces } from '../../scenarios'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { @@ -14,11 +15,12 @@ import { getUrlPrefix, getTestAlertData, ObjectRemover, + TaskManagerDoc, } from '../../../common/lib'; // eslint-disable-next-line import/no-default-export export default function createEnableAlertTests({ getService }: FtrProviderContext) { - const es = getService('legacyEs'); + const es = getService('es'); const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('enable', () => { @@ -27,11 +29,12 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex after(() => objectRemover.removeAll()); - async function getScheduledTask(id: string) { - return await es.get({ + async function getScheduledTask(id: string): Promise { + const scheduledTask: ApiResponse> = await es.get({ id: `task:${id}`, index: '.kibana_task_manager', }); + return scheduledTask.body._source!; } it('should handle enable alert request appropriately', async () => { @@ -49,7 +52,7 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex .set('kbn-xsrf', 'foo') .expect(200); expect(typeof updatedAlert.scheduled_task_id).to.eql('string'); - const { _source: taskRecord } = await getScheduledTask(updatedAlert.scheduled_task_id); + const taskRecord = await getScheduledTask(updatedAlert.scheduled_task_id); expect(taskRecord.type).to.eql('task'); expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); expect(JSON.parse(taskRecord.task.params)).to.eql({ @@ -100,7 +103,7 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex .set('kbn-xsrf', 'foo') .expect(200); expect(typeof updatedAlert.scheduled_task_id).to.eql('string'); - const { _source: taskRecord } = await getScheduledTask(updatedAlert.scheduled_task_id); + const taskRecord = await getScheduledTask(updatedAlert.scheduled_task_id); expect(taskRecord.type).to.eql('task'); expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); expect(JSON.parse(taskRecord.task.params)).to.eql({ diff --git a/x-pack/test/plugin_api_integration/test_suites/event_log/service_api_integration.ts b/x-pack/test/plugin_api_integration/test_suites/event_log/service_api_integration.ts index 960deb692ac8d..e17b1400e6781 100644 --- a/x-pack/test/plugin_api_integration/test_suites/event_log/service_api_integration.ts +++ b/x-pack/test/plugin_api_integration/test_suites/event_log/service_api_integration.ts @@ -12,7 +12,7 @@ import { IEvent } from '../../../../plugins/event_log/server'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { - const es = getService('legacyEs'); + const es = getService('es'); const supertest = getService('supertest'); const log = getService('log'); const config = getService('config'); @@ -41,7 +41,7 @@ export default function ({ getService }: FtrProviderContext) { .find((val: string) => val === '--xpack.eventLog.indexEntries=true'); const result = await isIndexingEntries(); const exists = await es.indices.exists({ index: '.kibana-event-log-*' }); - expect(exists).to.be.eql(true); + expect(exists.body).to.be.eql(true); expect(configValue).to.be.eql( `--xpack.eventLog.indexEntries=${result.body.isIndexingEntries}` ); From dd20b8adb65c2d974ee8c04fe34fd6b3aac36b97 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Thu, 24 Jun 2021 18:22:14 +0200 Subject: [PATCH 02/25] Avoid using deprecated camelCase parameters for SAML APIs. (#103091) --- .../security/server/authentication/providers/saml.test.ts | 8 ++++---- .../security/server/authentication/providers/saml.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security/server/authentication/providers/saml.test.ts b/x-pack/plugins/security/server/authentication/providers/saml.test.ts index dfcdb66e61c35..4a32383d18dec 100644 --- a/x-pack/plugins/security/server/authentication/providers/saml.test.ts +++ b/x-pack/plugins/security/server/authentication/providers/saml.test.ts @@ -1186,7 +1186,7 @@ describe('SAMLAuthenticationProvider', () => { expect(mockOptions.client.asInternalUser.transport.request).toHaveBeenCalledWith({ method: 'POST', path: '/_security/saml/invalidate', - body: { queryString: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' }, + body: { query_string: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' }, }); }); @@ -1286,7 +1286,7 @@ describe('SAMLAuthenticationProvider', () => { expect(mockOptions.client.asInternalUser.transport.request).toHaveBeenCalledWith({ method: 'POST', path: '/_security/saml/invalidate', - body: { queryString: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' }, + body: { query_string: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' }, }); }); @@ -1305,7 +1305,7 @@ describe('SAMLAuthenticationProvider', () => { expect(mockOptions.client.asInternalUser.transport.request).toHaveBeenCalledWith({ method: 'POST', path: '/_security/saml/invalidate', - body: { queryString: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' }, + body: { query_string: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' }, }); }); @@ -1324,7 +1324,7 @@ describe('SAMLAuthenticationProvider', () => { expect(mockOptions.client.asInternalUser.transport.request).toHaveBeenCalledWith({ method: 'POST', path: '/_security/saml/invalidate', - body: { queryString: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' }, + body: { query_string: 'SAMLRequest=xxx%20yyy', realm: 'test-realm' }, }); }); diff --git a/x-pack/plugins/security/server/authentication/providers/saml.ts b/x-pack/plugins/security/server/authentication/providers/saml.ts index ea818e5df6e12..37e7e868e4d3d 100644 --- a/x-pack/plugins/security/server/authentication/providers/saml.ts +++ b/x-pack/plugins/security/server/authentication/providers/saml.ts @@ -624,9 +624,9 @@ export class SAMLAuthenticationProvider extends BaseAuthenticationProvider { await this.options.client.asInternalUser.transport.request({ method: 'POST', path: '/_security/saml/invalidate', - // Elasticsearch expects `queryString` without leading `?`, so we should strip it with `slice`. + // Elasticsearch expects `query_string` without leading `?`, so we should strip it with `slice`. body: { - queryString: request.url.search ? request.url.search.slice(1) : '', + query_string: request.url.search ? request.url.search.slice(1) : '', realm: this.realm, }, }) From 5e898734d5c5fcd4d1d9cffaf4a02d78b94e6bd7 Mon Sep 17 00:00:00 2001 From: Bryan Clement Date: Thu, 24 Jun 2021 09:31:57 -0700 Subject: [PATCH 03/25] [Asset management] Osquery app bug squashing (#102406) * only display healthy agents to query * updated toasts to clear on update * null checking aggBuckets * properly display expired actions * clear the error toasts on success * review comments Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../action_results/action_results_summary.tsx | 58 ++++++++++++------- .../action_results/use_action_results.ts | 14 ++--- .../public/actions/use_action_details.ts | 10 ++-- .../osquery/public/actions/use_all_actions.ts | 10 ++-- .../agent_policies/use_agent_policies.ts | 10 ++-- .../public/agent_policies/use_agent_policy.ts | 10 ++-- .../osquery/public/agents/use_agent_groups.ts | 10 ++-- .../public/agents/use_agent_policies.ts | 10 ++-- .../osquery/public/agents/use_agent_status.ts | 10 ++-- .../osquery/public/agents/use_all_agents.ts | 25 ++++---- .../public/agents/use_osquery_policies.ts | 10 ++-- .../public/common/hooks/use_error_toast.tsx | 26 +++++++++ .../common/hooks/use_osquery_integration.tsx | 9 ++- .../public/live_queries/form/index.tsx | 28 ++++++--- .../osquery/public/queries/edit/tabs.tsx | 11 +++- .../osquery/public/results/use_all_results.ts | 10 ++-- .../routes/live_queries/details/index.tsx | 23 ++++++-- .../active_state_switch.tsx | 5 +- .../scheduled_query_groups/form/index.tsx | 5 +- .../osquery/server/lib/parse_agent_groups.ts | 4 +- 20 files changed, 186 insertions(+), 112 deletions(-) create mode 100644 x-pack/plugins/osquery/public/common/hooks/use_error_toast.tsx diff --git a/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx b/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx index 23eaaeac1439d..257c89047aab0 100644 --- a/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx +++ b/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx @@ -36,6 +36,7 @@ const StyledEuiCard = styled(EuiCard)` interface ActionResultsSummaryProps { actionId: string; + expirationDate: Date; agentIds?: string[]; isLive?: boolean; } @@ -48,6 +49,7 @@ const renderErrorMessage = (error: string) => ( const ActionResultsSummaryComponent: React.FC = ({ actionId, + expirationDate, agentIds, isLive, }) => { @@ -56,6 +58,7 @@ const ActionResultsSummaryComponent: React.FC = ({ const [pageIndex, setPageIndex] = useState(0); // @ts-expect-error update types const [pageSize, setPageSize] = useState(50); + const expired = useMemo(() => expirationDate < new Date(), [expirationDate]); const { // @ts-expect-error update types data: { aggregations, edges }, @@ -66,7 +69,7 @@ const ActionResultsSummaryComponent: React.FC = ({ limit: pageSize, direction: Direction.asc, sortField: '@timestamp', - isLive, + isLive: !expired && isLive, }); const { data: logsResults } = useAllResults({ @@ -79,7 +82,7 @@ const ActionResultsSummaryComponent: React.FC = ({ direction: Direction.asc, }, ], - isLive, + isLive: !expired && isLive, }); const notRespondedCount = useMemo(() => { @@ -108,9 +111,13 @@ const ActionResultsSummaryComponent: React.FC = ({ description: aggregations.successful, }, { - title: i18n.translate('xpack.osquery.liveQueryActionResults.summary.pendingLabelText', { - defaultMessage: 'Not yet responded', - }), + title: expired + ? i18n.translate('xpack.osquery.liveQueryActionResults.summary.expiredLabelText', { + defaultMessage: 'Expired', + }) + : i18n.translate('xpack.osquery.liveQueryActionResults.summary.pendingLabelText', { + defaultMessage: 'Not yet responded', + }), description: notRespondedCount, }, { @@ -124,7 +131,7 @@ const ActionResultsSummaryComponent: React.FC = ({ ), }, ], - [agentIds, aggregations.failed, aggregations.successful, notRespondedCount] + [agentIds, aggregations.failed, aggregations.successful, notRespondedCount, expired] ); const renderAgentIdColumn = useCallback( @@ -158,23 +165,30 @@ const ActionResultsSummaryComponent: React.FC = ({ [logsResults] ); - const renderStatusColumn = useCallback((_, item) => { - if (!item.fields.completed_at) { - return i18n.translate('xpack.osquery.liveQueryActionResults.table.pendingStatusText', { - defaultMessage: 'pending', - }); - } + const renderStatusColumn = useCallback( + (_, item) => { + if (!item.fields.completed_at) { + return expired + ? i18n.translate('xpack.osquery.liveQueryActionResults.table.expiredStatusText', { + defaultMessage: 'expired', + }) + : i18n.translate('xpack.osquery.liveQueryActionResults.table.pendingStatusText', { + defaultMessage: 'pending', + }); + } - if (item.fields['error.keyword']) { - return i18n.translate('xpack.osquery.liveQueryActionResults.table.errorStatusText', { - defaultMessage: 'error', - }); - } + if (item.fields['error.keyword']) { + return i18n.translate('xpack.osquery.liveQueryActionResults.table.errorStatusText', { + defaultMessage: 'error', + }); + } - return i18n.translate('xpack.osquery.liveQueryActionResults.table.successStatusText', { - defaultMessage: 'success', - }); - }, []); + return i18n.translate('xpack.osquery.liveQueryActionResults.table.successStatusText', { + defaultMessage: 'success', + }); + }, + [expired] + ); const columns = useMemo( () => [ @@ -227,7 +241,7 @@ const ActionResultsSummaryComponent: React.FC = ({ - {notRespondedCount ? : null} + {!expired && notRespondedCount ? : null} { - const { - data, - notifications: { toasts }, - } = useKibana().services; + const { data } = useKibana().services; + const setErrorToast = useErrorToast(); return useQuery( ['actionResults', { actionId }], @@ -103,9 +102,9 @@ export const useActionResults = ({ aggregations: { totalResponded, // @ts-expect-error update types - successful: aggsBuckets.find((bucket) => bucket.key === 'success')?.doc_count ?? 0, + successful: aggsBuckets?.find((bucket) => bucket.key === 'success')?.doc_count ?? 0, // @ts-expect-error update types - failed: aggsBuckets.find((bucket) => bucket.key === 'error')?.doc_count ?? 0, + failed: aggsBuckets?.find((bucket) => bucket.key === 'error')?.doc_count ?? 0, }, inspect: getInspectResponse(responseData, {} as InspectResponse), }; @@ -124,8 +123,9 @@ export const useActionResults = ({ refetchInterval: isLive ? 1000 : false, keepPreviousData: true, enabled: !skip && !!agentIds?.length, + onSuccess: () => setErrorToast(), onError: (error: Error) => - toasts.addError(error, { + setErrorToast(error, { title: i18n.translate('xpack.osquery.action_results.fetchError', { defaultMessage: 'Error while fetching action results', }), diff --git a/x-pack/plugins/osquery/public/actions/use_action_details.ts b/x-pack/plugins/osquery/public/actions/use_action_details.ts index bb260cd78ca76..445912b27bc93 100644 --- a/x-pack/plugins/osquery/public/actions/use_action_details.ts +++ b/x-pack/plugins/osquery/public/actions/use_action_details.ts @@ -18,6 +18,7 @@ import { import { ESTermQuery } from '../../common/typed_json'; import { getInspectResponse, InspectResponse } from './helpers'; +import { useErrorToast } from '../common/hooks/use_error_toast'; export interface ActionDetailsArgs { actionDetails: Record; @@ -33,10 +34,8 @@ interface UseActionDetails { } export const useActionDetails = ({ actionId, filterQuery, skip = false }: UseActionDetails) => { - const { - data, - notifications: { toasts }, - } = useKibana().services; + const { data } = useKibana().services; + const setErrorToast = useErrorToast(); return useQuery( ['actionDetails', { actionId, filterQuery }], @@ -61,8 +60,9 @@ export const useActionDetails = ({ actionId, filterQuery, skip = false }: UseAct }, { enabled: !skip, + onSuccess: () => setErrorToast(), onError: (error: Error) => - toasts.addError(error, { + setErrorToast(error, { title: i18n.translate('xpack.osquery.action_details.fetchError', { defaultMessage: 'Error while fetching action details', }), diff --git a/x-pack/plugins/osquery/public/actions/use_all_actions.ts b/x-pack/plugins/osquery/public/actions/use_all_actions.ts index 375d108c4dd8b..ae872d3c1ed52 100644 --- a/x-pack/plugins/osquery/public/actions/use_all_actions.ts +++ b/x-pack/plugins/osquery/public/actions/use_all_actions.ts @@ -21,6 +21,7 @@ import { import { ESTermQuery } from '../../common/typed_json'; import { generateTablePaginationOptions, getInspectResponse, InspectResponse } from './helpers'; +import { useErrorToast } from '../common/hooks/use_error_toast'; export interface ActionsArgs { actions: ActionEdges; @@ -48,10 +49,8 @@ export const useAllActions = ({ filterQuery, skip = false, }: UseAllActions) => { - const { - data, - notifications: { toasts }, - } = useKibana().services; + const { data } = useKibana().services; + const setErrorToast = useErrorToast(); return useQuery( ['actions', { activePage, direction, limit, sortField }], @@ -82,8 +81,9 @@ export const useAllActions = ({ { keepPreviousData: true, enabled: !skip, + onSuccess: () => setErrorToast(), onError: (error: Error) => - toasts.addError(error, { + setErrorToast(error, { title: i18n.translate('xpack.osquery.all_actions.fetchError', { defaultMessage: 'Error while fetching actions', }), diff --git a/x-pack/plugins/osquery/public/agent_policies/use_agent_policies.ts b/x-pack/plugins/osquery/public/agent_policies/use_agent_policies.ts index d4bd0a1f4277f..6f87610667198 100644 --- a/x-pack/plugins/osquery/public/agent_policies/use_agent_policies.ts +++ b/x-pack/plugins/osquery/public/agent_policies/use_agent_policies.ts @@ -14,12 +14,11 @@ import { GetAgentPoliciesResponse, GetAgentPoliciesResponseItem, } from '../../../fleet/common'; +import { useErrorToast } from '../common/hooks/use_error_toast'; export const useAgentPolicies = () => { - const { - http, - notifications: { toasts }, - } = useKibana().services; + const { http } = useKibana().services; + const setErrorToast = useErrorToast(); return useQuery( ['agentPolicies'], @@ -34,8 +33,9 @@ export const useAgentPolicies = () => { placeholderData: [], keepPreviousData: true, select: (response) => response.items, + onSuccess: () => setErrorToast(), onError: (error) => - toasts.addError(error as Error, { + setErrorToast(error as Error, { title: i18n.translate('xpack.osquery.agent_policies.fetchError', { defaultMessage: 'Error while fetching agent policies', }), diff --git a/x-pack/plugins/osquery/public/agent_policies/use_agent_policy.ts b/x-pack/plugins/osquery/public/agent_policies/use_agent_policy.ts index e87d8d1c9f28e..dcebf136b6773 100644 --- a/x-pack/plugins/osquery/public/agent_policies/use_agent_policy.ts +++ b/x-pack/plugins/osquery/public/agent_policies/use_agent_policy.ts @@ -10,6 +10,7 @@ import { useQuery } from 'react-query'; import { i18n } from '@kbn/i18n'; import { useKibana } from '../common/lib/kibana'; import { agentPolicyRouteService } from '../../../fleet/common'; +import { useErrorToast } from '../common/hooks/use_error_toast'; interface UseAgentPolicy { policyId: string; @@ -17,10 +18,8 @@ interface UseAgentPolicy { } export const useAgentPolicy = ({ policyId, skip }: UseAgentPolicy) => { - const { - http, - notifications: { toasts }, - } = useKibana().services; + const { http } = useKibana().services; + const setErrorToast = useErrorToast(); return useQuery( ['agentPolicy', { policyId }], @@ -29,8 +28,9 @@ export const useAgentPolicy = ({ policyId, skip }: UseAgentPolicy) => { enabled: !skip, keepPreviousData: true, select: (response) => response.item, + onSuccess: () => setErrorToast(), onError: (error: Error) => - toasts.addError(error, { + setErrorToast(error, { title: i18n.translate('xpack.osquery.agent_policy_details.fetchError', { defaultMessage: 'Error while fetching agent policy details', }), diff --git a/x-pack/plugins/osquery/public/agents/use_agent_groups.ts b/x-pack/plugins/osquery/public/agents/use_agent_groups.ts index 44737af9d3477..bfa224a23135b 100644 --- a/x-pack/plugins/osquery/public/agents/use_agent_groups.ts +++ b/x-pack/plugins/osquery/public/agents/use_agent_groups.ts @@ -18,6 +18,7 @@ import { import { generateTablePaginationOptions, processAggregations } from './helpers'; import { Overlap, Group } from './types'; +import { useErrorToast } from '../common/hooks/use_error_toast'; interface UseAgentGroups { osqueryPolicies: string[]; @@ -25,10 +26,8 @@ interface UseAgentGroups { } export const useAgentGroups = ({ osqueryPolicies, osqueryPoliciesLoading }: UseAgentGroups) => { - const { - data, - notifications: { toasts }, - } = useKibana().services; + const { data } = useKibana().services; + const setErrorToast = useErrorToast(); const { agentPoliciesLoading, agentPolicyById } = useAgentPolicies(osqueryPolicies); const [platforms, setPlatforms] = useState([]); @@ -100,8 +99,9 @@ export const useAgentGroups = ({ osqueryPolicies, osqueryPoliciesLoading }: UseA }, { enabled: !osqueryPoliciesLoading && !agentPoliciesLoading, + onSuccess: () => setErrorToast(), onError: (error) => - toasts.addError(error as Error, { + setErrorToast(error as Error, { title: i18n.translate('xpack.osquery.agent_groups.fetchError', { defaultMessage: 'Error while fetching agent groups', }), diff --git a/x-pack/plugins/osquery/public/agents/use_agent_policies.ts b/x-pack/plugins/osquery/public/agents/use_agent_policies.ts index ecb95fff8838e..115b5af9d3a1b 100644 --- a/x-pack/plugins/osquery/public/agents/use_agent_policies.ts +++ b/x-pack/plugins/osquery/public/agents/use_agent_policies.ts @@ -10,20 +10,20 @@ import { useQueries, UseQueryResult } from 'react-query'; import { i18n } from '@kbn/i18n'; import { useKibana } from '../common/lib/kibana'; import { agentPolicyRouteService, GetOneAgentPolicyResponse } from '../../../fleet/common'; +import { useErrorToast } from '../common/hooks/use_error_toast'; export const useAgentPolicies = (policyIds: string[] = []) => { - const { - http, - notifications: { toasts }, - } = useKibana().services; + const { http } = useKibana().services; + const setErrorToast = useErrorToast(); const agentResponse = useQueries( policyIds.map((policyId) => ({ queryKey: ['agentPolicy', policyId], queryFn: () => http.get(agentPolicyRouteService.getInfoPath(policyId)), enabled: policyIds.length > 0, + onSuccess: () => setErrorToast(), onError: (error) => - toasts.addError(error as Error, { + setErrorToast(error as Error, { title: i18n.translate('xpack.osquery.action_policy_details.fetchError', { defaultMessage: 'Error while fetching policy details', }), diff --git a/x-pack/plugins/osquery/public/agents/use_agent_status.ts b/x-pack/plugins/osquery/public/agents/use_agent_status.ts index 4954eb0dc80c4..c8bc8d2fe5c0e 100644 --- a/x-pack/plugins/osquery/public/agents/use_agent_status.ts +++ b/x-pack/plugins/osquery/public/agents/use_agent_status.ts @@ -9,6 +9,7 @@ import { i18n } from '@kbn/i18n'; import { useQuery } from 'react-query'; import { GetAgentStatusResponse, agentRouteService } from '../../../fleet/common'; +import { useErrorToast } from '../common/hooks/use_error_toast'; import { useKibana } from '../common/lib/kibana'; interface UseAgentStatus { @@ -17,10 +18,8 @@ interface UseAgentStatus { } export const useAgentStatus = ({ policyId, skip }: UseAgentStatus) => { - const { - http, - notifications: { toasts }, - } = useKibana().services; + const { http } = useKibana().services; + const setErrorToast = useErrorToast(); return useQuery( ['agentStatus', policyId], @@ -38,8 +37,9 @@ export const useAgentStatus = ({ policyId, skip }: UseAgentStatus) => { { enabled: !skip, select: (response) => response.results, + onSuccess: () => setErrorToast(), onError: (error) => - toasts.addError(error as Error, { + setErrorToast(error as Error, { title: i18n.translate('xpack.osquery.agent_status.fetchError', { defaultMessage: 'Error while fetching agent status', }), diff --git a/x-pack/plugins/osquery/public/agents/use_all_agents.ts b/x-pack/plugins/osquery/public/agents/use_all_agents.ts index 674deb3b339bd..30ba4d2f57907 100644 --- a/x-pack/plugins/osquery/public/agents/use_all_agents.ts +++ b/x-pack/plugins/osquery/public/agents/use_all_agents.ts @@ -9,6 +9,7 @@ import { i18n } from '@kbn/i18n'; import { useQuery } from 'react-query'; import { GetAgentsResponse, agentRouteService } from '../../../fleet/common'; +import { useErrorToast } from '../common/hooks/use_error_toast'; import { useKibana } from '../common/lib/kibana'; interface UseAllAgents { @@ -28,36 +29,30 @@ export const useAllAgents = ( opts: RequestOptions = { perPage: 9000 } ) => { const { perPage } = opts; - const { - http, - notifications: { toasts }, - } = useKibana().services; + const { http } = useKibana().services; + const setErrorToast = useErrorToast(); const { isLoading: agentsLoading, data: agentData } = useQuery( ['agents', osqueryPolicies, searchValue, perPage], () => { - const kueryFragments: string[] = []; - if (osqueryPolicies.length) { - kueryFragments.push(`${osqueryPolicies.map((p) => `policy_id:${p}`).join(' or ')}`); - } + const policyFragment = osqueryPolicies.map((p) => `policy_id:${p}`).join(' or '); + let kuery = `last_checkin_status: online and (${policyFragment})`; if (searchValue) { - kueryFragments.push( - `local_metadata.host.hostname:*${searchValue}* or local_metadata.elastic.agent.id:*${searchValue}*` - ); + kuery += `and (local_metadata.host.hostname:*${searchValue}* or local_metadata.elastic.agent.id:*${searchValue}*)`; } return http.get(agentRouteService.getListPath(), { query: { - kuery: kueryFragments.map((frag) => `(${frag})`).join(' and '), + kuery, perPage, - showInactive: true, }, }); }, { - enabled: !osqueryPoliciesLoading, + enabled: !osqueryPoliciesLoading && osqueryPolicies.length > 0, + onSuccess: () => setErrorToast(), onError: (error) => - toasts.addError(error as Error, { + setErrorToast(error as Error, { title: i18n.translate('xpack.osquery.agents.fetchError', { defaultMessage: 'Error while fetching agents', }), diff --git a/x-pack/plugins/osquery/public/agents/use_osquery_policies.ts b/x-pack/plugins/osquery/public/agents/use_osquery_policies.ts index 0eb94af73e3a8..9064dac1ae5d0 100644 --- a/x-pack/plugins/osquery/public/agents/use_osquery_policies.ts +++ b/x-pack/plugins/osquery/public/agents/use_osquery_policies.ts @@ -12,12 +12,11 @@ import { i18n } from '@kbn/i18n'; import { useKibana } from '../common/lib/kibana'; import { packagePolicyRouteService, PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '../../../fleet/common'; import { OSQUERY_INTEGRATION_NAME } from '../../common'; +import { useErrorToast } from '../common/hooks/use_error_toast'; export const useOsqueryPolicies = () => { - const { - http, - notifications: { toasts }, - } = useKibana().services; + const { http } = useKibana().services; + const setErrorToast = useErrorToast(); const { isLoading: osqueryPoliciesLoading, data: osqueryPolicies = [] } = useQuery( ['osqueryPolicies'], @@ -30,8 +29,9 @@ export const useOsqueryPolicies = () => { { select: (response) => uniq(response.items.map((p: { policy_id: string }) => p.policy_id)), + onSuccess: () => setErrorToast(), onError: (error: Error) => - toasts.addError(error, { + setErrorToast(error, { title: i18n.translate('xpack.osquery.osquery_policies.fetchError', { defaultMessage: 'Error while fetching osquery policies', }), diff --git a/x-pack/plugins/osquery/public/common/hooks/use_error_toast.tsx b/x-pack/plugins/osquery/public/common/hooks/use_error_toast.tsx new file mode 100644 index 0000000000000..fb17803a9d57b --- /dev/null +++ b/x-pack/plugins/osquery/public/common/hooks/use_error_toast.tsx @@ -0,0 +1,26 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ErrorToastOptions, Toast } from 'kibana/public'; +import { useState } from 'react'; +import { useKibana } from '../../common/lib/kibana'; + +export const useErrorToast = () => { + const [errorToast, setErrorToast] = useState(); + const { + notifications: { toasts }, + } = useKibana().services; + return (error?: unknown, opts?: ErrorToastOptions) => { + if (errorToast) { + toasts.remove(errorToast); + } + if (error) { + // @ts-expect-error update types + setErrorToast(toasts.addError(error, opts)); + } + }; +}; diff --git a/x-pack/plugins/osquery/public/common/hooks/use_osquery_integration.tsx b/x-pack/plugins/osquery/public/common/hooks/use_osquery_integration.tsx index ccfb407eab58b..236fdb1af1815 100644 --- a/x-pack/plugins/osquery/public/common/hooks/use_osquery_integration.tsx +++ b/x-pack/plugins/osquery/public/common/hooks/use_osquery_integration.tsx @@ -12,12 +12,11 @@ import { useQuery } from 'react-query'; import { GetPackagesResponse, epmRouteService } from '../../../../fleet/common'; import { OSQUERY_INTEGRATION_NAME } from '../../../common'; import { useKibana } from '../lib/kibana'; +import { useErrorToast } from './use_error_toast'; export const useOsqueryIntegration = () => { - const { - http, - notifications: { toasts }, - } = useKibana().services; + const { http } = useKibana().services; + const setErrorToast = useErrorToast(); return useQuery( 'integrations', @@ -31,7 +30,7 @@ export const useOsqueryIntegration = () => { select: ({ response }: GetPackagesResponse) => find(['name', OSQUERY_INTEGRATION_NAME], response), onError: (error: Error) => - toasts.addError(error, { + setErrorToast(error, { title: i18n.translate('xpack.osquery.osquery_integration.fetchError', { defaultMessage: 'Error while fetching osquery integration', }), diff --git a/x-pack/plugins/osquery/public/live_queries/form/index.tsx b/x-pack/plugins/osquery/public/live_queries/form/index.tsx index 4cf2d4aa4fe91..6f2d1afec6fe9 100644 --- a/x-pack/plugins/osquery/public/live_queries/form/index.tsx +++ b/x-pack/plugins/osquery/public/live_queries/form/index.tsx @@ -19,6 +19,7 @@ import { useKibana } from '../../common/lib/kibana'; import { ResultTabs } from '../../queries/edit/tabs'; import { queryFieldValidation } from '../../common/validations'; import { fieldValidators } from '../../shared_imports'; +import { useErrorToast } from '../../common/hooks/use_error_toast'; const FORM_ID = 'liveQueryForm'; @@ -35,10 +36,9 @@ const LiveQueryFormComponent: React.FC = ({ // onSubmit, onSuccess, }) => { - const { - http, - notifications: { toasts }, - } = useKibana().services; + const { http } = useKibana().services; + + const setErrorToast = useErrorToast(); const { data, @@ -53,14 +53,20 @@ const LiveQueryFormComponent: React.FC = ({ body: JSON.stringify(payload), }), { - onSuccess, + onSuccess: () => { + setErrorToast(); + if (onSuccess) { + onSuccess(); + } + }, onError: (error) => { - // @ts-expect-error update types - toasts.addError(error, { title: error.body.error, toastMessage: error.body.message }); + setErrorToast(error); }, } ); + const expirationDate = useMemo(() => new Date(data?.actions[0].expiration), [data?.actions]); + const formSchema = { query: { type: FIELD_TYPES.TEXT, @@ -173,7 +179,12 @@ const LiveQueryFormComponent: React.FC = ({ defaultMessage: 'Check results', }), children: actionId ? ( - + ) : null, status: resultsStatus, }, @@ -185,6 +196,7 @@ const LiveQueryFormComponent: React.FC = ({ queryComponentProps, queryStatus, queryValueProvided, + expirationDate, resultsStatus, submit, ] diff --git a/x-pack/plugins/osquery/public/queries/edit/tabs.tsx b/x-pack/plugins/osquery/public/queries/edit/tabs.tsx index 978c3f938f1d6..2c9421606ea30 100644 --- a/x-pack/plugins/osquery/public/queries/edit/tabs.tsx +++ b/x-pack/plugins/osquery/public/queries/edit/tabs.tsx @@ -14,6 +14,7 @@ import { ActionResultsSummary } from '../../action_results/action_results_summar interface ResultTabsProps { actionId: string; agentIds?: string[]; + expirationDate: Date; isLive?: boolean; startDate?: string; endDate?: string; @@ -22,6 +23,7 @@ interface ResultTabsProps { const ResultTabsComponent: React.FC = ({ actionId, agentIds, + expirationDate, endDate, isLive, startDate, @@ -34,7 +36,12 @@ const ResultTabsComponent: React.FC = ({ content: ( <> - + ), }, @@ -55,7 +62,7 @@ const ResultTabsComponent: React.FC = ({ ), }, ], - [actionId, agentIds, endDate, isLive, startDate] + [actionId, agentIds, endDate, isLive, startDate, expirationDate] ); return ( diff --git a/x-pack/plugins/osquery/public/results/use_all_results.ts b/x-pack/plugins/osquery/public/results/use_all_results.ts index d5e2bbc886940..1121898410278 100644 --- a/x-pack/plugins/osquery/public/results/use_all_results.ts +++ b/x-pack/plugins/osquery/public/results/use_all_results.ts @@ -21,6 +21,7 @@ import { import { ESTermQuery } from '../../common/typed_json'; import { generateTablePaginationOptions, getInspectResponse, InspectResponse } from './helpers'; +import { useErrorToast } from '../common/hooks/use_error_toast'; export interface ResultsArgs { results: ResultEdges; @@ -50,10 +51,8 @@ export const useAllResults = ({ skip = false, isLive = false, }: UseAllResults) => { - const { - data, - notifications: { toasts }, - } = useKibana().services; + const { data } = useKibana().services; + const setErrorToast = useErrorToast(); return useQuery( ['allActionResults', { actionId, activePage, limit, sort }], @@ -81,8 +80,9 @@ export const useAllResults = ({ { refetchInterval: isLive ? 1000 : false, enabled: !skip, + onSuccess: () => setErrorToast(), onError: (error: Error) => - toasts.addError(error, { + setErrorToast(error, { title: i18n.translate('xpack.osquery.results.fetchError', { defaultMessage: 'Error while fetching results', }), diff --git a/x-pack/plugins/osquery/public/routes/live_queries/details/index.tsx b/x-pack/plugins/osquery/public/routes/live_queries/details/index.tsx index 5a80e12d0fef3..64a1fb0791e83 100644 --- a/x-pack/plugins/osquery/public/routes/live_queries/details/index.tsx +++ b/x-pack/plugins/osquery/public/routes/live_queries/details/index.tsx @@ -43,6 +43,10 @@ const LiveQueryDetailsPageComponent = () => { const liveQueryListProps = useRouterNavigate('live_queries'); const { data } = useActionDetails({ actionId }); + const expirationDate = useMemo(() => new Date(data?.actionDetails._source.expiration), [ + data?.actionDetails, + ]); + const expired = useMemo(() => expirationDate < new Date(), [expirationDate]); const { data: actionResultsData } = useActionResults({ actionId, activePage: 0, @@ -78,6 +82,18 @@ const LiveQueryDetailsPageComponent = () => { [liveQueryListProps] ); + const failed = useMemo(() => { + let result = actionResultsData?.aggregations.failed; + if (expired) { + result = '-'; + if (data?.actionDetails?.fields?.agents && actionResultsData?.aggregations) { + result = + data.actionDetails.fields.agents.length - actionResultsData.aggregations.successful; + } + } + return result; + }, [expired, actionResultsData?.aggregations, data?.actionDetails?.fields?.agents]); + const RightColumn = useMemo( () => ( @@ -114,15 +130,13 @@ const LiveQueryDetailsPageComponent = () => { /> - - {actionResultsData?.aggregations.failed} - + {failed} ), - [actionResultsData?.aggregations.failed, data?.actionDetails?.fields?.agents?.length] + [data?.actionDetails?.fields?.agents?.length, failed] ); return ( @@ -133,6 +147,7 @@ const LiveQueryDetailsPageComponent = () => { theme.eui.paddingSizes.s}; @@ -36,6 +37,7 @@ const ActiveStateSwitchComponent: React.FC = ({ item }) http, notifications: { toasts }, } = useKibana().services; + const setErrorToast = useErrorToast(); const [confirmationModal, setConfirmationModal] = useState(false); const hideConfirmationModal = useCallback(() => setConfirmationModal(false), []); @@ -51,6 +53,7 @@ const ActiveStateSwitchComponent: React.FC = ({ item }) { onSuccess: (response) => { queryClient.invalidateQueries('scheduledQueries'); + setErrorToast(); toasts.addSuccess( response.item.enabled ? i18n.translate( @@ -75,7 +78,7 @@ const ActiveStateSwitchComponent: React.FC = ({ item }) }, onError: (error) => { // @ts-expect-error update types - toasts.addError(error, { title: error.body.error, toastMessage: error.body.message }); + setErrorToast(error, { title: error.body.error, toastMessage: error.body.message }); }, } ); diff --git a/x-pack/plugins/osquery/public/scheduled_query_groups/form/index.tsx b/x-pack/plugins/osquery/public/scheduled_query_groups/form/index.tsx index 64efdf61fc735..c940b1f8527b5 100644 --- a/x-pack/plugins/osquery/public/scheduled_query_groups/form/index.tsx +++ b/x-pack/plugins/osquery/public/scheduled_query_groups/form/index.tsx @@ -45,6 +45,7 @@ import { PolicyIdComboBoxField } from './policy_id_combobox_field'; import { QueriesField } from './queries_field'; import { ConfirmDeployAgentPolicyModal } from './confirmation_modal'; import { useAgentPolicies } from '../../agent_policies'; +import { useErrorToast } from '../../common/hooks/use_error_toast'; const GhostFormField = () => <>; @@ -68,6 +69,7 @@ const ScheduledQueryGroupFormComponent: React.FC = http, notifications: { toasts }, } = useKibana().services; + const setErrorToast = useErrorToast(); const [showConfirmationModal, setShowConfirmationModal] = useState(false); const handleHideConfirmationModal = useCallback(() => setShowConfirmationModal(false), []); @@ -110,6 +112,7 @@ const ScheduledQueryGroupFormComponent: React.FC = return; } + setErrorToast(); navigateToApp(PLUGIN_ID, { path: `scheduled_query_groups/${data.item.id}` }); toasts.addSuccess( i18n.translate('xpack.osquery.scheduledQueryGroup.form.updateSuccessToastMessageText', { @@ -122,7 +125,7 @@ const ScheduledQueryGroupFormComponent: React.FC = }, onError: (error) => { // @ts-expect-error update types - toasts.addError(error, { title: error.body.error, toastMessage: error.body.message }); + setErrorToast(error, { title: error.body.error, toastMessage: error.body.message }); }, } ); diff --git a/x-pack/plugins/osquery/server/lib/parse_agent_groups.ts b/x-pack/plugins/osquery/server/lib/parse_agent_groups.ts index a120d7deddf50..8fe60f59f01d7 100644 --- a/x-pack/plugins/osquery/server/lib/parse_agent_groups.ts +++ b/x-pack/plugins/osquery/server/lib/parse_agent_groups.ts @@ -63,7 +63,7 @@ export const parseAgentSelection = async ( perPage, page, kuery, - showInactive: true, + showInactive: false, }); return { results: res.agents.map((agent) => agent.id), total: res.total }; }); @@ -84,7 +84,7 @@ export const parseAgentSelection = async ( perPage, page, kuery, - showInactive: true, + showInactive: false, }); return { results: res.agents.map((agent) => agent.id), total: res.total }; }); From 119845483f695431a153c9ce92a98b5803e7241b Mon Sep 17 00:00:00 2001 From: Pete Harverson Date: Thu, 24 Jun 2021 17:44:13 +0100 Subject: [PATCH 04/25] [ML] Fixes data frame analytics models list pipelines tab (#103235) --- .../components/models_management/expanded_row.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/expanded_row.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/expanded_row.tsx index 93be45bbdaf97..87a3f10992c06 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/expanded_row.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/expanded_row.tsx @@ -430,7 +430,7 @@ export const ExpandedRow: FC = ({ item }) => { Date: Thu, 24 Jun 2021 17:49:56 +0100 Subject: [PATCH 05/25] [ML] Add description and owner to kibana.json for ML owned plugins (#103254) --- x-pack/plugins/data_visualizer/kibana.json | 7 ++++++- x-pack/plugins/file_upload/kibana.json | 7 ++++++- x-pack/plugins/ml/kibana.json | 7 ++++++- x-pack/plugins/transform/kibana.json | 7 ++++++- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/data_visualizer/kibana.json b/x-pack/plugins/data_visualizer/kibana.json index 00eb3d7bf142c..01aca7c2bbaee 100644 --- a/x-pack/plugins/data_visualizer/kibana.json +++ b/x-pack/plugins/data_visualizer/kibana.json @@ -27,5 +27,10 @@ ], "extraPublicDirs": [ "common" - ] + ], + "owner": { + "name": "Machine Learning UI", + "githubTeam": "ml-ui" + }, + "description": "The Data Visualizer tools help you understand your data, by analyzing the metrics and fields in a log file or an existing Elasticsearch index." } diff --git a/x-pack/plugins/file_upload/kibana.json b/x-pack/plugins/file_upload/kibana.json index 6f93874cdbcaa..e69c5e34bc09b 100644 --- a/x-pack/plugins/file_upload/kibana.json +++ b/x-pack/plugins/file_upload/kibana.json @@ -16,5 +16,10 @@ ], "extraPublicDirs": [ "common" - ] + ], + "owner": { + "name": "Machine Learning UI", + "githubTeam": "ml-ui" + }, + "description": "The file upload plugin contains components and services for uploading a file, analyzing its data, and then importing the data into an Elasticsearch index. Supported file types include CSV, TSV, newline-delimited JSON and GeoJSON." } diff --git a/x-pack/plugins/ml/kibana.json b/x-pack/plugins/ml/kibana.json index 7b3f457106033..7f3ad80968b7a 100644 --- a/x-pack/plugins/ml/kibana.json +++ b/x-pack/plugins/ml/kibana.json @@ -43,5 +43,10 @@ ], "extraPublicDirs": [ "common" - ] + ], + "owner": { + "name": "Machine Learning UI", + "githubTeam": "ml-ui" + }, + "description": "This plugin provides access to the machine learning features provided by Elastic." } diff --git a/x-pack/plugins/transform/kibana.json b/x-pack/plugins/transform/kibana.json index 4216ac9761e86..c9f6beeee5aff 100644 --- a/x-pack/plugins/transform/kibana.json +++ b/x-pack/plugins/transform/kibana.json @@ -23,5 +23,10 @@ "kibanaUtils", "kibanaReact", "ml" - ] + ], + "owner": { + "name": "Machine Learning UI", + "githubTeam": "ml-ui" + }, + "description": "This plugin provides access to the transforms features provided by Elastic. Transforms enable you to convert existing Elasticsearch indices into summarized indices, which provide opportunities for new insights and analytics." } From bfb98053d6b361a18acd58e7f0ab34eb8a43a0ac Mon Sep 17 00:00:00 2001 From: Janeen Mikell-Straughn <57149392+jmikell821@users.noreply.github.com> Date: Thu, 24 Jun 2021 12:53:56 -0400 Subject: [PATCH 06/25] [DOCS] Security Overview (#103151) * updating overview topic for Kibana * formatting fixes * small formatting tweaks * small formatting tweaks * Update index.asciidoc Updating index file; removing siem-UI and machine learning topics from the TOC. * [DOCS] Change part to chapter * Update index.asciidoc * Adding attribute Co-authored-by: lcawl --- docs/siem/index.asciidoc | 198 +++++++++++++++++++++++++++++---------- 1 file changed, 151 insertions(+), 47 deletions(-) diff --git a/docs/siem/index.asciidoc b/docs/siem/index.asciidoc index 18895f0533fd7..05b1ec0b5b797 100644 --- a/docs/siem/index.asciidoc +++ b/docs/siem/index.asciidoc @@ -1,60 +1,164 @@ +[chapter] [role="xpack"] [[xpack-siem]] -= Elastic Security += Elastic Security overview +++++ +Security +++++ -[partintro] --- +https://www.elastic.co/security[Elastic Security] combines SIEM threat detection features with endpoint +prevention and response capabilities in one solution. These analytical and +protection capabilities, leveraged by the speed and extensibility of +Elasticsearch, enable analysts to defend their organization from threats before +damage and loss occur. -Elastic Security combines SIEM threat detection features with endpoint -prevention and response capabilities in one solution, including: +Elastic Security provides the following security benefits and capabilities: -* A detection engine to identify attacks and system misconfiguration +* A detection engine to identify attacks and system misconfigurations * A workspace for event triage and investigations * Interactive visualizations to investigate process relationships -* Embedded case management and automated actions -* Detection of signatureless attacks with prebuilt {ml} anomaly jobs and -detection rules +* Inbuilt case management with automated actions +* Detection of signatureless attacks with prebuilt machine learning anomaly jobs +and detection rules -[role="screenshot"] -image::siem/images/overview-ui.png[Elastic Security in Kibana] - -[float] -== Add data - -Kibana provides step-by-step instructions to help you add data. The -{security-guide}[Security Guide] is a good source for more -detailed information and instructions. - -[float] -=== {Beats} - -https://www.elastic.co/products/beats/auditbeat[{auditbeat}], -https://www.elastic.co/products/beats/filebeat[{filebeat}], -https://www.elastic.co/products/beats/winlogbeat[{winlogbeat}], and -https://www.elastic.co/products/beats/packetbeat[{packetbeat}] -send security events and other data to Elasticsearch. +[discrete] +== Elastic Security components and workflow -The default index patterns for Elastic Security events are `auditbeat-*`, `winlogbeat-*`, -`filebeat-*`, `packetbeat-*`, `endgame-*`, `logs-*`, and `apm-*-transaction*`. To change the default pattern patterns, go to *Stack Management > Advanced Settings > securitySolution:defaultIndex*. +The following diagram provides a comprehensive illustration of the Elastic Security workflow. -[float] -=== Elastic Security endpoint agent - -The agent detects and protects against malware, and ships host and network -events directly to Elastic Security. - -[float] -=== Elastic Common Schema (ECS) for normalizing data - -The {ecs-ref}[Elastic Common Schema (ECS)] defines a common set of fields to be -used for storing event data in Elasticsearch. ECS helps users normalize their -event data to better analyze, visualize, and correlate the data represented in -their events. - -Elastic Security can ingest and normalize events from ECS-compatible data sources. +[role="screenshot"] +image::../siem/images/workflow.png[] + +Here's an overview of the flow and its components: + +* Data is shipped from your hosts to {es} via beat modules and the Elastic https://www.elastic.co/endpoint-security/[Endpoint Security agent integration]. This integration provides capabilities such as collecting events, detecting and preventing {security-guide}/detection-engine-overview.html#malware-prevention[malicious activity], and artifact delivery. The {fleet-guide}/fleet-overview.html[{fleet}] app is used to +install and manage agents and integrations on your hosts. ++ +The Endpoint Security integration ships the following data sets: ++ +*** *Windows*: Process, network, file, DNS, registry, DLL and driver loads, +malware security detections +*** *Linux/macOS*: Process, network, file ++ +* https://www.elastic.co/integrations?solution=security[Beat modules]: {beats} +are lightweight data shippers. Beat modules provide a way of collecting and +parsing specific data sets from common sources, such as cloud and OS events, +logs, and metrics. Common security-related modules are listed {security-guide}/ingest-data.html#enable-beat-modules[here]. +* The {security-app} in {kib} is used to manage the *Detection engine*, +*Cases*, and *Timeline*, as well as administer hosts running Endpoint Security: +** Detection engine: Automatically searches for suspicious host and network +activity via the following: +*** {security-guide}/detection-engine-overview.html#detection-engine-overview[Detection rules]: Periodically search the data +({es} indices) sent from your hosts for suspicious events. When a suspicious +event is discovered, a detection alert is generated. External systems, such as +Slack and email, can be used to send notifications when alerts are generated. +You can create your own rules and make use of our {security-guide}/prebuilt-rules.html[prebuilt ones]. +*** {security-guide}/detections-ui-exceptions.html[Exceptions]: Reduce noise and the number of +false positives. Exceptions are associated with rules and prevent alerts when +an exception's conditions are met. *Value lists* contain source event +values that can be used as part of an exception's conditions. When +Elastic {endpoint-sec} is installed on your hosts, you can add malware exceptions +directly to the endpoint from the Security app. +*** {security-guide}/machine-learning.html#included-jobs[{ml-cap} jobs]: Automatic anomaly detection of host and +network events. Anomaly scores are provided per host and can be used with +detection rules. +** {security-guide}/timelines-ui.html[Timeline]: Workspace for investigating alerts and events. +Timelines use queries and filters to drill down into events related to +a specific incident. Timeline templates are attached to rules and use predefined +queries when alerts are investigated. Timelines can be saved and shared with +others, as well as attached to Cases. +** {security-guide}/cases-overview.html[Cases]: An internal system for opening, tracking, and sharing +security issues directly in the Security app. Cases can be integrated with +external ticketing systems. +** {security-guide}/admin-page-ov.html[Administration]: View and manage hosts running {endpoint-sec}. + +{security-guide}/ingest-data.html[Ingest data to Elastic Security] and {security-guide}/install-endpoint.html[Configure and install the Elastic Endpoint integration] describe how to ship security-related +data to {es}. + + +For more background information, see: + +* https://www.elastic.co/products/elasticsearch[{es}]: A real-time, +distributed storage, search, and analytics engine. {es} excels at indexing +streams of semi-structured data, such as logs or metrics. +* https://www.elastic.co/products/kibana[{kib}]: An open-source analytics and +visualization platform designed to work with {es}. You use {kib} to search, +view, and interact with data stored in {es} indices. You can easily compile +advanced data analysis and visualize your data in a variety of charts, tables, +and maps. + +[discrete] +=== Compatibility with cold tier nodes + +Cold tier is a {ref}/data-tiers.html[data tier] that holds time-series data that is accessed only occasionally. In {stack} version >=7.11.0, {elastic-sec} supports cold tier data for the following {es} indices: + +* Index patterns specified in `securitySolution:defaultIndex` +* Index patterns specified in the definitions of detection rules, except for indicator match rules +* Index patterns specified in the data sources selector on various {security-app} pages + +{elastic-sec} does NOT support cold tier data for the following {es} indices: + +* Index patterns controlled by {elastic-sec}, including signals and list indices +* Index patterns specified in indicator match rules + +Using cold tier data for unsupported indices may result in detection rule timeouts and overall performance degradation. + +[discrete] +[[self-protection]] +==== Elastic Endpoint self-protection + +Self-protection means that {elastic-endpoint} has guards against users and attackers that may try to interfere with its functionality. This protection feature is consistently enhanced to prevent attackers who may attempt to use newer, more sophisticated tactics to interfere with the {elastic-endpoint}. Self-protection is enabled by default when {elastic-endpoint} installs on supported platforms, listed below. + +Self-protection is enabled on the following 64-bit Windows versions: + +* Windows 8.1 +* Windows 10 +* Windows Server 2012 R2 +* Windows Server 2016 +* Windows Server 2019 + +And on the following macOS versions: + +* macOS 10.15 (Catalina) +* macOS 11 (Big Sur) + +NOTE: Other Windows and macOS variants (and all Linux distributions) do not have self-protection. + +For {stack} version >= 7.11.0, self-protection defines the following permissions: + +* Users -- even Administrator/root -- *cannot* delete {elastic-endpoint} files (located at `c:\Program Files\Elastic\Endpoint` on Windows, and `/Library/Elastic/Endpoint` on macOS). +* Users *cannot* terminate the {elastic-endpoint} program or service. +* Administrator/root users *can* read the endpoint's files. On Windows, the easiest way to read Endpoint files is to start an Administrator `cmd.exe` prompt. On macOS, an Administrator can use the `sudo` command. +* Administrator/root users *can* stop the {elastic-agent}'s service. On Windows, run the `sc stop "Elastic Agent"` command. On macOS, run the `sudo launchctl stop elastic-agent` command. + + +[discrete] +[[siem-integration]] +=== Integration with other Elastic products + +You can use {elastic-sec} with other Elastic products and features to help you +identify and investigate suspicious activity: + +* https://www.elastic.co/products/stack/machine-learning[{ml-cap}] +* https://www.elastic.co/products/stack/alerting[Alerting] +* https://www.elastic.co/products/stack/canvas[Canvas] + +[discrete] +[[data-sources]] +=== APM transaction data sources + +By default, {elastic-sec} monitors {apm-app-ref}/apm-getting-started.html[APM] +`apm-*-transaction*` indices. To add additional APM indices, update the +index patterns in the `securitySolution:defaultIndex` setting ({kib} -> Stack Management -> Advanced Settings -> `securitySolution:defaultIndex`). --- +[discrete] +[[ecs-compliant-reqs]] +=== ECS compliance data requirements +The {ecs-ref}[Elastic Common Schema (ECS)] defines a common set of fields used for +storing event data in Elasticsearch. ECS helps users normalize their event data +to better analyze, visualize, and correlate the data represented in their +events. {elastic-sec} supports events and indicator index data from any ECS-compliant data source. -include::siem-ui.asciidoc[] -include::machine-learning.asciidoc[] +IMPORTANT: {elastic-sec} requires {ecs-ref}[ECS-compliant data]. If you use third-party data collectors to ship data to {es}, the data must be mapped to ECS. +{security-guide}/siem-field-reference.html[Elastic Security ECS field reference] lists ECS fields used in {elastic-sec}. From eb8e9d7cc9a36b2a6cf1da3561aed572da6710eb Mon Sep 17 00:00:00 2001 From: John Schulz Date: Thu, 24 Jun 2021 12:56:48 -0400 Subject: [PATCH 07/25] [Fleet] Remove duplication between two files #103282 ## Summary `public/applications/integrations/constants.tsx` and `public/applications/integrations/sections/epm/constants.tsx` are identical except for this line in `public/applications/integrations/constants.tsx` ```ts export * from '../../constants'; ``` This PR removes all the duplication from the "upper" file (`public/applications/integrations/constants.tsx`) and leaves the other code "down" in `/sections/epm/` closer to where it's used. Initially, I deleted `public/applications/integrations/constants.tsx` entirely but several files do `import` the constants it exports, so I left it. --- .../applications/integrations/constants.tsx | 53 ------------------- .../detail/assets/assets_accordion.tsx | 2 +- 2 files changed, 1 insertion(+), 54 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/integrations/constants.tsx b/x-pack/plugins/fleet/public/applications/integrations/constants.tsx index 08197e18fec02..f2cb57301f49c 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/constants.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/constants.tsx @@ -5,57 +5,4 @@ * 2.0. */ -import type { IconType } from '@elastic/eui'; - -import type { ServiceName } from '../../types'; -import { ElasticsearchAssetType, KibanaAssetType } from '../../types'; - export * from '../../constants'; - -// only allow Kibana assets for the kibana key, ES asssets for elasticsearch, etc -type ServiceNameToAssetTypes = Record, KibanaAssetType[]> & - Record, ElasticsearchAssetType[]>; - -export const DisplayedAssets: ServiceNameToAssetTypes = { - kibana: Object.values(KibanaAssetType), - elasticsearch: Object.values(ElasticsearchAssetType), -}; -export type DisplayedAssetType = KibanaAssetType | ElasticsearchAssetType; - -export const AssetTitleMap: Record = { - dashboard: 'Dashboard', - ilm_policy: 'ILM Policy', - ingest_pipeline: 'Ingest Pipeline', - transform: 'Transform', - index_pattern: 'Index Pattern', - index_template: 'Index Template', - component_template: 'Component Template', - search: 'Saved Search', - visualization: 'Visualization', - map: 'Map', - data_stream_ilm_policy: 'Data Stream ILM Policy', - lens: 'Lens', - security_rule: 'Security Rule', - ml_module: 'ML Module', -}; - -export const ServiceTitleMap: Record = { - kibana: 'Kibana', - elasticsearch: 'Elasticsearch', -}; - -export const AssetIcons: Record = { - dashboard: 'dashboardApp', - index_pattern: 'indexPatternApp', - search: 'searchProfilerApp', - visualization: 'visualizeApp', - map: 'emsApp', - lens: 'lensApp', - security_rule: 'securityApp', - ml_module: 'mlApp', -}; - -export const ServiceIcons: Record = { - elasticsearch: 'logoElasticsearch', - kibana: 'logoKibana', -}; diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx index abfdd88d27162..12d4a0014b976 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/assets/assets_accordion.tsx @@ -20,7 +20,7 @@ import { EuiNotificationBadge, } from '@elastic/eui'; -import { AssetTitleMap } from '../../../../../constants'; +import { AssetTitleMap } from '../../../constants'; import { getHrefToObjectInKibanaApp, useStartServices } from '../../../../../hooks'; From 5af69edfbaf58d3874b043c1fc3674080a1b2430 Mon Sep 17 00:00:00 2001 From: Dmitry Shevchenko Date: Thu, 24 Jun 2021 19:17:09 +0200 Subject: [PATCH 08/25] Fix "Deleted rule" badge is not displayed if 'Rule Name' contains more than 55 words (#103164) --- .../__snapshots__/index.test.tsx.snap | 4 ++-- .../__snapshots__/title.test.tsx.snap | 16 +++++++------ .../common/components/header_page/index.tsx | 12 ++++++++-- .../common/components/header_page/title.tsx | 23 +++++++++++++++---- .../common/components/header_page/types.ts | 2 ++ .../detection_engine/rules/details/index.tsx | 22 +++++++++++------- .../network/pages/details/index.test.tsx | 2 +- 7 files changed, 57 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/header_page/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/header_page/__snapshots__/index.test.tsx.snap index 9cb9f28612b15..d00bd7040c164 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_page/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/common/components/header_page/__snapshots__/index.test.tsx.snap @@ -6,7 +6,7 @@ exports[`HeaderPage it renders 1`] = ` alignItems="center" bottomBorder={true} > - + - + diff --git a/x-pack/plugins/security_solution/public/common/components/header_page/__snapshots__/title.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/header_page/__snapshots__/title.test.tsx.snap index ca02d0ac5cb2d..176902ae38d20 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_page/__snapshots__/title.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/common/components/header_page/__snapshots__/title.test.tsx.snap @@ -4,20 +4,22 @@ exports[`Title it renders 1`] = ` -

- - Test title - + + + Test title + + -

+
`; diff --git a/x-pack/plugins/security_solution/public/common/components/header_page/index.tsx b/x-pack/plugins/security_solution/public/common/components/header_page/index.tsx index 1c87d70c0c7cb..75453f2d759fb 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_page/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/header_page/index.tsx @@ -55,6 +55,14 @@ const Badge = (styled(EuiBadge)` ` as unknown) as typeof EuiBadge; Badge.displayName = 'Badge'; +const HeaderSection = styled(EuiPageHeaderSection)` + // Without min-width: 0, as a flex child, it wouldn't shrink properly + // and could overflow its parent. + min-width: 0; + max-width: 100%; +`; +HeaderSection.displayName = 'HeaderSection'; + interface BackOptions { href: LinkIconProps['href']; text: LinkIconProps['children']; @@ -105,7 +113,7 @@ const HeaderPageComponent: React.FC = ({ return ( <> - + {backOptions && ( = ({ {subtitle && } {subtitle2 && } {border && isLoading && } - + {children && ( diff --git a/x-pack/plugins/security_solution/public/common/components/header_page/title.tsx b/x-pack/plugins/security_solution/public/common/components/header_page/title.tsx index 471d539ea03f4..a99132d5c7f62 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_page/title.tsx +++ b/x-pack/plugins/security_solution/public/common/components/header_page/title.tsx @@ -24,6 +24,19 @@ const Badge = (styled(EuiBadge)` ` as unknown) as typeof EuiBadge; Badge.displayName = 'Badge'; +const Header = styled.h1` + display: flex; + align-items: center; +`; +Header.displayName = 'Header'; + +const TitleWrapper = styled.span` + // Without min-width: 0, as a flex child, it wouldn't shrink properly + // and could overflow its parent. + min-width: 0; +`; +TitleWrapper.displayName = 'TitleWrapper'; + interface Props { badgeOptions?: BadgeOptions; title: TitleProp; @@ -32,9 +45,11 @@ interface Props { const TitleComponent: React.FC = ({ draggableArguments, title, badgeOptions }) => ( -

+
{!draggableArguments ? ( - {title} + + {title} + ) : ( = ({ draggableArguments, title, badgeOptio tooltipPosition="bottom" /> ) : ( - + {badgeOptions.text} )} )} -

+
); diff --git a/x-pack/plugins/security_solution/public/common/components/header_page/types.ts b/x-pack/plugins/security_solution/public/common/components/header_page/types.ts index e95d0c8e1e69c..f099144eeb4be 100644 --- a/x-pack/plugins/security_solution/public/common/components/header_page/types.ts +++ b/x-pack/plugins/security_solution/public/common/components/header_page/types.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { EuiBadgeProps } from '@elastic/eui'; import type React from 'react'; export type TitleProp = string | React.ReactNode; @@ -17,4 +18,5 @@ export interface BadgeOptions { beta?: boolean; text: string; tooltip?: string; + color?: EuiBadgeProps['color']; } diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx index b4f1af41a0606..92679cb2662d7 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx @@ -18,7 +18,6 @@ import { EuiTabs, EuiToolTip, EuiWindowEvent, - EuiBadge, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { noop } from 'lodash/fp'; @@ -115,6 +114,7 @@ import { NeedAdminForUpdateRulesCallOut } from '../../../../components/callouts/ import { getRuleStatusText } from '../../../../../../common/detection_engine/utils'; import { MissingPrivilegesCallOut } from '../../../../components/callouts/missing_privileges_callout'; import { useRuleWithFallback } from '../../../../containers/detection_engine/rules/use_rule_with_fallback'; +import { BadgeOptions } from '../../../../../common/components/header_page/types'; /** * Need a 100% height here to account for the graph/analyze tool, which sets no explicit height parameters, but fills the available space. @@ -253,15 +253,20 @@ const RuleDetailsPageComponent = () => { const title = useMemo( () => ( <> - {rule?.name}{' '} - {ruleLoading ? ( - - ) : ( - !isExistingRule && {i18n.DELETED_RULE} - )} + {rule?.name} {ruleLoading && } ), - [rule, ruleLoading, isExistingRule] + [rule, ruleLoading] + ); + const badgeOptions = useMemo( + () => + !ruleLoading && !isExistingRule + ? { + text: i18n.DELETED_RULE, + color: 'default', + } + : undefined, + [isExistingRule, ruleLoading] ); const subTitle = useMemo( () => @@ -595,6 +600,7 @@ const RuleDetailsPageComponent = () => { , ]} title={title} + badgeOptions={badgeOptions} > diff --git a/x-pack/plugins/security_solution/public/network/pages/details/index.test.tsx b/x-pack/plugins/security_solution/public/network/pages/details/index.test.tsx index a9a97f6bac652..d9d5ac9241f19 100644 --- a/x-pack/plugins/security_solution/public/network/pages/details/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/pages/details/index.test.tsx @@ -149,7 +149,7 @@ describe('Network Details', () => { ); expect( wrapper - .find('[data-test-subj="network-details-headline"] [data-test-subj="header-page-title"]') + .find('[data-test-subj="network-details-headline"] h1[data-test-subj="header-page-title"]') .text() ).toEqual('fe80::24ce:f7ff:fede:a571'); }); From 5abac25ba3ca4fb20dbba49e354da7f1a6285a46 Mon Sep 17 00:00:00 2001 From: Marco Liberati Date: Thu, 24 Jun 2021 19:19:20 +0200 Subject: [PATCH 09/25] [Lens] Update formula icons (#103287) * :lipstick: Updated formula reference icon * :lipstick: Replace wordwrap icons --- .../definitions/formula/editor/formula_editor.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_editor.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_editor.tsx index d1b0ec8876feb..83a782b519248 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_editor.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/editor/formula_editor.tsx @@ -585,7 +585,6 @@ export function FormulaEditor({
- {/* TODO: Replace `bolt` with `wordWrap` icon (after latest EUI is deployed) and hook up button to enable/disable word wrapping. */} setIsHelpOpen(!isHelpOpen)} > - + @@ -747,7 +746,7 @@ export function FormulaEditor({ setIsHelpOpen(!isHelpOpen)} - iconType="help" + iconType="documentation" color="text" size="s" aria-label={i18n.translate( From bf6c53bb45a3488000c836a8cba1432f1f2dc2eb Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Thu, 24 Jun 2021 19:31:24 +0200 Subject: [PATCH 10/25] Improved Visualize button in field popover (#103099) * Improve field popover * Slightly improve type safteyness * Add unit tests for visualize trigger utils * Remove unused div Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- ...iscover_field_details_footer.test.tsx.snap | 705 ------------------ .../components/sidebar/discover_field.tsx | 37 +- .../sidebar/discover_field_details.scss | 10 - .../sidebar/discover_field_details.test.tsx | 41 +- .../sidebar/discover_field_details.tsx | 100 +-- .../discover_field_details_footer.test.tsx | 71 -- .../sidebar/discover_field_details_footer.tsx | 59 -- .../sidebar/discover_field_visualize.tsx | 66 ++ .../components/sidebar/lib/get_warnings.ts | 33 - .../lib/visualize_trigger_utils.test.ts | 116 +++ .../sidebar/lib/visualize_trigger_utils.ts | 84 ++- .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 13 files changed, 288 insertions(+), 1038 deletions(-) delete mode 100644 src/plugins/discover/public/application/apps/main/components/sidebar/__snapshots__/discover_field_details_footer.test.tsx.snap delete mode 100644 src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details.scss delete mode 100644 src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details_footer.test.tsx delete mode 100644 src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details_footer.tsx create mode 100644 src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_visualize.tsx delete mode 100644 src/plugins/discover/public/application/apps/main/components/sidebar/lib/get_warnings.ts create mode 100644 src/plugins/discover/public/application/apps/main/components/sidebar/lib/visualize_trigger_utils.test.ts diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/__snapshots__/discover_field_details_footer.test.tsx.snap b/src/plugins/discover/public/application/apps/main/components/sidebar/__snapshots__/discover_field_details_footer.test.tsx.snap deleted file mode 100644 index f976b961d8520..0000000000000 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/__snapshots__/discover_field_details_footer.test.tsx.snap +++ /dev/null @@ -1,705 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`discover sidebar field details footer renders properly 1`] = ` - - -
- -
- -
- - - -
-
-
-
-
-
-
-`; diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field.tsx b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field.tsx index 26a3c482e9d3c..301866c762fbd 100644 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field.tsx +++ b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field.tsx @@ -8,7 +8,7 @@ import './discover_field.scss'; -import React, { useState, useCallback, memo } from 'react'; +import React, { useState, useCallback, memo, useMemo } from 'react'; import { EuiPopover, EuiPopoverTitle, @@ -18,6 +18,7 @@ import { EuiIcon, EuiFlexGroup, EuiFlexItem, + EuiSpacer, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { UiCounterMetricType } from '@kbn/analytics'; @@ -27,7 +28,7 @@ import { FieldIcon, FieldButton } from '../../../../../../../kibana_react/public import { FieldDetails } from './types'; import { IndexPatternField, IndexPattern } from '../../../../../../../data/public'; import { getFieldTypeName } from './lib/get_field_type_name'; -import { DiscoverFieldDetailsFooter } from './discover_field_details_footer'; +import { DiscoverFieldVisualize } from './discover_field_visualize'; function wrapOnDot(str?: string) { // u200B is a non-width white-space character, which allows @@ -172,6 +173,7 @@ const MultiFields: React.FC = memo( })} + {multiFields.map((entry) => ( multiFields?.map((f) => f.field), [multiFields]); + if (field.type === '_source') { return ( {multiFields && ( - - )} - {!details.error && ( - + <> + + + )} + )} diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details.scss b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details.scss deleted file mode 100644 index ca48d67f75dec..0000000000000 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details.scss +++ /dev/null @@ -1,10 +0,0 @@ -.dscFieldDetails { - color: $euiTextColor; - margin-bottom: $euiSizeS; -} - -.dscFieldDetails__visualizeBtn { - @include euiFontSizeXS; - height: $euiSizeL !important; - min-width: $euiSize * 4; -} diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details.test.tsx b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details.test.tsx index a798abb60b833..8c9ad5bc9708a 100644 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details.test.tsx +++ b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details.test.tsx @@ -25,10 +25,11 @@ const indexPattern = getStubIndexPattern( ); describe('discover sidebar field details', function () { + const onAddFilter = jest.fn(); const defaultProps = { indexPattern, details: { buckets: [], error: '', exists: 1, total: 2, columns: [] }, - onAddFilter: jest.fn(), + onAddFilter, }; function mountComponent(field: IndexPatternField) { @@ -36,7 +37,7 @@ describe('discover sidebar field details', function () { return mountWithIntl(); } - it('should enable the visualize link for a number field', function () { + it('click on addFilter calls the function', function () { const visualizableField = new IndexPatternField({ name: 'bytes', type: 'number', @@ -47,37 +48,9 @@ describe('discover sidebar field details', function () { aggregatable: true, readFromDocValues: true, }); - const comp = mountComponent(visualizableField); - expect(findTestSubject(comp, 'fieldVisualize-bytes')).toBeTruthy(); - }); - - it('should disable the visualize link for an _id field', function () { - const conflictField = new IndexPatternField({ - name: '_id', - type: 'string', - esTypes: ['_id'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }); - const comp = mountComponent(conflictField); - expect(findTestSubject(comp, 'fieldVisualize-_id')).toEqual({}); - }); - - it('should disable the visualize link for an unknown field', function () { - const unknownField = new IndexPatternField({ - name: 'test', - type: 'unknown', - esTypes: ['double'], - count: 0, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }); - const comp = mountComponent(unknownField); - expect(findTestSubject(comp, 'fieldVisualize-test')).toEqual({}); + const component = mountComponent(visualizableField); + const onAddButton = findTestSubject(component, 'onAddFilterButton'); + onAddButton.simulate('click'); + expect(onAddFilter).toHaveBeenCalledWith('_exists_', visualizableField.name, '+'); }); }); diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details.tsx b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details.tsx index ffa7b30de5280..e29799b720e21 100644 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details.tsx +++ b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details.tsx @@ -6,27 +6,18 @@ * Side Public License, v 1. */ -import React, { useState, useEffect } from 'react'; -import { EuiIconTip, EuiText, EuiButton, EuiSpacer } from '@elastic/eui'; +import React from 'react'; +import { EuiText, EuiSpacer, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; -import { METRIC_TYPE, UiCounterMetricType } from '@kbn/analytics'; import { DiscoverFieldBucket } from './discover_field_bucket'; -import { getWarnings } from './lib/get_warnings'; -import { - triggerVisualizeActions, - isFieldVisualizable, - getVisualizeHref, -} from './lib/visualize_trigger_utils'; import { Bucket, FieldDetails } from './types'; import { IndexPatternField, IndexPattern } from '../../../../../../../data/public'; -import './discover_field_details.scss'; interface DiscoverFieldDetailsProps { field: IndexPatternField; indexPattern: IndexPattern; details: FieldDetails; onAddFilter: (field: IndexPatternField | string, value: string, type: '+' | '-') => void; - trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void; } export function DiscoverFieldDetails({ @@ -34,46 +25,12 @@ export function DiscoverFieldDetails({ indexPattern, details, onAddFilter, - trackUiMetric, }: DiscoverFieldDetailsProps) { - const warnings = getWarnings(field); - const [showVisualizeLink, setShowVisualizeLink] = useState(false); - const [visualizeLink, setVisualizeLink] = useState(''); - - useEffect(() => { - isFieldVisualizable(field, indexPattern.id, details.columns).then( - (flag) => { - setShowVisualizeLink(flag); - // get href only if Visualize button is enabled - getVisualizeHref(field, indexPattern.id, details.columns).then( - (uri) => { - if (uri) setVisualizeLink(uri); - }, - () => { - setVisualizeLink(''); - } - ); - }, - () => { - setShowVisualizeLink(false); - } - ); - }, [field, indexPattern.id, details.columns]); - - const handleVisualizeLinkClick = (event: React.MouseEvent) => { - // regular link click. let the uiActions code handle the navigation and show popup if needed - event.preventDefault(); - if (trackUiMetric) { - trackUiMetric(METRIC_TYPE.CLICK, 'visualize_link_click'); - } - triggerVisualizeActions(field, indexPattern.id, details.columns); - }; - return ( <> -
- {details.error && {details.error}} - {!details.error && ( + {details.error && {details.error}} + {!details.error && ( + <>
{details.buckets.map((bucket: Bucket, idx: number) => ( ))}
- )} - - {showVisualizeLink && ( - <> - - {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} - handleVisualizeLinkClick(e)} - href={visualizeLink} - size="s" - className="dscFieldDetails__visualizeBtn" - data-test-subj={`fieldVisualize-${field.name}`} - > + + + {!indexPattern.metaFields.includes(field.name) && !field.scripted ? ( + onAddFilter('_exists_', field.name, '+')} + data-test-subj="onAddFilterButton" + > + + + ) : ( - - {warnings.length > 0 && ( - )} - - )} -
+ + + )} ); } diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details_footer.test.tsx b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details_footer.test.tsx deleted file mode 100644 index aa93b2a663736..0000000000000 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details_footer.test.tsx +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { findTestSubject } from '@elastic/eui/lib/test'; -import { mountWithIntl } from '@kbn/test/jest'; -// @ts-expect-error -import stubbedLogstashFields from '../../../../../__fixtures__/logstash_fields'; -import { coreMock } from '../../../../../../../../core/public/mocks'; -import { IndexPatternField } from '../../../../../../../data/public'; -import { getStubIndexPattern } from '../../../../../../../data/public/test_utils'; -import { DiscoverFieldDetailsFooter } from './discover_field_details_footer'; - -const indexPattern = getStubIndexPattern( - 'logstash-*', - (cfg: unknown) => cfg, - 'time', - stubbedLogstashFields(), - coreMock.createSetup() -); - -describe('discover sidebar field details footer', function () { - const onAddFilter = jest.fn(); - const defaultProps = { - indexPattern, - details: { buckets: [], error: '', exists: 1, total: 2, columns: [] }, - onAddFilter, - }; - - function mountComponent(field: IndexPatternField) { - const compProps = { ...defaultProps, field }; - return mountWithIntl(); - } - - it('renders properly', function () { - const visualizableField = new IndexPatternField({ - name: 'bytes', - type: 'number', - esTypes: ['long'], - count: 10, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }); - const component = mountComponent(visualizableField); - expect(component).toMatchSnapshot(); - }); - - it('click on addFilter calls the function', function () { - const visualizableField = new IndexPatternField({ - name: 'bytes', - type: 'number', - esTypes: ['long'], - count: 10, - scripted: false, - searchable: true, - aggregatable: true, - readFromDocValues: true, - }); - const component = mountComponent(visualizableField); - const onAddButton = findTestSubject(component, 'onAddFilterButton'); - onAddButton.simulate('click'); - expect(onAddFilter).toHaveBeenCalledWith('_exists_', visualizableField.name, '+'); - }); -}); diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details_footer.tsx b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details_footer.tsx deleted file mode 100644 index 148dfc67c3e41..0000000000000 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_details_footer.tsx +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { EuiLink, EuiPopoverFooter, EuiText } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { IndexPatternField } from '../../../../../../../data/common/index_patterns/fields'; -import { IndexPattern } from '../../../../../../../data/common/index_patterns/index_patterns'; -import { FieldDetails } from './types'; - -interface DiscoverFieldDetailsFooterProps { - field: IndexPatternField; - indexPattern: IndexPattern; - details: FieldDetails; - onAddFilter: (field: IndexPatternField | string, value: string, type: '+' | '-') => void; -} - -export function DiscoverFieldDetailsFooter({ - field, - indexPattern, - details, - onAddFilter, -}: DiscoverFieldDetailsFooterProps) { - return ( - - - {!indexPattern.metaFields.includes(field.name) && !field.scripted ? ( - onAddFilter('_exists_', field.name, '+')} - data-test-subj="onAddFilterButton" - > - - - ) : ( - - )} - - - ); -} diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_visualize.tsx b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_visualize.tsx new file mode 100644 index 0000000000000..baf740531e6bf --- /dev/null +++ b/src/plugins/discover/public/application/apps/main/components/sidebar/discover_field_visualize.tsx @@ -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 + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import React, { useEffect, useState } from 'react'; +import { EuiButton, EuiPopoverFooter } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { METRIC_TYPE, UiCounterMetricType } from '@kbn/analytics'; +import type { IndexPattern, IndexPatternField } from 'src/plugins/data/common'; + +import { triggerVisualizeActions, VisualizeInformation } from './lib/visualize_trigger_utils'; +import type { FieldDetails } from './types'; +import { getVisualizeInformation } from './lib/visualize_trigger_utils'; + +interface Props { + field: IndexPatternField; + indexPattern: IndexPattern; + details: FieldDetails; + multiFields?: IndexPatternField[]; + trackUiMetric?: (metricType: UiCounterMetricType, eventName: string | string[]) => void; +} + +export const DiscoverFieldVisualize: React.FC = React.memo( + ({ field, indexPattern, details, trackUiMetric, multiFields }) => { + const [visualizeInfo, setVisualizeInfo] = useState(); + + useEffect(() => { + getVisualizeInformation(field, indexPattern.id, details.columns, multiFields).then( + setVisualizeInfo + ); + }, [details.columns, field, indexPattern, multiFields]); + + if (!visualizeInfo) { + return null; + } + + const handleVisualizeLinkClick = (event: React.MouseEvent) => { + // regular link click. let the uiActions code handle the navigation and show popup if needed + event.preventDefault(); + trackUiMetric?.(METRIC_TYPE.CLICK, 'visualize_link_click'); + triggerVisualizeActions(visualizeInfo.field, indexPattern.id, details.columns); + }; + + return ( + + {/* eslint-disable-next-line @elastic/eui/href-or-on-click */} + + + + + ); + } +); diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/lib/get_warnings.ts b/src/plugins/discover/public/application/apps/main/components/sidebar/lib/get_warnings.ts deleted file mode 100644 index 60ce5351e2cd3..0000000000000 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/lib/get_warnings.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { IndexPatternField } from '../../../../../../../../data/public'; - -export function getWarnings(field: IndexPatternField) { - let warnings = []; - - if (field.scripted) { - warnings.push( - i18n.translate( - 'discover.fieldChooser.discoverField.scriptedFieldsTakeLongExecuteDescription', - { - defaultMessage: 'Scripted fields can take a long time to execute.', - } - ) - ); - } - - if (warnings.length > 1) { - warnings = warnings.map(function (warning, i) { - return (i > 0 ? '\n' : '') + (i + 1) + ' - ' + warning; - }); - } - - return warnings; -} diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/lib/visualize_trigger_utils.test.ts b/src/plugins/discover/public/application/apps/main/components/sidebar/lib/visualize_trigger_utils.test.ts new file mode 100644 index 0000000000000..0a61bf1ea6029 --- /dev/null +++ b/src/plugins/discover/public/application/apps/main/components/sidebar/lib/visualize_trigger_utils.test.ts @@ -0,0 +1,116 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { IndexPatternField } from 'src/plugins/data/common'; +import type { Action } from 'src/plugins/ui_actions/public'; +import { getVisualizeInformation } from './visualize_trigger_utils'; + +const field = { + name: 'fieldName', + type: 'string', + esTypes: ['text'], + count: 1, + scripted: false, + searchable: true, + aggregatable: true, + readFromDocValues: true, + visualizable: true, +} as IndexPatternField; + +const mockGetActions = jest.fn>>, [string, { fieldName: string }]>( + () => Promise.resolve([]) +); + +jest.mock('../../../../../../kibana_services', () => ({ + getUiActions: () => ({ + getTriggerCompatibleActions: mockGetActions, + }), +})); + +const action: Action = { + id: 'action', + type: 'VISUALIZE_FIELD', + getIconType: () => undefined, + getDisplayName: () => 'Action', + isCompatible: () => Promise.resolve(true), + execute: () => Promise.resolve(), +}; + +describe('visualize_trigger_utils', () => { + afterEach(() => { + mockGetActions.mockReset(); + }); + + describe('getVisualizeInformation', () => { + it('should return for a visualizeable field with an action', async () => { + mockGetActions.mockResolvedValue([action]); + const information = await getVisualizeInformation(field, '1', [], undefined); + expect(information).not.toBeUndefined(); + expect(information?.field).toHaveProperty('name', 'fieldName'); + expect(information?.href).toBeUndefined(); + }); + + it('should return field and href from the action', async () => { + mockGetActions.mockResolvedValue([{ ...action, getHref: () => Promise.resolve('hreflink') }]); + const information = await getVisualizeInformation(field, '1', [], undefined); + expect(information).not.toBeUndefined(); + expect(information?.field).toHaveProperty('name', 'fieldName'); + expect(information).toHaveProperty('href', 'hreflink'); + }); + + it('should return undefined if no field has a compatible action', async () => { + mockGetActions.mockResolvedValue([]); + const information = await getVisualizeInformation( + { ...field, name: 'rootField' } as IndexPatternField, + '1', + [], + [ + { ...field, name: 'multi1' }, + { ...field, name: 'multi2' }, + ] as IndexPatternField[] + ); + expect(information).toBeUndefined(); + }); + + it('should return information for the root field, when multi fields and root are having actions', async () => { + mockGetActions.mockResolvedValue([action]); + const information = await getVisualizeInformation( + { ...field, name: 'rootField' } as IndexPatternField, + '1', + [], + [ + { ...field, name: 'multi1' }, + { ...field, name: 'multi2' }, + ] as IndexPatternField[] + ); + expect(information).not.toBeUndefined(); + expect(information?.field).toHaveProperty('name', 'rootField'); + }); + + it('should return information for first multi field that has a compatible action', async () => { + mockGetActions.mockImplementation(async (_, { fieldName }) => { + if (fieldName === 'multi2' || fieldName === 'multi3') { + return [action]; + } + return []; + }); + const information = await getVisualizeInformation( + { ...field, name: 'rootField' } as IndexPatternField, + '1', + [], + [ + { ...field, name: 'multi1' }, + { ...field, name: 'multi2' }, + { ...field, name: 'multi3' }, + ] as IndexPatternField[] + ); + expect(information).not.toBeUndefined(); + expect(information?.field).toHaveProperty('name', 'multi2'); + }); + }); +}); diff --git a/src/plugins/discover/public/application/apps/main/components/sidebar/lib/visualize_trigger_utils.ts b/src/plugins/discover/public/application/apps/main/components/sidebar/lib/visualize_trigger_utils.ts index 2fabaa0ddd100..f00b430e5acef 100644 --- a/src/plugins/discover/public/application/apps/main/components/sidebar/lib/visualize_trigger_utils.ts +++ b/src/plugins/discover/public/application/apps/main/components/sidebar/lib/visualize_trigger_utils.ts @@ -41,30 +41,6 @@ async function getCompatibleActions( return compatibleActions; } -export async function getVisualizeHref( - field: IndexPatternField, - indexPatternId: string | undefined, - contextualFields: string[] -) { - if (!indexPatternId) return undefined; - const triggerOptions = { - indexPatternId, - fieldName: field.name, - contextualFields, - trigger: getTrigger(field.type), - }; - const compatibleActions = await getCompatibleActions( - field.name, - indexPatternId, - contextualFields, - getTriggerConstant(field.type) - ); - // enable the link only if only one action is registered - return compatibleActions.length === 1 - ? compatibleActions[0].getHref?.(triggerOptions) - : undefined; -} - export function triggerVisualizeActions( field: IndexPatternField, indexPatternId: string | undefined, @@ -80,21 +56,55 @@ export function triggerVisualizeActions( getUiActions().getTrigger(trigger).exec(triggerOptions); } -export async function isFieldVisualizable( +export interface VisualizeInformation { + field: IndexPatternField; + href?: string; +} + +/** + * Returns the field name and potentially href of the field or the first multi-field + * that has a compatible visualize uiAction. + */ +export async function getVisualizeInformation( field: IndexPatternField, indexPatternId: string | undefined, - contextualFields: string[] -) { + contextualFields: string[], + multiFields: IndexPatternField[] = [] +): Promise { if (field.name === '_id' || !indexPatternId) { - // for first condition you'd get a 'Fielddata access on the _id field is disallowed' error on ES side. - return false; + // _id fields are not visualizeable in ES + return undefined; } - const trigger = getTriggerConstant(field.type); - const compatibleActions = await getCompatibleActions( - field.name, - indexPatternId, - contextualFields, - trigger - ); - return compatibleActions.length > 0 && field.visualizable; + + for (const f of [field, ...multiFields]) { + if (!f.visualizable) { + continue; + } + // Retrieve compatible actions for the specific field + const actions = await getCompatibleActions( + f.name, + indexPatternId, + contextualFields, + getTriggerConstant(f.type) + ); + + // if the field has compatible actions use this field for visualizing + if (actions.length > 0) { + const triggerOptions = { + indexPatternId, + fieldName: f.name, + contextualFields, + trigger: getTrigger(f.type), + }; + + return { + field: f, + // We use the href of the first action always. Multiple actions will only work + // via the modal shown by triggerVisualizeActions that should be called via onClick. + href: await actions[0].getHref?.(triggerOptions), + }; + } + } + + return undefined; } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 837716ec9dd5a..5f86e020a0407 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -1625,7 +1625,6 @@ "discover.fieldChooser.detailViews.filterOutValueButtonAriaLabel": "{field}を除外:\"{value}\"", "discover.fieldChooser.detailViews.filterValueButtonAriaLabel": "{field}を除外:\"{value}\"", "discover.fieldChooser.detailViews.valueOfRecordsText": "{value} / {totalValue}件のレコード", - "discover.fieldChooser.detailViews.visualizeLinkText": "可視化", "discover.fieldChooser.discoverField.addButtonAriaLabel": "{field}を表に追加", "discover.fieldChooser.discoverField.addFieldTooltip": "フィールドを列として追加", "discover.fieldChooser.discoverField.deleteFieldLabel": "インデックスパターンフィールドを削除", @@ -1634,7 +1633,6 @@ "discover.fieldChooser.discoverField.multiFields": "マルチフィールド", "discover.fieldChooser.discoverField.removeButtonAriaLabel": "{field}を表から削除", "discover.fieldChooser.discoverField.removeFieldTooltip": "フィールドを表から削除", - "discover.fieldChooser.discoverField.scriptedFieldsTakeLongExecuteDescription": "スクリプトフィールドは実行に時間がかかる場合があります。", "discover.fieldChooser.fieldCalculator.analysisIsNotAvailableForGeoFieldsErrorMessage": "ジオフィールドは分析できません。", "discover.fieldChooser.fieldCalculator.analysisIsNotAvailableForObjectFieldsErrorMessage": "オブジェクトフィールドは分析できません。", "discover.fieldChooser.fieldCalculator.fieldIsNotPresentInDocumentsErrorMessage": "このフィールドはElasticsearchマッピングに表示されますが、ドキュメントテーブルの{hitsLength}件のドキュメントには含まれません。可視化や検索は可能な場合があります。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 0192566db0731..acad67a0b1c7a 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -1634,7 +1634,6 @@ "discover.fieldChooser.detailViews.filterOutValueButtonAriaLabel": "筛除 {field}:“{value}”", "discover.fieldChooser.detailViews.filterValueButtonAriaLabel": "筛留 {field}:“{value}”", "discover.fieldChooser.detailViews.valueOfRecordsText": "{value} / {totalValue} 条记录", - "discover.fieldChooser.detailViews.visualizeLinkText": "Visualize", "discover.fieldChooser.discoverField.addButtonAriaLabel": "将 {field} 添加到表中", "discover.fieldChooser.discoverField.addFieldTooltip": "将字段添加为列", "discover.fieldChooser.discoverField.deleteFieldLabel": "删除索引模式字段", @@ -1643,7 +1642,6 @@ "discover.fieldChooser.discoverField.multiFields": "多字段", "discover.fieldChooser.discoverField.removeButtonAriaLabel": "从表中移除 {field}", "discover.fieldChooser.discoverField.removeFieldTooltip": "从表中移除字段", - "discover.fieldChooser.discoverField.scriptedFieldsTakeLongExecuteDescription": "脚本字段执行时间会很长。", "discover.fieldChooser.fieldCalculator.analysisIsNotAvailableForGeoFieldsErrorMessage": "分析不适用于地理字段。", "discover.fieldChooser.fieldCalculator.analysisIsNotAvailableForObjectFieldsErrorMessage": "分析不适用于对象字段。", "discover.fieldChooser.fieldCalculator.fieldIsNotPresentInDocumentsErrorMessage": "此字段在您的 Elasticsearch 映射中,但不在文档表中显示的 {hitsLength} 个文档中。您可能仍能够基于它可视化或搜索。", From 23c8d181989b69b8178d0c89c757fc9ce0e9df68 Mon Sep 17 00:00:00 2001 From: Spencer Date: Thu, 24 Jun 2021 10:59:49 -0700 Subject: [PATCH 11/25] [ui-shared-deps] reuse react-beautiful-dnd from eui (#102834) Co-authored-by: spalger --- packages/kbn-ui-shared-deps/src/entry.js | 1 + packages/kbn-ui-shared-deps/src/index.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/kbn-ui-shared-deps/src/entry.js b/packages/kbn-ui-shared-deps/src/entry.js index b8d21a473c65f..0e91c45ae6392 100644 --- a/packages/kbn-ui-shared-deps/src/entry.js +++ b/packages/kbn-ui-shared-deps/src/entry.js @@ -40,6 +40,7 @@ export const ElasticEui = require('@elastic/eui'); export const ElasticEuiLibServices = require('@elastic/eui/lib/services'); export const ElasticEuiLibServicesFormat = require('@elastic/eui/lib/services/format'); export const ElasticEuiChartsTheme = require('@elastic/eui/dist/eui_charts_theme'); +export const ReactBeautifulDnD = require('react-beautiful-dnd'); export const Theme = require('./theme.ts'); export const Lodash = require('lodash'); export const LodashFp = require('lodash/fp'); diff --git a/packages/kbn-ui-shared-deps/src/index.js b/packages/kbn-ui-shared-deps/src/index.js index c5853dc091875..36c2e6b02879e 100644 --- a/packages/kbn-ui-shared-deps/src/index.js +++ b/packages/kbn-ui-shared-deps/src/index.js @@ -85,6 +85,8 @@ exports.externals = { '@elastic/eui/dist/eui_charts_theme': '__kbnSharedDeps__.ElasticEuiChartsTheme', '@elastic/eui/dist/eui_theme_light.json': '__kbnSharedDeps__.Theme.euiLightVars', '@elastic/eui/dist/eui_theme_dark.json': '__kbnSharedDeps__.Theme.euiDarkVars', + // transient dep of eui + 'react-beautiful-dnd': '__kbnSharedDeps__.ReactBeautifulDnD', lodash: '__kbnSharedDeps__.Lodash', 'lodash/fp': '__kbnSharedDeps__.LodashFp', fflate: '__kbnSharedDeps__.Fflate', From fb7b596841be2c115cd2ef78d62eeaf5d994aa78 Mon Sep 17 00:00:00 2001 From: Kyle Pollich Date: Thu, 24 Jun 2021 14:29:56 -0400 Subject: [PATCH 12/25] Fix missing setting modal in integrations app (#103317) --- .../public/applications/integrations/app.tsx | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/integrations/app.tsx b/x-pack/plugins/fleet/public/applications/integrations/app.tsx index c69b6805e0e86..cad51a54d7074 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/app.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/app.tsx @@ -7,7 +7,7 @@ import React, { memo, useEffect, useState } from 'react'; import type { AppMountParameters } from 'kibana/public'; -import { EuiCode, EuiEmptyPrompt, EuiErrorBoundary, EuiPanel } from '@elastic/eui'; +import { EuiCode, EuiEmptyPrompt, EuiErrorBoundary, EuiPanel, EuiPortal } from '@elastic/eui'; import type { History } from 'history'; import { createHashHistory } from 'history'; import { Router, Redirect, Route, Switch } from 'react-router-dom'; @@ -29,10 +29,10 @@ import type { FleetConfigType, FleetStartServices } from '../../plugin'; import { KibanaContextProvider } from '../../../../../../src/plugins/kibana_react/public'; import { EuiThemeProvider } from '../../../../../../src/plugins/kibana_react/common'; -import { AgentPolicyContextProvider } from './hooks'; +import { AgentPolicyContextProvider, useUrlModal } from './hooks'; import { INTEGRATIONS_ROUTING_PATHS } from './constants'; -import { Error, Loading } from './components'; +import { Error, Loading, SettingFlyout } from './components'; import type { UIExtensionsStorage } from './types'; @@ -234,12 +234,24 @@ export const IntegrationsAppContext: React.FC<{ ); export const AppRoutes = memo(() => { + const { modal, setModal } = useUrlModal(); return ( - - - - - - + <> + {modal === 'settings' && ( + + { + setModal(null); + }} + /> + + )} + + + + + + + ); }); From fbcf405f156ab99ab40d0de6993479712a24f55b Mon Sep 17 00:00:00 2001 From: Josh Dover <1813008+joshdover@users.noreply.github.com> Date: Thu, 24 Jun 2021 20:47:38 +0200 Subject: [PATCH 13/25] Add telemetry for Elastic Cloud (#102390) --- NOTICE.txt | 4 + package.json | 9 +- x-pack/plugins/cloud/public/fullstory.ts | 100 +++++++++++ .../plugins/cloud/public/plugin.test.mocks.ts | 13 ++ x-pack/plugins/cloud/public/plugin.test.ts | 164 ++++++++++++++++-- x-pack/plugins/cloud/public/plugin.ts | 79 ++++++++- .../cloud/server/assets/fullstory_library.js | 13 ++ x-pack/plugins/cloud/server/config.test.ts | 6 +- x-pack/plugins/cloud/server/plugin.ts | 8 + .../cloud/server/routes/fullstory.test.ts | 62 +++++++ .../plugins/cloud/server/routes/fullstory.ts | 75 ++++++++ x-pack/test/cloud_integration/config.ts | 87 ++++++++++ x-pack/test/cloud_integration/constants.ts | 8 + .../fixtures/saml/saml_provider/kibana.json | 7 + .../fixtures/saml/saml_provider/metadata.xml | 41 +++++ .../saml/saml_provider/server/index.ts | 15 ++ .../saml/saml_provider/server/init_routes.ts | 58 +++++++ .../saml/saml_provider/server/saml_tools.ts | 161 +++++++++++++++++ .../ftr_provider_context.d.ts | 13 ++ .../test/cloud_integration/tests/fullstory.ts | 66 +++++++ yarn.lock | 5 + 21 files changed, 973 insertions(+), 21 deletions(-) create mode 100644 x-pack/plugins/cloud/public/fullstory.ts create mode 100644 x-pack/plugins/cloud/public/plugin.test.mocks.ts create mode 100644 x-pack/plugins/cloud/server/assets/fullstory_library.js create mode 100644 x-pack/plugins/cloud/server/routes/fullstory.test.ts create mode 100644 x-pack/plugins/cloud/server/routes/fullstory.ts create mode 100644 x-pack/test/cloud_integration/config.ts create mode 100644 x-pack/test/cloud_integration/constants.ts create mode 100644 x-pack/test/cloud_integration/fixtures/saml/saml_provider/kibana.json create mode 100644 x-pack/test/cloud_integration/fixtures/saml/saml_provider/metadata.xml create mode 100644 x-pack/test/cloud_integration/fixtures/saml/saml_provider/server/index.ts create mode 100644 x-pack/test/cloud_integration/fixtures/saml/saml_provider/server/init_routes.ts create mode 100644 x-pack/test/cloud_integration/fixtures/saml/saml_provider/server/saml_tools.ts create mode 100644 x-pack/test/cloud_integration/ftr_provider_context.d.ts create mode 100644 x-pack/test/cloud_integration/tests/fullstory.ts diff --git a/NOTICE.txt b/NOTICE.txt index 4eec329b7a603..b0f7e65f46fa9 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -235,6 +235,10 @@ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +--- +Portions of this code are licensed under the following license: +For license information please see https://edge.fullstory.com/s/fs.js.LICENSE.txt + --- This product bundles bootstrap@3.3.6 which is available under a "MIT" license. diff --git a/package.json b/package.json index ecedb64c343ec..ceb178d068519 100644 --- a/package.json +++ b/package.json @@ -128,25 +128,26 @@ "@kbn/analytics": "link:bazel-bin/packages/kbn-analytics", "@kbn/apm-config-loader": "link:bazel-bin/packages/kbn-apm-config-loader", "@kbn/apm-utils": "link:bazel-bin/packages/kbn-apm-utils", + "@kbn/common-utils": "link:bazel-bin/packages/kbn-common-utils", "@kbn/config": "link:bazel-bin/packages/kbn-config", "@kbn/config-schema": "link:bazel-bin/packages/kbn-config-schema", "@kbn/crypto": "link:bazel-bin/packages/kbn-crypto", - "@kbn/mapbox-gl": "link:bazel-bin/packages/kbn-mapbox-gl", "@kbn/i18n": "link:bazel-bin/packages/kbn-i18n", "@kbn/interpreter": "link:bazel-bin/packages/kbn-interpreter", "@kbn/io-ts-utils": "link:bazel-bin/packages/kbn-io-ts-utils", "@kbn/legacy-logging": "link:bazel-bin/packages/kbn-legacy-logging", "@kbn/logging": "link:bazel-bin/packages/kbn-logging", + "@kbn/mapbox-gl": "link:bazel-bin/packages/kbn-mapbox-gl", "@kbn/monaco": "link:bazel-bin/packages/kbn-monaco", "@kbn/rule-data-utils": "link:bazel-bin/packages/kbn-rule-data-utils", - "@kbn/securitysolution-list-constants": "link:bazel-bin/packages/kbn-securitysolution-list-constants", "@kbn/securitysolution-es-utils": "link:bazel-bin/packages/kbn-securitysolution-es-utils", "@kbn/securitysolution-hook-utils": "link:bazel-bin/packages/kbn-securitysolution-hook-utils", - "@kbn/securitysolution-io-ts-types": "link:bazel-bin/packages/kbn-securitysolution-io-ts-types", "@kbn/securitysolution-io-ts-alerting-types": "link:bazel-bin/packages/kbn-securitysolution-io-ts-alerting-types", "@kbn/securitysolution-io-ts-list-types": "link:bazel-bin/packages/kbn-securitysolution-io-ts-list-types", + "@kbn/securitysolution-io-ts-types": "link:bazel-bin/packages/kbn-securitysolution-io-ts-types", "@kbn/securitysolution-io-ts-utils": "link:bazel-bin/packages/kbn-securitysolution-io-ts-utils", "@kbn/securitysolution-list-api": "link:bazel-bin/packages/kbn-securitysolution-list-api", + "@kbn/securitysolution-list-constants": "link:bazel-bin/packages/kbn-securitysolution-list-constants", "@kbn/securitysolution-list-hooks": "link:bazel-bin/packages/kbn-securitysolution-list-hooks", "@kbn/securitysolution-list-utils": "link:bazel-bin/packages/kbn-securitysolution-list-utils", "@kbn/securitysolution-t-grid": "link:bazel-bin/packages/kbn-securitysolution-t-grid", @@ -158,7 +159,6 @@ "@kbn/ui-framework": "link:bazel-bin/packages/kbn-ui-framework", "@kbn/ui-shared-deps": "link:bazel-bin/packages/kbn-ui-shared-deps", "@kbn/utility-types": "link:bazel-bin/packages/kbn-utility-types", - "@kbn/common-utils": "link:bazel-bin/packages/kbn-common-utils", "@kbn/utils": "link:bazel-bin/packages/kbn-utils", "@loaders.gl/core": "^2.3.1", "@loaders.gl/json": "^2.3.1", @@ -273,6 +273,7 @@ "jquery": "^3.5.0", "js-levenshtein": "^1.1.6", "js-search": "^1.4.3", + "js-sha256": "^0.9.0", "js-yaml": "^3.14.0", "json-stable-stringify": "^1.0.1", "json-stringify-pretty-compact": "1.2.0", diff --git a/x-pack/plugins/cloud/public/fullstory.ts b/x-pack/plugins/cloud/public/fullstory.ts new file mode 100644 index 0000000000000..31e5ec128b9a3 --- /dev/null +++ b/x-pack/plugins/cloud/public/fullstory.ts @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { sha256 } from 'js-sha256'; +import type { IBasePath, PackageInfo } from '../../../../src/core/public'; + +export interface FullStoryDeps { + basePath: IBasePath; + orgId: string; + packageInfo: PackageInfo; + userIdPromise: Promise; +} + +interface FullStoryApi { + identify(userId: string, userVars?: Record): void; + event(eventName: string, eventProperties: Record): void; +} + +export const initializeFullStory = async ({ + basePath, + orgId, + packageInfo, + userIdPromise, +}: FullStoryDeps) => { + // @ts-expect-error + window._fs_debug = false; + // @ts-expect-error + window._fs_host = 'fullstory.com'; + // @ts-expect-error + window._fs_script = basePath.prepend(`/internal/cloud/${packageInfo.buildNum}/fullstory.js`); + // @ts-expect-error + window._fs_org = orgId; + // @ts-expect-error + window._fs_namespace = 'FSKibana'; + + /* eslint-disable */ + (function(m,n,e,t,l,o,g,y){ + if (e in m) {if(m.console && m.console.log) { m.console.log('FullStory namespace conflict. Please set window["_fs_namespace"].');} return;} + // @ts-expect-error + g=m[e]=function(a,b,s){g.q?g.q.push([a,b,s]):g._api(a,b,s);};g.q=[]; + // @ts-expect-error + o=n.createElement(t);o.async=1;o.crossOrigin='anonymous';o.src=_fs_script; + // @ts-expect-error + y=n.getElementsByTagName(t)[0];y.parentNode.insertBefore(o,y); + // @ts-expect-error + g.identify=function(i,v,s){g(l,{uid:i},s);if(v)g(l,v,s)};g.setUserVars=function(v,s){g(l,v,s)};g.event=function(i,v,s){g('event',{n:i,p:v},s)}; + // @ts-expect-error + g.anonymize=function(){g.identify(!!0)}; + // @ts-expect-error + g.shutdown=function(){g("rec",!1)};g.restart=function(){g("rec",!0)}; + // @ts-expect-error + g.log = function(a,b){g("log",[a,b])}; + // @ts-expect-error + g.consent=function(a){g("consent",!arguments.length||a)}; + // @ts-expect-error + g.identifyAccount=function(i,v){o='account';v=v||{};v.acctId=i;g(o,v)}; + // @ts-expect-error + g.clearUserCookie=function(){}; + // @ts-expect-error + g.setVars=function(n, p){g('setVars',[n,p]);}; + // @ts-expect-error + g._w={};y='XMLHttpRequest';g._w[y]=m[y];y='fetch';g._w[y]=m[y]; + // @ts-expect-error + if(m[y])m[y]=function(){return g._w[y].apply(this,arguments)}; + // @ts-expect-error + g._v="1.3.0"; + // @ts-expect-error + })(window,document,window['_fs_namespace'],'script','user'); + /* eslint-enable */ + + // @ts-expect-error + const fullstory: FullStoryApi = window.FSKibana; + + // Record an event that Kibana was opened so we can easily search for sessions that use Kibana + // @ts-expect-error + window.FSKibana.event('Loaded Kibana', { + kibana_version_str: packageInfo.version, + }); + + // Use a promise here so we don't have to wait to retrieve the user to start recording the session + userIdPromise + .then((userId) => { + if (!userId) return; + // Do the hashing here to keep it at clear as possible in our source code that we do not send literal user IDs + const hashedId = sha256(userId.toString()); + // @ts-expect-error + window.FSKibana.identify(hashedId); + }) + .catch((e) => { + // eslint-disable-next-line no-console + console.error( + `[cloud.full_story] Could not call FS.identify due to error: ${e.toString()}`, + e + ); + }); +}; diff --git a/x-pack/plugins/cloud/public/plugin.test.mocks.ts b/x-pack/plugins/cloud/public/plugin.test.mocks.ts new file mode 100644 index 0000000000000..889b8492d5b1b --- /dev/null +++ b/x-pack/plugins/cloud/public/plugin.test.mocks.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { FullStoryDeps } from './fullstory'; + +export const initializeFullStoryMock = jest.fn(); +jest.doMock('./fullstory', () => { + return { initializeFullStory: initializeFullStoryMock }; +}); diff --git a/x-pack/plugins/cloud/public/plugin.test.ts b/x-pack/plugins/cloud/public/plugin.test.ts index 981c5138d98d2..af4d3c4c9005d 100644 --- a/x-pack/plugins/cloud/public/plugin.test.ts +++ b/x-pack/plugins/cloud/public/plugin.test.ts @@ -9,11 +9,98 @@ import { nextTick } from '@kbn/test/jest'; import { coreMock } from 'src/core/public/mocks'; import { homePluginMock } from 'src/plugins/home/public/mocks'; import { securityMock } from '../../security/public/mocks'; -import { CloudPlugin } from './plugin'; +import { initializeFullStoryMock } from './plugin.test.mocks'; +import { CloudPlugin, CloudConfigType, loadFullStoryUserId } from './plugin'; describe('Cloud Plugin', () => { + describe('#setup', () => { + describe('setupFullstory', () => { + beforeEach(() => { + initializeFullStoryMock.mockReset(); + }); + + const setupPlugin = async ({ + config = {}, + securityEnabled = true, + currentUserProps = {}, + }: { + config?: Partial; + securityEnabled?: boolean; + currentUserProps?: Record; + }) => { + const initContext = coreMock.createPluginInitializerContext({ + id: 'cloudId', + base_url: 'https://cloud.elastic.co', + deployment_url: '/abc123', + profile_url: '/profile/alice', + organization_url: '/org/myOrg', + full_story: { + enabled: false, + }, + ...config, + }); + const plugin = new CloudPlugin(initContext); + + const coreSetup = coreMock.createSetup(); + const securitySetup = securityMock.createSetup(); + securitySetup.authc.getCurrentUser.mockResolvedValue( + securityMock.createMockAuthenticatedUser(currentUserProps) + ); + + const setup = plugin.setup(coreSetup, securityEnabled ? { security: securitySetup } : {}); + // Wait for fullstory dynamic import to resolve + await new Promise((r) => setImmediate(r)); + + return { initContext, plugin, setup }; + }; + + it('calls initializeFullStory with correct args when enabled and org_id are set', async () => { + const { initContext } = await setupPlugin({ + config: { full_story: { enabled: true, org_id: 'foo' } }, + currentUserProps: { + username: '1234', + }, + }); + + expect(initializeFullStoryMock).toHaveBeenCalled(); + const { + basePath, + orgId, + packageInfo, + userIdPromise, + } = initializeFullStoryMock.mock.calls[0][0]; + expect(basePath.prepend).toBeDefined(); + expect(orgId).toEqual('foo'); + expect(packageInfo).toEqual(initContext.env.packageInfo); + expect(await userIdPromise).toEqual('1234'); + }); + + it('passes undefined user ID when security is not available', async () => { + await setupPlugin({ + config: { full_story: { enabled: true, org_id: 'foo' } }, + securityEnabled: false, + }); + + expect(initializeFullStoryMock).toHaveBeenCalled(); + const { orgId, userIdPromise } = initializeFullStoryMock.mock.calls[0][0]; + expect(orgId).toEqual('foo'); + expect(await userIdPromise).toEqual(undefined); + }); + + it('does not call initializeFullStory when enabled=false', async () => { + await setupPlugin({ config: { full_story: { enabled: false, org_id: 'foo' } } }); + expect(initializeFullStoryMock).not.toHaveBeenCalled(); + }); + + it('does not call initializeFullStory when org_id is undefined', async () => { + await setupPlugin({ config: { full_story: { enabled: true } } }); + expect(initializeFullStoryMock).not.toHaveBeenCalled(); + }); + }); + }); + describe('#start', () => { - function setupPlugin() { + const startPlugin = () => { const plugin = new CloudPlugin( coreMock.createPluginInitializerContext({ id: 'cloudId', @@ -21,6 +108,9 @@ describe('Cloud Plugin', () => { deployment_url: '/abc123', profile_url: '/profile/alice', organization_url: '/org/myOrg', + full_story: { + enabled: false, + }, }) ); const coreSetup = coreMock.createSetup(); @@ -29,10 +119,10 @@ describe('Cloud Plugin', () => { plugin.setup(coreSetup, { home: homeSetup }); return { coreSetup, plugin }; - } + }; it('registers help support URL', async () => { - const { plugin } = setupPlugin(); + const { plugin } = startPlugin(); const coreStart = coreMock.createStart(); const securityStart = securityMock.createStart(); @@ -47,7 +137,7 @@ describe('Cloud Plugin', () => { }); it('does not register custom nav links on anonymous pages', async () => { - const { plugin } = setupPlugin(); + const { plugin } = startPlugin(); const coreStart = coreMock.createStart(); coreStart.http.anonymousPaths.isAnonymous.mockReturnValue(true); @@ -68,7 +158,7 @@ describe('Cloud Plugin', () => { }); it('registers a custom nav link for superusers', async () => { - const { plugin } = setupPlugin(); + const { plugin } = startPlugin(); const coreStart = coreMock.createStart(); const securityStart = securityMock.createStart(); @@ -94,7 +184,7 @@ describe('Cloud Plugin', () => { }); it('registers a custom nav link when there is an error retrieving the current user', async () => { - const { plugin } = setupPlugin(); + const { plugin } = startPlugin(); const coreStart = coreMock.createStart(); const securityStart = securityMock.createStart(); @@ -116,7 +206,7 @@ describe('Cloud Plugin', () => { }); it('does not register a custom nav link for non-superusers', async () => { - const { plugin } = setupPlugin(); + const { plugin } = startPlugin(); const coreStart = coreMock.createStart(); const securityStart = securityMock.createStart(); @@ -133,7 +223,7 @@ describe('Cloud Plugin', () => { }); it('registers user profile links for superusers', async () => { - const { plugin } = setupPlugin(); + const { plugin } = startPlugin(); const coreStart = coreMock.createStart(); const securityStart = securityMock.createStart(); @@ -169,7 +259,7 @@ describe('Cloud Plugin', () => { }); it('registers profile links when there is an error retrieving the current user', async () => { - const { plugin } = setupPlugin(); + const { plugin } = startPlugin(); const coreStart = coreMock.createStart(); const securityStart = securityMock.createStart(); @@ -201,7 +291,7 @@ describe('Cloud Plugin', () => { }); it('does not register profile links for non-superusers', async () => { - const { plugin } = setupPlugin(); + const { plugin } = startPlugin(); const coreStart = coreMock.createStart(); const securityStart = securityMock.createStart(); @@ -217,4 +307,56 @@ describe('Cloud Plugin', () => { expect(securityStart.navControlService.addUserMenuLinks).not.toHaveBeenCalled(); }); }); + + describe('loadFullStoryUserId', () => { + let consoleMock: jest.SpyInstance; + + beforeEach(() => { + consoleMock = jest.spyOn(console, 'debug').mockImplementation(() => {}); + }); + afterEach(() => { + consoleMock.mockRestore(); + }); + + it('returns principal ID when username specified', async () => { + expect( + await loadFullStoryUserId({ + getCurrentUser: jest.fn().mockResolvedValue({ + username: '1234', + }), + }) + ).toEqual('1234'); + expect(consoleMock).not.toHaveBeenCalled(); + }); + + it('returns undefined if getCurrentUser throws', async () => { + expect( + await loadFullStoryUserId({ + getCurrentUser: jest.fn().mockRejectedValue(new Error(`Oh no!`)), + }) + ).toBeUndefined(); + }); + + it('returns undefined if getCurrentUser returns undefined', async () => { + expect( + await loadFullStoryUserId({ + getCurrentUser: jest.fn().mockResolvedValue(undefined), + }) + ).toBeUndefined(); + }); + + it('returns undefined and logs if username undefined', async () => { + expect( + await loadFullStoryUserId({ + getCurrentUser: jest.fn().mockResolvedValue({ + username: undefined, + metadata: { foo: 'bar' }, + }), + }) + ).toBeUndefined(); + expect(consoleMock).toHaveBeenLastCalledWith( + `[cloud.full_story] username not specified. User metadata: {"foo":"bar"}` + ); + }); + }); }); diff --git a/x-pack/plugins/cloud/public/plugin.ts b/x-pack/plugins/cloud/public/plugin.ts index 5820452706539..68dece1bc5d3d 100644 --- a/x-pack/plugins/cloud/public/plugin.ts +++ b/x-pack/plugins/cloud/public/plugin.ts @@ -5,9 +5,20 @@ * 2.0. */ -import { CoreSetup, CoreStart, Plugin, PluginInitializerContext, HttpStart } from 'src/core/public'; +import { + CoreSetup, + CoreStart, + Plugin, + PluginInitializerContext, + HttpStart, + IBasePath, +} from 'src/core/public'; import { i18n } from '@kbn/i18n'; -import { SecurityPluginSetup, SecurityPluginStart } from '../../security/public'; +import type { + AuthenticatedUser, + SecurityPluginSetup, + SecurityPluginStart, +} from '../../security/public'; import { getIsCloudEnabled } from '../common/is_cloud_enabled'; import { ELASTIC_SUPPORT_LINK } from '../common/constants'; import { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; @@ -21,6 +32,10 @@ export interface CloudConfigType { profile_url?: string; deployment_url?: string; organization_url?: string; + full_story: { + enabled: boolean; + org_id?: string; + }; } interface CloudSetupDependencies { @@ -51,7 +66,12 @@ export class CloudPlugin implements Plugin { this.isCloudEnabled = false; } - public setup(core: CoreSetup, { home }: CloudSetupDependencies) { + public setup(core: CoreSetup, { home, security }: CloudSetupDependencies) { + this.setupFullstory({ basePath: core.http.basePath, security }).catch((e) => + // eslint-disable-next-line no-console + console.debug(`Error setting up FullStory: ${e.toString()}`) + ); + const { id, cname, @@ -135,4 +155,57 @@ export class CloudPlugin implements Plugin { const user = await security.authc.getCurrentUser().catch(() => null); return user?.roles.includes('superuser') ?? true; } + + private async setupFullstory({ + basePath, + security, + }: CloudSetupDependencies & { basePath: IBasePath }) { + const { enabled, org_id: orgId } = this.config.full_story; + if (!enabled || !orgId) { + return; + } + + // Keep this import async so that we do not load any FullStory code into the browser when it is disabled. + const { initializeFullStory } = await import('./fullstory'); + const userIdPromise: Promise = security + ? loadFullStoryUserId({ getCurrentUser: security.authc.getCurrentUser }) + : Promise.resolve(undefined); + + initializeFullStory({ + basePath, + orgId, + packageInfo: this.initializerContext.env.packageInfo, + userIdPromise, + }); + } } + +/** @internal exported for testing */ +export const loadFullStoryUserId = async ({ + getCurrentUser, +}: { + getCurrentUser: () => Promise; +}) => { + try { + const currentUser = await getCurrentUser().catch(() => undefined); + if (!currentUser) { + return undefined; + } + + // Log very defensively here so we can debug this easily if it breaks + if (!currentUser.username) { + // eslint-disable-next-line no-console + console.debug( + `[cloud.full_story] username not specified. User metadata: ${JSON.stringify( + currentUser.metadata + )}` + ); + } + + return currentUser.username; + } catch (e) { + // eslint-disable-next-line no-console + console.error(`[cloud.full_story] Error loading the current user: ${e.toString()}`, e); + return undefined; + } +}; diff --git a/x-pack/plugins/cloud/server/assets/fullstory_library.js b/x-pack/plugins/cloud/server/assets/fullstory_library.js new file mode 100644 index 0000000000000..487d6c8e8528c --- /dev/null +++ b/x-pack/plugins/cloud/server/assets/fullstory_library.js @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* @notice + * Portions of this code are licensed under the following license: + * For license information please see https://edge.fullstory.com/s/fs.js.LICENSE.txt + */ +/* eslint-disable */ +!function(e){var t={};function n(r){if(t[r])return t[r].exports;var i=t[r]={i:r,l:!1,exports:{}};return e[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)n.d(r,i,function(t){return e[t]}.bind(null,i));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/s",n(n.s=4)}([function(e,t,n){"use strict";var r=this&&this.__assign||function(){return(r=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0},t.assertExhaustive=function(e,t){throw void 0===t&&(t="Reached unexpected case in exhaustive switch"),new Error(t)},t.pick=function(e){for(var t=[],n=1;na&&(i=a);var u=n.split(/[#,]/);if(u.length<3&&(u=n.split("`")).length<3)return null;var c=u[0],h=u[1],d=u[2],l=u[3],p="";void 0!==l&&(p=decodeURIComponent(l),(f.indexOf(p)>=0||v.indexOf(p)>=0)&&(o("Ignoring invalid app key \""+p+"\" from cookie."),p=""));var m=d.split(":");return{expirationAbsTimeSeconds:i,host:c,orgId:h,userId:m[0],sessionId:m[1]||"",appKeyHash:p}}function y(e){for(var t={},n=e.cookie.split(";"),r=0;r=0&&(t=t.slice(0,n)),t}(e))?e:0==e.indexOf("www.")?"app."+e.slice(4):"app."+e:e}function H(e){return e?e+"/s/fs.js":void 0}!function(e){e.MUT_INSERT=2,e.MUT_REMOVE=3,e.MUT_ATTR=4,e.MUT_TEXT=6,e.MOUSEMOVE=8,e.MOUSEMOVE_CURVE=9,e.SCROLL_LAYOUT=10,e.SCROLL_LAYOUT_CURVE=11,e.MOUSEDOWN=12,e.MOUSEUP=13,e.KEYDOWN=14,e.KEYUP=15,e.CLICK=16,e.FOCUS=17,e.VALUECHANGE=18,e.RESIZE_LAYOUT=19,e.DOMLOADED=20,e.LOAD=21,e.PLACEHOLDER_SIZE=22,e.UNLOAD=23,e.BLUR=24,e.SET_FRAME_BASE=25,e.TOUCHSTART=32,e.TOUCHEND=33,e.TOUCHCANCEL=34,e.TOUCHMOVE=35,e.TOUCHMOVE_CURVE=36,e.NAVIGATE=37,e.PLAY=38,e.PAUSE=39,e.RESIZE_VISUAL=40,e.RESIZE_VISUAL_CURVE=41,e.RESIZE_DOCUMENT=42,e.LOG=48,e.ERROR=49,e.DBL_CLICK=50,e.FORM_SUBMIT=51,e.WINDOW_FOCUS=52,e.WINDOW_BLUR=53,e.HEARTBEAT=54,e.WATCHED_ELEM=56,e.PERF_ENTRY=57,e.REC_FEAT_SUPPORTED=58,e.SELECT=59,e.CSSRULE_INSERT=60,e.CSSRULE_DELETE=61,e.FAIL_THROTTLED=62,e.AJAX_REQUEST=63,e.SCROLL_VISUAL_OFFSET=64,e.SCROLL_VISUAL_OFFSET_CURVE=65,e.MEDIA_QUERY_CHANGE=66,e.RESOURCE_TIMING_BUFFER_FULL=67,e.MUT_SHADOW=68,e.DISABLE_STYLESHEET=69,e.FULLSCREEN=70,e.FULLSCREEN_ERROR=71,e.ADOPTED_STYLESHEETS=72,e.CUSTOM_ELEMENT_DEFINED=73,e.MODAL_OPEN=74,e.MODAL_CLOSE=75,e.SLOW_INTERACTION=76,e.LONG_FRAME=77,e.TIMING=78,e.STORAGE_WRITE_FAILURE=79,e.KEEP_ELEMENT=2e3,e.KEEP_URL=2001,e.KEEP_BOUNCE=2002,e.SYS_SETVAR=8193,e.SYS_RESOURCEHASH=8195,e.SYS_SETCONSENT=8196,e.SYS_CUSTOM=8197,e.SYS_REPORTCONSENT=8198}(R||(R={})),function(e){e.Unknown=0,e.Serialization=1}(A||(A={})),function(e){e.Unknown=0,e.DomSnapshot=1,e.NodeEncoding=2,e.LzEncoding=3}(x||(x={})),function(e){e.Internal=0,e.Public=1}(O||(O={}));var j,K,V,z,Y,G,Q,X,J,$,Z,ee,te,ne=["print","alert","confirm"];function re(e){switch(e){case R.MOUSEDOWN:case R.MOUSEMOVE:case R.MOUSEMOVE_CURVE:case R.MOUSEUP:case R.KEYDOWN:case R.KEYUP:case R.TOUCHSTART:case R.TOUCHEND:case R.TOUCHMOVE:case R.TOUCHMOVE_CURVE:case R.TOUCHCANCEL:case R.CLICK:case R.SCROLL_LAYOUT:case R.SCROLL_LAYOUT_CURVE:case R.SCROLL_VISUAL_OFFSET:case R.SCROLL_VISUAL_OFFSET_CURVE:case R.NAVIGATE:return!0;}return!1}!function(e){e.GrantConsent=!0,e.RevokeConsent=!1}(j||(j={})),function(e){e.Page=0,e.Document=1}(K||(K={})),function(e){e.Unknown=0,e.Api=1,e.FsShutdownFrame=2,e.Hibernation=3,e.Reidentify=4,e.SettingsBlocked=5,e.Size=6,e.Unload=7}(V||(V={})),function(e){e.Timing=0,e.Navigation=1,e.Resource=2,e.Paint=3,e.Mark=4,e.Measure=5,e.Memory=6}(z||(z={})),function(e){e.Performance=0,e.PerformanceEntries=1,e.PerformanceMemory=2,e.Console=3,e.Ajax=4,e.PerformanceObserver=5,e.AjaxFetch=6}(Y||(Y={})),function(e){e.Node=1,e.Sheet=2}(G||(G={})),function(e){e.StyleSheetHooks=0,e.SetPropertyHooks=1}(Q||(Q={})),function(e){e.User="user",e.Account="acct",e.Event="evt"}(X||(X={})),function(e){e.Elide=0,e.Record=1,e.Whitelist=2}(J||(J={})),function(e){e.ReasonNoSuchOrg=1,e.ReasonOrgDisabled=2,e.ReasonOrgOverQuota=3,e.ReasonBlockedDomain=4,e.ReasonBlockedIp=5,e.ReasonBlockedUserAgent=6,e.ReasonBlockedGeo=7,e.ReasonBlockedTrafficRamping=8,e.ReasonInvalidURL=9,e.ReasonUserOptOut=10,e.ReasonInvalidRecScript=11,e.ReasonDeletingUser=12,e.ReasonNativeHookFailure=13}($||($={})),function(e){e.Unset=0,e.Exclude=1,e.Mask=2,e.Unmask=3,e.Watch=4,e.Keep=5}(Z||(Z={})),function(e){e.Unset=0,e.Click=1}(ee||(ee={})),function(e){e.MaxLogsPerPage=1024,e.MutationProcessingInterval=250,e.CurveSamplingInterval=142,e.DefaultBundleUploadInterval=5e3,e.HeartbeatInitial=4e3,e.HeartbeatMax=256200,e.PageInactivityTimeout=18e5,e.BackoffMax=3e5,e.ScrollSampleInterval=e.MutationProcessingInterval/5,e.InactivityThreshold=4e3,e.MaxPayloadLength=16384}(te||(te={}));function ie(e,t){return function(){try{return e.apply(this,arguments)}catch(e){try{t&&t(e)}catch(e){}}}}var oe=function(){},se=navigator.userAgent,ae=se.indexOf("MSIE ")>-1||se.indexOf("Trident/")>-1,ue=(ae&&se.indexOf("Trident/5"),ae&&se.indexOf("Trident/6"),ae&&se.indexOf("rv:11")>-1),ce=se.indexOf("Edge/")>-1;se.indexOf("CriOS");var he=/^((?!chrome|android).)*safari/i.test(window.navigator.userAgent);function de(){var e=window.navigator.userAgent.match(/Version\/(\d+)/);return e?parseInt(e[1]):-1}function le(e){if(!he)return!1;var t=de();return t>=0&&t===e}function pe(e){if(!he)return!1;var t=de();return t>=0&&tt)return!1;return n==t}function pt(e,t){var n=0;for(var r in e)if(Object.prototype.hasOwnProperty.call(e,r)&&++n>t)return!0;return!1}Ze="function"==typeof s.objectKeys?function(e){return s.objectKeys(e)}:function(e){var t=[];for(var n in e)s.objectHasOwnProp(e,n)&&t.push(n);return t},st=(ot=function(e){return e.matches||e.msMatchesSelector||e.webkitMatchesSelector})(window.Element.prototype),!(at=window.document?window.document.documentElement:void 0)||st&&at instanceof window.Element||(st=ot(at)),it=($e=[st,function(e,t){return st.call(e,t)}])[0],rt=$e[1];var ft;ut=ae?function(e){var t=e.nextSibling;return t&&e.parentNode&&t===e.parentNode.firstChild?null:t}:function(e){return e.nextSibling};var vt;ft=ae?function(e,t){if(e){var n=e.parentNode?e.parentNode.firstChild:null;do{t(e),e=e.nextSibling}while(e&&e!=n)}}:function(e,t){for(;e;e=e.nextSibling)t(e)};vt=ae?function(e){var t=e.previousSibling;return t&&e.parentNode&&t===e.parentNode.lastChild?null:t}:function(e){return e.previousSibling};function _t(e,t){if(!e)return oe;var n=function(e){try{var t=window;return t.Zone&&t.Zone.root&&"function"==typeof t.Zone.root.wrap?t.Zone.root.wrap(e):e}catch(t){return e}}(e);return t&&(n=n.bind(t)),ie(n,function(e){o("Unexpected error: "+e)})}function gt(e){var t,n=Array.prototype.toJSON,r=String.prototype.toJSON;n&&(Array.prototype.toJSON=void 0),r&&(String.prototype.toJSON=void 0);try{t=s.jsonStringify(e)}catch(e){t=mt(e)}finally{n&&(Array.prototype.toJSON=n),r&&(String.prototype.toJSON=r)}return t}function mt(e){var t="Internal error: unable to determine what JSON error was";try{t=(t=""+e).replace(/[^a-zA-Z0-9\.\:\!\, ]/g,"_")}catch(e){}return"\""+t+"\""}function yt(e){var t=e.doctype;if(!t)return"";var n=""}function wt(e){return s.jsonParse(e)}function bt(e){var t=0,n=0;return null==e.screen?[t,n]:(t=parseInt(String(e.screen.width)),n=parseInt(String(e.screen.height)),[t=isNaN(t)?0:t,n=isNaN(n)?0:n])}var St=function(){function e(e,t){this.target=e,this.propertyName=t,this._before=oe,this._afterSync=oe,this._afterAsync=oe,this.on=!1}return e.prototype.before=function(e){return this._before=_t(e),this},e.prototype.afterSync=function(e){return this._afterSync=_t(e),this},e.prototype.afterAsync=function(e){return this._afterAsync=_t(function(t){s.setWindowTimeout(window,ie(function(){e(t)}),0)}),this},e.prototype.disable=function(){if(this.on=!1,this.shim){var e=this.shim,t=e.override,n=e["native"];this.target[this.propertyName]===t&&(this.target[this.propertyName]=n,this.shim=void 0)}},e.prototype.enable=function(){if(this.on=!0,this.shim)return!0;this.shim=this.makeShim();try{this.target[this.propertyName]=this.shim.override}catch(e){return!1}return!0},e.prototype.makeShim=function(){var e=this,t=this.target[this.propertyName];return{"native":t,override:function(){var n={that:this,args:arguments,result:null};e.on&&e._before(n);var r=t.apply(this,arguments);return e.on&&(n.result=r,e._afterSync(n),e._afterAsync(n)),r}}},e}(),Et={};function Tt(e,t){if(!e||"function"!=typeof e[t])return null;var n;Et[t]=Et[t]||[];for(var r=0;r\n";var n=[];try{for(var r=arguments.callee.caller.caller;r&&n.lengthn)return!1;var r=new Error("Assertion failed: "+t);return Mt.sendToBugsnag(r,"error"),e}function Pt(e,t,n,r){void 0!==n&&("function"==typeof e.addEventListener?e.addEventListener(t,n,r):"function"==typeof e.addListener?e.addListener(n):o("Target of "+t+" doesn't seem to support listeners"))}function qt(e,t,n,r){void 0!==n&&("function"==typeof e.removeEventListener?e.removeEventListener(t,n,r):"function"==typeof e.removeListener?e.removeListener(n):o("Target of "+t+" doesn't seem to support listeners"))}var Ut=function(){function e(){var e=this;this._listeners=[],this._children=[],this._yesCapture=!0,this._noCapture=!1;try{var t=Object.defineProperty({},"passive",{get:function(){e._yesCapture={capture:!0,passive:!0},e._noCapture={capture:!1,passive:!0}}});window.addEventListener("test",oe,t)}catch(e){}}return e.prototype.add=function(e,t,n,r,i){return void 0===i&&(i=!1),this.addCustom(e,t,n,r,i)},e.prototype.addCustom=function(e,t,n,r,i){void 0===i&&(i=!1);var o={target:e,type:t,fn:Mt.wrap(function(e){(i||!1!==e.isTrusted||"message"==t||e._fs_trust_event)&&r(e)}),options:n?this._yesCapture:this._noCapture,index:this._listeners.length};return this._listeners.push(o),Pt(e,t,o.fn,o.options),o},e.prototype.remove=function(e){e.target&&(qt(e.target,e.type,e.fn,e.options),e.target=null,e.fn=void 0)},e.prototype.clear=function(){for(var e=0;e0&&t.height>0)return this.width=t.width,void(this.height=t.height);r=this.computeLayoutViewportSizeFromMediaQueries(e),this.width=r[0],this.height=r[1]}}return e.prototype.computeLayoutViewportSizeFromMediaQueries=function(e){var t=this.findMediaValue(e,"width",this.clientWidth,this.clientWidth+128);void 0===t&&(t=this.tryToGet(e,"innerWidth")),void 0===t&&(t=this.clientWidth);var n=this.findMediaValue(e,"height",this.clientHeight,this.clientHeight+128);return void 0===n&&(n=this.tryToGet(e,"innerHeight")),void 0===n&&(n=this.clientHeight),[t,n]},e.prototype.findMediaValue=function(e,t,n,r){if(s.matchMedia){var i=s.matchMedia(e,"(min-"+t+": "+n+"px)");if(null!=i){if(i.matches&&s.matchMedia(e,"(max-"+t+": "+n+"px)").matches)return n;for(;n<=r;){var o=s.mathFloor((n+r)/2);if(s.matchMedia(e,"(min-"+t+": "+o+"px)").matches){if(s.matchMedia(e,"(max-"+t+": "+o+"px)").matches)return o;n=o+1}else r=o-1}}}},e.prototype.tryToGet=function(e,t){try{return e[t]}catch(e){return}},e}();function Yt(e,t){return new zt(e,t)}var Gt=function(e,t){this.offsetLeft=0,this.offsetTop=0,this.pageLeft=0,this.pageTop=0,this.width=0,this.height=0,this.scale=0;var n=e.document;if(n.body){var r="BackCompat"==n.compatMode;"pageXOffset"in e?(this.pageLeft=e.pageXOffset,this.pageTop=e.pageYOffset):n.scrollingElement?(this.pageLeft=n.scrollingElement.scrollLeft,this.pageTop=n.scrollingElement.scrollTop):r?(this.pageLeft=n.body.scrollLeft,this.pageTop=n.body.scrollTop):n.documentElement&&(n.documentElement.scrollLeft>0||n.documentElement.scrollTop>0)?(this.pageLeft=n.documentElement.scrollLeft,this.pageTop=n.documentElement.scrollTop):(this.pageLeft=n.body.scrollLeft||0,this.pageTop=n.body.scrollTop||0),this.offsetLeft=this.pageLeft-t.pageLeft,this.offsetTop=this.pageTop-t.pageTop;try{var i=e.innerWidth,o=e.innerHeight}catch(e){return}if(0!=i&&0!=o){this.scale=t.width/i,this.scale<1&&(this.scale=1);var s=t.width-t.clientWidth,a=t.height-t.clientHeight;this.width=i-s/this.scale,this.height=o-a/this.scale}}};var Qt,Xt=(Qt=function(e,t){return(Qt=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)},function(e,t){function n(){this.constructor=e}Qt(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}),Jt=function(e,t,n,r){return new(n||(n=Promise))(function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r["throw"](e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(s,a)}u((r=r.apply(e,t||[])).next())})},$t=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),"throw":a(1),"return":a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r["return"]:o[0]?r["throw"]||((i=r["return"])&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=(i=s.trys).length>0&&i[i.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]this._due)return et.resolve().then(this._wrappedTick)["catch"](function(){})},e.registry={},e.nextId=0,e.checkedAlready=!1,e.lastCheck=0,e}(),en=function(e){function t(t){var n=e.call(this)||this;return n._interval=t,n._handle=-1,n}return Xt(t,e),t.prototype.start=function(e){var t=this;-1==this._handle&&(this.setTick(function(){e(),t.register(t._interval)}),this._handle=s.setWindowInterval(window,this._wrappedTick,this._interval),this.register(this._interval))},t.prototype.cancel=function(){-1!=this._handle&&(s.clearWindowInterval(window,this._handle),this._handle=-1,this.setTick(function(){}))},t}(Zt),tn=function(e){function t(t,n,r){void 0===n&&(n=0);for(var i=[],o=3;ot&&(this._skew=e-t,this._reportTimeSkew("timekeeper set with future ts"))},e.prototype._reportTimeSkew=function(e){this._reported++<=2&&Mt.sendToBugsnag(e,"error",{skew:this._skew,startTime:this._startTime,wallTime:this.wallTime()})},e}();function on(e){var t=e;return t.tagName?"object"==typeof t.tagName?"form":t.tagName.toLowerCase():null}var sn,an,un=n(3),cn=n(0),hn=Object.defineProperty,dn=p()%1e9,ln=window.WeakMap||((sn=function(){this.name="__st"+(1e9*s.mathRandom()>>>0)+dn++ +"__"}).prototype={set:function(e,t){var n=e[this.name];n&&n[0]===e?n[1]=t:hn(e,this.name,{value:[e,t],writable:!0})},get:function(e){var t;return(t=e[this.name])&&t[0]===e?t[1]:void 0}},sn),pn=1,fn=4,vn=function(){for(var e=0,t=0,n=arguments.length;t0&&o(n[u],this._rules[u]),r[u].length>0&&o(r[u],this._consentRules[u])}},e.prototype._fallback=function(e){for(var t=0,n=e;t0&&t.length<1e4;){var n=t.pop();delete Tn[n.id],n.node._fs==n.id&&(n.node._fs=0),n.id=0,n.next&&t.push(n.next),n.child&&t.push(n.child)}Ft(t.length<1e4,"clearIds is fast")}var qn,Un=function(){function e(e,t){this._onchange=e,this._checkElem=t,this._fallback=!1,this._elems={},this.values={},this.radios={},qn=this}return e.prototype.hookEvents=function(){(function(){var e=Object.getOwnPropertyDescriptor(HTMLInputElement.prototype,"value");if(!e||!e.set)return!1;Nn||(kt(HTMLInputElement,"value",jn),kt(HTMLInputElement,"checked",jn),kt(HTMLSelectElement,"value",jn),kt(HTMLTextAreaElement,"value",jn),kt(HTMLSelectElement,"selectedIndex",jn),kt(HTMLOptionElement,"selected",jn),Nn=!0);return!0})()||(this._fallback=!0)},e.prototype.addInput=function(e){var t=Mn(e);if(this._elems[t]=e,Vn(e)){var n=Hn(e);e.checked&&(this.radios[n]=t)}else this.values[t]=Kn(e);(function(e){switch(e.type){case"checkbox":case"radio":return e.checked!=e.hasAttribute("checked");default:return(e.value||"")!=function(e){if("select"!=on(e))return e.getAttribute("value")||"";var t=e,n=t.querySelector("option[selected]")||t.querySelector("option");if(!n)return"";return n.value||""}(e);}})(e)&&this._onchange(e)},e.prototype.diffValue=function(e,t){var n=Mn(e);if(Vn(e)){var r=Hn(e);return this.radios[r]==n!=("true"==t)}return this.values[n]!=t},e.prototype.onChange=function(e,t){void 0===t&&(t=Kn(e));var n=Mn(e);if((e=this._elems[n])&&this.diffValue(e,t))if(this._onchange(e),Vn(e)){var r=Hn(e);"false"==t&&this.radios[r]==n?delete this.radios[r]:this.radios[r]=n}else this.values[n]=t},e.prototype.tick=function(){for(var e in this._elems){var t=this._elems[e];if(this._checkElem(t)){if(this._fallback){var n=Kn(t);if(t&&this.diffValue(t,n))if(this._onchange(t),Vn(t)){var r=Hn(t);this.radios[r]=+e}else this.values[e]=n}}else delete this._elems[e],delete this.values[e],Vn(t)&&delete this.radios[Hn(t)]}},e.prototype.shutdown=function(){qn=null},e.prototype._usingFallback=function(){return this._fallback},e.prototype._trackingElem=function(e){return!!this._elems[e]},e}(),Nn=!1;var Wn,Dn={};function Bn(){try{if(qn)for(var e in Dn){var t=Dn[e],n=t[0],r=t[1];qn.onChange(n,r)}}finally{Wn=null,Dn={}}}function Hn(e){if(!e)return"";for(var t=e;t&&"form"!=on(t);)t=t.parentElement;return(t&&"form"==on(t)?Mn(t):0)+":"+e.name}function jn(e,t){var n=function e(t,n){if(void 0===n&&(n=2),n<=0)return t;var r=on(t);return"option"!=r&&"optgroup"!=r||!t.parentElement?t:e(t.parentElement,n-1)}(e),r=Mn(n);r&&qn&&qn.diffValue(n,""+t)&&(Dn[r]=[n,""+t],Wn||(Wn=new tn(Bn)).start())}function Kn(e){switch(e.type){case"checkbox":case"radio":return""+e.checked;default:var t=e.value;return t||(t=""),""+t;}}function Vn(e){return e&&"radio"==e.type}var zn={};var Yn="__default";function Gn(e){void 0===e&&(e=Yn);var t=zn[e];return t||(t=function(){var e=document.implementation.createHTMLDocument("");return e.head||e.documentElement.appendChild(e.createElement("head")),e.body||e.documentElement.appendChild(e.createElement("body")),e}(),e!==Yn&&(t.open(),t.write(e),t.close()),zn[e]=t),t}var Qn=new(function(){function e(){var e=Gn(),t=e.getElementById("urlresolver-base");t||((t=e.createElement("base")).id="urlresolver-base",e.head.appendChild(t));var n=e.getElementById("urlresolver-parser");n||((n=e.createElement("a")).id="urlresolver-parser",e.head.appendChild(n)),this.base=t,this.parser=n}return e.prototype.parseUrl=function(e,t){if("undefined"!=typeof URL)try{e||(e=document.baseURI);var n=e?new URL(t,e):new URL(t);if(n.href)return n}catch(e){}return this.parseUrlUsingBaseAndAnchor(e,t)},e.prototype.parseUrlUsingBaseAndAnchor=function(e,t){this.base.setAttribute("href",e),this.parser.setAttribute("href",t);var n=document.createElement("a");return n.href=this.parser.href,n},e.prototype.resolveUrl=function(e,t){return this.parseUrl(e,t).href},e.prototype.resolveToDocument=function(e,t){var n=Jn(e);return null==n?t:this.resolveUrl(n,t)},e}());function Xn(e,t){return Qn.parseUrl(e,t)}function Jn(e){var t=e.document,n=e.location.href;if("string"==typeof t.baseURI)n=t.baseURI;else{var r=t.getElementsByTagName("base")[0];r&&r.href&&(n=r.href)}return"about:blank"==n&&e.parent!=e?Jn(e.parent):n}var $n=new RegExp("[^\\s]"),Zn=new RegExp("[\\s]*$");String.prototype;function er(e){var t=$n.exec(e);if(!t)return e;for(var n=t.index,r=(t=Zn.exec(e))?e.length-t.index:0,i="\uFFFF",o=e.slice(n,e.length-r).split(/\r\n?|\n/g),s=0;sir?(Mt.sendToBugsnag("Ignoring huge text node","warning",{length:r}),""):e.parentNode&&"style"==on(e.parentNode)?n:t.mask?er(n):n}function sr(e){return tr[e]||e.toLowerCase()}function ar(e,t,n,r){var i,o=on(t);if(null===o)return null;var s=function(e){var t,r,s;i=null!==(r=null===(t=nr[e][o])||void 0===t?void 0:t[n])&&void 0!==r?r:null===(s=nr[e]["*"])||void 0===s?void 0:s[n]};if(s("Any"),void 0===i){var a=xn(t);if(!a)return null;a.watchKind==an.Exclude?s("Exclude"):a.mask&&s("Mask")}if(void 0===i)return r;switch(i){case"erase":return null;case"scrubUrl":return ur(r,e,{source:"dom",type:o});case"maskText":return er(r);default:return Object(cn.assertExhaustive)(i);}}function ur(e,t,n){switch(n.source){case"dom":switch(r=n.type){case"frame":case"iframe":return hr(e,t);default:return cr(e,t);}case"event":switch(r=n.type){case R.AJAX_REQUEST:case R.NAVIGATE:return cr(e,t);case R.SET_FRAME_BASE:return hr(e,t);default:return Object(cn.assertExhaustive)(r);}case"log":return hr(e,t);case"page":var r;switch(r=n.type){case"base":return hr(e,t);case"referrer":case"url":return cr(e,t);default:return Object(cn.assertExhaustive)(r);}case"perfEntry":switch(n.type){case"frame":case"iframe":case"navigation":case"other":return hr(e,t);default:return cr(e,t);}default:return Object(cn.assertExhaustive)(n);}}function cr(e,t){return lr(e,t,function(e){if(!(e in pr)){var t=["password","token","^jwt$"];switch("4K3FQ"!==e&&"NQ829"!==e&&"KCF98"!==e&&t.push("^code$"),e){case"2FVM4":t.push("^e$","^eref$","^fn$");break;case"35500":t.push("share_token","password-reset-key");break;case"1HWDJ":t.push("email_id","invite","join");break;case"J82WF":t=[".*"];break;case"8MM83":t=["^creditCard"];break;case"PAN8Z":t.push("code","hash","ol","aeh");break;case"BKP05":t.push("api_key","session_id","encryption_key");break;case"QKM7G":t.push("postcode","encryptedQuoteId","registrationId","productNumber","customerName","agentId","qqQuoteId");break;case"FP60X":t.push("phrase");break;case"GDWG7":t=["^(?!productType|utmSource).*$"];break;case"RV68C":t.push("drivingLicense");break;case"S3VEC":t.push("data");break;case"Q8RZE":t.push("myLowesCardNumber");}pr[e]=new RegExp(t.join("|"),"i")}return pr[e]}(t))}function hr(e,t){return lr(e,t,fr)}function dr(e,t,n,r){var i=new RegExp("(\\/"+t+"\\/).*$","i");n==r&&e.pathname.indexOf(t)>=0&&(e.pathname=e.pathname.replace(i,"$1"+rr))}function lr(e,t,n){var r=Xn("",e);return r.hash&&r.hash.indexOf("access_token")>=0&&(r.hash="#"+rr),dr(r,"visitor",t,"QS8RG"),dr(r,"account",t,"QS8RG"),dr(r,"parentAccount",t,"QS8RG"),dr(r,"reset_password",t,"AGQFM"),dr(r,"reset-password",t,"95NJ7"),dr(r,"dl",t,"RV68C"),dr(r,"retailer",t,"FP60X"),dr(r,"ocadotech",t,"FP60X"),dr(r,"serviceAccounts",t,"FP60X"),dr(r,"signup",t,"7R98D"),r.search&&r.search.length>0&&(r.search=function(e,t){return e.split("?").map(function(e){return function(e,t){return e.replace("?","").split("&").map(function(e){return e.split("=")}).map(function(e){var n=e[0],r=e[1],i=e.slice(2);return t.test(n)&&void 0!==r?[n,rr].concat(i):[n,r].concat(i)}).map(function(e){var t=e[0],n=e[1],r=e.slice(2);return void 0===n?t:[t,n].concat(r).join("=")}).join("&")}(e,t)}).join("?")}(r.search,n)),r.href.substring(0,2048)}var pr={};var fr=new RegExp(".*","i");var vr=/([a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)/gi,_r=/(?:(http)|(ftp)|(file))[s]?:\/\/(?:[a-zA-Z]|[0-9]|[$-_@.&+#]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+/gi;function gr(e){return"function"==typeof(t=e.constructor)&&Function.prototype.toString.call(t).indexOf("[native code]")>-1;var t}var mr=function(){function e(e,t,n){this._watcher=e,this._resizer=t,this._orgId=n,Tn={},kn=1}return e.prototype.tokenizeNode=function(e,t,n,r,i,o,s){var a=this,u=xn(t),c=xn(n),h=[];return function(e){var t=kn;try{return e(),!0}catch(e){return kn=t,!1}}(function(){a.tokeNode(e,u,c,r,h,i,o,s)})||(h=[]),h},e.prototype.tokeNode=function(e,t,n,r,i,o,s,a){for(var u=[{parentMirror:t,nextMirror:n,node:r}],c=function(){var t=u.pop();if(!t)return"continue";if("string"==typeof t)return i.push(t),"continue";var n=t.parentMirror,r=t.nextMirror,c=t.node,d=h._encodeTagAndAttributes(e,n,r,c,i,o,s);if(null==d||d.watchKind===an.Exclude)return"continue";var l=c.nodeType===pn?c.shadowRoot:null;return(l||c.firstChild)&&a(d)?(u.push("]"),function(e,t){if(!e)return;var n=[];ft(e,function(e){return n.push(e)});for(;n.length>0;){var r=n.pop();r&&t(r)}}(c.firstChild,function(e){u.push({parentMirror:d,nextMirror:null,node:e})}),l&&u.push({parentMirror:d,nextMirror:null,node:l}),void u.push("[")):"continue"},h=this;u.length;)c()},e.prototype._encodeTagAndAttributes=function(e,t,n,r,i,o,s){if("script"==on(r)||8==r.nodeType)return null;var a,u,c,h,d=function(e){return e.constructor===window.ShadowRoot}(r),l=function(e){var t={id:kn++,node:e};return Tn[t.id]=t,e._fs=t.id,t}(r);if((d||(null==t?void 0:t.isInShadowDOM))&&(l.isInShadowDOM=!0),t&&(d?t.shadow=l:(a=t,u=l,c=n,h=this._resizer,Fn(u,h),u.parent=a,u.next=c,c&&(u.prev=c.prev,c.prev=u),null==u.next?(u.prev=a.lastChild,a.lastChild=u):u.next.prev=u,null==u.prev?a.child=u:u.prev.next=u)),10==r.nodeType){var p=r;return i.push("1?s.push([o.idx,a]):s.push(o.idx):s.push(i)}for(n=1;n1e3)return null;if(!n||n.nodeType!=pn)return null;var r=n;if(getComputedStyle(r).display.indexOf("inline")<0)return r;n=n.parentNode}},t}(Er),kr=function(e){function t(){return null!==e&&e.apply(this,arguments)||this}return br(t,e),t.prototype.observe=function(e){var t=this;if(e&&e.nodeType==pn){var n=e;this.growWatchedIndex(xn(e)),this._ctx.measurer.requestMeasureTask(function(){t.addEntry(n)})}},t.prototype.unobserveSubtree=function(e){var t=xn(e);t&&this.clearWatchedIndex(t)},t.prototype.nodeChanged=function(e){var t=this,n=this.relatedWatched(e);this._ctx.measurer.requestMeasureTask(function(){for(var e=0,r=n;e0){var r=zr(t[n-1],e);if(r)return void(t[n-1]=r)}else!function(e){qr.push(e),Pr||(Pr=!0,Mr(Ur))}(this.observer);t[n]=e},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(e){var t=this.options;t.attributes&&e.addEventListener("DOMAttrModified",this.handleEventBound,!0),t.characterData&&e.addEventListener("DOMCharacterDataModified",this.handleEventBound,!0),t.childList&&e.addEventListener("DOMNodeInserted",this.handleEventBound,!0),(t.childList||t.subtree)&&e.addEventListener("DOMNodeRemoved",this.handleEventBound,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(e){var t=this.options;t.attributes&&e.removeEventListener("DOMAttrModified",this.handleEventBound,!0),t.characterData&&e.removeEventListener("DOMCharacterDataModified",this.handleEventBound,!0),t.childList&&e.removeEventListener("DOMNodeInserted",this.handleEventBound,!0),(t.childList||t.subtree)&&e.removeEventListener("DOMNodeRemoved",this.handleEventBound,!0)},addTransientObserver:function(e){if(e!==this.target){this.addListeners_(e),this.transientObservedNodes.push(e);var t=Or.get(e);t||Or.set(e,t=[]),t.push(this)}},removeTransientObservers:function(){var e=this.transientObservedNodes;this.transientObservedNodes=[],e.forEach(function(e){this.removeListeners_(e);for(var t=Or.get(e),n=0;n0||this._toRefresh.length>0){var n={},r={};for(var i in this.processRecords(e,t,r,n),r){var o=i.split("\t");t.push({Kind:R.MUT_ATTR,When:e,Args:[parseInt(o[0]),o[1],r[i]]})}for(var i in n)t.push({Kind:R.MUT_TEXT,When:e,Args:[parseInt(i),n[i]]})}var s=this._newShadowContainers;this._newShadowContainers=[];for(var a=0;a0)for(var d=0;d0){s[h]=c.target;var p=Jr(c.target);p&&(s[p.id]=p.node)}break;case"characterData":Cn(c.target)||c.oldValue!=c.target.textContent&&(r[h]=or(c.target));break;case"attributes":var f=An(w=c.target);if(_n(this._watcher.isWatched(w))>_n(f)){a(w);break}var v=Xr(c.attributeNamespace)+(c.attributeName||""),_=sr(v);if(w.hasAttribute(v)){var g=c.target.getAttribute(v);c.oldValue!=g&&(g=ar(this._ctx.options.orgId,c.target,_,g||""),this._attrVisitor(c.target,_,g||""),null!==g&&(n[h+"\t"+_]=g))}else n[h+"\t"+_]=null;}}catch(e){}for(var m=0,y=this._toRefresh;m0&&n.push({When:t,Kind:R.MUT_SHADOW,Args:[o,this._compress?this._lz.encode(s):s]})},e.prototype.genInsert=function(e,t,n,r,i,o){var s=Mn(r)||-1,a=Mn(o)||-1,u=-1===s&&-1===a,c=p(),h=this.genDocStream(e,r,i,o),d=p()-c;if(h.length>0){var l=p(),f=this._compress?this._lz.encode(h):h,v=p()-l;n.push({When:t,Kind:R.MUT_INSERT,Args:[s,a,f]},{When:t,Kind:R.TIMING,Args:[[O.Internal,A.Serialization,u?x.DomSnapshot:x.NodeEncoding,t,d,[x.LzEncoding,v]]]})}},e.prototype.genDocStream=function(e,t,n,r){var i=this;if(t&&Cn(t))return[];for(var o=[],s=this._encoder.tokenizeNode(e,t,r,n,function(e){if(e.nodeType==pn){var t=e;t.shadowRoot&&i.observe(t.shadowRoot)}i._nodeVisitor(e,o)},this._attrVisitor,this._visitChildren),a=0,u=o;a0){var i=t[t.length-1];if(i.Kind==R.MUT_REMOVE)return void i.Args.push(r)}t.push({When:e,Kind:R.MUT_REMOVE,Args:[r]})},e.prototype.setUpIEWorkarounds=function(){var t=this;if(ue){var n=Object.getOwnPropertyDescriptor(Node.prototype,"textContent"),r=n&&n.set;if(!n||!r)throw new Error("Missing textContent setter -- not safe to record mutations.");Object.defineProperty(Element.prototype,"textContent",Gr(Gr({},n),{set:function(e){try{for(var t=void 0;t=this.firstChild;)this.removeChild(t);if(null===e||""==e)return;var n=(this.ownerDocument||document).createTextNode(e);this.appendChild(n)}catch(t){r&&r.call(this,e)}}}))}this._setPropertyThrottle=new nn(e.ThrottleMax,e.ThrottleInterval,function(){return new tn(function(){t._setPropertyWasThrottled=!0,t.tearDownIEWorkarounds()}).start()});var i=this._setPropertyThrottle.guard(function(e){e.cssText=e.cssText});this._setPropertyThrottle.open(),this._setPropertyHook=Tt(CSSStyleDeclaration.prototype,"setProperty"),this._setPropertyHook&&this._setPropertyHook.afterSync(function(e){i(e.that)}),this._removePropertyHook=Tt(CSSStyleDeclaration.prototype,"removeProperty"),this._removePropertyHook&&this._removePropertyHook.afterSync(function(e){i(e.that)})},e.prototype.tearDownIEWorkarounds=function(){this._setPropertyThrottle&&this._setPropertyThrottle.close(),this._setPropertyHook&&this._setPropertyHook.disable(),this._removePropertyHook&&this._removePropertyHook.disable()},e.prototype.updateConsent=function(){var e=this,t=xn(this._root);t&&function(e,t){for(var n=[e];n.length;){var r=n.pop();if(r){t(r);for(var i=r.child,o=r.shadow;i;)n.push(i),i=i.next;o&&n.push(o)}}}(t,function(t){var n=t.node;t.matchesAnyConsentRule&&e.refreshElement(n)})},e.prototype.refreshElement=function(e){Mn(e)&&this._toRefresh.push(e)},e.ThrottleMax=1024,e.ThrottleInterval=1e4,e}();function Xr(e){return void 0===e&&(e=""),null===e?"":{"http://www.w3.org/1999/xlink":"xlink:","http://www.w3.org/XML/1998/namespace":"xml:","http://www.w3.org/2000/xmlns/":"xmlns:"}[e]||""}function Jr(e){return!(null==e?void 0:e.shadowRoot)||gr(e.shadowRoot)?null:xn(e.shadowRoot)}var $r=["navigationStart","unloadEventStart","unloadEventEnd","redirectStart","redirectEnd","fetchStart","domainLookupStart","domainLookupEnd","connectStart","connectEnd","secureConnectionStart","requestStart","responseStart","responseEnd","domLoading","domInteractive","domContentLoadedEventStart","domContentLoadedEventEnd","domComplete","loadEventStart","loadEventEnd"],Zr=["name","startTime","duration","initiatorType","redirectStart","redirectEnd","fetchStart","domainLookupStart","domainLookupEnd","connectStart","connectEnd","secureConnectionStart","requestStart","responseStart","responseEnd","unloadEventStart","unloadEventEnd","domInteractive","domContentLoadedEventStart","domContentLoadedEventEnd","domComplete","loadEventStart","loadEventEnd","type","redirectCount","decodedBodySize","encodedBodySize","transferSize"],ei=["name","startTime","duration","initiatorType","redirectStart","redirectEnd","fetchStart","domainLookupStart","domainLookupEnd","connectStart","connectEnd","secureConnectionStart","requestStart","responseStart","responseEnd","decodedBodySize","encodedBodySize","transferSize"],ti=["name","startTime","duration"],ni=["jsHeapSizeLimit","totalJSHeapSize","usedJSHeapSize"],ri=function(){function e(e,t,n){this._ctx=e,this._queue=t,this._perfSupported=!1,this._timingSupported=!1,this._getEntriesSupported=!1,this._memorySupported=!1,this._lastUsedJSHeapSize=0,this._gotLoad=!1,this._observer=null,this._observedBatches=[];var r=window.performance;r&&(this._perfSupported=!0,r.timing&&(this._timingSupported=!0),r.memory&&(this._memorySupported=!0),"function"==typeof r.getEntries&&(this._getEntriesSupported=!0),this._listeners=n.createChild())}return e.prototype.start=function(e){var t=this;this._resourceUploader=e;var n=window.performance;n&&(this._ctx.recording.inFrame||this._queue.enqueue({Kind:R.REC_FEAT_SUPPORTED,Args:[Y.Performance,this._timingSupported,Y.PerformanceEntries,this._getEntriesSupported,Y.PerformanceMemory,this._memorySupported,Y.PerformanceObserver,!!window.PerformanceObserver]}),this.observe(),!this._observer&&n.addEventListener&&n.removeEventListener&&this._listeners.add(n,"resourcetimingbufferfull",!0,function(){t._queue.enqueue({Kind:R.RESOURCE_TIMING_BUFFER_FULL,Args:[]})}),this.checkMemory())},e.prototype.onLoad=function(){this._gotLoad||(this._gotLoad=!0,this._timingSupported&&(this.recordTiming(performance.timing),this.checkForNewEntries()))},e.prototype.tick=function(e){this.checkMemory(),e&&this.checkForNewEntries()},e.prototype.shutdown=function(){this._listeners&&this._listeners.clear(),this._resourceUploader=void 0;var e=[];this._observer?(this._observer.takeRecords&&(e=this._observer.takeRecords()),this._observer.disconnect()):window.performance&&window.performance.getEntries&&(e=window.performance.getEntries()),e.length>300&&(e=e.slice(0,300),this._queue.enqueue({Kind:R.RESOURCE_TIMING_BUFFER_FULL,Args:[]})),this._observedBatches.push(e),this.tick(!0)},e.prototype.observe=function(){var e=this;if(!this._observer&&this._getEntriesSupported&&window.PerformanceObserver){this._observedBatches.push(performance.getEntries()),this._observer=new window.PerformanceObserver(function(t){var n=t.getEntries();e._observedBatches.push(n)});var t=["navigation","resource","measure","mark"];window.PerformancePaintTiming&&t.push("paint"),this._observer.observe({entryTypes:t})}},e.prototype.checkMemory=function(){if(this._memorySupported&&!this._ctx.recording.inFrame){var e=performance.memory;if(e){var t=e.usedJSHeapSize-this._lastUsedJSHeapSize;(0==this._lastUsedJSHeapSize||s.mathAbs(t/this._lastUsedJSHeapSize)>.2)&&(this.addPerfEvent(z.Memory,e,ni),this._lastUsedJSHeapSize=e.usedJSHeapSize)}}},e.prototype.recordEntry=function(e){switch(e.entryType){case"navigation":this.recordNavigation(e);break;case"resource":this.recordResource(e);break;case"paint":this.recordPaint(e);break;case"measure":this.recordMeasure(e);break;case"mark":this.recordMark(e);}},e.prototype.checkForNewEntries=function(){if(this._perfSupported&&this._getEntriesSupported){var e=this._observedBatches;this._observedBatches=[];for(var t=0,n=e;t=t&&(n=void 0),o[o.length-1]--,n&&n!==si&&r&&(o.push(s.objectKeys(n).length),a.push(u));o[o.length-1]<=0;)o.pop(),a.pop();return n})}catch(e){}return"[error serializing "+e.constructor.name+"]"}}var ui=function(){function e(e){this._requestTracker=e}return e.prototype.disable=function(){this._hook&&(this._hook.disable(),this._hook=null)},e.prototype.enable=function(e){var t,n=this,r=I(e),i=null===(t=null==r?void 0:r._w)||void 0===t?void 0:t.fetch;(i||e.fetch)&&(this._hook=Tt(i?r._w:e,"fetch"),this._hook&&this._hook.afterSync(function(e){return n.recordFetch(e.that,e.result,e.args[0],e.args[1])}))},e.prototype.recordFetch=function(e,t,n,r){var i,o="GET",s="",a={};if("string"==typeof n?s=n:"url"in n?(s=n.url,o=n.method,i=n.body,n.headers&&n.headers.forEach(function(e,t){a[e]=t})):s=""+n,r){o=r.method||o;var u=r.headers;if(u)if(nt(u))for(var c=0,h=u;c-1;n&&o?t.clone().text().then(Mt.wrap(function(i){var o=mi(i,n),s=o[0],a=o[1];r.onComplete(e,t,s,a)}))["catch"](Mt.wrap(function(n){r.onComplete(e,t,-1,void 0)})):r.onComplete(e,t,-1,void 0)}))["catch"](Mt.wrap(function(t){r.onComplete(e,t,-1,void 0)}))},e.prototype.onComplete=function(e,t,n,r){var i=this,o=-1,s="";if("headers"in t){o=t.status;s=this.serializeFetchHeaders(t.headers,function(e){return i._requestTracker.isHeaderInResponseHeaderWhitelist(e[0])})}return this._requestTracker.onComplete(e,s,o,n,r)},e.prototype.serializeFetchHeaders=function(e,t){var n="";return e.forEach(function(e,r){r=r.toLowerCase();var i=t([r,e]);n+=r+(i?": "+e:"")+di}),n},e}(),ci=function(){function e(e){this._requestTracker=e}return e.prototype.disable=function(){this._xhrOpenHook&&(this._xhrOpenHook.disable(),this._xhrOpenHook=null),this._xhrSetHeaderHook&&(this._xhrSetHeaderHook.disable(),this._xhrSetHeaderHook=null)},e.prototype.enable=function(e){var t,n=this,r=I(e),i=(null===(t=null==r?void 0:r._w)||void 0===t?void 0:t.XMLHttpRequest)||e.XMLHttpRequest;if(i){var o=i.prototype;this._xhrOpenHook=Tt(o,"open"),this._xhrOpenHook&&this._xhrOpenHook.before(function(e){var t=e.args[0],r=e.args[1];n._requestTracker.addPendingReq(e.that,t,r),e.that.addEventListener("load",Mt.wrap(function(t){n.onComplete(e.that)})),e.that.addEventListener("error",Mt.wrap(function(t){n.onComplete(e.that)}))}),this._xhrSendHook=Tt(o,"send"),this._xhrSendHook&&this._xhrSendHook.before(function(e){var t=e.args[0];n._requestTracker.addRequestBody(e.that,t)}),this._xhrSetHeaderHook=Tt(o,"setRequestHeader"),this._xhrSetHeaderHook&&this._xhrSetHeaderHook.before(function(e){var t=e.args[0],r=e.args[1];n._requestTracker.addHeader(e.that,t,r)})}},e.prototype.onComplete=function(e){var t=this,n=this.responseBody(e),r=n[0],i=n[1],o=Ei(function(e){var t=[];return e.split(di).forEach(function(e){var n=e.indexOf(":");-1!=n?t.push([e.slice(0,n).trim(),e.slice(n+1,e.length).trim()]):t.push([e.trim(),null])}),t}(e.getAllResponseHeaders()),function(e){return t._requestTracker.isHeaderInResponseHeaderWhitelist(e[0])});return this._requestTracker.onComplete(e,o,e.status,r,i)},e.prototype.responseBody=function(e){var t=this._requestTracker.pendingReq(e);if(!t)return[-1,void 0];var n=this._requestTracker.getRspWhitelist(t.url);if(e.responseType){var r=e.response;switch(r||o("Maybe response type was different that expected."),e.responseType){case"text":return mi(e.responseText,n);case"json":return function(e,t){if(!e)return[-1,void 0];return[yi(e),ai(e,te.MaxPayloadLength,t)]}(r,n);case"arraybuffer":return function(e,t){return[e?e.byteLength:-1,t?"[ArrayBuffer]":void 0]}(r,n);case"blob":return function(e,t){return[e?e.size:-1,t?"[Blob]":void 0]}(r,n);case"document":return function(e,t){return[-1,t?"[Document]":void 0]}(0,n);}}return mi(e.responseText,n)},e}();var hi,di="\r\n",li=["a-im","accept","accept-charset","accept-encoding","accept-language","accept-datetime","access-control-request-method,","access-control-request-headers","cache-control","connection","content-length","content-md5","content-type","date","expect","forwarded","from","host","if-match","if-modified-since","if-none-match","if-range","if-unmodified-since","max-forwards","origin","pragma","range","referer","te","user-agent","upgrade","via","warning"],pi=["access-control-allow-origin","access-control-allow-credentials","access-control-expose-headers","access-control-max-age","access-control-allow-methods","access-control-allow-headers","accept-patch","accept-ranges","age","allow","alt-svc","cache-control","connection","content-disposition","content-encoding","content-language","content-length","content-location","content-md5","content-range","content-type","date","delta-base","etag","expires","im","last-modified","link","location","permanent","p3p","pragma","proxy-authenticate","public-key-pins","retry-after","permanent","server","status","strict-transport-security","trailer","transfer-encoding","tk","upgrade","vary","via","warning","www-authenticate","x-frame-options"],fi={BM7A6:["x-b3-traceid"],KD87S:["transactionid"],NHYJM:["x-att-conversationid"],GBNRN:["x-trace-id"],R16RC:["x-request-id"],DE9CX:["x-client","x-client-id","ot-baggage-original-client","x-req-id","x-datadog-trace-id","x-datadog-parent-id","x-datadog-sampling-priority"]},vi={"thefullstory.com":["x-cloud-trace-context"],TN1:["x-cloud-trace-context"],KD87S:["transactionid"],PPE96:["x-b3-traceid"],HWT6H:["x-b3-traceid"],PPEY7:["x-b3-traceid"],PPK3W:["x-b3-traceid"],NHYJM:["x-att-conversationid"],GBNRN:["x-trace-id"],NK5T9:["traceid","requestid"]},_i=function(){function e(e,t){this._ctx=e,this._queue=t,this._enabled=!1,this._tracker=new gi(e,t),this._xhr=new ci(this._tracker),this._fetch=new ui(this._tracker)}return e.prototype.isEnabled=function(){return this._enabled},e.prototype.enable=function(e){this._enabled||(this._enabled=!0,this._queue.enqueue({Kind:R.REC_FEAT_SUPPORTED,Args:[Y.Ajax,!0,Y.AjaxFetch,!!e]}),this._xhr.enable(this._ctx.window),e&&this._fetch.enable(this._ctx.window))},e.prototype.disable=function(){this._enabled&&(this._enabled=!1,this._xhr.disable(),this._fetch.disable())},e.prototype.tick=function(e){this._tracker.tick(e)},e.prototype.setWatches=function(e){this._tracker.setWatches(e)},e}(),gi=function(){function e(e,t){this._ctx=e,this._queue=t,this._reqHeaderWhitelist={},this._rspHeaderWhitelist={},this._pendingReqs={},this._events=[],this._curId=1,this.addHeaderWhitelist(li,pi),this.addHeaderWhitelist(fi[e.options.orgId],vi[e.options.orgId])}return e.prototype.getReqWhitelist=function(e){var t=this.findWhitelistIndexFor(e);return t>=0&&this._reqWhitelist[t]},e.prototype.getRspWhitelist=function(e){var t=this.findWhitelistIndexFor(e);return t>=0&&this._rspWhitelist[t]},e.prototype.isHeaderInRequestHeaderWhitelist=function(e){return e in this._reqHeaderWhitelist},e.prototype.isHeaderInResponseHeaderWhitelist=function(e){return e in this._rspHeaderWhitelist},e.prototype.pushEvent=function(e){this._events.push(e)},e.prototype.setWatches=function(e){var t=this,n=[];this._reqWhitelist=[],this._rspWhitelist=[],e.forEach(function(e){n.push(e.URLRegex),t._reqWhitelist.push(Si(e.RecordReq,e.ReqWhitelist)),t._rspWhitelist.push(Si(e.RecordRsp,e.RspWhitelist))}),this._reqBodyRegex=new RegExp("("+n.join(")|(")+")")},e.prototype.addHeaderWhitelist=function(e,t){var n=this;e&&e.forEach(function(e){return n._reqHeaderWhitelist[e]=!0}),t&&t.forEach(function(e){return n._rspHeaderWhitelist[e]=!0})},e.prototype.tick=function(e){if(e){for(var t=0;te.MaxRuleBytes&&(o("CSSRule too large, inserting dummy instead: "+n.length),n="dummy {}"),this.withEventQueueForSheet(t,function(e){return e.enqueue({Kind:R.CSSRULE_INSERT,Args:"number"==typeof r?[i,[n],r]:[i,[n]]})}))},e.prototype.addDelete=function(e,t){var n=Fi(e,G.Node);n&&this.withEventQueueForSheet(e,function(e){return e.enqueue({Kind:R.CSSRULE_DELETE,Args:[n,t]})})},e.prototype.onDisableSheet=function(e,t){var n=Fi(e,G.Node);n&&this.withEventQueueForSheet(e,function(e){return e.enqueue({Kind:R.DISABLE_STYLESHEET,Args:[n,!!t]})})},e.prototype.withEventQueueForSheet=function(e,t){if(e.ownerNode)return n=this.ctx,r=e.ownerNode,i=t,void((o=I(Ai(r)||n.window))&&"function"==typeof o._withEventQueue&&o._withEventQueue(n.recording.pageSignature(),function(e){i({enqueue:function(t){Ft(null!=e,Ri)&&e.enqueue(t)},enqueueFirst:function(t){Ft(null!=e,Ri)&&e.enqueueFirst(t)}}),e=null}));var n,r,i,o;t(this.queue)},e.prototype.stop=function(){this.throttle.close();for(var e=0,t=this.hooks;e0&&i[i.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]-1)return[n];if("srcset"==t&&("img"==i||"source"==i)){return null!=n.match(/^\s*$/)?[]:n.split(",").map(function(e){return e.trim().split(/\s+/)[0]})}var o=e;if("style"==t&&o.style){var s=o.style.backgroundImage;if(!s)return[];if(s.length>300)return[];var a=[],u=void 0;for(jt.lastIndex=0;u=jt.exec(s);){var c=u[1];c&&a.push(c.trim())}return a}return[]}(e,t,n);r5e5)){var n=ki(Ti(e));if(n){if(n.length>0&&Li.test(t))return 0;var r,i=Gn();ae?(r=i.createElement("style")).textContent=e.textContent:r=i.importNode(e,!0),i.head.appendChild(r);var o=ki(Ti(r));if(i.head.removeChild(r),o)return n.length>o.length?o.length:void 0}}}(o);void 0!==s&&t.push(function(){n._styleSheetWatcher.snapshotEl(o,s)});break;default:"#"!==e.nodeName[0]&&e.nodeName.indexOf("-")>-1&&this._customElementWatcher.onCustomNodeVisited(e);}if("scrollLeft"in e&&"scrollTop"in e){var a=e;this._ctx.measurer.requestMeasureTask(function(){0==a.scrollLeft&&0==a.scrollTop||n.addScroll(a)})}},e.prototype.isSafePointerEvent=function(e){var t=Ki(e);return!!Mn(t)&&!Cn(t)},e.prototype.addMouseMove=function(e){var t=Mn(Ki(e));this._queue.enqueue({Kind:R.MOUSEMOVE,Args:t?[e.clientX,e.clientY,t]:[e.clientX,e.clientY]})},e.prototype.addMouseDown=function(e){this._queue.enqueue({Kind:R.MOUSEDOWN,Args:[e.clientX,e.clientY]})},e.prototype.addMouseUp=function(e){this._queue.enqueue({Kind:R.MOUSEUP,Args:[e.clientX,e.clientY]})},e.prototype.addTouchEvent=function(e,t){if(void 0!==e.changedTouches)for(var n=0;n0)return n[0]}}return e.target}var Vi=/^\s*at .*(\S+\:\d+|native|())/m,zi=/^(eval@)?(\[native code\])?$/;function Yi(e){if(!e||"string"!=typeof e.stack)return[];var t=e;return t.stack.match(Vi)?t.stack.split("\n").filter(function(e){return!!e.match(Vi)}).map(function(e){e.indexOf("(eval ")>-1&&(e=e.replace(/eval code/g,"eval").replace(/(\(eval at [^\()]*)|(\)\,.*$)/g,""));var t=e.replace(/^\s+/,"").replace(/\(eval code/g,"(").replace(/\(native code\)/,"").split(/\s+/).slice(1),n=Qi(t.pop());return Gi(t.join(" "),["eval",""].indexOf(n[0])>-1?"":n[0],n[1],n[2])}):function(e){return e.split("\n").filter(function(e){return!e.match(zi)}).map(function(e){if(e.indexOf(" > eval")>-1&&(e=e.replace(/ line (\d+)(?: > eval line \d+)* > eval\:\d+\:\d+/g,":$1")),-1===e.indexOf("@")&&-1===e.indexOf(":"))return[e,"",-1,-1];var t=e.split("@"),n=Qi(t.pop());return Gi(t.join("@"),n[0],n[1],n[2])})}(t.stack)}function Gi(e,t,n,r){return[e||"",t||"",parseInt(n||"-1"),parseInt(r||"-1")]}function Qi(e){if(!e||-1===e.indexOf(":"))return["","",""];var t=/(.+?)(?:\:(\d+))?(?:\:(\d+))?$/.exec(e.replace(/[\(\)]/g,""));return t?[t[1]||"",t[2]||"",t[3]||""]:["","",""]}var Xi=function(){for(var e=0,t=0,n=arguments.length;t0&&"string"==typeof e.nodeName}(t)?function(e){return e.toString()}(t):void 0===t?"undefined":"object"!=typeof t||null==t?t:t instanceof Error?t.stack||t.name+": "+t.message:void 0;if(void 0!==o)return void 0===(o=s.jsonStringify(o))?0:("\""==o[0]&&(o=to(o,n,"...\"")),o.length<=n?(i.tokens.push(o),o.length):0);if(i.cyclic){i.opath.splice(r);var a=i.opath.lastIndexOf(t);if(a>-1){var u="";return u="\""+to(u,n-2)+"\"",i.tokens.push(u),u.length}i.opath.push(t)}var c=n,h=function(e){return c>=e.length&&(c-=e.length,i.tokens.push(e),!0)},d=function(e){","==i.tokens[i.tokens.length-1]?i.tokens[i.tokens.length-1]=e:h(e)};if(c<2)return 0;if(nt(t)){h("[");for(var l=0;l0;l++){var p=e(t[l],c-1,r+1,i);if(c-=p,0==p&&!h("null"))break;h(",")}d("]")}else{h("{");var f=Ze(t);for(l=0;l0;l++){var v=f[l],_=t[v];if(!h("\""+v+"\":"))break;if(0==(p=e(_,c-1,r+1,i))){i.tokens.pop();break}c-=p,h(",")}d("}")}return n==1/0?1:n-c}(e,t,0,i);var o=i.tokens.join("");return r?function(e,t){var n=t.replace(vr,"");return n=n.replace(_r,function(t){return ur(t,e,{source:"log",type:"debug"})})}(n,o):o}catch(e){return mt(e)}}function Zi(e,t){var n=0;try{s.jsonStringify(e,function(e,r){if(n++>t)throw"break";if("object"==typeof r)return r})}catch(e){return"break"!=e}return!1}var eo=function(e){return isNaN(e)?"Invalid Date":e.toUTCString()},to=function(e,t,n){return void 0===n&&(n="..."),e.length<=t?e:e.length<=n.length||t<=n.length?e.substring(0,t):e.substring(0,t-n.length)+n};var no=function(){for(var e=0,t=0,n=arguments.length;tthis._curveEndMs&&(this._curveEndMs=e.When),this._evts.push(e)},e.prototype.finish=function(e,t){void 0===t&&(t=[]);var n=this._evts.length;if(n<=1)return!1;for(var r=no([this._curveEndMs],t),i=this._evts[0].When,o=this._evts[n-1].When,s=0;s0?this._lastWhen:this._ctx.time.now();this.enqueueAt(t,e),Zt.checkForBrokenSchedulers()},e.prototype.enqueueAt=function(e,t){if(!this._recordingDisabled){e0){var t=e;t.When=this._eventQueue[0].When,this._eventQueue.unshift(t)}else this.enqueue(e)},e.prototype.addUnload=function(e){this._gotUnload||(this._gotUnload=!0,this.enqueue({Kind:R.UNLOAD,Args:[e]}),this.singSwanSong())},e.prototype.shutdown=function(e){this._flush(),this.addUnload(e),this._flush(),this._recordingDisabled=!0,this.stopPipeline()},e.prototype._flush=function(){this.processEvents(),this._transport.flush()},e.prototype.singSwanSong=function(){this._recordingDisabled||(this.processEvents(),this._transport.singSwanSong())},e.prototype.rebaseIframe=function(e){for(var t=0,n=this._eventQueue.length;t0){var d=h[h.length-1].Args[2];if(d)h[0].Args[9]=d}}for(var l in o){o[p=parseInt(l)].finish(R.SCROLL_LAYOUT_CURVE,[p])}for(var l in s){s[p=parseInt(l)].finish(R.SCROLL_VISUAL_OFFSET_CURVE,[p])}for(var l in i){var p;i[p=parseInt(l)].finish(R.TOUCHMOVE_CURVE,[p])}return t&&t.finish(R.RESIZE_VISUAL_CURVE),n}(t);e||(n=n.concat(this._gatherExternalEvents(0!=n.length))),this.ensureFrameIds(n),0!=n.length&&this._transport.enqueueEvents(this._ctx.recording.pageSignature(),n)}},e.prototype.ensureFrameIds=function(e){if(this._frameId)for(var t=this._parentIds,n=t&&t.length>0,r=0;r>>0).toString(16)).slice(-8);return e},e}();function uo(e){var t=new ao(1);return t.writeAscii(e),t.sumAsHex()}function co(e){var t=new Uint8Array(e);return lo(String.fromCharCode.apply(null,t))}var ho="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";function lo(e){var t;return(null!==(t=window.btoa)&&void 0!==t?t:po)(e).replace(/\+/g,"-").replace(/\//g,"_")}function po(e){for(var t=String(e),n=[],r=0,i=0,o=0,s=ho;t.charAt(0|o)||(s="=",o%1);n.push(s.charAt(63&r>>8-o%1*8))){if((i=t.charCodeAt(o+=.75))>255)throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");r=r<<8|i}return n.join("")}var fo=function(e,t,n,r){return new(n||(n=Promise))(function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r["throw"](e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(s,a)}u((r=r.apply(e,t||[])).next())})},vo=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),"throw":a(1),"return":a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r["return"]:o[0]?r["throw"]||((i=r["return"])&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=(i=s.trys).length>0&&i[i.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]go?[4,t(mo)]:[3,3]:[3,5];case 2:u.sent(),i=e.now(),u.label=3;case 3:a=new Uint8Array(n,s,Math.min(o-s,_o)),r.write(a),u.label=4;case 4:return s+=_o,[3,1];case 5:return[2,{hash:r.sum(),hasher:r}];}})})}var wo=function(e,t,n,r){return new(n||(n=Promise))(function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r["throw"](e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(s,a)}u((r=r.apply(e,t||[])).next())})},bo=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),"throw":a(1),"return":a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r["return"]:o[0]?r["throw"]||((i=r["return"])&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=(i=s.trys).length>0&&i[i.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]So){var i=ur(e,t,{source:"log",type:"bugsnag"});return Mt.sendToBugsnag("Size of blob resource exceeds limit","warning",{url:i,MaxResourceSizeBytes:So}),void r(null)}(function(e){var t=oo(),n=t.resolve,r=t.promise,i=new FileReader;return i.readAsArrayBuffer(e),i.onload=function(){n(i.result)},i.onerror=function(e){Mt.sendToBugsnag(e,"error"),n(null)},r})(n).then(function(e){r(e?{buffer:e,blob:n,contentType:n.type}:null)})},s.send(),i)}function ko(e,t){var n,r;return wo(this,void 0,et,function(){var i;return bo(this,function(o){switch(o.label){case 0:return i=e.window,(null===(r=null===(n=i.crypto)||void 0===n?void 0:n.subtle)||void 0===r?void 0:r.digest)?[4,i.crypto.subtle.digest({name:"sha-1"},t)]:[3,2];case 1:return[2,{hash:co(o.sent()),algorithm:"sha1"}];case 2:return[4,yo(e.time,so,t)];case 3:return[2,{hash:o.sent().hash,algorithm:"fsnv"}];}})})}var Io=function(e,t,n,r){return new(n||(n=Promise))(function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r["throw"](e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(s,a)}u((r=r.apply(e,t||[])).next())})},Co=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),"throw":a(1),"return":a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r["return"]:o[0]?r["throw"]||((i=r["return"])&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=(i=s.trys).length>0&&i[i.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]0&&(this._regexes=this._joinRegexes(t))},e.prototype.matches=function(e){return!!this._regexes&&this._regexes.test(e)},e.prototype._isValidRegex=function(e){try{return new RegExp(e),!0}catch(t){return Mt.sendToBugsnag("Browser rejected UrlKeep.Regex","error",{expr:e,error:t.toString()}),!1}},e.prototype._joinRegexes=function(e){try{return new RegExp("("+e.join(")|(")+")","i")}catch(t){return Mt.sendToBugsnag("Browser rejected joining UrlKeep.Regexs","error",{exprs:e,error:t.toString()}),null}},e}();function Po(e,t){var n=Mn(e)+" ";return e.id&&(n+="#"+e.id),n+="[src="+ur(e.src,t,{source:"log",type:"debug"})+"]"}var qo,Uo=function(e){var t=e.transport,n=e.frame,r=e.orgId,s=e.scheme,a=e.script,u=e.recHost,c=e.appHost,h=Po(n,r);o("Injecting into Frame "+h);try{if(function(e){return e.id==e.name&&No.test(e.id)}(n))return void o("Blacklisted iframe: "+h);if(function(e){if(!e.contentDocument||!e.contentWindow||!e.contentWindow.location)return!0;return function(e){return!!e.src&&"about:blank"!=e.src&&e.src.indexOf("javascript:")<0}(e)&&e.src!=e.contentWindow.location.href&&"loading"==e.contentDocument.readyState}(n))return void o("Frame not yet loaded: "+h);var d=n.contentWindow,l=n.contentDocument;if(!d||!l)return void o("Missing contentWindow or contentDocument: "+h);if(!l.head)return void o("Missing contentDocument.head: "+h);if(I(d))return void o("FS already defined in Frame contentWindow: "+h+". Ignoring.");d._fs_org=r,d._fs_script=a,d._fs_rec_host=u,d._fs_app_host=c,d._fs_debug=i(),d._fs_run_in_iframe=!0,t&&(d._fs_transport=t);var p=l.createElement("script");p.async=!0,p.crossOrigin="anonymous",p.src=s+"//"+a,"testdrive"==r&&(p.src+="?allowMoo=true"),l.head.appendChild(p)}catch(e){o("iFrame no injecty. Probably not same origin.")}},No=/^fb\d{18}$/;!function(e){e[e.NoInfoYet=1]="NoInfoYet",e[e.Enabled=2]="Enabled",e[e.Disabled=3]="Disabled"}(qo||(qo={}));var Wo=function(){function e(e,t,n,r){var i=this;this._ctx=e,this._transport=n,this._injector=r,this._bundleUploadInterval=te.DefaultBundleUploadInterval,this._iFrames=[],this._pendingChildFrameIdInits=[],this._listeners=new Ut,this._getCurrentSessionEnabled=qo.NoInfoYet,this._resourceUploadingEnabled=!1,this._tickerTasks=[],this._pendingIframes={},this._watcher=new yn,this._queue=new io(e,this._transport,function(e){for(var t=i._eventWatcher.bundleEvents(e),n=void 0;n=i._tickerTasks.pop();)n();return t},t),this._keep=new Lo(e,this._queue),this._eventWatcher=new Di(e,this._queue,this._keep,this._watcher,this._listeners,function(e){i.onFrameCreated(e)},function(e){i.beforeFrameRemoved(e)},new Eo(e,this._queue,new Ao(e))),this._consoleWatcher=new Ji(e,this._queue,this._listeners),this._scheme=e.options.scheme,this._script=e.options.script,this._recHost=e.options.recHost,this._appHost=e.options.appHost,this._orgId=e.options.orgId,this._wnd=e.window}return e.prototype.bundleUploadInterval=function(){return this._bundleUploadInterval},e.prototype.start=function(e,t){var n=this;this._onFullyStarted=t,"onpagehide"in this._wnd?this._listeners.add(this._wnd,"pagehide",!1,function(e){n.onUnload()}):this._listeners.add(this._wnd,"unload",!1,function(e){n.onUnload()}),this._listeners.add(this._wnd,"message",!1,function(e){if("string"==typeof e.data){var t=e.source;n.postMessageReceived(t,Bo(e.data))}});var r=this._wnd.Document?this._wnd.Document.prototype:this._wnd.document;this._docCloseHook=Tt(r,"close"),this._docCloseHook&&this._docCloseHook.afterAsync(function(){n._listeners.refresh()})},e.prototype.queue=function(){return this._queue},e.prototype.eventWatcher=function(){return this._eventWatcher},e.prototype.console=function(){return this._consoleWatcher},e.prototype.onDomLoad=function(){this._eventWatcher.onDomLoad()},e.prototype.onLoad=function(){this._eventWatcher.onLoad()},e.prototype.shutdown=function(e){this._eventWatcher.shutdown(e),this._consoleWatcher.disable(),this._listeners&&this._listeners.clear(),this._docCloseHook&&this._docCloseHook.disable(),this.tellAllFramesTo(["ShutdownFrame"])},e.prototype.tellAllFramesTo=function(e){for(var t=0;t0){for(var e=0;e0&&this._transport.enqueueEvents(r,n);break;case"RequestFrameId":if(!e)return void o("No MessageEvent.source, iframe may have unloaded.");var s=this.iFrameWndToFsId(e);s?(o("Responding to FID request for frame "+s),this._pendingIframes[s]=!1,this.sendFrameIdToInnerFrame(e,s)):o("No FrameId found. Hoping to send one later.");}},e.prototype.sendFrameIdToInnerFrame=function(e,t){var n=this,r=function(){var r=[];0!=n._frameId&&(r=n._parentIds?n._parentIds.concat(n._frameId):[n._frameId]);var i=n._ctx.time.startTime();Do(e,["SetFrameId",t,r,i,n._scheme,n._script,n._appHost,n._orgId,n._pageRsp])};null==this._frameId?this._pendingChildFrameIdInits.push(r):r()},e.prototype.iFrameWndToFsId=function(e){for(var t=0;t=400&&502!==e||202==e||206==e}var jo=function(){return(jo=Object.assign||function(e){for(var t,n=1,r=arguments.length;n2e6))try{localStorage._fs_swan_song=t}catch(e){}},e.prototype._recover=function(){try{if("_fs_swan_song"in localStorage){var e=localStorage._fs_swan_song||localStorage.singSwanSong;delete localStorage._fs_swan_song,delete localStorage.singSwanSong;var t=wt(e);if(!(t.Bundles&&t.UserId&&t.SessionId&&t.PageId))return void o("Malformed swan song found. Ignoring it.");t.OrgId||(t.OrgId=this._identity.orgId()),t.Bundles.length>0&&(o("Sending "+t.Bundles.length+" bundles as prior page swan song"),this.sendSwanSongBundles(t))}}catch(e){o("Error recovering swan-song: "+e)}},e.prototype.sendSwanSongBundles=function(e,t){var n=this;void 0===t&&(t=0);var r=null;if(nt(e.Bundles)&&0!==e.Bundles.length&&void 0!==e.Bundles[0]){1==e.Bundles.length&&(r=this._ctx.time.wallTime()-(e.LastBundleTime||0));this._protocol.bundle({bundle:e.Bundles[0],deltaT:r,orgId:e.OrgId,pageId:e.PageId,serverBundleTime:e.ServerBundleTime,serverPageStart:e.ServerPageStart,sessionId:e.SessionId,userId:e.UserId,isNewSession:e.IsNewSession,win:function(t){o("Sent "+e.Bundles[0].Evts.length+" trailing events from last session as Seq "+e.Bundles[0].Seq),e.Bundles.shift(),e.Bundles.length>0?n.sendSwanSongBundles(jo(jo({},e),{ServerBundleTime:t.BundleTime})):o("Done with prior page swan song")},lose:function(r){Ho(r)?o("Fatal error while sending events, giving up"):(o("Failed to send events from last session, will retry while on this page"),n._lastSwanSongRetryTimeout=new n._timeoutFactory(n.sendSwanSongBundles,n._protocol.exponentialBackoffMs(t,!0),n,e,t+1).start())}})}},e}(),Vo=function(){function e(e,t,n,r){var i=this;void 0===t&&(t=new Ro(e)),void 0===n&&(n=en),void 0===r&&(r=tn),this._ctx=e,this._protocol=t,this._tickerFactory=n,this._backoffRetries=0,this._backoffTime=0,this._bundleSeq=1,this._lastPostTime=0,this._serverBundleTime=0,this._isNewSession=!1,this._largePageSize=16e6,this._outgoingEventQueue=[],this._bundleQueue=[],this._hibernating=!1,this._heartbeatInterval=0,this._lastUserActivity=this._ctx.time.wallTime(),this._finished=!1,this._scheme=e.options.scheme,this._identity=e.recording.identity,this._lastBundleTime=e.time.wallTime(),this._swanSong=new Ko(e,this._protocol,this._identity,r),this._heartbeatTimeout=new r(function(){i.onHeartbeat()}),this._hibernationTimeout=new r(function(){i.onHibernate()},te.PageInactivityTimeout)}return e.prototype.onShutdown=function(e){this._onShutdown=e},e.prototype.scheme=function(){return this._scheme},e.prototype.enqueueEvents=function(e,t){if(this.maybeHibernate(),this._hibernating){if(this._finished)return;for(var n=0,r=t;n0&&this.enqueueNextBundle(!0),this._bundleQueue.length>0||this._pendingBundle)){var e=this._bundleQueue.concat();this._pendingBundle&&e.unshift(this._pendingBundle),this._swanSong.sing({pageId:this._pageId,bundles:e,lastBundleTime:this._lastBundleTime,serverPageStart:this._serverPageStart,serverBundleTime:this._serverBundleTime,isNewSession:this._isNewSession})}},e.prototype.maybeHibernate=function(){this._hibernating||this.calcLastUserActivityDuration()>=te.PageInactivityTimeout+5e3&&this.onHibernate()},e.prototype.calcLastUserActivityDuration=function(){return s.mathFloor(this._ctx.time.wallTime()-this._lastUserActivity)},e.prototype.onHeartbeat=function(){var e=this.calcLastUserActivityDuration();this._outgoingEventQueue.push({When:this._ctx.time.now(),Kind:R.HEARTBEAT,Args:[e]}),this._heartbeatInterval*=2,this._heartbeatInterval>te.HeartbeatMax&&(this._heartbeatInterval=te.HeartbeatMax),this._heartbeatTimeout.start(this._heartbeatInterval)},e.prototype.onHibernate=function(){this._hibernating||(this.calcLastUserActivityDuration()<=2*te.PageInactivityTimeout&&(this._outgoingEventQueue.push({When:this._ctx.time.now(),Kind:R.UNLOAD,Args:[V.Hibernation]}),this.singSwanSong()),this.stopPipeline(),this._hibernating=!0)},e.prototype.enqueueAndSendBundle=function(){this._pendingBundle?this._pendingBundleFailed&&this._sendPendingBundle():0!=this._outgoingEventQueue.length?this.enqueueNextBundle():this.maybeSendNextBundle()},e.prototype.enqueueNextBundle=function(e){void 0===e&&(e=!1);var t={When:this._outgoingEventQueue[0].When,Seq:this._bundleSeq++,Evts:this._outgoingEventQueue};this._outgoingEventQueue=[],this._bundleQueue.push(t),e?this._protocol.bundleBeacon({bundle:t,deltaT:null,orgId:this._identity.orgId(),pageId:this._pageId,serverBundleTime:this._serverBundleTime,serverPageStart:this._serverPageStart,isNewSession:this._isNewSession,sessionId:this._identity.sessionId(),userId:this._identity.userId(),win:function(){},lose:function(){}}):this.maybeSendNextBundle()},e.prototype.maybeSendNextBundle=function(){this._pageId&&this._serverPageStart&&!this._pendingBundle&&0!=this._bundleQueue.length&&(this._pendingBundle=this._bundleQueue.shift(),this._sendPendingBundle())},e.prototype._sendPendingBundle=function(){var e=this,t=this._ctx.time.wallTime();if(!(te._ctx.recording.bundleUploadInterval()&&e.maybeSendNextBundle()},function(t){if(o("Failed to send events."),Ho(t))return 206==t?Mt.sendToBugsnag("Failed to send bundle, probably because of its large size","error"):t>=500&&Mt.sendToBugsnag("Failed to send bundle, recording outage likely","error"),void(e._onShutdown&&e._onShutdown());e._pendingBundleFailed=!0,e._backoffTime=e._lastPostTime+e._protocol.exponentialBackoffMs(e._backoffRetries++,!1)}))}},e.prototype.sendBundle=function(e,t,n){var r=s.mathFloor(this._ctx.time.wallTime()-this._lastUserActivity),i=this._protocol.bundle({bundle:e,deltaT:null,lastUserActivity:r,orgId:this._identity.orgId(),pageId:this._pageId,serverBundleTime:this._serverBundleTime,serverPageStart:this._serverPageStart,isNewSession:this._isNewSession,sessionId:this._identity.sessionId(),userId:this._identity.userId(),win:t,lose:n});i>this._largePageSize&&this._bundleSeq>16&&(o("splitting large page: "+i),this._ctx.recording.splitPage(V.Size))},e}(),zo=function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),Yo=function(e){function t(t,n,r,i,o){void 0===r&&(r=new Vo(t,n)),void 0===i&&(i=en),void 0===o&&(o=Uo);var s,a,u=e.call(this,t,i,r,o)||this;return u._protocol=n,u._domLoaded=!1,u._recordingDisabled=!1,u._integrationScriptFetched=!1,r.onShutdown(function(){return u.shutdown(V.SettingsBlocked)}),u._doc=u._wnd.document,u._frameId=0,u._identity=t.recording.identity,u._getCurrentSessionEnabled=qo.NoInfoYet,s=u._wnd,a=function(e){if(u._eventWatcher.shutdown(V.Api),e){var t=u._doc.getElementById(e);t&&t.setAttribute("_fs_embed_token",u._embedToken)}},s._fs_shutdown=a,u}return zo(t,e),t.prototype.onDomLoad=function(){var t=this;e.prototype.onDomLoad.call(this),this._domLoaded=!0,this.injectIntegrationScript(function(){t.fireFsReady(t._recordingDisabled)})},t.prototype.getReplayFlags=function(){var e=U(this._wnd);if(/[?&]_fs_force_session=true(&|#|$)/.test(location.search)&&(e+=",forceSession",this._wnd.history)){var t=location.search.replace(/(^\?|&)_fs_force_session=true(&|$)/,function(e,t,n){return n?t:""});this._wnd.history.replaceState({},"",this._wnd.location.href.replace(location.search,t))}return e},t.prototype.start=function(t,n){var r,i,o,s=this;e.prototype.start.call(this,t,n);var a=this.getReplayFlags(),u=Vt(this._doc),c=u[0],h=u[1],d=bt(this._wnd),l=d[0],p=d[1],f="";t||(f=this._identity.userId());var v=null!==(o=null===(i=null===(r=this._ctx)||void 0===r?void 0:r.recording)||void 0===i?void 0:i.preroll)&&void 0!==o?o:-1,_=ur(Jn(this._wnd),this._orgId,{source:"page",type:"base"}),g=ur(this._doc.referrer,this._orgId,{source:"page",type:"referrer"}),m=ur(this._wnd.location.href,this._orgId,{source:"page",type:"url"}),y={OrgId:this._orgId,UserId:f,Url:m,Base:_,Width:c,Height:h,ScreenWidth:l,ScreenHeight:p,Referrer:g,Preroll:v,Doctype:yt(this._doc),CompiledTimestamp:1591209308,AppId:this._identity.appId()};a&&(y.ReplayFlags=a),this._protocol.page(y,function(e){s.handleResponse(e),s.handleIdentity(e.CookieDomain,e.UserIntId,e.SessionIntId,e.PageIntId,e.EmbedToken),s.handleIntegrationScript(e.IntegrationScript),e.PreviewMode&&s.maybeInjectPreviewScript();var t=s._wnd._fs_pagestart;t&&t();var n=!!e.Consented;s._queue.enqueueFirst({Kind:R.SYS_REPORTCONSENT,Args:[n,K.Document]}),s._queue.enqueueFirst({Kind:R.SET_FRAME_BASE,Args:[ur(Jn(s._wnd),s._orgId,{source:"event",type:R.SET_FRAME_BASE}),yt(s._doc)]}),s._queue.startPipeline({pageId:e.PageIntId,serverPageStart:e.PageStart,isNewSession:!!e.IsNewSession}),s.fullyStarted()},function(e,t){t&&t.user_id&&t.cookie_domain&&t.reason_code==$.ReasonBlockedTrafficRamping&&f!=t.user_id&&s.handleIdentity(t.cookie_domain,t.user_id,"","",""),s.disableBecauseRecPageSaidSo()})},t.prototype.handleIntegrationScript=function(e){var t=this;this._integrationScriptFetched=!0,this._integrationScript=e,this.injectIntegrationScript(function(){t.fireFsReady(t._recordingDisabled)})},t.prototype.handleIdentity=function(e,t,n,r,i){var s=this._identity;s.setIds(this._wnd,e,t,n),this._embedToken=i,o("/User,"+s.userId()+"/Session,"+s.sessionId()+"/Page,"+r)},t.prototype.injectIntegrationScript=function(e){if(this._domLoaded&&this._integrationScriptFetched)if(this._integrationScript){var t=this._doc.createElement("script");this._wnd._fs_csp?(t.addEventListener("load",e),t.addEventListener("error",e),t.async=!0,t.src=this._scheme+"//"+this._recHost+"/rec/integrations?OrgId="+this._orgId,this._doc.head.appendChild(t)):(t.text=this._integrationScript,this._doc.head.appendChild(t),e())}else e()},t.prototype.maybeInjectPreviewScript=function(){if(!this._doc.getElementById("FullStory-preview-script")){var e=this._doc.createElement("script");e.id="FullStory-preview-script",e.async=!0,e.src=this._scheme+"//"+this._appHost+"/s/fspreview.js",this._doc.head.appendChild(e)}},t.prototype.disableBecauseRecPageSaidSo=function(){this.shutdown(V.SettingsBlocked),o("Disabling FS."),this._recordingDisabled=!0,this.fireFsReady(this._recordingDisabled)},t}(Wo),Go=function(){function e(e,t){void 0===t&&(t=new Qo(e)),this._wnd=e,this._messagePoster=t}return e.prototype.enqueueEvents=function(e,t){this._messagePoster.postMessage(this._wnd.parent,"EvtBundle",t,e)},e.prototype.startPipeline=function(){},e.prototype.stopPipeline=function(){},e.prototype.flush=function(){},e.prototype.singSwanSong=function(){},e.prototype.onShutdown=function(e){},e}(),Qo=function(){function e(e){this.wnd=e}return e.prototype.postMessage=function(e,t,n,r){var i=N(this.wnd);if(i)try{i.send(t,gt(n),r)}catch(e){i.send(t,gt(n))}else e.postMessage(function(e,t,n){var r=[e,t];n&&r.push(n);return gt({__fs:r})}(t,n,r),"*")},e}();var Xo,Jo=function(){var e=function(t,n){return(e=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(t,n)};return function(t,n){function r(){this.constructor=t}e(t,n),t.prototype=null===n?Object.create(n):(r.prototype=n.prototype,new r)}}(),$o=function(e){function t(t,n,r,i,o){void 0===n&&(n=new Qo(t.window)),void 0===r&&(r=new Go(t.window)),void 0===i&&(i=en),void 0===o&&(o=Uo);var s=e.call(this,t,i,r,o)||this;return s._messagePoster=n,s}return Jo(t,e),t.prototype.start=function(t,n){var r=this;e.prototype.start.call(this,t,n),this.sendRequestForFrameId(),this._listeners.add(this._wnd,"load",!1,function(){r._eventWatcher.recordingIsDetached()&&(o("Recording wrong document. Restarting recording in iframe."),r._ctx.recording.splitPage(V.FsShutdownFrame))})},t.prototype.postMessageReceived=function(t,n){if(e.prototype.postMessageReceived.call(this,t,n),t==this._wnd.parent||t==this._wnd)switch(n[0]){case"GreetFrame":this.sendRequestForFrameId();break;case"SetFrameId":try{var r=n[1],i=n[2],s=n[3],a=n[4],u=n[5],c=n[6],h=n[7],d=n[8];if(!r)return void o("Outer page gave us a bogus frame Id! Iframe: "+ur(location.href,h,{source:"log",type:"debug"}));this.setFrameIdFromOutside(r,i,s,a,u,c,h,d)}catch(e){o("Failed to parse frameId from message: "+gt(n))}break;case"SetConsent":var l=n[1];this.setConsent(l);break;case"InitFrameMobile":try{var p=JSON.parse(n[1]),f=p.StartTime;if(n.length>2){var v=n[2];if(v.hasOwnProperty("ProtocolVersion"))v.ProtocolVersion>=20180723&&v.hasOwnProperty("OuterStartTime")&&(f=v.OuterStartTime)}var _=p.Host;this.setFrameIdFromOutside(0,[],f,"https:",H(_),B(_),p.OrgId,p.PageResponse)}catch(e){o("Failed to initialize mobile web recording from message: "+gt(n))}}},t.prototype.sendRequestForFrameId=function(){this._frameId||(0!=this._frameId?this._wnd.parent?(o("Asking for a frame ID."),this._messagePoster.postMessage(this._wnd.parent,"RequestFrameId",[])):o("Orphaned window."):o("For some reason the outer window attempted to request a frameId"))},t.prototype.setFrameIdFromOutside=function(e,t,n,r,i,s,a,u){if(this._frameId)this._frameId!=e?(o("Updating frame id from "+this._frameId+" to "+e),this._ctx.recording.splitPage(V.FsShutdownFrame)):o("frame Id is already set to "+this._frameId);else{o("FrameId received within frame "+ur(location.href,a,{source:"log",type:"debug"})+": "+e),this._scheme=r,this._script=i,this._appHost=s,this._orgId=a,this._frameId=e,this._parentIds=t,this.handleResponse(u),this.fireFsReady();var c=!!u.Consented;this._queue.enqueueFirst({Kind:R.SYS_REPORTCONSENT,Args:[c,K.Document]}),this._queue.enqueueFirst({Kind:R.SET_FRAME_BASE,Args:[ur(Jn(this._wnd),a,{source:"event",type:R.SET_FRAME_BASE}),yt(this._wnd.document)]}),this._queue.rebaseIframe(n),this._ctx.time.setStartTime(n),this._queue.startPipeline({pageId:this._pageId,serverPageStart:u.PageStart,isNewSession:!!u.IsNewSession,frameId:e,parentIds:t}),this.flushPendingChildFrameInits(),this.fullyStarted()}},t}(Wo),Zo="fsidentity",es="newuid",ts=function(){function e(e,t){void 0===e&&(e=document),void 0===t&&(t=function(){}),this._doc=e,this._onWriteFailure=t,this._cookies={},this._appId=void 0}return e.prototype.initFromCookies=function(e,t){this._cookies=y(this._doc);var n=this._cookies.fs_uid;if(!n)try{n=localStorage._fs_uid}catch(e){}var r=m(n);r&&r.host.replace(/^www\./,"")==e.replace(/^www\./,"")&&r.orgId==t?this._cookie=r:this._cookie={expirationAbsTimeSeconds:g(),host:e,orgId:t,userId:"",sessionId:"",appKeyHash:""}},e.prototype.initFromParsedCookie=function(e){this._cookie=e},e.prototype.clear=function(){this._cookie.userId=this._cookie.sessionId=this._cookie.appKeyHash=this._appId="",this._cookie.expirationAbsTimeSeconds=g(),this._write()},e.prototype.host=function(){return this._cookie.host},e.prototype.orgId=function(){return this._cookie.orgId},e.prototype.userId=function(){return this._cookie.userId},e.prototype.sessionId=function(){return this._cookie.sessionId},e.prototype.appKeyHash=function(){return this._cookie.appKeyHash},e.prototype.cookieData=function(){return this._cookie},e.prototype.cookies=function(){return this._cookies},e.prototype.setCookie=function(e,t,n){void 0===n&&(n=new Date(p()+6048e5).toUTCString());var r=e+"="+t;this._domain?r+="; domain=."+encodeURIComponent(this._domain):r+="; domain=",r+="; Expires="+n+"; path=/; SameSite=Strict","https:"===location.protocol&&(r+="; Secure"),this._doc.cookie=r},e.prototype.setIds=function(e,t,n,r){(C(t)||t.match(/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/g))&&(t="");var i=function(e){return e._fs_cookie_domain}(e);"string"==typeof i&&(t=i),this._domain=t,this._cookie.userId=n,this._cookie.sessionId=r,this._write()},e.prototype.clearAppId=function(){return!!this._cookie.appKeyHash&&(this._appId="",this._cookie.appKeyHash="",this._write(),!0)},e.prototype.setAppId=function(e){this._appId=e,this._cookie.appKeyHash=uo(e),this._write()},e.prototype.appId=function(){return this._appId},e.prototype.encode=function(){var e=this._cookie.host+"#"+this._cookie.orgId+"#"+this._cookie.userId+":"+this._cookie.sessionId;return this._cookie.appKeyHash&&(e+="#"+encodeURIComponent(this._cookie.appKeyHash)+"#"),e+="/"+this._cookie.expirationAbsTimeSeconds},e.prototype._write=function(){if(null!=this._domain){var e=this.encode(),t=new Date(1e3*this._cookie.expirationAbsTimeSeconds).toUTCString();this.setCookie("fs_uid",e,t);var n=[];-1===this._doc.cookie.indexOf(e)&&n.push(["fs_uid","cookie"]);try{localStorage._fs_uid=e,localStorage._fs_uid!==e&&n.push(["fs_uid","localStorage"])}catch(e){n.push(["fs_uid","localStorage",String(e)])}n.length>0&&this._onWriteFailure(n)}},e}();!function(e){e.rec="rec",e.user="user",e.account="account",e.consent="consent",e.customEvent="event",e.log="log"}(Xo||(Xo={}));var ns={acctId:"str",displayName:"str",website:"str"},rs={uid:"str",displayName:"str",email:"str"},is={str:os,bool:ss,real:as,"int":us,date:cs,strs:hs(os),bools:hs(ss),reals:hs(as),ints:hs(us),dates:hs(cs),objs:hs(ds),obj:ds};function os(e){return"string"==typeof e}function ss(e){return"boolean"==typeof e}function as(e){return"number"==typeof e}function us(e){return"number"==typeof e&&e-s.mathFloor(e)==0}function cs(e){return!!e&&(e.constructor===Date?!isNaN(e):("number"==typeof e||"string"==typeof e)&&!isNaN(new Date(e)))}function hs(e){return function(t){if(!(t instanceof Array))return!1;for(var n=0;n=0)return o("blocking FS.identify API call; uid value ("+n+") is illegal"),[void 0,Zo];var r=uo(n),i=void 0;t&&t._cookie.appKeyHash&&t._cookie.appKeyHash!==r&&t._cookie.appKeyHash!==n&&(o("user re-identified; existing uid hash ("+t._cookie.appKeyHash+") does not match provided uid ("+n+")"),i=es);return[n,i]}(a,this._identity),c=u[0],h=u[1];if(!c){switch(h){case Zo:case void 0:break;default:o("unexpected failReason returned from setAppId: "+h);}return{events:i}}t.uid=c,this._identity.setAppId(t.uid),h==es&&(r=!0)}}i.push.apply(i,this.rawEventsFromApi(X.User,rs,t,n));break;case Xo.customEvent:var d=t.n,l=t.p;i.push.apply(i,this.rawEventsFromApi(X.Event,{},l,n,d));break;default:o("invalid operation \""+e+"\"; only \"rec\", \"account\", and \"user\" are supported at present");}}catch(t){o("unexpected exception handling "+e+" API call: "+t.message)}return{events:i,reidentify:r}},e.prototype.rawEventsFromApi=function(e,t,n,r,i){var a=function e(t,n,r){var i={PayloadToSend:{},ValidationErrors:[]},a=function(r){var o=e(t,n,r);return i.ValidationErrors=i.ValidationErrors.concat(o.ValidationErrors),o.PayloadToSend};return ht(r,function(e,r){var u=function(e,t,n,r){var i=t,a=typeof n;if("undefined"===a)return o("Cannot infer type of "+a+" "+n),r.push({Type:"vartype",FieldName:t,ValueType:a+" (unsupported)"}),null;if(s.objectHasOwnProp(e,t))return{name:t,type:e[t]};var u=t.lastIndexOf("_");if(-1==u||!vs(t.substring(u+1))){var c=function(e){for(var t in is)if(is[t](e))return t;return null}(n);if(null==c)return o("Cannot infer type of "+a+" "+n),n?r.push({Type:"vartype",FieldName:t}):r.push({Type:"vartype",FieldName:t,ValueType:"null (unsupported)"}),null;u=t.length,o("Warning: Inferring user variable \""+t+"\" to be of type \""+c+"\""),t=t+"_"+c}var h=[t.substring(0,u),t.substring(u+1)],d=h[0],l=h[1];if("object"===a&&!n)return o("null is not a valid object type"),r.push({Type:"vartype",FieldName:i,ValueType:"null (unsupported)"}),null;if(!ls.test(d)){d=d.replace(/[^a-zA-Z0-9_]/g,"").replace(/^[0-9]+/,""),/[0-9]/.test(d[0])&&(d=d.substring(1)),r.push({Type:"varname",FieldName:i});var p=d+"_"+l;if(o("Warning: variable \""+i+"\" has invalid characters. It should match /"+ls.source+"/. Converted name to \""+p+"\"."),""==d)return null;t=p}if(!vs(l))return o("Variable \""+i+"\" has invalid type \""+l+"\""),r.push({Type:"varname",FieldName:i}),null;if(!function(e,t){return is[e](t)}(l,n))return o("illegal value "+gt(n)+" for type "+l),"number"===a?a=n%1==0?"integer":"real":"object"==a&&null!=n&&n.constructor==Date&&(a=isNaN(n)?"invalid date":"date"),r.push({Type:"vartype",FieldName:i,ValueType:a}),null;return{name:t,type:l}}(n,r,e,i.ValidationErrors);if(u){var c=u.name,h=u.type;if("obj"!=h){if("objs"!=h){var d,l;i.PayloadToSend[c]=fs(h,e)}else{t!=X.Event&&i.ValidationErrors.push({Type:"vartype",FieldName:c,ValueType:"Array (unsupported)"});for(var p=e,f=[],v=0;v0&&(i.PayloadToSend[c]=f)}}else{var _=a(e),g=(l="_obj").length>(d=r).length||d.substring(d.length-l.length)!=l?c.substring(0,c.length-"_obj".length):c;i.PayloadToSend[g]=_}}else i.PayloadToSend[r]=fs("",e)}),i}(e,t,n),u=[],c=e==X.Event,h=gt(a.PayloadToSend),d=!!r&&"fs"!==r;return c?u.push({When:0,Kind:R.SYS_CUSTOM,Args:d?[i,h,r]:[i,h]}):u.push({When:0,Kind:R.SYS_SETVAR,Args:d?[e,h,r]:[e,h]}),u},e}();function fs(e,t){return"str"==e&&null!=t&&(t=t.trim()),null==t||"date"!=e&&t.constructor!=Date||(t=function(e){var t,n=e.constructor===Date?e:new Date(e);try{t=n.toISOString()}catch(e){t=null}return t}(t)),t}function vs(e){return!!is[e]}var _s=function(){return(_s=Object.assign||function(e){for(var t,n=1,r=arguments.length;n0&&i[i.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]u.length?u.length:a.length,d=1,l=d;l=0}var Es=["__zone_symbol__OriginalDelegate","nr@original"];function Ts(e,t){if(t){for(var n=0,r=Es;n16)Mt.sendToBugsnag("Too much synchronous recursion in requestMeasureTask","error");else{var n=this.performingMeasurements?this.recursionDepth:0,r=Mt.wrap(function(){var r=t.recursionDepth;t.recursionDepth=n+1;try{e()}finally{t.recursionDepth=r}});this.measurementTasks?this.measurementTasks.push(r):(this.measurementTasks=[r],this.schedule())}},e.prototype.performMeasurementsNow=function(){this.performMeasurements()},e}(),As=function(e){function t(t,n){var r=e.call(this)||this;return r.wnd=t,r.ResizeObserver=n,r}return Cs(t,e),t.prototype.schedule=function(){var e=this,t=this.ResizeObserver,n=this.wnd.document,r=n.body||n.documentElement||n.head,i=new t(function(){i.unobserve(r),e.performMeasurements()});i.observe(r)},t}(Rs),xs=function(e){function t(t,n,r){var i=e.call(this)||this;return i.wnd=t,i.requestWindowAnimationFrame=n,i.onRAF=Mt.wrap(function(){i.ch.port2.postMessage(void 0)}),i.ch=new r,i}return Cs(t,e),t.prototype.schedule=function(){this.ch.port1.onmessage=this.performMeasurements,this.requestWindowAnimationFrame(this.wnd,this.onRAF)},t}(Rs),Os=function(e){function t(t){var n=e.call(this)||this;return n.wnd=t,n}return Cs(t,e),t.prototype.schedule=function(){s.setWindowTimeout(this.wnd,this.performMeasurements,0)},t}(Rs),Ms=function(e,t,n,r){return new(n||(n=Promise))(function(i,o){function s(e){try{u(r.next(e))}catch(e){o(e)}}function a(e){try{u(r["throw"](e))}catch(e){o(e)}}function u(e){var t;e.done?i(e.value):(t=e.value,t instanceof n?t:new n(function(e){e(t)})).then(s,a)}u((r=r.apply(e,t||[])).next())})},Ls=function(e,t){var n,r,i,o,s={label:0,sent:function(){if(1&i[0])throw i[1];return i[1]},trys:[],ops:[]};return o={next:a(0),"throw":a(1),"return":a(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function a(o){return function(a){return function(o){if(n)throw new TypeError("Generator is already executing.");for(;s;)try{if(n=1,r&&(i=2&o[0]?r["return"]:o[0]?r["throw"]||((i=r["return"])&&i.call(r),0):r.next)&&!(i=i.call(r,o[1])).done)return i;switch(r=0,i&&(o=[2&o[0],i.value]),o[0]){case 0:case 1:i=o;break;case 4:return s.label++,{value:o[1],done:!1};case 5:s.label++,r=o[1],o=[0];continue;case 7:o=s.ops.pop(),s.trys.pop();continue;default:if(!(i=(i=s.trys).length>0&&i[i.length-1])&&(6===o[0]||2===o[0])){s=0;continue}if(3===o[0]&&(!i||o[1]>i[0]&&o[1]=8)return void o("reidentified too many times; giving up");this.reidentifyCount++,W(this.wnd,[e,t]),this.splitPage(V.Reidentify,!0)}else u();void 0!==a&&(a?this.restart():this.shutdown(V.Api))}else W(this.wnd,[e,t])},e.prototype._cookies=function(){return this.identity?this.identity.cookies():(o("Error in FS integration: Can't get cookies from inside an iframe"),null)},e.prototype._setCookie=function(e,t){this.identity?this.identity.setCookie(e,t):o("Error in FS integration: Can't set cookies from inside an iframe")},e.prototype._withEventQueue=function(e,t){if(this.recorder){var n=this.recorder.queue(),r=this.recorder.pageSignature();null!=n&&null!=r?e===r?t(n):Mt.sendToBugsnag("Error in _withEventQueue: Page Signature mismatch","error",{pageSignature:r,callerSignature:e}):o("Error getting event queue or page signature: Recorder not initialized")}else o("Error in FS integration: Recorder not initialized")},e.prototype.initApi=function(){var e=I(this.wnd);e?(e.getCurrentSessionURL=_t(this.getCurrentSessionURL,this),e.getCurrentSession=_t(this.getCurrentSession,this),e.enableConsole=_t(this.enableConsole,this),e.disableConsole=_t(this.disableConsole,this),e.log=_t(this.log,this),e.shutdown=_t(this.shutdownApi,this),e.restart=_t(this.restart,this),e._api=_t(this._api,this),e._cookies=_t(this._cookies,this),e._setCookie=_t(this._setCookie,this),e._withEventQueue=_t(this._withEventQueue,this)):o("Missing browser API namespace; couldn't initialize API.")},e.prototype.start=function(){var e,t=this;e=L(this.wnd),r=e,o("script version UNSET (compiled at 1591209308)");var n=P(this.wnd);if(n){this.orgId=n;var i,s=(i=this.wnd)._fs_script||H(D(i));if(s){this.script=s;var a=F(this.wnd);if(a){this.recHost=a;var u=function(e){return e._fs_app_host||B(D(e))}(this.wnd);u?(this.appHost=u,o("script: "+this.script),o("recording host: "+this.recHost),o("orgid: "+this.orgId),"localhost:8080"==this.recHost&&(this.scheme="http:"),this.inFrame()||(this.identity=new ts(this.wnd.document,function(e){for(var n,r=0,i=e;r { describe('full_story', () => { - it('allows orgId when enabled: false', () => { + it('allows org_id when enabled: false', () => { expect(() => config.schema.validate({ full_story: { enabled: false, org_id: 'asdf' } }) ).not.toThrow(); }); - it('rejects undefined or empty orgId when enabled: true', () => { + it('rejects undefined or empty org_id when enabled: true', () => { expect(() => config.schema.validate({ full_story: { enabled: true } }) ).toThrowErrorMatchingInlineSnapshot( @@ -28,7 +28,7 @@ describe('xpack.cloud config', () => { ); }); - it('accepts orgId when enabled: true', () => { + it('accepts org_id when enabled: true', () => { expect(() => config.schema.validate({ full_story: { enabled: true, org_id: 'asdf' } }) ).not.toThrow(); diff --git a/x-pack/plugins/cloud/server/plugin.ts b/x-pack/plugins/cloud/server/plugin.ts index fea8be9f934e1..4c0b7b7f7eca6 100644 --- a/x-pack/plugins/cloud/server/plugin.ts +++ b/x-pack/plugins/cloud/server/plugin.ts @@ -11,6 +11,7 @@ import { CloudConfigType } from './config'; import { registerCloudUsageCollector } from './collectors'; import { getIsCloudEnabled } from '../common/is_cloud_enabled'; import { parseDeploymentIdFromDeploymentUrl } from './utils'; +import { registerFullstoryRoute } from './routes/fullstory'; interface PluginsSetup { usageCollection?: UsageCollectionSetup; @@ -40,6 +41,13 @@ export class CloudPlugin implements Plugin { const isCloudEnabled = getIsCloudEnabled(this.config.id); registerCloudUsageCollector(usageCollection, { isCloudEnabled }); + if (this.config.full_story.enabled) { + registerFullstoryRoute({ + httpResources: core.http.resources, + packageInfo: this.context.env.packageInfo, + }); + } + return { cloudId: this.config.id, deploymentId: parseDeploymentIdFromDeploymentUrl(this.config.deployment_url), diff --git a/x-pack/plugins/cloud/server/routes/fullstory.test.ts b/x-pack/plugins/cloud/server/routes/fullstory.test.ts new file mode 100644 index 0000000000000..dae541a8c033c --- /dev/null +++ b/x-pack/plugins/cloud/server/routes/fullstory.test.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +jest.mock('fs/promises'); +import { renderFullStoryLibraryFactory, FULLSTORY_LIBRARY_PATH } from './fullstory'; +import fs from 'fs/promises'; + +const fsMock = fs as jest.Mocked; + +describe('renderFullStoryLibraryFactory', () => { + beforeEach(() => { + jest.resetAllMocks(); + fsMock.readFile.mockResolvedValue(Buffer.from('fake fs src')); + }); + afterAll(() => jest.restoreAllMocks()); + + it('successfully returns file contents', async () => { + const render = renderFullStoryLibraryFactory(); + + const { body } = await render(); + expect(fsMock.readFile).toHaveBeenCalledWith(FULLSTORY_LIBRARY_PATH); + expect(body.toString()).toEqual('fake fs src'); + }); + + it('only reads from file system once callback is invoked', async () => { + const render = renderFullStoryLibraryFactory(); + expect(fsMock.readFile).not.toHaveBeenCalled(); + await render(); + expect(fsMock.readFile).toHaveBeenCalledTimes(1); + }); + + it('does not read from filesystem on subsequent calls', async () => { + const render = renderFullStoryLibraryFactory(); + await render(); + expect(fsMock.readFile).toHaveBeenCalledTimes(1); + await render(); + expect(fsMock.readFile).toHaveBeenCalledTimes(1); + await render(); + expect(fsMock.readFile).toHaveBeenCalledTimes(1); + }); + + it('returns max-age cache-control in dist', async () => { + const render = renderFullStoryLibraryFactory(true); + const { headers } = await render(); + expect(headers).toEqual({ + 'cache-control': 'max-age=31536000', + }); + }); + + it('returns must-revalidate cache-control and sha1 etag in dev', async () => { + const render = renderFullStoryLibraryFactory(false); + const { headers } = await render(); + expect(headers).toEqual({ + 'cache-control': 'must-revalidate', + etag: '1e02f94b45750ba9284c111d31ae7e59c13b8e6e', + }); + }); +}); diff --git a/x-pack/plugins/cloud/server/routes/fullstory.ts b/x-pack/plugins/cloud/server/routes/fullstory.ts new file mode 100644 index 0000000000000..c614d803eed9f --- /dev/null +++ b/x-pack/plugins/cloud/server/routes/fullstory.ts @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import path from 'path'; +import fs from 'fs/promises'; +import { createHash } from 'crypto'; +import { once } from 'lodash'; +import { HttpResources, HttpResponseOptions, PackageInfo } from '../../../../../src/core/server'; + +const MINUTE = 60; +const HOUR = 60 * MINUTE; +const DAY = 24 * HOUR; + +/** @internal exported for testing */ +export const FULLSTORY_LIBRARY_PATH = path.join(__dirname, '..', 'assets', 'fullstory_library.js'); + +/** @internal exported for testing */ +export const renderFullStoryLibraryFactory = (dist = true) => + once( + async (): Promise<{ + body: Buffer; + headers: HttpResponseOptions['headers']; + }> => { + const srcBuffer = await fs.readFile(FULLSTORY_LIBRARY_PATH); + const hash = createHash('sha1'); + hash.update(srcBuffer); + const hashDigest = hash.digest('hex'); + + return { + body: srcBuffer, + // In dist mode, return a long max-age, otherwise use etag + must-revalidate + headers: dist + ? { 'cache-control': `max-age=${DAY * 365}` } + : { 'cache-control': 'must-revalidate', etag: hashDigest }, + }; + } + ); + +export const registerFullstoryRoute = ({ + httpResources, + packageInfo, +}: { + httpResources: HttpResources; + packageInfo: Readonly; +}) => { + const renderFullStoryLibrary = renderFullStoryLibraryFactory(packageInfo.dist); + + /** + * Register a custom JS endpoint in order to acheive best caching possible with `max-age` similar to plugin bundles. + */ + httpResources.register( + { + // Use the build number in the URL path to leverage max-age caching on production builds + path: `/internal/cloud/${packageInfo.buildNum}/fullstory.js`, + validate: false, + options: { + authRequired: false, + }, + }, + async (context, req, res) => { + try { + return res.renderJs(await renderFullStoryLibrary()); + } catch (e) { + return res.customError({ + body: `Could not load FullStory library from disk due to error: ${e.toString()}`, + statusCode: 500, + }); + } + } + ); +}; diff --git a/x-pack/test/cloud_integration/config.ts b/x-pack/test/cloud_integration/config.ts new file mode 100644 index 0000000000000..a012dfd1ad34b --- /dev/null +++ b/x-pack/test/cloud_integration/config.ts @@ -0,0 +1,87 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { resolve } from 'path'; +import { FtrConfigProviderContext } from '@kbn/test'; +import { services } from '../functional/services'; +import { pageObjects } from '../functional/page_objects'; + +const FULLSTORY_ORG_ID = process.env.FULLSTORY_ORG_ID; +const FULLSTORY_API_KEY = process.env.FULLSTORY_API_KEY; +const RUN_FULLSTORY_TESTS = Boolean(FULLSTORY_ORG_ID && FULLSTORY_API_KEY); + +// the default export of config files must be a config provider +// that returns an object with the projects config values +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const kibanaCommonConfig = await readConfigFile( + require.resolve('../../../test/common/config.js') + ); + const kibanaFunctionalConfig = await readConfigFile( + require.resolve('../../../test/functional/config.js') + ); + + const kibanaPort = kibanaFunctionalConfig.get('servers.kibana.port'); + const idpPath = resolve(__dirname, './fixtures/saml/saml_provider/metadata.xml'); + const samlIdPPlugin = resolve(__dirname, './fixtures/saml/saml_provider'); + + return { + testFiles: [...(RUN_FULLSTORY_TESTS ? [resolve(__dirname, './tests/fullstory')] : [])], + + services, + pageObjects, + + servers: kibanaFunctionalConfig.get('servers'), + + esTestCluster: { + license: 'trial', + from: 'snapshot', + serverArgs: [ + 'xpack.security.authc.token.enabled=true', + 'xpack.security.authc.realms.saml.saml1.order=0', + `xpack.security.authc.realms.saml.saml1.idp.metadata.path=${idpPath}`, + 'xpack.security.authc.realms.saml.saml1.idp.entity_id=http://www.elastic.co/saml1', + `xpack.security.authc.realms.saml.saml1.sp.entity_id=http://localhost:${kibanaPort}`, + `xpack.security.authc.realms.saml.saml1.sp.logout=http://localhost:${kibanaPort}/logout`, + `xpack.security.authc.realms.saml.saml1.sp.acs=http://localhost:${kibanaPort}/api/security/saml/callback`, + 'xpack.security.authc.realms.saml.saml1.attributes.principal=http://saml.elastic-cloud.com/attributes/principal', + 'xpack.security.authc.realms.saml.saml1.attributes.groups=http://saml.elastic-cloud.com/attributes/roles', + ], + }, + + kbnTestServer: { + ...kibanaCommonConfig.get('kbnTestServer'), + serverArgs: [ + ...kibanaCommonConfig.get('kbnTestServer.serverArgs'), + `--plugin-path=${samlIdPPlugin}`, + '--server.uuid=5b2de169-2785-441b-ae8c-186a1936b17d', + '--xpack.security.encryptionKey="wuGNaIhoMpk5sO4UBxgr3NyW1sFcLgIf"', + '--xpack.security.authc.selector.enabled=false', + '--xpack.security.authc.providers.saml.saml1.order=0', + '--xpack.security.authc.providers.saml.saml1.realm=saml1', + '--xpack.security.authc.providers.basic.basic1.order=1', + ...(RUN_FULLSTORY_TESTS + ? [ + '--xpack.cloud.full_story.enabled=true', + `--xpack.cloud.full_story.org_id=${FULLSTORY_ORG_ID}`, + ] + : []), + ], + }, + uiSettings: { + defaults: { + 'accessibility:disableAnimations': true, + 'dateFormat:tz': 'UTC', + }, + }, + apps: kibanaFunctionalConfig.get('apps'), + screenshots: { directory: resolve(__dirname, 'screenshots') }, + + junit: { + reportName: 'Chrome X-Pack Cloud Integration Functional Tests (SAML)', + }, + }; +} diff --git a/x-pack/test/cloud_integration/constants.ts b/x-pack/test/cloud_integration/constants.ts new file mode 100644 index 0000000000000..95c5477fbe97b --- /dev/null +++ b/x-pack/test/cloud_integration/constants.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export const CLOUD_USER_ID = `1112244`; diff --git a/x-pack/test/cloud_integration/fixtures/saml/saml_provider/kibana.json b/x-pack/test/cloud_integration/fixtures/saml/saml_provider/kibana.json new file mode 100644 index 0000000000000..81ec23fc3d2f3 --- /dev/null +++ b/x-pack/test/cloud_integration/fixtures/saml/saml_provider/kibana.json @@ -0,0 +1,7 @@ +{ + "id": "samlProviderPlugin", + "version": "8.0.0", + "kibanaVersion": "kibana", + "server": true, + "ui": false +} diff --git a/x-pack/test/cloud_integration/fixtures/saml/saml_provider/metadata.xml b/x-pack/test/cloud_integration/fixtures/saml/saml_provider/metadata.xml new file mode 100644 index 0000000000000..19a6c13264144 --- /dev/null +++ b/x-pack/test/cloud_integration/fixtures/saml/saml_provider/metadata.xml @@ -0,0 +1,41 @@ + + + + + + + + MIIDOTCCAiGgAwIBAgIVANNWkg9lzNiLqNkMFhFKHcXyaZmqMA0GCSqGSIb3DQEB +CwUAMDQxMjAwBgNVBAMTKUVsYXN0aWMgQ2VydGlmaWNhdGUgVG9vbCBBdXRvZ2Vu +ZXJhdGVkIENBMCAXDTE5MTIyNzE3MDM0MloYDzIwNjkxMjE0MTcwMzQyWjARMQ8w +DQYDVQQDEwZraWJhbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCQ +wYYbQtbRBKJ4uNZc2+IgRU+7NNL21ZebQlEIMgK7jAqOMrsW2b5DATz41Fd+GQFU +FUYYjwo+PQj6sJHshOJo/gNb32HrydvMI7YPvevkszkuEGCfXxQ3Dw2RTACLgD0Q +OCkwHvn3TMf0loloV/ePGWaZDYZaXi3a5DdWi/HFFoJysgF0JV2f6XyKhJkGaEfJ +s9pWX269zH/XQvGNx4BEimJpYB8h4JnDYPFIiQdqj+sl2b+kS1hH9kL5gBAMXjFU +vcNnX+PmyTjyJrGo75k0ku+spBf1bMwuQt3uSmM+TQIXkvFDmS0DOVESrpA5EC1T +BUGRz6o/I88Xx4Mud771AgMBAAGjYzBhMB0GA1UdDgQWBBQLB1Eo23M3Ss8MsFaz +V+Twcb3PmDAfBgNVHSMEGDAWgBQa7SYOe8NGcF00EbwPHA91YCsHSTAUBgNVHREE +DTALgglsb2NhbGhvc3QwCQYDVR0TBAIwADANBgkqhkiG9w0BAQsFAAOCAQEAnEl/ +z5IElIjvkK4AgMPrNcRlvIGDt2orEik7b6Jsq6/RiJQ7cSsYTZf7xbqyxNsUOTxv ++frj47MEN448H2nRvUxH29YR3XygV5aEwADSAhwaQWn0QfWTCZbJTmSoNEDtDOzX +TGDlAoCD9s9Xz9S1JpxY4H+WWRZrBSDM6SC1c6CzuEeZRuScNAjYD5mh2v6fOlSy +b8xJWSg0AFlJPCa3ZsA2SKbNqI0uNfJTnkXRm88Z2NHcgtlADbOLKauWfCrpgsCk +cZgo6yAYkOM148h/8wGla1eX+iE1R72NUABGydu8MSQKvc0emWJkGsC1/KqPlf/O +eOUsdwn1yDKHRxDHyA== + + + + + + + + + + diff --git a/x-pack/test/cloud_integration/fixtures/saml/saml_provider/server/index.ts b/x-pack/test/cloud_integration/fixtures/saml/saml_provider/server/index.ts new file mode 100644 index 0000000000000..4ae669256d3a8 --- /dev/null +++ b/x-pack/test/cloud_integration/fixtures/saml/saml_provider/server/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { PluginInitializer } from '../../../../../../../src/core/server'; +import { initRoutes } from './init_routes'; + +export const plugin: PluginInitializer = () => ({ + setup: (core) => initRoutes(core), + start: () => {}, + stop: () => {}, +}); diff --git a/x-pack/test/cloud_integration/fixtures/saml/saml_provider/server/init_routes.ts b/x-pack/test/cloud_integration/fixtures/saml/saml_provider/server/init_routes.ts new file mode 100644 index 0000000000000..6bea9af2ed310 --- /dev/null +++ b/x-pack/test/cloud_integration/fixtures/saml/saml_provider/server/init_routes.ts @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { CoreSetup } from '../../../../../../../src/core/server'; +import { getSAMLResponse, getSAMLRequestId } from './saml_tools'; + +export function initRoutes(core: CoreSetup) { + const serverInfo = core.http.getServerInfo(); + core.http.resources.register( + { + path: '/saml_provider/login', + validate: false, + options: { authRequired: false }, + }, + async (context, request, response) => { + const samlResponse = await getSAMLResponse({ + inResponseTo: await getSAMLRequestId(request.url.href!), + destination: `${serverInfo.protocol}://${serverInfo.hostname}:${serverInfo.port}/api/security/saml/callback`, + }); + + return response.renderHtml({ + body: ` + + Kibana SAML Login + + + +
+ +
+ + `, + }); + } + ); + + core.http.resources.register( + { path: '/saml_provider/login/submit.js', validate: false, options: { authRequired: false } }, + (context, request, response) => { + return response.renderJs({ body: 'document.getElementById("loginForm").submit();' }); + } + ); + + core.http.resources.register( + { + path: '/saml_provider/logout', + validate: false, + options: { authRequired: false }, + }, + async (context, request, response) => { + return response.redirected({ headers: { location: '/logout?SAMLResponse=something' } }); + } + ); +} diff --git a/x-pack/test/cloud_integration/fixtures/saml/saml_provider/server/saml_tools.ts b/x-pack/test/cloud_integration/fixtures/saml/saml_provider/server/saml_tools.ts new file mode 100644 index 0000000000000..da902d332e6e7 --- /dev/null +++ b/x-pack/test/cloud_integration/fixtures/saml/saml_provider/server/saml_tools.ts @@ -0,0 +1,161 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import crypto from 'crypto'; +import fs from 'fs'; +import { stringify } from 'query-string'; +import url from 'url'; +import zlib from 'zlib'; +import { promisify } from 'util'; +import { parseString } from 'xml2js'; +import { SignedXml } from 'xml-crypto'; +import { KBN_KEY_PATH } from '@kbn/dev-utils'; +import { CLOUD_USER_ID } from '../../../../constants'; + +/** + * @file Defines a set of tools that allow us to parse and generate various SAML XML messages. + * The format of these XML messages is a minimum accepted by Elasticsearch and based on the format + * used by `Auth0` identity provider, `auth0/node-samlp` package and SAML 2.0 Specification: + * http://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf. + */ + +const inflateRawAsync = promisify(zlib.inflateRaw); +const deflateRawAsync = promisify(zlib.deflateRaw); +const parseStringAsync = promisify(parseString); + +const signingKey = fs.readFileSync(KBN_KEY_PATH); +const signatureAlgorithm = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'; + +export async function getSAMLRequestId(urlWithSAMLRequestId: string) { + const inflatedSAMLRequest = (await inflateRawAsync( + Buffer.from( + url.parse(urlWithSAMLRequestId, true /* parseQueryString */).query.SAMLRequest as string, + 'base64' + ) + )) as Buffer; + + const parsedSAMLRequest = (await parseStringAsync(inflatedSAMLRequest.toString())) as any; + return parsedSAMLRequest['saml2p:AuthnRequest'].$.ID; +} + +export async function getSAMLResponse({ + destination, + inResponseTo, + sessionIndex, + username = 'a@b.c', + issuer = 'http://www.elastic.co/saml1', +}: { + destination?: string; + inResponseTo?: string; + sessionIndex?: string; + username?: string; + issuer?: string; +} = {}) { + const issueInstant = new Date().toISOString(); + const notOnOrAfter = new Date(Date.now() + 3600 * 1000).toISOString(); + + const samlAssertionTemplateXML = ` + + ${issuer} + + a@b.c + + + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified + + + + + ${CLOUD_USER_ID} + + + superuser + + + + `; + + const signature = new SignedXml(); + signature.signatureAlgorithm = signatureAlgorithm; + signature.signingKey = signingKey; + + // Adds a reference to a `Assertion` xml element and an array of transform algorithms to be used during signing. + signature.addReference( + `//*[local-name(.)='Assertion']`, + [ + 'http://www.w3.org/2000/09/xmldsig#enveloped-signature', + 'http://www.w3.org/2001/10/xml-exc-c14n#', + ], + 'http://www.w3.org/2001/04/xmlenc#sha256' + ); + + signature.computeSignature(samlAssertionTemplateXML, { + location: { reference: `//*[local-name(.)='Issuer']`, action: 'after' }, + }); + + return Buffer.from( + ` + + ${issuer} + + + ${signature.getSignedXml()} + + ` + ).toString('base64'); +} + +export async function getLogoutRequest({ + destination, + sessionIndex, + issuer = 'http://www.elastic.co/saml1', +}: { + destination: string; + sessionIndex: string; + issuer?: string; +}) { + const issueInstant = new Date().toISOString(); + const logoutRequestTemplateXML = ` + + ${issuer} + a@b.c + ${sessionIndex} + + `; + + // HTTP-Redirect with deflate encoding: + // http://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf - section 3.4.4.1 + const deflatedLogoutRequest = (await deflateRawAsync( + Buffer.from(logoutRequestTemplateXML) + )) as Buffer; + + const queryStringParameters: Record = { + SAMLRequest: deflatedLogoutRequest.toString('base64'), + SigAlg: signatureAlgorithm, + }; + + const signer = crypto.createSign('RSA-SHA256'); + signer.update(stringify(queryStringParameters, { sort: false })); + queryStringParameters.Signature = signer.sign(signingKey.toString(), 'base64'); + + return queryStringParameters; +} diff --git a/x-pack/test/cloud_integration/ftr_provider_context.d.ts b/x-pack/test/cloud_integration/ftr_provider_context.d.ts new file mode 100644 index 0000000000000..66d4e37b795ca --- /dev/null +++ b/x-pack/test/cloud_integration/ftr_provider_context.d.ts @@ -0,0 +1,13 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { GenericFtrProviderContext } from '@kbn/test'; + +import { pageObjects } from '../functional/page_objects'; +import { services } from '../functional/services'; + +export type FtrProviderContext = GenericFtrProviderContext; diff --git a/x-pack/test/cloud_integration/tests/fullstory.ts b/x-pack/test/cloud_integration/tests/fullstory.ts new file mode 100644 index 0000000000000..1cdad719e94e5 --- /dev/null +++ b/x-pack/test/cloud_integration/tests/fullstory.ts @@ -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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import fetch from 'node-fetch'; +import { sha256 } from 'js-sha256'; +import { FtrProviderContext } from '../ftr_provider_context'; +import { CLOUD_USER_ID } from '../constants'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const browser = getService('browser'); + const find = getService('find'); + const PageObjects = getPageObjects(['common']); + + const delay = (ms: number) => new Promise((r) => setTimeout(r, ms)); + + describe('Cloud FullStory integration', function () { + before(async () => { + // Create role mapping so user gets superuser access + await getService('esSupertest') + .post('/_security/role_mapping/saml1') + .send({ roles: ['superuser'], enabled: true, rules: { field: { 'realm.name': 'saml1' } } }) + .expect(200); + }); + + it('initializes FullStory', async () => { + await PageObjects.common.navigateToApp('home'); + await find.byCssSelector('[data-test-subj="userMenuButton"]', 20000); + + // Check FullStory library loaded + // @ts-expect-error + expect(await browser.execute(() => typeof window.FSKibana === 'function')).to.eql(true); + }); + + it('records a FullStory session with the associated SAML user', async () => { + // Get session ID once fullstory has initialized + let sessionUrl: string | null = null; + let attempts = 0; + while (sessionUrl === null && attempts < 30) { + // @ts-expect-error + sessionUrl = await browser.execute(() => window.FSKibana.getCurrentSessionURL()); + attempts++; + await delay(1000); + } + expect(typeof sessionUrl).to.eql('string'); + sessionUrl = sessionUrl!.replace('%3A', ':'); // undo encoding so comparisons work with API response + + // Check that the session was recorded in the FS API for the given user based on their hashed ID + const hashedUserId = sha256(CLOUD_USER_ID); + const fsSessions = await fetch( + `https://www.fullstory.com/api/v1/sessions?uid=${hashedUserId}&limit=100`, + { + headers: { + 'content-type': 'application/json', + Authorization: `Basic ${process.env.FULLSTORY_API_KEY}`, + }, + } + ).then((r) => r.json()); + expect(fsSessions.find((s: any) => s.FsUrl === sessionUrl)).not.to.be(undefined); + }); + }); +} diff --git a/yarn.lock b/yarn.lock index 448c97ff82469..9d7569b6ab4f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17600,6 +17600,11 @@ js-search@^1.4.3: resolved "https://registry.yarnpkg.com/js-search/-/js-search-1.4.3.tgz#23a86d7e064ca53a473930edc48615b6b1c1954a" integrity sha512-Sny5pf00kX1sM1KzvUC9nGYWXOvBfy30rmvZWeRktpg+esQKedIXrXNee/I2CAnsouCyaTjitZpRflDACx4toA== +js-sha256@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" + integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA== + js-sha3@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" From 67d4c3184efc3c909ae0e9ca819f3a7429327195 Mon Sep 17 00:00:00 2001 From: Kuldeep M Date: Thu, 24 Jun 2021 20:10:22 +0100 Subject: [PATCH 14/25] [Workplace Search] source connection panel content vertical alignment (#103225) * fix 1786 source connection panel vertical alignment * Update x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configured_sources_list.tsx Co-authored-by: Constance Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Constance --- .../components/add_source/configured_sources_list.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configured_sources_list.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configured_sources_list.tsx index ac19043a30ca6..6da09acf45cbe 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configured_sources_list.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/configured_sources_list.tsx @@ -70,7 +70,12 @@ export const ConfiguredSourcesList: React.FC = ({ - + Date: Thu, 24 Jun 2021 20:12:52 +0100 Subject: [PATCH 15/25] [Logs UI] Log threshold rule performance improvements (#102650) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add optimisations for executor / chart previews Co-authored-by: Felix Stürmer --- .../alerting/logs/log_threshold/types.ts | 108 +++-- .../http_api/log_alerts/chart_preview_data.ts | 9 + .../criterion_preview_chart.tsx | 13 +- .../components/expression_editor/editor.tsx | 25 + .../log_threshold_chart_preview.ts | 54 ++- .../log_threshold_executor.test.ts | 455 ++++++++---------- .../log_threshold/log_threshold_executor.ts | 154 ++++-- 7 files changed, 483 insertions(+), 335 deletions(-) diff --git a/x-pack/plugins/infra/common/alerting/logs/log_threshold/types.ts b/x-pack/plugins/infra/common/alerting/logs/log_threshold/types.ts index f1e983fc34df8..6da0bb58e4e85 100644 --- a/x-pack/plugins/infra/common/alerting/logs/log_threshold/types.ts +++ b/x-pack/plugins/infra/common/alerting/logs/log_threshold/types.ts @@ -100,7 +100,7 @@ export enum AlertStates { ERROR, } -const ThresholdRT = rt.type({ +export const ThresholdRT = rt.type({ comparator: ComparatorRT, value: rt.number, }); @@ -240,31 +240,43 @@ const chartPreviewHistogramBucket = rt.type({ doc_count: rt.number, }); +const ChartPreviewBucketsRT = rt.partial({ + histogramBuckets: rt.type({ + buckets: rt.array(chartPreviewHistogramBucket), + }), +}); + // ES query responses // +const hitsRT = rt.type({ + total: rt.type({ + value: rt.number, + }), +}); + +const bucketFieldsRT = rt.type({ + key: rt.record(rt.string, rt.string), + doc_count: rt.number, +}); + +const afterKeyRT = rt.partial({ + after_key: rt.record(rt.string, rt.string), +}); + export const UngroupedSearchQueryResponseRT = rt.intersection([ commonSearchSuccessResponseFieldsRT, rt.intersection([ rt.type({ - hits: rt.type({ - total: rt.type({ - value: rt.number, - }), - }), + hits: hitsRT, }), - // Chart preview buckets rt.partial({ - aggregations: rt.type({ - histogramBuckets: rt.type({ - buckets: rt.array(chartPreviewHistogramBucket), - }), - }), + aggregations: ChartPreviewBucketsRT, }), ]), ]); export type UngroupedSearchQueryResponse = rt.TypeOf; -export const GroupedSearchQueryResponseRT = rt.intersection([ +export const UnoptimizedGroupedSearchQueryResponseRT = rt.intersection([ commonSearchSuccessResponseFieldsRT, rt.type({ aggregations: rt.type({ @@ -272,33 +284,73 @@ export const GroupedSearchQueryResponseRT = rt.intersection([ rt.type({ buckets: rt.array( rt.type({ - key: rt.record(rt.string, rt.string), - doc_count: rt.number, + ...bucketFieldsRT.props, filtered_results: rt.intersection([ rt.type({ doc_count: rt.number, }), - // Chart preview buckets - rt.partial({ - histogramBuckets: rt.type({ - buckets: rt.array(chartPreviewHistogramBucket), - }), - }), + ChartPreviewBucketsRT, ]), }) ), }), - rt.partial({ - after_key: rt.record(rt.string, rt.string), - }), + afterKeyRT, ]), }), - hits: rt.type({ - total: rt.type({ - value: rt.number, - }), + hits: hitsRT, + }), +]); + +export type UnoptimizedGroupedSearchQueryResponse = rt.TypeOf< + typeof UnoptimizedGroupedSearchQueryResponseRT +>; + +export const OptimizedGroupedSearchQueryResponseRT = rt.intersection([ + commonSearchSuccessResponseFieldsRT, + rt.type({ + aggregations: rt.type({ + groups: rt.intersection([ + rt.type({ + buckets: rt.array(rt.intersection([bucketFieldsRT, ChartPreviewBucketsRT])), + }), + afterKeyRT, + ]), }), + hits: hitsRT, }), ]); +export type OptimizedGroupedSearchQueryResponse = rt.TypeOf< + typeof OptimizedGroupedSearchQueryResponseRT +>; + +export const GroupedSearchQueryResponseRT = rt.union([ + UnoptimizedGroupedSearchQueryResponseRT, + OptimizedGroupedSearchQueryResponseRT, +]); + export type GroupedSearchQueryResponse = rt.TypeOf; + +export const isOptimizedGroupedSearchQueryResponse = ( + response: GroupedSearchQueryResponse['aggregations']['groups']['buckets'] +): response is OptimizedGroupedSearchQueryResponse['aggregations']['groups']['buckets'] => { + const result = response[0]; + return result && !result.hasOwnProperty('filtered_results'); +}; + +export const isOptimizableGroupedThreshold = ( + selectedComparator: AlertParams['count']['comparator'], + selectedValue?: AlertParams['count']['value'] +) => { + if (selectedComparator === Comparator.GT) { + return true; + } else if ( + typeof selectedValue === 'number' && + selectedComparator === Comparator.GT_OR_EQ && + selectedValue > 0 + ) { + return true; + } else { + return false; + } +}; diff --git a/x-pack/plugins/infra/common/http_api/log_alerts/chart_preview_data.ts b/x-pack/plugins/infra/common/http_api/log_alerts/chart_preview_data.ts index e6baca305508e..5f488dd532285 100644 --- a/x-pack/plugins/infra/common/http_api/log_alerts/chart_preview_data.ts +++ b/x-pack/plugins/infra/common/http_api/log_alerts/chart_preview_data.ts @@ -7,6 +7,7 @@ import * as rt from 'io-ts'; import { + ThresholdRT, countCriteriaRT, timeUnitRT, timeSizeRT, @@ -58,6 +59,14 @@ export type GetLogAlertsChartPreviewDataSuccessResponsePayload = rt.TypeOf< export const getLogAlertsChartPreviewDataAlertParamsSubsetRT: any = rt.intersection([ rt.type({ criteria: countCriteriaRT, + count: rt.intersection([ + rt.type({ + comparator: ThresholdRT.props.comparator, + }), + rt.partial({ + value: ThresholdRT.props.value, + }), + ]), timeUnit: timeUnitRT, timeSize: timeSizeRT, }), diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/criterion_preview_chart.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/criterion_preview_chart.tsx index 4e84cf0f9127c..4fa96ea6828d4 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/criterion_preview_chart.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/criterion_preview_chart.tsx @@ -68,6 +68,10 @@ export const CriterionPreview: React.FC = ({ const criteria = field && comparator && value ? [{ field, comparator, value }] : []; const params = { criteria, + count: { + comparator: alertParams.count.comparator, + value: alertParams.count.value, + }, timeSize: alertParams.timeSize, timeUnit: alertParams.timeUnit, groupBy: alertParams.groupBy, @@ -78,7 +82,14 @@ export const CriterionPreview: React.FC = ({ } catch (error) { return null; } - }, [alertParams.timeSize, alertParams.timeUnit, alertParams.groupBy, chartCriterion]); + }, [ + alertParams.timeSize, + alertParams.timeUnit, + alertParams.groupBy, + alertParams.count.comparator, + alertParams.count.value, + chartCriterion, + ]); // Check for the existence of properties that are necessary for a meaningful chart. if (chartAlertParams === null || chartAlertParams.criteria.length === 0) return null; diff --git a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx index ef533f63dc175..4eb0f3e8645cf 100644 --- a/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx +++ b/x-pack/plugins/infra/public/alerting/log_threshold/components/expression_editor/editor.tsx @@ -23,6 +23,7 @@ import { PartialRatioAlertParams, ThresholdType, timeUnitRT, + isOptimizableGroupedThreshold, } from '../../../../../common/alerting/logs/log_threshold/types'; import { decodeOrThrow } from '../../../../../common/runtime_types'; import { ObjectEntries } from '../../../../../common/utility_types'; @@ -255,6 +256,15 @@ export const Editor: React.FC< setHasSetDefaults(true); }); + const shouldShowGroupByOptimizationWarning = useMemo(() => { + const hasSetGroupBy = alertParams.groupBy && alertParams.groupBy.length > 0; + return ( + hasSetGroupBy && + alertParams.count && + !isOptimizableGroupedThreshold(alertParams.count.comparator, alertParams.count.value) + ); + }, [alertParams]); + // Wait until the alert param defaults have been set if (!hasSetDefaults) return null; @@ -299,6 +309,21 @@ export const Editor: React.FC< {alertParams.criteria && isRatioAlert(alertParams.criteria) && criteriaComponent} + {shouldShowGroupByOptimizationWarning && ( + <> + + + {i18n.translate('xpack.infra.logs.alertFlyout.groupByOptimizationWarning', { + defaultMessage: + 'When setting a "group by" we highly recommend using the "{comparator}" comparator for your threshold. This can lead to significant performance improvements.', + values: { + comparator: Comparator.GT, + }, + })} + + + )} + ); diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_chart_preview.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_chart_preview.ts index 321273c656216..7bf2cb5ea3394 100644 --- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_chart_preview.ts +++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_chart_preview.ts @@ -23,6 +23,7 @@ import { UngroupedSearchQueryResponse, GroupedSearchQueryResponse, GroupedSearchQueryResponseRT, + isOptimizedGroupedSearchQueryResponse, } from '../../../../common/alerting/logs/log_threshold/types'; import { decodeOrThrow } from '../../../../common/runtime_types'; import { ResolvedLogSourceConfiguration } from '../../../../common/log_sources'; @@ -97,10 +98,19 @@ const addHistogramAggregationToQuery = ( }; if (isGrouped) { - query.body.aggregations.groups.aggregations.filtered_results = { - ...query.body.aggregations.groups.aggregations.filtered_results, - aggregations: histogramAggregation, - }; + const isOptimizedQuery = !query.body.aggregations.groups.aggregations?.filtered_results; + + if (isOptimizedQuery) { + query.body.aggregations.groups.aggregations = { + ...query.body.aggregations.groups.aggregations, + ...histogramAggregation, + }; + } else { + query.body.aggregations.groups.aggregations.filtered_results = { + ...query.body.aggregations.groups.aggregations.filtered_results, + aggregations: histogramAggregation, + }; + } } else { query.body = { ...query.body, @@ -151,18 +161,34 @@ const getGroupedResults = async ( const processGroupedResults = ( results: GroupedSearchQueryResponse['aggregations']['groups']['buckets'] ): Series => { - return results.reduce((series, group) => { - if (!group.filtered_results.histogramBuckets) return series; - const groupName = Object.values(group.key).join(', '); - const points = group.filtered_results.histogramBuckets.buckets.reduce( - (pointsAcc, bucket) => { + const getGroupName = ( + key: GroupedSearchQueryResponse['aggregations']['groups']['buckets'][0]['key'] + ) => Object.values(key).join(', '); + + if (isOptimizedGroupedSearchQueryResponse(results)) { + return results.reduce((series, group) => { + if (!group.histogramBuckets) return series; + const groupName = getGroupName(group.key); + const points = group.histogramBuckets.buckets.reduce((pointsAcc, bucket) => { const { key, doc_count: count } = bucket; return [...pointsAcc, { timestamp: key, value: count }]; - }, - [] - ); - return [...series, { id: groupName, points }]; - }, []); + }, []); + return [...series, { id: groupName, points }]; + }, []); + } else { + return results.reduce((series, group) => { + if (!group.filtered_results.histogramBuckets) return series; + const groupName = getGroupName(group.key); + const points = group.filtered_results.histogramBuckets.buckets.reduce( + (pointsAcc, bucket) => { + const { key, doc_count: count } = bucket; + return [...pointsAcc, { timestamp: key, value: count }]; + }, + [] + ); + return [...series, { id: groupName, points }]; + }, []); + } }; const processUngroupedResults = (results: UngroupedSearchQueryResponse): Series => { diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts index ffabd7ba65f03..55c66f0aabbfb 100644 --- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts +++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts @@ -58,6 +58,74 @@ const negativeCriteria: Criterion[] = [ { ...textField, comparator: Comparator.NOT_MATCH_PHRASE }, ]; +const expectedPositiveFilterClauses = [ + { + range: { + numericField: { + gt: 10, + }, + }, + }, + { + range: { + numericField: { + gte: 10, + }, + }, + }, + { + range: { + numericField: { + lt: 10, + }, + }, + }, + { + range: { + numericField: { + lte: 10, + }, + }, + }, + { + term: { + keywordField: { + value: 'error', + }, + }, + }, + { + match: { + textField: 'Something went wrong', + }, + }, + { + match_phrase: { + textField: 'Something went wrong', + }, + }, +]; + +const expectedNegativeFilterClauses = [ + { + term: { + keywordField: { + value: 'error', + }, + }, + }, + { + match: { + textField: 'Something went wrong', + }, + }, + { + match_phrase: { + textField: 'Something went wrong', + }, + }, +]; + const baseAlertParams: Pick = { count: { comparator: Comparator.GT, @@ -102,53 +170,7 @@ describe('Log threshold executor', () => { criteria: positiveCriteria, }; const filters = buildFiltersFromCriteria(alertParams, TIMESTAMP_FIELD); - expect(filters.mustFilters).toEqual([ - { - range: { - numericField: { - gt: 10, - }, - }, - }, - { - range: { - numericField: { - gte: 10, - }, - }, - }, - { - range: { - numericField: { - lt: 10, - }, - }, - }, - { - range: { - numericField: { - lte: 10, - }, - }, - }, - { - term: { - keywordField: { - value: 'error', - }, - }, - }, - { - match: { - textField: 'Something went wrong', - }, - }, - { - match_phrase: { - textField: 'Something went wrong', - }, - }, - ]); + expect(filters.mustFilters).toEqual(expectedPositiveFilterClauses); }); test('Handles negative criteria', () => { @@ -158,25 +180,7 @@ describe('Log threshold executor', () => { }; const filters = buildFiltersFromCriteria(alertParams, TIMESTAMP_FIELD); - expect(filters.mustNotFilters).toEqual([ - { - term: { - keywordField: { - value: 'error', - }, - }, - }, - { - match: { - textField: 'Something went wrong', - }, - }, - { - match_phrase: { - textField: 'Something went wrong', - }, - }, - ]); + expect(filters.mustNotFilters).toEqual(expectedNegativeFilterClauses); }); test('Handles time range', () => { @@ -194,7 +198,7 @@ describe('Log threshold executor', () => { describe('ES queries', () => { describe('Query generation', () => { - test('Correctly generates ungrouped queries', () => { + it('Correctly generates ungrouped queries', () => { const alertParams: AlertParams = { ...baseAlertParams, criteria: [...positiveCriteria, ...negativeCriteria], @@ -223,71 +227,9 @@ describe('Log threshold executor', () => { }, }, }, - { - range: { - numericField: { - gt: 10, - }, - }, - }, - { - range: { - numericField: { - gte: 10, - }, - }, - }, - { - range: { - numericField: { - lt: 10, - }, - }, - }, - { - range: { - numericField: { - lte: 10, - }, - }, - }, - { - term: { - keywordField: { - value: 'error', - }, - }, - }, - { - match: { - textField: 'Something went wrong', - }, - }, - { - match_phrase: { - textField: 'Something went wrong', - }, - }, - ], - must_not: [ - { - term: { - keywordField: { - value: 'error', - }, - }, - }, - { - match: { - textField: 'Something went wrong', - }, - }, - { - match_phrase: { - textField: 'Something went wrong', - }, - }, + ...expectedPositiveFilterClauses, ], + must_not: [...expectedNegativeFilterClauses], }, }, runtime_mappings: { @@ -304,148 +246,159 @@ describe('Log threshold executor', () => { }); }); - test('Correctly generates grouped queries', () => { - const alertParams: AlertParams = { - ...baseAlertParams, - groupBy: ['host.name'], - criteria: [...positiveCriteria, ...negativeCriteria], - }; - const query = getGroupedESQuery( - alertParams, - TIMESTAMP_FIELD, - FILEBEAT_INDEX, - runtimeMappings - ); - expect(query).toEqual({ - index: 'filebeat-*', - allow_no_indices: true, - ignore_unavailable: true, - body: { - query: { - bool: { - filter: [ - { - range: { - '@timestamp': { - gte: expect.any(Number), - lte: expect.any(Number), - format: 'epoch_millis', + describe('Correctly generates grouped queries', () => { + it('When using an optimizable threshold comparator', () => { + const alertParams: AlertParams = { + ...baseAlertParams, + groupBy: ['host.name'], + criteria: [...positiveCriteria, ...negativeCriteria], + }; + const query = getGroupedESQuery( + alertParams, + TIMESTAMP_FIELD, + FILEBEAT_INDEX, + runtimeMappings + ); + + expect(query).toEqual({ + index: 'filebeat-*', + allow_no_indices: true, + ignore_unavailable: true, + body: { + query: { + bool: { + filter: [ + { + range: { + '@timestamp': { + gte: expect.any(Number), + lte: expect.any(Number), + format: 'epoch_millis', + }, }, }, + ...expectedPositiveFilterClauses, + ], + must_not: [...expectedNegativeFilterClauses], + }, + }, + aggregations: { + groups: { + composite: { + size: 2000, + sources: [ + { + 'group-0-host.name': { + terms: { + field: 'host.name', + }, + }, + }, + ], }, - ], + }, + }, + runtime_mappings: { + runtime_field: { + type: 'keyword', + script: { + lang: 'painless', + source: 'emit("a runtime value")', + }, + }, }, + size: 0, }, - aggregations: { - groups: { - composite: { - size: 40, - sources: [ + }); + }); + + it('When not using an optimizable threshold comparator', () => { + const alertParams: AlertParams = { + ...baseAlertParams, + count: { + ...baseAlertParams.count, + comparator: Comparator.LT, + }, + groupBy: ['host.name'], + criteria: [...positiveCriteria, ...negativeCriteria], + }; + + const query = getGroupedESQuery( + alertParams, + TIMESTAMP_FIELD, + FILEBEAT_INDEX, + runtimeMappings + ); + + expect(query).toEqual({ + index: 'filebeat-*', + allow_no_indices: true, + ignore_unavailable: true, + body: { + query: { + bool: { + filter: [ { - 'group-0-host.name': { - terms: { - field: 'host.name', + range: { + '@timestamp': { + gte: expect.any(Number), + lte: expect.any(Number), + format: 'epoch_millis', }, }, }, ], }, - aggregations: { - filtered_results: { - filter: { - bool: { - filter: [ - { - range: { - '@timestamp': { - gte: expect.any(Number), - lte: expect.any(Number), - format: 'epoch_millis', - }, - }, - }, - { - range: { - numericField: { - gt: 10, - }, - }, - }, - { - range: { - numericField: { - gte: 10, - }, - }, - }, - { - range: { - numericField: { - lt: 10, - }, - }, - }, - { - range: { - numericField: { - lte: 10, - }, - }, - }, - { - term: { - keywordField: { - value: 'error', - }, - }, - }, - { - match: { - textField: 'Something went wrong', - }, - }, - { - match_phrase: { - textField: 'Something went wrong', - }, + }, + aggregations: { + groups: { + composite: { + size: 2000, + sources: [ + { + 'group-0-host.name': { + terms: { + field: 'host.name', }, - ], - must_not: [ - { - term: { - keywordField: { - value: 'error', + }, + }, + ], + }, + aggregations: { + filtered_results: { + filter: { + bool: { + filter: [ + { + range: { + '@timestamp': { + gte: expect.any(Number), + lte: expect.any(Number), + format: 'epoch_millis', + }, }, }, - }, - { - match: { - textField: 'Something went wrong', - }, - }, - { - match_phrase: { - textField: 'Something went wrong', - }, - }, - ], + ...expectedPositiveFilterClauses, + ], + must_not: [...expectedNegativeFilterClauses], + }, }, }, }, }, }, - }, - runtime_mappings: { - runtime_field: { - type: 'keyword', - script: { - lang: 'painless', - source: 'emit("a runtime value")', + runtime_mappings: { + runtime_field: { + type: 'keyword', + script: { + lang: 'painless', + source: 'emit("a runtime value")', + }, }, }, + size: 0, }, - size: 0, - }, + }); }); }); }); diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts index a537801202217..f9d0b5575abfc 100644 --- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts @@ -36,6 +36,8 @@ import { CountCriteria, CountAlertParams, RatioAlertParams, + isOptimizedGroupedSearchQueryResponse, + isOptimizableGroupedThreshold, } from '../../../../common/alerting/logs/log_threshold/types'; import { InfraBackendLibs } from '../../infra_types'; import { getIntervalInSeconds } from '../../../utils/get_interval_in_seconds'; @@ -57,7 +59,7 @@ type LogThresholdAlertExecutorOptions = AlertExecutorOptions< LogThresholdActionGroups >; -const COMPOSITE_GROUP_SIZE = 40; +const COMPOSITE_GROUP_SIZE = 2000; const checkValueAgainstComparatorMap: { [key: string]: (a: number, b: number) => boolean; @@ -68,6 +70,10 @@ const checkValueAgainstComparatorMap: { [Comparator.LT_OR_EQ]: (a: number, b: number) => a <= b, }; +// The executor execution roughly follows a pattern of: +// ES Query generation -> fetching of results -> processing of results. +// With forks for group_by vs ungrouped, and ratio vs non-ratio. + export const createLogThresholdExecutor = (libs: InfraBackendLibs) => async function ({ services, params }: LogThresholdAlertExecutorOptions) { const { alertInstanceFactory, savedObjectsClient, scopedClusterClient } = services; @@ -277,11 +283,26 @@ type ReducedGroupByResults = ReducedGroupByResult[]; const getReducedGroupByResults = ( results: GroupedSearchQueryResponse['aggregations']['groups']['buckets'] ): ReducedGroupByResults => { - return results.reduce((acc, groupBucket) => { - const groupName = Object.values(groupBucket.key).join(', '); - const groupResult = { name: groupName, documentCount: groupBucket.filtered_results.doc_count }; - return [...acc, groupResult]; - }, []); + const getGroupName = ( + key: GroupedSearchQueryResponse['aggregations']['groups']['buckets'][0]['key'] + ) => Object.values(key).join(', '); + + if (isOptimizedGroupedSearchQueryResponse(results)) { + return results.reduce((acc, groupBucket) => { + const groupName = getGroupName(groupBucket.key); + const groupResult = { name: groupName, documentCount: groupBucket.doc_count }; + return [...acc, groupResult]; + }, []); + } else { + return results.reduce((acc, groupBucket) => { + const groupName = getGroupName(groupBucket.key); + const groupResult = { + name: groupName, + documentCount: groupBucket.filtered_results.doc_count, + }; + return [...acc, groupResult]; + }, []); + } }; export const processGroupByResults = ( @@ -430,12 +451,29 @@ export const buildFiltersFromCriteria = ( }; export const getGroupedESQuery = ( - params: Pick & { criteria: CountCriteria }, + params: Pick & { + criteria: CountCriteria; + count: { + comparator: AlertParams['count']['comparator']; + value?: AlertParams['count']['value']; + }; + }, timestampField: string, index: string, runtimeMappings: estypes.MappingRuntimeFields ): estypes.SearchRequest | undefined => { - const { groupBy } = params; + // IMPORTANT: + // For the group by scenario we need to account for users utilizing "less than" configurations + // to attempt to match on "0", e.g. something has stopped reporting. We need to cast a wider net for these + // configurations to try and capture more documents, so that the filtering doesn't make the group "disappear". + // Due to this there are two forks in the group by code, one where we can optimize the filtering early, and one where + // it is an inner aggregation. "Less than" configurations with high cardinality group by fields can cause severe performance + // problems. + + const { + groupBy, + count: { comparator, value }, + } = params; if (!groupBy || !groupBy.length) { return; @@ -446,47 +484,81 @@ export const getGroupedESQuery = ( timestampField ); - const aggregations = { - groups: { - composite: { - size: COMPOSITE_GROUP_SIZE, - sources: groupBy.map((field, groupIndex) => ({ - [`group-${groupIndex}-${field}`]: { - terms: { field }, - }, - })), + if (isOptimizableGroupedThreshold(comparator, value)) { + const aggregations = { + groups: { + composite: { + size: COMPOSITE_GROUP_SIZE, + sources: groupBy.map((field, groupIndex) => ({ + [`group-${groupIndex}-${field}`]: { + terms: { field }, + }, + })), + }, }, - aggregations: { - filtered_results: { - filter: { - bool: { - // Scope the inner filtering back to the unpadded range - filter: [rangeFilter, ...mustFilters], - ...(mustNotFilters.length > 0 && { must_not: mustNotFilters }), + }; + + const body: estypes.SearchRequest['body'] = { + query: { + bool: { + filter: [rangeFilter, ...mustFilters], + ...(mustNotFilters.length > 0 && { must_not: mustNotFilters }), + }, + }, + aggregations, + runtime_mappings: runtimeMappings, + size: 0, + }; + + return { + index, + allow_no_indices: true, + ignore_unavailable: true, + body, + }; + } else { + const aggregations = { + groups: { + composite: { + size: COMPOSITE_GROUP_SIZE, + sources: groupBy.map((field, groupIndex) => ({ + [`group-${groupIndex}-${field}`]: { + terms: { field }, + }, + })), + }, + aggregations: { + filtered_results: { + filter: { + bool: { + // Scope the inner filtering back to the unpadded range + filter: [rangeFilter, ...mustFilters], + ...(mustNotFilters.length > 0 && { must_not: mustNotFilters }), + }, }, }, }, }, - }, - }; + }; - const body: estypes.SearchRequest['body'] = { - query: { - bool: { - filter: [groupedRangeFilter], + const body: estypes.SearchRequest['body'] = { + query: { + bool: { + filter: [groupedRangeFilter], + }, }, - }, - aggregations, - runtime_mappings: runtimeMappings, - size: 0, - }; + aggregations, + runtime_mappings: runtimeMappings, + size: 0, + }; - return { - index, - allow_no_indices: true, - ignore_unavailable: true, - body, - }; + return { + index, + allow_no_indices: true, + ignore_unavailable: true, + body, + }; + } }; export const getUngroupedESQuery = ( From fb3e8f4498680d1d3bc52990572e6d0f0c00c7c2 Mon Sep 17 00:00:00 2001 From: Constance Date: Thu, 24 Jun 2021 12:43:26 -0700 Subject: [PATCH 16/25] [Enterprise Search] Product 404 polish pass (#103198) * Refactor NotFound component - shared NotFound becomes NotFoundPrompt - returns only an EuiEmptyPrompt, and individual products/plugins are in charge of their own layout, rather than NotFound doing a bunch of arduous switch handling (also closer to how errorConnecting is a component set per-plugin) - This is both due to the recent page template refactor and the fact that WS has extra complex logic of needing to switch between its kibana layout and personal dashboard layout - logos are still hosted in shared/ since they need extra custom CSS to work correctly sizing wise and in dark mode. I renamed its folder from `assets`->`logos` for extra clarity * [AS] Update current AS routers using NotFound + update EngineRouter to use NotFound * [WS] Update app router - Handle errorConnecting at the topmost level, instead of in WorkplaceSearchConfigured (to simplify various logic/expectations & match App Search) - Simplify isOrganization check to use `useRouteMatch` instead of a regex - Use new NotFound component - Add NotFound component for the personal dashboard router * [WS] Improve Source 404 UX - Add NotFound to SourceRouter + add breadcrumbs for organization views - When an actual source ID 404s, fix blanket redirect to a dashboard aware redirect - personal dashboard 404s should send the user back to personal sources, not organization sources + add a flash message error (similar to how App Search behaves for engine 404s) + harden error status checks (gracefully allow for non-http errors to fall back flashAPIErrors * [WS] Improve Settings 404 UX - This was the only remaining WS route I found that either did not have a 404 or a fallback to some overview page, so I tweaked the redirect order for a graceful redirect (vs a blank page) * Fix settings router test * Move away from custom product logos to OOTB Enterprise Search logo Keeping it simple, etc. RIP in peace fancy logos * [PR feedback] toContain over stringContaining --- .../components/analytics/analytics_router.tsx | 8 +- .../components/engine/engine_router.tsx | 6 +- .../components/not_found/index.ts} | 16 +-- .../components/not_found/not_found.test.tsx | 38 ++++++ .../components/not_found/not_found.tsx | 23 ++++ .../applications/app_search/index.test.tsx | 17 +-- .../public/applications/app_search/index.tsx | 13 +- .../not_found/assets/app_search_logo.tsx | 33 ----- .../assets/workplace_search_logo.tsx | 39 ------ .../applications/shared/not_found/index.ts | 2 +- .../shared/not_found/not_found.test.tsx | 70 ----------- .../shared/not_found/not_found.tsx | 117 ------------------ .../not_found/not_found_prompt.test.tsx | 51 ++++++++ .../shared/not_found/not_found_prompt.tsx | 65 ++++++++++ .../workplace_search/index.test.tsx | 32 ++--- .../applications/workplace_search/index.tsx | 38 +++--- .../content_sources/source_logic.test.ts | 80 ++++++------ .../views/content_sources/source_logic.ts | 12 +- .../content_sources/source_router.test.tsx | 4 +- .../views/content_sources/source_router.tsx | 6 +- .../workplace_search/views/not_found/index.ts | 8 ++ .../views/not_found/not_found.test.tsx | 52 ++++++++ .../views/not_found/not_found.tsx | 33 +++++ .../views/settings/settings_router.test.tsx | 4 +- .../views/settings/settings_router.tsx | 5 +- 25 files changed, 378 insertions(+), 394 deletions(-) rename x-pack/plugins/enterprise_search/public/applications/{shared/not_found/assets/logo.scss => app_search/components/not_found/index.ts} (53%) create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/not_found/not_found.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/app_search/components/not_found/not_found.tsx delete mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/not_found/assets/app_search_logo.tsx delete mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/not_found/assets/workplace_search_logo.tsx delete mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx delete mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found_prompt.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found_prompt.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/not_found/index.ts create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/not_found/not_found.test.tsx create mode 100644 x-pack/plugins/enterprise_search/public/applications/workplace_search/views/not_found/not_found.tsx diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.tsx index d56fe949431c3..2ed06d68301c9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/analytics_router.tsx @@ -8,8 +8,6 @@ import React from 'react'; import { Route, Switch, Redirect } from 'react-router-dom'; -import { APP_SEARCH_PLUGIN } from '../../../../../common/constants'; -import { NotFound } from '../../../shared/not_found'; import { ENGINE_ANALYTICS_PATH, ENGINE_ANALYTICS_TOP_QUERIES_PATH, @@ -21,6 +19,7 @@ import { ENGINE_ANALYTICS_QUERY_DETAIL_PATH, } from '../../routes'; import { generateEnginePath, getEngineBreadcrumbs } from '../engine'; +import { NotFound } from '../not_found'; import { ANALYTICS_TITLE } from './constants'; import { @@ -61,10 +60,7 @@ export const AnalyticsRouter: React.FC = () => { - + ); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.tsx index da8dd8467bb61..2d1bd32a0fff5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine/engine_router.tsx @@ -38,6 +38,7 @@ import { CurationsRouter } from '../curations'; import { DocumentDetail, Documents } from '../documents'; import { EngineOverview } from '../engine_overview'; import { AppSearchPageTemplate } from '../layout'; +import { NotFound } from '../not_found'; import { RelevanceTuning } from '../relevance_tuning'; import { ResultSettings } from '../result_settings'; import { SchemaRouter } from '../schema'; @@ -45,7 +46,7 @@ import { SearchUI } from '../search_ui'; import { SourceEngines } from '../source_engines'; import { Synonyms } from '../synonyms'; -import { EngineLogic } from './'; +import { EngineLogic, getEngineBreadcrumbs } from './'; export const EngineRouter: React.FC = () => { const { @@ -159,6 +160,9 @@ export const EngineRouter: React.FC = () => { )} + + + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/assets/logo.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/not_found/index.ts similarity index 53% rename from x-pack/plugins/enterprise_search/public/applications/shared/not_found/assets/logo.scss rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/not_found/index.ts index b157f55cbba68..482c1a58faa9c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/assets/logo.scss +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/not_found/index.ts @@ -5,18 +5,4 @@ * 2.0. */ -.logo404 { - width: $euiSize * 8; - height: $euiSize * 8; - - fill: $euiColorEmptyShade; - stroke: $euiColorLightShade; - - &__light { - fill: $euiColorLightShade; - } - - &__dark { - fill: $euiColorMediumShade; - } -} +export { NotFound } from './not_found'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/not_found/not_found.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/not_found/not_found.test.tsx new file mode 100644 index 0000000000000..6fed726eb5e0b --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/not_found/not_found.test.tsx @@ -0,0 +1,38 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { NotFoundPrompt } from '../../../shared/not_found'; +import { SendAppSearchTelemetry } from '../../../shared/telemetry'; +import { AppSearchPageTemplate } from '../layout'; + +import { NotFound } from './'; + +describe('NotFound', () => { + const wrapper = shallow(); + + it('renders the shared not found prompt', () => { + expect(wrapper.find(NotFoundPrompt)).toHaveLength(1); + }); + + it('renders a telemetry error event', () => { + expect(wrapper.find(SendAppSearchTelemetry).prop('action')).toEqual('error'); + }); + + it('passes optional preceding page chrome', () => { + wrapper.setProps({ pageChrome: ['Engines', 'some-engine'] }); + + expect(wrapper.find(AppSearchPageTemplate).prop('pageChrome')).toEqual([ + 'Engines', + 'some-engine', + '404', + ]); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/not_found/not_found.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/not_found/not_found.tsx new file mode 100644 index 0000000000000..f6165fa192d57 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/not_found/not_found.tsx @@ -0,0 +1,23 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { APP_SEARCH_PLUGIN } from '../../../../../common/constants'; +import { PageTemplateProps } from '../../../shared/layout'; +import { NotFoundPrompt } from '../../../shared/not_found'; +import { SendAppSearchTelemetry } from '../../../shared/telemetry'; +import { AppSearchPageTemplate } from '../layout'; + +export const NotFound: React.FC = ({ pageChrome = [] }) => { + return ( + + + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx index 00acea945177a..46596cc5d6765 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/index.test.tsx @@ -17,7 +17,7 @@ import { Redirect } from 'react-router-dom'; import { shallow, ShallowWrapper } from 'enzyme'; -import { Layout, SideNav, SideNavLink } from '../shared/layout'; +import { SideNav, SideNavLink } from '../shared/layout'; import { rerender } from '../test_helpers'; @@ -83,13 +83,6 @@ describe('AppSearchConfigured', () => { wrapper = shallow(); }); - it('renders with layout', () => { - expect(wrapper.find(Layout)).toHaveLength(1); - expect(wrapper.find(Layout).prop('readOnlyMode')).toBeFalsy(); - expect(wrapper.find(EnginesOverview)).toHaveLength(1); - expect(wrapper.find(EngineRouter)).toHaveLength(1); - }); - it('renders header actions', () => { expect(renderHeaderActions).toHaveBeenCalled(); }); @@ -98,11 +91,9 @@ describe('AppSearchConfigured', () => { expect(AppLogic).toHaveBeenCalledWith(DEFAULT_INITIAL_APP_DATA); }); - it('passes readOnlyMode state', () => { - setMockValues({ myRole: {}, readOnlyMode: true }); - rerender(wrapper); - - expect(wrapper.find(Layout).first().prop('readOnlyMode')).toEqual(true); + it('renders engine routes', () => { + expect(wrapper.find(EnginesOverview)).toHaveLength(1); + expect(wrapper.find(EngineRouter)).toHaveLength(1); }); describe('routes with ability checks', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx index d7ddad5683f38..6d049b2015487 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/index.tsx @@ -14,8 +14,7 @@ import { APP_SEARCH_PLUGIN } from '../../../common/constants'; import { InitialAppData } from '../../../common/types'; import { HttpLogic } from '../shared/http'; import { KibanaLogic } from '../shared/kibana'; -import { Layout, SideNav, SideNavLink } from '../shared/layout'; -import { NotFound } from '../shared/not_found'; +import { SideNav, SideNavLink } from '../shared/layout'; import { ROLE_MAPPINGS_TITLE } from '../shared/role_mapping/constants'; @@ -28,6 +27,7 @@ import { ErrorConnecting } from './components/error_connecting'; import { KibanaHeaderActions } from './components/layout'; import { Library } from './components/library'; import { MetaEngineCreation } from './components/meta_engine_creation'; +import { NotFound } from './components/not_found'; import { RoleMappings } from './components/role_mappings'; import { Settings, SETTINGS_TITLE } from './components/settings'; import { SetupGuide } from './components/setup_guide'; @@ -85,7 +85,6 @@ export const AppSearchConfigured: React.FC> = (props) = }, } = useValues(AppLogic(props)); const { renderHeaderActions } = useValues(KibanaLogic); - const { readOnlyMode } = useValues(HttpLogic); useEffect(() => { renderHeaderActions(KibanaHeaderActions); @@ -133,13 +132,7 @@ export const AppSearchConfigured: React.FC> = (props) = )} - } readOnlyMode={readOnlyMode}> - - - - - - + ); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/assets/app_search_logo.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/assets/app_search_logo.tsx deleted file mode 100644 index 8eb2059afd3ed..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/assets/app_search_logo.tsx +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -export const AppSearchLogo: React.FC = () => ( - -); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/assets/workplace_search_logo.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/assets/workplace_search_logo.tsx deleted file mode 100644 index df5b1a1118c41..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/assets/workplace_search_logo.tsx +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -export const WorkplaceSearchLogo: React.FC = () => ( - -); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/index.ts index 482c1a58faa9c..8be374d549952 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export { NotFound } from './not_found'; +export { NotFoundPrompt } from './not_found_prompt'; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx deleted file mode 100644 index 1561224a26e42..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.test.tsx +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { setMockValues } from '../../__mocks__/kea_logic'; - -import React from 'react'; - -import { shallow } from 'enzyme'; - -import { EuiButton as EuiButtonExternal, EuiEmptyPrompt } from '@elastic/eui'; - -import { APP_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN } from '../../../../common/constants'; -import { SetAppSearchChrome } from '../kibana_chrome'; - -import { AppSearchLogo } from './assets/app_search_logo'; -import { WorkplaceSearchLogo } from './assets/workplace_search_logo'; - -import { NotFound } from './'; - -describe('NotFound', () => { - it('renders an App Search 404 view', () => { - const wrapper = shallow(); - const prompt = wrapper.find(EuiEmptyPrompt).dive().shallow(); - - expect(prompt.find('h2').text()).toEqual('404 error'); - expect(prompt.find(EuiButtonExternal).prop('href')).toEqual(APP_SEARCH_PLUGIN.SUPPORT_URL); - - const logo = prompt.find(AppSearchLogo).dive().shallow(); - expect(logo.type()).toEqual('svg'); - }); - - it('renders a Workplace Search 404 view', () => { - const wrapper = shallow(); - const prompt = wrapper.find(EuiEmptyPrompt).dive().shallow(); - - expect(prompt.find('h2').text()).toEqual('404 error'); - expect(prompt.find(EuiButtonExternal).prop('href')).toEqual( - WORKPLACE_SEARCH_PLUGIN.SUPPORT_URL - ); - - const logo = prompt.find(WorkplaceSearchLogo).dive().shallow(); - expect(logo.type()).toEqual('svg'); - }); - - it('changes the support URL if the user has a gold+ license', () => { - setMockValues({ hasGoldLicense: true }); - const wrapper = shallow(); - const prompt = wrapper.find(EuiEmptyPrompt).dive().shallow(); - - expect(prompt.find(EuiButtonExternal).prop('href')).toEqual('https://support.elastic.co'); - }); - - it('passes down optional custom breadcrumbs', () => { - const wrapper = shallow( - - ); - - expect(wrapper.find(SetAppSearchChrome).prop('trail')).toEqual(['Hello', 'World']); - }); - - it('does not render anything without a valid product', () => { - const wrapper = shallow(); - - expect(wrapper.isEmptyRender()).toBe(true); - }); -}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.tsx deleted file mode 100644 index f288961b72de4..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found.tsx +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; - -import { useValues } from 'kea'; - -import { - EuiPageContent, - EuiEmptyPrompt, - EuiTitle, - EuiFlexGroup, - EuiFlexItem, - EuiButton, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { - APP_SEARCH_PLUGIN, - WORKPLACE_SEARCH_PLUGIN, - LICENSED_SUPPORT_URL, -} from '../../../../common/constants'; - -import { SetAppSearchChrome, SetWorkplaceSearchChrome } from '../kibana_chrome'; -import { BreadcrumbTrail } from '../kibana_chrome/generate_breadcrumbs'; -import { LicensingLogic } from '../licensing'; -import { EuiButtonTo } from '../react_router_helpers'; -import { SendAppSearchTelemetry, SendWorkplaceSearchTelemetry } from '../telemetry'; - -import { AppSearchLogo } from './assets/app_search_logo'; -import { WorkplaceSearchLogo } from './assets/workplace_search_logo'; -import './assets/logo.scss'; - -interface NotFoundProps { - // Expects product plugin constants (@see common/constants.ts) - product: { - ID: string; - SUPPORT_URL: string; - }; - // Optional breadcrumbs - breadcrumbs?: BreadcrumbTrail; -} - -export const NotFound: React.FC = ({ product = {}, breadcrumbs }) => { - const { hasGoldLicense } = useValues(LicensingLogic); - const supportUrl = hasGoldLicense ? LICENSED_SUPPORT_URL : product.SUPPORT_URL; - - let Logo; - let SetPageChrome; - let SendTelemetry; - - switch (product.ID) { - case APP_SEARCH_PLUGIN.ID: - Logo = AppSearchLogo; - SetPageChrome = SetAppSearchChrome; - SendTelemetry = SendAppSearchTelemetry; - break; - case WORKPLACE_SEARCH_PLUGIN.ID: - Logo = WorkplaceSearchLogo; - SetPageChrome = SetWorkplaceSearchChrome; - SendTelemetry = SendWorkplaceSearchTelemetry; - break; - default: - return null; - } - - return ( - <> - - - - - } - body={ - <> - -

- {i18n.translate('xpack.enterpriseSearch.notFound.title', { - defaultMessage: '404 error', - })} -

-
-

- {i18n.translate('xpack.enterpriseSearch.notFound.description', { - defaultMessage: 'The page you’re looking for was not found.', - })} -

- - } - actions={ - - - - {i18n.translate('xpack.enterpriseSearch.notFound.action1', { - defaultMessage: 'Back to your dashboard', - })} - - - - - {i18n.translate('xpack.enterpriseSearch.notFound.action2', { - defaultMessage: 'Contact support', - })} - - - - } - /> -
- - ); -}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found_prompt.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found_prompt.test.tsx new file mode 100644 index 0000000000000..c21aeff2780b6 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found_prompt.test.tsx @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { setMockValues } from '../../__mocks__/kea_logic'; + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { EuiEmptyPrompt, EuiButton } from '@elastic/eui'; + +import { EuiButtonTo } from '../react_router_helpers'; + +import { NotFoundPrompt } from './'; + +describe('NotFoundPrompt', () => { + const subject = (props?: object) => + shallow() + .find(EuiEmptyPrompt) + .dive(); + + it('renders', () => { + const wrapper = subject({ + productSupportUrl: 'https://discuss.elastic.co/c/enterprise-search/app-search/', + }); + + expect(wrapper.find('h1').text()).toEqual('404 error'); + expect(wrapper.find(EuiButtonTo).prop('to')).toEqual('/'); + expect(wrapper.find(EuiButton).prop('href')).toContain('https://discuss.elastic.co'); + }); + + it('renders with a custom "Back to dashboard" link if passed', () => { + const wrapper = subject({ + productSupportUrl: 'https://discuss.elastic.co/c/enterprise-search/workplace-search/', + backToLink: '/workplace_search/p/sources', + }); + + expect(wrapper.find(EuiButtonTo).prop('to')).toEqual('/workplace_search/p/sources'); + }); + + it('renders with a link to our licensed support URL for gold+ licenses', () => { + setMockValues({ hasGoldLicense: true }); + const wrapper = subject(); + + expect(wrapper.find(EuiButton).prop('href')).toEqual('https://support.elastic.co'); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found_prompt.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found_prompt.tsx new file mode 100644 index 0000000000000..97debd21ec16c --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/not_found/not_found_prompt.tsx @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { useValues } from 'kea'; + +import { EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, EuiButton } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { LICENSED_SUPPORT_URL } from '../../../../common/constants'; +import { LicensingLogic } from '../licensing'; +import { EuiButtonTo } from '../react_router_helpers'; + +interface Props { + productSupportUrl: string; + backToLink?: string; +} + +export const NotFoundPrompt: React.FC = ({ productSupportUrl, backToLink = '/' }) => { + const { hasGoldLicense } = useValues(LicensingLogic); + const supportUrl = hasGoldLicense ? LICENSED_SUPPORT_URL : productSupportUrl; + + return ( + + {i18n.translate('xpack.enterpriseSearch.notFound.title', { + defaultMessage: '404 error', + })} + + } + body={ +

+ {i18n.translate('xpack.enterpriseSearch.notFound.description', { + defaultMessage: 'The page you’re looking for was not found.', + })} +

+ } + actions={ + + + + {i18n.translate('xpack.enterpriseSearch.notFound.action1', { + defaultMessage: 'Back to your dashboard', + })} + + + + + {i18n.translate('xpack.enterpriseSearch.notFound.action2', { + defaultMessage: 'Contact support', + })} + + + + } + /> + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx index 28169afd4bdeb..2743dfc794ec6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx @@ -5,17 +5,15 @@ * 2.0. */ -import '../__mocks__/react_router'; import '../__mocks__/shallow_useeffect.mock'; import { setMockValues, setMockActions, mockKibanaValues } from '../__mocks__/kea_logic'; +import { mockUseRouteMatch } from '../__mocks__/react_router'; import React from 'react'; import { Redirect } from 'react-router-dom'; import { shallow } from 'enzyme'; -import { Layout } from '../shared/layout'; - import { WorkplaceSearchHeaderActions } from './components/layout'; import { SourceAdded } from './views/content_sources/components/source_added'; import { ErrorState } from './views/error_state'; @@ -38,6 +36,14 @@ describe('WorkplaceSearch', () => { expect(wrapper.find(WorkplaceSearchConfigured)).toHaveLength(1); }); + + it('renders ErrorState', () => { + setMockValues({ errorConnecting: true }); + + const wrapper = shallow(); + + expect(wrapper.find(ErrorState)).toHaveLength(1); + }); }); describe('WorkplaceSearchUnconfigured', () => { @@ -56,12 +62,12 @@ describe('WorkplaceSearchConfigured', () => { beforeEach(() => { jest.clearAllMocks(); setMockActions({ initializeAppData, setContext }); + mockUseRouteMatch.mockReturnValue(false); }); - it('renders layout, chrome, and header actions', () => { + it('renders chrome and header actions', () => { const wrapper = shallow(); - expect(wrapper.find(Layout).first().prop('readOnlyMode')).toBeFalsy(); expect(wrapper.find(Overview)).toHaveLength(1); expect(mockKibanaValues.setChromeIsVisible).toHaveBeenCalledWith(true); @@ -83,22 +89,6 @@ describe('WorkplaceSearchConfigured', () => { expect(mockKibanaValues.renderHeaderActions).not.toHaveBeenCalled(); }); - it('renders ErrorState', () => { - setMockValues({ errorConnecting: true }); - - const wrapper = shallow(); - - expect(wrapper.find(ErrorState)).toHaveLength(1); - }); - - it('passes readOnlyMode state', () => { - setMockValues({ readOnlyMode: true }); - - const wrapper = shallow(); - - expect(wrapper.find(Layout).first().prop('readOnlyMode')).toEqual(true); - }); - it('renders SourceAdded', () => { const wrapper = shallow(); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx index 05018be2934b4..2daf677962163 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.tsx @@ -6,19 +6,16 @@ */ import React, { useEffect } from 'react'; -import { Route, Redirect, Switch, useLocation } from 'react-router-dom'; +import { Route, Redirect, Switch, useRouteMatch } from 'react-router-dom'; import { useActions, useValues } from 'kea'; -import { WORKPLACE_SEARCH_PLUGIN } from '../../../common/constants'; import { InitialAppData } from '../../../common/types'; import { HttpLogic } from '../shared/http'; import { KibanaLogic } from '../shared/kibana'; -import { Layout } from '../shared/layout'; -import { NotFound } from '../shared/not_found'; import { AppLogic } from './app_logic'; -import { WorkplaceSearchNav, WorkplaceSearchHeaderActions } from './components/layout'; +import { WorkplaceSearchHeaderActions } from './components/layout'; import { GROUPS_PATH, SETUP_GUIDE_PATH, @@ -36,6 +33,7 @@ import { SourcesRouter } from './views/content_sources'; import { SourceAdded } from './views/content_sources/components/source_added'; import { ErrorState } from './views/error_state'; import { GroupsRouter } from './views/groups'; +import { NotFound } from './views/not_found'; import { Overview } from './views/overview'; import { RoleMappings } from './views/role_mappings'; import { Security } from './views/security'; @@ -44,30 +42,33 @@ import { SetupGuide } from './views/setup_guide'; export const WorkplaceSearch: React.FC = (props) => { const { config } = useValues(KibanaLogic); - return !config.host ? : ; + const { errorConnecting } = useValues(HttpLogic); + return !config.host ? ( + + ) : errorConnecting ? ( + + ) : ( + + ); }; export const WorkplaceSearchConfigured: React.FC = (props) => { const { hasInitialized } = useValues(AppLogic); const { initializeAppData, setContext } = useActions(AppLogic); const { renderHeaderActions, setChromeIsVisible } = useValues(KibanaLogic); - const { errorConnecting, readOnlyMode } = useValues(HttpLogic); - - const { pathname } = useLocation(); /** * Personal dashboard urls begin with /p/ * EX: http://localhost:5601/app/enterprise_search/workplace_search/p/sources */ - const personalSourceUrlRegex = /^\/p\//g; // matches '/p/*' - const isOrganization = !pathname.match(personalSourceUrlRegex); // TODO: Once auth is figured out, we need to have a check for the equivilent of `isAdmin`. + const isOrganization = !useRouteMatch(PERSONAL_PATH); // TODO: Once auth is figured out, we need to have a check for the equivalent of `isAdmin`. setContext(isOrganization); useEffect(() => { setChromeIsVisible(isOrganization); - }, [pathname]); + }, [isOrganization]); useEffect(() => { if (!hasInitialized) { @@ -95,6 +96,9 @@ export const WorkplaceSearchConfigured: React.FC = (props) => { + + + @@ -113,15 +117,7 @@ export const WorkplaceSearchConfigured: React.FC = (props) => { - } restrictWidth readOnlyMode={readOnlyMode}> - {errorConnecting ? ( - - ) : ( - - - - )} - + ); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts index 03f46830fafc3..2aed64af53f16 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.test.ts @@ -22,8 +22,6 @@ jest.mock('../../app_logic', () => ({ })); import { AppLogic } from '../../app_logic'; -import { NOT_FOUND_PATH } from '../../routes'; - import { SourceLogic } from './source_logic'; describe('SourceLogic', () => { @@ -176,47 +174,55 @@ describe('SourceLogic', () => { expect(initializeFederatedSummarySpy).toHaveBeenCalledWith(contentSource.id); }); - it('handles error', async () => { - const error = { - response: { - error: 'this is an error', - status: 400, - }, - }; - const promise = Promise.reject(error); - http.get.mockReturnValue(promise); - SourceLogic.actions.initializeSource(contentSource.id); - await expectedAsyncError(promise); + describe('errors', () => { + it('handles generic errors', async () => { + const mockError = Promise.reject('error'); + http.get.mockReturnValue(mockError); - expect(flashAPIErrors).toHaveBeenCalledWith(error); - }); + SourceLogic.actions.initializeSource(contentSource.id); + await expectedAsyncError(mockError); - it('handles not found state', async () => { - const error = { - response: { - error: 'this is an error', - status: 404, - }, - }; - const promise = Promise.reject(error); - http.get.mockReturnValue(promise); - SourceLogic.actions.initializeSource(contentSource.id); - await expectedAsyncError(promise); + expect(flashAPIErrors).toHaveBeenCalledWith('error'); + }); - expect(navigateToUrl).toHaveBeenCalledWith(NOT_FOUND_PATH); - }); + describe('404s', () => { + const mock404 = Promise.reject({ response: { status: 404 } }); - it('renders error messages passed in success response from server', async () => { - const errors = ['ERROR']; - const promise = Promise.resolve({ - ...contentSource, - errors, + it('redirects to the organization sources page on organization views', async () => { + AppLogic.values.isOrganization = true; + http.get.mockReturnValue(mock404); + + SourceLogic.actions.initializeSource('404ing_org_source'); + await expectedAsyncError(mock404); + + expect(navigateToUrl).toHaveBeenCalledWith('/sources'); + expect(setErrorMessage).toHaveBeenCalledWith('Source not found.'); + }); + + it('redirects to the personal dashboard sources page on personal views', async () => { + AppLogic.values.isOrganization = false; + http.get.mockReturnValue(mock404); + + SourceLogic.actions.initializeSource('404ing_personal_source'); + await expectedAsyncError(mock404); + + expect(navigateToUrl).toHaveBeenCalledWith('/p/sources'); + expect(setErrorMessage).toHaveBeenCalledWith('Source not found.'); + }); }); - http.get.mockReturnValue(promise); - SourceLogic.actions.initializeSource(contentSource.id); - await promise; - expect(setErrorMessage).toHaveBeenCalledWith(errors); + it('renders error messages passed in success response from server', async () => { + const errors = ['ERROR']; + const promise = Promise.resolve({ + ...contentSource, + errors, + }); + http.get.mockReturnValue(promise); + SourceLogic.actions.initializeSource(contentSource.id); + await promise; + + expect(setErrorMessage).toHaveBeenCalledWith(errors); + }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts index 2e6a3c65597ea..0fd44e01ae495 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts @@ -20,7 +20,7 @@ import { import { HttpLogic } from '../../../shared/http'; import { KibanaLogic } from '../../../shared/kibana'; import { AppLogic } from '../../app_logic'; -import { NOT_FOUND_PATH, SOURCES_PATH, getSourcesPath } from '../../routes'; +import { PERSONAL_SOURCES_PATH, SOURCES_PATH, getSourcesPath } from '../../routes'; import { ContentSourceFullData, Meta, DocumentSummaryItem, SourceContentItem } from '../../types'; export interface SourceActions { @@ -155,8 +155,14 @@ export const SourceLogic = kea>({ clearFlashMessages(); } } catch (e) { - if (e.response.status === 404) { - KibanaLogic.values.navigateToUrl(NOT_FOUND_PATH); + if (e?.response?.status === 404) { + const redirect = isOrganization ? SOURCES_PATH : PERSONAL_SOURCES_PATH; + KibanaLogic.values.navigateToUrl(redirect); + setErrorMessage( + i18n.translate('xpack.enterpriseSearch.workplaceSearch.sources.notFoundErrorMessage', { + defaultMessage: 'Source not found.', + }) + ); } else { flashAPIErrors(e); } diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.test.tsx index afe0d1f89faea..fbc8eb159a7a8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.test.tsx @@ -90,7 +90,7 @@ describe('SourceRouter', () => { expect(wrapper.find(Overview)).toHaveLength(1); expect(wrapper.find(SourceSettings)).toHaveLength(1); expect(wrapper.find(SourceContent)).toHaveLength(1); - expect(wrapper.find(Route)).toHaveLength(3); + expect(wrapper.find(Route)).toHaveLength(4); }); it('renders source routes (custom)', () => { @@ -100,6 +100,6 @@ describe('SourceRouter', () => { expect(wrapper.find(DisplaySettingsRouter)).toHaveLength(1); expect(wrapper.find(Schema)).toHaveLength(1); expect(wrapper.find(SchemaChangeErrors)).toHaveLength(1); - expect(wrapper.find(Route)).toHaveLength(6); + expect(wrapper.find(Route)).toHaveLength(7); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx index bf68a60757c0d..9f793fcd34fbe 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_router.tsx @@ -13,7 +13,7 @@ import { useActions, useValues } from 'kea'; import { AppLogic } from '../../app_logic'; import { WorkplaceSearchPageTemplate, PersonalDashboardLayout } from '../../components/layout'; -import { CUSTOM_SERVICE_TYPE } from '../../constants'; +import { NAV, CUSTOM_SERVICE_TYPE } from '../../constants'; import { REINDEX_JOB_PATH, SOURCE_DETAILS_PATH, @@ -24,6 +24,7 @@ import { getContentSourcePath as sourcePath, getSourcesPath, } from '../../routes'; +import { NotFound } from '../../views/not_found'; import { DisplaySettingsRouter } from './components/display_settings'; import { Overview } from './components/overview'; @@ -85,6 +86,9 @@ export const SourceRouter: React.FC = () => { + + + ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/not_found/index.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/not_found/index.ts new file mode 100644 index 0000000000000..482c1a58faa9c --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/not_found/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { NotFound } from './not_found'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/not_found/not_found.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/not_found/not_found.test.tsx new file mode 100644 index 0000000000000..0e388a73f0e18 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/not_found/not_found.test.tsx @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { shallow } from 'enzyme'; + +import { NotFoundPrompt } from '../../../shared/not_found'; +import { SendWorkplaceSearchTelemetry } from '../../../shared/telemetry'; +import { WorkplaceSearchPageTemplate, PersonalDashboardLayout } from '../../components/layout'; + +import { NotFound } from './'; + +describe('NotFound', () => { + it('renders the shared not found prompt', () => { + const wrapper = shallow(); + expect(wrapper.find(NotFoundPrompt)).toHaveLength(1); + }); + + it('renders a telemetry error event', () => { + const wrapper = shallow(); + expect(wrapper.find(SendWorkplaceSearchTelemetry).prop('action')).toEqual('error'); + }); + + it('passes optional preceding page chrome', () => { + const wrapper = shallow(); + expect(wrapper.prop('pageChrome')).toEqual(['Sources', '404']); + }); + + describe('organization views', () => { + it('renders the WorkplaceSearchPageTemplate', () => { + const wrapper = shallow(); + expect(wrapper.type()).toEqual(WorkplaceSearchPageTemplate); + }); + }); + + describe('personal views', () => { + it('renders the PersonalDashboardLayout', () => { + const wrapper = shallow(); + expect(wrapper.type()).toEqual(PersonalDashboardLayout); + }); + + it('sets the "Back to dashboard" link to /p/sources', () => { + const wrapper = shallow(); + expect(wrapper.find(NotFoundPrompt).prop('backToLink')).toEqual('/p/sources'); + }); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/not_found/not_found.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/not_found/not_found.tsx new file mode 100644 index 0000000000000..ef55668775513 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/not_found/not_found.tsx @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; + +import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants'; +import { PageTemplateProps } from '../../../shared/layout'; +import { NotFoundPrompt } from '../../../shared/not_found'; +import { SendWorkplaceSearchTelemetry } from '../../../shared/telemetry'; +import { WorkplaceSearchPageTemplate, PersonalDashboardLayout } from '../../components/layout'; +import { PERSONAL_SOURCES_PATH } from '../../routes'; + +interface Props { + isOrganization?: boolean; + pageChrome?: PageTemplateProps['pageChrome']; +} +export const NotFound: React.FC = ({ isOrganization = true, pageChrome = [] }) => { + const Layout = isOrganization ? WorkplaceSearchPageTemplate : PersonalDashboardLayout; + + return ( + + + + + ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.test.tsx index 74092f17eadcf..123167f0ad1d0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.test.tsx @@ -25,8 +25,8 @@ import { SettingsRouter } from './settings_router'; describe('SettingsRouter', () => { const initializeSettings = jest.fn(); const NUM_SOURCES = staticSourceData.length; - // Should be 3 routes other than the sources listed Connectors, Customize, & OauthApplication - const NUM_ROUTES = NUM_SOURCES + 3; + // Should be 4 routes other than the sources listed: Connectors, Customize, & OauthApplication, & a redirect + const NUM_ROUTES = NUM_SOURCES + 4; beforeEach(() => { setMockActions({ initializeSettings }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.tsx index f8c8050e20153..d9aeba361d240 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/settings/settings_router.tsx @@ -11,7 +11,6 @@ import { Redirect, Route, Switch } from 'react-router-dom'; import { useActions } from 'kea'; import { - ORG_SETTINGS_PATH, ORG_SETTINGS_CUSTOMIZE_PATH, ORG_SETTINGS_CONNECTORS_PATH, ORG_SETTINGS_OAUTH_APPLICATION_PATH, @@ -33,7 +32,6 @@ export const SettingsRouter: React.FC = () => { return ( - @@ -48,6 +46,9 @@ export const SettingsRouter: React.FC = () => { ))} + + + ); }; From 0857e620c7565281290c3de4334a6ae0e04fc8d8 Mon Sep 17 00:00:00 2001 From: Scotty Bollinger Date: Thu, 24 Jun 2021 14:59:10 -0500 Subject: [PATCH 17/25] [Workplace Search] Remove `isFederatedAuth` checks to expose user features (#103278) * Remove isFederated from main app and routes * Expose all overview cards that were hidden for federated auth * Expose all user features that were hidden for groups * Remove remaining isFederatedAuth references * Lint fixes * Add modified test back for Workplace Search * Remove extraCell Co-authored-by: Constance * Remove brackets Co-authored-by: Constance * Update test name Co-authored-by: Constance Co-authored-by: Constance --- .../common/__mocks__/initial_app_data.ts | 1 - .../enterprise_search/common/types/index.ts | 1 - .../workplace_search/app_logic.test.ts | 3 -- .../workplace_search/app_logic.ts | 12 +----- .../workplace_search/index.test.tsx | 6 ++- .../applications/workplace_search/routes.ts | 1 - .../groups/components/group_overview.tsx | 7 +-- .../groups/components/group_row.test.tsx | 7 --- .../views/groups/components/group_row.tsx | 24 ++++------- .../components/group_users_table.test.tsx | 11 +---- .../groups/components/group_users_table.tsx | 11 ++--- .../groups/components/groups_table.test.tsx | 10 +---- .../views/groups/components/groups_table.tsx | 4 +- .../groups/components/table_filters.test.tsx | 9 +--- .../views/groups/components/table_filters.tsx | 10 ++--- .../views/groups/groups.test.tsx | 20 +-------- .../workplace_search/views/groups/groups.tsx | 11 ++--- .../overview/__mocks__/overview_logic.mock.ts | 2 +- .../views/overview/onboarding_steps.test.tsx | 19 ++++---- .../views/overview/onboarding_steps.tsx | 40 ++++++++--------- .../overview/organization_stats.test.tsx | 9 ---- .../views/overview/organization_stats.tsx | 43 ++++++++----------- .../lib/enterprise_search_config_api.test.ts | 1 - .../lib/enterprise_search_config_api.ts | 1 - 24 files changed, 76 insertions(+), 187 deletions(-) diff --git a/x-pack/plugins/enterprise_search/common/__mocks__/initial_app_data.ts b/x-pack/plugins/enterprise_search/common/__mocks__/initial_app_data.ts index 7ea4289b21967..a4e3ada1c06cb 100644 --- a/x-pack/plugins/enterprise_search/common/__mocks__/initial_app_data.ts +++ b/x-pack/plugins/enterprise_search/common/__mocks__/initial_app_data.ts @@ -8,7 +8,6 @@ export const DEFAULT_INITIAL_APP_DATA = { readOnlyMode: false, ilmEnabled: true, - isFederatedAuth: false, configuredLimits: { appSearch: { engine: { diff --git a/x-pack/plugins/enterprise_search/common/types/index.ts b/x-pack/plugins/enterprise_search/common/types/index.ts index 68904483720f2..f405c86de18f0 100644 --- a/x-pack/plugins/enterprise_search/common/types/index.ts +++ b/x-pack/plugins/enterprise_search/common/types/index.ts @@ -17,7 +17,6 @@ import { export interface InitialAppData { readOnlyMode?: boolean; ilmEnabled?: boolean; - isFederatedAuth?: boolean; configuredLimits?: ConfiguredLimits; access?: ProductAccess; appSearch?: AppSearchAccount; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.test.ts index b2cc835da4ecd..24a156bbd67b8 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.test.ts @@ -20,7 +20,6 @@ describe('AppLogic', () => { const DEFAULT_VALUES = { account: {}, hasInitialized: false, - isFederatedAuth: true, isOrganization: false, organization: {}, }; @@ -36,7 +35,6 @@ describe('AppLogic', () => { viewedOnboardingPage: true, }, hasInitialized: true, - isFederatedAuth: false, isOrganization: false, organization: { defaultOrgName: 'My Organization', @@ -61,7 +59,6 @@ describe('AppLogic', () => { expect(AppLogic.values).toEqual({ ...DEFAULT_VALUES, hasInitialized: true, - isFederatedAuth: false, }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.ts index 26e1d7fbb93fd..ee1f6a69fa4b9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/app_logic.ts @@ -16,7 +16,6 @@ import { interface AppValues extends WorkplaceSearchInitialData { hasInitialized: boolean; - isFederatedAuth: boolean; isOrganization: boolean; } interface AppActions { @@ -32,10 +31,7 @@ const emptyAccount = {} as Account; export const AppLogic = kea>({ path: ['enterprise_search', 'workplace_search', 'app_logic'], actions: { - initializeAppData: ({ workplaceSearch, isFederatedAuth }) => ({ - workplaceSearch, - isFederatedAuth, - }), + initializeAppData: ({ workplaceSearch }) => ({ workplaceSearch }), setContext: (isOrganization) => isOrganization, setOrgName: (name: string) => name, setSourceRestriction: (canCreatePersonalSources: boolean) => canCreatePersonalSources, @@ -47,12 +43,6 @@ export const AppLogic = kea>({ initializeAppData: () => true, }, ], - isFederatedAuth: [ - true, - { - initializeAppData: (_, { isFederatedAuth }) => !!isFederatedAuth, - }, - ], isOrganization: [ false, { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx index 2743dfc794ec6..3ddccde6abd33 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/index.test.tsx @@ -6,6 +6,7 @@ */ import '../__mocks__/shallow_useeffect.mock'; +import { DEFAULT_INITIAL_APP_DATA } from '../../../common/__mocks__'; import { setMockValues, setMockActions, mockKibanaValues } from '../__mocks__/kea_logic'; import { mockUseRouteMatch } from '../__mocks__/react_router'; @@ -75,9 +76,10 @@ describe('WorkplaceSearchConfigured', () => { }); it('initializes app data with passed props', () => { - shallow(); + const { workplaceSearch } = DEFAULT_INITIAL_APP_DATA; + shallow(); - expect(initializeAppData).toHaveBeenCalledWith({ isFederatedAuth: true }); + expect(initializeAppData).toHaveBeenCalledWith({ workplaceSearch }); }); it('does not re-initialize app data or re-render header actions', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts index b9309ffd94809..3dac5f80700c0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/routes.ts @@ -50,7 +50,6 @@ export const PERSONAL_PATH = '/p'; export const USERS_AND_ROLES_PATH = '/users_and_roles'; -export const USERS_PATH = '/users'; export const SECURITY_PATH = '/security'; export const GROUPS_PATH = '/groups'; diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.tsx index 6914c5dcfcad1..76658cec75e51 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_overview.tsx @@ -24,7 +24,6 @@ import { import { i18n } from '@kbn/i18n'; import { TruncatedContent } from '../../../../shared/truncate'; -import { AppLogic } from '../../../app_logic'; import noSharedSourcesIcon from '../../../assets/share_circle.svg'; import { WorkplaceSearchPageTemplate } from '../../../components/layout'; import { ContentSection } from '../../../components/shared/content_section'; @@ -124,8 +123,6 @@ export const GroupOverview: React.FC = () => { confirmDeleteModalVisible, } = useValues(GroupLogic); - const { isFederatedAuth } = useValues(AppLogic); - const truncatedName = name && ( ); @@ -167,7 +164,7 @@ export const GroupOverview: React.FC = () => { {MANAGE_SOURCES_BUTTON_TEXT} ); - const manageUsersButton = !isFederatedAuth && ( + const manageUsersButton = ( {MANAGE_USERS_BUTTON_TEXT} @@ -199,7 +196,7 @@ export const GroupOverview: React.FC = () => { ); - const usersSection = !isFederatedAuth && ( + const usersSection = ( { - beforeEach(() => { - setMockValues({ isFederatedAuth: true }); - }); - it('renders', () => { const wrapper = shallow(); @@ -30,7 +25,6 @@ describe('GroupRow', () => { }); it('renders group users', () => { - setMockValues({ isFederatedAuth: false }); const wrapper = shallow(); expect(wrapper.find(GroupUsers)).toHaveLength(1); @@ -51,7 +45,6 @@ describe('GroupRow', () => { }); it('renders empty users message when no users present', () => { - setMockValues({ isFederatedAuth: false }); const wrapper = shallow(); expect(wrapper.find('.user-group__accounts').text()).toEqual(NO_USERS_MESSAGE); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.tsx index 204d8f5655172..94d44fde57aed 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_row.tsx @@ -7,7 +7,6 @@ import React from 'react'; -import { useValues } from 'kea'; import moment from 'moment'; import { EuiTableRow, EuiTableRowCell, EuiIcon } from '@elastic/eui'; @@ -15,7 +14,6 @@ import { i18n } from '@kbn/i18n'; import { EuiLinkTo } from '../../../../shared/react_router_helpers'; import { TruncatedContent } from '../../../../shared/truncate'; -import { AppLogic } from '../../../app_logic'; import { getGroupPath } from '../../../routes'; import { Group } from '../../../types'; import { MAX_NAME_LENGTH } from '../group_logic'; @@ -50,8 +48,6 @@ export const GroupRow: React.FC = ({ users, usersCount, }) => { - const { isFederatedAuth } = useValues(AppLogic); - const GROUP_UPDATED_TEXT = i18n.translate( 'xpack.enterpriseSearch.workplaceSearch.groups.groupUpdatedText', { @@ -80,17 +76,15 @@ export const GroupRow: React.FC = ({ )} - {!isFederatedAuth && ( - -
- {usersCount > 0 ? ( - - ) : ( - NO_USERS_MESSAGE - )} -
-
- )} + +
+ {usersCount > 0 ? ( + + ) : ( + NO_USERS_MESSAGE + )} +
+
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.test.tsx index 0dde2f5eaf7f7..cc5f9c4effd21 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.test.tsx @@ -23,17 +23,10 @@ const group = groups[0]; describe('GroupUsersTable', () => { it('renders', () => { - setMockValues({ isFederatedAuth: true, group }); + setMockValues({ group }); const wrapper = shallow(); expect(wrapper.find(EuiTable)).toHaveLength(1); - expect(wrapper.find(TableHeader).prop('headerItems')).toHaveLength(1); - }); - - it('adds header item for non-federated auth', () => { - setMockValues({ isFederatedAuth: false, group }); - const wrapper = shallow(); - expect(wrapper.find(TableHeader).prop('headerItems')).toHaveLength(2); }); @@ -48,7 +41,7 @@ describe('GroupUsersTable', () => { }); }); - setMockValues({ isFederatedAuth: true, group: { users } }); + setMockValues({ group: { users } }); const wrapper = shallow(); const pagination = wrapper.find(EuiTablePagination); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.tsx index 050aaf1dadf89..3e9e40fef44a6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/group_users_table.tsx @@ -14,7 +14,6 @@ import { Pager } from '@elastic/eui'; import { USERNAME_LABEL, EMAIL_LABEL } from '../../../../shared/constants'; import { TableHeader } from '../../../../shared/table_header'; -import { AppLogic } from '../../../app_logic'; import { UserRow } from '../../../components/shared/user_row'; import { User } from '../../../types'; import { GroupLogic } from '../group_logic'; @@ -22,14 +21,10 @@ import { GroupLogic } from '../group_logic'; const USERS_PER_PAGE = 10; export const GroupUsersTable: React.FC = () => { - const { isFederatedAuth } = useValues(AppLogic); const { group: { users }, } = useValues(GroupLogic); - const headerItems = [USERNAME_LABEL]; - if (!isFederatedAuth) { - headerItems.push(EMAIL_LABEL); - } + const headerItems = [USERNAME_LABEL, EMAIL_LABEL]; const [firstItem, setFirstItem] = useState(0); const [lastItem, setLastItem] = useState(USERS_PER_PAGE - 1); @@ -58,10 +53,10 @@ export const GroupUsersTable: React.FC = () => { return ( <> - + {users.slice(firstItem, lastItem + 1).map((user: User) => ( - + ))} diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.test.tsx index d11b830a8fc4b..cbb028139623c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.test.tsx @@ -12,7 +12,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { EuiTable, EuiTableHeaderCell } from '@elastic/eui'; +import { EuiTable } from '@elastic/eui'; import { DEFAULT_META } from '../../../../shared/constants'; import { TablePaginationBar } from '../../../components/shared/table_pagination_bar'; @@ -27,7 +27,6 @@ const mockValues = { groupsMeta: DEFAULT_META, groups, hasFiltersSet: false, - isFederatedAuth: true, }; describe('GroupsTable', () => { @@ -43,13 +42,6 @@ describe('GroupsTable', () => { expect(wrapper.find(GroupRow)).toHaveLength(1); }); - it('renders extra header for non-federated auth', () => { - setMockValues({ ...mockValues, isFederatedAuth: false }); - const wrapper = shallow(); - - expect(wrapper.find(EuiTableHeaderCell)).toHaveLength(4); - }); - it('handles pagination', () => { setMockValues({ ...mockValues, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.tsx index deaf223afa6b3..cfb3ed8044235 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/groups_table.tsx @@ -18,7 +18,6 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { AppLogic } from '../../../app_logic'; import { TablePaginationBar } from '../../../components/shared/table_pagination_bar'; import { GroupsLogic } from '../groups_logic'; @@ -53,7 +52,6 @@ export const GroupsTable: React.FC<{}> = () => { groups, hasFiltersSet, } = useValues(GroupsLogic); - const { isFederatedAuth } = useValues(AppLogic); const clearFiltersLink = hasFiltersSet ? : undefined; @@ -79,7 +77,7 @@ export const GroupsTable: React.FC<{}> = () => { {GROUP_TABLE_HEADER} {SOURCES_TABLE_HEADER} - {!isFederatedAuth && {USERS_TABLE_HEADER}} + {USERS_TABLE_HEADER} diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.test.tsx index 83a20efe5257e..f0758831e2af6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.test.tsx @@ -21,7 +21,7 @@ const setFilterValue = jest.fn(); describe('TableFilters', () => { beforeEach(() => { - setMockValues({ filterValue: '', isFederatedAuth: true }); + setMockValues({ filterValue: '' }); setMockActions({ setFilterValue }); }); it('renders', () => { @@ -29,13 +29,6 @@ describe('TableFilters', () => { expect(wrapper.find(EuiFieldSearch)).toHaveLength(1); expect(wrapper.find(TableFilterSourcesDropdown)).toHaveLength(1); - expect(wrapper.find(TableFilterUsersDropdown)).toHaveLength(0); - }); - - it('renders for non-federated Auth', () => { - setMockValues({ filterValue: '', isFederatedAuth: false }); - const wrapper = shallow(); - expect(wrapper.find(TableFilterUsersDropdown)).toHaveLength(1); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.tsx index e9ea6a7c6b4aa..0907e0b8b3740 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/components/table_filters.tsx @@ -12,7 +12,6 @@ import { useActions, useValues } from 'kea'; import { EuiFieldSearch, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { AppLogic } from '../../../app_logic'; import { GroupsLogic } from '../groups_logic'; import { TableFilterSourcesDropdown } from './table_filter_sources_dropdown'; @@ -28,7 +27,6 @@ const FILTER_GROUPS_PLACEHOLDER = i18n.translate( export const TableFilters: React.FC = () => { const { setFilterValue } = useActions(GroupsLogic); const { filterValue } = useValues(GroupsLogic); - const { isFederatedAuth } = useValues(AppLogic); const handleSearchChange = (e: ChangeEvent) => setFilterValue(e.target.value); @@ -47,11 +45,9 @@ export const TableFilters: React.FC = () => { - {!isFederatedAuth && ( - - - - )} + + +
diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx index 5be61da22fda9..dccb1ad114db9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.test.tsx @@ -50,7 +50,6 @@ const mockValues = { filteredSources: [], filteredUsers: [], filterValue: '', - isFederatedAuth: false, }; describe('GroupOverview', () => { @@ -112,12 +111,7 @@ describe('GroupOverview', () => { expect(wrapper.find(ClearFiltersLink)).toHaveLength(1); }); - it('renders inviteUsersButton when not federated auth', () => { - setMockValues({ - ...mockValues, - isFederatedAuth: false, - }); - + it('renders inviteUsersButton', () => { const wrapper = shallow(); const actions = getPageHeaderActions(wrapper); @@ -125,18 +119,6 @@ describe('GroupOverview', () => { expect(actions.find(EuiButtonTo)).toHaveLength(1); }); - it('does not render inviteUsersButton when federated auth', () => { - setMockValues({ - ...mockValues, - isFederatedAuth: true, - }); - - const wrapper = shallow(); - const actions = getPageHeaderActions(wrapper); - - expect(actions.find('[data-test-subj="InviteUsersButton"]')).toHaveLength(0); - }); - it('renders EuiLoadingSpinner when loading', () => { setMockValues({ ...mockValues, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.tsx index 60806a53deb5f..1a4c4f51e93ea 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/groups/groups.tsx @@ -14,10 +14,9 @@ import { i18n } from '@kbn/i18n'; import { FlashMessagesLogic } from '../../../shared/flash_messages'; import { EuiButtonTo } from '../../../shared/react_router_helpers'; -import { AppLogic } from '../../app_logic'; import { WorkplaceSearchPageTemplate } from '../../components/layout'; import { NAV } from '../../constants'; -import { getGroupPath, USERS_PATH } from '../../routes'; +import { getGroupPath, USERS_AND_ROLES_PATH } from '../../routes'; import { AddGroupModal } from './components/add_group_modal'; import { ClearFiltersLink } from './components/clear_filters_link'; @@ -43,8 +42,6 @@ export const Groups: React.FC = () => { filterValue, } = useValues(GroupsLogic); - const { isFederatedAuth } = useValues(AppLogic); - const hasMessages = messages.length > 0; useEffect(() => { @@ -68,7 +65,7 @@ export const Groups: React.FC = () => { const clearFilters = hasFiltersSet && ; const inviteUsersButton = ( - + {i18n.translate('xpack.enterpriseSearch.workplaceSearch.groups.inviteUsers.action', { defaultMessage: 'Invite users', })} @@ -81,9 +78,7 @@ export const Groups: React.FC = () => { })} ); - const headerActions = !isFederatedAuth - ? [inviteUsersButton, createGroupButton] - : [createGroupButton]; + const headerActions = [inviteUsersButton, createGroupButton]; const noResults = ( diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/__mocks__/overview_logic.mock.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/__mocks__/overview_logic.mock.ts index 9aaa6253ea0ab..f6468aefa4fb9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/__mocks__/overview_logic.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/__mocks__/overview_logic.mock.ts @@ -27,7 +27,7 @@ export const mockActions = { initializeOverview: jest.fn(() => ({})), }; -const mockValues = { ...mockOverviewValues, ...mockAppValues, isFederatedAuth: true }; +const mockValues = { ...mockOverviewValues, ...mockAppValues }; setMockActions({ ...mockActions }); setMockKeaValues({ ...mockValues }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.test.tsx index 01e5245c597eb..fd3e1877fdb3e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.test.tsx @@ -13,7 +13,7 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { SOURCES_PATH, USERS_PATH } from '../../routes'; +import { SOURCES_PATH, USERS_AND_ROLES_PATH } from '../../routes'; import { OnboardingCard } from './onboarding_card'; import { OnboardingSteps, OrgNameOnboarding } from './onboarding_steps'; @@ -33,9 +33,9 @@ describe('OnboardingSteps', () => { setMockValues({ canCreateContentSources: true }); const wrapper = shallow(); - expect(wrapper.find(OnboardingCard)).toHaveLength(1); - expect(wrapper.find(OnboardingCard).prop('actionPath')).toBe(SOURCES_PATH); - expect(wrapper.find(OnboardingCard).prop('description')).toBe( + expect(wrapper.find(OnboardingCard)).toHaveLength(2); + expect(wrapper.find(OnboardingCard).first().prop('actionPath')).toBe(SOURCES_PATH); + expect(wrapper.find(OnboardingCard).first().prop('description')).toBe( 'Add shared sources for your organization to start searching.' ); }); @@ -44,7 +44,7 @@ describe('OnboardingSteps', () => { setMockValues({ sourcesCount: 2, hasOrgSources: true }); const wrapper = shallow(); - expect(wrapper.find(OnboardingCard).prop('description')).toEqual( + expect(wrapper.find(OnboardingCard).first().prop('description')).toEqual( 'You have added 2 shared sources. Happy searching.' ); }); @@ -53,14 +53,13 @@ describe('OnboardingSteps', () => { setMockValues({ canCreateContentSources: false }); const wrapper = shallow(); - expect(wrapper.find(OnboardingCard).prop('actionPath')).toBe(undefined); + expect(wrapper.find(OnboardingCard).first().prop('actionPath')).toBe(undefined); }); }); describe('Users & Invitations', () => { - it('renders 0 users when not on federated auth', () => { + it('renders 0 users state', () => { setMockValues({ - isFederatedAuth: false, account, accountsCount: 0, hasUsers: false, @@ -68,7 +67,7 @@ describe('OnboardingSteps', () => { const wrapper = shallow(); expect(wrapper.find(OnboardingCard)).toHaveLength(2); - expect(wrapper.find(OnboardingCard).last().prop('actionPath')).toBe(USERS_PATH); + expect(wrapper.find(OnboardingCard).last().prop('actionPath')).toBe(USERS_AND_ROLES_PATH); expect(wrapper.find(OnboardingCard).last().prop('description')).toEqual( 'Invite your colleagues into this organization to search with you.' ); @@ -76,7 +75,6 @@ describe('OnboardingSteps', () => { it('renders completed users state', () => { setMockValues({ - isFederatedAuth: false, account, accountsCount: 1, hasUsers: true, @@ -90,7 +88,6 @@ describe('OnboardingSteps', () => { it('disables link when the user cannot create invitations', () => { setMockValues({ - isFederatedAuth: false, account: { ...account, canCreateInvitations: false, diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.tsx index a89e3294597e4..44d09ed73ed1f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/onboarding_steps.tsx @@ -26,7 +26,7 @@ import { TelemetryLogic } from '../../../shared/telemetry'; import { AppLogic } from '../../app_logic'; import sharedSourcesIcon from '../../components/shared/assets/source_icons/share_circle.svg'; import { ContentSection } from '../../components/shared/content_section'; -import { SOURCES_PATH, USERS_PATH, ORG_SETTINGS_PATH } from '../../routes'; +import { SOURCES_PATH, USERS_AND_ROLES_PATH, ORG_SETTINGS_PATH } from '../../routes'; import { OnboardingCard } from './onboarding_card'; import { OverviewLogic } from './overview_logic'; @@ -58,7 +58,6 @@ const ONBOARDING_USERS_CARD_DESCRIPTION = i18n.translate( export const OnboardingSteps: React.FC = () => { const { - isFederatedAuth, organization: { name, defaultOrgName }, account: { isCurated, canCreateInvitations }, } = useValues(AppLogic); @@ -71,8 +70,7 @@ export const OnboardingSteps: React.FC = () => { sourcesCount, } = useValues(OverviewLogic); - const accountsPath = - !isFederatedAuth && (canCreateInvitations || isCurated) ? USERS_PATH : undefined; + const accountsPath = canCreateInvitations || isCurated ? USERS_AND_ROLES_PATH : undefined; const sourcesPath = canCreateContentSources || isCurated ? SOURCES_PATH : undefined; const SOURCES_CARD_DESCRIPTION = i18n.translate( @@ -86,7 +84,7 @@ export const OnboardingSteps: React.FC = () => { return ( - + { actionPath={sourcesPath} complete={hasOrgSources} /> - {!isFederatedAuth && ( - 0 ? 'more' : '' }, - } - )} - actionPath={accountsPath} - complete={hasUsers} - /> - )} + 0 ? 'more' : '' }, + } + )} + actionPath={accountsPath} + complete={hasUsers} + /> {name === defaultOrgName && ( <> diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.test.tsx index 110557ac4087a..0d690e500f9e2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.test.tsx @@ -5,7 +5,6 @@ * 2.0. */ -import { setMockValues } from './__mocks__'; import './__mocks__/overview_logic.mock'; import React from 'react'; @@ -21,14 +20,6 @@ describe('OrganizationStats', () => { it('renders', () => { const wrapper = shallow(); - expect(wrapper.find(StatisticCard)).toHaveLength(2); - expect(wrapper.find(EuiFlexGrid).prop('columns')).toEqual(2); - }); - - it('renders additional cards for federated auth', () => { - setMockValues({ isFederatedAuth: false }); - const wrapper = shallow(); - expect(wrapper.find(StatisticCard)).toHaveLength(4); expect(wrapper.find(EuiFlexGrid).prop('columns')).toEqual(4); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.tsx index d1f0f6a030421..5608032f8bdd9 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/overview/organization_stats.tsx @@ -13,16 +13,13 @@ import { EuiFlexGrid, EuiPanel } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { AppLogic } from '../../app_logic'; import { ContentSection } from '../../components/shared/content_section'; -import { SOURCES_PATH, USERS_PATH } from '../../routes'; +import { SOURCES_PATH, USERS_AND_ROLES_PATH } from '../../routes'; import { OverviewLogic } from './overview_logic'; import { StatisticCard } from './statistic_card'; export const OrganizationStats: React.FC = () => { - const { isFederatedAuth } = useValues(AppLogic); - const { sourcesCount, pendingInvitationsCount, accountsCount, personalSourcesCount } = useValues( OverviewLogic ); @@ -37,7 +34,7 @@ export const OrganizationStats: React.FC = () => { } > - + { count={sourcesCount} actionPath={SOURCES_PATH} /> - {!isFederatedAuth && ( - <> - - - - )} + + { publicUrl: undefined, readOnlyMode: false, ilmEnabled: false, - isFederatedAuth: false, configuredLimits: { appSearch: { engine: { diff --git a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts index 8cce01d1932ee..833419e34ef5f 100644 --- a/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts +++ b/x-pack/plugins/enterprise_search/server/lib/enterprise_search_config_api.ts @@ -75,7 +75,6 @@ export const callEnterpriseSearchConfigAPI = async ({ publicUrl: stripTrailingSlash(data?.settings?.external_url), readOnlyMode: !!data?.settings?.read_only_mode, ilmEnabled: !!data?.settings?.ilm_enabled, - isFederatedAuth: !!data?.settings?.is_federated_auth, // i.e., not standard auth configuredLimits: { appSearch: { engine: { From cebf16fb538895e8bd4fbbc787d964392bfe9430 Mon Sep 17 00:00:00 2001 From: Candace Park <56409205+parkiino@users.noreply.github.com> Date: Thu, 24 Jun 2021 16:11:16 -0400 Subject: [PATCH 18/25] [Security Solution][Endpoint][Host Isolation] Remove agent status for non endpoint alerts (#102976) --- .../event_details/alert_summary_view.tsx | 11 +++++-- .../common/utils/endpoint_alert_check.test.ts | 31 +++++++++++++++++++ .../common/utils/endpoint_alert_check.ts | 14 +++++++++ .../side_panel/event_details/index.tsx | 4 +-- .../timeline/body/renderers/constants.tsx | 2 +- .../body/renderers/formatted_field.tsx | 4 +-- 6 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.test.ts create mode 100644 x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.ts diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.tsx index e229c0c6fae49..9cc0b43f52123 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/alert_summary_view.tsx @@ -37,6 +37,7 @@ import { SummaryView } from './summary_view'; import { AlertSummaryRow, getSummaryColumns, SummaryRow } from './helpers'; import { useRuleAsync } from '../../../detections/containers/detection_engine/rules/use_rule_async'; import { LineClamp } from '../line_clamp'; +import { endpointAlertCheck } from '../../utils/endpoint_alert_check'; const StyledEuiDescriptionList = styled(EuiDescriptionList)` padding: 24px 4px 4px; @@ -53,7 +54,7 @@ const fields = [ { id: 'signal.rule.severity', label: ALERTS_HEADERS_SEVERITY }, { id: 'signal.rule.risk_score', label: ALERTS_HEADERS_RISK_SCORE }, { id: 'host.name' }, - { id: 'host.status' }, + { id: 'agent.status' }, { id: 'user.name' }, { id: SOURCE_IP_FIELD_NAME, fieldType: IP_FIELD_TYPE }, { id: DESTINATION_IP_FIELD_NAME, fieldType: IP_FIELD_TYPE }, @@ -178,6 +179,10 @@ const AlertSummaryViewComponent: React.FC<{ timelineId, ]); + const isEndpointAlert = useMemo(() => { + return endpointAlertCheck({ data }); + }, [data]); + const agentId = useMemo(() => { const findAgentId = find({ category: 'agent', field: 'agent.id' }, data)?.values; return findAgentId ? findAgentId[0] : ''; @@ -188,7 +193,7 @@ const AlertSummaryViewComponent: React.FC<{ description: { contextId: timelineId, eventId, - fieldName: 'host.status', + fieldName: 'agent.status', value: agentId, linkValue: undefined, }, @@ -209,7 +214,7 @@ const AlertSummaryViewComponent: React.FC<{ {maybeRule?.note && ( diff --git a/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.test.ts b/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.test.ts new file mode 100644 index 0000000000000..b085fe67d3814 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.test.ts @@ -0,0 +1,31 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import _ from 'lodash'; +import { mockDetailItemData } from '../mock'; +import { endpointAlertCheck } from './endpoint_alert_check'; + +describe('utils', () => { + describe('endpointAlertCheck', () => { + it('should return false if detections data does not come from endpoint rule', () => { + expect(endpointAlertCheck({ data: mockDetailItemData })).toBeFalsy(); + }); + it('should return true if detections data comes from an endpoint rule', () => { + _.remove(mockDetailItemData, function (o) { + return o.field === 'agent.type'; + }); + const mockEndpointDetailItemData = _.concat(mockDetailItemData, { + field: 'agent.type', + originalValue: 'endpoint', + values: ['endpoint'], + isObjectArray: false, + }); + + expect(endpointAlertCheck({ data: mockEndpointDetailItemData })).toBeTruthy(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.ts b/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.ts new file mode 100644 index 0000000000000..e399cec0f3bbe --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/utils/endpoint_alert_check.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { find } from 'lodash/fp'; +import { TimelineEventsDetailsItem } from '../../../common/search_strategy'; + +export const endpointAlertCheck = ({ data }: { data: TimelineEventsDetailsItem[] | null }) => { + const findEndpointAlert = find({ field: 'agent.type' }, data)?.values; + return findEndpointAlert ? findEndpointAlert[0] === 'endpoint' : false; +}; diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx index 76341055f28ef..395538610f567 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/index.tsx @@ -32,6 +32,7 @@ import { } from '../../../../detections/components/host_isolation/translations'; import { ALERT_DETAILS } from './translations'; import { useIsolationPrivileges } from '../../../../common/hooks/endpoint/use_isolate_privileges'; +import { endpointAlertCheck } from '../../../../common/utils/endpoint_alert_check'; const StyledEuiFlyoutBody = styled(EuiFlyoutBody)` .euiFlyoutBody__overflow { @@ -92,8 +93,7 @@ const EventDetailsPanelComponent: React.FC = ({ const isAlert = some({ category: 'signal', field: 'signal.rule.id' }, detailsData); const isEndpointAlert = useMemo(() => { - const findEndpointAlert = find({ category: 'agent', field: 'agent.type' }, detailsData)?.values; - return findEndpointAlert ? findEndpointAlert[0] === 'endpoint' : false; + return endpointAlertCheck({ data: detailsData }); }, [detailsData]); const agentId = useMemo(() => { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/constants.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/constants.tsx index 761d82b482af2..aeb40bed26c8e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/constants.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/constants.tsx @@ -16,4 +16,4 @@ export const REFERENCE_URL_FIELD_NAME = 'reference.url'; export const EVENT_URL_FIELD_NAME = 'event.url'; export const SIGNAL_RULE_NAME_FIELD_NAME = 'signal.rule.name'; export const SIGNAL_STATUS_FIELD_NAME = 'signal.status'; -export const HOST_STATUS_FIELD_NAME = 'host.status'; +export const AGENT_STATUS_FIELD_NAME = 'agent.status'; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx index efb51916e3765..3d5d410abb87e 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/formatted_field.tsx @@ -32,7 +32,7 @@ import { REFERENCE_URL_FIELD_NAME, EVENT_URL_FIELD_NAME, SIGNAL_STATUS_FIELD_NAME, - HOST_STATUS_FIELD_NAME, + AGENT_STATUS_FIELD_NAME, GEO_FIELD_TYPE, } from './constants'; import { RenderRuleName, renderEventModule, renderUrl } from './formatted_field_helpers'; @@ -120,7 +120,7 @@ const FormattedFieldValueComponent: React.FC<{ return ( ); - } else if (fieldName === HOST_STATUS_FIELD_NAME) { + } else if (fieldName === AGENT_STATUS_FIELD_NAME) { return ( Date: Thu, 24 Jun 2021 14:17:09 -0600 Subject: [PATCH 19/25] [Maps] Disable draw mode on layer remove (#103188) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/maps/public/actions/layer_actions.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/x-pack/plugins/maps/public/actions/layer_actions.ts b/x-pack/plugins/maps/public/actions/layer_actions.ts index 8bd79474e7f71..1d239a75d1499 100644 --- a/x-pack/plugins/maps/public/actions/layer_actions.ts +++ b/x-pack/plugins/maps/public/actions/layer_actions.ts @@ -11,6 +11,7 @@ import { Query } from 'src/plugins/data/public'; import { MapStoreState } from '../reducers/store'; import { createLayerInstance, + getEditState, getLayerById, getLayerList, getLayerListRaw, @@ -481,6 +482,11 @@ function removeLayerFromLayerList(layerId: string) { type: REMOVE_LAYER, id: layerId, }); + // Clean up draw state if needed + const editState = getEditState(getState()); + if (layerId === editState?.layerId) { + dispatch(setDrawMode(DRAW_MODE.NONE)); + } }; } From e1ef2ea5cd2d13ee7ff09bfc015dc43ef4120002 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Thu, 24 Jun 2021 14:18:44 -0600 Subject: [PATCH 20/25] [Maps] Disable edit features if editing already enabled for layer (#103300) --- .../__snapshots__/toc_entry.test.tsx.snap | 5 + .../layer_toc/toc_entry/toc_entry.tsx | 1 + .../toc_entry_actions_popover.test.tsx.snap | 115 ++++++++++++++++++ .../toc_entry_actions_popover.test.tsx | 14 +++ .../toc_entry_actions_popover.tsx | 3 +- 5 files changed, 137 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap index 6310b5507dca5..42618d099ffcf 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/__snapshots__/toc_entry.test.tsx.snap @@ -11,6 +11,7 @@ exports[`TOCEntry is rendered 1`] = ` > { openLayerSettings={this._openLayerPanelWithCheck} isEditButtonDisabled={this.props.isEditButtonDisabled} supportsFitToBounds={this.state.supportsFitToBounds} + editModeActiveForLayer={this.props.editModeActiveForLayer} /> {this._renderQuickActions()} diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/__snapshots__/toc_entry_actions_popover.test.tsx.snap b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/__snapshots__/toc_entry_actions_popover.test.tsx.snap index 5068a5dc1ad71..5d1fc8e28f993 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/__snapshots__/toc_entry_actions_popover.test.tsx.snap +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/__snapshots__/toc_entry_actions_popover.test.tsx.snap @@ -115,6 +115,121 @@ exports[`TOCEntryActionsPopover is rendered 1`] = ` `; +exports[`TOCEntryActionsPopover should disable Edit features when edit mode active for layer 1`] = ` + + } + className="mapLayTocActions" + closePopover={[Function]} + display="inlineBlock" + hasArrow={true} + id="testLayer" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" +> + , + "name": "Fit to data", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "layerVisibilityToggleButton", + "icon": , + "name": "Hide layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "layerSettingsButton", + "disabled": false, + "icon": , + "name": "Edit layer settings", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "cloneLayerButton", + "icon": , + "name": "Clone layer", + "onClick": [Function], + "toolTipContent": null, + }, + Object { + "data-test-subj": "removeLayerButton", + "icon": , + "name": "Remove layer", + "onClick": [Function], + "toolTipContent": null, + }, + ], + "title": "Layer actions", + }, + ] + } + size="m" + /> + +`; + exports[`TOCEntryActionsPopover should disable fit to data when supportsFitToBounds is false 1`] = ` {}, enablePointEditing: () => {}, openLayerSettings: () => {}, + editModeActiveForLayer: false, }; describe('TOCEntryActionsPopover', () => { @@ -100,4 +101,17 @@ describe('TOCEntryActionsPopover', () => { expect(component).toMatchSnapshot(); }); + + test('should disable Edit features when edit mode active for layer', async () => { + const component = shallow( + + ); + + // Ensure all promises resolve + await new Promise((resolve) => process.nextTick(resolve)); + // Ensure the state changes are reflected + component.update(); + + expect(component).toMatchSnapshot(); + }); }); diff --git a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx index ab7a54be37404..83b4d2c2a756b 100644 --- a/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx +++ b/x-pack/plugins/maps/public/connected_components/right_side_controls/layer_control/layer_toc/toc_entry/toc_entry_actions_popover/toc_entry_actions_popover.tsx @@ -36,6 +36,7 @@ export interface Props { removeLayer: (layerId: string) => void; supportsFitToBounds: boolean; toggleVisible: (layerId: string) => void; + editModeActiveForLayer: boolean; } interface State { @@ -170,7 +171,7 @@ export class TOCEntryActionsPopover extends Component { defaultMessage: 'Edit features only supported for document layers without clustering, joins, or time filtering', }), - disabled: !this.state.isFeatureEditingEnabled, + disabled: !this.state.isFeatureEditingEnabled || this.props.editModeActiveForLayer, onClick: async () => { this._closePopover(); const supportedShapeTypes = await (this.props.layer.getSource() as ESSearchSource).getSupportedShapeTypes(); From 60086a9aac1fe2fbaa4211210bcb9b3446c1f83a Mon Sep 17 00:00:00 2001 From: Constance Date: Thu, 24 Jun 2021 13:30:02 -0700 Subject: [PATCH 21/25] Fix Engine Overview not properly stretching to full page height (#103337) - Caused by the wrapping
around the child views - removing that div and moving the `data-test-subj` hooks to the individual views fixes the issue --- .../components/engine_overview/engine_overview.test.tsx | 5 ----- .../components/engine_overview/engine_overview.tsx | 6 +----- .../components/engine_overview/engine_overview_empty.tsx | 1 + .../components/engine_overview/engine_overview_metrics.tsx | 1 + 4 files changed, 3 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.test.tsx index a2e0ba4fcd44d..01472987e4d48 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.test.tsx @@ -29,11 +29,6 @@ describe('EngineOverview', () => { setMockValues(values); }); - it('renders', () => { - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="EngineOverview"]')).toHaveLength(1); - }); - describe('EmptyEngineOverview', () => { it('renders when the engine has no documents & the user can add documents', () => { const myRole = { canManageEngineDocuments: true, canViewEngineCredentials: true }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx index a3f98d8c13e8e..e966709dc1084 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.tsx @@ -25,9 +25,5 @@ export const EngineOverview: React.FC = () => { const canAddDocuments = canManageEngineDocuments && canViewEngineCredentials; const showEngineOverview = !isEngineEmpty || !canAddDocuments || isMetaEngine; - return ( -
- {showEngineOverview ? : } -
- ); + return showEngineOverview ? : ; }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx index 27d9c3723f126..6f8332e1e332e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx @@ -34,6 +34,7 @@ export const EmptyEngineOverview: React.FC = () => { , ], }} + data-test-subj="EngineOverview" > diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.tsx index 3cc7138623735..9c3a900dfe115 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_metrics.tsx @@ -36,6 +36,7 @@ export const EngineOverviewMetrics: React.FC = () => { }), }} isLoading={dataLoading} + data-test-subj="EngineOverview" > From d5f68eef4f391a2cf9efcf57e258bbf594cf5f0a Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Thu, 24 Jun 2021 16:46:50 -0400 Subject: [PATCH 22/25] [Lens] Fix formula formatting in Metric visualization type (#103167) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../metric_visualization/expression.test.tsx | 98 +++++++++++++++---- .../metric_visualization/expression.tsx | 2 +- 2 files changed, 82 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/lens/public/metric_visualization/expression.test.tsx b/x-pack/plugins/lens/public/metric_visualization/expression.test.tsx index 2e189e094ef01..b31125a1912ef 100644 --- a/x-pack/plugins/lens/public/metric_visualization/expression.test.tsx +++ b/x-pack/plugins/lens/public/metric_visualization/expression.test.tsx @@ -20,17 +20,22 @@ function sampleArgs() { l1: { type: 'datatable', columns: [ - { id: 'a', name: 'a', meta: { type: 'string' } }, + // Simulating a calculated column like a formula + { id: 'a', name: 'a', meta: { type: 'string', params: { id: 'string' } } }, { id: 'b', name: 'b', meta: { type: 'string' } }, - { id: 'c', name: 'c', meta: { type: 'number' } }, + { + id: 'c', + name: 'c', + meta: { type: 'number', params: { id: 'percent', params: { format: '0.000%' } } }, + }, ], - rows: [{ a: 10110, b: 2, c: 3 }], + rows: [{ a: 'last', b: 'last', c: 3 }], }, }, }; const args: MetricConfig = { - accessor: 'a', + accessor: 'c', layerId: 'l1', title: 'My fanci metric chart', description: 'Fancy chart description', @@ -39,7 +44,7 @@ function sampleArgs() { }; const noAttributesArgs: MetricConfig = { - accessor: 'a', + accessor: 'c', layerId: 'l1', title: '', description: '', @@ -65,11 +70,17 @@ describe('metric_expression', () => { }); describe('MetricChart component', () => { - test('it renders the all attributes when passed (title, description, metricTitle, value)', () => { + test('it renders all attributes when passed (title, description, metricTitle, value)', () => { const { data, args } = sampleArgs(); expect( - shallow( x as IFieldFormat} />) + shallow( + ({ convert: (x) => x } as IFieldFormat)} + /> + ) ).toMatchInlineSnapshot(` { } } > - 10110 + 3 +
+
+ My fanci metric chart +
+ + + `); + }); + + test('it renders strings', () => { + const { data, args } = sampleArgs(); + args.accessor = 'a'; + + expect( + shallow( + ({ convert: (x) => x } as IFieldFormat)} + /> + ) + ).toMatchInlineSnapshot(` + + +
+ last
{ x as IFieldFormat} + formatFactory={() => ({ convert: (x) => x } as IFieldFormat)} /> ) ).toMatchInlineSnapshot(` @@ -130,7 +186,7 @@ describe('metric_expression', () => { } } > - 10110 + 3
{ x as IFieldFormat} + formatFactory={() => ({ convert: (x) => x } as IFieldFormat)} /> ) ).toMatchInlineSnapshot(` @@ -174,7 +230,7 @@ describe('metric_expression', () => { } } > - 10110 + 3
@@ -189,7 +245,7 @@ describe('metric_expression', () => { x as IFieldFormat} + formatFactory={() => ({ convert: (x) => x } as IFieldFormat)} /> ) ).toMatchInlineSnapshot(` @@ -202,14 +258,14 @@ describe('metric_expression', () => { test('it renders an EmptyPlaceholder when null value is passed as data', () => { const { data, noAttributesArgs } = sampleArgs(); - data.tables.l1.rows[0].a = null; + data.tables.l1.rows[0].c = null; expect( shallow( x as IFieldFormat} + formatFactory={() => ({ convert: (x) => x } as IFieldFormat)} /> ) ).toMatchInlineSnapshot(` @@ -222,14 +278,14 @@ describe('metric_expression', () => { test('it renders 0 value', () => { const { data, noAttributesArgs } = sampleArgs(); - data.tables.l1.rows[0].a = 0; + data.tables.l1.rows[0].c = 0; expect( shallow( x as IFieldFormat} + formatFactory={() => ({ convert: (x) => x } as IFieldFormat)} /> ) ).toMatchInlineSnapshot(` @@ -264,5 +320,13 @@ describe('metric_expression', () => { `); }); + + test('it finds the right column to format', () => { + const { data, args } = sampleArgs(); + const factory = jest.fn(() => ({ convert: (x) => x } as IFieldFormat)); + + shallow(); + expect(factory).toHaveBeenCalledWith({ id: 'percent', params: { format: '0.000%' } }); + }); }); }); diff --git a/x-pack/plugins/lens/public/metric_visualization/expression.tsx b/x-pack/plugins/lens/public/metric_visualization/expression.tsx index 70b2cb17c7fe1..60d9d66bce995 100644 --- a/x-pack/plugins/lens/public/metric_visualization/expression.tsx +++ b/x-pack/plugins/lens/public/metric_visualization/expression.tsx @@ -127,7 +127,7 @@ export function MetricChart({ return ; } - const column = firstTable.columns[0]; + const column = firstTable.columns.find(({ id }) => id === accessor)!; const row = firstTable.rows[0]; // NOTE: Cardinality and Sum never receives "null" as value, but always 0, even for empty dataset. From b12095b079d7836e554ab0b15702574398fe4149 Mon Sep 17 00:00:00 2001 From: Chris Cowan Date: Thu, 24 Jun 2021 14:13:15 -0700 Subject: [PATCH 23/25] [Metrics UI] Prevent saved views from trampling URL state (#103146) * [Metrics UI] Prevent saved views from trampling URL state * Adding space back in --- .../public/containers/saved_view/saved_view.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/infra/public/containers/saved_view/saved_view.tsx b/x-pack/plugins/infra/public/containers/saved_view/saved_view.tsx index 56a2a13e31ff7..c54a2a69a994c 100644 --- a/x-pack/plugins/infra/public/containers/saved_view/saved_view.tsx +++ b/x-pack/plugins/infra/public/containers/saved_view/saved_view.tsx @@ -255,12 +255,21 @@ export const useSavedView = (props: Props) => { }, [urlState, setUrlState, currentView, defaultViewId, data]); useEffect(() => { - if (!currentView && !loading && data) { + if (!currentView && !loading && data && shouldLoadDefault) { const viewToSet = views.find((v) => v.id === urlState.viewId); if (viewToSet) setCurrentView(viewToSet); else loadDefaultViewIfSet(); } - }, [loading, currentView, data, views, setCurrentView, loadDefaultViewIfSet, urlState.viewId]); + }, [ + loading, + currentView, + data, + views, + setCurrentView, + loadDefaultViewIfSet, + urlState.viewId, + shouldLoadDefault, + ]); return { views, From 45b660172ae868c4e6ddce6e3f88c9ba7e374f87 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 24 Jun 2021 16:19:01 -0500 Subject: [PATCH 24/25] skip suite failing es promotion. #103364 --- .../apis/management/index_lifecycle_management/policies.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/policies.js b/x-pack/test/api_integration/apis/management/index_lifecycle_management/policies.js index 756fda7566843..d59d364c38827 100644 --- a/x-pack/test/api_integration/apis/management/index_lifecycle_management/policies.js +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/policies.js @@ -32,7 +32,8 @@ export default function ({ getService }) { const { addPolicyToIndex } = registerIndexHelpers({ supertest }); - describe('policies', () => { + // failing ES promotion https://github.com/elastic/kibana/issues/103364 + describe.skip('policies', () => { after(() => Promise.all([cleanUpEsResources(), cleanUpPolicies()])); describe('list', () => { From c1ced880bc3b6d3cf819576e0001d46380fb7495 Mon Sep 17 00:00:00 2001 From: Ross Wolf <31489089+rw-access@users.noreply.github.com> Date: Thu, 24 Jun 2021 15:31:25 -0600 Subject: [PATCH 25/25] [Detections] Adds automatic updating for Prebuilt Security Detection Rules package (#101846) * Automatically install and update the security_detection_engine package * Remove security_detection_engine from required Fleet packages * Update fleet package-registry image * Add sha256: to the distribution package * Use distribution from https://beats-ci.elastic.co/job/Ingest-manager/job/release-distribution/152 * Change fleet required packag * Fix bad merge * Update rules to 0.13.1 package * Fix NOTICE.txt --- NOTICE.txt | 18 ++-- .../public/app/home/index.tsx | 4 +- ...de.ts => use_upgrade_security_packages.ts} | 20 ++--- .../apm_403_response_to_a_post.json | 2 +- .../apm_405_response_method_not_allowed.json | 2 +- .../apm_null_user_agent.json | 2 +- .../apm_sqlmap_user_agent.json | 2 +- ...tion_added_to_google_workspace_domain.json | 2 +- ...tempt_to_deactivate_okta_network_zone.json | 2 +- .../attempt_to_delete_okta_network_zone.json | 2 +- ...collection_cloudtrail_logging_created.json | 2 +- ...ion_gcp_pub_sub_subscription_creation.json | 2 +- ...collection_gcp_pub_sub_topic_creation.json | 2 +- ...llection_microsoft_365_new_inbox_rule.json | 2 +- ...collection_update_event_hub_auth_rule.json | 2 +- ...d_control_certutil_network_connection.json | 7 +- ...mand_and_control_cobalt_strike_beacon.json | 2 +- ...cobalt_strike_default_teamserver_cert.json | 2 +- ..._control_dns_directly_to_the_internet.json | 7 +- ...nd_and_control_dns_tunneling_nslookup.json | 2 +- ...download_rar_powershell_from_internet.json | 7 +- .../command_and_control_fin7_c2_behavior.json | 2 +- .../command_and_control_halfbaked_beacon.json | 2 +- ...d_control_nat_traversal_port_activity.json | 2 +- .../command_and_control_port_26_activity.json | 2 +- ...te_desktop_protocol_from_the_internet.json | 7 +- ...mand_and_control_telnet_port_activity.json | 2 +- ...l_network_computing_from_the_internet.json | 7 +- ...ual_network_computing_to_the_internet.json | 7 +- ...l_access_attempted_bypass_of_okta_mfa.json | 2 +- ...mpts_to_brute_force_okta_user_account.json | 10 ++- ...ccess_aws_iam_assume_role_brute_force.json | 2 +- ...ial_access_collection_sensitive_files.json | 2 +- ...dential_access_dumping_hashes_bi_cmds.json | 2 +- ...ial_access_iam_user_addition_to_group.json | 2 +- .../credential_access_kerberosdump_kcc.json | 2 +- .../credential_access_key_vault_modified.json | 2 +- ..._365_brute_force_user_account_attempt.json | 4 +- ...65_potential_password_spraying_attack.json | 2 +- ...ential_access_mitm_localhost_webproxy.json | 2 +- ...okta_brute_force_or_password_spraying.json | 2 +- ...ntial_access_potential_ssh_bruteforce.json | 2 +- ...cess_root_console_failure_brute_force.json | 2 +- ..._access_secretsmanager_getsecretvalue.json | 2 +- ...ccess_storage_account_key_regenerated.json | 2 +- .../credential_access_systemkey_dumping.json | 2 +- .../defense_evasion_amsienable_key_mod.json | 57 ++++++++++++ ...vasion_apple_softupdates_modification.json | 2 +- ...evasion_attempt_to_disable_gatekeeper.json | 2 +- ...tempt_to_disable_iptables_or_firewall.json | 2 +- ...ion_attempt_to_disable_syslog_service.json | 2 +- ...e_application_credential_modification.json | 2 +- ...on_azure_diagnostic_settings_deletion.json | 2 +- ...sion_azure_service_principal_addition.json | 2 +- ..._base32_encoding_or_decoding_activity.json | 2 +- ...vasion_clearing_windows_security_logs.json | 2 +- ...se_evasion_cloudtrail_logging_deleted.json | 2 +- ..._evasion_cloudtrail_logging_suspended.json | 2 +- ...nse_evasion_cloudwatch_alarm_deletion.json | 2 +- ..._evasion_config_service_rule_deletion.json | 2 +- ...vasion_configuration_recorder_stopped.json | 2 +- .../defense_evasion_cve_2020_0601.json | 2 +- ...fense_evasion_disable_selinux_attempt.json | 2 +- ...defense_evasion_ec2_flow_log_deletion.json | 2 +- ...ense_evasion_ec2_network_acl_deletion.json | 2 +- .../defense_evasion_event_hub_deletion.json | 2 +- ...fense_evasion_file_deletion_via_shred.json | 2 +- ...defense_evasion_file_mod_writable_dir.json | 2 +- ...ense_evasion_firewall_policy_deletion.json | 2 +- ...nse_evasion_gcp_firewall_rule_created.json | 2 +- ...nse_evasion_gcp_firewall_rule_deleted.json | 2 +- ...se_evasion_gcp_firewall_rule_modified.json | 2 +- ...e_evasion_gcp_logging_bucket_deletion.json | 2 +- ...nse_evasion_gcp_logging_sink_deletion.json | 2 +- ...ion_gcp_pub_sub_subscription_deletion.json | 2 +- ...se_evasion_gcp_pub_sub_topic_deletion.json | 2 +- ...storage_bucket_configuration_modified.json | 2 +- ...p_storage_bucket_permissions_modified.json | 2 +- ...e_evasion_guardduty_detector_deletion.json | 2 +- .../defense_evasion_hidden_file_dir_tmp.json | 2 +- .../defense_evasion_injection_msbuild.json | 2 +- ...ense_evasion_install_root_certificate.json | 2 +- ...defense_evasion_kernel_module_removal.json | 2 +- ...osoft_365_exchange_dlp_policy_removed.json | 2 +- ...change_malware_filter_policy_deletion.json | 2 +- ..._365_exchange_malware_filter_rule_mod.json | 2 +- ...65_exchange_safe_attach_rule_disabled.json | 2 +- ...isc_lolbin_connecting_to_the_internet.json | 7 +- ..._evasion_modify_environment_launchctl.json | 2 +- .../defense_evasion_msxsl_network.json | 7 +- ...ense_evasion_network_watcher_deletion.json | 2 +- ...sion_s3_bucket_configuration_deletion.json | 2 +- .../defense_evasion_safari_config_change.json | 2 +- ...dboxed_office_app_suspicious_zip_file.json | 2 +- ...vasion_stop_process_service_threshold.json | 2 +- ...picious_execution_from_mounted_device.json | 89 +++++++++++++++++++ ...ser_password_reset_or_unlock_attempts.json | 12 +-- ...vasion_tcc_bypass_mounted_apfs_access.json | 2 +- ..._evasion_unload_endpointsecurity_kext.json | 2 +- ...nusual_network_connection_via_dllhost.json | 51 +++++++++++ ...usual_network_connection_via_rundll32.json | 7 +- .../defense_evasion_waf_acl_deletion.json | 2 +- ...asion_waf_rule_or_rule_group_deletion.json | 2 +- .../discovery_blob_container_access_mod.json | 2 +- .../discovery_kernel_module_enumeration.json | 2 +- ...covery_virtual_machine_fingerprinting.json | 2 +- ...d_to_google_workspace_trusted_domains.json | 2 +- .../elastic_endpoint_security.json | 2 +- .../endgame_adversary_behavior_detected.json | 2 +- .../endgame_cred_dumping_detected.json | 2 +- .../endgame_cred_dumping_prevented.json | 2 +- .../endgame_cred_manipulation_detected.json | 2 +- .../endgame_cred_manipulation_prevented.json | 2 +- .../endgame_exploit_detected.json | 2 +- .../endgame_exploit_prevented.json | 2 +- .../endgame_malware_detected.json | 2 +- .../endgame_malware_prevented.json | 2 +- .../endgame_permission_theft_detected.json | 2 +- .../endgame_permission_theft_prevented.json | 2 +- .../endgame_process_injection_detected.json | 2 +- .../endgame_process_injection_prevented.json | 2 +- .../endgame_ransomware_detected.json | 2 +- .../endgame_ransomware_prevented.json | 2 +- ...and_prompt_connecting_to_the_internet.json | 7 +- .../execution_command_virtual_machine.json | 2 +- ...vasion_electron_app_childproc_node_js.json | 2 +- ...le_program_connecting_to_the_internet.json | 7 +- ...ution_installer_spawned_network_event.json | 7 +- ...on_pentest_eggshell_remote_admin_tool.json | 2 +- .../execution_perl_tty_shell.json | 2 +- .../execution_python_tty_shell.json | 2 +- ...er_program_connecting_to_the_internet.json | 7 +- ...ing_osascript_exec_followed_by_netcon.json | 7 +- ...ltration_ec2_snapshot_change_activity.json | 2 +- .../exfiltration_ec2_vm_export_failure.json | 70 +++++++++++++++ ...tration_gcp_logging_sink_modification.json | 2 +- ..._365_exchange_transport_rule_creation.json | 2 +- ...osoft_365_exchange_transport_rule_mod.json | 2 +- .../prepackaged_rules/external_alerts.json | 2 +- .../google_workspace_admin_role_deletion.json | 2 +- ...le_workspace_mfa_enforcement_disabled.json | 2 +- .../google_workspace_policy_modified.json | 2 +- ...pact_attempt_to_revoke_okta_api_token.json | 2 +- ...pact_azure_automation_runbook_deleted.json | 2 +- .../impact_cloudtrail_logging_updated.json | 2 +- .../impact_cloudwatch_log_group_deletion.json | 2 +- ...impact_cloudwatch_log_stream_deletion.json | 2 +- .../impact_ec2_disable_ebs_encryption.json | 2 +- .../impact_gcp_iam_role_deletion.json | 2 +- .../impact_gcp_service_account_deleted.json | 2 +- .../impact_gcp_service_account_disabled.json | 2 +- .../impact_gcp_storage_bucket_deleted.json | 2 +- ...virtual_private_cloud_network_deleted.json | 2 +- ...p_virtual_private_cloud_route_created.json | 2 +- ...p_virtual_private_cloud_route_deleted.json | 2 +- .../impact_iam_deactivate_mfa_device.json | 2 +- .../impact_iam_group_deletion.json | 2 +- .../impact_possible_okta_dos_attack.json | 2 +- .../impact_rds_cluster_deletion.json | 2 +- .../impact_rds_instance_cluster_stoppage.json | 2 +- .../impact_resource_group_deletion.json | 2 +- .../rules/prepackaged_rules/index.ts | 10 ++- ...ure_active_directory_high_risk_signin.json | 2 +- ...re_active_directory_powershell_signin.json | 2 +- ...tack_via_azure_registered_application.json | 2 +- .../initial_access_console_login_root.json | 2 +- ...ial_access_external_guest_user_invite.json | 2 +- ...l_access_gcp_iam_custom_role_creation.json | 2 +- .../initial_access_login_failures.json | 2 +- .../initial_access_login_location.json | 2 +- .../initial_access_login_sessions.json | 2 +- .../initial_access_login_time.json | 2 +- ...5_exchange_anti_phish_policy_deletion.json | 2 +- ...soft_365_exchange_anti_phish_rule_mod.json | 2 +- ...osoft_365_exchange_safelinks_disabled.json | 2 +- .../initial_access_password_recovery.json | 2 +- ...mote_procedure_call_from_the_internet.json | 7 +- ...remote_procedure_call_to_the_internet.json | 7 +- ...file_sharing_activity_to_the_internet.json | 2 +- ...icious_activity_reported_by_okta_user.json | 2 +- ...al_access_unsecure_elasticsearch_node.json | 2 +- .../initial_access_via_system_manager.json | 2 +- ..._access_zoom_meeting_with_no_passcode.json | 2 +- ...ential_access_kerberos_bifrostconsole.json | 2 +- .../lateral_movement_dns_server_overflow.json | 2 +- ...ral_movement_remote_ssh_login_enabled.json | 2 +- ...ment_telnet_network_activity_external.json | 7 +- ...ment_telnet_network_activity_internal.json | 7 +- .../linux_hping_activity.json | 2 +- .../linux_iodine_activity.json | 2 +- .../linux_nping_activity.json | 2 +- ...nux_process_started_in_temp_directory.json | 2 +- .../linux_strace_activity.json | 2 +- ...led_for_google_workspace_organization.json | 2 +- ...exchange_dkim_signing_config_disabled.json | 2 +- ..._teams_custom_app_interaction_allowed.json | 2 +- .../ml_high_count_network_denies.json | 6 +- .../ml_high_count_network_events.json | 6 +- .../ml_linux_anomalous_metadata_process.json | 7 +- .../ml_linux_anomalous_metadata_user.json | 7 +- ...linux_anomalous_network_port_activity.json | 7 +- .../ml_linux_anomalous_process_all_hosts.json | 7 +- .../ml_linux_anomalous_user_name.json | 7 +- .../ml_rare_destination_country.json | 6 +- .../ml_rare_process_by_host_linux.json | 7 +- .../ml_rare_process_by_host_windows.json | 7 +- .../ml_spike_in_traffic_to_a_country.json | 6 +- ...ml_windows_anomalous_metadata_process.json | 7 +- .../ml_windows_anomalous_metadata_user.json | 7 +- ...ml_windows_anomalous_network_activity.json | 7 +- .../ml_windows_anomalous_path_activity.json | 7 +- ...l_windows_anomalous_process_all_hosts.json | 7 +- ...ml_windows_anomalous_process_creation.json | 7 +- .../ml_windows_anomalous_user_name.json | 7 +- .../rules/prepackaged_rules/notice.ts | 18 ++-- ...ttempt_to_deactivate_okta_application.json | 2 +- ...kta_attempt_to_deactivate_okta_policy.json | 2 +- ...ttempt_to_deactivate_okta_policy_rule.json | 2 +- ...ta_attempt_to_delete_okta_application.json | 2 +- .../okta_attempt_to_delete_okta_policy.json | 2 +- ...ta_attempt_to_delete_okta_policy_rule.json | 2 +- ...ta_attempt_to_modify_okta_application.json | 2 +- ...a_attempt_to_modify_okta_network_zone.json | 2 +- .../okta_attempt_to_modify_okta_policy.json | 2 +- ...ta_attempt_to_modify_okta_policy_rule.json | 2 +- ..._or_delete_application_sign_on_policy.json | 2 +- ...threat_detected_by_okta_threatinsight.json | 2 +- ...stence_account_creation_hide_at_logon.json | 2 +- ...tor_privileges_assigned_to_okta_group.json | 2 +- ...inistrator_role_assigned_to_okta_user.json | 2 +- ...ence_attempt_to_create_okta_api_token.json | 2 +- ..._deactivate_mfa_for_okta_user_account.json | 2 +- ...set_mfa_factors_for_okta_user_account.json | 2 +- ...ence_azure_automation_account_created.json | 2 +- ...utomation_runbook_created_or_modified.json | 2 +- ...ence_azure_automation_webhook_created.json | 2 +- ...re_conditional_access_policy_modified.json | 2 +- ...nce_azure_pim_user_added_global_admin.json | 2 +- ...ged_identity_management_role_modified.json | 2 +- ..._access_authorization_plugin_creation.json | 2 +- ...l_access_modify_auth_module_or_config.json | 2 +- ...credential_access_modify_ssh_binaries.json | 2 +- ...launch_agent_deamon_logonitem_process.json | 2 +- ...rectory_services_plugins_modification.json | 2 +- ...e_docker_shortcuts_plist_modification.json | 2 +- .../persistence_ec2_network_acl_creation.json | 2 +- .../persistence_enable_root_account.json | 2 +- ..._gcp_iam_service_account_key_deletion.json | 2 +- ...e_gcp_key_created_for_service_account.json | 2 +- ...rsistence_gcp_service_account_created.json | 2 +- ...workspace_admin_role_assigned_to_user.json | 2 +- ...a_domain_wide_delegation_of_authority.json | 2 +- ...e_workspace_custom_admin_role_created.json | 2 +- ...stence_google_workspace_role_modified.json | 2 +- .../persistence_iam_group_creation.json | 2 +- ...stence_loginwindow_plist_modification.json | 2 +- ...rsistence_mfa_disabled_for_azure_user.json | 2 +- ...5_exchange_management_role_assignment.json | 2 +- ...oft_365_teams_external_access_enabled.json | 2 +- ...rosoft_365_teams_guest_access_enabled.json | 2 +- ...ersistence_periodic_tasks_file_mdofiy.json | 2 +- .../persistence_rds_cluster_creation.json | 2 +- ...sistence_shell_activity_by_web_server.json | 2 +- ...ersistence_shell_profile_modification.json | 2 +- ...ence_ssh_authorized_keys_modification.json | 2 +- ...ence_suspicious_calendar_modification.json | 2 +- ...stence_suspicious_com_hijack_registry.json | 4 +- ..._added_as_owner_for_azure_application.json | 2 +- ..._as_owner_for_azure_service_principal.json | 2 +- ...tence_via_atom_init_file_modification.json | 2 +- ...lege_escalation_echo_nopasswd_sudoers.json | 2 +- ...calation_explicit_creds_via_scripting.json | 2 +- ...alation_exploit_adobe_acrobat_updater.json | 2 +- ...lation_ld_preload_shared_object_modif.json | 2 +- ..._escalation_local_user_added_to_admin.json | 2 +- ...ge_escalation_persistence_phantom_dll.json | 4 +- ...ilege_escalation_root_crontab_filemod.json | 2 +- ...ege_escalation_root_login_without_mfa.json | 2 +- ...ation_setuid_setgid_bit_set_via_chmod.json | 2 +- ...ilege_escalation_sudo_buffer_overflow.json | 2 +- ...privilege_escalation_sudoers_file_mod.json | 2 +- ...ege_escalation_updateassumerolepolicy.json | 2 +- .../threat_intel_module_match.json | 2 +- .../fleet_api_integration/apis/epm/delete.ts | 2 +- x-pack/test/fleet_api_integration/config.ts | 3 +- 285 files changed, 728 insertions(+), 362 deletions(-) rename x-pack/plugins/security_solution/public/common/hooks/{endpoint/upgrade.ts => use_upgrade_security_packages.ts} (80%) create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_amsienable_key_mod.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_execution_from_mounted_device.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unusual_network_connection_via_dllhost.json create mode 100644 x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_ec2_vm_export_failure.json diff --git a/NOTICE.txt b/NOTICE.txt index b0f7e65f46fa9..4ede43610ca7b 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -149,17 +149,17 @@ SOFTWARE. --- Detection Rules -Copyright 2020 Elasticsearch B.V. +Copyright 2021 Elasticsearch B.V. --- This product bundles rules based on https://github.com/BlueTeamLabs/sentinel-attack -which is available under a "MIT" license. The files based on this license are: +which is available under a "MIT" license. The rules based on this license are: -- defense_evasion_via_filter_manager -- discovery_process_discovery_via_tasklist_command -- persistence_priv_escalation_via_accessibility_features -- persistence_via_application_shimming -- defense_evasion_execution_via_trusted_developer_utilities +- "Potential Evasion via Filter Manager" (06dceabf-adca-48af-ac79-ffdf4c3b1e9a) +- "Process Discovery via Tasklist" (cc16f774-59f9-462d-8b98-d27ccd4519ec) +- "Potential Modification of Accessibility Binaries" (7405ddf1-6c8e-41ce-818f-48bea6bcaed8) +- "Potential Application Shimming via Sdbinst" (fd4a992d-6130-4802-9ff8-829b89ae801f) +- "Trusted Developer Application Usage" (9d110cb3-5f4b-4c9a-b9f5-53f0a1707ae1) MIT License @@ -185,9 +185,9 @@ SOFTWARE. --- This product bundles rules based on https://github.com/FSecureLABS/leonidas -which is available under a "MIT" license. The files based on this license are: +which is available under a "MIT" license. The rules based on this license are: -- credential_access_secretsmanager_getsecretvalue.toml +- "AWS Access Secret in Secrets Manager" (a00681e3-9ed6-447c-ab2c-be648821c622) MIT License diff --git a/x-pack/plugins/security_solution/public/app/home/index.tsx b/x-pack/plugins/security_solution/public/app/home/index.tsx index 9a57ab3fc3a73..17a6fab103d6f 100644 --- a/x-pack/plugins/security_solution/public/app/home/index.tsx +++ b/x-pack/plugins/security_solution/public/app/home/index.tsx @@ -17,7 +17,7 @@ import { useInitSourcerer, useSourcererScope } from '../../common/containers/sou import { useKibana } from '../../common/lib/kibana'; import { DETECTIONS_SUB_PLUGIN_ID } from '../../../common/constants'; import { SourcererScopeName } from '../../common/store/sourcerer/model'; -import { useUpgradeEndpointPackage } from '../../common/hooks/endpoint/upgrade'; +import { useUpgradeSecurityPackages } from '../../common/hooks/use_upgrade_security_packages'; import { GlobalHeader } from './global_header'; import { SecuritySolutionTemplateWrapper } from './template_wrapper'; @@ -56,7 +56,7 @@ const HomePageComponent: React.FC = ({ // tabs in the app. This is useful for keeping the endpoint package as up to date as possible until // a background task solution can be built on the server side. Once a background task solution is available we // can remove this. - useUpgradeEndpointPackage(); + useUpgradeSecurityPackages(); return ( diff --git a/x-pack/plugins/security_solution/public/common/hooks/endpoint/upgrade.ts b/x-pack/plugins/security_solution/public/common/hooks/use_upgrade_security_packages.ts similarity index 80% rename from x-pack/plugins/security_solution/public/common/hooks/endpoint/upgrade.ts rename to x-pack/plugins/security_solution/public/common/hooks/use_upgrade_security_packages.ts index 8e083b3c6b5f2..6a3afccd8794d 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/endpoint/upgrade.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/use_upgrade_security_packages.ts @@ -6,31 +6,31 @@ */ import { useEffect } from 'react'; -import { HttpFetchOptions, HttpStart } from 'src/core/public'; -import { useKibana } from '../../../../../../../src/plugins/kibana_react/public'; +import { HttpFetchOptions, HttpStart } from 'kibana/public'; +import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; import { epmRouteService, appRoutesService, CheckPermissionsResponse, BulkInstallPackagesResponse, -} from '../../../../../fleet/common'; -import { StartServices } from '../../../types'; -import { useIngestEnabledCheck } from './ingest_enabled'; +} from '../../../../fleet/common'; +import { StartServices } from '../../types'; +import { useIngestEnabledCheck } from './endpoint/ingest_enabled'; /** - * Requests that the endpoint package be upgraded to the latest version + * Requests that the endpoint and security_detection_engine package be upgraded to the latest version * * @param http an http client for sending the request * @param options an object containing options for the request */ -const sendUpgradeEndpointPackage = async ( +const sendUpgradeSecurityPackages = async ( http: HttpStart, options: HttpFetchOptions = {} ): Promise => { return http.post(epmRouteService.getBulkInstallPath(), { ...options, body: JSON.stringify({ - packages: ['endpoint'], + packages: ['endpoint', 'security_detection_engine'], }), }); }; @@ -51,7 +51,7 @@ const sendCheckPermissions = async ( }); }; -export const useUpgradeEndpointPackage = () => { +export const useUpgradeSecurityPackages = () => { const context = useKibana(); const { allEnabled: ingestEnabled } = useIngestEnabledCheck(); @@ -79,7 +79,7 @@ export const useUpgradeEndpointPackage = () => { } // ignore the response for now since we aren't notifying the user - await sendUpgradeEndpointPackage(context.services.http, { signal }); + await sendUpgradeSecurityPackages(context.services.http, { signal }); } catch (error) { // Ignore Errors, since this should not hinder the user's ability to use the UI diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_403_response_to_a_post.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_403_response_to_a_post.json index 4c40216391c8b..76ba58be0a428 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_403_response_to_a_post.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_403_response_to_a_post.json @@ -12,7 +12,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Web Application Suspicious Activity: POST Request Declined", - "query": "http.response.status_code:403 and http.request.method:post", + "query": "http.response.status_code:403 and http.request.method:post\n", "references": [ "https://en.wikipedia.org/wiki/HTTP_403" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_405_response_method_not_allowed.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_405_response_method_not_allowed.json index 40138f470c631..0633004273952 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_405_response_method_not_allowed.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_405_response_method_not_allowed.json @@ -12,7 +12,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Web Application Suspicious Activity: Unauthorized Method", - "query": "http.response.status_code:405", + "query": "http.response.status_code:405\n", "references": [ "https://en.wikipedia.org/wiki/HTTP_405" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_null_user_agent.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_null_user_agent.json index a2e9b130f0840..87bbfd727cdf3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_null_user_agent.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_null_user_agent.json @@ -30,7 +30,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Web Application Suspicious Activity: No User Agent", - "query": "url.path:*", + "query": "url.path:*\n", "references": [ "https://en.wikipedia.org/wiki/User_agent" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_sqlmap_user_agent.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_sqlmap_user_agent.json index ec65f7cb57661..334cf78b4338c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_sqlmap_user_agent.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/apm_sqlmap_user_agent.json @@ -12,7 +12,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Web Application Suspicious Activity: sqlmap User Agent", - "query": "user_agent.original:\"sqlmap/1.3.11#stable (http://sqlmap.org)\"", + "query": "user_agent.original:\"sqlmap/1.3.11#stable (http://sqlmap.org)\"\n", "references": [ "http://sqlmap.org/" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/application_added_to_google_workspace_domain.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/application_added_to_google_workspace_domain.json index b447e59e71435..c45d377645b05 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/application_added_to_google_workspace_domain.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/application_added_to_google_workspace_domain.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "Application Added to Google Workspace Domain", "note": "## Config\n\nThe Google Workspace Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n\n### Important Information Regarding Google Workspace Event Lag Times\n- As per Google's documentation, Google Workspace administrators may observe lag times ranging from minutes up to 3 days between the time of an event's occurrence and the event being visible in the Google Workspace admin/audit logs.\n- This rule is configured to run every 10 minutes with a lookback time of 130 minutes.\n- To reduce the risk of false negatives, consider reducing the interval that the Google Workspace (formerly G Suite) Filebeat module polls Google's reporting API for new events.\n- By default, `var.interval` is set to 2 hours (2h). Consider changing this interval to a lower value, such as 10 minutes (10m).\n- See the following references for further information.\n - https://support.google.com/a/answer/7061566\n - https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-gsuite.html", - "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:ADD_APPLICATION", + "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:ADD_APPLICATION\n", "references": [ "https://support.google.com/a/answer/6328701?hl=en#" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/attempt_to_deactivate_okta_network_zone.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/attempt_to_deactivate_okta_network_zone.json index fbdf3d58f2b81..8c8353f1d5f9c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/attempt_to_deactivate_okta_network_zone.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/attempt_to_deactivate_okta_network_zone.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Deactivate an Okta Network Zone", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:zone.deactivate", + "query": "event.dataset:okta.system and event.action:zone.deactivate\n", "references": [ "https://help.okta.com/en/prod/Content/Topics/Security/network/network-zones.htm", "https://developer.okta.com/docs/reference/api/system-log/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/attempt_to_delete_okta_network_zone.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/attempt_to_delete_okta_network_zone.json index b0bd850c1d63c..903475b441d01 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/attempt_to_delete_okta_network_zone.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/attempt_to_delete_okta_network_zone.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Delete an Okta Network Zone", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:zone.delete", + "query": "event.dataset:okta.system and event.action:zone.delete\n", "references": [ "https://help.okta.com/en/prod/Content/Topics/Security/network/network-zones.htm", "https://developer.okta.com/docs/reference/api/system-log/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_cloudtrail_logging_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_cloudtrail_logging_created.json index 3e2479369ebb2..7debf76f371c5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_cloudtrail_logging_created.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_cloudtrail_logging_created.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS CloudTrail Log Created", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:cloudtrail.amazonaws.com and event.action:CreateTrail and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:cloudtrail.amazonaws.com and event.action:CreateTrail and event.outcome:success\n", "references": [ "https://docs.aws.amazon.com/awscloudtrail/latest/APIReference/API_CreateTrail.html", "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/cloudtrail/create-trail.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_subscription_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_subscription_creation.json index d50013c90b122..a24c533e2c272 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_subscription_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_subscription_creation.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Pub/Sub Subscription Creation", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.pubsub.v*.Subscriber.CreateSubscription and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.pubsub.v*.Subscriber.CreateSubscription and event.outcome:success\n", "references": [ "https://cloud.google.com/pubsub/docs/overview" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_topic_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_topic_creation.json index 5438b8fb2a8c9..af20bdf46e42a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_topic_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_gcp_pub_sub_topic_creation.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Pub/Sub Topic Creation", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.pubsub.v*.Publisher.CreateTopic and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.pubsub.v*.Publisher.CreateTopic and event.outcome:success\n", "references": [ "https://cloud.google.com/pubsub/docs/admin" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_microsoft_365_new_inbox_rule.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_microsoft_365_new_inbox_rule.json index 5fcfbd797e9d3..1a9ccc9c70696 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_microsoft_365_new_inbox_rule.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_microsoft_365_new_inbox_rule.json @@ -17,7 +17,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 New Inbox Rule Created", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"New-InboxRule\" and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"New-InboxRule\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/responding-to-a-compromised-email-account?view=o365-worldwide", "https://docs.microsoft.com/en-us/powershell/module/exchange/new-inboxrule?view=exchange-ps", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_update_event_hub_auth_rule.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_update_event_hub_auth_rule.json index a9fd96efcb383..7e8ab8d94d8f0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_update_event_hub_auth_rule.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/collection_update_event_hub_auth_rule.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure Event Hub Authorization Rule Created or Updated", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.EVENTHUB/NAMESPACES/AUTHORIZATIONRULES/WRITE\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.EVENTHUB/NAMESPACES/AUTHORIZATIONRULES/WRITE\" and event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/event-hubs/authorize-access-shared-access-signature" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_certutil_network_connection.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_certutil_network_connection.json index c6622deed9502..2f265710feb0a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_certutil_network_connection.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_certutil_network_connection.json @@ -12,7 +12,10 @@ "language": "eql", "license": "Elastic License v2", "name": "Network Connection via Certutil", - "query": "sequence by process.entity_id\n [process where process.name : \"certutil.exe\" and event.type == \"start\"]\n [network where process.name : \"certutil.exe\" and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"172.16.0.0/12\", \"192.168.0.0/16\")]\n", + "query": "sequence by process.entity_id\n [process where process.name : \"certutil.exe\" and event.type == \"start\"]\n [network where process.name : \"certutil.exe\" and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\",\n \"192.0.0.0/29\", \"192.0.0.8/32\", \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\",\n \"192.0.0.171/32\", \"192.0.2.0/24\", \"192.31.196.0/24\", \"192.52.193.0/24\",\n \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\", \"100.64.0.0/10\", \"192.175.48.0/24\",\n \"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\",\n \"FE80::/10\", \"FF00::/8\")]\n", + "references": [ + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], "risk_score": 21, "rule_id": "3838e0e3-1850-4850-a411-2e8c5ba40ba8", "severity": "low", @@ -41,5 +44,5 @@ } ], "type": "eql", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_cobalt_strike_beacon.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_cobalt_strike_beacon.json index eba26c7be6e94..4e1780af8df82 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_cobalt_strike_beacon.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_cobalt_strike_beacon.json @@ -13,7 +13,7 @@ "license": "Elastic License v2", "name": "Cobalt Strike Command and Control Beacon", "note": "## Threat intel\n\nThis activity has been observed in FIN7 campaigns.", - "query": "event.category:(network OR network_traffic) AND type:(tls OR http) AND network.transport:tcp AND destination.domain:/[a-z]{3}.stage.[0-9]{8}\\..*/", + "query": "event.category:(network OR network_traffic) AND type:(tls OR http) AND network.transport:tcp AND destination.domain:/[a-z]{3}.stage.[0-9]{8}\\..*/\n", "references": [ "https://blog.morphisec.com/fin7-attacks-restaurant-industry", "https://www.fireeye.com/blog/threat-research/2017/04/fin7-phishing-lnk.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_cobalt_strike_default_teamserver_cert.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_cobalt_strike_default_teamserver_cert.json index 6fffa5c4634a0..1d57f302554b7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_cobalt_strike_default_teamserver_cert.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_cobalt_strike_default_teamserver_cert.json @@ -11,7 +11,7 @@ "license": "Elastic License v2", "name": "Default Cobalt Strike Team Server Certificate", "note": "## Threat intel\n\nWhile Cobalt Strike is intended to be used for penetration tests and IR training, it is frequently used by actual threat actors (TA) such as APT19, APT29, APT32, APT41, FIN6, DarkHydrus, CopyKittens, Cobalt Group, Leviathan, and many other unnamed criminal TAs. This rule uses high-confidence atomic indicators, alerts should be investigated rapidly.", - "query": "event.category:(network or network_traffic) and (tls.server.hash.md5:950098276A495286EB2A2556FBAB6D83 or tls.server.hash.sha1:6ECE5ECE4192683D2D84E25B0BA7E04F9CB7EB7C or tls.server.hash.sha256:87F2085C32B6A2CC709B365F55873E207A9CAA10BFFECF2FD16D3CF9D94D390C)", + "query": "event.category:(network or network_traffic) and (tls.server.hash.md5:950098276A495286EB2A2556FBAB6D83 or\n tls.server.hash.sha1:6ECE5ECE4192683D2D84E25B0BA7E04F9CB7EB7C or\n tls.server.hash.sha256:87F2085C32B6A2CC709B365F55873E207A9CAA10BFFECF2FD16D3CF9D94D390C)\n", "references": [ "https://attack.mitre.org/software/S0154/", "https://www.cobaltstrike.com/help-setup-collaboration", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_dns_directly_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_dns_directly_to_the_internet.json index d283b489c278d..ec05c1645c699 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_dns_directly_to_the_internet.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_dns_directly_to_the_internet.json @@ -13,10 +13,11 @@ "language": "kuery", "license": "Elastic License v2", "name": "DNS Activity to the Internet", - "query": "event.category:(network or network_traffic) and (event.type:connection or type:dns) and (destination.port:53 or event.dataset:zeek.dns) and source.ip:( 10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16 ) and not destination.ip:( 10.0.0.0/8 or 127.0.0.0/8 or 169.254.0.0/16 or 172.16.0.0/12 or 192.168.0.0/16 or 224.0.0.0/4 or 255.255.255.255 or \"::1\" or \"FE80::/10\" or \"FF00::/8\")", + "query": "event.category:(network or network_traffic) and (event.type:connection or type:dns) and (destination.port:53 or event.dataset:zeek.dns)\n and source.ip:(\n 10.0.0.0/8 or\n 172.16.0.0/12 or\n 192.168.0.0/16\n ) and\n not destination.ip:(\n 10.0.0.0/8 or\n 127.0.0.0/8 or\n 169.254.0.0/16 or\n 172.16.0.0/12 or\n 192.0.0.0/24 or\n 192.0.0.0/29 or\n 192.0.0.8/32 or\n 192.0.0.9/32 or\n 192.0.0.10/32 or\n 192.0.0.170/32 or\n 192.0.0.171/32 or\n 192.0.2.0/24 or\n 192.31.196.0/24 or\n 192.52.193.0/24 or\n 192.168.0.0/16 or\n 192.88.99.0/24 or\n 224.0.0.0/4 or\n 100.64.0.0/10 or\n 192.175.48.0/24 or\n 198.18.0.0/15 or\n 198.51.100.0/24 or\n 203.0.113.0/24 or\n 240.0.0.0/4 or\n \"::1\" or\n \"FE80::/10\" or\n \"FF00::/8\"\n )\n", "references": [ "https://www.us-cert.gov/ncas/alerts/TA15-240A", - "https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-81-2.pdf" + "https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-81-2.pdf", + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" ], "risk_score": 47, "rule_id": "6ea71ff0-9e95-475b-9506-2580d1ce6154", @@ -40,5 +41,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 8 + "version": 9 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_dns_tunneling_nslookup.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_dns_tunneling_nslookup.json index 62654dfb2a9dd..0920f336bab44 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_dns_tunneling_nslookup.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_dns_tunneling_nslookup.json @@ -12,7 +12,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential DNS Tunneling via NsLookup", - "query": "event.category:process and event.type:start and process.name:nslookup.exe and process.args:(-querytype=* or -qt=* or -q=* or -type=*)", + "query": "event.category:process and event.type:start and process.name:nslookup.exe and process.args:(-querytype=* or -qt=* or -q=* or -type=*)\n", "references": [ "https://unit42.paloaltonetworks.com/dns-tunneling-in-the-wild-overview-of-oilrigs-dns-tunneling/" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_download_rar_powershell_from_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_download_rar_powershell_from_internet.json index 7cfba90cf67c8..50010d809f6fd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_download_rar_powershell_from_internet.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_download_rar_powershell_from_internet.json @@ -13,10 +13,11 @@ "license": "Elastic License v2", "name": "Roshal Archive (RAR) or PowerShell File Downloaded from the Internet", "note": "## Threat intel\n\nThis activity has been observed in FIN7 campaigns.", - "query": "event.category:(network OR network_traffic) AND network.protocol:http AND url.path:/.*(rar|ps1)/ AND source.ip:(10.0.0.0\\/8 OR 172.16.0.0\\/12 OR 192.168.0.0\\/16)", + "query": "event.category:(network or network_traffic) and network.protocol:http and\n (url.extension:(ps1 or rar) or url.path:(*.ps1 or *.rar)) and\n not destination.ip:(\n 10.0.0.0/8 or\n 127.0.0.0/8 or\n 169.254.0.0/16 or\n 172.16.0.0/12 or\n 192.0.0.0/24 or\n 192.0.0.0/29 or\n 192.0.0.8/32 or\n 192.0.0.9/32 or\n 192.0.0.10/32 or\n 192.0.0.170/32 or\n 192.0.0.171/32 or\n 192.0.2.0/24 or\n 192.31.196.0/24 or\n 192.52.193.0/24 or\n 192.168.0.0/16 or\n 192.88.99.0/24 or\n 224.0.0.0/4 or\n 100.64.0.0/10 or\n 192.175.48.0/24 or\n 198.18.0.0/15 or\n 198.51.100.0/24 or\n 203.0.113.0/24 or\n 240.0.0.0/4 or\n \"::1\" or\n \"FE80::/10\" or\n \"FF00::/8\"\n ) and\n source.ip:(\n 10.0.0.0/8 or\n 172.16.0.0/12 or\n 192.168.0.0/16\n )\n", "references": [ "https://www.fireeye.com/blog/threat-research/2017/04/fin7-phishing-lnk.html", - "https://www.justice.gov/opa/press-release/file/1084361/download" + "https://www.justice.gov/opa/press-release/file/1084361/download", + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" ], "risk_score": 47, "rule_id": "ff013cb4-274d-434a-96bb-fe15ddd3ae92", @@ -46,5 +47,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_fin7_c2_behavior.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_fin7_c2_behavior.json index 305612da0f47e..80087935eae0f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_fin7_c2_behavior.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_fin7_c2_behavior.json @@ -13,7 +13,7 @@ "license": "Elastic License v2", "name": "Possible FIN7 DGA Command and Control Behavior", "note": "## Triage and analysis\n\nIn the event this rule identifies benign domains in your environment, the `destination.domain` field in the rule can be modified to include those domains. Example: `...AND NOT destination.domain:(zoom.us OR benign.domain1 OR benign.domain2)`.", - "query": "event.category:(network OR network_traffic) AND type:(tls OR http) AND network.transport:tcp AND destination.domain:/[a-zA-Z]{4,5}\\.(pw|us|club|info|site|top)/ AND NOT destination.domain:zoom.us", + "query": "event.category:(network OR network_traffic) AND type:(tls OR http) AND network.transport:tcp\nAND destination.domain:/[a-zA-Z]{4,5}\\.(pw|us|club|info|site|top)/ AND NOT destination.domain:zoom.us\n", "references": [ "https://www.fireeye.com/blog/threat-research/2018/08/fin7-pursuing-an-enigmatic-and-evasive-global-criminal-operation.html" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_halfbaked_beacon.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_halfbaked_beacon.json index ed6fb726896ac..f7a770b4cfcc9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_halfbaked_beacon.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_halfbaked_beacon.json @@ -13,7 +13,7 @@ "license": "Elastic License v2", "name": "Halfbaked Command and Control Beacon", "note": "## Threat intel\n\nThis activity has been observed in FIN7 campaigns.", - "query": "event.category:(network OR network_traffic) AND network.protocol:http AND network.transport:tcp AND url.full:/http:\\/\\/[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}\\/cd/ AND destination.port:(53 OR 80 OR 8080 OR 443)", + "query": "event.category:(network OR network_traffic) AND network.protocol:http AND\n network.transport:tcp AND url.full:/http:\\/\\/[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}\\/cd/ AND\n destination.port:(53 OR 80 OR 8080 OR 443)\n", "references": [ "https://www.fireeye.com/blog/threat-research/2017/04/fin7-phishing-lnk.html", "https://attack.mitre.org/software/S0151/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_nat_traversal_port_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_nat_traversal_port_activity.json index 33b7cb020a69f..7cd0a865c4b3e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_nat_traversal_port_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_nat_traversal_port_activity.json @@ -15,7 +15,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "IPSEC NAT Traversal Port Activity", - "query": "event.category:(network or network_traffic) and network.transport:udp and destination.port:4500", + "query": "event.category:(network or network_traffic) and network.transport:udp and destination.port:4500\n", "risk_score": 21, "rule_id": "a9cb3641-ff4b-4cdc-a063-b4b8d02a67c7", "severity": "low", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_26_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_26_activity.json index 48a7fae4b259e..1ea0da645d785 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_26_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_port_26_activity.json @@ -15,7 +15,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "SMTP on Port 26/TCP", - "query": "event.category:(network or network_traffic) and network.transport:tcp and (destination.port:26 or (event.dataset:zeek.smtp and destination.port:26))", + "query": "event.category:(network or network_traffic) and network.transport:tcp and (destination.port:26 or (event.dataset:zeek.smtp and destination.port:26))\n", "references": [ "https://unit42.paloaltonetworks.com/unit42-badpatch/", "https://isc.sans.edu/forums/diary/Next+up+whats+up+with+TCP+port+26/25564/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_rdp_remote_desktop_protocol_from_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_rdp_remote_desktop_protocol_from_the_internet.json index 1ecfdc45352aa..625b1e470192f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_rdp_remote_desktop_protocol_from_the_internet.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_rdp_remote_desktop_protocol_from_the_internet.json @@ -15,7 +15,10 @@ "language": "kuery", "license": "Elastic License v2", "name": "RDP (Remote Desktop Protocol) from the Internet", - "query": "event.category:(network or network_traffic) and network.transport:tcp and (destination.port:3389 or event.dataset:zeek.rdp) and not source.ip:( 10.0.0.0/8 or 127.0.0.0/8 or 169.254.0.0/16 or 172.16.0.0/12 or 192.168.0.0/16 or 224.0.0.0/4 or \"::1\" or \"FE80::/10\" or \"FF00::/8\" ) and destination.ip:( 10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16 )", + "query": "event.category:(network or network_traffic) and network.transport:tcp and (destination.port:3389 or event.dataset:zeek.rdp) and\n not source.ip:(\n 10.0.0.0/8 or\n 127.0.0.0/8 or\n 169.254.0.0/16 or\n 172.16.0.0/12 or\n 192.0.0.0/24 or\n 192.0.0.0/29 or\n 192.0.0.8/32 or\n 192.0.0.9/32 or\n 192.0.0.10/32 or\n 192.0.0.170/32 or\n 192.0.0.171/32 or\n 192.0.2.0/24 or\n 192.31.196.0/24 or\n 192.52.193.0/24 or\n 192.168.0.0/16 or\n 192.88.99.0/24 or\n 224.0.0.0/4 or\n 100.64.0.0/10 or\n 192.175.48.0/24 or\n 198.18.0.0/15 or\n 198.51.100.0/24 or\n 203.0.113.0/24 or\n 240.0.0.0/4 or\n \"::1\" or\n \"FE80::/10\" or\n \"FF00::/8\"\n ) and\n destination.ip:(\n 10.0.0.0/8 or\n 172.16.0.0/12 or\n 192.168.0.0/16\n )\n", + "references": [ + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], "risk_score": 47, "rule_id": "8c1bdde8-4204-45c0-9e0c-c85ca3902488", "severity": "medium", @@ -69,5 +72,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 8 + "version": 9 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_telnet_port_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_telnet_port_activity.json index f66e2ce891198..34adaa49df9c4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_telnet_port_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_telnet_port_activity.json @@ -15,7 +15,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Telnet Port Activity", - "query": "event.category:(network or network_traffic) and network.transport:tcp and destination.port:23", + "query": "event.category:(network or network_traffic) and network.transport:tcp and destination.port:23\n", "risk_score": 47, "rule_id": "34fde489-94b0-4500-a76f-b8a157cf9269", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_from_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_from_the_internet.json index e593a2fed8ba0..7a3da39baad33 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_from_the_internet.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_from_the_internet.json @@ -15,7 +15,10 @@ "language": "kuery", "license": "Elastic License v2", "name": "VNC (Virtual Network Computing) from the Internet", - "query": "event.category:(network or network_traffic) and network.transport:tcp and destination.port >= 5800 and destination.port <= 5810 and not source.ip:( 10.0.0.0/8 or 127.0.0.0/8 or 169.254.0.0/16 or 172.16.0.0/12 or 192.168.0.0/16 or 224.0.0.0/4 or \"::1\" or \"FE80::/10\" or \"FF00::/8\" ) and destination.ip:( 10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16 )", + "query": "event.category:(network or network_traffic) and network.transport:tcp and destination.port >= 5800 and destination.port <= 5810 and\n not source.ip:(\n 10.0.0.0/8 or\n 127.0.0.0/8 or\n 169.254.0.0/16 or\n 172.16.0.0/12 or\n 192.0.0.0/24 or\n 192.0.0.0/29 or\n 192.0.0.8/32 or\n 192.0.0.9/32 or\n 192.0.0.10/32 or\n 192.0.0.170/32 or\n 192.0.0.171/32 or\n 192.0.2.0/24 or\n 192.31.196.0/24 or\n 192.52.193.0/24 or\n 192.168.0.0/16 or\n 192.88.99.0/24 or\n 224.0.0.0/4 or\n 100.64.0.0/10 or\n 192.175.48.0/24 or\n 198.18.0.0/15 or\n 198.51.100.0/24 or\n 203.0.113.0/24 or\n 240.0.0.0/4 or\n \"::1\" or\n \"FE80::/10\" or\n \"FF00::/8\"\n ) and\n destination.ip:(\n 10.0.0.0/8 or\n 172.16.0.0/12 or\n 192.168.0.0/16\n )\n", + "references": [ + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], "risk_score": 73, "rule_id": "5700cb81-df44-46aa-a5d7-337798f53eb8", "severity": "high", @@ -60,5 +63,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 8 + "version": 9 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_to_the_internet.json index 2e43ad410daec..4b30de0ee0211 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_to_the_internet.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/command_and_control_vnc_virtual_network_computing_to_the_internet.json @@ -15,7 +15,10 @@ "language": "kuery", "license": "Elastic License v2", "name": "VNC (Virtual Network Computing) to the Internet", - "query": "event.category:(network or network_traffic) and network.transport:tcp and destination.port >= 5800 and destination.port <= 5810 and source.ip:( 10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16 ) and not destination.ip:( 10.0.0.0/8 or 127.0.0.0/8 or 169.254.0.0/16 or 172.16.0.0/12 or 192.168.0.0/16 or 224.0.0.0/4 or \"::1\" or \"FE80::/10\" or \"FF00::/8\" )", + "query": "event.category:(network or network_traffic) and network.transport:tcp and destination.port >= 5800 and destination.port <= 5810 and\n source.ip:(\n 10.0.0.0/8 or\n 172.16.0.0/12 or\n 192.168.0.0/16\n ) and\n not destination.ip:(\n 10.0.0.0/8 or\n 127.0.0.0/8 or\n 169.254.0.0/16 or\n 172.16.0.0/12 or\n 192.0.0.0/24 or\n 192.0.0.0/29 or\n 192.0.0.8/32 or\n 192.0.0.9/32 or\n 192.0.0.10/32 or\n 192.0.0.170/32 or\n 192.0.0.171/32 or\n 192.0.2.0/24 or\n 192.31.196.0/24 or\n 192.52.193.0/24 or\n 192.168.0.0/16 or\n 192.88.99.0/24 or\n 224.0.0.0/4 or\n 100.64.0.0/10 or\n 192.175.48.0/24 or\n 198.18.0.0/15 or\n 198.51.100.0/24 or\n 203.0.113.0/24 or\n 240.0.0.0/4 or\n \"::1\" or\n \"FE80::/10\" or\n \"FF00::/8\"\n )\n", + "references": [ + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], "risk_score": 47, "rule_id": "3ad49c61-7adc-42c1-b788-732eda2f5abf", "severity": "medium", @@ -45,5 +48,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 8 + "version": 9 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempted_bypass_of_okta_mfa.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempted_bypass_of_okta_mfa.json index c3614e0e69e9a..fc3c3f5ca90d9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempted_bypass_of_okta_mfa.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempted_bypass_of_okta_mfa.json @@ -11,7 +11,7 @@ "license": "Elastic License v2", "name": "Attempted Bypass of Okta MFA", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:user.mfa.attempt_bypass", + "query": "event.dataset:okta.system and event.action:user.mfa.attempt_bypass\n", "references": [ "https://developer.okta.com/docs/reference/api/system-log/", "https://developer.okta.com/docs/reference/api/event-types/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempts_to_brute_force_okta_user_account.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempts_to_brute_force_okta_user_account.json index 5556f3787fbdd..ea2b05b485585 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempts_to_brute_force_okta_user_account.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_attempts_to_brute_force_okta_user_account.json @@ -1,6 +1,8 @@ { "author": [ - "Elastic" + "Elastic", + "@BenB196", + "Austin Songer" ], "description": "Identifies when an Okta user account is locked out 3 times within a 3 hour window. An adversary may attempt a brute force or password spraying attack to obtain unauthorized access to user accounts. The default Okta authentication policy ensures that a user account is locked out after 10 failed authentication attempts.", "from": "now-180m", @@ -12,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempts to Brute Force an Okta User Account", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:user.account.lock", + "query": "event.dataset:okta.system and event.action:user.account.lock\n", "references": [ "https://developer.okta.com/docs/reference/api/system-log/", "https://developer.okta.com/docs/reference/api/event-types/" @@ -47,10 +49,10 @@ ], "threshold": { "field": [ - "okta.actor.id" + "okta.actor.alternate_id" ], "value": 3 }, "type": "threshold", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_aws_iam_assume_role_brute_force.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_aws_iam_assume_role_brute_force.json index 3ea689aaa3570..6ef3e3d255779 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_aws_iam_assume_role_brute_force.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_aws_iam_assume_role_brute_force.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "name": "AWS IAM Brute Force of Assume Role Policy", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:iam.amazonaws.com and event.action:UpdateAssumeRolePolicy and aws.cloudtrail.error_code:MalformedPolicyDocumentException and event.outcome:failure", + "query": "event.dataset:aws.cloudtrail and\n event.provider:iam.amazonaws.com and event.action:UpdateAssumeRolePolicy and\n aws.cloudtrail.error_code:MalformedPolicyDocumentException and event.outcome:failure\n", "references": [ "https://www.praetorian.com/blog/aws-iam-assume-role-vulnerabilities", "https://rhinosecuritylabs.com/aws/assume-worst-aws-assume-role-enumeration/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_collection_sensitive_files.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_collection_sensitive_files.json index b8a608dc47ab1..bd155ce8e914d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_collection_sensitive_files.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_collection_sensitive_files.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Sensitive Files Compression", - "query": "event.category:process and event.type:start and process.name:(zip or tar or gzip or hdiutil or 7z) and process.args: ( /root/.ssh/id_rsa or /root/.ssh/id_rsa.pub or /root/.ssh/id_ed25519 or /root/.ssh/id_ed25519.pub or /root/.ssh/authorized_keys or /root/.ssh/authorized_keys2 or /root/.ssh/known_hosts or /root/.bash_history or /etc/hosts or /home/*/.ssh/id_rsa or /home/*/.ssh/id_rsa.pub or /home/*/.ssh/id_ed25519 or /home/*/.ssh/id_ed25519.pub or /home/*/.ssh/authorized_keys or /home/*/.ssh/authorized_keys2 or /home/*/.ssh/known_hosts or /home/*/.bash_history or /root/.aws/credentials or /root/.aws/config or /home/*/.aws/credentials or /home/*/.aws/config or /root/.docker/config.json or /home/*/.docker/config.json or /etc/group or /etc/passwd or /etc/shadow or /etc/gshadow )", + "query": "event.category:process and event.type:start and\n process.name:(zip or tar or gzip or hdiutil or 7z) and\n process.args:\n (\n /root/.ssh/id_rsa or\n /root/.ssh/id_rsa.pub or\n /root/.ssh/id_ed25519 or\n /root/.ssh/id_ed25519.pub or\n /root/.ssh/authorized_keys or\n /root/.ssh/authorized_keys2 or\n /root/.ssh/known_hosts or\n /root/.bash_history or\n /etc/hosts or\n /home/*/.ssh/id_rsa or\n /home/*/.ssh/id_rsa.pub or\n /home/*/.ssh/id_ed25519 or\n /home/*/.ssh/id_ed25519.pub or\n /home/*/.ssh/authorized_keys or\n /home/*/.ssh/authorized_keys2 or\n /home/*/.ssh/known_hosts or\n /home/*/.bash_history or\n /root/.aws/credentials or\n /root/.aws/config or\n /home/*/.aws/credentials or\n /home/*/.aws/config or\n /root/.docker/config.json or\n /home/*/.docker/config.json or\n /etc/group or\n /etc/passwd or\n /etc/shadow or\n /etc/gshadow\n )\n", "references": [ "https://www.trendmicro.com/en_ca/research/20/l/teamtnt-now-deploying-ddos-capable-irc-bot-tntbotinger.html" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_dumping_hashes_bi_cmds.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_dumping_hashes_bi_cmds.json index c9070cc09dd65..bb513cbebdc3f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_dumping_hashes_bi_cmds.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_dumping_hashes_bi_cmds.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Dumping Account Hashes via Built-In Commands", - "query": "event.category:process and event.type:start and process.name:(defaults or mkpassdb) and process.args:(ShadowHashData or \"-dump\")", + "query": "event.category:process and event.type:start and\n process.name:(defaults or mkpassdb) and process.args:(ShadowHashData or \"-dump\")\n", "references": [ "https://apple.stackexchange.com/questions/186893/os-x-10-9-where-are-password-hashes-stored", "https://www.unix.com/man-page/osx/8/mkpassdb/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iam_user_addition_to_group.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iam_user_addition_to_group.json index 0d94ac36944a9..b66008c6931a4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iam_user_addition_to_group.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_iam_user_addition_to_group.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS IAM User Addition to Group", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:iam.amazonaws.com and event.action:AddUserToGroup and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:iam.amazonaws.com and event.action:AddUserToGroup and event.outcome:success\n", "references": [ "https://docs.aws.amazon.com/IAM/latest/APIReference/API_AddUserToGroup.html" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_kerberosdump_kcc.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_kerberosdump_kcc.json index 9429e3414e615..de5a9d80ed3df 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_kerberosdump_kcc.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_kerberosdump_kcc.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Kerberos Cached Credentials Dumping", - "query": "event.category:process and event.type:(start or process_started) and process.name:kcc and process.args:copy_cred_cache", + "query": "event.category:process and event.type:(start or process_started) and\n process.name:kcc and\n process.args:copy_cred_cache\n", "references": [ "https://github.com/EmpireProject/EmPyre/blob/master/lib/modules/collection/osx/kerberosdump.py", "https://opensource.apple.com/source/Heimdal/Heimdal-323.12/kuser/kcc-commands.in.auto.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_key_vault_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_key_vault_modified.json index 27f76a13d657d..8efd74d4e7f1c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_key_vault_modified.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_key_vault_modified.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure Key Vault Modified", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.KEYVAULT/VAULTS/WRITE\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.KEYVAULT/VAULTS/WRITE\" and event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/key-vault/general/basic-concepts", "https://docs.microsoft.com/en-us/azure/key-vault/general/secure-your-key-vault" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_brute_force_user_account_attempt.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_brute_force_user_account_attempt.json index 8e9c142929a05..532b9bf3b17b3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_brute_force_user_account_attempt.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_brute_force_user_account_attempt.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Attempts to Brute Force a Microsoft 365 User Account", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:AzureActiveDirectory and event.category:authentication and event.action:UserLoginFailed and event.outcome:failure", + "query": "event.dataset:o365.audit and event.provider:(Exchange or AzureActiveDirectory) and event.category:authentication and \nevent.action:(\"UserLoginFailed\" or \"PasswordLogonInitialAuthUsingPassword\") and event.outcome:failure\n", "risk_score": 73, "rule_id": "26f68dba-ce29-497b-8e13-b4fde1db5a2d", "severity": "high", @@ -51,5 +51,5 @@ "value": 10 }, "type": "threshold", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_potential_password_spraying_attack.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_potential_password_spraying_attack.json index 14314feebb712..536f893236dee 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_potential_password_spraying_attack.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_microsoft_365_potential_password_spraying_attack.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Potential Password Spraying of Microsoft 365 User Accounts", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:AzureActiveDirectory and event.category:authentication and event.action:UserLoginFailed and event.outcome:failure", + "query": "event.dataset:o365.audit and event.provider:AzureActiveDirectory and event.category:authentication and event.action:UserLoginFailed and event.outcome:failure\n", "risk_score": 73, "rule_id": "3efee4f0-182a-40a8-a835-102c68a4175d", "severity": "high", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mitm_localhost_webproxy.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mitm_localhost_webproxy.json index e226df7a23da9..9c0f2d0c07dc9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mitm_localhost_webproxy.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_mitm_localhost_webproxy.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "WebProxy Settings Modification", - "query": "event.category : process and event.type : start and process.name : networksetup and process.args : ((\"-setwebproxy\" or \"-setsecurewebproxy\" or \"-setautoproxyurl\") and not (Bluetooth or off)) and not process.parent.executable : (\"/Library/PrivilegedHelperTools/com.80pct.FreedomHelper\" or \"/Applications/Fiddler Everywhere.app/Contents/Resources/app/out/WebServer/Fiddler.WebUi\" or \"/usr/libexec/xpcproxy\")", + "query": "event.category : process and event.type : start and\n process.name : networksetup and process.args : ((\"-setwebproxy\" or \"-setsecurewebproxy\" or \"-setautoproxyurl\") and not (Bluetooth or off)) and\n not process.parent.executable : (\"/Library/PrivilegedHelperTools/com.80pct.FreedomHelper\" or\n \"/Applications/Fiddler Everywhere.app/Contents/Resources/app/out/WebServer/Fiddler.WebUi\" or\n \"/usr/libexec/xpcproxy\")\n", "references": [ "https://unit42.paloaltonetworks.com/mac-malware-steals-cryptocurrency-exchanges-cookies/", "https://objectivebythesea.com/v2/talks/OBTS_v2_Zohar.pdf" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_okta_brute_force_or_password_spraying.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_okta_brute_force_or_password_spraying.json index 16c2816e30690..f5449e4e30a1c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_okta_brute_force_or_password_spraying.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_okta_brute_force_or_password_spraying.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Okta Brute Force or Password Spraying Attack", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.category:authentication and event.outcome:failure", + "query": "event.dataset:okta.system and event.category:authentication and event.outcome:failure\n", "references": [ "https://developer.okta.com/docs/reference/api/system-log/", "https://developer.okta.com/docs/reference/api/event-types/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_potential_ssh_bruteforce.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_potential_ssh_bruteforce.json index 410db35bf77d3..4f945e22abdb3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_potential_ssh_bruteforce.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_potential_ssh_bruteforce.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential SSH Brute Force Detected", - "query": "event.category:process and event.type:start and process.name:\"sshd-keygen-wrapper\" and process.parent.name:launchd", + "query": "event.category:process and event.type:start and process.name:\"sshd-keygen-wrapper\" and process.parent.name:launchd\n", "references": [ "https://themittenmac.com/detecting-ssh-activity-via-process-monitoring/" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_root_console_failure_brute_force.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_root_console_failure_brute_force.json index fb296d82b992b..b20ef22a9d152 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_root_console_failure_brute_force.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_root_console_failure_brute_force.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "AWS Management Console Brute Force of Root User Identity", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:signin.amazonaws.com and event.action:ConsoleLogin and aws.cloudtrail.user_identity.type:Root and event.outcome:failure", + "query": "event.dataset:aws.cloudtrail and event.provider:signin.amazonaws.com and event.action:ConsoleLogin and aws.cloudtrail.user_identity.type:Root and event.outcome:failure\n", "references": [ "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_secretsmanager_getsecretvalue.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_secretsmanager_getsecretvalue.json index 8eebcc5c45096..6d0d4c8d112a4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_secretsmanager_getsecretvalue.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_secretsmanager_getsecretvalue.json @@ -17,7 +17,7 @@ "license": "Elastic License v2", "name": "AWS Access Secret in Secrets Manager", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:secretsmanager.amazonaws.com and event.action:GetSecretValue", + "query": "event.dataset:aws.cloudtrail and event.provider:secretsmanager.amazonaws.com and event.action:GetSecretValue\n", "references": [ "https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html", "http://detectioninthe.cloud/credential_access/access_secret_in_secrets_manager/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_storage_account_key_regenerated.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_storage_account_key_regenerated.json index d6f5a05c86e1a..3f286081c49f2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_storage_account_key_regenerated.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_storage_account_key_regenerated.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure Storage Account Key Regenerated", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.STORAGE/STORAGEACCOUNTS/REGENERATEKEY/ACTION\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.STORAGE/STORAGEACCOUNTS/REGENERATEKEY/ACTION\" and event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/storage/common/storage-account-keys-manage?tabs=azure-portal" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_systemkey_dumping.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_systemkey_dumping.json index 9094124c480bd..9eaa51279bf4b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_systemkey_dumping.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/credential_access_systemkey_dumping.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "SystemKey Access via Command Line", - "query": "event.category:process and event.type:(start or process_started) and process.args:\"/private/var/db/SystemKey\"", + "query": "event.category:process and event.type:(start or process_started) and\n process.args:\"/private/var/db/SystemKey\"\n", "references": [ "https://github.com/AlessandroZ/LaZagne/blob/master/Mac/lazagne/softwares/system/chainbreaker.py" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_amsienable_key_mod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_amsienable_key_mod.json new file mode 100644 index 0000000000000..6f30b53d24bdb --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_amsienable_key_mod.json @@ -0,0 +1,57 @@ +{ + "author": [ + "Elastic" + ], + "description": "Jscript tries to query the AmsiEnable registry key from the HKEY_USERS registry hive before initializing Antimalware Scan Interface (AMSI). If this key is set to 0, AMSI is not enabled for the Jscript process. An adversary can modify this key to disable AMSI protections.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-endpoint.events.*", + "logs-windows.*" + ], + "language": "eql", + "license": "Elastic License v2", + "name": "Modification of AmsiEnable Registry Key", + "query": "registry where event.type in (\"creation\", \"change\") and\n registry.path: \"HKEY_USERS\\\\*\\\\Software\\\\Microsoft\\\\Windows Script\\\\Settings\\\\AmsiEnable\" and\n registry.data.strings: \"0\"\n", + "references": [ + "https://hackinparis.com/data/slides/2019/talks/HIP2019-Dominic_Chell-Cracking_The_Perimeter_With_Sharpshooter.pdf", + "https://docs.microsoft.com/en-us/windows/win32/amsi/antimalware-scan-interface-portal" + ], + "risk_score": 73, + "rule_id": "f874315d-5188-4b4a-8521-d1c73093a7e4", + "severity": "high", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Defense Evasion" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1562", + "name": "Impair Defenses", + "reference": "https://attack.mitre.org/techniques/T1562/", + "subtechnique": [ + { + "id": "T1562.001", + "name": "Disable or Modify Tools", + "reference": "https://attack.mitre.org/techniques/T1562/001/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "eql", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_apple_softupdates_modification.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_apple_softupdates_modification.json index 9340425c518a7..f354f521d168e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_apple_softupdates_modification.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_apple_softupdates_modification.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "SoftwareUpdate Preferences Modification", - "query": "event.category:process and event.type:(start or process_started) and process.name:defaults and process.args:(write and \"-bool\" and (com.apple.SoftwareUpdate or /Library/Preferences/com.apple.SoftwareUpdate.plist) and not (TRUE or true))", + "query": "event.category:process and event.type:(start or process_started) and\n process.name:defaults and \n process.args:(write and \"-bool\" and (com.apple.SoftwareUpdate or /Library/Preferences/com.apple.SoftwareUpdate.plist) and not (TRUE or true))\n", "references": [ "https://blog.checkpoint.com/2017/07/13/osxdok-refuses-go-away-money/" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_gatekeeper.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_gatekeeper.json index ab423dc0ebe14..9bb48361ccf89 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_gatekeeper.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_gatekeeper.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Attempt to Disable Gatekeeper", - "query": "event.category:process and event.type:(start or process_started) and process.args:(spctl and \"--master-disable\")", + "query": "event.category:process and event.type:(start or process_started) and \n process.args:(spctl and \"--master-disable\")\n", "references": [ "https://support.apple.com/en-us/HT202491", "https://www.carbonblack.com/blog/tau-threat-intelligence-notification-new-macos-malware-variant-of-shlayer-osx-discovered/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_iptables_or_firewall.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_iptables_or_firewall.json index 8913c63f811dd..3eb5f25298c72 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_iptables_or_firewall.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_iptables_or_firewall.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Attempt to Disable IPTables or Firewall", - "query": "event.category:process and event.type:(start or process_started) and process.name:ufw and process.args:(allow or disable or reset) or (((process.name:service and process.args:stop) or (process.name:chkconfig and process.args:off) or (process.name:systemctl and process.args:(disable or stop or kill))) and process.args:(firewalld or ip6tables or iptables))", + "query": "event.category:process and event.type:(start or process_started) and\n process.name:ufw and process.args:(allow or disable or reset) or\n\n (((process.name:service and process.args:stop) or\n (process.name:chkconfig and process.args:off) or\n (process.name:systemctl and process.args:(disable or stop or kill))) and\n process.args:(firewalld or ip6tables or iptables))\n", "risk_score": 47, "rule_id": "125417b8-d3df-479f-8418-12d7e034fee3", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_syslog_service.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_syslog_service.json index b465340a83223..610648df94d37 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_syslog_service.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_attempt_to_disable_syslog_service.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Attempt to Disable Syslog Service", - "query": "event.category:process and event.type:(start or process_started) and ((process.name:service and process.args:stop) or (process.name:chkconfig and process.args:off) or (process.name:systemctl and process.args:(disable or stop or kill))) and process.args:(syslog or rsyslog or \"syslog-ng\")", + "query": "event.category:process and event.type:(start or process_started) and\n ((process.name:service and process.args:stop) or\n (process.name:chkconfig and process.args:off) or\n (process.name:systemctl and process.args:(disable or stop or kill)))\n and process.args:(syslog or rsyslog or \"syslog-ng\")\n", "risk_score": 47, "rule_id": "2f8a1226-5720-437d-9c20-e0029deb6194", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_application_credential_modification.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_application_credential_modification.json index d695695e2c23b..5f96b81247942 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_application_credential_modification.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_application_credential_modification.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure Application Credential Modification", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.auditlogs and azure.auditlogs.operation_name:\"Update application - Certificates and secrets management\" and event.outcome:(success or Success)", + "query": "event.dataset:azure.auditlogs and azure.auditlogs.operation_name:\"Update application - Certificates and secrets management\" and event.outcome:(success or Success)\n", "references": [ "https://msrc-blog.microsoft.com/2020/12/13/customer-guidance-on-recent-nation-state-cyber-attacks/" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_diagnostic_settings_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_diagnostic_settings_deletion.json index 31eec6ee4d1c2..d9f70f88a23b7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_diagnostic_settings_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_diagnostic_settings_deletion.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure Diagnostic Settings Deletion", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/DELETE\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/DELETE\" and event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/azure-monitor/platform/diagnostic-settings" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_service_principal_addition.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_service_principal_addition.json index 43557bfeb31ba..c715ea42e4b7e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_service_principal_addition.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_azure_service_principal_addition.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure Service Principal Addition", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.auditlogs and azure.auditlogs.operation_name:\"Add service principal\" and event.outcome:(success or Success)", + "query": "event.dataset:azure.auditlogs and azure.auditlogs.operation_name:\"Add service principal\" and event.outcome:(success or Success)\n", "references": [ "https://msrc-blog.microsoft.com/2020/12/13/customer-guidance-on-recent-nation-state-cyber-attacks/", "https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-create-service-principal-portal" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_base16_or_base32_encoding_or_decoding_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_base16_or_base32_encoding_or_decoding_activity.json index bedb41cb726a6..1cc353f1add3a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_base16_or_base32_encoding_or_decoding_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_base16_or_base32_encoding_or_decoding_activity.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Base16 or Base32 Encoding/Decoding Activity", - "query": "event.category:process and event.type:(start or process_started) and process.name:(base16 or base32 or base32plain or base32hex)", + "query": "event.category:process and event.type:(start or process_started) and\n process.name:(base16 or base32 or base32plain or base32hex)\n", "risk_score": 21, "rule_id": "debff20a-46bc-4a4d-bae5-5cdd14222795", "severity": "low", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_clearing_windows_security_logs.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_clearing_windows_security_logs.json index ca7485a29f4fc..d04c2b2a38915 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_clearing_windows_security_logs.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_clearing_windows_security_logs.json @@ -12,7 +12,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Windows Event Logs Cleared", - "query": "event.action:(\"audit-log-cleared\" or \"Log clear\")", + "query": "event.action:(\"audit-log-cleared\" or \"Log clear\")\n", "risk_score": 21, "rule_id": "45ac4800-840f-414c-b221-53dd36a5aaf7", "severity": "low", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_deleted.json index 8daf17dc8c386..744543ab8a1f0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_deleted.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS CloudTrail Log Deleted", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:cloudtrail.amazonaws.com and event.action:DeleteTrail and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:cloudtrail.amazonaws.com and event.action:DeleteTrail and event.outcome:success\n", "references": [ "https://docs.aws.amazon.com/awscloudtrail/latest/APIReference/API_DeleteTrail.html", "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/cloudtrail/delete-trail.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_suspended.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_suspended.json index c140a1f9b9734..27990a74ac5b2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_suspended.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudtrail_logging_suspended.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS CloudTrail Log Suspended", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:cloudtrail.amazonaws.com and event.action:StopLogging and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:cloudtrail.amazonaws.com and event.action:StopLogging and event.outcome:success\n", "references": [ "https://docs.aws.amazon.com/awscloudtrail/latest/APIReference/API_StopLogging.html", "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/cloudtrail/stop-logging.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudwatch_alarm_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudwatch_alarm_deletion.json index b5984d5d624c3..61806b640fae2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudwatch_alarm_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cloudwatch_alarm_deletion.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS CloudWatch Alarm Deletion", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:monitoring.amazonaws.com and event.action:DeleteAlarms and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:monitoring.amazonaws.com and event.action:DeleteAlarms and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/cloudwatch/delete-alarms.html", "https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_DeleteAlarms.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_config_service_rule_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_config_service_rule_deletion.json index a512cd8c842ee..f58164d1a483f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_config_service_rule_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_config_service_rule_deletion.json @@ -17,7 +17,7 @@ "license": "Elastic License v2", "name": "AWS Config Service Tampering", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:config.amazonaws.com and event.action:(DeleteConfigRule or DeleteOrganizationConfigRule or DeleteConfigurationAggregator or DeleteConfigurationRecorder or DeleteConformancePack or DeleteOrganizationConformancePack or DeleteDeliveryChannel or DeleteRemediationConfiguration or DeleteRetentionConfiguration)", + "query": "event.dataset:aws.cloudtrail and event.provider:config.amazonaws.com and\n event.action:(DeleteConfigRule or DeleteOrganizationConfigRule or DeleteConfigurationAggregator or\n DeleteConfigurationRecorder or DeleteConformancePack or DeleteOrganizationConformancePack or\n DeleteDeliveryChannel or DeleteRemediationConfiguration or DeleteRetentionConfiguration)\n", "references": [ "https://docs.aws.amazon.com/config/latest/developerguide/how-does-config-work.html", "https://docs.aws.amazon.com/config/latest/APIReference/API_Operations.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_configuration_recorder_stopped.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_configuration_recorder_stopped.json index abadb416deec8..c222b25721292 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_configuration_recorder_stopped.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_configuration_recorder_stopped.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS Configuration Recorder Stopped", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:config.amazonaws.com and event.action:StopConfigurationRecorder and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:config.amazonaws.com and event.action:StopConfigurationRecorder and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/configservice/stop-configuration-recorder.html", "https://docs.aws.amazon.com/config/latest/APIReference/API_StopConfigurationRecorder.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cve_2020_0601.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cve_2020_0601.json index c7ac34a39563e..fba792e80d490 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cve_2020_0601.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_cve_2020_0601.json @@ -10,7 +10,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Windows CryptoAPI Spoofing Vulnerability (CVE-2020-0601 - CurveBall)", - "query": "event.provider:\"Microsoft-Windows-Audit-CVE\" and message:\"[CVE-2020-0601]\"", + "query": "event.provider:\"Microsoft-Windows-Audit-CVE\" and message:\"[CVE-2020-0601]\"\n", "risk_score": 21, "rule_id": "56557cde-d923-4b88-adee-c61b3f3b5dc3", "severity": "low", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_selinux_attempt.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_selinux_attempt.json index 0a51b0ccc87f5..cc84001428ff0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_selinux_attempt.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_disable_selinux_attempt.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential Disabling of SELinux", - "query": "event.category:process and event.type:(start or process_started) and process.name:setenforce and process.args:0", + "query": "event.category:process and event.type:(start or process_started) and process.name:setenforce and process.args:0\n", "risk_score": 47, "rule_id": "eb9eb8ba-a983-41d9-9c93-a1c05112ca5e", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_flow_log_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_flow_log_deletion.json index f88b8b3589d93..8c74783642395 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_flow_log_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_flow_log_deletion.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS EC2 Flow Log Deletion", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:ec2.amazonaws.com and event.action:DeleteFlowLogs and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:ec2.amazonaws.com and event.action:DeleteFlowLogs and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/delete-flow-logs.html", "https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeleteFlowLogs.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_network_acl_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_network_acl_deletion.json index 06fc3a3f094a5..b64f7eed4be8d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_network_acl_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_ec2_network_acl_deletion.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS EC2 Network Access Control List Deletion", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:ec2.amazonaws.com and event.action:(DeleteNetworkAcl or DeleteNetworkAclEntry) and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:ec2.amazonaws.com and event.action:(DeleteNetworkAcl or DeleteNetworkAclEntry) and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/delete-network-acl.html", "https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeleteNetworkAcl.html", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_event_hub_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_event_hub_deletion.json index 0ea25e05915c6..a8a2f945c76e6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_event_hub_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_event_hub_deletion.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure Event Hub Deletion", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.EVENTHUB/NAMESPACES/EVENTHUBS/DELETE\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.EVENTHUB/NAMESPACES/EVENTHUBS/DELETE\" and event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-about", "https://azure.microsoft.com/en-in/services/event-hubs/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_deletion_via_shred.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_deletion_via_shred.json index 0b934676ac1eb..6d86f27cd52b4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_deletion_via_shred.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_deletion_via_shred.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "File Deletion via Shred", - "query": "event.category:process and event.type:(start or process_started) and process.name:shred and process.args:(\"-u\" or \"--remove\" or \"-z\" or \"--zero\")", + "query": "event.category:process and event.type:(start or process_started) and process.name:shred and\n process.args:(\"-u\" or \"--remove\" or \"-z\" or \"--zero\")\n", "risk_score": 21, "rule_id": "a1329140-8de3-4445-9f87-908fb6d824f4", "severity": "low", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_mod_writable_dir.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_mod_writable_dir.json index cd83733d81830..be7e8b71694ba 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_mod_writable_dir.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_file_mod_writable_dir.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "File Permission Modification in Writable Directory", - "query": "event.category:process and event.type:(start or process_started) and process.name:(chmod or chown or chattr or chgrp) and process.working_directory:(/tmp or /var/tmp or /dev/shm) and not user.name:root", + "query": "event.category:process and event.type:(start or process_started) and\n process.name:(chmod or chown or chattr or chgrp) and\n process.working_directory:(/tmp or /var/tmp or /dev/shm) and\n not user.name:root\n", "risk_score": 21, "rule_id": "9f9a2a82-93a8-4b1a-8778-1780895626d4", "severity": "low", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_firewall_policy_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_firewall_policy_deletion.json index f8961a832ac1e..98ee5f6eb8cbf 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_firewall_policy_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_firewall_policy_deletion.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure Firewall Policy Deletion", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.NETWORK/FIREWALLPOLICIES/DELETE\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.NETWORK/FIREWALLPOLICIES/DELETE\" and event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/firewall-manager/policy-overview" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_created.json index 7fbe044738386..ff2a20f85d3e3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_created.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_created.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Firewall Rule Creation", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:v*.compute.firewalls.insert", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:v*.compute.firewalls.insert\n", "references": [ "https://cloud.google.com/vpc/docs/firewalls" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_deleted.json index 4cc8fde077c3e..3fc9b6bc49d3d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_deleted.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Firewall Rule Deletion", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:v*.compute.firewalls.delete", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:v*.compute.firewalls.delete\n", "references": [ "https://cloud.google.com/vpc/docs/firewalls" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_modified.json index 614da7f79a46b..e6ad1fc554183 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_modified.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_firewall_rule_modified.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Firewall Rule Modification", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:v*.compute.firewalls.patch", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:v*.compute.firewalls.patch\n", "references": [ "https://cloud.google.com/vpc/docs/firewalls" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_bucket_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_bucket_deletion.json index 805f21f875f02..d2fd746f8971e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_bucket_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_bucket_deletion.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Logging Bucket Deletion", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.logging.v*.ConfigServiceV*.DeleteBucket and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.logging.v*.ConfigServiceV*.DeleteBucket and event.outcome:success\n", "references": [ "https://cloud.google.com/logging/docs/buckets", "https://cloud.google.com/logging/docs/storage" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_sink_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_sink_deletion.json index 6fa62fe3a6313..3e103413967fe 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_sink_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_logging_sink_deletion.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Logging Sink Deletion", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.logging.v*.ConfigServiceV*.DeleteSink and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.logging.v*.ConfigServiceV*.DeleteSink and event.outcome:success\n", "references": [ "https://cloud.google.com/logging/docs/export" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_subscription_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_subscription_deletion.json index 4907e0f13e550..78435128865f2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_subscription_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_subscription_deletion.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Pub/Sub Subscription Deletion", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.pubsub.v*.Subscriber.DeleteSubscription and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.pubsub.v*.Subscriber.DeleteSubscription and event.outcome:success\n", "references": [ "https://cloud.google.com/pubsub/docs/overview" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_topic_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_topic_deletion.json index 7632a73ddfa90..eb6945e88e3fa 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_topic_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_pub_sub_topic_deletion.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Pub/Sub Topic Deletion", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.pubsub.v*.Publisher.DeleteTopic and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.pubsub.v*.Publisher.DeleteTopic and event.outcome:success\n", "references": [ "https://cloud.google.com/pubsub/docs/overview" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_configuration_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_configuration_modified.json index abb6912f0828d..063e844c990be 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_configuration_modified.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_configuration_modified.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Storage Bucket Configuration Modification", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:\"storage.buckets.update\" and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:\"storage.buckets.update\" and event.outcome:success\n", "references": [ "https://cloud.google.com/storage/docs/key-terms#buckets" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_permissions_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_permissions_modified.json index 8eb238c9dc796..c0a3c90853d79 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_permissions_modified.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_gcp_storage_bucket_permissions_modified.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Storage Bucket Permissions Modification", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:\"storage.setIamPermissions\" and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:\"storage.setIamPermissions\" and event.outcome:success\n", "references": [ "https://cloud.google.com/storage/docs/access-control/iam-permissions" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_guardduty_detector_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_guardduty_detector_deletion.json index 8ededad39f415..7132fed195ccf 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_guardduty_detector_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_guardduty_detector_deletion.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS GuardDuty Detector Deletion", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:guardduty.amazonaws.com and event.action:DeleteDetector and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:guardduty.amazonaws.com and event.action:DeleteDetector and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/guardduty/delete-detector.html", "https://docs.aws.amazon.com/guardduty/latest/APIReference/API_DeleteDetector.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hidden_file_dir_tmp.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hidden_file_dir_tmp.json index a14258e533275..fe8014936316c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hidden_file_dir_tmp.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_hidden_file_dir_tmp.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "max_signals": 33, "name": "Creation of Hidden Files and Directories", - "query": "event.category:process AND event.type:(start or process_started) AND process.working_directory:(\"/tmp\" or \"/var/tmp\" or \"/dev/shm\") AND process.args:/\\.[a-zA-Z0-9_\\-][a-zA-Z0-9_\\-\\.]{1,254}/ AND NOT process.name:(ls or find)", + "query": "event.category:process AND event.type:(start or process_started) AND\n process.working_directory:(\"/tmp\" or \"/var/tmp\" or \"/dev/shm\") AND\n process.args:/\\.[a-zA-Z0-9_\\-][a-zA-Z0-9_\\-\\.]{1,254}/ AND\n NOT process.name:(ls or find)\n", "risk_score": 47, "rule_id": "b9666521-4742-49ce-9ddc-b8e84c35acae", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_injection_msbuild.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_injection_msbuild.json index 2ddcd0c640415..43d662df271ee 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_injection_msbuild.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_injection_msbuild.json @@ -13,7 +13,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Process Injection by the Microsoft Build Engine", - "query": "process.name:MSBuild.exe and event.action:\"CreateRemoteThread detected (rule: CreateRemoteThread)\"", + "query": "process.name:MSBuild.exe and event.action:\"CreateRemoteThread detected (rule: CreateRemoteThread)\"\n", "risk_score": 21, "rule_id": "9d110cb3-5f4b-4c9a-b9f5-53f0a1707ae9", "severity": "low", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_install_root_certificate.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_install_root_certificate.json index 6585c1b8c8ffb..3397db22f51f3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_install_root_certificate.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_install_root_certificate.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Attempt to Install Root Certificate", - "query": "event.category:process and event.type:(start or process_started) and process.name:security and process.args:\"add-trusted-cert\"", + "query": "event.category:process and event.type:(start or process_started) and\n process.name:security and process.args:\"add-trusted-cert\"\n", "references": [ "https://ss64.com/osx/security-cert.html" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kernel_module_removal.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kernel_module_removal.json index 691c30d6f42a5..35c0cb2fb2645 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kernel_module_removal.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_kernel_module_removal.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Kernel Module Removal", - "query": "event.category:process and event.type:(start or process_started) and process.args:((rmmod and sudo) or (modprobe and sudo and (\"--remove\" or \"-r\")))", + "query": "event.category:process and event.type:(start or process_started) and\n process.args:((rmmod and sudo) or (modprobe and sudo and (\"--remove\" or \"-r\")))\n", "references": [ "http://man7.org/linux/man-pages/man8/modprobe.8.html" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_dlp_policy_removed.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_dlp_policy_removed.json index b39aee071a874..f4c3e3476c0b6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_dlp_policy_removed.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_dlp_policy_removed.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 Exchange DLP Policy Removed", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Remove-DlpPolicy\" and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Remove-DlpPolicy\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/remove-dlppolicy?view=exchange-ps", "https://docs.microsoft.com/en-us/microsoft-365/compliance/data-loss-prevention-policies?view=o365-worldwide" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_policy_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_policy_deletion.json index c4de503b66540..ab3399bddbe7a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_policy_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_policy_deletion.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 Exchange Malware Filter Policy Deletion", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Remove-MalwareFilterPolicy\" and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Remove-MalwareFilterPolicy\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/remove-malwarefilterpolicy?view=exchange-ps" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_rule_mod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_rule_mod.json index c0dcec7e1b0d7..06728dee5b150 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_rule_mod.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_malware_filter_rule_mod.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 Exchange Malware Filter Rule Modification", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:(\"Remove-MalwareFilterRule\" or \"Disable-MalwareFilterRule\") and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:(\"Remove-MalwareFilterRule\" or \"Disable-MalwareFilterRule\") and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/remove-malwarefilterrule?view=exchange-ps", "https://docs.microsoft.com/en-us/powershell/module/exchange/disable-malwarefilterrule?view=exchange-ps" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_safe_attach_rule_disabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_safe_attach_rule_disabled.json index 5273115ead302..50af384100139 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_safe_attach_rule_disabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_microsoft_365_exchange_safe_attach_rule_disabled.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 Exchange Safe Attachment Rule Disabled", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Disable-SafeAttachmentRule\" and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Disable-SafeAttachmentRule\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/disable-safeattachmentrule?view=exchange-ps" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_misc_lolbin_connecting_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_misc_lolbin_connecting_to_the_internet.json index b61a45e1287b7..5f45aa836ddf5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_misc_lolbin_connecting_to_the_internet.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_misc_lolbin_connecting_to_the_internet.json @@ -12,7 +12,10 @@ "language": "eql", "license": "Elastic License v2", "name": "Network Connection via Signed Binary", - "query": "sequence by process.entity_id\n [process where (process.name : \"expand.exe\" or process.name : \"extrac.exe\" or\n process.name : \"ieexec.exe\" or process.name : \"makecab.exe\") and\n event.type == \"start\"]\n [network where (process.name : \"expand.exe\" or process.name : \"extrac.exe\" or\n process.name : \"ieexec.exe\" or process.name : \"makecab.exe\") and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"172.16.0.0/12\", \"192.168.0.0/16\")]\n", + "query": "sequence by process.entity_id\n [process where (process.name : \"expand.exe\" or process.name : \"extrac.exe\" or\n process.name : \"ieexec.exe\" or process.name : \"makecab.exe\") and\n event.type == \"start\"]\n [network where (process.name : \"expand.exe\" or process.name : \"extrac.exe\" or\n process.name : \"ieexec.exe\" or process.name : \"makecab.exe\") and\n not cidrmatch(destination.ip,\n \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\", \"192.0.0.0/29\", \"192.0.0.8/32\",\n \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\", \"192.0.0.171/32\", \"192.0.2.0/24\", \"192.31.196.0/24\",\n \"192.52.193.0/24\", \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\", \"100.64.0.0/10\", \"192.175.48.0/24\",\n \"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\", \"FE80::/10\", \"FF00::/8\")]\n", + "references": [ + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], "risk_score": 21, "rule_id": "63e65ec3-43b1-45b0-8f2d-45b34291dc44", "severity": "low", @@ -50,5 +53,5 @@ } ], "type": "eql", - "version": 7 + "version": 8 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_modify_environment_launchctl.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_modify_environment_launchctl.json index d41804247945b..aa0efa290c4f6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_modify_environment_launchctl.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_modify_environment_launchctl.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Modification of Environment Variable via Launchctl", - "query": "event.category:process and event.type:start and process.name:launchctl and process.args:(setenv and not (JAVA*_HOME or RUNTIME_JAVA_HOME or DBUS_LAUNCHD_SESSION_BUS_SOCKET or ANT_HOME or LG_WEBOS_TV_SDK_HOME or WEBOS_CLI_TV or EDEN_ENV) ) and not process.parent.executable:(\"/Applications/NoMachine.app/Contents/Frameworks/bin/nxserver.bin\" or \"/usr/local/bin/kr\" or \"/Applications/NoMachine.app/Contents/Frameworks/bin/nxserver.bin\" or \"/Applications/IntelliJ IDEA CE.app/Contents/jbr/Contents/Home/lib/jspawnhelper\")", + "query": "event.category:process and event.type:start and\n process.name:launchctl and\n process.args:(setenv and not (JAVA*_HOME or\n RUNTIME_JAVA_HOME or\n DBUS_LAUNCHD_SESSION_BUS_SOCKET or\n ANT_HOME or\n LG_WEBOS_TV_SDK_HOME or\n WEBOS_CLI_TV or\n EDEN_ENV)\n ) and\n not process.parent.executable:(\"/Applications/NoMachine.app/Contents/Frameworks/bin/nxserver.bin\" or\n \"/usr/local/bin/kr\" or\n \"/Applications/NoMachine.app/Contents/Frameworks/bin/nxserver.bin\" or\n \"/Applications/IntelliJ IDEA CE.app/Contents/jbr/Contents/Home/lib/jspawnhelper\")\n", "references": [ "https://github.com/rapid7/metasploit-framework/blob/master//modules/post/osx/escalate/tccbypass.rb" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_msxsl_network.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_msxsl_network.json index 6d6541269030d..8f8871b75022e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_msxsl_network.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_msxsl_network.json @@ -12,7 +12,10 @@ "language": "eql", "license": "Elastic License v2", "name": "Network Connection via MsXsl", - "query": "sequence by process.entity_id\n [process where process.name : \"msxsl.exe\" and event.type == \"start\"]\n [network where process.name : \"msxsl.exe\" and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"172.16.0.0/12\", \"192.168.0.0/16\")]\n", + "query": "sequence by process.entity_id\n [process where process.name : \"msxsl.exe\" and event.type == \"start\"]\n [network where process.name : \"msxsl.exe\" and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\",\n \"192.0.0.0/29\", \"192.0.0.8/32\", \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\", \"192.0.0.171/32\",\n \"192.0.2.0/24\", \"192.31.196.0/24\", \"192.52.193.0/24\", \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\",\n \"100.64.0.0/10\", \"192.175.48.0/24\",\"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\",\n \"FE80::/10\", \"FF00::/8\")]\n", + "references": [ + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], "risk_score": 21, "rule_id": "b86afe07-0d98-4738-b15d-8d7465f95ff5", "severity": "low", @@ -41,5 +44,5 @@ } ], "type": "eql", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_watcher_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_watcher_deletion.json index 27a590f49cb31..030e72dd4a411 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_watcher_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_network_watcher_deletion.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure Network Watcher Deletion", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.NETWORK/NETWORKWATCHERS/DELETE\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.NETWORK/NETWORKWATCHERS/DELETE\" and event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/network-watcher/network-watcher-monitoring-overview" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_s3_bucket_configuration_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_s3_bucket_configuration_deletion.json index 4eb3bb47beff5..d673b7ef324f6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_s3_bucket_configuration_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_s3_bucket_configuration_deletion.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS S3 Bucket Configuration Deletion", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:s3.amazonaws.com and event.action:(DeleteBucketPolicy or DeleteBucketReplication or DeleteBucketCors or DeleteBucketEncryption or DeleteBucketLifecycle) and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:s3.amazonaws.com and\n event.action:(DeleteBucketPolicy or DeleteBucketReplication or DeleteBucketCors or\n DeleteBucketEncryption or DeleteBucketLifecycle)\n and event.outcome:success\n", "references": [ "https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketPolicy.html", "https://docs.aws.amazon.com/AmazonS3/latest/API/API_DeleteBucketReplication.html", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_safari_config_change.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_safari_config_change.json index 8021a21c8010d..a56b2cf6e6ded 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_safari_config_change.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_safari_config_change.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Modification of Safari Settings via Defaults Command", - "query": "event.category:process and event.type:start and process.name:defaults and process.args: (com.apple.Safari and write and not ( UniversalSearchEnabled or SuppressSearchSuggestions or WebKitTabToLinksPreferenceKey or ShowFullURLInSmartSearchField or com.apple.Safari.ContentPageGroupIdentifier.WebKit2TabsToLinks ) )", + "query": "event.category:process and event.type:start and\n process.name:defaults and process.args:\n (com.apple.Safari and write and not\n (\n UniversalSearchEnabled or\n SuppressSearchSuggestions or\n WebKitTabToLinksPreferenceKey or\n ShowFullURLInSmartSearchField or\n com.apple.Safari.ContentPageGroupIdentifier.WebKit2TabsToLinks\n )\n )\n", "references": [ "https://objectivebythesea.com/v2/talks/OBTS_v2_Zohar.pdf" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_sandboxed_office_app_suspicious_zip_file.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_sandboxed_office_app_suspicious_zip_file.json index 338010e1fe0e3..385f89910ab7d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_sandboxed_office_app_suspicious_zip_file.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_sandboxed_office_app_suspicious_zip_file.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential Microsoft Office Sandbox Evasion", - "query": "event.category:file and not event.type:deletion and file.name:~$*.zip", + "query": "event.category:file and not event.type:deletion and file.name:~$*.zip\n", "references": [ "https://i.blackhat.com/USA-20/Wednesday/us-20-Wardle-Office-Drama-On-macOS.pdf", "https://www.mdsec.co.uk/2018/08/escaping-the-sandbox-microsoft-office-on-macos/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_stop_process_service_threshold.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_stop_process_service_threshold.json index 8339c75c59c52..86903058b62fe 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_stop_process_service_threshold.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_stop_process_service_threshold.json @@ -12,7 +12,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "High Number of Process and/or Service Terminations", - "query": "event.category:process and event.type:start and process.name:(net.exe or sc.exe or taskkill.exe) and process.args:(stop or pause or delete or \"/PID\" or \"/IM\" or \"/T\" or \"/F\" or \"/t\" or \"/f\" or \"/im\" or \"/pid\")", + "query": "event.category:process and event.type:start and process.name:(net.exe or sc.exe or taskkill.exe) and\n process.args:(stop or pause or delete or \"/PID\" or \"/IM\" or \"/T\" or \"/F\" or \"/t\" or \"/f\" or \"/im\" or \"/pid\")\n", "risk_score": 47, "rule_id": "035889c4-2686-4583-a7df-67f89c292f2c", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_execution_from_mounted_device.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_execution_from_mounted_device.json new file mode 100644 index 0000000000000..b05402f419f5a --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_execution_from_mounted_device.json @@ -0,0 +1,89 @@ +{ + "author": [ + "Elastic" + ], + "description": "Identifies when a script interpreter or signed binary is launched via a non-standard working directory. An attacker may use this technique to evade defenses.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-endpoint.events.*", + "logs-windows.*" + ], + "language": "eql", + "license": "Elastic License v2", + "name": "Suspicious Execution from a Mounted Device", + "query": "process where event.type == \"start\" and process.executable : \"C:\\\\*\" and\n (process.working_directory : \"?:\\\\\" and not process.working_directory: \"C:\\\\\") and\n process.parent.name : \"explorer.exe\" and\n process.name : (\"rundll32.exe\", \"mshta.exe\", \"powershell.exe\", \"pwsh.exe\", \"cmd.exe\", \"regsvr32.exe\",\n \"cscript.exe\", \"wscript.exe\")\n", + "references": [ + "https://www.microsoft.com/security/blog/2021/05/27/new-sophisticated-email-based-attack-from-nobelium/", + "https://www.volexity.com/blog/2021/05/27/suspected-apt29-operation-launches-election-fraud-themed-phishing-campaigns/" + ], + "risk_score": 47, + "rule_id": "8a1d4831-3ce6-4859-9891-28931fa6101d", + "severity": "medium", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Defense Evasion" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1218", + "name": "Signed Binary Proxy Execution", + "reference": "https://attack.mitre.org/techniques/T1218/", + "subtechnique": [ + { + "id": "T1218.011", + "name": "Rundll32", + "reference": "https://attack.mitre.org/techniques/T1218/011/" + }, + { + "id": "T1218.005", + "name": "Mshta", + "reference": "https://attack.mitre.org/techniques/T1218/005/" + }, + { + "id": "T1218.010", + "name": "Regsvr32", + "reference": "https://attack.mitre.org/techniques/T1218/010/" + } + ] + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0002", + "name": "Execution", + "reference": "https://attack.mitre.org/tactics/TA0002/" + }, + "technique": [ + { + "id": "T1059", + "name": "Command and Scripting Interpreter", + "reference": "https://attack.mitre.org/techniques/T1059/", + "subtechnique": [ + { + "id": "T1059.001", + "name": "PowerShell", + "reference": "https://attack.mitre.org/techniques/T1059/001/" + } + ] + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "eql", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_okta_user_password_reset_or_unlock_attempts.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_okta_user_password_reset_or_unlock_attempts.json index b1ab19a25d840..d33620cbbf63b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_okta_user_password_reset_or_unlock_attempts.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_suspicious_okta_user_password_reset_or_unlock_attempts.json @@ -1,8 +1,10 @@ { "author": [ - "Elastic" + "Elastic", + "@BenB196", + "Austin Songer" ], - "description": "Identifies a high number of Okta user password reset or account unlock attempts. An adversary may attempt to obtain unauthorized access to an Okta user account using these methods and attempt to blend in with normal activity in their target's environment and evade detection.", + "description": "Identifies a high number of Okta user password reset or account unlock attempts. An adversary may attempt to obtain unauthorized access to Okta user accounts using these methods and attempt to blend in with normal activity in their target's environment and evade detection.", "false_positives": [ "The number of Okta user password reset or account unlock attempts will likely vary between organizations. To fit this rule to their organization, users can duplicate this rule and edit the schedule and threshold values in the new rule." ], @@ -15,7 +17,7 @@ "license": "Elastic License v2", "name": "High Number of Okta User Password Reset or Unlock Attempts", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:(system.email.account_unlock.sent_message or system.email.password_reset.sent_message or system.sms.send_account_unlock_message or system.sms.send_password_reset_message or system.voice.send_account_unlock_call or system.voice.send_password_reset_call or user.account.unlock_token)", + "query": "event.dataset:okta.system and\n event.action:(system.email.account_unlock.sent_message or system.email.password_reset.sent_message or\n system.sms.send_account_unlock_message or system.sms.send_password_reset_message or\n system.voice.send_account_unlock_call or system.voice.send_password_reset_call or\n user.account.unlock_token)\n", "references": [ "https://developer.okta.com/docs/reference/api/system-log/", "https://developer.okta.com/docs/reference/api/event-types/" @@ -80,10 +82,10 @@ ], "threshold": { "field": [ - "okta.actor.id" + "okta.actor.alternate_id" ], "value": 5 }, "type": "threshold", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_tcc_bypass_mounted_apfs_access.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_tcc_bypass_mounted_apfs_access.json index 963eb444305c7..4b1f13a10414d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_tcc_bypass_mounted_apfs_access.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_tcc_bypass_mounted_apfs_access.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "TCC Bypass via Mounted APFS Snapshot Access", - "query": "event.category : process and event.type : (start or process_started) and process.name : mount_apfs and process.args : (/System/Volumes/Data and noowners)", + "query": "event.category : process and event.type : (start or process_started) and process.name : mount_apfs and\n process.args : (/System/Volumes/Data and noowners)\n", "references": [ "https://theevilbit.github.io/posts/cve_2020_9771/" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unload_endpointsecurity_kext.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unload_endpointsecurity_kext.json index dc854dee776c4..aadcaadaba980 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unload_endpointsecurity_kext.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unload_endpointsecurity_kext.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Attempt to Unload Elastic Endpoint Security Kernel Extension", - "query": "event.category:process and event.type:(start or process_started) and process.name:kextunload and process.args:(\"/System/Library/Extensions/EndpointSecurity.kext\" or \"EndpointSecurity.kext\")", + "query": "event.category:process and event.type:(start or process_started) and\n process.name:kextunload and process.args:(\"/System/Library/Extensions/EndpointSecurity.kext\" or \"EndpointSecurity.kext\")\n", "risk_score": 73, "rule_id": "70fa1af4-27fd-4f26-bd03-50b6af6b9e24", "severity": "high", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unusual_network_connection_via_dllhost.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unusual_network_connection_via_dllhost.json new file mode 100644 index 0000000000000..a030c88941a41 --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unusual_network_connection_via_dllhost.json @@ -0,0 +1,51 @@ +{ + "author": [ + "Elastic" + ], + "description": "Identifies unusual instances of dllhost.exe making outbound network connections. This may indicate adversarial Command and Control activity.", + "from": "now-9m", + "index": [ + "winlogbeat-*", + "logs-endpoint.events.*", + "logs-windows.*" + ], + "language": "eql", + "license": "Elastic License v2", + "name": "Unusual Network Connection via DllHost", + "query": "sequence by host.id, process.entity_id with maxspan=1m\n [process where event.type in (\"start\", \"process_started\") and process.name : \"dllhost.exe\" and process.args_count == 1]\n [network where process.name : \"dllhost.exe\" and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\",\n \"192.0.0.0/29\", \"192.0.0.8/32\", \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\", \"192.0.0.171/32\", \"192.0.2.0/24\",\n \"192.31.196.0/24\", \"192.52.193.0/24\", \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\", \"100.64.0.0/10\",\n \"192.175.48.0/24\", \"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\", \"FE80::/10\",\n \"FF00::/8\")]\n", + "references": [ + "https://www.microsoft.com/security/blog/2021/05/27/new-sophisticated-email-based-attack-from-nobelium/", + "https://www.volexity.com/blog/2021/05/27/suspected-apt29-operation-launches-election-fraud-themed-phishing-campaigns/", + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], + "risk_score": 47, + "rule_id": "c7894234-7814-44c2-92a9-f7d851ea246a", + "severity": "medium", + "tags": [ + "Elastic", + "Host", + "Windows", + "Threat Detection", + "Defense Evasion" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0005", + "name": "Defense Evasion", + "reference": "https://attack.mitre.org/tactics/TA0005/" + }, + "technique": [ + { + "id": "T1218", + "name": "Signed Binary Proxy Execution", + "reference": "https://attack.mitre.org/techniques/T1218/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "eql", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unusual_network_connection_via_rundll32.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unusual_network_connection_via_rundll32.json index d920c4f853dfd..f37b6a21c7e58 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unusual_network_connection_via_rundll32.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_unusual_network_connection_via_rundll32.json @@ -12,7 +12,10 @@ "language": "eql", "license": "Elastic License v2", "name": "Unusual Network Connection via RunDLL32", - "query": "sequence by host.id, process.entity_id with maxspan=1m\n [process where event.type in (\"start\", \"process_started\") and process.name : \"rundll32.exe\" and process.args_count == 1]\n [network where process.name : \"rundll32.exe\" and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"172.16.0.0/12\", \"192.168.0.0/16\", \"127.0.0.0/8\", \"FE80::/10\", \"::1/128\")]\n", + "query": "sequence by host.id, process.entity_id with maxspan=1m\n [process where event.type in (\"start\", \"process_started\") and process.name : \"rundll32.exe\" and process.args_count == 1]\n [network where process.name : \"rundll32.exe\" and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\",\n \"192.0.0.0/29\", \"192.0.0.8/32\", \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\", \"192.0.0.171/32\",\n \"192.0.2.0/24\", \"192.31.196.0/24\", \"192.52.193.0/24\", \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\",\n \"100.64.0.0/10\", \"192.175.48.0/24\",\"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\",\n \"FE80::/10\", \"FF00::/8\")]\n", + "references": [ + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], "risk_score": 47, "rule_id": "52aaab7b-b51c-441a-89ce-4387b3aea886", "severity": "medium", @@ -48,5 +51,5 @@ } ], "type": "eql", - "version": 9 + "version": 10 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_acl_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_acl_deletion.json index cc2d47812b48c..9a7c7c9f668cc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_acl_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_acl_deletion.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS WAF Access Control List Deletion", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.action:DeleteWebACL and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.action:DeleteWebACL and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/waf-regional/delete-web-acl.html", "https://docs.aws.amazon.com/waf/latest/APIReference/API_wafRegional_DeleteWebACL.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_rule_or_rule_group_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_rule_or_rule_group_deletion.json index ee21d03f8464b..6f42caa63cf49 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_rule_or_rule_group_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/defense_evasion_waf_rule_or_rule_group_deletion.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS WAF Rule or Rule Group Deletion", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.action:(DeleteRule or DeleteRuleGroup) and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.action:(DeleteRule or DeleteRuleGroup) and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/waf/delete-rule-group.html", "https://docs.aws.amazon.com/waf/latest/APIReference/API_waf_DeleteRuleGroup.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_blob_container_access_mod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_blob_container_access_mod.json index 16eabb82de0f7..ed50b58a91e13 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_blob_container_access_mod.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_blob_container_access_mod.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure Blob Container Access Level Modification", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/WRITE\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/WRITE\" and event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/storage/blobs/anonymous-read-access-prevent" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_kernel_module_enumeration.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_kernel_module_enumeration.json index 01d07b03c079a..96860eb7e6f79 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_kernel_module_enumeration.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_kernel_module_enumeration.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Enumeration of Kernel Modules", - "query": "event.category:process and event.type:(start or process_started) and process.args:(kmod and list and sudo or sudo and (depmod or lsmod or modinfo))", + "query": "event.category:process and event.type:(start or process_started) and\n process.args:(kmod and list and sudo or sudo and (depmod or lsmod or modinfo))\n", "risk_score": 47, "rule_id": "2d8043ed-5bda-4caf-801c-c1feb7410504", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_virtual_machine_fingerprinting.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_virtual_machine_fingerprinting.json index 7defca7b649de..09adcdc65b02a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_virtual_machine_fingerprinting.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/discovery_virtual_machine_fingerprinting.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Virtual Machine Fingerprinting", - "query": "event.category:process and event.type:(start or process_started) and process.args:(\"/sys/class/dmi/id/bios_version\" or \"/sys/class/dmi/id/product_name\" or \"/sys/class/dmi/id/chassis_vendor\" or \"/proc/scsi/scsi\" or \"/proc/ide/hd0/model\") and not user.name:root", + "query": "event.category:process and event.type:(start or process_started) and\n process.args:(\"/sys/class/dmi/id/bios_version\" or\n \"/sys/class/dmi/id/product_name\" or\n \"/sys/class/dmi/id/chassis_vendor\" or\n \"/proc/scsi/scsi\" or\n \"/proc/ide/hd0/model\") and\n not user.name:root\n", "risk_score": 73, "rule_id": "5b03c9fb-9945-4d2f-9568-fd690fee3fba", "severity": "high", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/domain_added_to_google_workspace_trusted_domains.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/domain_added_to_google_workspace_trusted_domains.json index 96f246f9403bf..300840771081d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/domain_added_to_google_workspace_trusted_domains.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/domain_added_to_google_workspace_trusted_domains.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "Domain Added to Google Workspace Trusted Domains", "note": "## Config\n\nThe Google Workspace Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n\n### Important Information Regarding Google Workspace Event Lag Times\n- As per Google's documentation, Google Workspace administrators may observe lag times ranging from minutes up to 3 days between the time of an event's occurrence and the event being visible in the Google Workspace admin/audit logs.\n- This rule is configured to run every 10 minutes with a lookback time of 130 minutes.\n- To reduce the risk of false negatives, consider reducing the interval that the Google Workspace (formerly G Suite) Filebeat module polls Google's reporting API for new events.\n- By default, `var.interval` is set to 2 hours (2h). Consider changing this interval to a lower value, such as 10 minutes (10m).\n- See the following references for further information.\n - https://support.google.com/a/answer/7061566\n - https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-gsuite.html", - "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:ADD_TRUSTED_DOMAINS", + "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:ADD_TRUSTED_DOMAINS\n", "references": [ "https://support.google.com/a/answer/6160020?hl=en" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security.json index c3fb6d83f194f..63bf6fea698ae 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/elastic_endpoint_security.json @@ -20,7 +20,7 @@ "license": "Elastic License v2", "max_signals": 10000, "name": "Endpoint Security", - "query": "event.kind:alert and event.module:(endpoint and not endgame)", + "query": "event.kind:alert and event.module:(endpoint and not endgame)\n", "risk_score": 47, "risk_score_mapping": [ { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_adversary_behavior_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_adversary_behavior_detected.json index bf53625cef750..ff690710b5ba3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_adversary_behavior_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_adversary_behavior_detected.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Adversary Behavior - Detected - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and (event.action:rules_engine_event or endgame.event_subtype_full:rules_engine_event)", + "query": "event.kind:alert and event.module:endgame and (event.action:rules_engine_event or endgame.event_subtype_full:rules_engine_event)\n", "risk_score": 47, "rule_id": "77a3c3df-8ec4-4da4-b758-878f551dee69", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_detected.json index 43cb19f50d675..4aaf9938c29da 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_detected.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Credential Dumping - Detected - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:cred_theft_event or endgame.event_subtype_full:cred_theft_event)", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:cred_theft_event or endgame.event_subtype_full:cred_theft_event)\n", "risk_score": 73, "rule_id": "571afc56-5ed9-465d-a2a9-045f099f6e7e", "severity": "high", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_prevented.json index 29b5bc3f39cf1..11e8dece47fb5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_prevented.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_dumping_prevented.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Credential Dumping - Prevented - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:cred_theft_event or endgame.event_subtype_full:cred_theft_event)", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:cred_theft_event or endgame.event_subtype_full:cred_theft_event)\n", "risk_score": 47, "rule_id": "db8c33a8-03cd-4988-9e2c-d0a4863adb13", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_detected.json index 393591a241114..b6753cbbf784e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_detected.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Credential Manipulation - Detected - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:token_manipulation_event or endgame.event_subtype_full:token_manipulation_event)", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:token_manipulation_event or endgame.event_subtype_full:token_manipulation_event)\n", "risk_score": 73, "rule_id": "c0be5f31-e180-48ed-aa08-96b36899d48f", "severity": "high", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_prevented.json index e9ca199c4a791..9f409b00d6421 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_prevented.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_cred_manipulation_prevented.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Credential Manipulation - Prevented - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:token_manipulation_event or endgame.event_subtype_full:token_manipulation_event)", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:token_manipulation_event or endgame.event_subtype_full:token_manipulation_event)\n", "risk_score": 47, "rule_id": "c9e38e64-3f4c-4bf3-ad48-0e61a60ea1fa", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_detected.json index a169582c2da92..0cc778cc12714 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_detected.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Exploit - Detected - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:exploit_event or endgame.event_subtype_full:exploit_event)", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:exploit_event or endgame.event_subtype_full:exploit_event)\n", "risk_score": 73, "rule_id": "2003cdc8-8d83-4aa5-b132-1f9a8eb48514", "severity": "high", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_prevented.json index b781a1fae1847..fe7218fe878ee 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_prevented.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_exploit_prevented.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Exploit - Prevented - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:exploit_event or endgame.event_subtype_full:exploit_event)", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:exploit_event or endgame.event_subtype_full:exploit_event)\n", "risk_score": 47, "rule_id": "2863ffeb-bf77-44dd-b7a5-93ef94b72036", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_detected.json index f7a064961f039..92795c3811345 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_detected.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Malware - Detected - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:file_classification_event or endgame.event_subtype_full:file_classification_event)", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:file_classification_event or endgame.event_subtype_full:file_classification_event)\n", "risk_score": 99, "rule_id": "0a97b20f-4144-49ea-be32-b540ecc445de", "severity": "critical", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_prevented.json index 59cbd98e2d42b..f712f3f1b221d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_prevented.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_malware_prevented.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Malware - Prevented - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:file_classification_event or endgame.event_subtype_full:file_classification_event)", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:file_classification_event or endgame.event_subtype_full:file_classification_event)\n", "risk_score": 73, "rule_id": "3b382770-efbb-44f4-beed-f5e0a051b895", "severity": "high", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_detected.json index b3db96d6d121b..96b64c026ad0d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_detected.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Permission Theft - Detected - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:token_protection_event or endgame.event_subtype_full:token_protection_event)", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:token_protection_event or endgame.event_subtype_full:token_protection_event)\n", "risk_score": 73, "rule_id": "c3167e1b-f73c-41be-b60b-87f4df707fe3", "severity": "high", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_prevented.json index 18b316a293da8..fcb453d16100f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_prevented.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_permission_theft_prevented.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Permission Theft - Prevented - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:token_protection_event or endgame.event_subtype_full:token_protection_event)", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:token_protection_event or endgame.event_subtype_full:token_protection_event)\n", "risk_score": 47, "rule_id": "453f659e-0429-40b1-bfdb-b6957286e04b", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_detected.json index 861daa2d004c7..83a8ff2f83c8d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_detected.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Process Injection - Detected - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:kernel_shellcode_event or endgame.event_subtype_full:kernel_shellcode_event)", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:kernel_shellcode_event or endgame.event_subtype_full:kernel_shellcode_event)\n", "risk_score": 73, "rule_id": "80c52164-c82a-402c-9964-852533d58be1", "severity": "high", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_prevented.json index 5f78a3517e931..e171fbcf6bb83 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_prevented.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_process_injection_prevented.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Process Injection - Prevented - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:kernel_shellcode_event or endgame.event_subtype_full:kernel_shellcode_event)", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:kernel_shellcode_event or endgame.event_subtype_full:kernel_shellcode_event)\n", "risk_score": 47, "rule_id": "990838aa-a953-4f3e-b3cb-6ddf7584de9e", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_detected.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_detected.json index 4c060bb52f32f..b12352ee144d9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_detected.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_detected.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Ransomware - Detected - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:ransomware_event or endgame.event_subtype_full:ransomware_event)", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:detection and (event.action:ransomware_event or endgame.event_subtype_full:ransomware_event)\n", "risk_score": 99, "rule_id": "8cb4f625-7743-4dfb-ae1b-ad92be9df7bd", "severity": "critical", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_prevented.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_prevented.json index 78845ffc4c845..22150cd72a4c9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_prevented.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/endgame_ransomware_prevented.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Ransomware - Prevented - Elastic Endgame", - "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:ransomware_event or endgame.event_subtype_full:ransomware_event)", + "query": "event.kind:alert and event.module:endgame and endgame.metadata.type:prevention and (event.action:ransomware_event or endgame.event_subtype_full:ransomware_event)\n", "risk_score": 73, "rule_id": "e3c5d5cb-41d5-4206-805c-f30561eae3ac", "severity": "high", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_prompt_connecting_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_prompt_connecting_to_the_internet.json index 32673c7800f0b..e5bef64a4c747 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_prompt_connecting_to_the_internet.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_prompt_connecting_to_the_internet.json @@ -15,7 +15,10 @@ "language": "eql", "license": "Elastic License v2", "name": "Command Prompt Network Connection", - "query": "sequence by process.entity_id\n [process where process.name : \"cmd.exe\" and event.type == \"start\"]\n [network where process.name : \"cmd.exe\" and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"172.16.0.0/12\", \"192.168.0.0/16\")]\n", + "query": "sequence by process.entity_id\n [process where process.name : \"cmd.exe\" and event.type == \"start\"]\n [network where process.name : \"cmd.exe\" and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\",\n \"192.0.0.0/29\", \"192.0.0.8/32\", \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\",\n \"192.0.0.171/32\", \"192.0.2.0/24\", \"192.31.196.0/24\", \"192.52.193.0/24\",\n \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\", \"100.64.0.0/10\", \"192.175.48.0/24\",\n \"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\",\n \"FE80::/10\", \"FF00::/8\")]\n", + "references": [ + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], "risk_score": 21, "rule_id": "89f9a4b0-9f8f-4ee0-8823-c4751a6d6696", "severity": "low", @@ -59,5 +62,5 @@ } ], "type": "eql", - "version": 6 + "version": 7 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_virtual_machine.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_virtual_machine.json index 8254e9e1c75e0..1292596404eff 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_virtual_machine.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_command_virtual_machine.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure Command Execution on Virtual Machine", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION\" and event.outcome:(Success or success)\n", "references": [ "https://adsecurity.org/?p=4277", "https://posts.specterops.io/attacking-azure-azure-ad-and-introducing-powerzure-ca70b330511a", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_defense_evasion_electron_app_childproc_node_js.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_defense_evasion_electron_app_childproc_node_js.json index cb3c3b3d040f3..4bf6c272e59ae 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_defense_evasion_electron_app_childproc_node_js.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_defense_evasion_electron_app_childproc_node_js.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Execution via Electron Child Process Node.js Module", - "query": "event.category:process and event.type:(start or process_started) and process.args:(\"-e\" and const*require*child_process*)", + "query": "event.category:process and event.type:(start or process_started) and process.args:(\"-e\" and const*require*child_process*)\n", "references": [ "https://www.matthewslipper.com/2019/09/22/everything-you-wanted-electron-child-process.html", "https://www.trustedsec.com/blog/macos-injection-via-third-party-frameworks/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_html_help_executable_program_connecting_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_html_help_executable_program_connecting_to_the_internet.json index 31a81001d9e04..abc41d9f6d5c3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_html_help_executable_program_connecting_to_the_internet.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_html_help_executable_program_connecting_to_the_internet.json @@ -12,7 +12,10 @@ "language": "eql", "license": "Elastic License v2", "name": "Network Connection via Compiled HTML File", - "query": "sequence by process.entity_id\n [process where process.name : \"hh.exe\" and event.type == \"start\"]\n [network where process.name : \"hh.exe\" and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"172.16.0.0/12\", \"192.168.0.0/16\")]\n", + "query": "sequence by process.entity_id\n [process where process.name : \"hh.exe\" and event.type == \"start\"]\n [network where process.name : \"hh.exe\" and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\",\n \"192.0.0.0/29\", \"192.0.0.8/32\", \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\", \"192.0.0.171/32\",\n \"192.0.2.0/24\", \"192.31.196.0/24\", \"192.52.193.0/24\", \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\",\n \"100.64.0.0/10\", \"192.175.48.0/24\",\"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\",\n \"FE80::/10\", \"FF00::/8\")]\n", + "references": [ + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], "risk_score": 21, "rule_id": "b29ee2be-bf99-446c-ab1a-2dc0183394b8", "severity": "low", @@ -57,5 +60,5 @@ } ], "type": "eql", - "version": 7 + "version": 8 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_installer_spawned_network_event.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_installer_spawned_network_event.json index 6fce74fb44b12..5781c25789b94 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_installer_spawned_network_event.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_installer_spawned_network_event.json @@ -13,9 +13,10 @@ "language": "eql", "license": "Elastic License v2", "name": "macOS Installer Spawns Network Event", - "query": "sequence by process.entity_id with maxspan=1m\n [ process where event.type == \"start\" and host.os.family == \"macos\" and \n process.parent.executable in (\"/usr/sbin/installer\", \"/System/Library/CoreServices/Installer.app/Contents/MacOS/Installer\") ]\n [ network where not cidrmatch(destination.ip,\n \"192.168.0.0/16\",\n \"10.0.0.0/8\",\n \"172.16.0.0/12\",\n \"224.0.0.0/8\",\n \"127.0.0.0/8\",\n \"169.254.0.0/16\",\n \"::1\",\n \"FE80::/10\",\n \"FF00::/8\") ]\n", + "query": "sequence by process.entity_id with maxspan=1m\n [process where event.type == \"start\" and host.os.family == \"macos\" and\n process.parent.executable in (\"/usr/sbin/installer\", \"/System/Library/CoreServices/Installer.app/Contents/MacOS/Installer\") ]\n [network where not cidrmatch(destination.ip,\n \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\", \"192.0.0.0/29\", \"192.0.0.8/32\",\n \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\", \"192.0.0.171/32\", \"192.0.2.0/24\", \"192.31.196.0/24\",\n \"192.52.193.0/24\", \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\", \"100.64.0.0/10\", \"192.175.48.0/24\",\n \"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\", \"FE80::/10\", \"FF00::/8\")]\n", "references": [ - "https://redcanary.com/blog/clipping-silver-sparrows-wings" + "https://redcanary.com/blog/clipping-silver-sparrows-wings", + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" ], "risk_score": 47, "rule_id": "99239e7d-b0d4-46e3-8609-acafcf99f68c", @@ -75,5 +76,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_pentest_eggshell_remote_admin_tool.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_pentest_eggshell_remote_admin_tool.json index eb453205441a7..77537be3f1cbb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_pentest_eggshell_remote_admin_tool.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_pentest_eggshell_remote_admin_tool.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "EggShell Backdoor Execution", - "query": "event.category:process and event.type:(start or process_started) and process.name:espl and process.args:eyJkZWJ1ZyI6*", + "query": "event.category:process and event.type:(start or process_started) and process.name:espl and process.args:eyJkZWJ1ZyI6*\n", "references": [ "https://github.com/neoneggplant/EggShell" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_perl_tty_shell.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_perl_tty_shell.json index b2d71b355e3a1..0f1e857232e40 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_perl_tty_shell.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_perl_tty_shell.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Interactive Terminal Spawned via Perl", - "query": "event.category:process and event.type:(start or process_started) and process.name:perl and process.args:(\"exec \\\"/bin/sh\\\";\" or \"exec \\\"/bin/dash\\\";\" or \"exec \\\"/bin/bash\\\";\")", + "query": "event.category:process and event.type:(start or process_started) and process.name:perl and\n process.args:(\"exec \\\"/bin/sh\\\";\" or \"exec \\\"/bin/dash\\\";\" or \"exec \\\"/bin/bash\\\";\")\n", "risk_score": 73, "rule_id": "05e5a668-7b51-4a67-93ab-e9af405c9ef3", "severity": "high", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_python_tty_shell.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_python_tty_shell.json index 402f5b0ab33ff..2c40ff28bfa11 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_python_tty_shell.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_python_tty_shell.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Interactive Terminal Spawned via Python", - "query": "event.category:process and event.type:(start or process_started) and process.name:python and process.args:(\"import pty; pty.spawn(\\\"/bin/sh\\\")\" or \"import pty; pty.spawn(\\\"/bin/dash\\\")\" or \"import pty; pty.spawn(\\\"/bin/bash\\\")\")", + "query": "event.category:process and event.type:(start or process_started) and process.name:python and\n process.args:(\"import pty; pty.spawn(\\\"/bin/sh\\\")\" or\n \"import pty; pty.spawn(\\\"/bin/dash\\\")\" or\n \"import pty; pty.spawn(\\\"/bin/bash\\\")\")\n", "risk_score": 73, "rule_id": "d76b02ef-fc95-4001-9297-01cb7412232f", "severity": "high", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_register_server_program_connecting_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_register_server_program_connecting_to_the_internet.json index ca919d06e34a4..2ccc730c3fa01 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_register_server_program_connecting_to_the_internet.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_register_server_program_connecting_to_the_internet.json @@ -15,7 +15,10 @@ "language": "eql", "license": "Elastic License v2", "name": "Network Connection via Registration Utility", - "query": "sequence by process.entity_id\n [process where event.type == \"start\" and\n process.name : (\"regsvr32.exe\", \"RegAsm.exe\", \"RegSvcs.exe\") and\n not (\n user.id == \"S-1-5-18\" and\n (process.parent.name : \"msiexec.exe\" or process.parent.executable : (\"C:\\\\Program Files (x86)\\\\*.exe\", \"C:\\\\Program Files\\\\*.exe\"))\n )\n ]\n [network where process.name : (\"regsvr32.exe\", \"RegAsm.exe\", \"RegSvcs.exe\") and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"169.254.169.254\", \"172.16.0.0/12\", \"192.168.0.0/16\") and network.protocol != \"dns\"]\n", + "query": "sequence by process.entity_id\n [process where event.type == \"start\" and\n process.name : (\"regsvr32.exe\", \"RegAsm.exe\", \"RegSvcs.exe\") and\n not (\n user.id == \"S-1-5-18\" and\n (process.parent.name : \"msiexec.exe\" or process.parent.executable : (\"C:\\\\Program Files (x86)\\\\*.exe\", \"C:\\\\Program Files\\\\*.exe\"))\n )\n ]\n [network where process.name : (\"regsvr32.exe\", \"RegAsm.exe\", \"RegSvcs.exe\") and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\",\n \"192.0.0.0/29\", \"192.0.0.8/32\", \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\", \"192.0.0.171/32\",\n \"192.0.2.0/24\", \"192.31.196.0/24\", \"192.52.193.0/24\", \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\",\n \"100.64.0.0/10\", \"192.175.48.0/24\",\"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\",\n \"FE80::/10\", \"FF00::/8\") and network.protocol != \"dns\"]\n", + "references": [ + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], "risk_score": 21, "rule_id": "fb02b8d3-71ee-4af1-bacd-215d23f17efa", "severity": "low", @@ -60,5 +63,5 @@ } ], "type": "eql", - "version": 8 + "version": 9 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_scripting_osascript_exec_followed_by_netcon.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_scripting_osascript_exec_followed_by_netcon.json index 1d6fa8507ac43..74a70eb7ebd93 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_scripting_osascript_exec_followed_by_netcon.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/execution_scripting_osascript_exec_followed_by_netcon.json @@ -11,9 +11,10 @@ "language": "eql", "license": "Elastic License v2", "name": "Apple Script Execution followed by Network Connection", - "query": "sequence by host.id, process.entity_id with maxspan=30s\n [process where event.type == \"start\" and process.name == \"osascript\"]\n [network where event.type != \"end\" and process.name == \"osascript\" and destination.ip != \"::1\" and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \n \"172.16.0.0/12\", \n \"192.168.0.0/16\", \n \"127.0.0.0/8\", \n \"169.254.0.0/16\", \n \"224.0.0.0/4\", \n \"FE80::/10\", \n \"FF00::/8\")\n ]\n", + "query": "sequence by host.id, process.entity_id with maxspan=30s\n [process where event.type == \"start\" and process.name == \"osascript\"]\n [network where event.type != \"end\" and process.name == \"osascript\" and destination.ip != \"::1\" and\n not cidrmatch(destination.ip,\n \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\", \"192.0.0.0/29\", \"192.0.0.8/32\",\n \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\", \"192.0.0.171/32\", \"192.0.2.0/24\", \"192.31.196.0/24\",\n \"192.52.193.0/24\", \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\", \"100.64.0.0/10\", \"192.175.48.0/24\",\n \"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\", \"FE80::/10\", \"FF00::/8\")]\n", "references": [ - "https://developer.apple.com/library/archive/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/index.html" + "https://developer.apple.com/library/archive/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/index.html", + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" ], "risk_score": 47, "rule_id": "47f76567-d58a-4fed-b32b-21f571e28910", @@ -59,5 +60,5 @@ } ], "type": "eql", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_ec2_snapshot_change_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_ec2_snapshot_change_activity.json index 7c67a3f037538..f4d0877ca70b7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_ec2_snapshot_change_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_ec2_snapshot_change_activity.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS EC2 Snapshot Activity", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:ec2.amazonaws.com and event.action:ModifySnapshotAttribute", + "query": "event.dataset:aws.cloudtrail and event.provider:ec2.amazonaws.com and event.action:ModifySnapshotAttribute\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/modify-snapshot-attribute.html", "https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifySnapshotAttribute.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_ec2_vm_export_failure.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_ec2_vm_export_failure.json new file mode 100644 index 0000000000000..2bf25435b84de --- /dev/null +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_ec2_vm_export_failure.json @@ -0,0 +1,70 @@ +{ + "author": [ + "Elastic", + "Austin Songer" + ], + "description": "Identifies an attempt to export an AWS EC2 instance. A virtual machine (VM) export may indicate an attempt to extract or exfiltrate information.", + "false_positives": [ + "VM exports may be done by a system or network administrator. Verify whether the user identity, user agent, and/or hostname should be making changes in your environment. VM exports from unfamiliar users or hosts should be investigated. If known behavior is causing false positives, it can be exempted from the rule." + ], + "from": "now-60m", + "index": [ + "filebeat-*", + "logs-aws*" + ], + "interval": "10m", + "language": "kuery", + "license": "Elastic License v2", + "name": "AWS EC2 VM Export Failure", + "note": "## Config\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", + "query": "event.dataset:aws.cloudtrail and event.provider:ec2.amazonaws.com and event.action:CreateInstanceExportTask and event.outcome:failure\n", + "references": [ + "https://docs.aws.amazon.com/vm-import/latest/userguide/vmexport.html#export-instance" + ], + "risk_score": 21, + "rule_id": "e919611d-6b6f-493b-8314-7ed6ac2e413b", + "severity": "low", + "tags": [ + "Elastic", + "Cloud", + "AWS", + "Continuous Monitoring", + "SecOps", + "Asset Visibility" + ], + "threat": [ + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0010", + "name": "Exfiltration", + "reference": "https://attack.mitre.org/tactics/TA0010/" + }, + "technique": [ + { + "id": "T1537", + "name": "Transfer Data to Cloud Account", + "reference": "https://attack.mitre.org/techniques/T1537/" + } + ] + }, + { + "framework": "MITRE ATT&CK", + "tactic": { + "id": "TA0009", + "name": "Collection", + "reference": "https://attack.mitre.org/tactics/TA0009/" + }, + "technique": [ + { + "id": "T1005", + "name": "Data from Local System", + "reference": "https://attack.mitre.org/techniques/T1005/" + } + ] + } + ], + "timestamp_override": "event.ingested", + "type": "query", + "version": 1 +} diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_gcp_logging_sink_modification.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_gcp_logging_sink_modification.json index ddff312a362ee..ac016370fe1c0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_gcp_logging_sink_modification.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_gcp_logging_sink_modification.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Logging Sink Modification", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.logging.v*.ConfigServiceV*.UpdateSink and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.logging.v*.ConfigServiceV*.UpdateSink and event.outcome:success\n", "references": [ "https://cloud.google.com/logging/docs/export#how_sinks_work" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_creation.json index ec9373352254b..a6a9e24ccb63a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_creation.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 Exchange Transport Rule Creation", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"New-TransportRule\" and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"New-TransportRule\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/new-transportrule?view=exchange-ps", "https://docs.microsoft.com/en-us/exchange/security-and-compliance/mail-flow-rules/mail-flow-rules" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_mod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_mod.json index 2503f679464f1..836ade6c0b80f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_mod.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/exfiltration_microsoft_365_exchange_transport_rule_mod.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 Exchange Transport Rule Modification", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:(\"Remove-TransportRule\" or \"Disable-TransportRule\") and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:(\"Remove-TransportRule\" or \"Disable-TransportRule\") and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/remove-transportrule?view=exchange-ps", "https://docs.microsoft.com/en-us/powershell/module/exchange/disable-transportrule?view=exchange-ps", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/external_alerts.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/external_alerts.json index b97e868b21f55..fbcc6e757c66b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/external_alerts.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/external_alerts.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "max_signals": 10000, "name": "External Alerts", - "query": "event.kind:alert and not event.module:(endgame or endpoint)", + "query": "event.kind:alert and not event.module:(endgame or endpoint)\n", "risk_score": 47, "risk_score_mapping": [ { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/google_workspace_admin_role_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/google_workspace_admin_role_deletion.json index ba84d38d7e4ee..e0a333d92c5aa 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/google_workspace_admin_role_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/google_workspace_admin_role_deletion.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "Google Workspace Admin Role Deletion", "note": "## Config\n\nThe Google Workspace Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n\n### Important Information Regarding Google Workspace Event Lag Times\n- As per Google's documentation, Google Workspace administrators may observe lag times ranging from minutes up to 3 days between the time of an event's occurrence and the event being visible in the Google Workspace admin/audit logs.\n- This rule is configured to run every 10 minutes with a lookback time of 130 minutes.\n- To reduce the risk of false negatives, consider reducing the interval that the Google Workspace (formerly G Suite) Filebeat module polls Google's reporting API for new events.\n- By default, `var.interval` is set to 2 hours (2h). Consider changing this interval to a lower value, such as 10 minutes (10m).\n- See the following references for further information.\n - https://support.google.com/a/answer/7061566\n - https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-gsuite.html", - "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:DELETE_ROLE", + "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:DELETE_ROLE\n", "references": [ "https://support.google.com/a/answer/2406043?hl=en" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/google_workspace_mfa_enforcement_disabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/google_workspace_mfa_enforcement_disabled.json index 551133ed2a58d..b05edc0566614 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/google_workspace_mfa_enforcement_disabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/google_workspace_mfa_enforcement_disabled.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "Google Workspace MFA Enforcement Disabled", "note": "## Config\n\nThe Google Workspace Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n\n### Important Information Regarding Google Workspace Event Lag Times\n- As per Google's documentation, Google Workspace administrators may observe lag times ranging from minutes up to 3 days between the time of an event's occurrence and the event being visible in the Google Workspace admin/audit logs.\n- This rule is configured to run every 10 minutes with a lookback time of 130 minutes.\n- To reduce the risk of false negatives, consider reducing the interval that the Google Workspace (formerly G Suite) Filebeat module polls Google's reporting API for new events.\n- By default, `var.interval` is set to 2 hours (2h). Consider changing this interval to a lower value, such as 10 minutes (10m).\n- See the following references for further information.\n - https://support.google.com/a/answer/7061566\n - https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-gsuite.html", - "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:ENFORCE_STRONG_AUTHENTICATION and gsuite.admin.new_value:false", + "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:ENFORCE_STRONG_AUTHENTICATION and gsuite.admin.new_value:false\n", "references": [ "https://support.google.com/a/answer/9176657?hl=en#" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/google_workspace_policy_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/google_workspace_policy_modified.json index 5893782912b35..58a409570f0db 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/google_workspace_policy_modified.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/google_workspace_policy_modified.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "Google Workspace Password Policy Modified", "note": "## Config\n\nThe Google Workspace Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n\n### Important Information Regarding Google Workspace Event Lag Times\n- As per Google's documentation, Google Workspace administrators may observe lag times ranging from minutes up to 3 days between the time of an event's occurrence and the event being visible in the Google Workspace admin/audit logs.\n- This rule is configured to run every 10 minutes with a lookback time of 130 minutes.\n- To reduce the risk of false negatives, consider reducing the interval that the Google Workspace (formerly G Suite) Filebeat module polls Google's reporting API for new events.\n- By default, `var.interval` is set to 2 hours (2h). Consider changing this interval to a lower value, such as 10 minutes (10m).\n- See the following references for further information.\n - https://support.google.com/a/answer/7061566\n - https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-gsuite.html", - "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:(CHANGE_APPLICATION_SETTING or CREATE_APPLICATION_SETTING) and gsuite.admin.setting.name:( \"Password Management - Enforce strong password\" or \"Password Management - Password reset frequency\" or \"Password Management - Enable password reuse\" or \"Password Management - Enforce password policy at next login\" or \"Password Management - Minimum password length\" or \"Password Management - Maximum password length\" )", + "query": "event.dataset:(gsuite.admin or google_workspace.admin) and\n event.provider:admin and event.category:iam and\n event.action:(CHANGE_APPLICATION_SETTING or CREATE_APPLICATION_SETTING) and\n gsuite.admin.setting.name:(\n \"Password Management - Enforce strong password\" or\n \"Password Management - Password reset frequency\" or\n \"Password Management - Enable password reuse\" or\n \"Password Management - Enforce password policy at next login\" or\n \"Password Management - Minimum password length\" or\n \"Password Management - Maximum password length\"\n )\n", "risk_score": 47, "rule_id": "a99f82f5-8e77-4f8b-b3ce-10c0f6afbc73", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_attempt_to_revoke_okta_api_token.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_attempt_to_revoke_okta_api_token.json index aebda3bb268d1..ba55b3fc7a9bb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_attempt_to_revoke_okta_api_token.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_attempt_to_revoke_okta_api_token.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Revoke Okta API Token", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:system.api_token.revoke", + "query": "event.dataset:okta.system and event.action:system.api_token.revoke\n", "references": [ "https://developer.okta.com/docs/reference/api/system-log/", "https://developer.okta.com/docs/reference/api/event-types/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_azure_automation_runbook_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_azure_automation_runbook_deleted.json index fb468ff8f6d7d..83fd544c51f13 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_azure_automation_runbook_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_azure_automation_runbook_deleted.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "name": "Azure Automation Runbook Deleted", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/DELETE\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/DELETE\" and event.outcome:(Success or success)\n", "references": [ "https://powerzure.readthedocs.io/en/latest/Functions/operational.html#create-backdoor", "https://github.com/hausec/PowerZure", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudtrail_logging_updated.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudtrail_logging_updated.json index 9d1c0d3758a9d..196f54bfc174d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudtrail_logging_updated.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudtrail_logging_updated.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS CloudTrail Log Updated", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:cloudtrail.amazonaws.com and event.action:UpdateTrail and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:cloudtrail.amazonaws.com and event.action:UpdateTrail and event.outcome:success\n", "references": [ "https://docs.aws.amazon.com/awscloudtrail/latest/APIReference/API_UpdateTrail.html", "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/cloudtrail/update-trail.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_group_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_group_deletion.json index 14f0419cb4073..f92d6ec44d655 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_group_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_group_deletion.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS CloudWatch Log Group Deletion", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:logs.amazonaws.com and event.action:DeleteLogGroup and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:logs.amazonaws.com and event.action:DeleteLogGroup and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/logs/delete-log-group.html", "https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_DeleteLogGroup.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_stream_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_stream_deletion.json index 6d37a106aa9ab..46ac2d19889f2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_stream_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_cloudwatch_log_stream_deletion.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS CloudWatch Log Stream Deletion", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:logs.amazonaws.com and event.action:DeleteLogStream and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:logs.amazonaws.com and event.action:DeleteLogStream and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/logs/delete-log-stream.html", "https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_DeleteLogStream.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_ec2_disable_ebs_encryption.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_ec2_disable_ebs_encryption.json index 94b1839dfc5dd..04f1adaee3edb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_ec2_disable_ebs_encryption.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_ec2_disable_ebs_encryption.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS EC2 Encryption Disabled", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:ec2.amazonaws.com and event.action:DisableEbsEncryptionByDefault and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:ec2.amazonaws.com and event.action:DisableEbsEncryptionByDefault and event.outcome:success\n", "references": [ "https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSEncryption.html", "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/disable-ebs-encryption-by-default.html", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_iam_role_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_iam_role_deletion.json index 5ed1aa4386de4..76901da74ce96 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_iam_role_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_iam_role_deletion.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP IAM Role Deletion", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.iam.admin.v*.DeleteRole and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.iam.admin.v*.DeleteRole and event.outcome:success\n", "references": [ "https://cloud.google.com/iam/docs/understanding-roles" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_deleted.json index 134278f30abb6..e928a60c132f6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_deleted.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Service Account Deletion", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.iam.admin.v*.DeleteServiceAccount and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.iam.admin.v*.DeleteServiceAccount and event.outcome:success\n", "references": [ "https://cloud.google.com/iam/docs/service-accounts" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_disabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_disabled.json index a7750fc586729..6c205987eaf17 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_disabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_service_account_disabled.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Service Account Disabled", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.iam.admin.v*.DisableServiceAccount and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.iam.admin.v*.DisableServiceAccount and event.outcome:success\n", "references": [ "https://cloud.google.com/iam/docs/service-accounts" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_storage_bucket_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_storage_bucket_deleted.json index c534dae963970..c3aa1523e4d1e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_storage_bucket_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_storage_bucket_deleted.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Storage Bucket Deletion", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:\"storage.buckets.delete\"", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:\"storage.buckets.delete\"\n", "references": [ "https://cloud.google.com/storage/docs/key-terms#buckets" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_network_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_network_deleted.json index caad64c558863..2748a1f573e9f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_network_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_network_deleted.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Virtual Private Cloud Network Deletion", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:v*.compute.networks.delete and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:v*.compute.networks.delete and event.outcome:success\n", "references": [ "https://cloud.google.com/vpc/docs/vpc" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_created.json index 7e2090de29c62..ef4ee82058d32 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_created.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_created.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Virtual Private Cloud Route Creation", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:(v*.compute.routes.insert or \"beta.compute.routes.insert\")", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:(v*.compute.routes.insert or \"beta.compute.routes.insert\")\n", "references": [ "https://cloud.google.com/vpc/docs/routes", "https://cloud.google.com/vpc/docs/using-routes" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_deleted.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_deleted.json index a8b8b12b60960..0d4f5591c9688 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_deleted.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_gcp_virtual_private_cloud_route_deleted.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Virtual Private Cloud Route Deletion", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:v*.compute.routes.delete and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:v*.compute.routes.delete and event.outcome:success\n", "references": [ "https://cloud.google.com/vpc/docs/routes", "https://cloud.google.com/vpc/docs/using-routes" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_deactivate_mfa_device.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_deactivate_mfa_device.json index 7b77a414dd1e0..cb4f1a15cd337 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_deactivate_mfa_device.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_deactivate_mfa_device.json @@ -17,7 +17,7 @@ "license": "Elastic License v2", "name": "AWS IAM Deactivation of MFA Device", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:iam.amazonaws.com and event.action:(DeactivateMFADevice or DeleteVirtualMFADevice) and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:iam.amazonaws.com and event.action:(DeactivateMFADevice or DeleteVirtualMFADevice) and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/deactivate-mfa-device.html", "https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeactivateMFADevice.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_group_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_group_deletion.json index 2c43b0560e660..e1f5fcbf4836e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_group_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_iam_group_deletion.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS IAM Group Deletion", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:iam.amazonaws.com and event.action:DeleteGroup and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:iam.amazonaws.com and event.action:DeleteGroup and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/delete-group.html", "https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeleteGroup.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_possible_okta_dos_attack.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_possible_okta_dos_attack.json index 649c859de8184..7372eb0e0286b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_possible_okta_dos_attack.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_possible_okta_dos_attack.json @@ -11,7 +11,7 @@ "license": "Elastic License v2", "name": "Possible Okta DoS Attack", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:(application.integration.rate_limit_exceeded or system.org.rate_limit.warning or system.org.rate_limit.violation or core.concurrency.org.limit.violation)", + "query": "event.dataset:okta.system and event.action:(application.integration.rate_limit_exceeded or system.org.rate_limit.warning or system.org.rate_limit.violation or core.concurrency.org.limit.violation)\n", "references": [ "https://developer.okta.com/docs/reference/api/system-log/", "https://developer.okta.com/docs/reference/api/event-types/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_cluster_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_cluster_deletion.json index 94837f665af75..08ae6ce11bbb5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_cluster_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_cluster_deletion.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS RDS Cluster Deletion", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:rds.amazonaws.com and event.action:(DeleteDBCluster or DeleteGlobalCluster) and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:rds.amazonaws.com and event.action:(DeleteDBCluster or DeleteGlobalCluster) and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/rds/delete-db-cluster.html", "https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DeleteDBCluster.html", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_instance_cluster_stoppage.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_instance_cluster_stoppage.json index 065c39f8f676b..e35a0c145ac59 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_instance_cluster_stoppage.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_rds_instance_cluster_stoppage.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS RDS Instance/Cluster Stoppage", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:rds.amazonaws.com and event.action:(StopDBCluster or StopDBInstance) and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:rds.amazonaws.com and event.action:(StopDBCluster or StopDBInstance) and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/rds/stop-db-cluster.html", "https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_StopDBCluster.html", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_resource_group_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_resource_group_deletion.json index 221f1b1e46eb2..16153a832dcb9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_resource_group_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/impact_resource_group_deletion.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure Resource Group Deletion", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.RESOURCES/SUBSCRIPTIONS/RESOURCEGROUPS/DELETE\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.RESOURCES/SUBSCRIPTIONS/RESOURCEGROUPS/DELETE\" and event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts index e910b1a10f586..dc3ca4ceed4c8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/index.ts @@ -544,7 +544,11 @@ import rule531 from './ml_spike_in_traffic_to_a_country.json'; import rule532 from './command_and_control_tunneling_via_earthworm.json'; import rule533 from './lateral_movement_evasion_rdp_shadowing.json'; import rule534 from './threat_intel_module_match.json'; -import rule535 from './persistence_via_bits_job_notify_command.json'; +import rule535 from './exfiltration_ec2_vm_export_failure.json'; +import rule536 from './defense_evasion_suspicious_execution_from_mounted_device.json'; +import rule537 from './defense_evasion_unusual_network_connection_via_dllhost.json'; +import rule538 from './defense_evasion_amsienable_key_mod.json'; +import rule539 from './persistence_via_bits_job_notify_command.json'; export const rawRules = [ rule1, @@ -1082,4 +1086,8 @@ export const rawRules = [ rule533, rule534, rule535, + rule536, + rule537, + rule538, + rule539, ]; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_azure_active_directory_high_risk_signin.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_azure_active_directory_high_risk_signin.json index b18ab4090b1f8..008f6ac7b874c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_azure_active_directory_high_risk_signin.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_azure_active_directory_high_risk_signin.json @@ -13,7 +13,7 @@ "license": "Elastic License v2", "name": "Azure Active Directory High Risk Sign-in", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.signinlogs and azure.signinlogs.properties.risk_level_during_signin:high and event.outcome:(success or Success)", + "query": "event.dataset:azure.signinlogs and\n azure.signinlogs.properties.risk_level_during_signin:high and\n event.outcome:(success or Success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/howto-conditional-access-policy-risk", "https://docs.microsoft.com/en-us/azure/active-directory/identity-protection/overview-identity-protection", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_azure_active_directory_powershell_signin.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_azure_active_directory_powershell_signin.json index 7e77d851eac00..207d5534efd79 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_azure_active_directory_powershell_signin.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_azure_active_directory_powershell_signin.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure Active Directory PowerShell Sign-in", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.signinlogs and azure.signinlogs.properties.app_display_name:\"Azure Active Directory PowerShell\" and azure.signinlogs.properties.token_issuer_type:AzureAD and event.outcome:(success or Success)", + "query": "event.dataset:azure.signinlogs and\n azure.signinlogs.properties.app_display_name:\"Azure Active Directory PowerShell\" and\n azure.signinlogs.properties.token_issuer_type:AzureAD and event.outcome:(success or Success)\n", "references": [ "https://msrc-blog.microsoft.com/2020/12/13/customer-guidance-on-recent-nation-state-cyber-attacks/", "https://docs.microsoft.com/en-us/microsoft-365/enterprise/connect-to-microsoft-365-powershell?view=o365-worldwide" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_consent_grant_attack_via_azure_registered_application.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_consent_grant_attack_via_azure_registered_application.json index f73c30f55eb3a..45acc46fcd49d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_consent_grant_attack_via_azure_registered_application.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_consent_grant_attack_via_azure_registered_application.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "name": "Possible Consent Grant Attack via Azure-Registered Application", "note": "## Triage and analysis\n\n- In a consent grant attack, an attacker tricks an end user into granting a malicious application consent to access their data, usually via a phishing attack. After the malicious application has been granted consent, it has account-level access to data without the need for an organizational account.\n- Normal remediation steps, like resetting passwords for breached accounts or requiring Multi-Factor Authentication (MFA) on accounts, are not effective against this type of attack, since these are third-party applications and are external to the organization.\n- Security analysts should review the list of trusted applications for any suspicious items.\n\n\n## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(azure.activitylogs or azure.auditlogs or o365.audit) and ( azure.activitylogs.operation_name:\"Consent to application\" or azure.auditlogs.operation_name:\"Consent to application\" or o365.audit.Operation:\"Consent to application.\" ) and event.outcome:(Success or success)", + "query": "event.dataset:(azure.activitylogs or azure.auditlogs or o365.audit) and \n (\n azure.activitylogs.operation_name:\"Consent to application\" or\n azure.auditlogs.operation_name:\"Consent to application\" or\n o365.audit.Operation:\"Consent to application.\"\n ) and\n event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/detect-and-remediate-illicit-consent-grants?view=o365-worldwide" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_console_login_root.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_console_login_root.json index 7d199f72a22bd..346f679b6c570 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_console_login_root.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_console_login_root.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS Management Console Root Login", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:signin.amazonaws.com and event.action:ConsoleLogin and aws.cloudtrail.user_identity.type:Root and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:signin.amazonaws.com and event.action:ConsoleLogin and aws.cloudtrail.user_identity.type:Root and event.outcome:success\n", "references": [ "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_external_guest_user_invite.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_external_guest_user_invite.json index fa04b1f724ef7..70c3ea5de73f9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_external_guest_user_invite.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_external_guest_user_invite.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Azure External Guest User Invitation", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.auditlogs and azure.auditlogs.operation_name:\"Invite external user\" and azure.auditlogs.properties.target_resources.*.display_name:guest and event.outcome:(Success or success)", + "query": "event.dataset:azure.auditlogs and azure.auditlogs.operation_name:\"Invite external user\" and azure.auditlogs.properties.target_resources.*.display_name:guest and event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/governance/policy/samples/cis-azure-1-1-0" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_gcp_iam_custom_role_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_gcp_iam_custom_role_creation.json index a823f162d405a..7cd94103c6395 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_gcp_iam_custom_role_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_gcp_iam_custom_role_creation.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP IAM Custom Role Creation", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.iam.admin.v*.CreateRole and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.iam.admin.v*.CreateRole and event.outcome:success\n", "references": [ "https://cloud.google.com/iam/docs/understanding-custom-roles" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_failures.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_failures.json index 92b9bf7dc8090..18a201e7638ef 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_failures.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_failures.json @@ -9,7 +9,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Auditd Max Failed Login Attempts", - "query": "event.module:auditd and event.action:\"failed-log-in-too-many-times-to\"", + "query": "event.module:auditd and event.action:\"failed-log-in-too-many-times-to\"\n", "references": [ "https://github.com/linux-pam/linux-pam/blob/0adbaeb273da1d45213134aa271e95987103281c/modules/pam_faillock/pam_faillock.c#L574" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_location.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_location.json index f762779103ee1..3224836eb927a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_location.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_location.json @@ -9,7 +9,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Auditd Login from Forbidden Location", - "query": "event.module:auditd and event.action:\"attempted-log-in-from-unusual-place-to\"", + "query": "event.module:auditd and event.action:\"attempted-log-in-from-unusual-place-to\"\n", "references": [ "https://github.com/linux-pam/linux-pam/blob/aac5a8fdc4aa3f7e56335a6343774cc1b63b408d/modules/pam_access/pam_access.c#L412" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_sessions.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_sessions.json index 09c389033ca07..b7a51feb122a1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_sessions.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_sessions.json @@ -9,7 +9,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Auditd Max Login Sessions", - "query": "event.module:auditd and event.action:\"opened-too-many-sessions-to\"", + "query": "event.module:auditd and event.action:\"opened-too-many-sessions-to\"\n", "references": [ "https://github.com/linux-pam/linux-pam/blob/70c32cc6fca51338f92afa58eb75b1107a5c2430/modules/pam_limits/pam_limits.c#L1007" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_time.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_time.json index 9eacbca79708a..f5ab15fb442f2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_time.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_login_time.json @@ -9,7 +9,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Auditd Login Attempt at Forbidden Time", - "query": "event.module:auditd and event.action:\"attempted-log-in-during-unusual-hour-to\"", + "query": "event.module:auditd and event.action:\"attempted-log-in-during-unusual-hour-to\"\n", "references": [ "https://github.com/linux-pam/linux-pam/blob/aac5a8fdc4aa3f7e56335a6343774cc1b63b408d/modules/pam_time/pam_time.c#L666" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_policy_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_policy_deletion.json index 46c771e5b5ede..d98c6d1fb2260 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_policy_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_policy_deletion.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 Exchange Anti-Phish Policy Deletion", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Remove-AntiPhishPolicy\" and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Remove-AntiPhishPolicy\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/remove-antiphishpolicy?view=exchange-ps", "https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/set-up-anti-phishing-policies?view=o365-worldwide" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_rule_mod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_rule_mod.json index 471a010338085..554f5f80be246 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_rule_mod.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_anti_phish_rule_mod.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 Exchange Anti-Phish Rule Modification", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:(\"Remove-AntiPhishRule\" or \"Disable-AntiPhishRule\") and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:(\"Remove-AntiPhishRule\" or \"Disable-AntiPhishRule\") and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/remove-antiphishrule?view=exchange-ps", "https://docs.microsoft.com/en-us/powershell/module/exchange/disable-antiphishrule?view=exchange-ps" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_safelinks_disabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_safelinks_disabled.json index d348d790f0c4e..0f936a91023f2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_safelinks_disabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_microsoft_365_exchange_safelinks_disabled.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 Exchange Safe Link Policy Disabled", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Disable-SafeLinksRule\" and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Disable-SafeLinksRule\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/disable-safelinksrule?view=exchange-ps", "https://docs.microsoft.com/en-us/microsoft-365/security/office-365-security/atp-safe-links?view=o365-worldwide" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_password_recovery.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_password_recovery.json index fcbbcec5f06ac..9d0315ea692fb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_password_recovery.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_password_recovery.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS IAM Password Recovery Requested", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:signin.amazonaws.com and event.action:PasswordRecoveryRequested and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:signin.amazonaws.com and event.action:PasswordRecoveryRequested and event.outcome:success\n", "references": [ "https://www.cadosecurity.com/2020/06/11/an-ongoing-aws-phishing-campaign/" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_from_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_from_the_internet.json index 81c011cda898a..8e7f8ea6a842b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_from_the_internet.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_from_the_internet.json @@ -12,7 +12,10 @@ "language": "kuery", "license": "Elastic License v2", "name": "RPC (Remote Procedure Call) from the Internet", - "query": "event.category:(network or network_traffic) and network.transport:tcp and (destination.port:135 or event.dataset:zeek.dce_rpc) and not source.ip:( 10.0.0.0/8 or 127.0.0.0/8 or 169.254.0.0/16 or 172.16.0.0/12 or 192.168.0.0/16 or 224.0.0.0/4 or \"::1\" or \"FE80::/10\" or \"FF00::/8\" ) and destination.ip:( 10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16 )", + "query": "event.category:(network or network_traffic) and network.transport:tcp and (destination.port:135 or event.dataset:zeek.dce_rpc) and\n not source.ip:(\n 10.0.0.0/8 or\n 127.0.0.0/8 or\n 169.254.0.0/16 or\n 172.16.0.0/12 or\n 192.0.0.0/24 or\n 192.0.0.0/29 or\n 192.0.0.8/32 or\n 192.0.0.9/32 or\n 192.0.0.10/32 or\n 192.0.0.170/32 or\n 192.0.0.171/32 or\n 192.0.2.0/24 or\n 192.31.196.0/24 or\n 192.52.193.0/24 or\n 192.168.0.0/16 or\n 192.88.99.0/24 or\n 224.0.0.0/4 or\n 100.64.0.0/10 or\n 192.175.48.0/24 or\n 198.18.0.0/15 or\n 198.51.100.0/24 or\n 203.0.113.0/24 or\n 240.0.0.0/4 or\n \"::1\" or\n \"FE80::/10\" or\n \"FF00::/8\"\n ) and\n destination.ip:(\n 10.0.0.0/8 or\n 172.16.0.0/12 or\n 192.168.0.0/16\n )\n", + "references": [ + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], "risk_score": 73, "rule_id": "143cb236-0956-4f42-a706-814bcaa0cf5a", "severity": "high", @@ -42,5 +45,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 8 + "version": 9 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_to_the_internet.json index 7d1a59886164a..5892bca71d5c9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_to_the_internet.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_rpc_remote_procedure_call_to_the_internet.json @@ -12,7 +12,10 @@ "language": "kuery", "license": "Elastic License v2", "name": "RPC (Remote Procedure Call) to the Internet", - "query": "event.category:(network or network_traffic) and network.transport:tcp and (destination.port:135 or event.dataset:zeek.dce_rpc) and source.ip:( 10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16 ) and not destination.ip:( 10.0.0.0/8 or 127.0.0.0/8 or 169.254.0.0/16 or 172.16.0.0/12 or 192.168.0.0/16 or 224.0.0.0/4 or \"::1\" or \"FE80::/10\" or \"FF00::/8\" )", + "query": "event.category:(network or network_traffic) and network.transport:tcp and (destination.port:135 or event.dataset:zeek.dce_rpc) and\n source.ip:(\n 10.0.0.0/8 or\n 172.16.0.0/12 or\n 192.168.0.0/16\n ) and\n not destination.ip:(\n 10.0.0.0/8 or\n 127.0.0.0/8 or\n 169.254.0.0/16 or\n 172.16.0.0/12 or\n 192.0.0.0/24 or\n 192.0.0.0/29 or\n 192.0.0.8/32 or\n 192.0.0.9/32 or\n 192.0.0.10/32 or\n 192.0.0.170/32 or\n 192.0.0.171/32 or\n 192.0.2.0/24 or\n 192.31.196.0/24 or\n 192.52.193.0/24 or\n 192.168.0.0/16 or\n 192.88.99.0/24 or\n 224.0.0.0/4 or\n 100.64.0.0/10 or\n 192.175.48.0/24 or\n 198.18.0.0/15 or\n 198.51.100.0/24 or\n 203.0.113.0/24 or\n 240.0.0.0/4 or\n \"::1\" or\n \"FE80::/10\" or\n \"FF00::/8\"\n )\n", + "references": [ + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], "risk_score": 73, "rule_id": "32923416-763a-4531-bb35-f33b9232ecdb", "severity": "high", @@ -42,5 +45,5 @@ ], "timestamp_override": "event.ingested", "type": "query", - "version": 8 + "version": 9 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_smb_windows_file_sharing_activity_to_the_internet.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_smb_windows_file_sharing_activity_to_the_internet.json index 60f488fe9d05f..b119dc0a4f211 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_smb_windows_file_sharing_activity_to_the_internet.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_smb_windows_file_sharing_activity_to_the_internet.json @@ -12,7 +12,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "SMB (Windows File Sharing) Activity to the Internet", - "query": "event.category:(network or network_traffic) and network.transport:tcp and (destination.port:(139 or 445) or event.dataset:zeek.smb) and source.ip:( 10.0.0.0/8 or 172.16.0.0/12 or 192.168.0.0/16 ) and not destination.ip:( 10.0.0.0/8 or 127.0.0.0/8 or 169.254.0.0/16 or 172.16.0.0/12 or 192.168.0.0/16 or 224.0.0.0/4 or \"::1\" or \"FE80::/10\" or \"FF00::/8\" )", + "query": "event.category:(network or network_traffic) and network.transport:tcp and (destination.port:(139 or 445) or event.dataset:zeek.smb) and\n source.ip:(\n 10.0.0.0/8 or\n 172.16.0.0/12 or\n 192.168.0.0/16\n ) and\n not destination.ip:(\n 10.0.0.0/8 or\n 127.0.0.0/8 or\n 169.254.0.0/16 or\n 172.16.0.0/12 or\n 192.168.0.0/16 or\n 224.0.0.0/4 or\n \"::1\" or\n \"FE80::/10\" or\n \"FF00::/8\"\n )\n", "risk_score": 73, "rule_id": "c82b2bd8-d701-420c-ba43-f11a155b681a", "severity": "high", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_suspicious_activity_reported_by_okta_user.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_suspicious_activity_reported_by_okta_user.json index 03fb7e44b200d..abcc8d06444e0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_suspicious_activity_reported_by_okta_user.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_suspicious_activity_reported_by_okta_user.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Suspicious Activity Reported by Okta User", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:user.account.report_suspicious_activity_by_enduser", + "query": "event.dataset:okta.system and event.action:user.account.report_suspicious_activity_by_enduser\n", "references": [ "https://developer.okta.com/docs/reference/api/system-log/", "https://developer.okta.com/docs/reference/api/event-types/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_unsecure_elasticsearch_node.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_unsecure_elasticsearch_node.json index 41ab4386c6817..965d4a7f62369 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_unsecure_elasticsearch_node.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_unsecure_elasticsearch_node.json @@ -13,7 +13,7 @@ "license": "Elastic License v2", "name": "Inbound Connection to an Unsecure Elasticsearch Node", "note": "## Config\n\nThis rule requires the addition of port `9200` and `send_all_headers` to the `HTTP` protocol configuration in `packetbeat.yml`. See the References section for additional configuration documentation.", - "query": "event.category:network_traffic AND network.protocol:http AND status:OK AND destination.port:9200 AND network.direction:inbound AND NOT http.response.headers.content-type:\"image/x-icon\" AND NOT _exists_:http.request.headers.authorization", + "query": "event.category:network_traffic AND network.protocol:http AND status:OK AND destination.port:9200 AND network.direction:inbound AND NOT http.response.headers.content-type:\"image/x-icon\" AND NOT _exists_:http.request.headers.authorization\n", "references": [ "https://www.elastic.co/guide/en/elasticsearch/reference/current/configuring-security.html", "https://www.elastic.co/guide/en/beats/packetbeat/current/packetbeat-http-options.html#_send_all_headers" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_via_system_manager.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_via_system_manager.json index 73370f48253a6..70fadcc29f648 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_via_system_manager.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_via_system_manager.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS Execution via System Manager", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:ssm.amazonaws.com and event.action:SendCommand and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:ssm.amazonaws.com and event.action:SendCommand and event.outcome:success\n", "references": [ "https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-plugins.html" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_zoom_meeting_with_no_passcode.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_zoom_meeting_with_no_passcode.json index 9ceb2d7143713..8c3ae88116a79 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_zoom_meeting_with_no_passcode.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/initial_access_zoom_meeting_with_no_passcode.json @@ -10,7 +10,7 @@ "license": "Elastic License v2", "name": "Zoom Meeting with no Passcode", "note": "## Config\n\nThe Zoom Filebeat module or similarly structured data is required to be compatible with this rule.", - "query": "event.type:creation and event.module:zoom and event.dataset:zoom.webhook and event.action:meeting.created and not zoom.meeting.password:*", + "query": "event.type:creation and event.module:zoom and event.dataset:zoom.webhook and\n event.action:meeting.created and not zoom.meeting.password:*\n", "references": [ "https://blog.zoom.us/a-message-to-our-users/", "https://www.fbi.gov/contact-us/field-offices/boston/news/press-releases/fbi-warns-of-teleconferencing-and-online-classroom-hijacking-during-covid-19-pandemic" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_credential_access_kerberos_bifrostconsole.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_credential_access_kerberos_bifrostconsole.json index e8f28ffd5e4c6..82fa9d8d72a92 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_credential_access_kerberos_bifrostconsole.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_credential_access_kerberos_bifrostconsole.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential Kerberos Attack via Bifrost", - "query": "event.category:process and event.type:start and process.args:(\"-action\" and (\"-kerberoast\" or askhash or asktgs or asktgt or s4u or (\"-ticket\" and ptt) or (dump and (tickets or keytab))))", + "query": "event.category:process and event.type:start and \n process.args:(\"-action\" and (\"-kerberoast\" or askhash or asktgs or asktgt or s4u or (\"-ticket\" and ptt) or (dump and (tickets or keytab))))\n", "references": [ "https://github.com/its-a-feature/bifrost" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_dns_server_overflow.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_dns_server_overflow.json index 51bf90ff1eaf0..b34badc7c8611 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_dns_server_overflow.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_dns_server_overflow.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Abnormally Large DNS Response", "note": "## Triage and analysis\n\n### Investigating Large DNS Responses\nDetection alerts from this rule indicate an attempt was made to exploit CVE-2020-1350 (SigRed) through the use of large DNS responses on a Windows DNS server. Here are some possible avenues of investigation:\n- Investigate any corresponding Intrusion Detection Signatures (IDS) alerts that can validate this detection alert.\n- Examine the `dns.question_type` network fieldset with a protocol analyzer, such as Zeek, Packetbeat, or Suricata, for `SIG` or `RRSIG` data.\n- Validate the patch level and OS of the targeted DNS server to validate the observed activity was not large-scale Internet vulnerability scanning.\n- Validate that the source of the network activity was not from an authorized vulnerability scan or compromise assessment.", - "query": "event.category:(network or network_traffic) and destination.port:53 and (event.dataset:zeek.dns or type:dns or event.type:connection) and network.bytes > 60000", + "query": "event.category:(network or network_traffic) and destination.port:53 and\n (event.dataset:zeek.dns or type:dns or event.type:connection) and network.bytes > 60000\n", "references": [ "https://research.checkpoint.com/2020/resolving-your-way-into-domain-admin-exploiting-a-17-year-old-bug-in-windows-dns-servers/", "https://msrc-blog.microsoft.com/2020/07/14/july-2020-security-update-cve-2020-1350-vulnerability-in-windows-domain-name-system-dns-server/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_remote_ssh_login_enabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_remote_ssh_login_enabled.json index 37fe1a6a99791..dc4d84d497097 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_remote_ssh_login_enabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_remote_ssh_login_enabled.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Remote SSH Login Enabled via systemsetup Command", - "query": "event.category:process and event.type:(start or process_started) and process.name:systemsetup and process.args:(\"-setremotelogin\" and on)", + "query": "event.category:process and event.type:(start or process_started) and\n process.name:systemsetup and\n process.args:(\"-setremotelogin\" and on)\n", "references": [ "https://documents.trendmicro.com/assets/pdf/XCSSET_Technical_Brief.pdf", "https://ss64.com/osx/systemsetup.html", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_external.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_external.json index 1c31fa440238a..73dca7c566421 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_external.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_external.json @@ -14,7 +14,10 @@ "language": "eql", "license": "Elastic License v2", "name": "Connection to External Network via Telnet", - "query": "sequence by process.entity_id\n [process where process.name == \"telnet\" and event.type == \"start\"]\n [network where process.name == \"telnet\" and\n not cidrmatch(destination.ip, \"127.0.0.0/8\", \"10.0.0.0/8\", \"172.16.0.0/12\",\n \"192.168.0.0/16\", \"FE80::/10\", \"::1/128\")]\n", + "query": "sequence by process.entity_id\n [process where process.name == \"telnet\" and event.type == \"start\"]\n [network where process.name == \"telnet\" and\n not cidrmatch(destination.ip, \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\",\n \"192.0.0.0/29\", \"192.0.0.8/32\", \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\",\n \"192.0.0.171/32\", \"192.0.2.0/24\", \"192.31.196.0/24\", \"192.52.193.0/24\",\n \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\", \"100.64.0.0/10\", \"192.175.48.0/24\",\n \"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\",\n \"FE80::/10\", \"FF00::/8\")]\n", + "references": [ + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], "risk_score": 47, "rule_id": "e19e64ee-130e-4c07-961f-8a339f0b8362", "severity": "medium", @@ -43,5 +46,5 @@ } ], "type": "eql", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_internal.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_internal.json index 9b4a031aa1609..31ca15c44a8bb 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_internal.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/lateral_movement_telnet_network_activity_internal.json @@ -14,7 +14,10 @@ "language": "eql", "license": "Elastic License v2", "name": "Connection to Internal Network via Telnet", - "query": "sequence by process.entity_id\n [process where process.name == \"telnet\" and event.type == \"start\"]\n [network where process.name == \"telnet\" and\n cidrmatch(destination.ip, \"10.0.0.0/8\", \"172.16.0.0/12\", \"192.168.0.0/16\", \"FE80::/10\") and\n not cidrmatch(destination.ip, \"127.0.0.0/8\", \"::1/128\")]\n", + "query": "sequence by process.entity_id\n [process where process.name == \"telnet\" and event.type == \"start\"]\n [network where process.name == \"telnet\" and\n cidrmatch(destination.ip, \"10.0.0.0/8\", \"127.0.0.0/8\", \"169.254.0.0/16\", \"172.16.0.0/12\", \"192.0.0.0/24\",\n \"192.0.0.0/29\", \"192.0.0.8/32\", \"192.0.0.9/32\", \"192.0.0.10/32\", \"192.0.0.170/32\",\n \"192.0.0.171/32\", \"192.0.2.0/24\", \"192.31.196.0/24\", \"192.52.193.0/24\",\n \"192.168.0.0/16\", \"192.88.99.0/24\", \"224.0.0.0/4\", \"100.64.0.0/10\", \"192.175.48.0/24\",\n \"198.18.0.0/15\", \"198.51.100.0/24\", \"203.0.113.0/24\", \"240.0.0.0/4\", \"::1\",\n \"FE80::/10\", \"FF00::/8\")]\n", + "references": [ + "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" + ], "risk_score": 47, "rule_id": "1b21abcc-4d9f-4b08-a7f5-316f5f94b973", "severity": "medium", @@ -43,5 +46,5 @@ } ], "type": "eql", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json index a706d2a117e7b..3a91b205e9da3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_hping_activity.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Hping Process Activity", - "query": "event.category:process and event.type:(start or process_started) and process.name:(hping or hping2 or hping3)", + "query": "event.category:process and event.type:(start or process_started) and process.name:(hping or hping2 or hping3)\n", "references": [ "https://en.wikipedia.org/wiki/Hping" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json index cbd8c14052fee..d092c64098648 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_iodine_activity.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential DNS Tunneling via Iodine", - "query": "event.category:process and event.type:(start or process_started) and process.name:(iodine or iodined)", + "query": "event.category:process and event.type:(start or process_started) and process.name:(iodine or iodined)\n", "references": [ "https://code.kryo.se/iodine/" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json index 94c37610abf2e..c9898b7414c09 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_nping_activity.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Nping Process Activity", - "query": "event.category:process and event.type:(start or process_started) and process.name:nping", + "query": "event.category:process and event.type:(start or process_started) and process.name:nping\n", "references": [ "https://en.wikipedia.org/wiki/Nmap" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json index 7b3c8af056f18..8b71c053fc6d6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_process_started_in_temp_directory.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Unusual Process Execution - Temp", - "query": "event.category:process and event.type:(start or process_started) and process.working_directory:/tmp", + "query": "event.category:process and event.type:(start or process_started) and process.working_directory:/tmp\n", "risk_score": 47, "rule_id": "df959768-b0c9-4d45-988c-5606a2be8e5a", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json index d14db4869a8f7..210a71ced9222 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/linux_strace_activity.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Strace Process Activity", - "query": "event.category:process and event.type:(start or process_started) and process.name:strace", + "query": "event.category:process and event.type:(start or process_started) and process.name:strace\n", "references": [ "https://en.wikipedia.org/wiki/Strace" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/mfa_disabled_for_google_workspace_organization.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/mfa_disabled_for_google_workspace_organization.json index b393fa13db8c7..db8ea7369d456 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/mfa_disabled_for_google_workspace_organization.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/mfa_disabled_for_google_workspace_organization.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "MFA Disabled for Google Workspace Organization", "note": "## Config\n\nThe Google Workspace Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n\n### Important Information Regarding Google Workspace Event Lag Times\n- As per Google's documentation, Google Workspace administrators may observe lag times ranging from minutes up to 3 days between the time of an event's occurrence and the event being visible in the Google Workspace admin/audit logs.\n- This rule is configured to run every 10 minutes with a lookback time of 130 minutes.\n- To reduce the risk of false negatives, consider reducing the interval that the Google Workspace (formerly G Suite) Filebeat module polls Google's reporting API for new events.\n- By default, `var.interval` is set to 2 hours (2h). Consider changing this interval to a lower value, such as 10 minutes (10m).\n- See the following references for further information.\n - https://support.google.com/a/answer/7061566\n - https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-gsuite.html", - "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:(ENFORCE_STRONG_AUTHENTICATION or ALLOW_STRONG_AUTHENTICATION) and gsuite.admin.new_value:false", + "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:(ENFORCE_STRONG_AUTHENTICATION or ALLOW_STRONG_AUTHENTICATION) and gsuite.admin.new_value:false\n", "risk_score": 47, "rule_id": "e555105c-ba6d-481f-82bb-9b633e7b4827", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_exchange_dkim_signing_config_disabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_exchange_dkim_signing_config_disabled.json index 280d40537e448..6933a81a22944 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_exchange_dkim_signing_config_disabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_exchange_dkim_signing_config_disabled.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 Exchange DKIM Signing Configuration Disabled", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Set-DkimSigningConfig\" and o365.audit.Parameters.Enabled:False and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"Set-DkimSigningConfig\" and o365.audit.Parameters.Enabled:False and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/set-dkimsigningconfig?view=exchange-ps" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_teams_custom_app_interaction_allowed.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_teams_custom_app_interaction_allowed.json index cb87e9f7cb257..add3495d03271 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_teams_custom_app_interaction_allowed.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/microsoft_365_teams_custom_app_interaction_allowed.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 Teams Custom Application Interaction Allowed", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:MicrosoftTeams and event.category:web and event.action:TeamsTenantSettingChanged and o365.audit.Name:\"Allow sideloading and interaction of custom apps\" and o365.audit.NewValue:True and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:MicrosoftTeams and\nevent.category:web and event.action:TeamsTenantSettingChanged and\no365.audit.Name:\"Allow sideloading and interaction of custom apps\" and\no365.audit.NewValue:True and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/deploy-and-publish/apps-upload" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_high_count_network_denies.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_high_count_network_denies.json index 7856d13b8d66f..f0d999476bb42 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_high_count_network_denies.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_high_count_network_denies.json @@ -9,8 +9,8 @@ ], "from": "now-30m", "interval": "15m", - "license": "Elastic License", - "machine_learning_job_id": "high-count-network-denies", + "license": "Elastic License v2", + "machine_learning_job_id": "high_count_network_denies", "name": "Spike in Firewall Denies", "references": [ "https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html" @@ -25,5 +25,5 @@ "ML" ], "type": "machine_learning", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_high_count_network_events.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_high_count_network_events.json index 14aec268cc13b..39ded30776bad 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_high_count_network_events.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_high_count_network_events.json @@ -9,8 +9,8 @@ ], "from": "now-30m", "interval": "15m", - "license": "Elastic License", - "machine_learning_job_id": "high-count-network-events", + "license": "Elastic License v2", + "machine_learning_job_id": "high_count_network_events", "name": "Spike in Network Traffic", "references": [ "https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html" @@ -25,5 +25,5 @@ "ML" ], "type": "machine_learning", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_process.json index 1c886d0457afc..a2638f60d7495 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_process.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_process.json @@ -10,7 +10,10 @@ "from": "now-45m", "interval": "15m", "license": "Elastic License v2", - "machine_learning_job_id": "linux_rare_metadata_process", + "machine_learning_job_id": [ + "linux_rare_metadata_process", + "v2_linux_rare_metadata_process" + ], "name": "Unusual Linux Process Calling the Metadata Service", "risk_score": 21, "rule_id": "9d302377-d226-4e12-b54c-1906b5aec4f6", @@ -23,5 +26,5 @@ "ML" ], "type": "machine_learning", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_user.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_user.json index 984060951b3c5..c176bf0d7ad68 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_user.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_metadata_user.json @@ -10,7 +10,10 @@ "from": "now-45m", "interval": "15m", "license": "Elastic License v2", - "machine_learning_job_id": "linux_rare_metadata_user", + "machine_learning_job_id": [ + "linux_rare_metadata_user", + "v2_linux_rare_metadata_user" + ], "name": "Unusual Linux User Calling the Metadata Service", "risk_score": 21, "rule_id": "1faec04b-d902-4f89-8aff-92cd9043c16f", @@ -23,5 +26,5 @@ "ML" ], "type": "machine_learning", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_port_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_port_activity.json index c56235774c077..eb6a960702ac7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_port_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_network_port_activity.json @@ -10,7 +10,10 @@ "from": "now-45m", "interval": "15m", "license": "Elastic License v2", - "machine_learning_job_id": "linux_anomalous_network_port_activity_ecs", + "machine_learning_job_id": [ + "linux_anomalous_network_port_activity_ecs", + "v2_linux_anomalous_network_port_activity_ecs" + ], "name": "Unusual Linux Network Port Activity", "references": [ "https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html" @@ -26,5 +29,5 @@ "ML" ], "type": "machine_learning", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_process_all_hosts.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_process_all_hosts.json index 9243389de0d97..bab02f0a6aa24 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_process_all_hosts.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_process_all_hosts.json @@ -10,7 +10,10 @@ "from": "now-45m", "interval": "15m", "license": "Elastic License v2", - "machine_learning_job_id": "linux_anomalous_process_all_hosts_ecs", + "machine_learning_job_id": [ + "linux_anomalous_process_all_hosts_ecs", + "v2_linux_anomalous_process_all_hosts_ecs" + ], "name": "Anomalous Process For a Linux Population", "note": "## Triage and analysis\n\n### Investigating an Unusual Linux Process\nDetection alerts from this rule indicate the presence of a Linux process that is rare and unusual for all of the monitored Linux hosts for which Auditbeat data is available. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.", "references": [ @@ -27,5 +30,5 @@ "ML" ], "type": "machine_learning", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_user_name.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_user_name.json index e77247dc0e931..4eb10707e0eb2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_user_name.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_linux_anomalous_user_name.json @@ -10,7 +10,10 @@ "from": "now-45m", "interval": "15m", "license": "Elastic License v2", - "machine_learning_job_id": "linux_anomalous_user_name_ecs", + "machine_learning_job_id": [ + "linux_anomalous_user_name_ecs", + "v2_linux_anomalous_user_name_ecs" + ], "name": "Unusual Linux Username", "note": "## Triage and analysis\n\n### Investigating an Unusual Linux User\nDetection alerts from this rule indicate activity for a Linux user name that is rare and unusual. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host? Could this be related to troubleshooting or debugging activity by a developer or site reliability engineer?\n- Examine the history of user activity. If this user manifested only very recently, it might be a service account for a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks that the user is performing.", "references": [ @@ -27,5 +30,5 @@ "ML" ], "type": "machine_learning", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_destination_country.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_destination_country.json index 571c7e0d0d32c..8c8b7ffbd12ff 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_destination_country.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_destination_country.json @@ -9,8 +9,8 @@ ], "from": "now-30m", "interval": "15m", - "license": "Elastic License", - "machine_learning_job_id": "rare-destination-country", + "license": "Elastic License v2", + "machine_learning_job_id": "rare_destination_country", "name": "Network Traffic to Rare Destination Country", "references": [ "https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html" @@ -25,5 +25,5 @@ "ML" ], "type": "machine_learning", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_linux.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_linux.json index 11f6c2605f6ad..934a5e598629b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_linux.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_linux.json @@ -10,7 +10,10 @@ "from": "now-45m", "interval": "15m", "license": "Elastic License v2", - "machine_learning_job_id": "rare_process_by_host_linux_ecs", + "machine_learning_job_id": [ + "rare_process_by_host_linux_ecs", + "v2_rare_process_by_host_linux_ecs" + ], "name": "Unusual Process For a Linux Host", "note": "## Triage and analysis\n\n### Investigating an Unusual Linux Process\nDetection alerts from this rule indicate the presence of a Linux process that is rare and unusual for the host it ran on. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.", "references": [ @@ -27,5 +30,5 @@ "ML" ], "type": "machine_learning", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_windows.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_windows.json index 72db8ff93d4d4..3373f51b69db0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_windows.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_rare_process_by_host_windows.json @@ -10,7 +10,10 @@ "from": "now-45m", "interval": "15m", "license": "Elastic License v2", - "machine_learning_job_id": "rare_process_by_host_windows_ecs", + "machine_learning_job_id": [ + "rare_process_by_host_windows_ecs", + "v2_rare_process_by_host_windows_ecs" + ], "name": "Unusual Process For a Windows Host", "note": "## Triage and analysis\n\n### Investigating an Unusual Windows Process\nDetection alerts from this rule indicate the presence of a Windows process that is rare and unusual for the host it ran on. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process metadata like the values of the Company, Description and Product fields which may indicate whether the program is associated with an expected software vendor or package.\n- Examine arguments and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools. ", "references": [ @@ -27,5 +30,5 @@ "ML" ], "type": "machine_learning", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_spike_in_traffic_to_a_country.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_spike_in_traffic_to_a_country.json index e1e571bbd1c99..1b6c71ed0b0bf 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_spike_in_traffic_to_a_country.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_spike_in_traffic_to_a_country.json @@ -9,8 +9,8 @@ ], "from": "now-30m", "interval": "15m", - "license": "Elastic License", - "machine_learning_job_id": "high-count-by-destination-country", + "license": "Elastic License v2", + "machine_learning_job_id": "high_count_by_destination_country", "name": "Spike in Network Traffic To a Country", "references": [ "https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html" @@ -25,5 +25,5 @@ "ML" ], "type": "machine_learning", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_process.json index d19897057497c..deaf07a77c7be 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_process.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_process.json @@ -10,7 +10,10 @@ "from": "now-45m", "interval": "15m", "license": "Elastic License v2", - "machine_learning_job_id": "windows_rare_metadata_process", + "machine_learning_job_id": [ + "windows_rare_metadata_process", + "v2_windows_rare_metadata_process" + ], "name": "Unusual Windows Process Calling the Metadata Service", "risk_score": 21, "rule_id": "abae61a8-c560-4dbd-acca-1e1438bff36b", @@ -23,5 +26,5 @@ "ML" ], "type": "machine_learning", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_user.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_user.json index 27f100c4e65b8..31e078b795256 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_user.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_metadata_user.json @@ -10,7 +10,10 @@ "from": "now-45m", "interval": "15m", "license": "Elastic License v2", - "machine_learning_job_id": "windows_rare_metadata_user", + "machine_learning_job_id": [ + "windows_rare_metadata_user", + "v2_windows_rare_metadata_user" + ], "name": "Unusual Windows User Calling the Metadata Service", "risk_score": 21, "rule_id": "df197323-72a8-46a9-a08e-3f5b04a4a97a", @@ -23,5 +26,5 @@ "ML" ], "type": "machine_learning", - "version": 2 + "version": 3 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_network_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_network_activity.json index 5e3d5757b160d..dbee5dd256873 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_network_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_network_activity.json @@ -10,7 +10,10 @@ "from": "now-45m", "interval": "15m", "license": "Elastic License v2", - "machine_learning_job_id": "windows_anomalous_network_activity_ecs", + "machine_learning_job_id": [ + "windows_anomalous_network_activity_ecs", + "v2_windows_anomalous_network_activity_ecs" + ], "name": "Unusual Windows Network Activity", "note": "## Triage and analysis\n\n### Investigating Unusual Network Activity\nDetection alerts from this rule indicate the presence of network activity from a Windows process for which network activity is very unusual. Here are some possible avenues of investigation:\n- Consider the IP addresses, protocol and ports. Are these used by normal but infrequent network workflows? Are they expected or unexpected?\n- If the destination IP address is remote or external, does it associate with an expected domain, organization or geography? Note: avoid interacting directly with suspected malicious IP addresses.\n- Consider the user as identified by the username field. Is this network activity part of an expected workflow for the user who ran the program?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools.", "references": [ @@ -27,5 +30,5 @@ "ML" ], "type": "machine_learning", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_path_activity.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_path_activity.json index 93a33e41e6ce9..782a80c53f9b3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_path_activity.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_path_activity.json @@ -10,7 +10,10 @@ "from": "now-45m", "interval": "15m", "license": "Elastic License v2", - "machine_learning_job_id": "windows_anomalous_path_activity_ecs", + "machine_learning_job_id": [ + "windows_anomalous_path_activity_ecs", + "v2_windows_anomalous_path_activity_ecs" + ], "name": "Unusual Windows Path Activity", "references": [ "https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html" @@ -26,5 +29,5 @@ "ML" ], "type": "machine_learning", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_all_hosts.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_all_hosts.json index b73637c1a7cdf..09acb2121fd5c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_all_hosts.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_all_hosts.json @@ -10,7 +10,10 @@ "from": "now-45m", "interval": "15m", "license": "Elastic License v2", - "machine_learning_job_id": "windows_anomalous_process_all_hosts_ecs", + "machine_learning_job_id": [ + "windows_anomalous_process_all_hosts_ecs", + "v2_windows_anomalous_process_all_hosts_ecs" + ], "name": "Anomalous Process For a Windows Population", "note": "## Triage and analysis\n\n### Investigating an Unusual Windows Process\nDetection alerts from this rule indicate the presence of a Windows process that is rare and unusual for all of the Windows hosts for which Winlogbeat data is available. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host?\n- Examine the history of execution. If this process manifested only very recently, it might be part of a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process metadata like the values of the Company, Description and Product fields which may indicate whether the program is associated with an expected software vendor or package.\n- Examine arguments and working directory. These may provide indications as to the source of the program or the nature of the tasks it is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.\n- If you have file hash values in the event data, and you suspect malware, you can optionally run a search for the file hash to see if the file is identified as malware by anti-malware tools. ", "references": [ @@ -27,5 +30,5 @@ "ML" ], "type": "machine_learning", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_creation.json index 7b3a028f1b371..cfe9e7ff1eaa3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_process_creation.json @@ -10,7 +10,10 @@ "from": "now-45m", "interval": "15m", "license": "Elastic License v2", - "machine_learning_job_id": "windows_anomalous_process_creation", + "machine_learning_job_id": [ + "windows_anomalous_process_creation", + "v2_windows_anomalous_process_creation" + ], "name": "Anomalous Windows Process Creation", "references": [ "https://www.elastic.co/guide/en/security/current/prebuilt-ml-jobs.html" @@ -26,5 +29,5 @@ "ML" ], "type": "machine_learning", - "version": 4 + "version": 5 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_user_name.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_user_name.json index d3cbc34bd1a3d..b2183c8ff66c3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_user_name.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/ml_windows_anomalous_user_name.json @@ -10,7 +10,10 @@ "from": "now-45m", "interval": "15m", "license": "Elastic License v2", - "machine_learning_job_id": "windows_anomalous_user_name_ecs", + "machine_learning_job_id": [ + "windows_anomalous_user_name_ecs", + "v2_windows_anomalous_user_name_ecs" + ], "name": "Unusual Windows Username", "note": "## Triage and analysis\n\n### Investigating an Unusual Windows User\nDetection alerts from this rule indicate activity for a Windows user name that is rare and unusual. Here are some possible avenues of investigation:\n- Consider the user as identified by the username field. Is this program part of an expected workflow for the user who ran this program on this host? Could this be related to occasional troubleshooting or support activity?\n- Examine the history of user activity. If this user manifested only very recently, it might be a service account for a new software package. If it has a consistent cadence - for example if it runs monthly or quarterly - it might be part of a monthly or quarterly business process.\n- Examine the process arguments, title and working directory. These may provide indications as to the source of the program or the nature of the tasks that the user is performing.\n- Consider the same for the parent process. If the parent process is a legitimate system utility or service, this could be related to software updates or system management. If the parent process is something user-facing like an Office application, this process could be more suspicious.", "references": [ @@ -27,5 +30,5 @@ "ML" ], "type": "machine_learning", - "version": 5 + "version": 6 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/notice.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/notice.ts index cad41391e2b42..86d95c1e021b4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/notice.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/notice.ts @@ -2,17 +2,17 @@ /* @notice * Detection Rules - * Copyright 2020 Elasticsearch B.V. + * Copyright 2021 Elasticsearch B.V. * * --- * This product bundles rules based on https://github.com/BlueTeamLabs/sentinel-attack - * which is available under a "MIT" license. The files based on this license are: + * which is available under a "MIT" license. The rules based on this license are: * - * - defense_evasion_via_filter_manager - * - discovery_process_discovery_via_tasklist_command - * - persistence_priv_escalation_via_accessibility_features - * - persistence_via_application_shimming - * - defense_evasion_execution_via_trusted_developer_utilities + * - "Potential Evasion via Filter Manager" (06dceabf-adca-48af-ac79-ffdf4c3b1e9a) + * - "Process Discovery via Tasklist" (cc16f774-59f9-462d-8b98-d27ccd4519ec) + * - "Potential Modification of Accessibility Binaries" (7405ddf1-6c8e-41ce-818f-48bea6bcaed8) + * - "Potential Application Shimming via Sdbinst" (fd4a992d-6130-4802-9ff8-829b89ae801f) + * - "Trusted Developer Application Usage" (9d110cb3-5f4b-4c9a-b9f5-53f0a1707ae1) * * MIT License * @@ -38,9 +38,9 @@ * * --- * This product bundles rules based on https://github.com/FSecureLABS/leonidas - * which is available under a "MIT" license. The files based on this license are: + * which is available under a "MIT" license. The rules based on this license are: * - * - credential_access_secretsmanager_getsecretvalue.toml + * - "AWS Access Secret in Secrets Manager" (a00681e3-9ed6-447c-ab2c-be648821c622) * * MIT License * diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_application.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_application.json index bb4cdc6ded201..2c3512fb2ad77 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_application.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_application.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Deactivate an Okta Application", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:application.lifecycle.deactivate", + "query": "event.dataset:okta.system and event.action:application.lifecycle.deactivate\n", "references": [ "https://help.okta.com/en/prod/Content/Topics/Apps/Apps_Apps.htm", "https://developer.okta.com/docs/reference/api/system-log/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_policy.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_policy.json index 54dd1f0741488..45605a297987b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_policy.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_policy.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Deactivate an Okta Policy", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:policy.lifecycle.deactivate", + "query": "event.dataset:okta.system and event.action:policy.lifecycle.deactivate\n", "references": [ "https://help.okta.com/en/prod/Content/Topics/Security/Security_Policies.htm", "https://developer.okta.com/docs/reference/api/system-log/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_policy_rule.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_policy_rule.json index 495404ac9e108..ba25dde279426 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_policy_rule.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_deactivate_okta_policy_rule.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Deactivate an Okta Policy Rule", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:policy.rule.deactivate", + "query": "event.dataset:okta.system and event.action:policy.rule.deactivate\n", "references": [ "https://help.okta.com/en/prod/Content/Topics/Security/Security_Policies.htm", "https://developer.okta.com/docs/reference/api/system-log/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_application.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_application.json index 950964c81458a..4f18d2496e874 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_application.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_application.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Delete an Okta Application", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:application.lifecycle.delete", + "query": "event.dataset:okta.system and event.action:application.lifecycle.delete\n", "references": [ "https://developer.okta.com/docs/reference/api/system-log/", "https://developer.okta.com/docs/reference/api/event-types/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_policy.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_policy.json index 43b146b1377b7..47660e2d5d73e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_policy.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_policy.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Delete an Okta Policy", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:policy.lifecycle.delete", + "query": "event.dataset:okta.system and event.action:policy.lifecycle.delete\n", "references": [ "https://help.okta.com/en/prod/Content/Topics/Security/Security_Policies.htm", "https://developer.okta.com/docs/reference/api/system-log/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_policy_rule.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_policy_rule.json index 3e32480d958ea..d865bda9c3a6f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_policy_rule.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_delete_okta_policy_rule.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Delete an Okta Policy Rule", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:policy.rule.delete", + "query": "event.dataset:okta.system and event.action:policy.rule.delete\n", "references": [ "https://help.okta.com/en/prod/Content/Topics/Security/Security_Policies.htm", "https://developer.okta.com/docs/reference/api/system-log/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_application.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_application.json index 47c0c836348d6..3c0524749eed9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_application.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_application.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Modify an Okta Application", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:application.lifecycle.update", + "query": "event.dataset:okta.system and event.action:application.lifecycle.update\n", "references": [ "https://help.okta.com/en/prod/Content/Topics/Apps/Apps_Apps.htm", "https://developer.okta.com/docs/reference/api/system-log/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_network_zone.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_network_zone.json index 05e48c9175daf..de94a52a4caa4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_network_zone.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_network_zone.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Modify an Okta Network Zone", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:(zone.update or network_zone.rule.disabled or zone.remove_blacklist)", + "query": "event.dataset:okta.system and event.action:(zone.update or network_zone.rule.disabled or zone.remove_blacklist)\n", "references": [ "https://help.okta.com/en/prod/Content/Topics/Security/network/network-zones.htm", "https://developer.okta.com/docs/reference/api/system-log/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_policy.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_policy.json index 78451913b110a..768d69341e71a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_policy.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_policy.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Modify an Okta Policy", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:policy.lifecycle.update", + "query": "event.dataset:okta.system and event.action:policy.lifecycle.update\n", "references": [ "https://developer.okta.com/docs/reference/api/system-log/", "https://developer.okta.com/docs/reference/api/event-types/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_policy_rule.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_policy_rule.json index 3d89183e4a921..cae49f5789b29 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_policy_rule.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_okta_policy_rule.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Modify an Okta Policy Rule", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:policy.rule.update", + "query": "event.dataset:okta.system and event.action:policy.rule.update\n", "references": [ "https://help.okta.com/en/prod/Content/Topics/Security/Security_Policies.htm", "https://developer.okta.com/docs/reference/api/system-log/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_or_delete_application_sign_on_policy.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_or_delete_application_sign_on_policy.json index ce68423ffa4a4..20e52ad1aca7b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_or_delete_application_sign_on_policy.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_attempt_to_modify_or_delete_application_sign_on_policy.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Modification or Removal of an Okta Application Sign-On Policy", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:(application.policy.sign_on.update or application.policy.sign_on.rule.delete)", + "query": "event.dataset:okta.system and event.action:(application.policy.sign_on.update or application.policy.sign_on.rule.delete)\n", "references": [ "https://help.okta.com/en/prod/Content/Topics/Security/App_Based_Signon.htm", "https://developer.okta.com/docs/reference/api/system-log/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_threat_detected_by_okta_threatinsight.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_threat_detected_by_okta_threatinsight.json index 51be6cc2aba45..c2225b53e30b6 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_threat_detected_by_okta_threatinsight.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/okta_threat_detected_by_okta_threatinsight.json @@ -11,7 +11,7 @@ "license": "Elastic License v2", "name": "Threat Detected by Okta ThreatInsight", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:security.threat.detected", + "query": "event.dataset:okta.system and event.action:security.threat.detected\n", "references": [ "https://developer.okta.com/docs/reference/api/system-log/", "https://developer.okta.com/docs/reference/api/event-types/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_account_creation_hide_at_logon.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_account_creation_hide_at_logon.json index faf309fac1365..dc8a5ba10fa00 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_account_creation_hide_at_logon.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_account_creation_hide_at_logon.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential Hidden Local User Account Creation", - "query": "event.category:process and event.type:(start or process_started) and process.name:dscl and process.args:(IsHidden and create and (true or 1 or yes))", + "query": "event.category:process and event.type:(start or process_started) and\n process.name:dscl and process.args:(IsHidden and create and (true or 1 or yes))\n", "references": [ "https://support.apple.com/en-us/HT203998" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_administrator_privileges_assigned_to_okta_group.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_administrator_privileges_assigned_to_okta_group.json index 2284e08ba0caa..071fb643083a1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_administrator_privileges_assigned_to_okta_group.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_administrator_privileges_assigned_to_okta_group.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Administrator Privileges Assigned to an Okta Group", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:group.privilege.grant", + "query": "event.dataset:okta.system and event.action:group.privilege.grant\n", "references": [ "https://help.okta.com/en/prod/Content/Topics/Security/administrators-admin-comparison.htm", "https://developer.okta.com/docs/reference/api/system-log/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_administrator_role_assigned_to_okta_user.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_administrator_role_assigned_to_okta_user.json index 8aa425e4faac6..eccd892913023 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_administrator_role_assigned_to_okta_user.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_administrator_role_assigned_to_okta_user.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Administrator Role Assigned to an Okta User", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:user.account.privilege.grant", + "query": "event.dataset:okta.system and event.action:user.account.privilege.grant\n", "references": [ "https://help.okta.com/en/prod/Content/Topics/Security/administrators-admin-comparison.htm", "https://developer.okta.com/docs/reference/api/system-log/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_create_okta_api_token.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_create_okta_api_token.json index df234db46fed2..02cc638a7ce0d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_create_okta_api_token.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_create_okta_api_token.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Create Okta API Token", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:system.api_token.create", + "query": "event.dataset:okta.system and event.action:system.api_token.create\n", "references": [ "https://developer.okta.com/docs/reference/api/system-log/", "https://developer.okta.com/docs/reference/api/event-types/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_deactivate_mfa_for_okta_user_account.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_deactivate_mfa_for_okta_user_account.json index df70b91b8c8a0..29d604a2953ba 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_deactivate_mfa_for_okta_user_account.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_deactivate_mfa_for_okta_user_account.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Deactivate MFA for an Okta User Account", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:user.mfa.factor.deactivate", + "query": "event.dataset:okta.system and event.action:user.mfa.factor.deactivate\n", "references": [ "https://developer.okta.com/docs/reference/api/system-log/", "https://developer.okta.com/docs/reference/api/event-types/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_reset_mfa_factors_for_okta_user_account.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_reset_mfa_factors_for_okta_user_account.json index a9bbbca91e2b7..2a2f5acfcc114 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_reset_mfa_factors_for_okta_user_account.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_attempt_to_reset_mfa_factors_for_okta_user_account.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Attempt to Reset MFA Factors for an Okta User Account", "note": "## Config\n\nThe Okta Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:okta.system and event.action:user.mfa.factor.reset_all", + "query": "event.dataset:okta.system and event.action:user.mfa.factor.reset_all\n", "references": [ "https://developer.okta.com/docs/reference/api/system-log/", "https://developer.okta.com/docs/reference/api/event-types/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_account_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_account_created.json index 5ec70f2970d28..bdae2f42bd04e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_account_created.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_account_created.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "name": "Azure Automation Account Created", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/WRITE\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name:\"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/WRITE\" and event.outcome:(Success or success)\n", "references": [ "https://powerzure.readthedocs.io/en/latest/Functions/operational.html#create-backdoor", "https://github.com/hausec/PowerZure", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_runbook_created_or_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_runbook_created_or_modified.json index f7ef529895222..0c6a82d37701b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_runbook_created_or_modified.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_runbook_created_or_modified.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "name": "Azure Automation Runbook Created or Modified", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name: ( \"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/DRAFT/WRITE\" or \"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/WRITE\" or \"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/PUBLISH/ACTION\" ) and event.outcome:(Success or success)", + "query": "event.dataset:azure.activitylogs and\n azure.activitylogs.operation_name:\n (\n \"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/DRAFT/WRITE\" or\n \"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/WRITE\" or\n \"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/PUBLISH/ACTION\"\n ) and\n event.outcome:(Success or success)\n", "references": [ "https://powerzure.readthedocs.io/en/latest/Functions/operational.html#create-backdoor", "https://github.com/hausec/PowerZure", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_webhook_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_webhook_created.json index e77d1f91747e7..2b8110b8e7d54 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_webhook_created.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_automation_webhook_created.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "name": "Azure Automation Webhook Created", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.activitylogs and azure.activitylogs.operation_name: ( \"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/WEBHOOKS/ACTION\" or \"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/WEBHOOKS/WRITE\" ) and event.outcome:(Success or success)", + "query": "event.dataset:azure.activitylogs and\n azure.activitylogs.operation_name:\n (\n \"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/WEBHOOKS/ACTION\" or\n \"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/WEBHOOKS/WRITE\"\n ) and\n event.outcome:(Success or success)\n", "references": [ "https://powerzure.readthedocs.io/en/latest/Functions/operational.html#create-backdoor", "https://github.com/hausec/PowerZure", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_conditional_access_policy_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_conditional_access_policy_modified.json index 00826c3d6162e..700ae78685257 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_conditional_access_policy_modified.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_conditional_access_policy_modified.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "name": "Azure Conditional Access Policy Modified", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(azure.activitylogs or azure.auditlogs) and ( azure.activitylogs.operation_name:\"Update policy\" or azure.auditlogs.operation_name:\"Update policy\" ) and event.outcome:(Success or success)", + "query": "event.dataset:(azure.activitylogs or azure.auditlogs) and\n (\n azure.activitylogs.operation_name:\"Update policy\" or\n azure.auditlogs.operation_name:\"Update policy\"\n ) and\n event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/active-directory/conditional-access/overview" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_pim_user_added_global_admin.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_pim_user_added_global_admin.json index 1d5332beed4f6..4ee9f8074985b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_pim_user_added_global_admin.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_pim_user_added_global_admin.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "Azure Global Administrator Role Addition to PIM User", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.auditlogs and azure.auditlogs.properties.category:RoleManagement and azure.auditlogs.operation_name:(\"Add eligible member to role in PIM completed (permanent)\" or \"Add member to role in PIM completed (timebound)\") and azure.auditlogs.properties.target_resources.*.display_name:\"Global Administrator\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.auditlogs and azure.auditlogs.properties.category:RoleManagement and\n azure.auditlogs.operation_name:(\"Add eligible member to role in PIM completed (permanent)\" or\n \"Add member to role in PIM completed (timebound)\") and\n azure.auditlogs.properties.target_resources.*.display_name:\"Global Administrator\" and\n event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/active-directory/users-groups-roles/directory-assign-admin-roles" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_privileged_identity_management_role_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_privileged_identity_management_role_modified.json index 0a75c0feaa516..214100ffced5c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_privileged_identity_management_role_modified.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_azure_privileged_identity_management_role_modified.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "name": "Azure Privilege Identity Management Role Modified", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.auditlogs and azure.auditlogs.operation_name:\"Update role setting in PIM\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.auditlogs and azure.auditlogs.operation_name:\"Update role setting in PIM\" and event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-resource-roles-assign-roles", "https://docs.microsoft.com/en-us/azure/active-directory/privileged-identity-management/pim-configure" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_credential_access_authorization_plugin_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_credential_access_authorization_plugin_creation.json index 3df0e48eb5ee3..d66066bca644e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_credential_access_authorization_plugin_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_credential_access_authorization_plugin_creation.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Authorization Plugin Modification", - "query": "event.category:file and not event.type:deletion and file.path:(/Library/Security/SecurityAgentPlugins/* and not /Library/Security/SecurityAgentPlugins/TeamViewerAuthPlugin.bundle/Contents/*)", + "query": "event.category:file and not event.type:deletion and\n file.path:(/Library/Security/SecurityAgentPlugins/* and\n not /Library/Security/SecurityAgentPlugins/TeamViewerAuthPlugin.bundle/Contents/*)\n", "references": [ "https://developer.apple.com/documentation/security/authorization_plug-ins", "https://www.xorrior.com/persistent-credential-theft/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_credential_access_modify_auth_module_or_config.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_credential_access_modify_auth_module_or_config.json index e1d8c05438b81..31e52590e22e0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_credential_access_modify_auth_module_or_config.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_credential_access_modify_auth_module_or_config.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Modification of Standard Authentication Module or Configuration", - "query": "event.category:file and event.type:change and (file.name:pam_*.so or file.path:(/etc/pam.d/* or /private/etc/pam.d/*)) and process.executable: (* and not ( /bin/yum or \"/usr/sbin/pam-auth-update\" or /usr/libexec/packagekitd or /usr/bin/dpkg or /usr/bin/vim or /usr/libexec/xpcproxy or /usr/bin/bsdtar or /usr/local/bin/brew or /usr/bin/rsync or /usr/bin/yum or /var/lib/docker/*/bin/yum or /var/lib/docker/*/bin/dpkg or ./merged/var/lib/docker/*/bin/dpkg or \"/System/Library/PrivateFrameworks/PackageKit.framework/Versions/A/XPCServices/package_script_service.xpc/Contents/MacOS/package_script_service\" ) ) and not file.path: ( /tmp/snap.rootfs_*/pam_*.so or /tmp/newroot/lib/*/pam_*.so or /private/var/folders/*/T/com.apple.fileprovider.ArchiveService/TemporaryItems/*/lib/security/pam_*.so or /tmp/newroot/usr/lib64/security/pam_*.so )", + "query": "event.category:file and event.type:change and \n (file.name:pam_*.so or file.path:(/etc/pam.d/* or /private/etc/pam.d/*)) and \n process.executable:\n (* and \n not \n (\n /bin/yum or \n \"/usr/sbin/pam-auth-update\" or \n /usr/libexec/packagekitd or \n /usr/bin/dpkg or \n /usr/bin/vim or \n /usr/libexec/xpcproxy or \n /usr/bin/bsdtar or \n /usr/local/bin/brew or\n /usr/bin/rsync or\n /usr/bin/yum or\n /var/lib/docker/*/bin/yum or\n /var/lib/docker/*/bin/dpkg or\n ./merged/var/lib/docker/*/bin/dpkg or\n \"/System/Library/PrivateFrameworks/PackageKit.framework/Versions/A/XPCServices/package_script_service.xpc/Contents/MacOS/package_script_service\"\n )\n ) and\n not file.path:\n (\n /tmp/snap.rootfs_*/pam_*.so or\n /tmp/newroot/lib/*/pam_*.so or\n /private/var/folders/*/T/com.apple.fileprovider.ArchiveService/TemporaryItems/*/lib/security/pam_*.so or\n /tmp/newroot/usr/lib64/security/pam_*.so\n )\n", "references": [ "https://github.com/zephrax/linux-pam-backdoor", "https://github.com/eurialo/pambd", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_credential_access_modify_ssh_binaries.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_credential_access_modify_ssh_binaries.json index e9f4aeea01129..46414c400ab8d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_credential_access_modify_ssh_binaries.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_credential_access_modify_ssh_binaries.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Modification of OpenSSH Binaries", - "query": "event.category:file and event.type:change and process.name:* and (file.path:(/usr/sbin/sshd or /usr/bin/ssh or /usr/bin/sftp or /usr/bin/scp) or file.name:libkeyutils.so) and not process.executable:/usr/bin/dpkg", + "query": "event.category:file and event.type:change and \n process.name:* and\n (file.path:(/usr/sbin/sshd or /usr/bin/ssh or /usr/bin/sftp or /usr/bin/scp) or file.name:libkeyutils.so) and\n not process.executable:/usr/bin/dpkg\n", "references": [ "https://blog.angelalonso.es/2016/09/anatomy-of-real-linux-intrusion-part-ii.html" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_defense_evasion_hidden_launch_agent_deamon_logonitem_process.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_defense_evasion_hidden_launch_agent_deamon_logonitem_process.json index 9778691f1d2f3..7ff8f12e60011 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_defense_evasion_hidden_launch_agent_deamon_logonitem_process.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_defense_evasion_hidden_launch_agent_deamon_logonitem_process.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Suspicious Hidden Child Process of Launchd", - "query": "event.category:process and event.type:(start or process_started) and process.name:.* and process.parent.executable:/sbin/launchd", + "query": "event.category:process and event.type:(start or process_started) and\n process.name:.* and process.parent.executable:/sbin/launchd\n", "references": [ "https://objective-see.com/blog/blog_0x61.html", "https://www.intezer.com/blog/research/operation-electrorat-attacker-creates-fake-companies-to-drain-your-crypto-wallets/", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_directory_services_plugins_modification.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_directory_services_plugins_modification.json index 18595dfe18048..0fce2b7647df4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_directory_services_plugins_modification.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_directory_services_plugins_modification.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Persistence via DirectoryService Plugin Modification", - "query": "event.category:file and not event.type:deletion and file.path:/Library/DirectoryServices/PlugIns/*.dsplug", + "query": "event.category:file and not event.type:deletion and\n file.path:/Library/DirectoryServices/PlugIns/*.dsplug\n", "references": [ "https://blog.chichou.me/2019/11/21/two-macos-persistence-tricks-abusing-plugins/" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_docker_shortcuts_plist_modification.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_docker_shortcuts_plist_modification.json index 6ccc3dbe509f2..941fe5cbf5484 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_docker_shortcuts_plist_modification.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_docker_shortcuts_plist_modification.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Persistence via Docker Shortcut Modification", - "query": "event.category : file and event.action : modification and file.path : /Users/*/Library/Preferences/com.apple.dock.plist and not process.name : (xpcproxy or cfprefsd or plutil or jamf or PlistBuddy or InstallerRemotePluginService)", + "query": "event.category : file and event.action : modification and \n file.path : /Users/*/Library/Preferences/com.apple.dock.plist and \n not process.name : (xpcproxy or cfprefsd or plutil or jamf or PlistBuddy or InstallerRemotePluginService)\n", "references": [ "https://github.com/specterops/presentations/raw/master/Leo Pitt/Hey_Im_Still_in_Here_Modern_macOS_Persistence_SO-CON2020.pdf" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_network_acl_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_network_acl_creation.json index 79ff9080c8f23..a545ae77d03ea 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_network_acl_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ec2_network_acl_creation.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS EC2 Network Access Control List Creation", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:ec2.amazonaws.com and event.action:(CreateNetworkAcl or CreateNetworkAclEntry) and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:ec2.amazonaws.com and event.action:(CreateNetworkAcl or CreateNetworkAclEntry) and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ec2/create-network-acl.html", "https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateNetworkAcl.html", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_enable_root_account.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_enable_root_account.json index 5d608649abe21..b81496a79f960 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_enable_root_account.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_enable_root_account.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Attempt to Enable the Root Account", - "query": "event.category:process and event.type:(start or process_started) and process.name:dsenableroot and not process.args:\"-d\"", + "query": "event.category:process and event.type:(start or process_started) and\n process.name:dsenableroot and not process.args:\"-d\"\n", "references": [ "https://ss64.com/osx/dsenableroot.html" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_iam_service_account_key_deletion.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_iam_service_account_key_deletion.json index 34efe6e0b3d0e..07372389f48c3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_iam_service_account_key_deletion.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_iam_service_account_key_deletion.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP IAM Service Account Key Deletion", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.iam.admin.v*.DeleteServiceAccountKey and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.iam.admin.v*.DeleteServiceAccountKey and event.outcome:success\n", "references": [ "https://cloud.google.com/iam/docs/service-accounts", "https://cloud.google.com/iam/docs/creating-managing-service-account-keys" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_key_created_for_service_account.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_key_created_for_service_account.json index 2c84a68b7603c..88249ad30adb9 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_key_created_for_service_account.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_key_created_for_service_account.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Service Account Key Creation", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.iam.admin.v*.CreateServiceAccountKey and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.iam.admin.v*.CreateServiceAccountKey and event.outcome:success\n", "references": [ "https://cloud.google.com/iam/docs/service-accounts", "https://cloud.google.com/iam/docs/creating-managing-service-account-keys" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_service_account_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_service_account_created.json index 54d4c01c66ea4..d37cc80d562cd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_service_account_created.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_gcp_service_account_created.json @@ -14,7 +14,7 @@ "license": "Elastic License v2", "name": "GCP Service Account Creation", "note": "## Config\n\nThe GCP Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.iam.admin.v*.CreateServiceAccount and event.outcome:success", + "query": "event.dataset:(googlecloud.audit or gcp.audit) and event.action:google.iam.admin.v*.CreateServiceAccount and event.outcome:success\n", "references": [ "https://cloud.google.com/iam/docs/service-accounts" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_admin_role_assigned_to_user.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_admin_role_assigned_to_user.json index 681d9f4f7d4c8..1ad3e0afeed52 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_admin_role_assigned_to_user.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_admin_role_assigned_to_user.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "Google Workspace Admin Role Assigned to a User", "note": "## Config\n\nThe Google Workspace Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n\n### Important Information Regarding Google Workspace Event Lag Times\n- As per Google's documentation, Google Workspace administrators may observe lag times ranging from minutes up to 3 days between the time of an event's occurrence and the event being visible in the Google Workspace admin/audit logs.\n- This rule is configured to run every 10 minutes with a lookback time of 130 minutes.\n- To reduce the risk of false negatives, consider reducing the interval that the Google Workspace (formerly G Suite) Filebeat module polls Google's reporting API for new events.\n- By default, `var.interval` is set to 2 hours (2h). Consider changing this interval to a lower value, such as 10 minutes (10m).\n- See the following references for further information.\n - https://support.google.com/a/answer/7061566\n - https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-gsuite.html", - "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:ASSIGN_ROLE", + "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:ASSIGN_ROLE\n", "references": [ "https://support.google.com/a/answer/172176?hl=en" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_api_access_granted_via_domain_wide_delegation_of_authority.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_api_access_granted_via_domain_wide_delegation_of_authority.json index 819c047a2c64f..19dd54c6ccb35 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_api_access_granted_via_domain_wide_delegation_of_authority.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_api_access_granted_via_domain_wide_delegation_of_authority.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "Google Workspace API Access Granted via Domain-Wide Delegation of Authority", "note": "## Config\n\nThe Google Workspace Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n\n### Important Information Regarding Google Workspace Event Lag Times\n- As per Google's documentation, Google Workspace administrators may observe lag times ranging from minutes up to 3 days between the time of an event's occurrence and the event being visible in the Google Workspace admin/audit logs.\n- This rule is configured to run every 10 minutes with a lookback time of 130 minutes.\n- To reduce the risk of false negatives, consider reducing the interval that the Google Workspace (formerly G Suite) Filebeat module polls Google's reporting API for new events.\n- By default, `var.interval` is set to 2 hours (2h). Consider changing this interval to a lower value, such as 10 minutes (10m).\n- See the following references for further information.\n - https://support.google.com/a/answer/7061566\n - https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-gsuite.html", - "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:AUTHORIZE_API_CLIENT_ACCESS", + "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:AUTHORIZE_API_CLIENT_ACCESS\n", "references": [ "https://developers.google.com/admin-sdk/directory/v1/guides/delegation" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_custom_admin_role_created.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_custom_admin_role_created.json index 2a68fc2604f8b..ae03288800adc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_custom_admin_role_created.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_custom_admin_role_created.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "Google Workspace Custom Admin Role Created", "note": "## Config\n\nThe Google Workspace Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n\n### Important Information Regarding Google Workspace Event Lag Times\n- As per Google's documentation, Google Workspace administrators may observe lag times ranging from minutes up to 3 days between the time of an event's occurrence and the event being visible in the Google Workspace admin/audit logs.\n- This rule is configured to run every 10 minutes with a lookback time of 130 minutes.\n- To reduce the risk of false negatives, consider reducing the interval that the Google Workspace (formerly G Suite) Filebeat module polls Google's reporting API for new events.\n- By default, `var.interval` is set to 2 hours (2h). Consider changing this interval to a lower value, such as 10 minutes (10m).\n- See the following references for further information.\n - https://support.google.com/a/answer/7061566\n - https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-gsuite.html", - "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:CREATE_ROLE", + "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:CREATE_ROLE\n", "references": [ "https://support.google.com/a/answer/2406043?hl=en" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_role_modified.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_role_modified.json index daf5b9b97a522..75bd229efa31c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_role_modified.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_google_workspace_role_modified.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "Google Workspace Role Modified", "note": "## Config\n\nThe Google Workspace Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.\n\n### Important Information Regarding Google Workspace Event Lag Times\n- As per Google's documentation, Google Workspace administrators may observe lag times ranging from minutes up to 3 days between the time of an event's occurrence and the event being visible in the Google Workspace admin/audit logs.\n- This rule is configured to run every 10 minutes with a lookback time of 130 minutes.\n- To reduce the risk of false negatives, consider reducing the interval that the Google Workspace (formerly G Suite) Filebeat module polls Google's reporting API for new events.\n- By default, `var.interval` is set to 2 hours (2h). Consider changing this interval to a lower value, such as 10 minutes (10m).\n- See the following references for further information.\n - https://support.google.com/a/answer/7061566\n - https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-gsuite.html", - "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:(ADD_PRIVILEGE or UPDATE_ROLE)", + "query": "event.dataset:(gsuite.admin or google_workspace.admin) and event.provider:admin and event.category:iam and event.action:(ADD_PRIVILEGE or UPDATE_ROLE)\n", "references": [ "https://support.google.com/a/answer/2406043?hl=en" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_iam_group_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_iam_group_creation.json index 0930201f0422e..084ccb4da74f2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_iam_group_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_iam_group_creation.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS IAM Group Creation", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:iam.amazonaws.com and event.action:CreateGroup and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:iam.amazonaws.com and event.action:CreateGroup and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iam/create-group.html", "https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateGroup.html" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_loginwindow_plist_modification.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_loginwindow_plist_modification.json index d6ffaa532a530..0ec8607f4d71d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_loginwindow_plist_modification.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_loginwindow_plist_modification.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "name": "Potential Persistence via Login Hook", "note": "## Triage and analysis\n\nStarting in Mac OS X 10.7 (Lion), users can specify certain applications to be re-opened when a user reboots their machine. This can be abused to establish or maintain persistence on a compromised system.", - "query": "event.category:\"file\" and not event.type:\"deletion\" and file.name:\"com.apple.loginwindow.plist\" and process.name:(* and not (systemmigrationd or DesktopServicesHelper or diskmanagementd or rsync or launchd or cfprefsd or xpcproxy or ManagedClient or MCXCompositor))", + "query": "event.category:\"file\" and not event.type:\"deletion\" and\n file.name:\"com.apple.loginwindow.plist\" and\n process.name:(* and not (systemmigrationd or DesktopServicesHelper or diskmanagementd or rsync or launchd or cfprefsd or xpcproxy or ManagedClient or MCXCompositor))\n", "references": [ "https://github.com/D00MFist/PersistentJXA/blob/master/LoginScript.js" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_mfa_disabled_for_azure_user.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_mfa_disabled_for_azure_user.json index e13975684a722..2514b5790d023 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_mfa_disabled_for_azure_user.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_mfa_disabled_for_azure_user.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "name": "Multi-Factor Authentication Disabled for an Azure User", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.auditlogs and azure.auditlogs.operation_name:\"Disable Strong Authentication\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.auditlogs and azure.auditlogs.operation_name:\"Disable Strong Authentication\" and event.outcome:(Success or success)\n", "risk_score": 47, "rule_id": "dafa3235-76dc-40e2-9f71-1773b96d24cf", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_exchange_management_role_assignment.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_exchange_management_role_assignment.json index a0e51fa3b8eed..b145642a01968 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_exchange_management_role_assignment.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_exchange_management_role_assignment.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 Exchange Management Group Role Assignment", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"New-ManagementRoleAssignment\" and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:Exchange and event.category:web and event.action:\"New-ManagementRoleAssignment\" and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/exchange/new-managementroleassignment?view=exchange-ps", "https://docs.microsoft.com/en-us/microsoft-365/admin/add-users/about-admin-roles?view=o365-worldwide" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_external_access_enabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_external_access_enabled.json index 570ac0323dfd1..f3ad4d22cf14c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_external_access_enabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_external_access_enabled.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 Teams External Access Enabled", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:(SkypeForBusiness or MicrosoftTeams) and event.category:web and event.action:\"Set-CsTenantFederationConfiguration\" and o365.audit.Parameters.AllowFederatedUsers:True and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:(SkypeForBusiness or MicrosoftTeams) and\nevent.category:web and event.action:\"Set-CsTenantFederationConfiguration\" and\no365.audit.Parameters.AllowFederatedUsers:True and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/microsoftteams/manage-external-access" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_guest_access_enabled.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_guest_access_enabled.json index 492c3dcd5bc9d..93f72b401d51e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_guest_access_enabled.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_microsoft_365_teams_guest_access_enabled.json @@ -15,7 +15,7 @@ "license": "Elastic License v2", "name": "Microsoft 365 Teams Guest Access Enabled", "note": "## Config\n\nThe Microsoft 365 Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:o365.audit and event.provider:(SkypeForBusiness or MicrosoftTeams) and event.category:web and event.action:\"Set-CsTeamsClientConfiguration\" and o365.audit.Parameters.AllowGuestUser:True and event.outcome:success", + "query": "event.dataset:o365.audit and event.provider:(SkypeForBusiness or MicrosoftTeams) and\nevent.category:web and event.action:\"Set-CsTeamsClientConfiguration\" and\no365.audit.Parameters.AllowGuestUser:True and event.outcome:success\n", "references": [ "https://docs.microsoft.com/en-us/powershell/module/skype/get-csteamsclientconfiguration?view=skype-ps" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_periodic_tasks_file_mdofiy.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_periodic_tasks_file_mdofiy.json index f48ea64022ecb..2df59206645b4 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_periodic_tasks_file_mdofiy.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_periodic_tasks_file_mdofiy.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential Persistence via Periodic Tasks", - "query": "event.category:\"file\" and not event.type:\"deletion\" and file.path:(/private/etc/periodic/* or /private/etc/defaults/periodic.conf or /private/etc/periodic.conf)", + "query": "event.category:\"file\" and not event.type:\"deletion\" and\n file.path:(/private/etc/periodic/* or /private/etc/defaults/periodic.conf or /private/etc/periodic.conf)\n", "references": [ "https://opensource.apple.com/source/crontabs/crontabs-13/private/etc/defaults/periodic.conf.auto.html", "https://www.oreilly.com/library/view/mac-os-x/0596003706/re328.html", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_cluster_creation.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_cluster_creation.json index 3a13c02a368ad..4f28f277d21e1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_cluster_creation.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_rds_cluster_creation.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS RDS Cluster Creation", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:rds.amazonaws.com and event.action:(CreateDBCluster or CreateGlobalCluster) and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:rds.amazonaws.com and event.action:(CreateDBCluster or CreateGlobalCluster) and event.outcome:success\n", "references": [ "https://awscli.amazonaws.com/v2/documentation/api/latest/reference/rds/create-db-cluster.html", "https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_CreateDBCluster.html", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_shell_activity_by_web_server.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_shell_activity_by_web_server.json index 545787d7ec999..eec7157c74148 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_shell_activity_by_web_server.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_shell_activity_by_web_server.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential Shell via Web Server", - "query": "event.category:process and event.type:(start or process_started) and process.name:(bash or dash) and user.name:(apache or nginx or www or \"www-data\")", + "query": "event.category:process and event.type:(start or process_started) and process.name:(bash or dash) and\n user.name:(apache or nginx or www or \"www-data\")\n", "references": [ "https://pentestlab.blog/tag/web-shell/" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_shell_profile_modification.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_shell_profile_modification.json index fa56d07b190cd..41ca64fb6c162 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_shell_profile_modification.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_shell_profile_modification.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Bash Shell Profile Modification", - "query": "event.category:file and event.type:change and process.name:(* and not (sudo or vim or zsh or env or nano or bash or Terminal or xpcproxy or login or cat or cp or launchctl or java)) and not process.executable:(/Applications/* or /private/var/folders/* or /usr/local/*) and file.path:(/private/etc/rc.local or /etc/rc.local or /home/*/.profile or /home/*/.profile1 or /home/*/.bash_profile or /home/*/.bash_profile1 or /home/*/.bashrc or /Users/*/.bash_profile or /Users/*/.zshenv)", + "query": "event.category:file and event.type:change and\n process.name:(* and not (sudo or\n vim or\n zsh or\n env or\n nano or\n bash or\n Terminal or\n xpcproxy or\n login or\n cat or\n cp or\n launchctl or\n java)) and\n not process.executable:(/Applications/* or /private/var/folders/* or /usr/local/*) and\n file.path:(/private/etc/rc.local or\n /etc/rc.local or\n /home/*/.profile or\n /home/*/.profile1 or\n /home/*/.bash_profile or\n /home/*/.bash_profile1 or\n /home/*/.bashrc or\n /Users/*/.bash_profile or\n /Users/*/.zshenv)\n", "references": [ "https://www.anomali.com/blog/pulling-linux-rabbit-rabbot-malware-out-of-a-hat" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ssh_authorized_keys_modification.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ssh_authorized_keys_modification.json index 46358ec7f47fe..23d16f121921b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ssh_authorized_keys_modification.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_ssh_authorized_keys_modification.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "SSH Authorized Keys File Modification", - "query": "event.category:file and event.type:(change or creation) and file.name:(\"authorized_keys\" or \"authorized_keys2\") and not process.executable: (/Library/Developer/CommandLineTools/usr/bin/git or /usr/local/Cellar/maven/*/libexec/bin/mvn or /Library/Java/JavaVirtualMachines/jdk*.jdk/Contents/Home/bin/java or /usr/bin/vim or /usr/local/Cellar/coreutils/*/bin/gcat or /usr/bin/bsdtar or /usr/bin/nautilus or /usr/bin/scp or /usr/bin/touch or /var/lib/docker/*)", + "query": "event.category:file and event.type:(change or creation) and \n file.name:(\"authorized_keys\" or \"authorized_keys2\") and \n not process.executable:\n (/Library/Developer/CommandLineTools/usr/bin/git or \n /usr/local/Cellar/maven/*/libexec/bin/mvn or \n /Library/Java/JavaVirtualMachines/jdk*.jdk/Contents/Home/bin/java or \n /usr/bin/vim or \n /usr/local/Cellar/coreutils/*/bin/gcat or \n /usr/bin/bsdtar or\n /usr/bin/nautilus or \n /usr/bin/scp or\n /usr/bin/touch or \n /var/lib/docker/*)\n", "risk_score": 47, "rule_id": "2215b8bd-1759-4ffa-8ab8-55c8e6b32e7f", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_calendar_modification.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_calendar_modification.json index 1f0186c39ad26..97a3de8f4060d 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_calendar_modification.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_calendar_modification.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Suspicious Calendar File Modification", - "query": "event.category:file and event.action:modification and file.path:/Users/*/Library/Calendars/*.calendar/Events/*.ics and process.executable: (* and not ( /System/Library/* or /System/Applications/Calendar.app/Contents/MacOS/* or /usr/libexec/xpcproxy or /sbin/launchd or /Applications/* ) )", + "query": "event.category:file and event.action:modification and\n file.path:/Users/*/Library/Calendars/*.calendar/Events/*.ics and\n process.executable:\n (* and not \n (\n /System/Library/* or \n /System/Applications/Calendar.app/Contents/MacOS/* or \n /usr/libexec/xpcproxy or \n /sbin/launchd or \n /Applications/*\n )\n )\n", "references": [ "https://labs.f-secure.com/blog/operationalising-calendar-alerts-persistence-on-macos", "https://github.com/FSecureLABS/CalendarPersist", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_com_hijack_registry.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_com_hijack_registry.json index f20b00d057f1a..b0f573730b73f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_com_hijack_registry.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_suspicious_com_hijack_registry.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Component Object Model Hijacking", - "query": "registry where\n /* uncomment once length is stable length(bytes_written_string) > 0 and */\n (registry.path : \"HK*}\\\\InprocServer32\\\\\" and registry.data.strings: (\"scrobj.dll\", \"C:\\\\*\\\\scrobj.dll\") and\n not registry.path : \"*\\\\{06290BD*-48AA-11D2-8432-006008C3FBFC}\\\\*\") \n or\n /* in general COM Registry changes on Users Hive is less noisy and worth alerting */\n (registry.path : (\"HKEY_USERS\\\\*Classes\\\\*\\\\InprocXServer32\\\\\", \n \"HKEY_USERS\\\\*Classes\\\\*\\\\LocalServer32\\\\\", \n \"HKEY_USERS\\\\*Classes\\\\*\\\\DelegateExecute\\\\\", \n \"HKEY_USERS\\\\*Classes\\\\*\\\\TreatAs\\\\\", \n \"HKEY_USERS\\\\*Classes\\\\CLSID\\\\*\\\\ScriptletURL\\\\\") and\n /* not necessary but good for filtering privileged installations */\n user.domain != \"NT AUTHORITY\")\n", + "query": "registry where\n /* uncomment once length is stable length(bytes_written_string) > 0 and */\n (registry.path : \"HK*}\\\\InprocServer32\\\\\" and registry.data.strings: (\"scrobj.dll\", \"C:\\\\*\\\\scrobj.dll\") and\n not registry.path : \"*\\\\{06290BD*-48AA-11D2-8432-006008C3FBFC}\\\\*\") \n or\n /* in general COM Registry changes on Users Hive is less noisy and worth alerting */\n (registry.path : (\"HKEY_USERS\\\\*Classes\\\\*\\\\InprocServer32\\\\\",\n \"HKEY_USERS\\\\*Classes\\\\*\\\\LocalServer32\\\\\", \n \"HKEY_USERS\\\\*Classes\\\\*\\\\DelegateExecute\\\\\", \n \"HKEY_USERS\\\\*Classes\\\\*\\\\TreatAs\\\\\", \n \"HKEY_USERS\\\\*Classes\\\\CLSID\\\\*\\\\ScriptletURL\\\\\") and\n /* not necessary but good for filtering privileged installations */\n user.domain != \"NT AUTHORITY\")\n", "references": [ "https://bohops.com/2018/08/18/abusing-the-com-registry-structure-part-2-loading-techniques-for-evasion-and-persistence/" ], @@ -52,5 +52,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 3 + "version": 4 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_application.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_application.json index ee2fdb5b75eac..1d0990e951925 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_application.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_application.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "name": "User Added as Owner for Azure Application", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.auditlogs and azure.auditlogs.operation_name:\"Add owner to application\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.auditlogs and azure.auditlogs.operation_name:\"Add owner to application\" and event.outcome:(Success or success)\n", "risk_score": 21, "rule_id": "774f5e28-7b75-4a58-b94e-41bf060fdd86", "severity": "low", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_service_principal.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_service_principal.json index aacc17bb6be53..b68b4826bc4cf 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_service_principal.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_user_added_as_owner_for_azure_service_principal.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "name": "User Added as Owner for Azure Service Principal", "note": "## Config\n\nThe Azure Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:azure.auditlogs and azure.auditlogs.operation_name:\"Add owner to service principal\" and event.outcome:(Success or success)", + "query": "event.dataset:azure.auditlogs and azure.auditlogs.operation_name:\"Add owner to service principal\" and event.outcome:(Success or success)\n", "references": [ "https://docs.microsoft.com/en-us/azure/active-directory/develop/app-objects-and-service-principals" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_atom_init_file_modification.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_atom_init_file_modification.json index 30c2d3a9b4ab7..0977d8310cf6b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_atom_init_file_modification.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/persistence_via_atom_init_file_modification.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential Persistence via Atom Init Script Modification", - "query": "event.category:\"file\" and not event.type:\"deletion\" and file.path:/Users/*/.atom/init.coffee and not process.name:(Atom or xpcproxy) and not user.name:root", + "query": "event.category:\"file\" and not event.type:\"deletion\" and\n file.path:/Users/*/.atom/init.coffee and not process.name:(Atom or xpcproxy) and not user.name:root\n", "references": [ "https://github.com/D00MFist/PersistentJXA/blob/master/AtomPersist.js", "https://flight-manual.atom.io/hacking-atom/sections/the-init-file/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_echo_nopasswd_sudoers.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_echo_nopasswd_sudoers.json index e6bd7784006ee..6023854cd6641 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_echo_nopasswd_sudoers.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_echo_nopasswd_sudoers.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential Privilege Escalation via Sudoers File Modification", - "query": "event.category:process and event.type:start and process.args:(echo and *NOPASSWD*ALL*)", + "query": "event.category:process and event.type:start and process.args:(echo and *NOPASSWD*ALL*)\n", "risk_score": 73, "rule_id": "76152ca1-71d0-4003-9e37-0983e12832da", "severity": "high", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_explicit_creds_via_scripting.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_explicit_creds_via_scripting.json index c8ec829d3ae8a..32c47afd93019 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_explicit_creds_via_scripting.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_explicit_creds_via_scripting.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Execution with Explicit Credentials via Scripting", - "query": "event.category:process and event.type:(start or process_started) and process.name:\"security_authtrampoline\" and process.parent.name:(osascript or com.apple.automator.runner or sh or bash or dash or zsh or python* or perl* or php* or ruby or pwsh)", + "query": "event.category:process and event.type:(start or process_started) and\n process.name:\"security_authtrampoline\" and\n process.parent.name:(osascript or com.apple.automator.runner or sh or bash or dash or zsh or python* or perl* or php* or ruby or pwsh)\n", "references": [ "https://objectivebythesea.com/v2/talks/OBTS_v2_Thomas.pdf", "https://www.manpagez.com/man/8/security_authtrampoline/" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_exploit_adobe_acrobat_updater.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_exploit_adobe_acrobat_updater.json index 0fb4285ea2a98..0c30cbb23b56b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_exploit_adobe_acrobat_updater.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_exploit_adobe_acrobat_updater.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Suspicious Child Process of Adobe Acrobat Reader Update Service", - "query": "event.category:process and event.type:(start or process_started) and process.parent.name:com.adobe.ARMDC.SMJobBlessHelper and user.name:root and not process.executable: (/Library/PrivilegedHelperTools/com.adobe.ARMDC.SMJobBlessHelper or /usr/bin/codesign or /private/var/folders/zz/*/T/download/ARMDCHammer or /usr/sbin/pkgutil or /usr/bin/shasum or /usr/bin/perl* or /usr/sbin/spctl or /usr/sbin/installer)", + "query": "event.category:process and event.type:(start or process_started) and\n process.parent.name:com.adobe.ARMDC.SMJobBlessHelper and\n user.name:root and\n not process.executable: (/Library/PrivilegedHelperTools/com.adobe.ARMDC.SMJobBlessHelper or\n /usr/bin/codesign or\n /private/var/folders/zz/*/T/download/ARMDCHammer or\n /usr/sbin/pkgutil or\n /usr/bin/shasum or\n /usr/bin/perl* or\n /usr/sbin/spctl or\n /usr/sbin/installer)\n", "references": [ "https://rekken.github.io/2020/05/14/Security-Flaws-in-Adobe-Acrobat-Reader-Allow-Malicious-Program-to-Gain-Root-on-macOS-Silently/" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_ld_preload_shared_object_modif.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_ld_preload_shared_object_modif.json index 7000e119f8881..4b1b367a5ea35 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_ld_preload_shared_object_modif.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_ld_preload_shared_object_modif.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Modification of Dynamic Linker Preload Shared Object", - "query": "event.category:file and not event.type:deletion and file.path:/etc/ld.so.preload", + "query": "event.category:file and not event.type:deletion and file.path:/etc/ld.so.preload\n", "references": [ "https://www.anomali.com/blog/rocke-evolves-its-arsenal-with-a-new-malware-family-written-in-golang" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_local_user_added_to_admin.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_local_user_added_to_admin.json index 58c151d6de0c4..72c3bfc9a520c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_local_user_added_to_admin.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_local_user_added_to_admin.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Potential Admin Group Account Addition", - "query": "event.category:process and event.type:(start or process_started) and process.name:(dscl or dseditgroup) and process.args:((\"/Groups/admin\" or admin) and (\"-a\" or \"-append\"))", + "query": "event.category:process and event.type:(start or process_started) and\n process.name:(dscl or dseditgroup) and process.args:((\"/Groups/admin\" or admin) and (\"-a\" or \"-append\"))\n", "references": [ "https://managingosx.wordpress.com/2010/01/14/add-a-user-to-the-admin-group-via-command-line-3-0/" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_persistence_phantom_dll.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_persistence_phantom_dll.json index a85558df6f388..e454a387b3883 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_persistence_phantom_dll.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_persistence_phantom_dll.json @@ -12,7 +12,7 @@ "language": "eql", "license": "Elastic License v2", "name": "Suspicious DLL Loaded for Persistence or Privilege Escalation", - "query": "library where dll.name :\n (\n \"wlbsctrl.dll\",\n \"wbemcomn.dll\",\n \"WptsExtensions.dll\",\n \"Tsmsisrv.dll\",\n \"TSVIPSrv.dll\",\n \"Msfte.dll\",\n \"wow64log.dll\",\n \"WindowsCoreDeviceInfo.dll\",\n \"Ualapi.dll\",\n \"wlanhlp.dll\",\n \"phoneinfo.dll\",\n \"EdgeGdi.dll\",\n \"cdpsgshims.dll\",\n \"windowsperformancerecordercontrol.dll\",\n \"diagtrack_win.dll\"\n ) and \nnot (dll.code_signature.subject_name : \"Microsoft Windows\" and dll.code_signature.status : \"trusted\")\n", + "query": "library where dll.name :\n (\n \"wlbsctrl.dll\",\n \"wbemcomn.dll\",\n \"WptsExtensions.dll\",\n \"Tsmsisrv.dll\",\n \"TSVIPSrv.dll\",\n \"Msfte.dll\",\n \"wow64log.dll\",\n \"WindowsCoreDeviceInfo.dll\",\n \"Ualapi.dll\",\n \"wlanhlp.dll\",\n \"phoneinfo.dll\",\n \"EdgeGdi.dll\",\n \"cdpsgshims.dll\",\n \"windowsperformancerecordercontrol.dll\",\n \"diagtrack_win.dll\"\n ) and \nnot (dll.code_signature.subject_name : (\"Microsoft Windows\", \"Microsoft Corporation\") and dll.code_signature.status : \"trusted\")\n", "references": [ "https://itm4n.github.io/windows-dll-hijacking-clarified/", "http://remoteawesomethoughts.blogspot.com/2019/05/windows-10-task-schedulerservice.html", @@ -80,5 +80,5 @@ ], "timestamp_override": "event.ingested", "type": "eql", - "version": 1 + "version": 2 } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_root_crontab_filemod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_root_crontab_filemod.json index f782e429dd29e..57f893168ba57 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_root_crontab_filemod.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_root_crontab_filemod.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Privilege Escalation via Root Crontab File Modification", - "query": "event.category:file and not event.type:deletion and file.path:/private/var/at/tabs/root and not process.executable:/usr/bin/crontab", + "query": "event.category:file and not event.type:deletion and\n file.path:/private/var/at/tabs/root and not process.executable:/usr/bin/crontab\n", "references": [ "https://phoenhex.re/2017-06-09/pwn2own-diskarbitrationd-privesc", "https://www.exploit-db.com/exploits/42146" diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_root_login_without_mfa.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_root_login_without_mfa.json index 5ab6b41582030..33b5cd400fd33 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_root_login_without_mfa.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_root_login_without_mfa.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS Root Login Without MFA", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:signin.amazonaws.com and event.action:ConsoleLogin and aws.cloudtrail.user_identity.type:Root and aws.cloudtrail.console_login.additional_eventdata.mfa_used:false and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:signin.amazonaws.com and event.action:ConsoleLogin and\n aws.cloudtrail.user_identity.type:Root and\n aws.cloudtrail.console_login.additional_eventdata.mfa_used:false and\n event.outcome:success\n", "references": [ "https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_setuid_setgid_bit_set_via_chmod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_setuid_setgid_bit_set_via_chmod.json index 67633985221e3..29113d078ae5f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_setuid_setgid_bit_set_via_chmod.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_setuid_setgid_bit_set_via_chmod.json @@ -12,7 +12,7 @@ "license": "Elastic License v2", "max_signals": 33, "name": "Setuid / Setgid Bit Set via chmod", - "query": "event.category:process AND event.type:(start OR process_started) AND process.name:chmod AND process.args:(\"+s\" OR \"u+s\" OR /4[0-9]{3}/ OR g+s OR /2[0-9]{3}/) AND NOT process.args: ( /.*\\/Applications\\/VirtualBox.app\\/.+/ OR /\\/usr\\/local\\/lib\\/python.+/ OR /\\/var\\/folders\\/.+\\/FP.*nstallHelper/ OR /\\/Library\\/Filesystems\\/.+/ OR /\\/usr\\/lib\\/virtualbox\\/.+/ OR /\\/Library\\/Application.*/ OR \"/run/postgresql\" OR \"/var/crash\" OR \"/var/run/postgresql\" OR /\\/usr\\/bin\\/.+/ OR /\\/usr\\/local\\/share\\/.+/ OR /\\/Applications\\/.+/ OR /\\/usr\\/libexec\\/.+/ OR \"/var/metrics\" OR /\\/var\\/lib\\/dpkg\\/.+/ OR /\\/run\\/log\\/journal\\/.*/ OR \\/Users\\/*\\/.minikube\\/bin\\/docker-machine-driver-hyperkit ) AND NOT process.parent.executable: ( /\\/var\\/lib\\/docker\\/.+/ OR \"/System/Library/PrivateFrameworks/PackageKit.framework/Versions/A/XPCServices/package_script_service.xpc/Contents/MacOS/package_script_service\" OR \"/var/lib/dpkg/info/whoopsie.postinst\" )", + "query": "event.category:process AND event.type:(start OR process_started) AND\n process.name:chmod AND process.args:(\"+s\" OR \"u+s\" OR /4[0-9]{3}/ OR g+s OR /2[0-9]{3}/) AND\n NOT process.args:\n (\n /.*\\/Applications\\/VirtualBox.app\\/.+/ OR\n /\\/usr\\/local\\/lib\\/python.+/ OR\n /\\/var\\/folders\\/.+\\/FP.*nstallHelper/ OR\n /\\/Library\\/Filesystems\\/.+/ OR\n /\\/usr\\/lib\\/virtualbox\\/.+/ OR\n /\\/Library\\/Application.*/ OR\n \"/run/postgresql\" OR\n \"/var/crash\" OR\n \"/var/run/postgresql\" OR\n /\\/usr\\/bin\\/.+/ OR /\\/usr\\/local\\/share\\/.+/ OR\n /\\/Applications\\/.+/ OR /\\/usr\\/libexec\\/.+/ OR\n \"/var/metrics\" OR /\\/var\\/lib\\/dpkg\\/.+/ OR\n /\\/run\\/log\\/journal\\/.*/ OR\n \\/Users\\/*\\/.minikube\\/bin\\/docker-machine-driver-hyperkit\n ) AND\n NOT process.parent.executable:\n (\n /\\/var\\/lib\\/docker\\/.+/ OR\n \"/System/Library/PrivateFrameworks/PackageKit.framework/Versions/A/XPCServices/package_script_service.xpc/Contents/MacOS/package_script_service\" OR\n \"/var/lib/dpkg/info/whoopsie.postinst\"\n )\n", "risk_score": 21, "rule_id": "8a1b0278-0f9a-487d-96bd-d4833298e87a", "severity": "low", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sudo_buffer_overflow.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sudo_buffer_overflow.json index 144cea40e6a4b..1c7a064131171 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sudo_buffer_overflow.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sudo_buffer_overflow.json @@ -14,7 +14,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Sudo Heap-Based Buffer Overflow Attempt", - "query": "event.category:process and event.type:start and process.name:(sudo or sudoedit) and process.args:(*\\\\ and (\"-i\" or \"-s\"))", + "query": "event.category:process and event.type:start and\n process.name:(sudo or sudoedit) and\n process.args:(*\\\\ and (\"-i\" or \"-s\"))\n", "references": [ "https://cve.mitre.org/cgi-bin/cvename.cgi?name=2021-3156", "https://blog.qualys.com/vulnerabilities-research/2021/01/26/cve-2021-3156-heap-based-buffer-overflow-in-sudo-baron-samedit", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sudoers_file_mod.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sudoers_file_mod.json index 1b480e3d19650..963c16ae4dd61 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sudoers_file_mod.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_sudoers_file_mod.json @@ -11,7 +11,7 @@ "language": "kuery", "license": "Elastic License v2", "name": "Sudoers File Modification", - "query": "event.category:file and event.type:change and file.path:(/etc/sudoers* or /private/etc/sudoers*)", + "query": "event.category:file and event.type:change and file.path:(/etc/sudoers* or /private/etc/sudoers*)\n", "risk_score": 47, "rule_id": "931e25a5-0f5e-4ae0-ba0d-9e94eff7e3a4", "severity": "medium", diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_updateassumerolepolicy.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_updateassumerolepolicy.json index 8f01db818dfb9..e46e59feea6f0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_updateassumerolepolicy.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/privilege_escalation_updateassumerolepolicy.json @@ -16,7 +16,7 @@ "license": "Elastic License v2", "name": "AWS IAM Assume Role Policy Update", "note": "## Config\n\nThe AWS Fleet integration, Filebeat module, or similarly structured data is required to be compatible with this rule.", - "query": "event.dataset:aws.cloudtrail and event.provider:iam.amazonaws.com and event.action:UpdateAssumeRolePolicy and event.outcome:success", + "query": "event.dataset:aws.cloudtrail and event.provider:iam.amazonaws.com and event.action:UpdateAssumeRolePolicy and event.outcome:success\n", "references": [ "https://labs.bishopfox.com/tech-blog/5-privesc-attack-vectors-in-aws" ], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_module_match.json b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_module_match.json index 9a058b50683b6..f582eba053d64 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_module_match.json +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/prepackaged_rules/threat_intel_module_match.json @@ -17,7 +17,7 @@ "license": "Elastic License v2", "name": "Threat Intel Filebeat Module Indicator Match", "note": "## Triage and Analysis\n\nIf an indicator matches a local observation, the following enriched fields will be generated to identify the indicator, field, and type matched.\n\n- `threatintel.indicator.matched.atomic` - this identifies the atomic indicator that matched the local observation\n- `threatintel.indicator.matched.field` - this identifies the indicator field that matched the local observation\n- `threatintel.indicator.matched.type` - this identifies the indicator type that matched the local observation\n", - "query": "file.hash.*:* or file.pe.imphash:* or source.ip:* or destination.ip:* or url.full:* or registry.path:*", + "query": "file.hash.*:* or file.pe.imphash:* or source.ip:* or destination.ip:* or url.full:* or registry.path:*\n", "references": [ "https://www.elastic.co/guide/en/beats/filebeat/current/filebeat-module-threatintel.html" ], diff --git a/x-pack/test/fleet_api_integration/apis/epm/delete.ts b/x-pack/test/fleet_api_integration/apis/epm/delete.ts index c79a29a858b46..5f90805e5879f 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/delete.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/delete.ts @@ -11,7 +11,7 @@ import { skipIfNoDockerRegistry } from '../../helpers'; export default function (providerContext: FtrProviderContext) { const { getService } = providerContext; const supertest = getService('supertest'); - const requiredPackage = 'system-0.12.6'; + const requiredPackage = 'system-0.13.3'; const installPackage = async (pkgkey: string) => { await supertest diff --git a/x-pack/test/fleet_api_integration/config.ts b/x-pack/test/fleet_api_integration/config.ts index d18ba9c55ca96..d1c6c3c3f6b1e 100644 --- a/x-pack/test/fleet_api_integration/config.ts +++ b/x-pack/test/fleet_api_integration/config.ts @@ -15,8 +15,7 @@ import { defineDockerServersConfig } from '@kbn/test'; // example: https://beats-ci.elastic.co/blue/organizations/jenkins/Ingest-manager%2Fpackage-storage/detail/snapshot/74/pipeline/257#step-302-log-1. // It should be updated any time there is a new Docker image published for the Snapshot Distribution of the Package Registry. export const dockerImage = - process.env.FLEET_PACKAGE_REGISTRY_DOCKER_IMAGE || - 'docker.elastic.co/package-registry/distribution:fc104ac437370d80518e24da6d0b84370edf0c0c'; + 'docker.elastic.co/package-registry/distribution@sha256:35cedaaa6adac547947321fa0c3b60a63eba153ba09524b9c1a21f1247a09bd2'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { const xPackAPITestsConfig = await readConfigFile(require.resolve('../api_integration/config.ts'));