mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Detection Engine][FTR] Audit DE exceptions tests (#179706)
## Summary Continues work on https://github.com/elastic/kibana/issues/169185 and https://github.com/elastic/kibana/issues/151877 . There wasn't a ton of folder restructure, just switching the tests to run on basic license/essentials tier and some test renaming for clarity sake.
This commit is contained in:
parent
6b29552382
commit
9215efb6aa
44 changed files with 1300 additions and 1123 deletions
|
@ -475,18 +475,18 @@ enabled:
|
|||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/basic_license_essentials_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/trial_license_complete_tier/configs/ess.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/alerts/trial_license_complete_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/date_numeric_types/trial_license_complete_tier/configs/ess.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/date_numeric_types/trial_license_complete_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/ips/trial_license_complete_tier/configs/ess.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/ips/trial_license_complete_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/keyword/trial_license_complete_tier/configs/ess.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/keyword/trial_license_complete_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/long/trial_license_complete_tier/configs/ess.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/long/trial_license_complete_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/text/trial_license_complete_tier/configs/ess.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/text/trial_license_complete_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/workflows/trial_license_complete_tier/configs/ess.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/workflows/trial_license_complete_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/date_numeric_types/basic_license_essentials_tier/configs/ess.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/date_numeric_types/basic_license_essentials_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/ips/basic_license_essentials_tier/configs/ess.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/ips/basic_license_essentials_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/keyword/basic_license_essentials_tier/configs/ess.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/keyword/basic_license_essentials_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/long/basic_license_essentials_tier/configs/ess.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/long/basic_license_essentials_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/text/basic_license_essentials_tier/configs/ess.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/operators_data_types/text/basic_license_essentials_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/workflows/basic_license_essentials_tier/configs/ess.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/workflows/basic_license_essentials_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/configs/ess.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/configs/serverless.config.ts
|
||||
- x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/configs/ess.config.ts
|
||||
|
|
|
@ -90,7 +90,7 @@ FORMATTED_KB_URL="${KB_URL/https:\/\//}"
|
|||
# This is used in order to wait for the environment to be ready.
|
||||
sleep 150
|
||||
|
||||
TEST_CLOUD=1 TEST_ES_URL="https://elastic:$PASSWORD@$FORMATTED_ES_URL:443" TEST_KIBANA_URL="https://elastic:$PASSWORD@$FORMATTED_KB_URL:443" yarn run $1
|
||||
TEST_CLOUD=1 TEST_ES_URL="https://$USERNAME:$PASSWORD@$FORMATTED_ES_URL:443" TEST_KIBANA_URL="https://$USERNAME:$PASSWORD@$FORMATTED_KB_URL:443" yarn run $1
|
||||
cmd_status=$?
|
||||
echo "Exit code with status: $cmd_status"
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@
|
|||
"logs-*",
|
||||
"packetbeat-*",
|
||||
"winlogbeat-*",
|
||||
"logstash-*",
|
||||
".asset-criticality.asset-criticality-*"
|
||||
],
|
||||
"privileges": ["read", "write"]
|
||||
|
@ -117,7 +118,7 @@
|
|||
"privileges": ["read", "write"]
|
||||
},
|
||||
{
|
||||
"names": ["metrics-endpoint.metadata_current_*", ".fleet-agents*", ".fleet-actions*"],
|
||||
"names": ["metrics-endpoint.metadata_current_*", ".fleet-agents*", ".fleet-actions*", "risk-score.risk-score-*"],
|
||||
"privileges": ["read"]
|
||||
}
|
||||
],
|
||||
|
@ -143,9 +144,14 @@
|
|||
"file_operations_all"
|
||||
],
|
||||
"securitySolutionCases": ["all"],
|
||||
"securitySolutionAssistant": ["all"],
|
||||
"actions": ["read"],
|
||||
"builtInAlerts": ["all"],
|
||||
"osquery": ["all"]
|
||||
"osquery": ["all"],
|
||||
"discover": ["all"],
|
||||
"dashboard": ["all"],
|
||||
"maps": ["all"],
|
||||
"visualize": ["all"]
|
||||
},
|
||||
"spaces": ["*"],
|
||||
"base": []
|
||||
|
|
|
@ -74,41 +74,41 @@
|
|||
"telemetry:server:ess": "npm run initialize-server:dr telemetry ess",
|
||||
"telemetry:runner:ess": "npm run run-tests:dr telemetry ess essEnv",
|
||||
|
||||
"exception_workflows:server:serverless": "npm run initialize-server:de exceptions/workflows serverless",
|
||||
"exception_workflows:runner:serverless": "npm run run-tests:de exceptions/workflows serverless serverlessEnv",
|
||||
"exception_workflows:qa:serverless": "npm run run-tests:de exceptions/workflows serverless qaEnv",
|
||||
"exception_workflows:server:ess": "npm run initialize-server:de exceptions/workflows ess",
|
||||
"exception_workflows:runner:ess": "npm run run-tests:de exceptions/workflows ess essEnv",
|
||||
"exception_workflows:essentials:server:serverless": "npm run initialize-server:de:basic_essentials exceptions/workflows serverless",
|
||||
"exception_workflows:essentials:runner:serverless": "npm run run-tests:de:basic_essentials exceptions/workflows serverless serverlessEnv",
|
||||
"exception_workflows:essentials:qa:serverless": "npm run run-tests:de:basic_essentials exceptions/workflows serverless qaEnv",
|
||||
"exception_workflows:basic:server:ess": "npm run initialize-server:de:basic_essentials exceptions/workflows ess",
|
||||
"exception_workflows:basic:runner:ess": "npm run run-tests:de:basic_essentials exceptions/workflows ess essEnv",
|
||||
|
||||
"exception_operators_date_numeric_types:server:serverless": "npm run initialize-server:de exceptions/operators_data_types/date_numeric_types serverless",
|
||||
"exception_operators_date_numeric_types:runner:serverless": "npm run run-tests:de exceptions/operators_data_types/date_numeric_types serverless serverlessEnv",
|
||||
"exception_operators_date_numeric_types:qa:serverless": "npm run run-tests:de exceptions/operators_data_types/date_numeric_types serverless qaEnv",
|
||||
"exception_operators_date_numeric_types:server:ess": "npm run initialize-server:de exceptions/operators_data_types/date_numeric_types ess",
|
||||
"exception_operators_date_numeric_types:runner:ess": "npm run run-tests:de exceptions/operators_data_types/date_numeric_types ess essEnv",
|
||||
"exception_operators_date_numeric_types:essentials:server:serverless": "npm run initialize-server:de:basic_essentials exceptions/operators_data_types/date_numeric_types serverless",
|
||||
"exception_operators_date_numeric_types:essentials:runner:serverless": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/date_numeric_types serverless serverlessEnv",
|
||||
"exception_operators_date_numeric_types:essentials:qa:serverless": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/date_numeric_types serverless qaEnv",
|
||||
"exception_operators_date_numeric_types:basic:server:ess": "npm run initialize-server:de:basic_essentials exceptions/operators_data_types/date_numeric_types ess",
|
||||
"exception_operators_date_numeric_types:basic:runner:ess": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/date_numeric_types ess essEnv",
|
||||
|
||||
"exception_operators_keyword:server:serverless": "npm run initialize-server:de exceptions/operators_data_types/keyword serverless",
|
||||
"exception_operators_keyword:runner:serverless": "npm run run-tests:de exceptions/operators_data_types/keyword serverless serverlessEnv",
|
||||
"exception_operators_keyword:qa:serverless": "npm run run-tests:de exceptions/operators_data_types/keyword serverless qaEnv",
|
||||
"exception_operators_keyword:server:ess": "npm run initialize-server:de exceptions/operators_data_types/keyword ess",
|
||||
"exception_operators_keyword:runner:ess": "npm run run-tests:de exceptions/operators_data_types/keyword ess essEnv",
|
||||
"exception_operators_keyword:essentials:server:serverless": "npm run initialize-server:de:basic_essentials exceptions/operators_data_types/keyword serverless",
|
||||
"exception_operators_keyword:essentials:runner:serverless": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/keyword serverless serverlessEnv",
|
||||
"exception_operators_keyword:essentials:qa:serverless": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/keyword serverless qaEnv",
|
||||
"exception_operators_keyword:basic:server:ess": "npm run initialize-server:de:basic_essentials exceptions/operators_data_types/keyword ess",
|
||||
"exception_operators_keyword:basic:runner:ess": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/keyword ess essEnv",
|
||||
|
||||
"exception_operators_ips:server:serverless": "npm run initialize-server:de exceptions/operators_data_types/ips serverless",
|
||||
"exception_operators_ips:runner:serverless": "npm run run-tests:de exceptions/operators_data_types/ips serverless serverlessEnv",
|
||||
"exception_operators_ips:qa:serverless": "npm run run-tests:de exceptions/operators_data_types/ips serverless qaEnv",
|
||||
"exception_operators_ips:server:ess": "npm run initialize-server:de exceptions/operators_data_types/ips ess",
|
||||
"exception_operators_ips:runner:ess": "npm run run-tests:de exceptions/operators_data_types/ips ess essEnv",
|
||||
"exception_operators_ips:essentials:server:serverless": "npm run initialize-server:de:basic_essentials exceptions/operators_data_types/ips serverless",
|
||||
"exception_operators_ips:essentials:runner:serverless": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/ips serverless serverlessEnv",
|
||||
"exception_operators_ips:essentials:qa:serverless": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/ips serverless qaEnv",
|
||||
"exception_operators_ips:basic:server:ess": "npm run initialize-server:de:basic_essentials exceptions/operators_data_types/ips ess",
|
||||
"exception_operators_ips:basic:runner:ess": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/ips ess essEnv",
|
||||
|
||||
"exception_operators_long:server:serverless": "npm run initialize-server:de exceptions/operators_data_types/long serverless",
|
||||
"exception_operators_long:runner:serverless": "npm run run-tests:de exceptions/operators_data_types/long serverless serverlessEnv",
|
||||
"exception_operators_long:qa:serverless": "npm run run-tests:de exceptions/operators_data_types/long serverless qaEnv",
|
||||
"exception_operators_long:server:ess": "npm run initialize-server:de exceptions/operators_data_types/long ess",
|
||||
"exception_operators_long:runner:ess": "npm run run-tests:de exceptions/operators_data_types/long ess essEnv",
|
||||
"exception_operators_long:essentials:server:serverless": "npm run initialize-server:de:basic_essentials exceptions/operators_data_types/long serverless",
|
||||
"exception_operators_long:essentials:runner:serverless": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/long serverless serverlessEnv",
|
||||
"exception_operators_long:essentials:qa:serverless": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/long serverless qaEnv",
|
||||
"exception_operators_long:basic:server:ess": "npm run initialize-server:de:basic_essentials exceptions/operators_data_types/long ess",
|
||||
"exception_operators_long:basic:runner:ess": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/long ess essEnv",
|
||||
|
||||
"exception_operators_text:server:serverless": "npm run initialize-server:de exceptions/operators_data_types/text serverless",
|
||||
"exception_operators_text:runner:serverless": "npm run run-tests:de exceptions/operators_data_types/text serverless serverlessEnv",
|
||||
"exception_operators_text:qa:serverless": "npm run run-tests:de exceptions/operators_data_types/text serverless qaEnv",
|
||||
"exception_operators_text:server:ess": "npm run initialize-server:de exceptions/operators_data_types/text ess",
|
||||
"exception_operators_text:runner:ess": "npm run run-tests:de exceptions/operators_data_types/text ess essEnv",
|
||||
"exception_operators_text:essentials:server:serverless": "npm run initialize-server:de:basic_essentials exceptions/operators_data_types/text serverless",
|
||||
"exception_operators_text:essentials:runner:serverless": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/text serverless serverlessEnv",
|
||||
"exception_operators_text:essentials:qa:serverless": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/text serverless qaEnv",
|
||||
"exception_operators_text:basic:server:ess": "npm run initialize-server:de:basic_essentials exceptions/operators_data_types/text ess",
|
||||
"exception_operators_text:basic:runner:ess": "npm run run-tests:de:basic_essentials exceptions/operators_data_types/text ess essEnv",
|
||||
|
||||
"actions:server:serverless": "npm run initialize-server:de actions serverless",
|
||||
"actions:runner:serverless": "npm run run-tests:de actions serverless serverlessEnv",
|
||||
|
|
|
@ -72,7 +72,6 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
await createAlertsIndex(supertest, log);
|
||||
});
|
||||
after(async () => {
|
||||
// await esArchiver.unload('x-pack/test/functional/es_archives/endpoint/resolver/signals');
|
||||
await deleteAllAlerts(supertest, log, es);
|
||||
});
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import { FtrConfigProviderContext } from '@kbn/test';
|
|||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const functionalConfig = await readConfigFile(
|
||||
require.resolve('../../../../../../../../config/ess/config.base.trial')
|
||||
require.resolve('../../../../../../../../config/ess/config.base.basic')
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -17,7 +17,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
testFiles: [require.resolve('..')],
|
||||
junit: {
|
||||
reportName:
|
||||
'Detection Engine - Exception Operators Date & Numeric Types Integration Tests - ESS Env - Trial License',
|
||||
'Detection Engine - Exception Operators Date & Numeric Types Integration Tests - ESS Env - Basic License',
|
||||
},
|
||||
};
|
||||
}
|
|
@ -5,12 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { createTestConfig } from '../../../../../../../../config/serverless/config.base';
|
||||
import { createTestConfig } from '../../../../../../../../config/serverless/config.base.essentials';
|
||||
|
||||
export default createTestConfig({
|
||||
testFiles: [require.resolve('..')],
|
||||
junit: {
|
||||
reportName:
|
||||
'Detection Engine - Exception Operators Date & Numeric Types Integration Tests - Serverless Env - Complete Tier',
|
||||
'Detection Engine - Exception Operators Date & Numeric Types Integration Tests - Serverless Env - Essentials Tier',
|
||||
},
|
||||
});
|
|
@ -9,7 +9,7 @@ import { FtrConfigProviderContext } from '@kbn/test';
|
|||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const functionalConfig = await readConfigFile(
|
||||
require.resolve('../../../../../../../../config/ess/config.base.trial')
|
||||
require.resolve('../../../../../../../../config/ess/config.base.basic')
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -17,7 +17,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
testFiles: [require.resolve('..')],
|
||||
junit: {
|
||||
reportName:
|
||||
'Detection Engine - Exception Operators IP Types Integration Tests - ESS Env - Trial License',
|
||||
'Detection Engine - Exception Operators IP Types Integration Tests - ESS Env - Basic License',
|
||||
},
|
||||
};
|
||||
}
|
|
@ -5,12 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { createTestConfig } from '../../../../../../../../config/serverless/config.base';
|
||||
import { createTestConfig } from '../../../../../../../../config/serverless/config.base.essentials';
|
||||
|
||||
export default createTestConfig({
|
||||
testFiles: [require.resolve('..')],
|
||||
junit: {
|
||||
reportName:
|
||||
'Detection Engine - Exception Operators IP Types Integration Tests - Serverless Env - Complete Tier',
|
||||
'Detection Engine - Exception Operators IP Types Integration Tests - Serverless Env - Essentials Tier',
|
||||
},
|
||||
});
|
|
@ -9,7 +9,7 @@ import { FtrConfigProviderContext } from '@kbn/test';
|
|||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const functionalConfig = await readConfigFile(
|
||||
require.resolve('../../../../../../../../config/ess/config.base.trial')
|
||||
require.resolve('../../../../../../../../config/ess/config.base.basic')
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -17,7 +17,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
testFiles: [require.resolve('..')],
|
||||
junit: {
|
||||
reportName:
|
||||
'Detection Engine - Exception Operators Keyword Types Integration Tests - ESS Env - Trial License',
|
||||
'Detection Engine - Exception Operators Keyword Types Integration Tests - ESS Env - Basic License',
|
||||
},
|
||||
};
|
||||
}
|
|
@ -5,12 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { createTestConfig } from '../../../../../../../../config/serverless/config.base';
|
||||
import { createTestConfig } from '../../../../../../../../config/serverless/config.base.essentials';
|
||||
|
||||
export default createTestConfig({
|
||||
testFiles: [require.resolve('..')],
|
||||
junit: {
|
||||
reportName:
|
||||
'Detection Engine - Exception Operators Keyword Types Integration Tests - Serverless Env - Complete Tier',
|
||||
'Detection Engine - Exception Operators Keyword Types Integration Tests - Serverless Env - Essentials Tier',
|
||||
},
|
||||
});
|
|
@ -9,7 +9,7 @@ import { FtrConfigProviderContext } from '@kbn/test';
|
|||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const functionalConfig = await readConfigFile(
|
||||
require.resolve('../../../../../../../../config/ess/config.base.trial')
|
||||
require.resolve('../../../../../../../../config/ess/config.base.basic')
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -17,7 +17,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
testFiles: [require.resolve('..')],
|
||||
junit: {
|
||||
reportName:
|
||||
'Detection Engine - Exception Operators Long Types Integration Tests - ESS Env - Trial License',
|
||||
'Detection Engine - Exception Operators Long Types Integration Tests - ESS Env - Basic License',
|
||||
},
|
||||
};
|
||||
}
|
|
@ -5,12 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { createTestConfig } from '../../../../../../../../config/serverless/config.base';
|
||||
import { createTestConfig } from '../../../../../../../../config/serverless/config.base.essentials';
|
||||
|
||||
export default createTestConfig({
|
||||
testFiles: [require.resolve('..')],
|
||||
junit: {
|
||||
reportName:
|
||||
'Detection Engine - Exception Operators Long Types Integration Tests - Serverless Env - Complete Tier',
|
||||
'Detection Engine - Exception Operators Long Types Integration Tests - Serverless Env - Essentials Tier',
|
||||
},
|
||||
});
|
|
@ -9,7 +9,7 @@ import { FtrConfigProviderContext } from '@kbn/test';
|
|||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const functionalConfig = await readConfigFile(
|
||||
require.resolve('../../../../../../../../config/ess/config.base.trial')
|
||||
require.resolve('../../../../../../../../config/ess/config.base.basic')
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -17,7 +17,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
testFiles: [require.resolve('..')],
|
||||
junit: {
|
||||
reportName:
|
||||
'Detection Engine - Exception Operators Text Types Integration Tests - ESS Env - Trial License',
|
||||
'Detection Engine - Exception Operators Text Types Integration Tests - ESS Env - Basic License',
|
||||
},
|
||||
};
|
||||
}
|
|
@ -5,12 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { createTestConfig } from '../../../../../../../../config/serverless/config.base';
|
||||
import { createTestConfig } from '../../../../../../../../config/serverless/config.base.essentials';
|
||||
|
||||
export default createTestConfig({
|
||||
testFiles: [require.resolve('..')],
|
||||
junit: {
|
||||
reportName:
|
||||
'Detection Engine - Exception Operators Text Types Integration Tests - Serverless Env - Complete Tier',
|
||||
'Detection Engine - Exception Operators Text Types Integration Tests - Serverless Env - Essentials Tier',
|
||||
},
|
||||
});
|
|
@ -9,7 +9,7 @@ import { FtrConfigProviderContext } from '@kbn/test';
|
|||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const functionalConfig = await readConfigFile(
|
||||
require.resolve('../../../../../../../config/ess/config.base.trial')
|
||||
require.resolve('../../../../../../../config/ess/config.base.basic')
|
||||
);
|
||||
|
||||
return {
|
||||
|
@ -17,7 +17,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
|||
testFiles: [require.resolve('..')],
|
||||
junit: {
|
||||
reportName:
|
||||
'Detection Engine - Exception Workflows Integration Tests - ESS Env - Trial License',
|
||||
'Detection Engine - Exception Workflows Integration Tests - ESS Env - Basic License',
|
||||
},
|
||||
};
|
||||
}
|
|
@ -5,12 +5,12 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { createTestConfig } from '../../../../../../../config/serverless/config.base';
|
||||
import { createTestConfig } from '../../../../../../../config/serverless/config.base.essentials';
|
||||
|
||||
export default createTestConfig({
|
||||
testFiles: [require.resolve('..')],
|
||||
junit: {
|
||||
reportName:
|
||||
'Detection Engine - Exception Workflows Integration Tests - Serverless Env - Complete Tier',
|
||||
'Detection Engine - Exception Workflows Integration Tests - Serverless Env - Essentials Tier',
|
||||
},
|
||||
});
|
|
@ -6,8 +6,6 @@
|
|||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { Rule } from '@kbn/alerting-plugin/common';
|
||||
import { BaseRuleParams } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_schema';
|
||||
import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants';
|
||||
import {
|
||||
CreateExceptionListSchema,
|
||||
|
@ -16,15 +14,7 @@ import {
|
|||
ExceptionListTypeEnum,
|
||||
} from '@kbn/securitysolution-io-ts-list-types';
|
||||
import { getCreateExceptionListMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock';
|
||||
import {
|
||||
fetchRule,
|
||||
getSimpleRule,
|
||||
createExceptionList,
|
||||
getRuleSOById,
|
||||
createRuleThroughAlertingEndpoint,
|
||||
getRuleSavedObjectWithLegacyInvestigationFields,
|
||||
checkInvestigationFieldSoValue,
|
||||
} from '../../../../utils';
|
||||
import { fetchRule, getSimpleRule, createExceptionList } from '../../../../utils';
|
||||
import {
|
||||
createRule,
|
||||
createAlertsIndex,
|
||||
|
@ -58,7 +48,7 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
const config = getService('config');
|
||||
const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username');
|
||||
|
||||
describe('@serverless @ess create_rule_exception_route', () => {
|
||||
describe('@serverless @ess create "rule_default" exceptions', () => {
|
||||
before(async () => {
|
||||
await createAlertsIndex(supertest, log);
|
||||
});
|
||||
|
@ -254,54 +244,5 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
status_code: 500,
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: When available this tag should be @skipInServerless
|
||||
// This use case is not relevant to serverless.
|
||||
describe('@brokenInServerless legacy investigation_fields', () => {
|
||||
let ruleWithLegacyInvestigationField: Rule<BaseRuleParams>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
ruleWithLegacyInvestigationField = await createRuleThroughAlertingEndpoint(
|
||||
supertest,
|
||||
getRuleSavedObjectWithLegacyInvestigationFields()
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
});
|
||||
|
||||
it('creates and associates a `rule_default` exception list to a rule with a legacy investigation_field', async () => {
|
||||
await supertest
|
||||
.post(`${DETECTION_ENGINE_RULES_URL}/${ruleWithLegacyInvestigationField.id}/exceptions`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({
|
||||
items: [getRuleExceptionItemMock()],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
/**
|
||||
* Confirm type on SO so that it's clear in the tests whether it's expected that
|
||||
* the SO itself is migrated to the inteded object type, or if the transformation is
|
||||
* happening just on the response. In this case, change will
|
||||
* NOT include a migration on SO.
|
||||
*/
|
||||
const {
|
||||
hits: {
|
||||
hits: [{ _source: ruleSO }],
|
||||
},
|
||||
} = await getRuleSOById(es, ruleWithLegacyInvestigationField.id);
|
||||
const isInvestigationFieldMigratedInSo = await checkInvestigationFieldSoValue(ruleSO, {
|
||||
field_names: ['client.address', 'agent.name'],
|
||||
});
|
||||
|
||||
expect(
|
||||
ruleSO?.alert.params.exceptionsList.some((list) => list.type === 'rule_default')
|
||||
).to.eql(true);
|
||||
expect(isInvestigationFieldMigratedInSo).to.eql(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* 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 { Rule } from '@kbn/alerting-plugin/common';
|
||||
import { BaseRuleParams } from '@kbn/security-solution-plugin/server/lib/detection_engine/rule_schema';
|
||||
import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants';
|
||||
import { CreateRuleExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
|
||||
import {
|
||||
getRuleSOById,
|
||||
createRuleThroughAlertingEndpoint,
|
||||
getRuleSavedObjectWithLegacyInvestigationFields,
|
||||
checkInvestigationFieldSoValue,
|
||||
} from '../../../../utils';
|
||||
import {
|
||||
createAlertsIndex,
|
||||
deleteAllRules,
|
||||
deleteAllAlerts,
|
||||
} from '../../../../../../../common/utils/security_solution';
|
||||
import { deleteAllExceptions } from '../../../../../lists_and_exception_lists/utils';
|
||||
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
|
||||
|
||||
const getRuleExceptionItemMock = (): CreateRuleExceptionListItemSchema => ({
|
||||
description: 'Exception item for rule default exception list',
|
||||
entries: [
|
||||
{
|
||||
field: 'some.not.nested.field',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
],
|
||||
name: 'Sample exception item',
|
||||
type: 'simple',
|
||||
});
|
||||
|
||||
export default ({ getService }: FtrProviderContext) => {
|
||||
const supertest = getService('supertest');
|
||||
const log = getService('log');
|
||||
const es = getService('es');
|
||||
|
||||
describe('@ess create rule exception routes, ESS specific logic', () => {
|
||||
before(async () => {
|
||||
await createAlertsIndex(supertest, log);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await deleteAllExceptions(supertest, log);
|
||||
await deleteAllAlerts(supertest, log, es);
|
||||
await deleteAllRules(supertest, log);
|
||||
});
|
||||
|
||||
describe('legacy investigation_fields', () => {
|
||||
let ruleWithLegacyInvestigationField: Rule<BaseRuleParams>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
ruleWithLegacyInvestigationField = await createRuleThroughAlertingEndpoint(
|
||||
supertest,
|
||||
getRuleSavedObjectWithLegacyInvestigationFields()
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
});
|
||||
|
||||
it('creates and associates a `rule_default` exception list to a rule with a legacy investigation_field', async () => {
|
||||
await supertest
|
||||
.post(`${DETECTION_ENGINE_RULES_URL}/${ruleWithLegacyInvestigationField.id}/exceptions`)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({
|
||||
items: [getRuleExceptionItemMock()],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
/**
|
||||
* Confirm type on SO so that it's clear in the tests whether it's expected that
|
||||
* the SO itself is migrated to the inteded object type, or if the transformation is
|
||||
* happening just on the response. In this case, change will
|
||||
* NOT include a migration on SO.
|
||||
*/
|
||||
const {
|
||||
hits: {
|
||||
hits: [{ _source: ruleSO }],
|
||||
},
|
||||
} = await getRuleSOById(es, ruleWithLegacyInvestigationField.id);
|
||||
const isInvestigationFieldMigratedInSo = await checkInvestigationFieldSoValue(ruleSO, {
|
||||
field_names: ['client.address', 'agent.name'],
|
||||
});
|
||||
|
||||
expect(
|
||||
ruleSO?.alert.params.exceptionsList.some((list) => list.type === 'rule_default')
|
||||
).to.eql(true);
|
||||
expect(isInvestigationFieldMigratedInSo).to.eql(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -30,7 +30,7 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
const log = getService('log');
|
||||
const supertestWithoutAuth = getService('supertestWithoutAuth');
|
||||
|
||||
describe('@serverless @ess @brokenInServerless role_based_add_edit_comments', () => {
|
||||
describe('@ess exception item comments', () => {
|
||||
const socManager = ROLES.soc_manager;
|
||||
const detectionAdmin = ROLES.detections_admin;
|
||||
|
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
|
||||
import expect from 'expect';
|
||||
|
||||
import { EXCEPTION_LIST_ITEM_URL, EXCEPTION_LIST_URL } from '@kbn/securitysolution-list-constants';
|
||||
import {
|
||||
getCreateExceptionListDetectionSchemaMock,
|
||||
getCreateExceptionListMinimalSchemaMock,
|
||||
} from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock';
|
||||
import { getCreateExceptionListItemMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_item_schema.mock';
|
||||
import { ROLES } from '@kbn/security-solution-plugin/common/test';
|
||||
import { getUpdateMinimalExceptionListItemSchemaMock } from '@kbn/lists-plugin/common/schemas/request/update_exception_list_item_schema.mock';
|
||||
import { UpdateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
|
||||
import { deleteAllExceptions } from '../../../../../lists_and_exception_lists/utils';
|
||||
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
|
||||
|
||||
export default ({ getService }: FtrProviderContext) => {
|
||||
const supertest = getService('supertest');
|
||||
const log = getService('log');
|
||||
const supertestWithoutAuth = getService('supertestWithoutAuth');
|
||||
|
||||
// @skipInQA purposefully - only running tests in MKI whose failure should block release
|
||||
describe('@serverless @skipInQA exception item comments - serverless specific behavior', () => {
|
||||
describe('Rule Exceptions', () => {
|
||||
afterEach(async () => {
|
||||
await deleteAllExceptions(supertest, log);
|
||||
});
|
||||
|
||||
it('Add comment on a new exception, add another comment has unicode from a different user', async () => {
|
||||
await supertest
|
||||
.post(EXCEPTION_LIST_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(getCreateExceptionListDetectionSchemaMock())
|
||||
.expect(200);
|
||||
|
||||
const { os_types, ...ruleException } = getCreateExceptionListItemMinimalSchemaMock();
|
||||
|
||||
// Add comment by another user
|
||||
await supertestWithoutAuth
|
||||
.post(EXCEPTION_LIST_ITEM_URL)
|
||||
.auth(ROLES.t3_analyst, 'changeme')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send({
|
||||
...ruleException,
|
||||
comments: [{ comment: 'Comment by user@t3_analyst' }],
|
||||
})
|
||||
.expect(200);
|
||||
const { body: items } = await supertest
|
||||
.get(
|
||||
`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${
|
||||
getCreateExceptionListMinimalSchemaMock().list_id
|
||||
}`
|
||||
)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
// Validate the first user comment
|
||||
expect(items.total).toEqual(1);
|
||||
const [item] = items.data;
|
||||
const t3AnalystComments = item.comments;
|
||||
expect(t3AnalystComments.length).toEqual(1);
|
||||
|
||||
expect(t3AnalystComments[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
created_by: 't3_analyst',
|
||||
comment: 'Comment by user@t3_analyst',
|
||||
})
|
||||
);
|
||||
|
||||
const expectedId = item.id;
|
||||
|
||||
// Update exception comment by different user
|
||||
const { item_id: _, ...updateItemWithoutItemId } =
|
||||
getUpdateMinimalExceptionListItemSchemaMock();
|
||||
|
||||
const updatePayload: UpdateExceptionListItemSchema = {
|
||||
...updateItemWithoutItemId,
|
||||
comments: [
|
||||
...(updateItemWithoutItemId.comments || []),
|
||||
{ comment: 'Comment by elastic_serverless' },
|
||||
],
|
||||
id: expectedId,
|
||||
};
|
||||
await supertest
|
||||
.put(EXCEPTION_LIST_ITEM_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(updatePayload)
|
||||
.expect(200);
|
||||
|
||||
const { body: itemsAfterUpdate } = await supertest
|
||||
.get(
|
||||
`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${
|
||||
getCreateExceptionListMinimalSchemaMock().list_id
|
||||
}`
|
||||
)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
const [itemAfterUpdate] = itemsAfterUpdate.data;
|
||||
const comments = itemAfterUpdate.comments;
|
||||
|
||||
expect(comments.length).toEqual(2);
|
||||
|
||||
expect(comments).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
created_by: 't3_analyst',
|
||||
comment: 'Comment by user@t3_analyst',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
created_by: 'elastic_serverless',
|
||||
comment: 'Comment by elastic_serverless',
|
||||
}),
|
||||
])
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('Endpoint Exceptions', () => {
|
||||
afterEach(async () => {
|
||||
await deleteAllExceptions(supertest, log);
|
||||
});
|
||||
|
||||
it('Add comment on a new exception, add another comment has unicode from a different user', async () => {
|
||||
await supertest
|
||||
.post(EXCEPTION_LIST_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(getCreateExceptionListMinimalSchemaMock())
|
||||
.expect(200);
|
||||
|
||||
// Add comment by the t3 analyst
|
||||
await supertestWithoutAuth
|
||||
.post(EXCEPTION_LIST_ITEM_URL)
|
||||
.auth(ROLES.t3_analyst, 'changeme')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send({
|
||||
...getCreateExceptionListItemMinimalSchemaMock(),
|
||||
comments: [{ comment: 'Comment by user@t3_analyst' }],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const { body: items } = await supertest
|
||||
.get(
|
||||
`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${
|
||||
getCreateExceptionListMinimalSchemaMock().list_id
|
||||
}`
|
||||
)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
|
||||
// Validate the first user comment
|
||||
expect(items.total).toEqual(1);
|
||||
const [item] = items.data;
|
||||
const t3AnalystComments = item.comments;
|
||||
expect(t3AnalystComments.length).toEqual(1);
|
||||
|
||||
expect(t3AnalystComments[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
created_by: 't3_analyst',
|
||||
comment: 'Comment by user@t3_analyst',
|
||||
})
|
||||
);
|
||||
|
||||
const expectedId = item.id;
|
||||
|
||||
// Update exception comment by different user
|
||||
const { item_id: _, ...updateItemWithoutItemId } =
|
||||
getUpdateMinimalExceptionListItemSchemaMock();
|
||||
|
||||
const updatePayload: UpdateExceptionListItemSchema = {
|
||||
...updateItemWithoutItemId,
|
||||
comments: [
|
||||
...(updateItemWithoutItemId.comments || []),
|
||||
{ comment: 'Comment by elastic_serverless' },
|
||||
],
|
||||
id: expectedId,
|
||||
};
|
||||
await supertest
|
||||
.put(EXCEPTION_LIST_ITEM_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(updatePayload)
|
||||
.expect(200);
|
||||
|
||||
const { body: itemsAfterUpdate } = await supertest
|
||||
.get(
|
||||
`${EXCEPTION_LIST_ITEM_URL}/_find?list_id=${
|
||||
getCreateExceptionListMinimalSchemaMock().list_id
|
||||
}`
|
||||
)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(200);
|
||||
const [itemAfterUpdate] = itemsAfterUpdate.data;
|
||||
const comments = itemAfterUpdate.comments;
|
||||
|
||||
expect(comments.length).toEqual(2);
|
||||
|
||||
expect(comments).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
created_by: 't3_analyst',
|
||||
comment: 'Comment by user@t3_analyst',
|
||||
}),
|
||||
expect.objectContaining({
|
||||
created_by: 'elastic_serverless',
|
||||
comment: 'Comment by elastic_serverless',
|
||||
}),
|
||||
])
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -37,7 +37,8 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
const log = getService('log');
|
||||
const es = getService('es');
|
||||
|
||||
describe('@serverless @ess Synchronizations', () => {
|
||||
// @skipInQA purposefully - only running tests in MKI whose failure should block release
|
||||
describe('@serverless @ess @skipInQA exceptions data integrity', () => {
|
||||
afterEach(async () => {
|
||||
await deleteAllAlerts(supertest, log, es);
|
||||
await deleteAllRules(supertest, log);
|
|
@ -43,11 +43,11 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
|
||||
after(async () => {
|
||||
await deleteAllAlerts(supertest, log, es);
|
||||
await deleteAllRules(supertest, log);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllExceptions(supertest, log);
|
||||
await deleteAllRules(supertest, log);
|
||||
});
|
||||
|
||||
it('returns empty array per list_id if no references are found', async () => {
|
||||
|
@ -67,6 +67,7 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
.get(DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '1')
|
||||
.set('X-Elastic-Internal-Origin', 'Kibana')
|
||||
.query({
|
||||
ids: `${exceptionList.id}`,
|
||||
list_ids: `${exceptionList.list_id}`,
|
||||
|
@ -121,6 +122,7 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
.get(DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '1')
|
||||
.set('X-Elastic-Internal-Origin', 'Kibana')
|
||||
.query({
|
||||
ids: `1234`,
|
||||
list_ids: `i_dont_exist`,
|
||||
|
@ -168,6 +170,7 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
.get(DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '1')
|
||||
.set('X-Elastic-Internal-Origin', 'Kibana')
|
||||
.query({
|
||||
ids: `${exceptionList.id},${exceptionList2.id}`,
|
||||
list_ids: `${exceptionList.list_id},${exceptionList2.list_id}`,
|
||||
|
@ -217,6 +220,7 @@ export default ({ getService }: FtrProviderContext) => {
|
|||
.get(DETECTION_ENGINE_RULES_EXCEPTIONS_REFERENCE_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '1')
|
||||
.set('X-Elastic-Internal-Origin', 'Kibana')
|
||||
.query({
|
||||
namespace_types: 'single,agnostic',
|
||||
})
|
|
@ -8,11 +8,14 @@ import { FtrProviderContext } from '../../../../../../ftr_provider_context';
|
|||
|
||||
export default function ({ loadTestFile }: FtrProviderContext) {
|
||||
describe('Detection Engine - Exception workflows APIs', function () {
|
||||
loadTestFile(require.resolve('./create_rule_exceptions'));
|
||||
loadTestFile(require.resolve('./create_rule_exceptions'));
|
||||
loadTestFile(require.resolve('./role_based_rule_exceptions_workflows'));
|
||||
loadTestFile(require.resolve('./exception_comments_ess'));
|
||||
loadTestFile(require.resolve('./exception_comments_serverless'));
|
||||
loadTestFile(require.resolve('./create_endpoint_exceptions'));
|
||||
loadTestFile(require.resolve('./role_based_add_edit_comments'));
|
||||
loadTestFile(require.resolve('./rule_exception_synchronizations'));
|
||||
loadTestFile(require.resolve('./create_rule_exceptions_ess'));
|
||||
loadTestFile(require.resolve('./create_rule_exceptions'));
|
||||
loadTestFile(require.resolve('./exceptions_data_integrity'));
|
||||
loadTestFile(require.resolve('./find_rule_exception_references'));
|
||||
loadTestFile(require.resolve('./rule_exceptions_execution'));
|
||||
loadTestFile(require.resolve('./prebuilt_rules'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,402 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
|
||||
import expect from 'expect';
|
||||
|
||||
import { getCreateExceptionListMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock';
|
||||
|
||||
import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants';
|
||||
import { ELASTIC_SECURITY_RULE_ID } from '@kbn/security-solution-plugin/common';
|
||||
|
||||
import {
|
||||
fetchRule,
|
||||
createExceptionList,
|
||||
removeServerGeneratedProperties,
|
||||
downgradeImmutableRule,
|
||||
installMockPrebuiltRules,
|
||||
findImmutableRuleById,
|
||||
getPrebuiltRulesAndTimelinesStatus,
|
||||
SAMPLE_PREBUILT_RULES,
|
||||
} from '../../../../utils';
|
||||
import {
|
||||
createAlertsIndex,
|
||||
deleteAllRules,
|
||||
deleteAllAlerts,
|
||||
} from '../../../../../../../common/utils/security_solution';
|
||||
import { deleteAllExceptions } from '../../../../../lists_and_exception_lists/utils';
|
||||
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
|
||||
|
||||
export default ({ getService }: FtrProviderContext) => {
|
||||
const supertest = getService('supertest');
|
||||
const log = getService('log');
|
||||
const es = getService('es');
|
||||
|
||||
// @skipInQA purposefully - only running tests in MKI whose failure should block release
|
||||
describe('@serverless @ess @skipInQA exceptions workflows for prebuilt rules', () => {
|
||||
describe('creating rules with exceptions', () => {
|
||||
beforeEach(async () => {
|
||||
await createAlertsIndex(supertest, log);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllAlerts(supertest, log, es);
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllExceptions(supertest, log);
|
||||
});
|
||||
|
||||
it('should allow removing an exception list from an immutable rule through patch', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to use
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRule.exceptions_list.length).toBeGreaterThan(0); // make sure we have at least one exceptions_list
|
||||
|
||||
// remove the exceptions list as a user is allowed to remove it from an immutable rule
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({ rule_id: ELASTIC_SECURITY_RULE_ID, exceptions_list: [] })
|
||||
.expect(200);
|
||||
|
||||
const immutableRuleSecondTime = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRuleSecondTime.exceptions_list.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should allow adding a second exception list to an immutable rule through patch', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
const { id, list_id, namespace_type, type } = await createExceptionList(
|
||||
supertest,
|
||||
log,
|
||||
getCreateExceptionListMinimalSchemaMock()
|
||||
);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to use
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRule.exceptions_list.length).toBeGreaterThan(0); // make sure we have at least one
|
||||
|
||||
// add a second exceptions list as a user is allowed to add a second list to an immutable rule
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({
|
||||
rule_id: ELASTIC_SECURITY_RULE_ID,
|
||||
exceptions_list: [
|
||||
...immutableRule.exceptions_list,
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const immutableRuleSecondTime = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
|
||||
expect(immutableRuleSecondTime.exceptions_list.length).toEqual(2);
|
||||
});
|
||||
|
||||
it('should override any updates to pre-packaged rules if the user removes the exception list through the API but the new version of a rule has an exception list again', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to use
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRule.exceptions_list.length).toBeGreaterThan(0); // make sure we have at least one
|
||||
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({ rule_id: ELASTIC_SECURITY_RULE_ID, exceptions_list: [] })
|
||||
.expect(200);
|
||||
|
||||
await downgradeImmutableRule(es, log, ELASTIC_SECURITY_RULE_ID);
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
const immutableRuleSecondTime = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
|
||||
// We should have a length of 1 and it should be the same as our original before we tried to remove it using patch
|
||||
expect(immutableRuleSecondTime.exceptions_list.length).toEqual(1);
|
||||
expect(immutableRuleSecondTime.exceptions_list).toEqual(immutableRule.exceptions_list);
|
||||
});
|
||||
|
||||
it('should merge back an exceptions_list if it was removed from the immutable rule through PATCH', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
const { id, list_id, namespace_type, type } = await createExceptionList(
|
||||
supertest,
|
||||
log,
|
||||
getCreateExceptionListMinimalSchemaMock()
|
||||
);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to ensure does not stomp on our existing rule
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRule.exceptions_list.length).toBeGreaterThan(0); // make sure we have at least one
|
||||
|
||||
// remove the exception list and only have a single list that is not an endpoint_list
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({
|
||||
rule_id: ELASTIC_SECURITY_RULE_ID,
|
||||
exceptions_list: [
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await downgradeImmutableRule(es, log, ELASTIC_SECURITY_RULE_ID);
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
const immutableRuleSecondTime = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
|
||||
expect(immutableRuleSecondTime.exceptions_list).toEqual([
|
||||
...immutableRule.exceptions_list,
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should NOT add an extra exceptions_list that already exists on a rule during an upgrade', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to ensure does not stomp on our existing rule
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRule.exceptions_list.length).toBeGreaterThan(0); // make sure we have at least one
|
||||
|
||||
await downgradeImmutableRule(es, log, ELASTIC_SECURITY_RULE_ID);
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
const immutableRuleSecondTime = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
|
||||
// The installed rule should have both the original immutable exceptions list back and the
|
||||
// new list the user added.
|
||||
expect(immutableRuleSecondTime.exceptions_list).toEqual([...immutableRule.exceptions_list]);
|
||||
});
|
||||
|
||||
it('should NOT allow updates to pre-packaged rules to overwrite existing exception based rules when the user adds an additional exception list', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
const { id, list_id, namespace_type, type } = await createExceptionList(
|
||||
supertest,
|
||||
log,
|
||||
getCreateExceptionListMinimalSchemaMock()
|
||||
);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to ensure does not stomp on our existing rule
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
|
||||
// add a second exceptions list as a user is allowed to add a second list to an immutable rule
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({
|
||||
rule_id: ELASTIC_SECURITY_RULE_ID,
|
||||
exceptions_list: [
|
||||
...immutableRule.exceptions_list,
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await downgradeImmutableRule(es, log, ELASTIC_SECURITY_RULE_ID);
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
const immutableRuleSecondTime = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
|
||||
// It should be the same as what the user added originally
|
||||
expect(immutableRuleSecondTime.exceptions_list).toEqual([
|
||||
...immutableRule.exceptions_list,
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not remove any exceptions added to a pre-packaged/immutable rule during an update if that rule has no existing exception lists', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
// Create a new exception list
|
||||
const { id, list_id, namespace_type, type } = await createExceptionList(
|
||||
supertest,
|
||||
log,
|
||||
getCreateExceptionListMinimalSchemaMock()
|
||||
);
|
||||
|
||||
// Find a rule without exceptions_list
|
||||
const ruleWithoutExceptionList = SAMPLE_PREBUILT_RULES.find(
|
||||
(rule) => !rule['security-rule'].exceptions_list
|
||||
);
|
||||
const ruleId = ruleWithoutExceptionList?.['security-rule'].rule_id;
|
||||
if (!ruleId) {
|
||||
throw new Error('Cannot find a rule without exceptions_list in the sample data');
|
||||
}
|
||||
|
||||
const immutableRule = await fetchRule(supertest, { ruleId });
|
||||
expect(immutableRule.exceptions_list.length).toEqual(0); // make sure we have no exceptions_list
|
||||
|
||||
// add a second exceptions list as a user is allowed to add a second list to an immutable rule
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({
|
||||
rule_id: ruleId,
|
||||
exceptions_list: [
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await downgradeImmutableRule(es, log, ruleId);
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
const immutableRuleSecondTime = await fetchRule(supertest, { ruleId });
|
||||
|
||||
expect(immutableRuleSecondTime.exceptions_list).toEqual([
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not change the immutable tags when adding a second exception list to an immutable rule through patch', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
const { id, list_id, namespace_type, type } = await createExceptionList(
|
||||
supertest,
|
||||
log,
|
||||
getCreateExceptionListMinimalSchemaMock()
|
||||
);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to use
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRule.exceptions_list.length).toBeGreaterThan(0); // make sure we have at least one
|
||||
|
||||
// add a second exceptions list as a user is allowed to add a second list to an immutable rule
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({
|
||||
rule_id: ELASTIC_SECURITY_RULE_ID,
|
||||
exceptions_list: [
|
||||
...immutableRule.exceptions_list,
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const body = await findImmutableRuleById(supertest, log, ELASTIC_SECURITY_RULE_ID);
|
||||
expect(body.data.length).toEqual(1); // should have only one length to the data set, otherwise we have duplicates or the tags were removed and that is incredibly bad.
|
||||
|
||||
const bodyToCompare = removeServerGeneratedProperties(body.data[0]);
|
||||
expect(bodyToCompare.rule_id).toEqual(immutableRule.rule_id); // Rule id should not change with a a patch
|
||||
expect(bodyToCompare.immutable).toEqual(immutableRule.immutable); // Immutable should always stay the same which is true and never flip to false.
|
||||
expect(bodyToCompare.version).toEqual(immutableRule.version); // The version should never update on a patch
|
||||
});
|
||||
|
||||
it('should not change count of prepacked rules when adding a second exception list to an immutable rule through patch. If this fails, suspect the immutable tags are not staying on the rule correctly.', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
const { id, list_id, namespace_type, type } = await createExceptionList(
|
||||
supertest,
|
||||
log,
|
||||
getCreateExceptionListMinimalSchemaMock()
|
||||
);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to use
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRule.exceptions_list.length).toBeGreaterThan(0); // make sure we have at least one
|
||||
|
||||
// add a second exceptions list as a user is allowed to add a second list to an immutable rule
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({
|
||||
rule_id: ELASTIC_SECURITY_RULE_ID,
|
||||
exceptions_list: [
|
||||
...immutableRule.exceptions_list,
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const status = await getPrebuiltRulesAndTimelinesStatus(es, supertest);
|
||||
expect(status.rules_not_installed).toEqual(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -0,0 +1,479 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
|
||||
import expect from 'expect';
|
||||
import type { CreateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
|
||||
import { LIST_URL } from '@kbn/securitysolution-list-constants';
|
||||
import type {
|
||||
RuleCreateProps,
|
||||
EqlRuleCreateProps,
|
||||
QueryRuleCreateProps,
|
||||
ThreatMatchRuleCreateProps,
|
||||
ThresholdRuleCreateProps,
|
||||
} from '@kbn/security-solution-plugin/common/api/detection_engine';
|
||||
import { getCreateExceptionListItemMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_item_schema.mock';
|
||||
import { getCreateExceptionListMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock';
|
||||
|
||||
import { EsArchivePathBuilder } from '../../../../../../es_archive_path_builder';
|
||||
import {
|
||||
getSimpleRule,
|
||||
createExceptionList,
|
||||
createExceptionListItem,
|
||||
getThresholdRuleForAlertTesting,
|
||||
getOpenAlerts,
|
||||
createRuleWithExceptionEntries,
|
||||
getEqlRuleForAlertTesting,
|
||||
} from '../../../../utils';
|
||||
import {
|
||||
createAlertsIndex,
|
||||
createRule,
|
||||
deleteAllRules,
|
||||
waitForRuleSuccess,
|
||||
waitForAlertsToBePresent,
|
||||
getAlertsByIds,
|
||||
deleteAllAlerts,
|
||||
} from '../../../../../../../common/utils/security_solution';
|
||||
import {
|
||||
createListsIndex,
|
||||
deleteAllExceptions,
|
||||
deleteListsIndex,
|
||||
importFile,
|
||||
} from '../../../../../lists_and_exception_lists/utils';
|
||||
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
|
||||
|
||||
export default ({ getService }: FtrProviderContext) => {
|
||||
const supertest = getService('supertest');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const log = getService('log');
|
||||
const es = getService('es');
|
||||
// TODO: add a new service for loading archiver files similar to "getService('es')"
|
||||
const config = getService('config');
|
||||
const isServerless = config.get('serverless');
|
||||
const dataPathBuilder = new EsArchivePathBuilder(isServerless);
|
||||
const path = dataPathBuilder.getPath('auditbeat/hosts');
|
||||
|
||||
describe('@serverless @ess rule exceptions execution', () => {
|
||||
before(async () => {
|
||||
await esArchiver.load(path);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await esArchiver.unload(path);
|
||||
});
|
||||
|
||||
describe('creating rules with exceptions', () => {
|
||||
beforeEach(async () => {
|
||||
await createAlertsIndex(supertest, log);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllAlerts(supertest, log, es);
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllExceptions(supertest, log);
|
||||
});
|
||||
|
||||
it('should be able to execute against an exception list that does not include valid entries and get back 10 alerts', async () => {
|
||||
const { id, list_id, namespace_type, type } = await createExceptionList(
|
||||
supertest,
|
||||
log,
|
||||
getCreateExceptionListMinimalSchemaMock()
|
||||
);
|
||||
|
||||
const exceptionListItem: CreateExceptionListItemSchema = {
|
||||
...getCreateExceptionListItemMinimalSchemaMock(),
|
||||
entries: [
|
||||
{
|
||||
field: 'some.none.existent.field', // non-existent field where we should not exclude anything
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
],
|
||||
};
|
||||
await createExceptionListItem(supertest, log, exceptionListItem);
|
||||
|
||||
const ruleWithException: RuleCreateProps = {
|
||||
name: 'Simple Rule Query',
|
||||
description: 'Simple Rule Query',
|
||||
enabled: true,
|
||||
risk_score: 1,
|
||||
rule_id: 'rule-1',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'query',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: 'host.name: "suricata-sensor-amsterdam"',
|
||||
exceptions_list: [
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
};
|
||||
const { id: createdId } = await createRule(supertest, log, ruleWithException);
|
||||
await waitForRuleSuccess({ supertest, log, id: createdId });
|
||||
await waitForAlertsToBePresent(supertest, log, 10, [createdId]);
|
||||
const alertsOpen = await getAlertsByIds(supertest, log, [createdId]);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(10);
|
||||
});
|
||||
|
||||
it('should be able to execute against an exception list that does include valid entries and get back 0 alerts', async () => {
|
||||
const rule: QueryRuleCreateProps = {
|
||||
name: 'Simple Rule Query',
|
||||
description: 'Simple Rule Query',
|
||||
enabled: true,
|
||||
risk_score: 1,
|
||||
rule_id: 'rule-1',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'query',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: 'host.name: "suricata-sensor-amsterdam"',
|
||||
};
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.name', // This matches the query above which will exclude everything
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'suricata-sensor-amsterdam',
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should be able to execute against an exception list that does include valid case sensitive entries and get back 0 alerts', async () => {
|
||||
const rule: QueryRuleCreateProps = {
|
||||
name: 'Simple Rule Query',
|
||||
description: 'Simple Rule Query',
|
||||
enabled: true,
|
||||
risk_score: 1,
|
||||
rule_id: 'rule-1',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'query',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: 'host.name: "suricata-sensor-amsterdam"',
|
||||
};
|
||||
const rule2: QueryRuleCreateProps = {
|
||||
name: 'Simple Rule Query',
|
||||
description: 'Simple Rule Query',
|
||||
enabled: true,
|
||||
risk_score: 1,
|
||||
rule_id: 'rule-2',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'query',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: 'host.name: "suricata-sensor-amsterdam"',
|
||||
};
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.os.name',
|
||||
operator: 'included',
|
||||
type: 'match_any',
|
||||
value: ['ubuntu'],
|
||||
},
|
||||
],
|
||||
]);
|
||||
const createdRule2 = await createRuleWithExceptionEntries(supertest, log, rule2, [
|
||||
[
|
||||
{
|
||||
field: 'host.os.name', // This matches the query above which will exclude everything
|
||||
operator: 'included',
|
||||
type: 'match_any',
|
||||
value: ['ubuntu', 'Ubuntu'],
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
const alertsOpen2 = await getOpenAlerts(supertest, log, es, createdRule2);
|
||||
// Expect alerts here because all values are "Ubuntu"
|
||||
// and exception is one of ["ubuntu"]
|
||||
expect(alertsOpen.hits.hits.length).toEqual(10);
|
||||
// Expect no alerts here because all values are "Ubuntu"
|
||||
// and exception is one of ["ubuntu", "Ubuntu"]
|
||||
expect(alertsOpen2.hits.hits.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('generates no alerts when an exception is added for an EQL rule', async () => {
|
||||
const rule: EqlRuleCreateProps = {
|
||||
...getEqlRuleForAlertTesting(['auditbeat-*']),
|
||||
query: 'configuration where agent.id=="a1d7b39c-f898-4dbe-a761-efb61939302d"',
|
||||
};
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.id',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: '8cc95778cce5407c809480e8e32ad76b',
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('generates no alerts when an exception is added for a threshold rule', async () => {
|
||||
const rule: ThresholdRuleCreateProps = {
|
||||
...getThresholdRuleForAlertTesting(['auditbeat-*']),
|
||||
threshold: {
|
||||
field: 'host.id',
|
||||
value: 700,
|
||||
},
|
||||
};
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.id',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: '8cc95778cce5407c809480e8e32ad76b',
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('generates no alerts when an exception is added for a threat match rule', async () => {
|
||||
const rule: ThreatMatchRuleCreateProps = {
|
||||
description: 'Detecting root and admin users',
|
||||
name: 'Query with a rule id',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'threat_match',
|
||||
risk_score: 55,
|
||||
language: 'kuery',
|
||||
rule_id: 'rule-1',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: '*:*',
|
||||
threat_query: 'source.ip: "188.166.120.93"', // narrow things down with a query to a specific source ip
|
||||
threat_index: ['auditbeat-*'], // We use auditbeat as both the matching index and the threat list for simplicity
|
||||
threat_mapping: [
|
||||
// We match host.name against host.name
|
||||
{
|
||||
entries: [
|
||||
{
|
||||
field: 'host.name',
|
||||
value: 'host.name',
|
||||
type: 'mapping',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
threat_filters: [],
|
||||
};
|
||||
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'source.ip',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: '188.166.120.93',
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
describe('rules with value list exceptions', () => {
|
||||
beforeEach(async () => {
|
||||
await createListsIndex(supertest, log);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteListsIndex(supertest, log);
|
||||
});
|
||||
|
||||
it('generates no alerts when a value list exception is added for a query rule', async () => {
|
||||
const valueListId = 'value-list-id.txt';
|
||||
await importFile(supertest, log, 'keyword', ['suricata-sensor-amsterdam'], valueListId);
|
||||
const rule: QueryRuleCreateProps = {
|
||||
name: 'Simple Rule Query',
|
||||
description: 'Simple Rule Query',
|
||||
enabled: true,
|
||||
risk_score: 1,
|
||||
rule_id: 'rule-1',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'query',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: 'host.name: "suricata-sensor-amsterdam"',
|
||||
};
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.name',
|
||||
operator: 'included',
|
||||
type: 'list',
|
||||
list: {
|
||||
id: valueListId,
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('generates no alerts when a value list exception is added for a threat match rule', async () => {
|
||||
const valueListId = 'value-list-id.txt';
|
||||
await importFile(supertest, log, 'keyword', ['zeek-sensor-amsterdam'], valueListId);
|
||||
const rule: ThreatMatchRuleCreateProps = {
|
||||
description: 'Detecting root and admin users',
|
||||
name: 'Query with a rule id',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'threat_match',
|
||||
risk_score: 55,
|
||||
language: 'kuery',
|
||||
rule_id: 'rule-1',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: '*:*',
|
||||
threat_query: 'source.ip: "188.166.120.93"', // narrow things down with a query to a specific source ip
|
||||
threat_index: ['auditbeat-*'], // We use auditbeat as both the matching index and the threat list for simplicity
|
||||
threat_mapping: [
|
||||
// We match host.name against host.name
|
||||
{
|
||||
entries: [
|
||||
{
|
||||
field: 'host.name',
|
||||
value: 'host.name',
|
||||
type: 'mapping',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
threat_filters: [],
|
||||
};
|
||||
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.name',
|
||||
operator: 'included',
|
||||
type: 'list',
|
||||
list: {
|
||||
id: valueListId,
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('generates no alerts when a value list exception is added for a threshold rule', async () => {
|
||||
const valueListId = 'value-list-id.txt';
|
||||
await importFile(supertest, log, 'keyword', ['zeek-sensor-amsterdam'], valueListId);
|
||||
const rule: ThresholdRuleCreateProps = {
|
||||
description: 'Detecting root and admin users',
|
||||
name: 'Query with a rule id',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'threshold',
|
||||
risk_score: 55,
|
||||
language: 'kuery',
|
||||
rule_id: 'rule-1',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: 'host.name: "zeek-sensor-amsterdam"',
|
||||
threshold: {
|
||||
field: 'host.name',
|
||||
value: 1,
|
||||
},
|
||||
};
|
||||
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.name',
|
||||
operator: 'included',
|
||||
type: 'list',
|
||||
list: {
|
||||
id: valueListId,
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('generates no alerts when a value list exception is added for an EQL rule', async () => {
|
||||
const valueListId = 'value-list-id.txt';
|
||||
await importFile(supertest, log, 'keyword', ['zeek-sensor-amsterdam'], valueListId);
|
||||
const rule: EqlRuleCreateProps = {
|
||||
...getEqlRuleForAlertTesting(['auditbeat-*']),
|
||||
query: 'configuration where host.name=="zeek-sensor-amsterdam"',
|
||||
};
|
||||
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.name',
|
||||
operator: 'included',
|
||||
type: 'list',
|
||||
list: {
|
||||
id: valueListId,
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
it('should Not allow deleting value list when there are references and ignoreReferences is false', async () => {
|
||||
const valueListId = 'value-list-id.txt';
|
||||
await importFile(supertest, log, 'keyword', ['suricata-sensor-amsterdam'], valueListId);
|
||||
const rule: QueryRuleCreateProps = {
|
||||
...getSimpleRule(),
|
||||
query: 'host.name: "suricata-sensor-amsterdam"',
|
||||
};
|
||||
await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.name',
|
||||
operator: 'included',
|
||||
type: 'list',
|
||||
list: {
|
||||
id: valueListId,
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
const deleteReferences = false;
|
||||
const ignoreReferences = false;
|
||||
|
||||
// Delete the value list
|
||||
await supertest
|
||||
.delete(
|
||||
`${LIST_URL}?deleteReferences=${deleteReferences}&id=${valueListId}&ignoreReferences=${ignoreReferences}`
|
||||
)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(409);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -1,984 +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.
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
|
||||
import expect from 'expect';
|
||||
import type { CreateExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
|
||||
import {
|
||||
EXCEPTION_LIST_ITEM_URL,
|
||||
EXCEPTION_LIST_URL,
|
||||
LIST_URL,
|
||||
} from '@kbn/securitysolution-list-constants';
|
||||
import type {
|
||||
RuleCreateProps,
|
||||
EqlRuleCreateProps,
|
||||
QueryRuleCreateProps,
|
||||
ThreatMatchRuleCreateProps,
|
||||
ThresholdRuleCreateProps,
|
||||
} from '@kbn/security-solution-plugin/common/api/detection_engine';
|
||||
import { getCreateExceptionListItemMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_item_schema.mock';
|
||||
import { getCreateExceptionListMinimalSchemaMock } from '@kbn/lists-plugin/common/schemas/request/create_exception_list_schema.mock';
|
||||
|
||||
import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants';
|
||||
import { ROLES } from '@kbn/security-solution-plugin/common/test';
|
||||
import { ELASTIC_SECURITY_RULE_ID } from '@kbn/security-solution-plugin/common';
|
||||
|
||||
import { EsArchivePathBuilder } from '../../../../../../es_archive_path_builder';
|
||||
import {
|
||||
fetchRule,
|
||||
getSimpleRule,
|
||||
createExceptionList,
|
||||
createExceptionListItem,
|
||||
getThresholdRuleForAlertTesting,
|
||||
getSimpleRuleOutput,
|
||||
removeServerGeneratedProperties,
|
||||
downgradeImmutableRule,
|
||||
installMockPrebuiltRules,
|
||||
findImmutableRuleById,
|
||||
getPrebuiltRulesAndTimelinesStatus,
|
||||
getOpenAlerts,
|
||||
createRuleWithExceptionEntries,
|
||||
getEqlRuleForAlertTesting,
|
||||
SAMPLE_PREBUILT_RULES,
|
||||
updateUsername,
|
||||
} from '../../../../utils';
|
||||
import {
|
||||
createAlertsIndex,
|
||||
createRule,
|
||||
deleteAllRules,
|
||||
waitForRuleSuccess,
|
||||
waitForAlertsToBePresent,
|
||||
getAlertsByIds,
|
||||
deleteAllAlerts,
|
||||
} from '../../../../../../../common/utils/security_solution';
|
||||
import {
|
||||
createListsIndex,
|
||||
deleteAllExceptions,
|
||||
deleteListsIndex,
|
||||
importFile,
|
||||
} from '../../../../../lists_and_exception_lists/utils';
|
||||
import {
|
||||
createUserAndRole,
|
||||
deleteUserAndRole,
|
||||
} from '../../../../../../../common/services/security_solution';
|
||||
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
|
||||
|
||||
export default ({ getService }: FtrProviderContext) => {
|
||||
const supertest = getService('supertest');
|
||||
const supertestWithoutAuth = getService('supertestWithoutAuth');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const log = getService('log');
|
||||
const es = getService('es');
|
||||
// TODO: add a new service for loading archiver files similar to "getService('es')"
|
||||
const config = getService('config');
|
||||
const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username');
|
||||
const isServerless = config.get('serverless');
|
||||
const dataPathBuilder = new EsArchivePathBuilder(isServerless);
|
||||
const path = dataPathBuilder.getPath('auditbeat/hosts');
|
||||
|
||||
describe('@serverless @ess role_based_rule_exceptions_workflows', () => {
|
||||
before(async () => {
|
||||
await esArchiver.load(path);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await esArchiver.unload(path);
|
||||
});
|
||||
|
||||
describe('creating rules with exceptions', () => {
|
||||
beforeEach(async () => {
|
||||
await createAlertsIndex(supertest, log);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllAlerts(supertest, log, es);
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllExceptions(supertest, log);
|
||||
});
|
||||
|
||||
describe('elastic admin', () => {
|
||||
it('should create a single rule with a rule_id and add an exception list to the rule', async () => {
|
||||
const {
|
||||
body: { id, list_id, namespace_type, type },
|
||||
} = await supertest
|
||||
.post(EXCEPTION_LIST_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(getCreateExceptionListMinimalSchemaMock())
|
||||
.expect(200);
|
||||
|
||||
const ruleWithException: RuleCreateProps = {
|
||||
...getSimpleRule(),
|
||||
exceptions_list: [
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
};
|
||||
const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME);
|
||||
const rule = await createRule(supertest, log, ruleWithException);
|
||||
const expected = {
|
||||
...expectedRule,
|
||||
exceptions_list: [
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
};
|
||||
const bodyToCompare = removeServerGeneratedProperties(rule);
|
||||
expect(bodyToCompare).toEqual(expected);
|
||||
});
|
||||
|
||||
it('should create a single rule with an exception list and validate it ran successfully', async () => {
|
||||
const {
|
||||
body: { id, list_id, namespace_type, type },
|
||||
} = await supertest
|
||||
.post(EXCEPTION_LIST_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(getCreateExceptionListMinimalSchemaMock())
|
||||
.expect(200);
|
||||
|
||||
const ruleWithException: RuleCreateProps = {
|
||||
...getSimpleRule(),
|
||||
enabled: true,
|
||||
exceptions_list: [
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const rule = await createRule(supertest, log, ruleWithException);
|
||||
await waitForRuleSuccess({ supertest, log, id: rule.id });
|
||||
const bodyToCompare = removeServerGeneratedProperties(rule);
|
||||
const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME);
|
||||
|
||||
const expected = {
|
||||
...expectedRule,
|
||||
enabled: true,
|
||||
exceptions_list: [
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
};
|
||||
expect(bodyToCompare).toEqual(expected);
|
||||
});
|
||||
|
||||
it('@skipInQA should allow removing an exception list from an immutable rule through patch', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to use
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRule.exceptions_list.length).toBeGreaterThan(0); // make sure we have at least one exceptions_list
|
||||
|
||||
// remove the exceptions list as a user is allowed to remove it from an immutable rule
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({ rule_id: ELASTIC_SECURITY_RULE_ID, exceptions_list: [] })
|
||||
.expect(200);
|
||||
|
||||
const immutableRuleSecondTime = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRuleSecondTime.exceptions_list.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('@skipInQA should allow adding a second exception list to an immutable rule through patch', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
const { id, list_id, namespace_type, type } = await createExceptionList(
|
||||
supertest,
|
||||
log,
|
||||
getCreateExceptionListMinimalSchemaMock()
|
||||
);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to use
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRule.exceptions_list.length).toBeGreaterThan(0); // make sure we have at least one
|
||||
|
||||
// add a second exceptions list as a user is allowed to add a second list to an immutable rule
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({
|
||||
rule_id: ELASTIC_SECURITY_RULE_ID,
|
||||
exceptions_list: [
|
||||
...immutableRule.exceptions_list,
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const immutableRuleSecondTime = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
|
||||
expect(immutableRuleSecondTime.exceptions_list.length).toEqual(2);
|
||||
});
|
||||
|
||||
it('@skipInQA should override any updates to pre-packaged rules if the user removes the exception list through the API but the new version of a rule has an exception list again', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to use
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRule.exceptions_list.length).toBeGreaterThan(0); // make sure we have at least one
|
||||
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({ rule_id: ELASTIC_SECURITY_RULE_ID, exceptions_list: [] })
|
||||
.expect(200);
|
||||
|
||||
await downgradeImmutableRule(es, log, ELASTIC_SECURITY_RULE_ID);
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
const immutableRuleSecondTime = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
|
||||
// We should have a length of 1 and it should be the same as our original before we tried to remove it using patch
|
||||
expect(immutableRuleSecondTime.exceptions_list.length).toEqual(1);
|
||||
expect(immutableRuleSecondTime.exceptions_list).toEqual(immutableRule.exceptions_list);
|
||||
});
|
||||
|
||||
it('@skipInQA should merge back an exceptions_list if it was removed from the immutable rule through PATCH', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
const { id, list_id, namespace_type, type } = await createExceptionList(
|
||||
supertest,
|
||||
log,
|
||||
getCreateExceptionListMinimalSchemaMock()
|
||||
);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to ensure does not stomp on our existing rule
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRule.exceptions_list.length).toBeGreaterThan(0); // make sure we have at least one
|
||||
|
||||
// remove the exception list and only have a single list that is not an endpoint_list
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({
|
||||
rule_id: ELASTIC_SECURITY_RULE_ID,
|
||||
exceptions_list: [
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await downgradeImmutableRule(es, log, ELASTIC_SECURITY_RULE_ID);
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
const immutableRuleSecondTime = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
|
||||
expect(immutableRuleSecondTime.exceptions_list).toEqual([
|
||||
...immutableRule.exceptions_list,
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('@skipInQA should NOT add an extra exceptions_list that already exists on a rule during an upgrade', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to ensure does not stomp on our existing rule
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRule.exceptions_list.length).toBeGreaterThan(0); // make sure we have at least one
|
||||
|
||||
await downgradeImmutableRule(es, log, ELASTIC_SECURITY_RULE_ID);
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
const immutableRuleSecondTime = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
|
||||
// The installed rule should have both the original immutable exceptions list back and the
|
||||
// new list the user added.
|
||||
expect(immutableRuleSecondTime.exceptions_list).toEqual([
|
||||
...immutableRule.exceptions_list,
|
||||
]);
|
||||
});
|
||||
|
||||
it('@skipInQA should NOT allow updates to pre-packaged rules to overwrite existing exception based rules when the user adds an additional exception list', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
const { id, list_id, namespace_type, type } = await createExceptionList(
|
||||
supertest,
|
||||
log,
|
||||
getCreateExceptionListMinimalSchemaMock()
|
||||
);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to ensure does not stomp on our existing rule
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
|
||||
// add a second exceptions list as a user is allowed to add a second list to an immutable rule
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({
|
||||
rule_id: ELASTIC_SECURITY_RULE_ID,
|
||||
exceptions_list: [
|
||||
...immutableRule.exceptions_list,
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await downgradeImmutableRule(es, log, ELASTIC_SECURITY_RULE_ID);
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
const immutableRuleSecondTime = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
|
||||
// It should be the same as what the user added originally
|
||||
expect(immutableRuleSecondTime.exceptions_list).toEqual([
|
||||
...immutableRule.exceptions_list,
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('@skipInQA should not remove any exceptions added to a pre-packaged/immutable rule during an update if that rule has no existing exception lists', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
// Create a new exception list
|
||||
const { id, list_id, namespace_type, type } = await createExceptionList(
|
||||
supertest,
|
||||
log,
|
||||
getCreateExceptionListMinimalSchemaMock()
|
||||
);
|
||||
|
||||
// Find a rule without exceptions_list
|
||||
const ruleWithoutExceptionList = SAMPLE_PREBUILT_RULES.find(
|
||||
(rule) => !rule['security-rule'].exceptions_list
|
||||
);
|
||||
const ruleId = ruleWithoutExceptionList?.['security-rule'].rule_id;
|
||||
if (!ruleId) {
|
||||
throw new Error('Cannot find a rule without exceptions_list in the sample data');
|
||||
}
|
||||
|
||||
const immutableRule = await fetchRule(supertest, { ruleId });
|
||||
expect(immutableRule.exceptions_list.length).toEqual(0); // make sure we have no exceptions_list
|
||||
|
||||
// add a second exceptions list as a user is allowed to add a second list to an immutable rule
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({
|
||||
rule_id: ruleId,
|
||||
exceptions_list: [
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
await downgradeImmutableRule(es, log, ruleId);
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
const immutableRuleSecondTime = await fetchRule(supertest, { ruleId });
|
||||
|
||||
expect(immutableRuleSecondTime.exceptions_list).toEqual([
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it('@skipInQA should not change the immutable tags when adding a second exception list to an immutable rule through patch', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
const { id, list_id, namespace_type, type } = await createExceptionList(
|
||||
supertest,
|
||||
log,
|
||||
getCreateExceptionListMinimalSchemaMock()
|
||||
);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to use
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRule.exceptions_list.length).toBeGreaterThan(0); // make sure we have at least one
|
||||
|
||||
// add a second exceptions list as a user is allowed to add a second list to an immutable rule
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({
|
||||
rule_id: ELASTIC_SECURITY_RULE_ID,
|
||||
exceptions_list: [
|
||||
...immutableRule.exceptions_list,
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const body = await findImmutableRuleById(supertest, log, ELASTIC_SECURITY_RULE_ID);
|
||||
expect(body.data.length).toEqual(1); // should have only one length to the data set, otherwise we have duplicates or the tags were removed and that is incredibly bad.
|
||||
|
||||
const bodyToCompare = removeServerGeneratedProperties(body.data[0]);
|
||||
expect(bodyToCompare.rule_id).toEqual(immutableRule.rule_id); // Rule id should not change with a a patch
|
||||
expect(bodyToCompare.immutable).toEqual(immutableRule.immutable); // Immutable should always stay the same which is true and never flip to false.
|
||||
expect(bodyToCompare.version).toEqual(immutableRule.version); // The version should never update on a patch
|
||||
});
|
||||
|
||||
it('@skipInQA should not change count of prepacked rules when adding a second exception list to an immutable rule through patch. If this fails, suspect the immutable tags are not staying on the rule correctly.', async () => {
|
||||
await installMockPrebuiltRules(supertest, es);
|
||||
|
||||
const { id, list_id, namespace_type, type } = await createExceptionList(
|
||||
supertest,
|
||||
log,
|
||||
getCreateExceptionListMinimalSchemaMock()
|
||||
);
|
||||
|
||||
// This rule has an existing exceptions_list that we are going to use
|
||||
const immutableRule = await fetchRule(supertest, {
|
||||
ruleId: ELASTIC_SECURITY_RULE_ID,
|
||||
});
|
||||
expect(immutableRule.exceptions_list.length).toBeGreaterThan(0); // make sure we have at least one
|
||||
|
||||
// add a second exceptions list as a user is allowed to add a second list to an immutable rule
|
||||
await supertest
|
||||
.patch(DETECTION_ENGINE_RULES_URL)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set('elastic-api-version', '2023-10-31')
|
||||
.send({
|
||||
rule_id: ELASTIC_SECURITY_RULE_ID,
|
||||
exceptions_list: [
|
||||
...immutableRule.exceptions_list,
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
const status = await getPrebuiltRulesAndTimelinesStatus(es, supertest);
|
||||
expect(status.rules_not_installed).toEqual(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('@brokenInServerless t1_analyst', () => {
|
||||
const role = ROLES.t1_analyst;
|
||||
|
||||
beforeEach(async () => {
|
||||
await createUserAndRole(getService, role);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteUserAndRole(getService, role);
|
||||
});
|
||||
|
||||
it('should NOT be able to create an exception list', async () => {
|
||||
await supertestWithoutAuth
|
||||
.post(EXCEPTION_LIST_ITEM_URL)
|
||||
.auth(role, 'changeme')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(getCreateExceptionListItemMinimalSchemaMock())
|
||||
.expect(403);
|
||||
});
|
||||
|
||||
it('should NOT be able to create an exception list item', async () => {
|
||||
await supertestWithoutAuth
|
||||
.post(EXCEPTION_LIST_ITEM_URL)
|
||||
.auth(role, 'changeme')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(getCreateExceptionListItemMinimalSchemaMock())
|
||||
.expect(403);
|
||||
});
|
||||
});
|
||||
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/169664
|
||||
describe.skip('tests with auditbeat data', () => {
|
||||
before(async () => {
|
||||
await esArchiver.load(path);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await esArchiver.unload(path);
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await createAlertsIndex(supertest, log);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteAllAlerts(supertest, log, es);
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllExceptions(supertest, log);
|
||||
});
|
||||
|
||||
it('should be able to execute against an exception list that does not include valid entries and get back 10 alerts', async () => {
|
||||
const { id, list_id, namespace_type, type } = await createExceptionList(
|
||||
supertest,
|
||||
log,
|
||||
getCreateExceptionListMinimalSchemaMock()
|
||||
);
|
||||
|
||||
const exceptionListItem: CreateExceptionListItemSchema = {
|
||||
...getCreateExceptionListItemMinimalSchemaMock(),
|
||||
entries: [
|
||||
{
|
||||
field: 'some.none.existent.field', // non-existent field where we should not exclude anything
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'some value',
|
||||
},
|
||||
],
|
||||
};
|
||||
await createExceptionListItem(supertest, log, exceptionListItem);
|
||||
|
||||
const ruleWithException: RuleCreateProps = {
|
||||
name: 'Simple Rule Query',
|
||||
description: 'Simple Rule Query',
|
||||
enabled: true,
|
||||
risk_score: 1,
|
||||
rule_id: 'rule-1',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'query',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: 'host.name: "suricata-sensor-amsterdam"',
|
||||
exceptions_list: [
|
||||
{
|
||||
id,
|
||||
list_id,
|
||||
namespace_type,
|
||||
type,
|
||||
},
|
||||
],
|
||||
};
|
||||
const { id: createdId } = await createRule(supertest, log, ruleWithException);
|
||||
await waitForRuleSuccess({ supertest, log, id: createdId });
|
||||
await waitForAlertsToBePresent(supertest, log, 10, [createdId]);
|
||||
const alertsOpen = await getAlertsByIds(supertest, log, [createdId]);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(10);
|
||||
});
|
||||
|
||||
it('should be able to execute against an exception list that does include valid entries and get back 0 alerts', async () => {
|
||||
const rule: QueryRuleCreateProps = {
|
||||
name: 'Simple Rule Query',
|
||||
description: 'Simple Rule Query',
|
||||
enabled: true,
|
||||
risk_score: 1,
|
||||
rule_id: 'rule-1',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'query',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: 'host.name: "suricata-sensor-amsterdam"',
|
||||
};
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.name', // This matches the query above which will exclude everything
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: 'suricata-sensor-amsterdam',
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should be able to execute against an exception list that does include valid case sensitive entries and get back 0 alerts', async () => {
|
||||
const rule: QueryRuleCreateProps = {
|
||||
name: 'Simple Rule Query',
|
||||
description: 'Simple Rule Query',
|
||||
enabled: true,
|
||||
risk_score: 1,
|
||||
rule_id: 'rule-1',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'query',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: 'host.name: "suricata-sensor-amsterdam"',
|
||||
};
|
||||
const rule2: QueryRuleCreateProps = {
|
||||
name: 'Simple Rule Query',
|
||||
description: 'Simple Rule Query',
|
||||
enabled: true,
|
||||
risk_score: 1,
|
||||
rule_id: 'rule-2',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'query',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: 'host.name: "suricata-sensor-amsterdam"',
|
||||
};
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.os.name',
|
||||
operator: 'included',
|
||||
type: 'match_any',
|
||||
value: ['ubuntu'],
|
||||
},
|
||||
],
|
||||
]);
|
||||
const createdRule2 = await createRuleWithExceptionEntries(supertest, log, rule2, [
|
||||
[
|
||||
{
|
||||
field: 'host.os.name', // This matches the query above which will exclude everything
|
||||
operator: 'included',
|
||||
type: 'match_any',
|
||||
value: ['ubuntu', 'Ubuntu'],
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
const alertsOpen2 = await getOpenAlerts(supertest, log, es, createdRule2);
|
||||
// Expect alerts here because all values are "Ubuntu"
|
||||
// and exception is one of ["ubuntu"]
|
||||
expect(alertsOpen.hits.hits.length).toEqual(10);
|
||||
// Expect no alerts here because all values are "Ubuntu"
|
||||
// and exception is one of ["ubuntu", "Ubuntu"]
|
||||
expect(alertsOpen2.hits.hits.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('generates no alerts when an exception is added for an EQL rule', async () => {
|
||||
const rule: EqlRuleCreateProps = {
|
||||
...getEqlRuleForAlertTesting(['auditbeat-*']),
|
||||
query: 'configuration where agent.id=="a1d7b39c-f898-4dbe-a761-efb61939302d"',
|
||||
};
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.id',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: '8cc95778cce5407c809480e8e32ad76b',
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('generates no alerts when an exception is added for a threshold rule', async () => {
|
||||
const rule: ThresholdRuleCreateProps = {
|
||||
...getThresholdRuleForAlertTesting(['auditbeat-*']),
|
||||
threshold: {
|
||||
field: 'host.id',
|
||||
value: 700,
|
||||
},
|
||||
};
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.id',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: '8cc95778cce5407c809480e8e32ad76b',
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('generates no alerts when an exception is added for a threat match rule', async () => {
|
||||
const rule: ThreatMatchRuleCreateProps = {
|
||||
description: 'Detecting root and admin users',
|
||||
name: 'Query with a rule id',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'threat_match',
|
||||
risk_score: 55,
|
||||
language: 'kuery',
|
||||
rule_id: 'rule-1',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: '*:*',
|
||||
threat_query: 'source.ip: "188.166.120.93"', // narrow things down with a query to a specific source ip
|
||||
threat_index: ['auditbeat-*'], // We use auditbeat as both the matching index and the threat list for simplicity
|
||||
threat_mapping: [
|
||||
// We match host.name against host.name
|
||||
{
|
||||
entries: [
|
||||
{
|
||||
field: 'host.name',
|
||||
value: 'host.name',
|
||||
type: 'mapping',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
threat_filters: [],
|
||||
};
|
||||
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'source.ip',
|
||||
operator: 'included',
|
||||
type: 'match',
|
||||
value: '188.166.120.93',
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
describe('rules with value list exceptions', () => {
|
||||
beforeEach(async () => {
|
||||
await createListsIndex(supertest, log);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteListsIndex(supertest, log);
|
||||
});
|
||||
|
||||
it('generates no alerts when a value list exception is added for a query rule', async () => {
|
||||
const valueListId = 'value-list-id.txt';
|
||||
await importFile(supertest, log, 'keyword', ['suricata-sensor-amsterdam'], valueListId);
|
||||
const rule: QueryRuleCreateProps = {
|
||||
name: 'Simple Rule Query',
|
||||
description: 'Simple Rule Query',
|
||||
enabled: true,
|
||||
risk_score: 1,
|
||||
rule_id: 'rule-1',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'query',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: 'host.name: "suricata-sensor-amsterdam"',
|
||||
};
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.name',
|
||||
operator: 'included',
|
||||
type: 'list',
|
||||
list: {
|
||||
id: valueListId,
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('generates no alerts when a value list exception is added for a threat match rule', async () => {
|
||||
const valueListId = 'value-list-id.txt';
|
||||
await importFile(supertest, log, 'keyword', ['zeek-sensor-amsterdam'], valueListId);
|
||||
const rule: ThreatMatchRuleCreateProps = {
|
||||
description: 'Detecting root and admin users',
|
||||
name: 'Query with a rule id',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'threat_match',
|
||||
risk_score: 55,
|
||||
language: 'kuery',
|
||||
rule_id: 'rule-1',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: '*:*',
|
||||
threat_query: 'source.ip: "188.166.120.93"', // narrow things down with a query to a specific source ip
|
||||
threat_index: ['auditbeat-*'], // We use auditbeat as both the matching index and the threat list for simplicity
|
||||
threat_mapping: [
|
||||
// We match host.name against host.name
|
||||
{
|
||||
entries: [
|
||||
{
|
||||
field: 'host.name',
|
||||
value: 'host.name',
|
||||
type: 'mapping',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
threat_filters: [],
|
||||
};
|
||||
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.name',
|
||||
operator: 'included',
|
||||
type: 'list',
|
||||
list: {
|
||||
id: valueListId,
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('generates no alerts when a value list exception is added for a threshold rule', async () => {
|
||||
const valueListId = 'value-list-id.txt';
|
||||
await importFile(supertest, log, 'keyword', ['zeek-sensor-amsterdam'], valueListId);
|
||||
const rule: ThresholdRuleCreateProps = {
|
||||
description: 'Detecting root and admin users',
|
||||
name: 'Query with a rule id',
|
||||
severity: 'high',
|
||||
index: ['auditbeat-*'],
|
||||
type: 'threshold',
|
||||
risk_score: 55,
|
||||
language: 'kuery',
|
||||
rule_id: 'rule-1',
|
||||
from: '1900-01-01T00:00:00.000Z',
|
||||
query: 'host.name: "zeek-sensor-amsterdam"',
|
||||
threshold: {
|
||||
field: 'host.name',
|
||||
value: 1,
|
||||
},
|
||||
};
|
||||
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.name',
|
||||
operator: 'included',
|
||||
type: 'list',
|
||||
list: {
|
||||
id: valueListId,
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
|
||||
it('generates no alerts when a value list exception is added for an EQL rule', async () => {
|
||||
const valueListId = 'value-list-id.txt';
|
||||
await importFile(supertest, log, 'keyword', ['zeek-sensor-amsterdam'], valueListId);
|
||||
const rule: EqlRuleCreateProps = {
|
||||
...getEqlRuleForAlertTesting(['auditbeat-*']),
|
||||
query: 'configuration where host.name=="zeek-sensor-amsterdam"',
|
||||
};
|
||||
|
||||
const createdRule = await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.name',
|
||||
operator: 'included',
|
||||
type: 'list',
|
||||
list: {
|
||||
id: valueListId,
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
const alertsOpen = await getOpenAlerts(supertest, log, es, createdRule);
|
||||
expect(alertsOpen.hits.hits.length).toEqual(0);
|
||||
});
|
||||
it('should Not allow deleting value list when there are references and ignoreReferences is false', async () => {
|
||||
const valueListId = 'value-list-id.txt';
|
||||
await importFile(supertest, log, 'keyword', ['suricata-sensor-amsterdam'], valueListId);
|
||||
const rule: QueryRuleCreateProps = {
|
||||
...getSimpleRule(),
|
||||
query: 'host.name: "suricata-sensor-amsterdam"',
|
||||
};
|
||||
await createRuleWithExceptionEntries(supertest, log, rule, [
|
||||
[
|
||||
{
|
||||
field: 'host.name',
|
||||
operator: 'included',
|
||||
type: 'list',
|
||||
list: {
|
||||
id: valueListId,
|
||||
type: 'keyword',
|
||||
},
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
const deleteReferences = false;
|
||||
const ignoreReferences = false;
|
||||
|
||||
// Delete the value list
|
||||
await supertest
|
||||
.delete(
|
||||
`${LIST_URL}?deleteReferences=${deleteReferences}&id=${valueListId}&ignoreReferences=${ignoreReferences}`
|
||||
)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send()
|
||||
.expect(409);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue