@@ -14,6 +14,7 @@ import { CasesByAlertId } from '../../../../../cases/common/api/cases/case';
1414import { HostIsolationRequestSchema } from '../../../../common/endpoint/schema/actions' ;
1515import {
1616 ENDPOINT_ACTIONS_DS ,
17+ ENDPOINT_ACTION_RESPONSES_DS ,
1718 ISOLATE_HOST_ROUTE ,
1819 UNISOLATE_HOST_ROUTE ,
1920} from '../../../../common/endpoint/constants' ;
@@ -22,6 +23,7 @@ import {
2223 EndpointAction ,
2324 HostMetadata ,
2425 LogsEndpointAction ,
26+ LogsEndpointActionResponse ,
2527} from '../../../../common/endpoint/types' ;
2628import {
2729 SecuritySolutionPluginRouter ,
@@ -60,6 +62,32 @@ export function registerHostIsolationRoutes(
6062 ) ;
6163}
6264
65+ const createFailedActionResponseEntry = async ( {
66+ context,
67+ doc,
68+ logger,
69+ } : {
70+ context : SecuritySolutionRequestHandlerContext ;
71+ doc : LogsEndpointActionResponse ;
72+ logger : Logger ;
73+ } ) : Promise < void > => {
74+ const esClient = context . core . elasticsearch . client . asCurrentUser ;
75+ try {
76+ await esClient . index < LogsEndpointActionResponse > ( {
77+ index : `${ ENDPOINT_ACTION_RESPONSES_DS } -default` ,
78+ body : {
79+ ...doc ,
80+ error : {
81+ code : '424' ,
82+ message : 'Failed to send action request to agent' ,
83+ } ,
84+ } ,
85+ } ) ;
86+ } catch ( e ) {
87+ logger . error ( e ) ;
88+ }
89+ } ;
90+
6391const doLogsEndpointActionDsExists = async ( {
6492 context,
6593 logger,
@@ -166,12 +194,17 @@ export const isolationRequestHandler = function (
166194 } ;
167195
168196 // if .logs-endpoint.actions data stream exists
169- // create action request record in .logs-endpoint.actions DS as the current user
197+ // try to create action request record in .logs-endpoint.actions DS as the current user
198+ // (from >= v7.16, use this check to ensure the current user has privileges to write to the new index)
199+ // and allow only users with superuser privileges to write to fleet indices
200+ const logger = endpointContext . logFactory . get ( 'host-isolation' ) ;
170201 const doesLogsEndpointActionsDsExist = await doLogsEndpointActionDsExists ( {
171202 context,
172- logger : endpointContext . logFactory . get ( 'host-isolation' ) ,
203+ logger,
173204 dataStreamName : ENDPOINT_ACTIONS_DS ,
174205 } ) ;
206+ // if the new endpoint indices/data streams exists
207+ // write the action request to the new index as the current user
175208 if ( doesLogsEndpointActionsDsExist ) {
176209 try {
177210 const esClient = context . core . elasticsearch . client . asCurrentUser ;
@@ -197,15 +230,14 @@ export const isolationRequestHandler = function (
197230 }
198231 }
199232
200- // create action request record as system user in .fleet-actions
201233 try {
202- // we use this check to ensure the user has permission to write to the new index
203- // and thus allow this action record to be added to the fleet index specifically by kibana
204234 let esClient = context . core . elasticsearch . client . asCurrentUser ;
205235 if ( doesLogsEndpointActionsDsExist ) {
236+ // create action request record as system user with user in .fleet-actions
206237 esClient = context . core . elasticsearch . client . asInternalUser ;
207238 }
208-
239+ // write as the current user if the new indices do not exist
240+ // <v7.16 requires the current user to be super user
209241 fleetActionIndexResult = await esClient . index < EndpointAction > ( {
210242 index : AGENT_ACTIONS_INDEX ,
211243 body : {
@@ -216,6 +248,7 @@ export const isolationRequestHandler = function (
216248 user_id : doc . user . id ,
217249 } ,
218250 } ) ;
251+
219252 if ( fleetActionIndexResult . statusCode !== 201 ) {
220253 return res . customError ( {
221254 statusCode : 500 ,
@@ -225,6 +258,24 @@ export const isolationRequestHandler = function (
225258 } ) ;
226259 }
227260 } catch ( e ) {
261+ // create entry in .logs-endpoint.action.responses-default data stream
262+ // when writing to .fleet-actions fails
263+ if ( doesLogsEndpointActionsDsExist ) {
264+ await createFailedActionResponseEntry ( {
265+ context,
266+ doc : {
267+ '@timestamp' : moment ( ) . toISOString ( ) ,
268+ agent : doc . agent ,
269+ EndpointActions : {
270+ action_id : doc . EndpointActions . action_id ,
271+ completed_at : moment ( ) . toISOString ( ) ,
272+ started_at : moment ( ) . toISOString ( ) ,
273+ data : doc . EndpointActions . data ,
274+ } ,
275+ } ,
276+ logger,
277+ } ) ;
278+ }
228279 return res . customError ( {
229280 statusCode : 500 ,
230281 body : { message : e } ,
0 commit comments