diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/crowdstrike/crowdstrike_actions_client.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/crowdstrike/crowdstrike_actions_client.ts index b39c85726651f..f4ad7f981ab9d 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/crowdstrike/crowdstrike_actions_client.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/crowdstrike/crowdstrike_actions_client.ts @@ -70,9 +70,8 @@ export class CrowdstrikeActionsClient extends ResponseActionsClientImpl { LogsEndpointAction > { const agentId = actionRequest.endpoint_ids[0]; - const eventDetails = await this.getEventDetailsById(agentId); + const hostname = await this.getHostNameByAgentId(agentId); - const hostname = eventDetails.host.name; return super.writeActionRequestToEndpointIndex({ ...actionRequest, hosts: { @@ -124,13 +123,12 @@ export class CrowdstrikeActionsClient extends ResponseActionsClientImpl { return actionSendResponse; } - private async getEventDetailsById(agentId: string): Promise<{ - host: { name: string }; - }> { + private async getHostNameByAgentId(agentId: string): Promise { const search = { - index: ['logs-crowdstrike.fdr*', 'logs-crowdstrike.falcon*'], + // Multiple indexes: .falcon, .fdr, .host, .alert + index: ['logs-crowdstrike*'], size: 1, - _source: ['host.name'], + _source: ['host.hostname', 'host.name'], body: { query: { bool: { @@ -140,13 +138,14 @@ export class CrowdstrikeActionsClient extends ResponseActionsClientImpl { }, }; try { - const result: SearchResponse<{ host: { name: string } }> = - await this.options.esClient.search<{ host: { name: string } }>(search, { + const result: SearchResponse<{ host: { name: string; hostname: string } }> = + await this.options.esClient.search<{ host: { name: string; hostname: string } }>(search, { ignore: [404], }); // Check if host name exists - const hostName = result.hits.hits?.[0]?._source?.host?.name; + const host = result.hits.hits?.[0]?._source?.host; + const hostName = host?.name || host?.hostname; if (!hostName) { throw new ResponseActionsClientError( `Host name not found in the event document for agentId: ${agentId}`, @@ -154,7 +153,7 @@ export class CrowdstrikeActionsClient extends ResponseActionsClientImpl { ); } - return result.hits.hits[0]._source as { host: { name: string } }; + return hostName; } catch (err) { throw new ResponseActionsClientError( `Failed to fetch event document: ${err.message}`, diff --git a/x-pack/plugins/security_solution/server/endpoint/services/agent/clients/crowdstrike/crowdstrike_agent_status_client.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/agent/clients/crowdstrike/crowdstrike_agent_status_client.test.ts index cd70ac070d115..d2d10eea0e019 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/agent/clients/crowdstrike/crowdstrike_agent_status_client.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/agent/clients/crowdstrike/crowdstrike_agent_status_client.test.ts @@ -41,7 +41,7 @@ const getMockSearchResponse = ( { _id: '1', _index: 'index', - fields: { 'crowdstrike.host.id': [agentName] }, + fields: { 'device.id': [agentName] }, inner_hits: { most_recent: { hits: { @@ -52,11 +52,13 @@ const getMockSearchResponse = ( _source: { crowdstrike: { host: { - id: !wrongAgentName ? agentName : 'wrongAgentName', last_seen: '2023-01-01', status, }, }, + device: { + id: !wrongAgentName ? agentName : 'wrongAgentName', + }, }, }, ], diff --git a/x-pack/plugins/security_solution/server/endpoint/services/agent/clients/crowdstrike/crowdstrike_agent_status_client.ts b/x-pack/plugins/security_solution/server/endpoint/services/agent/clients/crowdstrike/crowdstrike_agent_status_client.ts index 61f746dbf4e55..dff47cf86ab6f 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/agent/clients/crowdstrike/crowdstrike_agent_status_client.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/agent/clients/crowdstrike/crowdstrike_agent_status_client.ts @@ -72,7 +72,7 @@ export class CrowdstrikeAgentStatusClient extends AgentStatusClient { filter: [ { terms: { - 'crowdstrike.host.id': agentIds, + 'device.id': agentIds, }, }, ], @@ -91,8 +91,7 @@ export class CrowdstrikeAgentStatusClient extends AgentStatusClient { size: DEFAULT_MAX_TABLE_QUERY_SIZE, query, collapse: { - // TODO: check if we should use crowdstrike.cid instead - field: 'crowdstrike.host.id', + field: 'device.id', inner_hits: { name: 'most_recent', size: 1, @@ -123,10 +122,8 @@ export class CrowdstrikeAgentStatusClient extends AgentStatusClient { const mostRecentAgentInfosByAgentId = searchResponse?.hits?.hits?.reduce< Record >((acc, hit) => { - // TODO TC: check if we should use crowdstrike.cid instead - if (hit.fields?.['crowdstrike.host.id'][0]) { - acc[hit.fields?.['crowdstrike.host.id'][0]] = - hit.inner_hits?.most_recent.hits.hits[0]._source; + if (hit.fields?.['device.id'][0]) { + acc[hit.fields?.['device.id'][0]] = hit.inner_hits?.most_recent.hits.hits[0]._source; } return acc; @@ -135,7 +132,7 @@ export class CrowdstrikeAgentStatusClient extends AgentStatusClient { const agentStatuses = await this.getAgentStatusFromConnectorAction(agentIds); return agentIds.reduce((acc, agentId) => { - const agentInfo = mostRecentAgentInfosByAgentId[agentId]?.crowdstrike; + const { device, crowdstrike } = mostRecentAgentInfosByAgentId[agentId]; const agentStatus = agentStatuses[agentId]; const pendingActions = allPendingActions.find( @@ -145,12 +142,11 @@ export class CrowdstrikeAgentStatusClient extends AgentStatusClient { acc[agentId] = { agentId, agentType: this.agentType, - // TODO: check if we should use crowdstrike.cid instead - found: agentInfo?.host.id === agentId, + found: device?.id === agentId, isolated: - agentInfo?.host.status === CROWDSTRIKE_NETWORK_STATUS.CONTAINED || - agentInfo?.host.status === CROWDSTRIKE_NETWORK_STATUS.LIFT_CONTAINMENT_PENDING, - lastSeen: agentInfo?.host.last_seen || '', + crowdstrike?.host.status === CROWDSTRIKE_NETWORK_STATUS.CONTAINED || + crowdstrike?.host.status === CROWDSTRIKE_NETWORK_STATUS.LIFT_CONTAINMENT_PENDING, + lastSeen: crowdstrike?.host.last_seen || agentStatus?.last_seen || '', status: agentStatus?.state === CROWDSTRIKE_STATUS_RESPONSE.ONLINE ? HostStatus.HEALTHY @@ -162,6 +158,7 @@ export class CrowdstrikeAgentStatusClient extends AgentStatusClient { pendingActions: pendingActions?.pending_actions ?? {}, }; + // console.log({ acc }); return acc; }, {}); } catch (err) { diff --git a/x-pack/plugins/stack_connectors/common/crowdstrike/schema.ts b/x-pack/plugins/stack_connectors/common/crowdstrike/schema.ts index 1bd1ac46f31fc..4e3d6464821b6 100644 --- a/x-pack/plugins/stack_connectors/common/crowdstrike/schema.ts +++ b/x-pack/plugins/stack_connectors/common/crowdstrike/schema.ts @@ -41,6 +41,7 @@ export const CrowdstrikeGetAgentOnlineStatusResponseSchema = schema.object( { state: schema.maybe(schema.string()), id: schema.maybe(schema.string()), + last_seen: schema.maybe(schema.string()), }, { unknowns: 'allow' } ) diff --git a/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.ts b/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.ts index 07967d5013fa2..3d14ae62924c4 100644 --- a/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.ts +++ b/x-pack/plugins/stack_connectors/server/connector_types/crowdstrike/crowdstrike.ts @@ -154,7 +154,7 @@ export class CrowdstrikeConnector extends SubActionConnector< headers: { accept: 'application/json', 'Content-Type': 'application/x-www-form-urlencoded', - authorization: 'Basic ' + this.base64encodedToken, + authorization: 'Basic ' + CrowdstrikeConnector.base64encodedToken, }, responseSchema: CrowdstrikeGetTokenResponseSchema, });