[8.x] [EDR Workflows] Crowdstrike - Add more routes and responses to mocked server (#192881) (#193119)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[EDR Workflows] Crowdstrike - Add more routes and responses to mocked
server (#192881)](https://github.com/elastic/kibana/pull/192881)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Tomasz
Ciecierski","email":"tomasz.ciecierski@elastic.co"},"sourceCommit":{"committedDate":"2024-09-17T08:00:38Z","message":"[EDR
Workflows] Crowdstrike - Add more routes and responses to mocked server
(#192881)","sha":"1ae7548c655c47f045923b8671ff8c61b04ca154","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:Defend
Workflows","v8.16.0"],"title":"[EDR Workflows] Crowdstrike - Add more
routes and responses to mocked
server","number":192881,"url":"https://github.com/elastic/kibana/pull/192881","mergeCommit":{"message":"[EDR
Workflows] Crowdstrike - Add more routes and responses to mocked server
(#192881)","sha":"1ae7548c655c47f045923b8671ff8c61b04ca154"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/192881","number":192881,"mergeCommit":{"message":"[EDR
Workflows] Crowdstrike - Add more routes and responses to mocked server
(#192881)","sha":"1ae7548c655c47f045923b8671ff8c61b04ca154"}},{"branch":"8.x","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Tomasz Ciecierski <tomasz.ciecierski@elastic.co>
This commit is contained in:
Kibana Machine 2024-09-17 19:28:57 +10:00 committed by GitHub
parent 9d09dbfcd4
commit 12fcb6110a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 1875 additions and 69 deletions

View file

@ -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]> = {}
): 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: 'f0e04444',
assigned_date: '2024-03-15T13:20:02.258285018Z',
applied_date: '2024-03-15T13:20:17.016591803Z',
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: '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
);

View file

@ -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: [],
};
};

View file

@ -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: [],
};
};

View file

@ -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: [],
};
};

View file

@ -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({})]);
};

View file

@ -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: [],
};
};

View file

@ -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,
},
],
};
};

View file

@ -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'],
};
};

View file

@ -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',
};
};

View file

@ -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',
},
],

View file

@ -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(),
];
};

View file

@ -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,
};
};

View file

@ -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: [],
};
};

View file

@ -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: [],
};
};

View file

@ -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,
};
};

View file

@ -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';