diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/mocks.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/mocks.ts index e915a16c250b0..d79d683877524 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/mocks.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/mocks.ts @@ -10,6 +10,7 @@ import type { CrowdstrikeGetAgentsResponse, } from '@kbn/stack-connectors-plugin/common/crowdstrike/types'; import { merge } from 'lodash'; +import { TEST_AGENT_ID, TEST_CID_ID } from './routes/utils'; export const createCrowdstrikeGetAgentsApiResponseMock = ( data: CrowdstrikeBaseApiResponse['resources'][number] @@ -18,55 +19,66 @@ export const createCrowdstrikeGetAgentsApiResponseMock = ( meta: { query_time: 0.001831479, powered_by: 'device-api', - trace_id: '4567898765-432423432432-42342342', + trace_id: 'xxx', }, errors: null, resources: data, }; }; +export const createCrowdstrikeErrorResponseMock = (error: object) => { + return { + meta: { + query_time: 0.001831479, + powered_by: 'device-api', + trace_id: 'xxx', + }, + errors: [error], + }; +}; + export const createCrowdstrikeAgentDetailsMock = ( overrides: Partial = {} ): CrowdstrikeGetAgentsResponse['resources'][number] => { return merge( { - device_id: '5f4ed7ec2690431f8fa79213268779cb', - cid: '234567890', + device_id: TEST_AGENT_ID, + cid: TEST_CID_ID, agent_load_flags: '0', - agent_local_time: '2024-03-18T22:21:00.173Z', - agent_version: '7.07.16206.0', - bios_manufacturer: 'Amazon EC2', - bios_version: '1.0', - config_id_base: '65994753', - config_id_build: '16206', - config_id_platform: '8', - cpu_signature: '8392466', - cpu_vendor: '1', - external_ip: '18.157.150.216', - mac_address: '03-f4-f4-f4-f4', - instance_id: 'i-456789', - service_provider: 'AWS_EC2_V2', - service_provider_account_id: '23456789', - hostname: 'Crowdstrike-1460', - first_seen: '2024-03-15T13:18:56Z', - last_login_timestamp: '2024-03-15T22:11:47Z', - last_login_user: 'testuser', - last_login_uid: '1002', - last_seen: '2024-03-20T07:19:01Z', - local_ip: '172.31.200.45', - major_version: '5', - minor_version: '14', - os_version: 'RHEL 9.3', + agent_local_time: '2024-09-08T06:07:00.326Z', + agent_version: '7.18.17106.0', + bios_manufacturer: 'EFI Development Kit II / OVMF', + bios_version: '0.0.0', + config_id_base: '65994763', + config_id_build: '17106', + config_id_platform: '128', + cpu_signature: '4294967295', + cpu_vendor: '3', + external_ip: '79.184.246.19', + mac_address: '52-54-00-09-42-a6', + hostname: 'cs-falcon', + filesystem_containment_status: 'normal', + first_login_timestamp: '2024-08-19T08:37:15Z', + first_login_user: 'ubuntu', + first_seen: '2024-08-19T08:37:17Z', + last_login_timestamp: '2024-08-19T08:37:15Z', + last_login_user: 'ubuntu', + last_login_uid: '1000', + last_seen: '2024-09-10T09:32:58Z', + local_ip: '192.168.80.7', + major_version: '6', + minor_version: '8', + os_version: 'Ubuntu 24.04', platform_id: '3', platform_name: 'Linux', policies: [ { policy_type: 'prevention', - policy_id: '234234234234', + policy_id: 'test_prevention_policy_id', applied: true, - settings_hash: 'f0e04444', - assigned_date: '2024-03-15T13:20:02.25821602Z', - applied_date: '2024-03-15T13:20:16.804783955Z', + settings_hash: 'test2984', + assigned_date: '2024-08-19T08:40:24.454802663Z', + applied_date: '2024-08-19T08:46:46.169115065Z', rule_groups: [], }, ], @@ -74,61 +86,67 @@ export const createCrowdstrikeAgentDetailsMock = ( device_policies: { prevention: { policy_type: 'prevention', - policy_id: '234234234234', + policy_id: 'test_prevention_policy_id', applied: true, - settings_hash: 'f0e04444', - assigned_date: '2024-03-15T13:20:02.25821602Z', - applied_date: '2024-03-15T13:20:16.804783955Z', + settings_hash: 'test2984', + assigned_date: '2024-08-19T08:40:24.454802663Z', + applied_date: '2024-08-19T08:46:46.169115065Z', rule_groups: [], }, sensor_update: { policy_type: 'sensor-update', - policy_id: '234234234234', + policy_id: 'test_sensor_update_policy_id', applied: true, - settings_hash: 'tagged|5;', - assigned_date: '2024-03-15T13:20:02.258765734Z', - applied_date: '2024-03-15T13:23:53.773752711Z', + settings_hash: 'test3a5bb', + assigned_date: '2024-08-19T08:40:24.406563043Z', + applied_date: '2024-08-19T08:44:54.277815271Z', uninstall_protection: 'UNKNOWN', }, global_config: { policy_type: 'globalconfig', - policy_id: '234234234234', + policy_id: 'test_global_config_policy_id', applied: true, - settings_hash: 'f0e04444', - assigned_date: '2024-03-18T22:21:01.50638371Z', - applied_date: '2024-03-18T22:21:30.565040189Z', + settings_hash: 'testa5bc', + assigned_date: '2024-09-08T04:54:07.410501178Z', + applied_date: '2024-09-08T04:55:06.81648557Z', }, remote_response: { policy_type: 'remote-response', - policy_id: '234234234234', + policy_id: 'test_remote_response_policy_id', + applied: true, + settings_hash: 'test205c', + assigned_date: '2024-08-19T08:48:00.144480664Z', + applied_date: '2024-08-19T08:55:01.036602542Z', + }, + 'host-retention': { + policy_type: 'host-retention', + policy_id: 'test_host-retention_policy_id', applied: true, - settings_hash: 'f0e04444', - assigned_date: '2024-03-15T13:20:02.258285018Z', - applied_date: '2024-03-15T13:20:17.016591803Z', + settings_hash: 'testfghjk', + assigned_date: '2024-08-19T08:40:24.444810716Z', + applied_date: '2024-08-19T08:44:54.577562462Z', }, }, - groups: [], - group_hash: '45678909876545678', + groups: ['test123', 'test456'], + group_hash: 'test123', product_type_desc: 'Server', - provision_status: 'NotProvisioned', - serial_number: '345678765-35d6-e704-1723-423423432', - status: 'containment_pending', - system_manufacturer: 'Amazon EC2', - system_product_name: 't3a.medium', + provision_status: 'Provisioned', + status: 'normal', + system_manufacturer: 'QEMU', + system_product_name: 'QEMU Virtual Machine', tags: [], - modified_timestamp: '2024-03-20T07:19:45Z', + modified_timestamp: '2024-09-10T09:33:21Z', meta: { - version: '484', - version_string: '9:33384301139', + version: '552', + version_string: '1:1815077394', }, - zone_group: 'eu-central-1a', - kernel_version: '5.14.0-234234el9_3.x86_64', + kernel_version: '6.8.0-41-generic', chassis_type: '1', chassis_type_desc: 'Other', - connection_ip: '172.31.200.45', - default_gateway_ip: '172.31.200.1', - connection_mac_address: '02-e8-f1-0e-b7-c4', - linux_sensor_mode: 'Kernel Mode', + connection_ip: '192.168.80.7', + default_gateway_ip: '192.168.80.1', + connection_mac_address: '52-54-00-09-42-a6', + linux_sensor_mode: 'User Mode', deployment_type: 'Standard', }, overrides @@ -140,8 +158,10 @@ export const createCrowdstrikeGetAgentOnlineStatusDetailsMock: ( ) => CrowdstrikeGetAgentOnlineStatusResponse['resources'][number] = (overrides) => { return merge( { + id: TEST_AGENT_ID, + cid: TEST_CID_ID, + last_seen: '2024-09-10T09:59:56Z', state: 'online', - id: '5f4ed7ec2690431f8fa79213268779cb', }, overrides ); diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/batch_init_rtr_route.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/batch_init_rtr_route.ts new file mode 100644 index 0000000000000..940ad4d127d4e --- /dev/null +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/batch_init_rtr_route.ts @@ -0,0 +1,99 @@ +/* + * 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 { buildCrowdstrikeRoutePath, TEST_AGENT_ID, TEST_BATCH_ID, TEST_SESSION_ID } from './utils'; +import type { ExternalEdrServerEmulatorRouteHandlerMethod } from '../../../external_edr_server_emulator.types'; +import type { EmulatorServerRouteDefinition } from '../../../lib/emulator_server.types'; + +export const batchInitRTRSessionRoute = (): EmulatorServerRouteDefinition => { + return { + path: buildCrowdstrikeRoutePath('/real-time-response/combined/batch-init-session/v1'), + method: 'POST', + handler: batchInitSessionSuccessHandler, + }; +}; +// @ts-expect-error - example of error response +const initSessionWrongHostIdError = async () => { + return { + meta: { + query_time: 0.244284399, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + batch_id: '', + resources: { + [TEST_AGENT_ID]: { + session_id: '', + complete: false, + stdout: '', + stderr: '', + aid: TEST_AGENT_ID, + errors: [ + { + code: 500, + message: `uuid: incorrect UUID length 47 in string ${TEST_AGENT_ID}`, + }, + ], + query_time: 0, + offline_queued: false, + }, + }, + errors: [ + { + code: 404, + message: 'no successful hosts initialized on RTR', + }, + ], + }; +}; +// @ts-expect-error - example of error response +const initSessionMissingIdsError = async () => { + return { + meta: { + query_time: 0.00034664, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + batch_id: '', + resources: {}, + errors: [ + { + code: 400, + message: + 'Invalid number of hosts in request: 0. Must be an integer greater than 0 and less than or equal to 10000', + }, + ], + }; +}; + +const batchInitSessionSuccessHandler: ExternalEdrServerEmulatorRouteHandlerMethod< + {}, + {} +> = async () => { + return { + meta: { + query_time: 1.067267552, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + batch_id: TEST_BATCH_ID, + resources: { + [TEST_AGENT_ID]: { + session_id: TEST_SESSION_ID, + task_id: 'xxx', + complete: true, + stdout: '/', + stderr: '', + base_command: 'pwd', + aid: TEST_AGENT_ID, + errors: [], + query_time: 0, + offline_queued: false, + }, + }, + errors: [], + }; +}; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/batch_refresh_rtr_session_route.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/batch_refresh_rtr_session_route.ts new file mode 100644 index 0000000000000..0b7ae5b6f4e19 --- /dev/null +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/batch_refresh_rtr_session_route.ts @@ -0,0 +1,56 @@ +/* + * 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 { buildCrowdstrikeRoutePath, TEST_AGENT_ID, TEST_SESSION_ID } from './utils'; +import type { ExternalEdrServerEmulatorRouteHandlerMethod } from '../../../external_edr_server_emulator.types'; +import type { EmulatorServerRouteDefinition } from '../../../lib/emulator_server.types'; + +export const batchRTRRefreshSessionRoute = (): EmulatorServerRouteDefinition => { + return { + path: buildCrowdstrikeRoutePath('/real-time-response/combined/batch-refresh-session/v1'), + method: 'POST', + handler: batchRTRRefreshSessionHandler, + }; +}; + +// @ts-expect-error - example of error response +const batchRTRRefreshSessionInvalidSessionError = async () => { + return { + meta: { + query_time: 0.001031577, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + resources: {}, + errors: [ + { + code: 400, + message: 'no hosts in this batch session', + }, + ], + }; +}; + +const batchRTRRefreshSessionHandler: ExternalEdrServerEmulatorRouteHandlerMethod< + {}, + {} +> = async () => { + return { + meta: { + query_time: 0.068379923, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + resources: { + [TEST_AGENT_ID]: { + aid: TEST_AGENT_ID, + session_id: TEST_SESSION_ID, + errors: [], + }, + }, + errors: [], + }; +}; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/batch_rtr_command_route.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/batch_rtr_command_route.ts new file mode 100644 index 0000000000000..07f5ad927b3d4 --- /dev/null +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/batch_rtr_command_route.ts @@ -0,0 +1,169 @@ +/* + * 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 { buildCrowdstrikeRoutePath, TEST_AGENT_ID, TEST_SESSION_ID } from './utils'; +import type { ExternalEdrServerEmulatorRouteHandlerMethod } from '../../../external_edr_server_emulator.types'; +import type { EmulatorServerRouteDefinition } from '../../../lib/emulator_server.types'; + +export const batchRTRCommandRoute = (): EmulatorServerRouteDefinition => { + return { + // we use `combined` api - which returns just one complete response, otherwise it would be coming in batches + path: buildCrowdstrikeRoutePath('/real-time-response/combined/batch-command/v1'), + method: 'POST', + handler: batchRTRCommandSuccessHandler, + }; +}; + +// @ts-expect-error - example of missing file error +const batchCommandResponseWithError = async () => { + return { + meta: { + query_time: 0.913513625, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: TEST_SESSION_ID, + task_id: 'xxx', + complete: true, + stdout: '', + stderr: 'cat: test.xt: No such file or directory', + base_command: 'cat', + aid: TEST_AGENT_ID, + errors: [], + query_time: 0.912058582, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; + +// @ts-expect-error - example of error response +const batchCommandResponseInvalidCommandError = async () => { + return { + meta: { + query_time: 0.101208469, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: '', + complete: false, + stdout: '', + stderr: '', + aid: TEST_AGENT_ID, + errors: [ + { + code: 40007, + message: 'Command not found', + }, + ], + query_time: 0, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; + +// @ts-expect-error - example of error response +const batchCommandInvalidSessionError = async () => { + return { + meta: { + query_time: 0.02078217, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: '', + complete: false, + stdout: '', + stderr: '', + aid: TEST_AGENT_ID, + errors: [ + { + code: 50007, + message: 'could not get session', + }, + ], + query_time: 0, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; +// @ts-expect-error - example of error response +const batchCommandCommandIsNotValidError = async () => { + return { + meta: { + query_time: 0.122372386, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: '', + complete: false, + stdout: '', + stderr: '', + aid: TEST_AGENT_ID, + errors: [ + { + code: 40006, + message: 'Command is not valid', + }, + ], + query_time: 0, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; + +const batchRTRCommandSuccessHandler: ExternalEdrServerEmulatorRouteHandlerMethod< + {}, + {} +> = async () => { + return { + meta: { + query_time: 0.888750872, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: TEST_SESSION_ID, + task_id: 'xxx', + complete: true, + stdout: + 'bin\nbin.usr-is-merged\nboot\ndev\netc\nhome\nlib\nlib.usr-is-merged\nlost+found\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nsbin.usr-is-merged\nsnap\nsrv\nsys\ntmp\nusr\nvar', + stderr: '', + base_command: 'ls', + aid: TEST_AGENT_ID, + errors: [], + query_time: 0.887764377, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_agent_details_route.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_agent_details_route.ts index 84e5f42783f3a..1734cda7e745e 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_agent_details_route.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_agent_details_route.ts @@ -21,6 +21,29 @@ export const getAgentDetailsRouteDefinition = (): EmulatorServerRouteDefinition }; }; +// @ts-expect-error - example of missing file error +const getAgentDetailsMissingIdsError = async () => { + return { + errors: [ + { + code: 400, + message: "The 'ids' parameter must be present at least once.", + }, + ], + }; +}; +// @ts-expect-error - example of missing file error +const getAgentDetailsInvalidIdsError = async () => { + return { + errors: [ + { + code: 400, + message: 'invalid device id [asdasd]', + }, + ], + }; +}; + const getAgentDetailsHandler: ExternalEdrServerEmulatorRouteHandlerMethod<{}> = async () => { return createCrowdstrikeGetAgentsApiResponseMock([createCrowdstrikeAgentDetailsMock({})]); }; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_rtr_command_details_route.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_rtr_command_details_route.ts new file mode 100644 index 0000000000000..3028d2910c7c4 --- /dev/null +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_rtr_command_details_route.ts @@ -0,0 +1,61 @@ +/* + * 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 { buildCrowdstrikeRoutePath, TEST_SESSION_ID } from './utils'; +import type { ExternalEdrServerEmulatorRouteHandlerMethod } from '../../../external_edr_server_emulator.types'; +import type { EmulatorServerRouteDefinition } from '../../../lib/emulator_server.types'; + +export const getRTRCommandDetailsRoute = (): EmulatorServerRouteDefinition => { + return { + // PARAMS /v1?cloud_request_id=test-cloud-request1&sequence_id=0 + path: buildCrowdstrikeRoutePath('/real-time-response/entities/command/v1'), + method: 'GET', + handler: getRTRCommandDetailsSuccessHandler, + }; +}; + +// @ts-expect-error - example of missing file error +const commandDetailsMissingCloudIdError = async () => { + return { + meta: { + query_time: 0.000238205, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + resources: [], + errors: [ + { + code: 400, + message: 'cloud_request_id must be a uuid string', + }, + ], + }; +}; + +const getRTRCommandDetailsSuccessHandler: ExternalEdrServerEmulatorRouteHandlerMethod< + {}, + {} +> = async () => { + return { + meta: { + query_time: 0.307542055, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + resources: [ + { + session_id: TEST_SESSION_ID, + task_id: 'xxx', + complete: true, + stdout: + 'archive\nbackup\nbin\nboot\ndev\necho\netc\nhome\nlib\nlost+found\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nsnap\nsrv\nstuff.exe\nsys\ntest.sh\ntestPush.exe\ntmp\nusr\nvar\n', + stderr: '', + base_command: 'ls', + }, + ], + errors: [], + }; +}; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_scripts_details_route.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_scripts_details_route.ts new file mode 100644 index 0000000000000..38f57e1f7b0a8 --- /dev/null +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_scripts_details_route.ts @@ -0,0 +1,80 @@ +/* + * 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 { buildCrowdstrikeRoutePath } from './utils'; +import type { ExternalEdrServerEmulatorRouteHandlerMethod } from '../../../external_edr_server_emulator.types'; +import type { EmulatorServerRouteDefinition } from '../../../lib/emulator_server.types'; + +export const getCustomScriptsDetailsRoute = (): EmulatorServerRouteDefinition => { + return { + path: buildCrowdstrikeRoutePath('/real-time-response/entities/scripts/v1'), + method: 'GET', + handler: getCustomScriptsDetailsSuccessHandler, + }; +}; + +// @ts-expect-error - example of missing file error +const getScriptsIdEmptyResponse = async () => { + return { + meta: { + query_time: 0.025758121, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + resources: [], + }; +}; + +const getCustomScriptsDetailsSuccessHandler: ExternalEdrServerEmulatorRouteHandlerMethod< + {}, + {} +> = async () => { + return { + meta: { + query_time: 0.531831172, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + resources: [ + { + id: 'test-id-1', + name: 'AnyDesk Remediation', + file_type: 'script', + platform: ['windows'], + size: 1979, + content: 'echo "AnyDesk Remediation"', + created_by: 'testuser@test.com', + created_by_uuid: '34d10-a0f7e5dc98a8', + created_timestamp: '2023-08-01T05:20:10.695182885Z', + modified_by: 'testuser@test.com', + modified_timestamp: '2023-08-01T05:20:10.695183074Z', + sha256: 'test58f74e15e56815d71b29450f077df2f6070630184b9d', + permission_type: 'public', + run_attempt_count: 67, + run_success_count: 0, + write_access: true, + }, + { + id: 'test-id-2', + name: 'Gather AnyDesk Artifacts', + file_type: 'script', + platform: ['windows'], + size: 1184, + content: 'echo Gather Anydesk Artifacts', + created_by: 'testuser@test.com', + created_by_uuid: '34d0610-a0f7e5dc98a8', + created_timestamp: '2023-08-17T07:08:00.839412392Z', + modified_by: 'testuser@test.com', + modified_timestamp: '2023-08-17T07:08:00.839412727Z', + sha256: 'teste8dfbb7cfb782c11484b47d336a93fdae80cffa77039c5', + permission_type: 'public', + run_attempt_count: 4, + run_success_count: 0, + write_access: true, + }, + ], + }; +}; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_scripts_ids_route.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_scripts_ids_route.ts new file mode 100644 index 0000000000000..71a6caf257ad0 --- /dev/null +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_scripts_ids_route.ts @@ -0,0 +1,36 @@ +/* + * 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 { buildCrowdstrikeRoutePath } from './utils'; +import type { ExternalEdrServerEmulatorRouteHandlerMethod } from '../../../external_edr_server_emulator.types'; +import type { EmulatorServerRouteDefinition } from '../../../lib/emulator_server.types'; + +export const getCustomScriptsIdsRoute = (): EmulatorServerRouteDefinition => { + return { + path: buildCrowdstrikeRoutePath('/real-time-response/queries/scripts/v1'), + method: 'GET', + handler: getCustomScriptsIdsHandler, + }; +}; + +const getCustomScriptsIdsHandler: ExternalEdrServerEmulatorRouteHandlerMethod< + {}, + {} +> = async () => { + return { + meta: { + query_time: 0.030241162, + pagination: { + offset: 0, + limit: 100, + total: 11, + }, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + resources: ['test-id-1', 'test-id-2'], + }; +}; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_token_route.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_token_route.ts index 6629c33974b04..8bc50860beb2a 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_token_route.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/get_token_route.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import { createCrowdstrikeErrorResponseMock } from '../mocks'; import { buildCrowdstrikeRoutePath } from './utils'; import type { ExternalEdrServerEmulatorRouteHandlerMethod } from '../../../external_edr_server_emulator.types'; import type { EmulatorServerRouteDefinition } from '../../../lib/emulator_server.types'; @@ -16,14 +17,18 @@ export const getTokenRouteDefinition = (): EmulatorServerRouteDefinition => { }; }; +// @ts-expect-error - example of missing token error +const getTokenError = async () => { + return createCrowdstrikeErrorResponseMock({ + code: 401, + message: 'access denied, invalid bearer token', + }); +}; + const getTokenHandler: ExternalEdrServerEmulatorRouteHandlerMethod<{}> = async () => { return { access_token: 'testtoken', expires_in: 123, token_type: 'bearer', - id_token: 'test', - issued_token_type: 'test', - refresh_token: 'test', - scope: 'test', }; }; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/host_actions_route.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/host_actions_route.ts index 2c648213a3f09..273285d519ded 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/host_actions_route.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/host_actions_route.ts @@ -17,6 +17,30 @@ export const hostActionsRouteDefinition = (): EmulatorServerRouteDefinition => { }; }; +// @ts-expect-error - example of missing action parameter error +const hostActionsMissingActionParameterError = async () => { + return { + errors: [ + { + code: 400, + message: "Provided data does not match expected 'Action Parameter' format", + }, + ], + }; +}; + +// @ts-expect-error - example of missing agent id error +const hostActionsInvalidAgentIdError = async () => { + return { + errors: [ + { + code: 404, + message: 'No matching device found for ID wrongAgentId', + }, + ], + }; +}; + const hostActionsHandler: ExternalEdrServerEmulatorRouteHandlerMethod< {}, CrowdstrikeHostActionsParams @@ -24,7 +48,7 @@ const hostActionsHandler: ExternalEdrServerEmulatorRouteHandlerMethod< return { resources: [ { - id: 'test', + id: 'test_id', path: 'test', }, ], diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/index.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/index.ts index 1da4f435aae4c..3be3fe20a2819 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/index.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/index.ts @@ -5,11 +5,21 @@ * 2.0. */ +import { rtrCommandRoute } from './rtr_command_route'; +import { batchRTRRefreshSessionRoute } from './batch_refresh_rtr_session_route'; +import { rtrAdminCommandRoute } from './rtr_admin_route'; +import { refreshRTRSessionRoute } from './refresh_rtr_session_route'; +import { getCustomScriptsDetailsRoute } from './get_scripts_details_route'; +import { initRTRSessionRoute } from './init_rtr_route'; +import { getRTRCommandDetailsRoute } from './get_rtr_command_details_route'; +import { batchRTRCommandRoute } from './batch_rtr_command_route'; +import { batchInitRTRSessionRoute } from './batch_init_rtr_route'; import { getTokenRouteDefinition } from './get_token_route'; import type { EmulatorServerRouteDefinition } from '../../../lib/emulator_server.types'; import { hostActionsRouteDefinition } from './host_actions_route'; import { getAgentDetailsRouteDefinition } from './get_agent_details_route'; import { getAgentOnlineStatusRouteDefinition } from './get_agent_online_status_route'; +import { getCustomScriptsIdsRoute } from './get_scripts_ids_route'; export const getCrowdstrikeRouteDefinitions = (): EmulatorServerRouteDefinition[] => { return [ @@ -17,5 +27,15 @@ export const getCrowdstrikeRouteDefinitions = (): EmulatorServerRouteDefinition[ hostActionsRouteDefinition(), getAgentDetailsRouteDefinition(), getAgentOnlineStatusRouteDefinition(), + batchInitRTRSessionRoute(), + batchRTRCommandRoute(), + getRTRCommandDetailsRoute(), + getCustomScriptsIdsRoute(), + getCustomScriptsDetailsRoute(), + initRTRSessionRoute(), + refreshRTRSessionRoute(), + rtrAdminCommandRoute(), + batchRTRRefreshSessionRoute(), + rtrCommandRoute(), ]; }; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/init_rtr_route.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/init_rtr_route.ts new file mode 100644 index 0000000000000..f16f166551356 --- /dev/null +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/init_rtr_route.ts @@ -0,0 +1,413 @@ +/* + * 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 { buildCrowdstrikeRoutePath, TEST_AGENT_ID, TEST_SESSION_ID } from './utils'; +import type { ExternalEdrServerEmulatorRouteHandlerMethod } from '../../../external_edr_server_emulator.types'; +import type { EmulatorServerRouteDefinition } from '../../../lib/emulator_server.types'; + +export const initRTRSessionRoute = (): EmulatorServerRouteDefinition => { + return { + path: buildCrowdstrikeRoutePath('/real-time-response/entities/sessions/v1'), + method: 'POST', + handler: initRTRSessionHandler, + }; +}; +// requestBody: +// { +// "device_id": "xxxxxx", +// "queue_offline": false +// } + +// @ts-expect-error - example of invalid agent id error +const initRTRSessionInvalidAgentIdError = async () => { + return { + meta: { + query_time: 0.244284399, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + batch_id: '', + resources: { + [TEST_AGENT_ID]: { + session_id: '', + complete: false, + stdout: '', + stderr: '', + aid: TEST_AGENT_ID, + errors: [ + { + code: 500, + message: 'uuid: incorrect UUID length 47 in string "wrongAgentId"', + }, + ], + query_time: 0, + offline_queued: false, + }, + }, + errors: [ + { + code: 404, + message: 'no successful hosts initialized on RTR', + }, + ], + }; +}; + +// @ts-expect-error - example of missing agent id error +const initRTRSessionMissingAgentIdError = async () => { + return { + meta: { + query_time: 0.00034664, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + batch_id: '', + resources: {}, + errors: [ + { + code: 400, + message: + 'Invalid number of hosts in request: 0. Must be an integer greater than 0 and less than or equal to 10000', + }, + ], + }; +}; + +const initRTRSessionHandler: ExternalEdrServerEmulatorRouteHandlerMethod<{}, {}> = async () => { + return { + meta: { + query_time: 1.776937422, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + resources: [ + { + session_id: TEST_SESSION_ID, + scripts: [ + { + command: 'cat', + description: 'Read a file from disk and display as ASCII', + examples: 'cat foo.txt\r\ncat -n foo.txt\r\ncat -t foo.txt\r\ncat -t -n foo.txt', + internal_only: false, + runnable: true, + sub_commands: [], + args: [ + { + id: 671, + created_at: '2020-09-22T00:54:20Z', + updated_at: '2020-09-22T00:54:20Z', + script_id: 94, + arg_type: 'arg', + data_type: 'string', + requires_value: false, + arg_name: 'Path', + description: 'path to cat', + default_value: '', + required: true, + sequence: 1, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + { + id: 672, + created_at: '2020-09-22T00:54:20Z', + updated_at: '2020-09-22T00:54:20Z', + script_id: 94, + arg_type: 'flag', + data_type: 'string', + requires_value: false, + arg_name: 'n', + description: 'Number the output lines starting from 1', + default_value: '', + required: false, + sequence: 2, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + { + id: 673, + created_at: '2020-09-22T00:54:20Z', + updated_at: '2020-09-22T00:54:20Z', + script_id: 94, + arg_type: 'flag', + data_type: 'string', + requires_value: false, + arg_name: 't', + description: "Display non-printing characters, and display tab characters as `^I'.", + default_value: '', + required: false, + sequence: 3, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + ], + }, + { + command: 'cd', + description: 'Change the current working directory', + examples: '', + internal_only: false, + runnable: true, + sub_commands: [], + args: [ + { + id: 674, + created_at: '2020-09-22T00:54:07Z', + updated_at: '2020-09-22T00:54:07Z', + script_id: 95, + arg_type: 'arg', + data_type: 'string', + requires_value: false, + arg_name: 'Path', + description: 'path', + default_value: '', + required: true, + sequence: 1, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + ], + }, + { + command: 'env', + description: 'Print out the environment', + examples: 'env', + internal_only: false, + runnable: true, + sub_commands: [], + args: [], + }, + { + command: 'filehash', + description: 'Generate the MD5, SHA1, and SHA256 hashes of a file', + examples: 'filehash /tmp/test', + internal_only: false, + runnable: true, + sub_commands: [], + args: [ + { + id: 680, + created_at: '2020-09-22T00:53:36Z', + updated_at: '2020-09-22T00:53:36Z', + script_id: 100, + arg_type: 'arg', + data_type: 'string', + requires_value: false, + arg_name: 'Path', + description: 'File to hash', + default_value: '', + required: true, + sequence: 1, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + ], + }, + { + command: 'ifconfig', + description: 'Show network configuration information', + examples: 'ifconfig', + internal_only: false, + runnable: true, + sub_commands: [], + args: [], + }, + { + command: 'ls', + description: 'Display the contents of the specified path', + examples: + 'ls\r\nls -l\r\nls -L\r\nls -t\r\nls -l -@\r\nls -R\r\nls -l -R\r\nls -l -t -R -L', + internal_only: false, + runnable: true, + sub_commands: [], + args: [ + { + id: 684, + created_at: '2020-09-22T00:53:14Z', + updated_at: '2020-09-22T00:53:14Z', + script_id: 104, + arg_type: 'arg', + data_type: 'string', + requires_value: false, + arg_name: 'Path', + description: 'Path', + default_value: '.', + required: false, + sequence: 1, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + { + id: 685, + created_at: '2020-09-22T00:53:14Z', + updated_at: '2020-09-22T00:53:14Z', + script_id: 104, + arg_type: 'flag', + data_type: 'string', + requires_value: false, + arg_name: 'l', + description: 'List in long format.', + default_value: '', + required: false, + sequence: 2, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + { + id: 686, + created_at: '2020-09-22T00:53:14Z', + updated_at: '2020-09-22T00:53:14Z', + script_id: 104, + arg_type: 'flag', + data_type: 'string', + requires_value: false, + arg_name: 'L', + description: + 'Follow all symbolic links to final target and list the file or directory the link references rather than the link itself.', + default_value: '', + required: false, + sequence: 3, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + { + id: 687, + created_at: '2020-09-22T00:53:14Z', + updated_at: '2020-09-22T00:53:14Z', + script_id: 104, + arg_type: 'flag', + data_type: 'string', + requires_value: false, + arg_name: 'R', + description: 'Recursively list subdirectories encountered.', + default_value: '', + required: false, + sequence: 4, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + { + id: 688, + created_at: '2020-09-22T00:53:14Z', + updated_at: '2020-09-22T00:53:14Z', + script_id: 104, + arg_type: 'flag', + data_type: 'string', + requires_value: false, + arg_name: 't', + description: + 'Sort by time modified (most recently modified first) before sorting the operands by lexicographical order.', + default_value: '', + required: false, + sequence: 5, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + ], + }, + { + command: 'mount', + description: 'List or mount filesystem volumes', + examples: + 'Executable by all RTR roles:\r\nmount\r\nExecutable by privileged RTR users only:\r\nmount -t=nfs "host:/exports/filesystem" "/mnt/filesystem"\r\n Mount the NFS filesystem located at "/exports/filesystem" on "host" to the local destination "/mnt/filesystem"\r\nmount -t=smbfs "//user:password@host/filesystem" "/mnt/mountpoint"\r\n Mount the SMB "/filesystem" on "host" as "user" with "password" to "/mnt/mountpoint"\r\nmount -t=smbfs -o=nobrowse "//user:password@host/filesystem" "/mnt/mountpoint"\r\n Mount the SMB "/filesystem" with option "nobrowse" on "host" as "user" with "password" to "/mnt/mountpoint"', + internal_only: false, + runnable: true, + sub_commands: [], + args: [], + }, + { + command: 'netstat', + description: 'Display routing information or network connections', + examples: 'netstat\r\nnetstat -nr', + internal_only: false, + runnable: true, + sub_commands: [], + args: [ + { + id: 699, + created_at: '2020-09-22T00:52:52Z', + updated_at: '2020-09-22T00:52:52Z', + script_id: 108, + arg_type: 'flag', + data_type: 'string', + requires_value: false, + arg_name: 'nr', + description: 'Flag to show routing information', + default_value: '', + required: false, + sequence: 1, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + ], + }, + { + command: 'ps', + description: 'Display process information', + examples: 'ps', + internal_only: false, + runnable: true, + sub_commands: [], + args: [], + }, + { + command: 'pwd', + description: 'Prints present working directory', + examples: '', + internal_only: false, + runnable: true, + sub_commands: [], + args: [], + }, + { + command: 'users', + description: 'Get details about local users', + examples: + 'users\r\n List details about all local users\r\nusers foo\r\n List details about local user "foo"', + internal_only: false, + runnable: true, + sub_commands: [], + args: [ + { + id: 719, + created_at: '2023-03-15T00:28:54Z', + updated_at: '2023-03-15T00:28:54Z', + script_id: 117, + arg_type: 'arg', + data_type: 'string', + requires_value: false, + arg_name: 'UserName', + description: 'Username to filter results', + default_value: '', + required: false, + sequence: 1, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + ], + }, + ], + existing_aid_sessions: 1, + created_at: '2024-09-12T07:22:55.684322249Z', + pwd: '/', + offline_queued: false, + }, + ], + errors: null, + }; +}; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/refresh_rtr_session_route.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/refresh_rtr_session_route.ts new file mode 100644 index 0000000000000..77908faf55246 --- /dev/null +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/refresh_rtr_session_route.ts @@ -0,0 +1,392 @@ +/* + * 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 { buildCrowdstrikeRoutePath, TEST_AGENT_ID, TEST_SESSION_ID } from './utils'; +import type { ExternalEdrServerEmulatorRouteHandlerMethod } from '../../../external_edr_server_emulator.types'; +import type { EmulatorServerRouteDefinition } from '../../../lib/emulator_server.types'; + +export const refreshRTRSessionRoute = (): EmulatorServerRouteDefinition => { + return { + path: buildCrowdstrikeRoutePath('/real-time-response/entities/refresh-session/v1'), + method: 'POST', + handler: refreshRTRSessionHandler, + }; +}; +// requestBody: +// { +// "device_id": "xxxxxx", +// "queue_offline": false +// } + +// @ts-expect-error - example of invalid agent id error +const refreshRTRSessionInvalidAgentIdError = async () => { + return { + meta: { + query_time: 0.244284399, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + batch_id: '', + resources: { + [TEST_AGENT_ID]: { + session_id: '', + complete: false, + stdout: '', + stderr: '', + aid: TEST_AGENT_ID, + errors: [ + { + code: 500, + message: 'uuid: incorrect UUID length 47 in string "wrongAgentId"', + }, + ], + query_time: 0, + offline_queued: false, + }, + }, + errors: [ + { + code: 404, + message: 'no successful hosts initialized on RTR', + }, + ], + }; +}; + +const refreshRTRSessionHandler: ExternalEdrServerEmulatorRouteHandlerMethod<{}, {}> = async () => { + return { + meta: { + query_time: 0.098432609, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + resources: [ + { + session_id: TEST_SESSION_ID, + scripts: [ + { + command: 'cat', + description: 'Read a file from disk and display as ASCII', + examples: 'cat foo.txt\r\ncat -n foo.txt\r\ncat -t foo.txt\r\ncat -t -n foo.txt', + internal_only: false, + runnable: true, + sub_commands: [], + args: [ + { + id: 671, + created_at: '2020-09-22T00:54:20Z', + updated_at: '2020-09-22T00:54:20Z', + script_id: 94, + arg_type: 'arg', + data_type: 'string', + requires_value: false, + arg_name: 'Path', + description: 'path to cat', + default_value: '', + required: true, + sequence: 1, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + { + id: 672, + created_at: '2020-09-22T00:54:20Z', + updated_at: '2020-09-22T00:54:20Z', + script_id: 94, + arg_type: 'flag', + data_type: 'string', + requires_value: false, + arg_name: 'n', + description: 'Number the output lines starting from 1', + default_value: '', + required: false, + sequence: 2, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + { + id: 673, + created_at: '2020-09-22T00:54:20Z', + updated_at: '2020-09-22T00:54:20Z', + script_id: 94, + arg_type: 'flag', + data_type: 'string', + requires_value: false, + arg_name: 't', + description: "Display non-printing characters, and display tab characters as `^I'.", + default_value: '', + required: false, + sequence: 3, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + ], + }, + { + command: 'cd', + description: 'Change the current working directory', + examples: '', + internal_only: false, + runnable: true, + sub_commands: [], + args: [ + { + id: 674, + created_at: '2020-09-22T00:54:07Z', + updated_at: '2020-09-22T00:54:07Z', + script_id: 95, + arg_type: 'arg', + data_type: 'string', + requires_value: false, + arg_name: 'Path', + description: 'path', + default_value: '', + required: true, + sequence: 1, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + ], + }, + { + command: 'env', + description: 'Print out the environment', + examples: 'env', + internal_only: false, + runnable: true, + sub_commands: [], + args: [], + }, + { + command: 'filehash', + description: 'Generate the MD5, SHA1, and SHA256 hashes of a file', + examples: 'filehash /tmp/test', + internal_only: false, + runnable: true, + sub_commands: [], + args: [ + { + id: 680, + created_at: '2020-09-22T00:53:36Z', + updated_at: '2020-09-22T00:53:36Z', + script_id: 100, + arg_type: 'arg', + data_type: 'string', + requires_value: false, + arg_name: 'Path', + description: 'File to hash', + default_value: '', + required: true, + sequence: 1, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + ], + }, + { + command: 'ifconfig', + description: 'Show network configuration information', + examples: 'ifconfig', + internal_only: false, + runnable: true, + sub_commands: [], + args: [], + }, + { + command: 'ls', + description: 'Display the contents of the specified path', + examples: + 'ls\r\nls -l\r\nls -L\r\nls -t\r\nls -l -@\r\nls -R\r\nls -l -R\r\nls -l -t -R -L', + internal_only: false, + runnable: true, + sub_commands: [], + args: [ + { + id: 684, + created_at: '2020-09-22T00:53:14Z', + updated_at: '2020-09-22T00:53:14Z', + script_id: 104, + arg_type: 'arg', + data_type: 'string', + requires_value: false, + arg_name: 'Path', + description: 'Path', + default_value: '.', + required: false, + sequence: 1, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + { + id: 685, + created_at: '2020-09-22T00:53:14Z', + updated_at: '2020-09-22T00:53:14Z', + script_id: 104, + arg_type: 'flag', + data_type: 'string', + requires_value: false, + arg_name: 'l', + description: 'List in long format.', + default_value: '', + required: false, + sequence: 2, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + { + id: 686, + created_at: '2020-09-22T00:53:14Z', + updated_at: '2020-09-22T00:53:14Z', + script_id: 104, + arg_type: 'flag', + data_type: 'string', + requires_value: false, + arg_name: 'L', + description: + 'Follow all symbolic links to final target and list the file or directory the link references rather than the link itself.', + default_value: '', + required: false, + sequence: 3, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + { + id: 687, + created_at: '2020-09-22T00:53:14Z', + updated_at: '2020-09-22T00:53:14Z', + script_id: 104, + arg_type: 'flag', + data_type: 'string', + requires_value: false, + arg_name: 'R', + description: 'Recursively list subdirectories encountered.', + default_value: '', + required: false, + sequence: 4, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + { + id: 688, + created_at: '2020-09-22T00:53:14Z', + updated_at: '2020-09-22T00:53:14Z', + script_id: 104, + arg_type: 'flag', + data_type: 'string', + requires_value: false, + arg_name: 't', + description: + 'Sort by time modified (most recently modified first) before sorting the operands by lexicographical order.', + default_value: '', + required: false, + sequence: 5, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + ], + }, + { + command: 'mount', + description: 'List or mount filesystem volumes', + examples: + 'Executable by all RTR roles:\r\nmount\r\nExecutable by privileged RTR users only:\r\nmount -t=nfs "host:/exports/filesystem" "/mnt/filesystem"\r\n Mount the NFS filesystem located at "/exports/filesystem" on "host" to the local destination "/mnt/filesystem"\r\nmount -t=smbfs "//user:password@host/filesystem" "/mnt/mountpoint"\r\n Mount the SMB "/filesystem" on "host" as "user" with "password" to "/mnt/mountpoint"\r\nmount -t=smbfs -o=nobrowse "//user:password@host/filesystem" "/mnt/mountpoint"\r\n Mount the SMB "/filesystem" with option "nobrowse" on "host" as "user" with "password" to "/mnt/mountpoint"', + internal_only: false, + runnable: true, + sub_commands: [], + args: [], + }, + { + command: 'netstat', + description: 'Display routing information or network connections', + examples: 'netstat\r\nnetstat -nr', + internal_only: false, + runnable: true, + sub_commands: [], + args: [ + { + id: 699, + created_at: '2020-09-22T00:52:52Z', + updated_at: '2020-09-22T00:52:52Z', + script_id: 108, + arg_type: 'flag', + data_type: 'string', + requires_value: false, + arg_name: 'nr', + description: 'Flag to show routing information', + default_value: '', + required: false, + sequence: 1, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + ], + }, + { + command: 'ps', + description: 'Display process information', + examples: 'ps', + internal_only: false, + runnable: true, + sub_commands: [], + args: [], + }, + { + command: 'pwd', + description: 'Prints present working directory', + examples: '', + internal_only: false, + runnable: true, + sub_commands: [], + args: [], + }, + { + command: 'users', + description: 'Get details about local users', + examples: + 'users\r\n List details about all local users\r\nusers foo\r\n List details about local user "foo"', + internal_only: false, + runnable: true, + sub_commands: [], + args: [ + { + id: 719, + created_at: '2023-03-15T00:28:54Z', + updated_at: '2023-03-15T00:28:54Z', + script_id: 117, + arg_type: 'arg', + data_type: 'string', + requires_value: false, + arg_name: 'UserName', + description: 'Username to filter results', + default_value: '', + required: false, + sequence: 1, + options: null, + encoding: '', + command_level: 'non-destructive', + }, + ], + }, + ], + existing_aid_sessions: 1, + created_at: '2024-09-13T08:52:22.671935129Z', + offline_queued: false, + }, + ], + errors: [], + }; +}; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/rtr_admin_route.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/rtr_admin_route.ts new file mode 100644 index 0000000000000..373c6b960948e --- /dev/null +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/rtr_admin_route.ts @@ -0,0 +1,264 @@ +/* + * 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 { buildCrowdstrikeRoutePath, TEST_AGENT_ID, TEST_SESSION_ID } from './utils'; +import type { ExternalEdrServerEmulatorRouteHandlerMethod } from '../../../external_edr_server_emulator.types'; +import type { EmulatorServerRouteDefinition } from '../../../lib/emulator_server.types'; + +export const rtrAdminCommandRoute = (): EmulatorServerRouteDefinition => { + return { + // we use admin command to run run `runscript` and access `cloudFiles` and `custom scripts` + path: buildCrowdstrikeRoutePath('/real-time-response/combined/batch-admin-command/v1'), + method: 'POST', + handler: rtrAdminCommandHandler, + }; +}; + +// @ts-expect-error - example of error while executing cat command +const rtrAdminCommandExampleError = async () => { + return { + meta: { + query_time: 0.913513625, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: TEST_SESSION_ID, + task_id: 'xxx', + complete: true, + stdout: '', + stderr: 'cat: test.xt: No such file or directory', + base_command: 'cat', + aid: TEST_AGENT_ID, + errors: [], + query_time: 0.912058582, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; + +// @ts-expect-error - example of inactive rtr session error +const rtrAdminCommandInactiveSessionError = async () => { + return { + meta: { + query_time: 0.02078217, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: '', + complete: false, + stdout: '', + stderr: '', + aid: TEST_AGENT_ID, + errors: [ + { + code: 50007, + message: 'could not get session', + }, + ], + query_time: 0, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; + +// "command_string": "runscript -CloudFile=\"your_script_name\"", - file not existing +// @ts-expect-error - example of wrong cloud file error +const rtrAdminCommandWrongCloudFileExampleError = async () => { + return { + meta: { + query_time: 0.034585269, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: '', + complete: false, + stdout: '', + stderr: '', + aid: TEST_AGENT_ID, + errors: [ + { + code: 40412, + message: 'The file your_script_name could not be found', + }, + ], + query_time: 0, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; + +// wrong command eg. asd "command_string": "runscript -Raw=```asd```", +// @ts-expect-error - example of invalid command error +const rtrAdminCommandInvalidCommandError: ExternalEdrServerEmulatorRouteHandlerMethod< + {}, + {} +> = async () => { + return { + meta: { + query_time: 1.959748222, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: TEST_SESSION_ID, + task_id: 'xxx', + complete: true, + stdout: '', + stderr: '/bin/bash: line 1: asd: command not found', + base_command: 'runscript', + aid: TEST_AGENT_ID, + errors: [], + query_time: 1.95571987, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; + +const rtrAdminCommandHandler: ExternalEdrServerEmulatorRouteHandlerMethod<{}, {}> = async () => { + return { + meta: { + query_time: 0.945570286, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: TEST_SESSION_ID, + task_id: 'xxx', + complete: true, + stdout: + 'archive\nbackup\nbin\nboot\ndev\netc\nhome\nlib\nlost+found\nmedia\nmnt\nopt\nproc\nroot\nrun\nsbin\nsnap\nsrv\nsys\ntmp\nusr\nvar', + stderr: '', + base_command: 'runscript', + aid: TEST_AGENT_ID, + errors: [], + query_time: 0.941080011, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; +// runscript -CloudFile='test1' (customScript name) - when script is not accessible - eg. private +// @ts-expect-error - example of private script error +const rtrAdminCommandCustomScriptNotFoundError: ExternalEdrServerEmulatorRouteHandlerMethod< + {}, + {} +> = async () => { + return { + meta: { + query_time: 0.01495486, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: '', + complete: false, + stdout: '', + stderr: '', + aid: TEST_AGENT_ID, + errors: [ + { + code: 40412, + message: 'The file test1 could not be found', + }, + ], + query_time: 0, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; +// @ts-expect-error - example of error while executing put on a file that already exists on host +const rtrCommandPutFileAlreadyExistError: ExternalEdrServerEmulatorRouteHandlerMethod< + {}, + {} +> = async () => { + return { + meta: { + query_time: 7.897133656, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: TEST_SESSION_ID, + task_id: 'xxx', + complete: true, + stdout: '', + stderr: 'put: Destination already exists.', + base_command: 'DOWNLOAD_RENAME', + aid: TEST_AGENT_ID, + errors: [], + query_time: 7.8957342520000005, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; + +// @ts-expect-error - example of success response while executing put on a file +const rtrAdminCommandPutSuccessResponse: ExternalEdrServerEmulatorRouteHandlerMethod< + {}, + {} +> = async () => { + return { + meta: { + query_time: 5.497466448, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: TEST_SESSION_ID, + task_id: 'xxx', + complete: true, + stdout: '', + stderr: '', + base_command: 'DOWNLOAD_RENAME', + aid: TEST_AGENT_ID, + errors: [], + query_time: 5.496508269, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/rtr_command_route.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/rtr_command_route.ts new file mode 100644 index 0000000000000..60f3c7dd19ca0 --- /dev/null +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/rtr_command_route.ts @@ -0,0 +1,137 @@ +/* + * 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 { + buildCrowdstrikeRoutePath, + TEST_AGENT_ID, + TEST_CLOUD_REQUEST_ID, + TEST_SESSION_ID, +} from './utils'; +import type { ExternalEdrServerEmulatorRouteHandlerMethod } from '../../../external_edr_server_emulator.types'; +import type { EmulatorServerRouteDefinition } from '../../../lib/emulator_server.types'; + +export const rtrCommandRoute = (): EmulatorServerRouteDefinition => { + return { + path: buildCrowdstrikeRoutePath('/real-time-response/entities/command/v1'), + method: 'POST', + handler: rtrCommandHandler, + }; +}; +// { +// "base_command": "ls", +// "command_string": "ls", +// "session_id": TEST_SESSION_ID, +// "device_id": TEST_AGENT_ID, +// "persist": true +// } + +// @ts-expect-error - example of error response while executing cat command +const rtrCommandExampleError = async () => { + return { + meta: { + query_time: 0.913513625, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: TEST_SESSION_ID, + task_id: 'xxx', + complete: true, + stdout: '', + stderr: 'cat: test.xt: No such file or directory', + base_command: 'cat', + aid: TEST_AGENT_ID, + errors: [], + query_time: 0.912058582, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; + +// @ts-expect-error - invalid command +const rtrCommandInvalidCommandError = async () => { + return { + meta: { + query_time: 0.101208469, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: '', + complete: false, + stdout: '', + stderr: '', + aid: TEST_AGENT_ID, + errors: [ + { + code: 40007, + message: 'Command not found', + }, + ], + query_time: 0, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; + +// @ts-expect-error - invalid session +const rtrCommandInvalidSessionError = async () => { + return { + meta: { + query_time: 0.02078217, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + combined: { + resources: { + [TEST_AGENT_ID]: { + session_id: '', + complete: false, + stdout: '', + stderr: '', + aid: TEST_AGENT_ID, + errors: [ + { + code: 50007, + message: 'could not get session', + }, + ], + query_time: 0, + offline_queued: false, + }, + }, + }, + errors: [], + }; +}; + +const rtrCommandHandler: ExternalEdrServerEmulatorRouteHandlerMethod<{}, {}> = async () => { + return { + meta: { + query_time: 0.274908106, + powered_by: 'empower-api', + trace_id: 'xxx', + }, + resources: [ + { + session_id: TEST_SESSION_ID, + cloud_request_id: TEST_CLOUD_REQUEST_ID, + queued_command_offline: false, + }, + ], + errors: null, + }; +}; diff --git a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/utils.ts b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/utils.ts index ab8ed1ecd57b6..cdaeb004e213b 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/utils.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/api_emulator/emulator_plugins/crowdstrike/routes/utils.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + export const buildCrowdstrikeRoutePath = (path: string): string => { if (!path.startsWith('/')) { throw new Error(`'path' must start with '/'!`); @@ -11,3 +12,9 @@ export const buildCrowdstrikeRoutePath = (path: string): string => { return path; }; + +export const TEST_CID_ID = 'test-cid-id-123456789'; +export const TEST_AGENT_ID = 'test-agent-id-123456789'; +export const TEST_SESSION_ID = 'test-session-id-123456789'; +export const TEST_BATCH_ID = 'test-batch-id-123456789'; +export const TEST_CLOUD_REQUEST_ID = 'test-cloud-request-id-123456789';