Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,8 @@ export class CrowdstrikeActionsClient extends ResponseActionsClientImpl {
LogsEndpointAction<TParameters, TOutputContent, TMeta & CrowdstrikeActionRequestCommonMeta>
> {
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: {
Expand Down Expand Up @@ -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<string> {
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: {
Expand All @@ -140,21 +138,22 @@ 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}`,
404
);
}

return result.hits.hits[0]._source as { host: { name: string } };
return hostName;
} catch (err) {
throw new ResponseActionsClientError(
`Failed to fetch event document: ${err.message}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const getMockSearchResponse = (
{
_id: '1',
_index: 'index',
fields: { 'crowdstrike.host.id': [agentName] },
fields: { 'device.id': [agentName] },
inner_hits: {
most_recent: {
hits: {
Expand All @@ -52,11 +52,13 @@ const getMockSearchResponse = (
_source: {
crowdstrike: {
host: {
id: !wrongAgentName ? agentName : 'wrongAgentName',
last_seen: '2023-01-01',
status,
},
},
device: {
id: !wrongAgentName ? agentName : 'wrongAgentName',
},
},
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export class CrowdstrikeAgentStatusClient extends AgentStatusClient {
filter: [
{
terms: {
'crowdstrike.host.id': agentIds,
'device.id': agentIds,
},
},
],
Expand All @@ -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,
Expand Down Expand Up @@ -123,10 +122,8 @@ export class CrowdstrikeAgentStatusClient extends AgentStatusClient {
const mostRecentAgentInfosByAgentId = searchResponse?.hits?.hits?.reduce<
Record<string, RawCrowdstrikeInfo>
>((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;
Expand All @@ -135,7 +132,7 @@ export class CrowdstrikeAgentStatusClient extends AgentStatusClient {
const agentStatuses = await this.getAgentStatusFromConnectorAction(agentIds);

return agentIds.reduce<AgentStatusRecords>((acc, agentId) => {
const agentInfo = mostRecentAgentInfosByAgentId[agentId]?.crowdstrike;
const { device, crowdstrike } = mostRecentAgentInfosByAgentId[agentId];

const agentStatus = agentStatuses[agentId];
const pendingActions = allPendingActions.find(
Expand All @@ -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
Expand All @@ -162,6 +158,7 @@ export class CrowdstrikeAgentStatusClient extends AgentStatusClient {
pendingActions: pendingActions?.pending_actions ?? {},
};

// console.log({ acc });
return acc;
}, {});
} catch (err) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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' }
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
Expand Down