diff --git a/x-pack/platform/plugins/shared/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap b/x-pack/platform/plugins/shared/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap index 6888a284249e4..429450bc350fc 100644 --- a/x-pack/platform/plugins/shared/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap +++ b/x-pack/platform/plugins/shared/actions/server/integration_tests/__snapshots__/connector_types.test.ts.snap @@ -9910,6 +9910,258 @@ Object { `; exports[`Connector type config checks detect connector type changes for: .microsoft_defender_endpoint 7`] = ` +Object { + "flags": Object { + "default": Object { + "special": "deep", + }, + "error": [Function], + "presence": "optional", + }, + "keys": Object {}, + "type": "object", +} +`; + +exports[`Connector type config checks detect connector type changes for: .microsoft_defender_endpoint 8`] = ` +Object { + "flags": Object { + "default": Object { + "special": "deep", + }, + "error": [Function], + "presence": "optional", + }, + "keys": Object { + "comment": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-min-length": 1, + }, + Object { + "x-oas-optional": true, + }, + ], + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + "id": Object { + "flags": Object { + "error": [Function], + }, + "metas": Array [ + Object { + "x-oas-min-length": 1, + }, + ], + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + "parameters": Object { + "flags": Object { + "default": Object { + "special": "deep", + }, + "error": [Function], + "presence": "optional", + }, + "keys": Object { + "args": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-min-length": 1, + }, + Object { + "x-oas-optional": true, + }, + ], + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + "scriptName": Object { + "flags": Object { + "error": [Function], + }, + "metas": Array [ + Object { + "x-oas-min-length": 1, + }, + ], + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + }, + "type": "object", + }, + }, + "type": "object", +} +`; + +exports[`Connector type config checks detect connector type changes for: .microsoft_defender_endpoint 9`] = ` +Object { + "flags": Object { + "default": Object { + "special": "deep", + }, + "error": [Function], + "presence": "optional", + }, + "keys": Object { + "id": Object { + "flags": Object { + "default": [Function], + "error": [Function], + "presence": "optional", + }, + "matches": Array [ + Object { + "schema": Object { + "flags": Object { + "error": [Function], + }, + "metas": Array [ + Object { + "x-oas-min-length": 1, + }, + ], + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + }, + Object { + "schema": Object { + "flags": Object { + "error": [Function], + }, + "items": Array [ + Object { + "flags": Object { + "error": [Function], + "presence": "optional", + }, + "metas": Array [ + Object { + "x-oas-min-length": 1, + }, + ], + "rules": Array [ + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + Object { + "args": Object { + "method": [Function], + }, + "name": "custom", + }, + ], + "type": "string", + }, + ], + "rules": Array [ + Object { + "args": Object { + "limit": 1, + }, + "name": "min", + }, + ], + "type": "array", + }, + }, + ], + "metas": Array [ + Object { + "x-oas-optional": true, + }, + ], + "type": "alternatives", + }, + }, + "type": "object", +} +`; + +exports[`Connector type config checks detect connector type changes for: .microsoft_defender_endpoint 10`] = ` Object { "flags": Object { "default": Object { @@ -10049,7 +10301,7 @@ Object { } `; -exports[`Connector type config checks detect connector type changes for: .microsoft_defender_endpoint 8`] = ` +exports[`Connector type config checks detect connector type changes for: .microsoft_defender_endpoint 11`] = ` Object { "flags": Object { "default": Object { @@ -10089,7 +10341,7 @@ Object { } `; -exports[`Connector type config checks detect connector type changes for: .microsoft_defender_endpoint 9`] = ` +exports[`Connector type config checks detect connector type changes for: .microsoft_defender_endpoint 12`] = ` Object { "flags": Object { "default": Object { diff --git a/x-pack/platform/plugins/shared/stack_connectors/common/microsoft_defender_endpoint/constants.ts b/x-pack/platform/plugins/shared/stack_connectors/common/microsoft_defender_endpoint/constants.ts index 07cb3192e04e4..71b4fe894c92f 100644 --- a/x-pack/platform/plugins/shared/stack_connectors/common/microsoft_defender_endpoint/constants.ts +++ b/x-pack/platform/plugins/shared/stack_connectors/common/microsoft_defender_endpoint/constants.ts @@ -15,4 +15,7 @@ export enum MICROSOFT_DEFENDER_ENDPOINT_SUB_ACTION { ISOLATE_HOST = 'isolateHost', RELEASE_HOST = 'releaseHost', GET_ACTIONS = 'getActions', + GET_LIBRARY_FILES = 'getLibraryFiles', + RUN_SCRIPT = 'runScript', + GET_ACTION_RESULTS = 'getActionResults', } diff --git a/x-pack/platform/plugins/shared/stack_connectors/common/microsoft_defender_endpoint/schema.ts b/x-pack/platform/plugins/shared/stack_connectors/common/microsoft_defender_endpoint/schema.ts index 0daf547de21fa..7ffab000ad413 100644 --- a/x-pack/platform/plugins/shared/stack_connectors/common/microsoft_defender_endpoint/schema.ts +++ b/x-pack/platform/plugins/shared/stack_connectors/common/microsoft_defender_endpoint/schema.ts @@ -31,6 +31,8 @@ export const MicrosoftDefenderEndpointBaseApiResponseSchema = schema.maybe( schema.object({}, { unknowns: 'allow' }) ); +export const MicrosoftDefenderEndpointEmptyParamsSchema = schema.object({}); + export const TestConnectorParamsSchema = schema.object({}); export const AgentDetailsParamsSchema = schema.object({ @@ -146,6 +148,15 @@ export const ReleaseHostParamsSchema = schema.object({ comment: schema.string({ minLength: 1 }), }); +export const RunScriptParamsSchema = schema.object({ + id: schema.string({ minLength: 1 }), + comment: schema.maybe(schema.string({ minLength: 1 })), + parameters: schema.object({ + scriptName: schema.string({ minLength: 1 }), + args: schema.maybe(schema.string({ minLength: 1 })), + }), +}); + const MachineActionTypeSchema = schema.oneOf([ schema.literal('RunAntiVirusScan'), schema.literal('Offboard'), @@ -207,6 +218,37 @@ export const GetActionsParamsSchema = schema.object({ sortDirection: schema.maybe(schema.oneOf([schema.literal('asc'), schema.literal('desc')])), }); +export const GetActionResultsParamsSchema = schema.object({ + id: schema.maybe( + schema.oneOf([ + schema.string({ minLength: 1 }), + schema.arrayOf(schema.string({ minLength: 1 }), { minSize: 1 }), + ]) + ), +}); + +export const MSDefenderLibraryFileSchema = schema.object( + { + fileName: schema.maybe(schema.string()), + sha256: schema.maybe(schema.string()), + description: schema.maybe(schema.string()), + creationTime: schema.maybe(schema.string()), + lastUpdatedTime: schema.maybe(schema.string()), + createdBy: schema.maybe(schema.string()), + hasParameters: schema.maybe(schema.boolean()), + parametersDescription: schema.maybe(schema.nullable(schema.string())), + }, + { unknowns: 'allow' } +); + +export const GetLibraryFilesResponse = schema.object( + { + '@odata.context': schema.maybe(schema.string()), + value: schema.maybe(schema.arrayOf(MSDefenderLibraryFileSchema)), + }, + { unknowns: 'allow' } +); + // ---------------------------------- // Connector Sub-Actions // ---------------------------------- @@ -225,9 +267,14 @@ const ReleaseHostSchema = schema.object({ subAction: schema.literal(MICROSOFT_DEFENDER_ENDPOINT_SUB_ACTION.RELEASE_HOST), subActionParams: ReleaseHostParamsSchema, }); +const RunScriptSchema = schema.object({ + subAction: schema.literal(MICROSOFT_DEFENDER_ENDPOINT_SUB_ACTION.RUN_SCRIPT), + subActionParams: RunScriptParamsSchema, +}); export const MicrosoftDefenderEndpointActionParamsSchema = schema.oneOf([ TestConnectorSchema, IsolateHostSchema, ReleaseHostSchema, + RunScriptSchema, ]); diff --git a/x-pack/platform/plugins/shared/stack_connectors/common/microsoft_defender_endpoint/types.ts b/x-pack/platform/plugins/shared/stack_connectors/common/microsoft_defender_endpoint/types.ts index 63402fabe6857..32c83c13b3731 100644 --- a/x-pack/platform/plugins/shared/stack_connectors/common/microsoft_defender_endpoint/types.ts +++ b/x-pack/platform/plugins/shared/stack_connectors/common/microsoft_defender_endpoint/types.ts @@ -18,6 +18,8 @@ import type { AgentDetailsParamsSchema, GetActionsParamsSchema, AgentListParamsSchema, + GetLibraryFilesResponse, + RunScriptParamsSchema, } from './schema'; export type MicrosoftDefenderEndpointConfig = TypeOf; @@ -60,6 +62,11 @@ export interface MicrosoftDefenderEndpointGetActionsResponse { value: MicrosoftDefenderEndpointMachineAction[]; } +export interface MicrosoftDefenderEndpointGetActionResultsResponse { + '@odata.context': string; + value: string[]; // Downloadable link +} + /** * @see https://learn.microsoft.com/en-us/defender-endpoint/api/machine */ @@ -177,6 +184,7 @@ export type MicrosoftDefenderEndpointTestConnectorParams = TypeOf; export type MicrosoftDefenderEndpointReleaseHostParams = TypeOf; +export type MicrosoftDefenderEndpointRunScriptParams = TypeOf; export type MicrosoftDefenderEndpointActionParams = TypeOf< typeof MicrosoftDefenderEndpointActionParamsSchema @@ -188,3 +196,5 @@ export interface MicrosoftDefenderEndpointApiTokenResponse { expires_in: number; access_token: string; } + +export type MicrosoftDefenderGetLibraryFilesResponse = TypeOf; diff --git a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/microsoft_defender_endpoint/microsoft_defender_endpoint.test.ts b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/microsoft_defender_endpoint/microsoft_defender_endpoint.test.ts index ff03fb3a61da2..07fb0b11ac6d8 100644 --- a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/microsoft_defender_endpoint/microsoft_defender_endpoint.test.ts +++ b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/microsoft_defender_endpoint/microsoft_defender_endpoint.test.ts @@ -29,6 +29,7 @@ describe('Microsoft Defender for Endpoint Connector', () => { 'API call to Machine Isolate was successful', 'API call to Machine Release was successful', 'API call to Machine Actions was successful', + 'API call to Machine RunScript was successful', ], }); diff --git a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/microsoft_defender_endpoint/microsoft_defender_endpoint.ts b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/microsoft_defender_endpoint/microsoft_defender_endpoint.ts index 4144f13f12a40..bea295b024c56 100644 --- a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/microsoft_defender_endpoint/microsoft_defender_endpoint.ts +++ b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/microsoft_defender_endpoint/microsoft_defender_endpoint.ts @@ -20,6 +20,9 @@ import { GetActionsParamsSchema, AgentDetailsParamsSchema, AgentListParamsSchema, + RunScriptParamsSchema, + MicrosoftDefenderEndpointEmptyParamsSchema, + GetActionResultsParamsSchema, } from '../../../common/microsoft_defender_endpoint/schema'; import type { MicrosoftDefenderEndpointAgentDetailsParams, @@ -36,6 +39,9 @@ import type { MicrosoftDefenderEndpointGetActionsResponse, MicrosoftDefenderEndpointAgentListParams, MicrosoftDefenderEndpointAgentListResponse, + MicrosoftDefenderGetLibraryFilesResponse, + MicrosoftDefenderEndpointRunScriptParams, + MicrosoftDefenderEndpointGetActionResultsResponse, } from '../../../common/microsoft_defender_endpoint/types'; export class MicrosoftDefenderEndpointConnector extends SubActionConnector< @@ -47,6 +53,7 @@ export class MicrosoftDefenderEndpointConnector extends SubActionConnector< private readonly urls: { machines: string; machineActions: string; + libraryFiles: string; }; constructor( @@ -62,6 +69,7 @@ export class MicrosoftDefenderEndpointConnector extends SubActionConnector< machines: `${this.config.apiUrl}/api/machines`, // API docs: https://learn.microsoft.com/en-us/defender-endpoint/api/get-machineactions-collection machineActions: `${this.config.apiUrl}/api/machineactions`, + libraryFiles: `${this.config.apiUrl}/api/libraryfiles`, }; this.registerSubActions(); @@ -102,6 +110,23 @@ export class MicrosoftDefenderEndpointConnector extends SubActionConnector< method: 'getActions', schema: GetActionsParamsSchema, }); + this.registerSubAction({ + name: MICROSOFT_DEFENDER_ENDPOINT_SUB_ACTION.GET_LIBRARY_FILES, + method: 'getLibraryFiles', + schema: MicrosoftDefenderEndpointEmptyParamsSchema, + }); + + this.registerSubAction({ + name: MICROSOFT_DEFENDER_ENDPOINT_SUB_ACTION.RUN_SCRIPT, + method: 'runScript', + schema: RunScriptParamsSchema, + }); + + this.registerSubAction({ + name: MICROSOFT_DEFENDER_ENDPOINT_SUB_ACTION.GET_ACTION_RESULTS, + method: 'getActionResults', + schema: GetActionResultsParamsSchema, + }); } private async fetchFromMicrosoft( @@ -270,6 +295,19 @@ export class MicrosoftDefenderEndpointConnector extends SubActionConnector< results.push('API call to Machine Actions was successful'); }); + await this.runScript( + { + id: 'elastic-connector-test', + comment: 'connector test', + parameters: { scriptName: 'test' }, + }, + connectorUsageCollector + ) + .catch(catchErrorAndIgnoreExpectedErrors) + .then(() => { + results.push('API call to Machine RunScript was successful'); + }); + return { results }; } @@ -346,6 +384,39 @@ export class MicrosoftDefenderEndpointConnector extends SubActionConnector< ); } + public async runScript( + payload: MicrosoftDefenderEndpointRunScriptParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + // API Reference:https://learn.microsoft.com/en-us/defender-endpoint/api/run-live-response + + return this.fetchFromMicrosoft( + { + url: `${this.urls.machines}/${payload.id}/runliveresponse`, + method: 'POST', + data: { + Comment: payload.comment, + Commands: [ + { + type: 'RunScript', + params: [ + { + key: 'ScriptName', + value: payload.parameters.scriptName, + }, + { + key: 'Args', + value: payload.parameters.args || '--noargs', + }, + ], + }, + ], + }, + }, + connectorUsageCollector + ); + } + public async getActions( { page = 1, @@ -375,6 +446,36 @@ export class MicrosoftDefenderEndpointConnector extends SubActionConnector< total: response['@odata.count'] ?? -1, }; } + + public async getActionResults( + { id }: MicrosoftDefenderEndpointGetActionsParams, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + // API Reference: https://learn.microsoft.com/en-us/defender-endpoint/api/get-live-response-result + + return this.fetchFromMicrosoft( + { + url: `${this.urls.machineActions}/${id}/GetLiveResponseResultDownloadLink(index=0)`, // We want to download the first result + method: 'GET', + }, + connectorUsageCollector + ); + } + + public async getLibraryFiles( + payload: {}, + connectorUsageCollector: ConnectorUsageCollector + ): Promise { + // API Reference:https://learn.microsoft.com/en-us/defender-endpoint/api/list-library-files + + return this.fetchFromMicrosoft( + { + url: `${this.urls.libraryFiles}`, + method: 'GET', + }, + connectorUsageCollector + ); + } } interface BuildODataUrlParamsResponse { diff --git a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/microsoft_defender_endpoint/mocks.ts b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/microsoft_defender_endpoint/mocks.ts index c1bcac0488386..7b5039b997a49 100644 --- a/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/microsoft_defender_endpoint/mocks.ts +++ b/x-pack/platform/plugins/shared/stack_connectors/server/connector_types/microsoft_defender_endpoint/mocks.ts @@ -147,6 +147,13 @@ const createMicrosoftDefenderConnectorMock = (): CreateMicrosoftDefenderConnecto '@odata.count': 1, value: [createMicrosoftMachineMock()], }), + + // Machine RunScript + [`${apiUrl}/api/machines/1-2-3/runliveresponse`]: () => + createAxiosResponseMock({ + '@odata.context': 'https://api-us3.securitycenter.microsoft.com/api/$metadata#Machines', + value: [createMicrosoftMachineMock()], + }), }; instanceMock.request.mockImplementation(