[Security Solution][EDR Workflows] Remove deprecated API's (#199598)

## Summary

- This adds api removals for deprecated API's.
- Also updates OAS documentations and api types.
- Also updates/removes test.

These changes are intended to be for `9.0` and Serverless GA.

API's removed:
- `/api/endpoint/isolate`
- `/api/endpoint/unisolate`
- `/api/endpoint/policy/summaries`
- `/api/endpoint/suggestions/{suggestion_type}`
- `/api/endpoint/action_log/{agent_id}`

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
David Sánchez 2024-11-13 10:59:20 +01:00 committed by GitHub
parent 90b14e2ba9
commit a79695deff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 13 additions and 2343 deletions

View file

@ -7597,34 +7597,6 @@ paths:
summary: Get response actions
tags:
- Security Endpoint Management API
/api/endpoint/action_log/{agent_id}:
get:
deprecated: true
description: Get an action request log for the specified agent ID.
operationId: EndpointGetActionLog
parameters:
- in: path
name: agent_id
required: true
schema:
$ref: '#/components/schemas/Security_Endpoint_Management_API_AgentId'
- in: query
name: query
required: true
schema:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_ActionLogRequestQuery
responses:
'200':
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_SuccessResponse
description: OK
summary: Get an action request log
tags:
- Security Endpoint Management API
/api/endpoint/action_status:
get:
description: Get the status of response actions for the specified agent IDs.
@ -7980,21 +7952,6 @@ paths:
summary: Get metadata
tags:
- Security Endpoint Management API
/api/endpoint/metadata/transforms:
get:
deprecated: true
operationId: GetEndpointMetadataTransform
responses:
'200':
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_SuccessResponse
description: OK
summary: Get metadata transforms
tags:
- Security Endpoint Management API
/api/endpoint/policy_response:
get:
operationId: GetPolicyResponse
@ -8018,33 +7975,6 @@ paths:
summary: Get a policy response
tags:
- Security Endpoint Management API
/api/endpoint/policy/summaries:
get:
deprecated: true
operationId: GetAgentPolicySummary
parameters:
- in: query
name: query
required: true
schema:
type: object
properties:
package_name:
type: string
policy_id:
nullable: true
type: string
responses:
'200':
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_SuccessResponse
description: OK
summary: Get an agent policy summary
tags:
- Security Endpoint Management API
/api/endpoint/protection_updates_note/{package_policy_id}:
get:
operationId: GetProtectionUpdatesNote
@ -8093,44 +8023,6 @@ paths:
summary: Create or update a protection updates note
tags:
- Security Endpoint Management API
/api/endpoint/suggestions/{suggestion_type}:
post:
deprecated: true
operationId: GetEndpointSuggestions
parameters:
- in: path
name: suggestion_type
required: true
schema:
enum:
- eventFilters
type: string
requestBody:
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
type: object
properties:
field:
type: string
fieldMeta: {}
filters: {}
query:
type: string
required:
- parameters
required: true
responses:
'200':
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_SuccessResponse
description: OK
summary: Get suggestions
tags:
- Security Endpoint Management API
/api/entity_store/engines:
get:
operationId: ListEntityEngines
@ -46207,17 +46099,6 @@ components:
required:
- status_code
- message
Security_Endpoint_Management_API_ActionLogRequestQuery:
type: object
properties:
end_date:
$ref: '#/components/schemas/Security_Endpoint_Management_API_EndDate'
page:
$ref: '#/components/schemas/Security_Endpoint_Management_API_Page'
page_size:
$ref: '#/components/schemas/Security_Endpoint_Management_API_PageSize'
start_date:
$ref: '#/components/schemas/Security_Endpoint_Management_API_StartDate'
Security_Endpoint_Management_API_ActionStateSuccessResponse:
type: object
properties:
@ -46536,12 +46417,6 @@ components:
description: Page number
minimum: 1
type: integer
Security_Endpoint_Management_API_PageSize:
default: 10
description: Number of items per page
maximum: 100
minimum: 1
type: integer
Security_Endpoint_Management_API_Parameters:
description: Optional parameters object
type: object

View file

@ -10916,34 +10916,6 @@ paths:
summary: Get response actions
tags:
- Security Endpoint Management API
/api/endpoint/action_log/{agent_id}:
get:
deprecated: true
description: Get an action request log for the specified agent ID.
operationId: EndpointGetActionLog
parameters:
- in: path
name: agent_id
required: true
schema:
$ref: '#/components/schemas/Security_Endpoint_Management_API_AgentId'
- in: query
name: query
required: true
schema:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_ActionLogRequestQuery
responses:
'200':
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_SuccessResponse
description: OK
summary: Get an action request log
tags:
- Security Endpoint Management API
/api/endpoint/action_status:
get:
description: Get the status of response actions for the specified agent IDs.
@ -11258,63 +11230,6 @@ paths:
summary: Upload a file
tags:
- Security Endpoint Management API
/api/endpoint/isolate:
post:
deprecated: true
description: >
Isolate an endpoint from the network.
> info
> This URL will return a 308 permanent redirect to `POST <kibana
host>:<port>/api/endpoint/action/isolate`.
operationId: EndpointIsolateRedirect
requestBody:
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
type: object
properties:
agent_type:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_AgentTypes
alert_ids:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_AlertIds
case_ids:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_CaseIds
comment:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_Comment
endpoint_ids:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_EndpointIds
parameters:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_Parameters
required:
- endpoint_ids
required: true
responses:
'200':
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_SuccessResponse
description: OK
'308':
description: Permanent Redirect
headers:
Location:
description: Permanently redirects to "/api/endpoint/action/isolate"
schema:
example: /api/endpoint/action/isolate
type: string
summary: Isolate an endpoint
tags:
- Security Endpoint Management API
/api/endpoint/metadata:
get:
operationId: GetEndpointMetadataList
@ -11356,21 +11271,6 @@ paths:
summary: Get metadata
tags:
- Security Endpoint Management API
/api/endpoint/metadata/transforms:
get:
deprecated: true
operationId: GetEndpointMetadataTransform
responses:
'200':
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_SuccessResponse
description: OK
summary: Get metadata transforms
tags:
- Security Endpoint Management API
/api/endpoint/policy_response:
get:
operationId: GetPolicyResponse
@ -11394,33 +11294,6 @@ paths:
summary: Get a policy response
tags:
- Security Endpoint Management API
/api/endpoint/policy/summaries:
get:
deprecated: true
operationId: GetAgentPolicySummary
parameters:
- in: query
name: query
required: true
schema:
type: object
properties:
package_name:
type: string
policy_id:
nullable: true
type: string
responses:
'200':
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_SuccessResponse
description: OK
summary: Get an agent policy summary
tags:
- Security Endpoint Management API
/api/endpoint/protection_updates_note/{package_policy_id}:
get:
operationId: GetProtectionUpdatesNote
@ -11469,101 +11342,6 @@ paths:
summary: Create or update a protection updates note
tags:
- Security Endpoint Management API
/api/endpoint/suggestions/{suggestion_type}:
post:
deprecated: true
operationId: GetEndpointSuggestions
parameters:
- in: path
name: suggestion_type
required: true
schema:
enum:
- eventFilters
type: string
requestBody:
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
type: object
properties:
field:
type: string
fieldMeta: {}
filters: {}
query:
type: string
required:
- parameters
required: true
responses:
'200':
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_SuccessResponse
description: OK
summary: Get suggestions
tags:
- Security Endpoint Management API
/api/endpoint/unisolate:
post:
deprecated: true
description: >
Release an isolated endpoint, allowing it to rejoin a network.
> info
> This URL will return a 308 permanent redirect to `POST <kibana
host>:<port>/api/endpoint/action/unisolate`.
operationId: EndpointUnisolateRedirect
requestBody:
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
type: object
properties:
agent_type:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_AgentTypes
alert_ids:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_AlertIds
case_ids:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_CaseIds
comment:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_Comment
endpoint_ids:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_EndpointIds
parameters:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_Parameters
required:
- endpoint_ids
required: true
responses:
'200':
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
$ref: >-
#/components/schemas/Security_Endpoint_Management_API_SuccessResponse
description: OK
'308':
description: Permanent Redirect
headers:
Location:
description: Permanently redirects to "/api/endpoint/action/unisolate"
schema:
example: /api/endpoint/action/unisolate
type: string
summary: Release an isolated endpoint
tags:
- Security Endpoint Management API
/api/entity_store/engines:
get:
operationId: ListEntityEngines
@ -54595,17 +54373,6 @@ components:
required:
- status_code
- message
Security_Endpoint_Management_API_ActionLogRequestQuery:
type: object
properties:
end_date:
$ref: '#/components/schemas/Security_Endpoint_Management_API_EndDate'
page:
$ref: '#/components/schemas/Security_Endpoint_Management_API_Page'
page_size:
$ref: '#/components/schemas/Security_Endpoint_Management_API_PageSize'
start_date:
$ref: '#/components/schemas/Security_Endpoint_Management_API_StartDate'
Security_Endpoint_Management_API_ActionStateSuccessResponse:
type: object
properties:
@ -54924,12 +54691,6 @@ components:
description: Page number
minimum: 1
type: integer
Security_Endpoint_Management_API_PageSize:
default: 10
description: Number of items per page
maximum: 100
minimum: 1
type: integer
Security_Endpoint_Management_API_Parameters:
description: Optional parameters object
type: object

View file

@ -1,27 +0,0 @@
/*
* 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.
*/
/*
* NOTICE: Do not edit this file manually.
* This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
*
* info:
* title: Action Log Schema
* version: 2023-10-31
*/
import { z } from '@kbn/zod';
import { Page, PageSize, StartDate, EndDate } from '../../model/schema/common.gen';
export type ActionLogRequestQuery = z.infer<typeof ActionLogRequestQuery>;
export const ActionLogRequestQuery = z.object({
page: Page.optional(),
page_size: PageSize.optional(),
start_date: StartDate.optional(),
end_date: EndDate.optional(),
});

View file

@ -1,45 +0,0 @@
openapi: 3.0.0
info:
title: Action Log Schema
version: '2023-10-31'
paths:
/api/endpoint/action_log/{agent_id}:
get:
summary: Get an action request log
operationId: EndpointGetActionLog
description: Get an action request log for the specified agent ID.
deprecated: true
x-codegen-enabled: false
x-labels: [ess, serverless]
parameters:
- name: agent_id
in: path
required: true
schema:
$ref: '../../model/schema/common.schema.yaml#/components/schemas/AgentId'
- name: query
in: query
required: true
schema:
$ref: '#/components/schemas/ActionLogRequestQuery'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '../../model/schema/common.schema.yaml#/components/schemas/SuccessResponse'
components:
schemas:
ActionLogRequestQuery:
type: object
properties:
page:
$ref: '../../model/schema/common.schema.yaml#/components/schemas/Page'
page_size:
$ref: '../../model/schema/common.schema.yaml#/components/schemas/PageSize'
start_date:
$ref: '../../model/schema/common.schema.yaml#/components/schemas/StartDate'
end_date:
$ref: '../../model/schema/common.schema.yaml#/components/schemas/EndDate'

View file

@ -6,4 +6,3 @@
*/
export * from './action_log';
export * from './deprecated_action_log.gen';

View file

@ -1,28 +0,0 @@
/*
* 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.
*/
/*
* NOTICE: Do not edit this file manually.
* This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
*
* info:
* title: Endpoint Isolate Schema
* version: 2023-10-31
*/
import type { z } from '@kbn/zod';
import { BaseActionSchema, SuccessResponse } from '../../../model/schema/common.gen';
export type EndpointIsolateRedirectRequestBody = z.infer<typeof EndpointIsolateRedirectRequestBody>;
export const EndpointIsolateRedirectRequestBody = BaseActionSchema;
export type EndpointIsolateRedirectRequestBodyInput = z.input<
typeof EndpointIsolateRedirectRequestBody
>;
export type EndpointIsolateRedirectResponse = z.infer<typeof EndpointIsolateRedirectResponse>;
export const EndpointIsolateRedirectResponse = SuccessResponse;

View file

@ -1,37 +0,0 @@
openapi: 3.0.0
info:
title: Endpoint Isolate Schema
version: '2023-10-31'
paths:
/api/endpoint/isolate:
post:
summary: Isolate an endpoint
description: |
Isolate an endpoint from the network.
> info
> This URL will return a 308 permanent redirect to `POST <kibana host>:<port>/api/endpoint/action/isolate`.
operationId: EndpointIsolateRedirect
deprecated: true
x-codegen-enabled: true
x-labels: [ess]
requestBody:
required: true
content:
application/json:
schema:
$ref: '../../../model/schema/common.schema.yaml#/components/schemas/BaseActionSchema'
responses:
'308':
description: Permanent Redirect
headers:
Location:
description: Permanently redirects to "/api/endpoint/action/isolate"
schema:
type: string
example: "/api/endpoint/action/isolate"
'200':
description: OK
content:
application/json:
schema:
$ref: '../../../model/schema/common.schema.yaml#/components/schemas/SuccessResponse'

View file

@ -1,30 +0,0 @@
/*
* 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.
*/
/*
* NOTICE: Do not edit this file manually.
* This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
*
* info:
* title: Endpoint Unisolate Schema
* version: 2023-10-31
*/
import type { z } from '@kbn/zod';
import { BaseActionSchema, SuccessResponse } from '../../../model/schema/common.gen';
export type EndpointUnisolateRedirectRequestBody = z.infer<
typeof EndpointUnisolateRedirectRequestBody
>;
export const EndpointUnisolateRedirectRequestBody = BaseActionSchema;
export type EndpointUnisolateRedirectRequestBodyInput = z.input<
typeof EndpointUnisolateRedirectRequestBody
>;
export type EndpointUnisolateRedirectResponse = z.infer<typeof EndpointUnisolateRedirectResponse>;
export const EndpointUnisolateRedirectResponse = SuccessResponse;

View file

@ -1,37 +0,0 @@
openapi: 3.0.0
info:
title: Endpoint Unisolate Schema
version: '2023-10-31'
paths:
/api/endpoint/unisolate:
post:
summary: Release an isolated endpoint
description: |
Release an isolated endpoint, allowing it to rejoin a network.
> info
> This URL will return a 308 permanent redirect to `POST <kibana host>:<port>/api/endpoint/action/unisolate`.
operationId: EndpointUnisolateRedirect
deprecated: true
x-codegen-enabled: true
x-labels: [ess]
requestBody:
required: true
content:
application/json:
schema:
$ref: '../../../model/schema/common.schema.yaml#/components/schemas/BaseActionSchema'
responses:
'308':
description: Permanent Redirect
headers:
Location:
description: Permanently redirects to "/api/endpoint/action/unisolate"
schema:
type: string
example: "/api/endpoint/action/unisolate"
'200':
description: OK
content:
application/json:
schema:
$ref: '../../../model/schema/common.schema.yaml#/components/schemas/SuccessResponse'

View file

@ -7,4 +7,3 @@
export * from './unisolate';
export * from './unisolate.gen';
export * from './deprecated_unisolate.gen';

View file

@ -23,13 +23,13 @@ paths:
schema:
$ref: '../model/schema/common.schema.yaml#/components/schemas/SuccessResponse'
/api/endpoint/metadata/transforms:
/internal/api/endpoint/metadata/transforms:
get:
deprecated: true
summary: Get metadata transforms
operationId: GetEndpointMetadataTransform
x-codegen-enabled: false
x-labels: [ess, serverless]
x-internal: true
responses:
'200':
description: OK

View file

@ -1,33 +0,0 @@
/*
* 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.
*/
/*
* NOTICE: Do not edit this file manually.
* This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
*
* info:
* title: Endpoint Policy Schema
* version: 2023-10-31
*/
import { z } from '@kbn/zod';
import { SuccessResponse } from '../model/schema/common.gen';
export type GetAgentPolicySummaryRequestQuery = z.infer<typeof GetAgentPolicySummaryRequestQuery>;
export const GetAgentPolicySummaryRequestQuery = z.object({
query: z.object({
package_name: z.string().optional(),
policy_id: z.string().nullable().optional(),
}),
});
export type GetAgentPolicySummaryRequestQueryInput = z.input<
typeof GetAgentPolicySummaryRequestQuery
>;
export type GetAgentPolicySummaryResponse = z.infer<typeof GetAgentPolicySummaryResponse>;
export const GetAgentPolicySummaryResponse = SuccessResponse;

View file

@ -1,32 +0,0 @@
openapi: 3.0.0
info:
title: Endpoint Policy Schema
version: '2023-10-31'
paths:
/api/endpoint/policy/summaries:
get:
summary: Get an agent policy summary
operationId: GetAgentPolicySummary
deprecated: true
x-codegen-enabled: true
x-labels: [ess, serverless]
parameters:
- name: query
in: query
required: true
schema:
type: object
properties:
package_name:
type: string
policy_id:
type: string
nullable: true
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '../model/schema/common.schema.yaml#/components/schemas/SuccessResponse'

View file

@ -1,15 +0,0 @@
/*
* 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 { schema } from '@kbn/config-schema';
export const GetAgentPolicySummaryRequestSchema = {
query: schema.object({
package_name: schema.string(),
policy_id: schema.nullable(schema.string()),
}),
};

View file

@ -6,6 +6,4 @@
*/
export * from './policy_response';
export * from './deprecated_agent_policy_summary';
export * from './policy_response.gen';
export * from './deprecated_agent_policy_summary.gen';

View file

@ -3,13 +3,13 @@ info:
title: Get Suggestions Schema
version: '2023-10-31'
paths:
/api/endpoint/suggestions/{suggestion_type}:
/internal/api/endpoint/suggestions/{suggestion_type}:
post:
deprecated: true
summary: Get suggestions
operationId: GetEndpointSuggestions
x-codegen-enabled: true
x-labels: [ess, serverless]
x-internal: true
requestBody:
required: true
content:

View file

@ -152,10 +152,6 @@ import type {
EndpointGetFileActionRequestBodyInput,
EndpointGetFileActionResponse,
} from './endpoint/actions/response_actions/get_file/get_file.gen';
import type {
EndpointIsolateRedirectRequestBodyInput,
EndpointIsolateRedirectResponse,
} from './endpoint/actions/response_actions/isolate/deprecated_isolate.gen';
import type {
EndpointIsolateActionRequestBodyInput,
EndpointIsolateActionResponse,
@ -176,10 +172,6 @@ import type {
EndpointSuspendProcessActionRequestBodyInput,
EndpointSuspendProcessActionResponse,
} from './endpoint/actions/response_actions/suspend_process/suspend_process.gen';
import type {
EndpointUnisolateRedirectRequestBodyInput,
EndpointUnisolateRedirectResponse,
} from './endpoint/actions/response_actions/unisolate/deprecated_unisolate.gen';
import type {
EndpointUnisolateActionRequestBodyInput,
EndpointUnisolateActionResponse,
@ -197,10 +189,6 @@ import type {
GetEndpointMetadataListRequestQueryInput,
GetEndpointMetadataListResponse,
} from './endpoint/metadata/get_metadata.gen';
import type {
GetAgentPolicySummaryRequestQueryInput,
GetAgentPolicySummaryResponse,
} from './endpoint/policy/deprecated_agent_policy_summary.gen';
import type {
GetPolicyResponseRequestQueryInput,
GetPolicyResponseResponse,
@ -1011,25 +999,6 @@ If a record already exists for the specified entity, that record is overwritten
})
.catch(catchAxiosErrorFormatAndThrow);
}
/**
* Isolate an endpoint from the network.
> info
> This URL will return a 308 permanent redirect to `POST <kibana host>:<port>/api/endpoint/action/isolate`.
*/
async endpointIsolateRedirect(props: EndpointIsolateRedirectProps) {
this.log.info(`${new Date().toISOString()} Calling API EndpointIsolateRedirect`);
return this.kbnClient
.request<EndpointIsolateRedirectResponse>({
path: '/api/endpoint/isolate',
headers: {
[ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31',
},
method: 'POST',
body: props.body,
})
.catch(catchAxiosErrorFormatAndThrow);
}
/**
* Terminate a running process on an endpoint.
*/
@ -1094,25 +1063,6 @@ If a record already exists for the specified entity, that record is overwritten
})
.catch(catchAxiosErrorFormatAndThrow);
}
/**
* Release an isolated endpoint, allowing it to rejoin a network.
> info
> This URL will return a 308 permanent redirect to `POST <kibana host>:<port>/api/endpoint/action/unisolate`.
*/
async endpointUnisolateRedirect(props: EndpointUnisolateRedirectProps) {
this.log.info(`${new Date().toISOString()} Calling API EndpointUnisolateRedirect`);
return this.kbnClient
.request<EndpointUnisolateRedirectResponse>({
path: '/api/endpoint/unisolate',
headers: {
[ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31',
},
method: 'POST',
body: props.body,
})
.catch(catchAxiosErrorFormatAndThrow);
}
/**
* Upload a file to an endpoint.
*/
@ -1233,20 +1183,6 @@ finalize it.
})
.catch(catchAxiosErrorFormatAndThrow);
}
async getAgentPolicySummary(props: GetAgentPolicySummaryProps) {
this.log.info(`${new Date().toISOString()} Calling API GetAgentPolicySummary`);
return this.kbnClient
.request<GetAgentPolicySummaryResponse>({
path: '/api/endpoint/policy/summaries',
headers: {
[ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31',
},
method: 'GET',
query: props.query,
})
.catch(catchAxiosErrorFormatAndThrow);
}
/**
* Retrieves the rule migrations stats for all migrations stored in the system
*/
@ -1326,7 +1262,7 @@ finalize it.
this.log.info(`${new Date().toISOString()} Calling API GetEndpointSuggestions`);
return this.kbnClient
.request<GetEndpointSuggestionsResponse>({
path: replaceParams('/api/endpoint/suggestions/{suggestion_type}', props.params),
path: replaceParams('/internal/api/endpoint/suggestions/{suggestion_type}', props.params),
headers: {
[ELASTIC_HTTP_VERSION_HEADER]: '2023-10-31',
},
@ -2214,9 +2150,6 @@ export interface EndpointGetProcessesActionProps {
export interface EndpointIsolateActionProps {
body: EndpointIsolateActionRequestBodyInput;
}
export interface EndpointIsolateRedirectProps {
body: EndpointIsolateRedirectRequestBodyInput;
}
export interface EndpointKillProcessActionProps {
body: EndpointKillProcessActionRequestBodyInput;
}
@ -2229,9 +2162,6 @@ export interface EndpointSuspendProcessActionProps {
export interface EndpointUnisolateActionProps {
body: EndpointUnisolateActionRequestBodyInput;
}
export interface EndpointUnisolateRedirectProps {
body: EndpointUnisolateRedirectRequestBodyInput;
}
export interface EndpointUploadActionProps {
body: EndpointUploadActionRequestBodyInput;
}
@ -2252,9 +2182,6 @@ export interface FindAssetCriticalityRecordsProps {
export interface FindRulesProps {
query: FindRulesRequestQueryInput;
}
export interface GetAgentPolicySummaryProps {
query: GetAgentPolicySummaryRequestQueryInput;
}
export interface GetAssetCriticalityRecordProps {
query: GetAssetCriticalityRecordRequestQueryInput;
}

View file

@ -70,30 +70,19 @@ export const BASE_INTERNAL_ENDPOINT_ROUTE = `/internal${BASE_ENDPOINT_ROUTE}`;
export const HOST_METADATA_LIST_ROUTE = `${BASE_ENDPOINT_ROUTE}/metadata`;
export const HOST_METADATA_GET_ROUTE = `${HOST_METADATA_LIST_ROUTE}/{id}`;
/** @deprecated public route, use {@link METADATA_TRANSFORMS_STATUS_INTERNAL_ROUTE} internal route */
export const METADATA_TRANSFORMS_STATUS_ROUTE = `${BASE_ENDPOINT_ROUTE}/metadata/transforms`;
export const METADATA_TRANSFORMS_STATUS_INTERNAL_ROUTE = `${BASE_INTERNAL_ENDPOINT_ROUTE}/metadata/transforms`;
export const BASE_POLICY_RESPONSE_ROUTE = `${BASE_ENDPOINT_ROUTE}/policy_response`;
export const BASE_POLICY_ROUTE = `${BASE_ENDPOINT_ROUTE}/policy`;
export const AGENT_POLICY_SUMMARY_ROUTE = `${BASE_POLICY_ROUTE}/summaries`;
export const PROTECTION_UPDATES_NOTE_ROUTE = `${BASE_ENDPOINT_ROUTE}/protection_updates_note/{package_policy_id}`;
/** Suggestions routes */
/** @deprecated public route, use {@link SUGGESTIONS_INTERNAL_ROUTE} internal route */
export const SUGGESTIONS_ROUTE = `${BASE_ENDPOINT_ROUTE}/suggestions/{suggestion_type}`;
export const SUGGESTIONS_INTERNAL_ROUTE = `${BASE_INTERNAL_ENDPOINT_ROUTE}/suggestions/{suggestion_type}`;
/**
* Action Response Routes
*/
/** @deprecated use `ISOLATE_HOST_ROUTE_V2` instead */
export const ISOLATE_HOST_ROUTE = `${BASE_ENDPOINT_ROUTE}/isolate`;
/** @deprecated use `ISOLATE_HOST_ROUTE_V2` instead */
export const UNISOLATE_HOST_ROUTE = `${BASE_ENDPOINT_ROUTE}/unisolate`;
/** Base Actions route. Used to get a list of all actions and is root to other action related routes */
export const BASE_ENDPOINT_ACTION_ROUTE = `${BASE_ENDPOINT_ROUTE}/action`;

View file

@ -1332,17 +1332,6 @@ export interface GetHostPolicyResponse {
policy_response: HostPolicyResponse;
}
/**
* REST API response for retrieving agent summary
*/
export interface GetAgentSummaryResponse {
summary_response: {
package: string;
policy_id?: string;
versions_count: { [key: string]: number };
};
}
/**
* REST API response for retrieving exception summary
*/

View file

@ -31,32 +31,6 @@ paths:
summary: Get response actions
tags:
- Security Endpoint Management API
/api/endpoint/action_log/{agent_id}:
get:
deprecated: true
description: Get an action request log for the specified agent ID.
operationId: EndpointGetActionLog
parameters:
- in: path
name: agent_id
required: true
schema:
$ref: '#/components/schemas/AgentId'
- in: query
name: query
required: true
schema:
$ref: '#/components/schemas/ActionLogRequestQuery'
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
description: OK
summary: Get an action request log
tags:
- Security Endpoint Management API
/api/endpoint/action_status:
get:
description: Get the status of response actions for the specified agent IDs.
@ -348,56 +322,6 @@ paths:
summary: Upload a file
tags:
- Security Endpoint Management API
/api/endpoint/isolate:
post:
deprecated: true
description: >
Isolate an endpoint from the network.
> info
> This URL will return a 308 permanent redirect to `POST <kibana
host>:<port>/api/endpoint/action/isolate`.
operationId: EndpointIsolateRedirect
requestBody:
content:
application/json:
schema:
type: object
properties:
agent_type:
$ref: '#/components/schemas/AgentTypes'
alert_ids:
$ref: '#/components/schemas/AlertIds'
case_ids:
$ref: '#/components/schemas/CaseIds'
comment:
$ref: '#/components/schemas/Comment'
endpoint_ids:
$ref: '#/components/schemas/EndpointIds'
parameters:
$ref: '#/components/schemas/Parameters'
required:
- endpoint_ids
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
description: OK
'308':
description: Permanent Redirect
headers:
Location:
description: Permanently redirects to "/api/endpoint/action/isolate"
schema:
example: /api/endpoint/action/isolate
type: string
summary: Isolate an endpoint
tags:
- Security Endpoint Management API
/api/endpoint/metadata:
get:
operationId: GetEndpointMetadataList
@ -436,20 +360,6 @@ paths:
summary: Get metadata
tags:
- Security Endpoint Management API
/api/endpoint/metadata/transforms:
get:
deprecated: true
operationId: GetEndpointMetadataTransform
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
description: OK
summary: Get metadata transforms
tags:
- Security Endpoint Management API
/api/endpoint/policy_response:
get:
operationId: GetPolicyResponse
@ -472,32 +382,6 @@ paths:
summary: Get a policy response
tags:
- Security Endpoint Management API
/api/endpoint/policy/summaries:
get:
deprecated: true
operationId: GetAgentPolicySummary
parameters:
- in: query
name: query
required: true
schema:
type: object
properties:
package_name:
type: string
policy_id:
nullable: true
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
description: OK
summary: Get an agent policy summary
tags:
- Security Endpoint Management API
/api/endpoint/protection_updates_note/{package_policy_id}:
get:
operationId: GetProtectionUpdatesNote
@ -544,106 +428,8 @@ paths:
summary: Create or update a protection updates note
tags:
- Security Endpoint Management API
/api/endpoint/suggestions/{suggestion_type}:
post:
deprecated: true
operationId: GetEndpointSuggestions
parameters:
- in: path
name: suggestion_type
required: true
schema:
enum:
- eventFilters
type: string
requestBody:
content:
application/json:
schema:
type: object
properties:
field:
type: string
fieldMeta: {}
filters: {}
query:
type: string
required:
- parameters
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
description: OK
summary: Get suggestions
tags:
- Security Endpoint Management API
/api/endpoint/unisolate:
post:
deprecated: true
description: >
Release an isolated endpoint, allowing it to rejoin a network.
> info
> This URL will return a 308 permanent redirect to `POST <kibana
host>:<port>/api/endpoint/action/unisolate`.
operationId: EndpointUnisolateRedirect
requestBody:
content:
application/json:
schema:
type: object
properties:
agent_type:
$ref: '#/components/schemas/AgentTypes'
alert_ids:
$ref: '#/components/schemas/AlertIds'
case_ids:
$ref: '#/components/schemas/CaseIds'
comment:
$ref: '#/components/schemas/Comment'
endpoint_ids:
$ref: '#/components/schemas/EndpointIds'
parameters:
$ref: '#/components/schemas/Parameters'
required:
- endpoint_ids
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
description: OK
'308':
description: Permanent Redirect
headers:
Location:
description: Permanently redirects to "/api/endpoint/action/unisolate"
schema:
example: /api/endpoint/action/unisolate
type: string
summary: Release an isolated endpoint
tags:
- Security Endpoint Management API
components:
schemas:
ActionLogRequestQuery:
type: object
properties:
end_date:
$ref: '#/components/schemas/EndDate'
page:
$ref: '#/components/schemas/Page'
page_size:
$ref: '#/components/schemas/PageSize'
start_date:
$ref: '#/components/schemas/StartDate'
ActionStateSuccessResponse:
type: object
properties:
@ -951,12 +737,6 @@ components:
description: Page number
minimum: 1
type: integer
PageSize:
default: 10
description: Number of items per page
maximum: 100
minimum: 1
type: integer
Parameters:
description: Optional parameters object
type: object

View file

@ -31,32 +31,6 @@ paths:
summary: Get response actions
tags:
- Security Endpoint Management API
/api/endpoint/action_log/{agent_id}:
get:
deprecated: true
description: Get an action request log for the specified agent ID.
operationId: EndpointGetActionLog
parameters:
- in: path
name: agent_id
required: true
schema:
$ref: '#/components/schemas/AgentId'
- in: query
name: query
required: true
schema:
$ref: '#/components/schemas/ActionLogRequestQuery'
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
description: OK
summary: Get an action request log
tags:
- Security Endpoint Management API
/api/endpoint/action_status:
get:
description: Get the status of response actions for the specified agent IDs.
@ -386,20 +360,6 @@ paths:
summary: Get metadata
tags:
- Security Endpoint Management API
/api/endpoint/metadata/transforms:
get:
deprecated: true
operationId: GetEndpointMetadataTransform
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
description: OK
summary: Get metadata transforms
tags:
- Security Endpoint Management API
/api/endpoint/policy_response:
get:
operationId: GetPolicyResponse
@ -422,32 +382,6 @@ paths:
summary: Get a policy response
tags:
- Security Endpoint Management API
/api/endpoint/policy/summaries:
get:
deprecated: true
operationId: GetAgentPolicySummary
parameters:
- in: query
name: query
required: true
schema:
type: object
properties:
package_name:
type: string
policy_id:
nullable: true
type: string
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
description: OK
summary: Get an agent policy summary
tags:
- Security Endpoint Management API
/api/endpoint/protection_updates_note/{package_policy_id}:
get:
operationId: GetProtectionUpdatesNote
@ -494,56 +428,8 @@ paths:
summary: Create or update a protection updates note
tags:
- Security Endpoint Management API
/api/endpoint/suggestions/{suggestion_type}:
post:
deprecated: true
operationId: GetEndpointSuggestions
parameters:
- in: path
name: suggestion_type
required: true
schema:
enum:
- eventFilters
type: string
requestBody:
content:
application/json:
schema:
type: object
properties:
field:
type: string
fieldMeta: {}
filters: {}
query:
type: string
required:
- parameters
required: true
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
description: OK
summary: Get suggestions
tags:
- Security Endpoint Management API
components:
schemas:
ActionLogRequestQuery:
type: object
properties:
end_date:
$ref: '#/components/schemas/EndDate'
page:
$ref: '#/components/schemas/Page'
page_size:
$ref: '#/components/schemas/PageSize'
start_date:
$ref: '#/components/schemas/StartDate'
ActionStateSuccessResponse:
type: object
properties:
@ -851,12 +737,6 @@ components:
description: Page number
minimum: 1
type: integer
PageSize:
default: 10
description: Number of items per page
maximum: 100
minimum: 1
type: integer
Parameters:
description: Optional parameters object
type: object

View file

@ -1,378 +0,0 @@
/*
* 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 type { KibanaResponseFactory } from '@kbn/core/server';
import {
coreMock,
elasticsearchServiceMock,
httpServerMock,
httpServiceMock,
savedObjectsClientMock,
} from '@kbn/core/server/mocks';
import { ENDPOINT_ACTION_LOG_ROUTE } from '../../../../common/endpoint/constants';
import { EndpointAppContextService } from '../../endpoint_app_context_services';
import {
createMockEndpointAppContext,
createMockEndpointAppContextServiceSetupContract,
createMockEndpointAppContextServiceStartContract,
createRouteHandlerContext,
getRegisteredVersionedRouteMock,
} from '../../mocks';
import { registerActionAuditLogRoutes } from './audit_log';
import { v4 as uuidv4 } from 'uuid';
import type { Results } from './mocks';
import { mockAuditLogSearchResult } from './mocks';
import type { SecuritySolutionRequestHandlerContext } from '../../../types';
import type {
ActivityLog,
EndpointAction,
EndpointActionResponse,
} from '../../../../common/endpoint/types';
import { FleetActionGenerator } from '../../../../common/endpoint/data_generators/fleet_action_generator';
import { EndpointActionGenerator } from '../../../../common/endpoint/data_generators/endpoint_action_generator';
import type {
EndpointActionLogRequestParams,
EndpointActionLogRequestQuery,
} from '../../../../common/api/endpoint';
import { EndpointActionLogRequestSchema } from '../../../../common/api/endpoint';
describe('Action Log API', () => {
describe('schema', () => {
it('should require at least 1 agent ID', () => {
expect(() => {
EndpointActionLogRequestSchema.params.validate({}); // no agent_ids provided
}).toThrow();
});
it('should accept a single agent ID', () => {
expect(() => {
EndpointActionLogRequestSchema.params.validate({ agent_id: uuidv4() });
}).not.toThrow();
});
it('should not work when no params while requesting with query params', () => {
expect(() => {
EndpointActionLogRequestSchema.query.validate({});
}).toThrow();
});
it('should work with all required query params', () => {
expect(() => {
EndpointActionLogRequestSchema.query.validate({
page: 10,
page_size: 100,
start_date: new Date(new Date().setDate(new Date().getDate() - 1)).toISOString(), // yesterday
end_date: new Date().toISOString(), // today
});
}).not.toThrow();
});
it('should not work without endDate', () => {
expect(() => {
EndpointActionLogRequestSchema.query.validate({
page: 1,
page_size: 100,
start_date: new Date(new Date().setDate(new Date().getDate() - 1)).toISOString(), // yesterday
});
}).toThrow();
});
it('should not work without startDate', () => {
expect(() => {
EndpointActionLogRequestSchema.query.validate({
page: 1,
page_size: 100,
end_date: new Date().toISOString(), // today
});
}).toThrow();
});
it('should not work without allowed page and page_size params', () => {
expect(() => {
EndpointActionLogRequestSchema.query.validate({ page_size: 101 });
}).toThrow();
});
});
describe('response', () => {
const mockAgentID = 'XYZABC-000';
let endpointAppContextService: EndpointAppContextService;
const fleetActionGenerator = new FleetActionGenerator('seed');
const endpointActionGenerator = new EndpointActionGenerator('seed');
// convenience for calling the route and handler for audit log
let getActivityLog: (
params: EndpointActionLogRequestParams,
query?: EndpointActionLogRequestQuery
) => Promise<jest.Mocked<KibanaResponseFactory>>;
// convenience for injecting mock action requests and responses
// for .logs-endpoint and .fleet indices
let mockActions: ({
numActions,
hasFleetActions,
hasFleetResponses,
hasResponses,
}: {
numActions: number;
hasFleetActions?: boolean;
hasFleetResponses?: boolean;
hasResponses?: boolean;
}) => void;
let havingErrors: () => void;
beforeEach(() => {
const esClientMock = elasticsearchServiceMock.createScopedClusterClient();
const routerMock = httpServiceMock.createRouter();
endpointAppContextService = new EndpointAppContextService();
endpointAppContextService.setup(createMockEndpointAppContextServiceSetupContract());
endpointAppContextService.start(createMockEndpointAppContextServiceStartContract());
registerActionAuditLogRoutes(routerMock, createMockEndpointAppContext());
getActivityLog = async (
params: { agent_id: string },
query?: { page: number; page_size: number; start_date?: string; end_date?: string }
): Promise<jest.Mocked<KibanaResponseFactory>> => {
const req = httpServerMock.createKibanaRequest({
params,
query,
});
const mockResponse = httpServerMock.createResponseFactory();
const { routeHandler } = getRegisteredVersionedRouteMock(
routerMock,
'get',
ENDPOINT_ACTION_LOG_ROUTE,
'2023-10-31'
);
await routeHandler(
coreMock.createCustomRequestHandlerContext(
createRouteHandlerContext(esClientMock, savedObjectsClientMock.create())
) as SecuritySolutionRequestHandlerContext,
req,
mockResponse
);
return mockResponse;
};
// some arbitrary ids for needed actions
const getMockActionIds = (numAction: number): string[] => {
return [...Array(numAction).keys()].map(() => Math.random().toString(36).split('.')[1]);
};
// create as many actions as needed
const getEndpointActionsData = (actionIds: string[]) => {
const data = actionIds.map((actionId) =>
endpointActionGenerator.generate({
agent: { id: mockAgentID },
EndpointActions: {
action_id: actionId,
},
})
);
return data;
};
// create as many responses as needed
const getEndpointResponseData = (actionIds: string[]) => {
const data = actionIds.map((actionId) =>
endpointActionGenerator.generateResponse({
agent: { id: mockAgentID },
EndpointActions: {
action_id: actionId,
},
})
);
return data;
};
// create as many fleet actions as needed
const getFleetResponseData = (actionIds: string[]) => {
const data = actionIds.map((actionId) =>
fleetActionGenerator.generateResponse({
agent_id: mockAgentID,
action_id: actionId,
})
);
return data;
};
// create as many fleet responses as needed
const getFleetActionData = (actionIds: string[]) => {
const data = actionIds.map((actionId) =>
fleetActionGenerator.generate({
agents: [mockAgentID],
action_id: actionId,
data: {
comment: 'some comment',
},
})
);
return data;
};
// mock actions and responses results in a single response
mockActions = ({
numActions,
hasFleetActions = false,
hasFleetResponses = false,
hasResponses = false,
}: {
numActions: number;
hasFleetActions?: boolean;
hasFleetResponses?: boolean;
hasResponses?: boolean;
}) => {
// @ts-expect-error incomplete types
esClientMock.asInternalUser.search.mockResponseImplementationOnce(() => {
let actions: Results[] = [];
let fleetActions: Results[] = [];
let responses: Results[] = [];
let fleetResponses: Results[] = [];
const actionIds = getMockActionIds(numActions);
actions = getEndpointActionsData(actionIds).map((e) => ({
_index: '.ds-.logs-endpoint.actions-default-2021.19.10-000001',
_source: e,
}));
if (hasFleetActions) {
fleetActions = getFleetActionData(actionIds).map((e) => ({
_index: '.fleet-actions-7',
_source: e,
}));
}
if (hasFleetResponses) {
fleetResponses = getFleetResponseData(actionIds).map((e) => ({
_index: '.ds-.fleet-actions-results-2021.19.10-000001',
_source: e,
}));
}
if (hasResponses) {
responses = getEndpointResponseData(actionIds).map((e) => ({
_index: '.ds-.logs-endpoint.action.responses-default-2021.19.10-000001',
_source: e,
}));
}
const results = mockAuditLogSearchResult([
...actions,
...fleetActions,
...responses,
...fleetResponses,
]);
return results;
});
};
havingErrors = () => {
esClientMock.asInternalUser.search.mockImplementationOnce(() =>
// @ts-expect-error wrong definition
Promise.resolve(() => {
throw new Error();
})
);
};
});
afterEach(() => {
endpointAppContextService.stop();
});
it('should return an empty array when nothing in audit log', async () => {
mockActions({ numActions: 0 });
const response = await getActivityLog({ agent_id: mockAgentID });
expect(response.ok).toBeCalled();
expect((response.ok.mock.calls[0][0]?.body as ActivityLog).data).toHaveLength(0);
});
it('should return fleet actions, fleet responses and endpoint responses', async () => {
mockActions({
numActions: 2,
hasFleetActions: true,
hasFleetResponses: true,
hasResponses: true,
});
const response = await getActivityLog({ agent_id: mockAgentID });
const responseBody = response.ok.mock.calls[0][0]?.body as ActivityLog;
expect(response.ok).toBeCalled();
expect(responseBody.data).toHaveLength(6);
expect(
responseBody.data.filter((e) => (e.item.data as EndpointActionResponse).completed_at)
).toHaveLength(2);
expect(
responseBody.data.filter((e) => (e.item.data as EndpointAction).expiration)
).toHaveLength(2);
});
it('should return only fleet actions and no responses', async () => {
mockActions({ numActions: 2, hasFleetActions: true });
const response = await getActivityLog({ agent_id: mockAgentID });
const responseBody = response.ok.mock.calls[0][0]?.body as ActivityLog;
expect(response.ok).toBeCalled();
expect(responseBody.data).toHaveLength(2);
expect(
responseBody.data.filter((e) => (e.item.data as EndpointAction).expiration)
).toHaveLength(2);
});
it('should only have fleet data', async () => {
mockActions({ numActions: 2, hasFleetActions: true, hasFleetResponses: true });
const response = await getActivityLog({ agent_id: mockAgentID });
const responseBody = response.ok.mock.calls[0][0]?.body as ActivityLog;
expect(response.ok).toBeCalled();
expect(responseBody.data).toHaveLength(4);
expect(
responseBody.data.filter((e) => (e.item.data as EndpointAction).expiration)
).toHaveLength(2);
expect(
responseBody.data.filter((e) => (e.item.data as EndpointActionResponse).completed_at)
).toHaveLength(2);
});
it('should throw errors when no results for some agentID', async () => {
havingErrors();
try {
await getActivityLog({ agent_id: mockAgentID });
} catch (error) {
expect(error.message).toEqual(`Error fetching actions log for agent_id ${mockAgentID}`);
}
});
it('should return date ranges if present in the query', async () => {
mockActions({ numActions: 0 });
const startDate = new Date(new Date().setDate(new Date().getDate() - 1)).toISOString();
const endDate = new Date().toISOString();
const response = await getActivityLog(
{ agent_id: mockAgentID },
{
page: 1,
page_size: 50,
start_date: startDate,
end_date: endDate,
}
);
expect(response.ok).toBeCalled();
expect((response.ok.mock.calls[0][0]?.body as ActivityLog).startDate).toEqual(startDate);
expect((response.ok.mock.calls[0][0]?.body as ActivityLog).endDate).toEqual(endDate);
});
});
});

View file

@ -1,50 +0,0 @@
/*
* 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 { EndpointActionLogRequestSchema } from '../../../../common/api/endpoint';
import { ENDPOINT_ACTION_LOG_ROUTE } from '../../../../common/endpoint/constants';
import { auditLogRequestHandler } from './audit_log_handler';
import type { SecuritySolutionPluginRouter } from '../../../types';
import type { EndpointAppContext } from '../../types';
import { withEndpointAuthz } from '../with_endpoint_authz';
/**
* Registers the endpoint activity_log route
* @deprecated
* @removeBy 9.0.0
*
*/
export function registerActionAuditLogRoutes(
router: SecuritySolutionPluginRouter,
endpointContext: EndpointAppContext
) {
router.versioned
.get({
access: 'public',
path: ENDPOINT_ACTION_LOG_ROUTE,
security: {
authz: {
requiredPrivileges: ['securitySolution'],
},
},
options: { authRequired: true },
})
.addVersion(
{
version: '2023-10-31',
validate: {
request: EndpointActionLogRequestSchema,
},
},
withEndpointAuthz(
{ all: ['canIsolateHost'] },
endpointContext.logFactory.get('hostIsolationLogs'),
auditLogRequestHandler(endpointContext)
)
);
}

View file

@ -1,46 +0,0 @@
/*
* 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 type { RequestHandler } from '@kbn/core/server';
import type {
EndpointActionLogRequestParams,
EndpointActionLogRequestQuery,
} from '../../../../common/api/endpoint';
import type { SecuritySolutionRequestHandlerContext } from '../../../types';
import { getAuditLogResponse } from '../../services/actions/actions_audit_log';
import type { EndpointAppContext } from '../../types';
export const auditLogRequestHandler = (
endpointContext: EndpointAppContext
): RequestHandler<
EndpointActionLogRequestParams,
EndpointActionLogRequestQuery,
unknown,
SecuritySolutionRequestHandlerContext
> => {
const logger = endpointContext.logFactory.get('audit_log');
return async (context, req, res) => {
const {
params: { agent_id: elasticAgentId },
query: { page, page_size: pageSize, start_date: startDate, end_date: endDate },
} = req;
const body = await getAuditLogResponse({
elasticAgentId,
page,
pageSize,
startDate,
endDate,
context,
logger,
});
return res.ok({
body,
});
};
};

View file

@ -12,7 +12,6 @@ import type { SecuritySolutionPluginRouter } from '../../../types';
import type { EndpointAppContext } from '../../types';
import { registerActionStatusRoutes } from './status';
import { registerActionStateRoutes } from './state';
import { registerActionAuditLogRoutes } from './audit_log';
import { registerActionListRoutes } from './list';
import { registerResponseActionRoutes } from './response_actions';
@ -25,7 +24,6 @@ export function registerActionRoutes(
) {
registerActionStatusRoutes(router, endpointContext);
registerActionStateRoutes(router, endpointContext, canEncrypt);
registerActionAuditLogRoutes(router, endpointContext);
registerActionListRoutes(router, endpointContext);
registerActionDetailsRoutes(router, endpointContext);
registerResponseActionRoutes(router, endpointContext);

View file

@ -28,12 +28,10 @@ import {
EXECUTE_ROUTE,
GET_FILE_ROUTE,
GET_PROCESSES_ROUTE,
ISOLATE_HOST_ROUTE,
ISOLATE_HOST_ROUTE_V2,
KILL_PROCESS_ROUTE,
SCAN_ROUTE,
SUSPEND_PROCESS_ROUTE,
UNISOLATE_HOST_ROUTE,
UNISOLATE_HOST_ROUTE_V2,
UPLOAD_ROUTE,
} from '../../../../common/endpoint/constants';
@ -245,28 +243,6 @@ describe('Response actions', () => {
getActionDetailsByIdSpy.mockClear();
});
it('correctly redirects legacy isolate to new route', async () => {
await callRoute(ISOLATE_HOST_ROUTE, {
body: { endpoint_ids: ['XYZ'] },
version: '2023-10-31',
});
expect(mockResponse.custom).toBeCalled();
const response = mockResponse.custom.mock.calls[0][0];
expect(response.statusCode).toEqual(308);
expect(response.headers?.location).toEqual(ISOLATE_HOST_ROUTE_V2);
});
it('correctly redirects legacy release to new route', async () => {
await callRoute(UNISOLATE_HOST_ROUTE, {
body: { endpoint_ids: ['XYZ'] },
version: '2023-10-31',
});
expect(mockResponse.custom).toBeCalled();
const response = mockResponse.custom.mock.calls[0][0];
expect(response.statusCode).toEqual(308);
expect(response.headers?.location).toEqual(UNISOLATE_HOST_ROUTE_V2);
});
it('succeeds when an endpoint ID is provided', async () => {
await callRoute(ISOLATE_HOST_ROUTE_V2, {
body: { endpoint_ids: ['XYZ'] },

View file

@ -6,7 +6,6 @@
*/
import type { RequestHandler } from '@kbn/core/server';
import type { TypeOf } from '@kbn/config-schema';
import { responseActionsWithLegacyActionProperty } from '../../services/actions/constants';
import { stringify } from '../../utils/stringify';
@ -24,7 +23,6 @@ import {
GetProcessesRouteRequestSchema,
IsolateRouteRequestSchema,
KillProcessRouteRequestSchema,
type NoParametersRequestSchema,
type ResponseActionGetFileRequestBody,
type ResponseActionsRequestBody,
type ScanActionRequestBody,
@ -39,12 +37,10 @@ import {
EXECUTE_ROUTE,
GET_FILE_ROUTE,
GET_PROCESSES_ROUTE,
ISOLATE_HOST_ROUTE,
ISOLATE_HOST_ROUTE_V2,
KILL_PROCESS_ROUTE,
SCAN_ROUTE,
SUSPEND_PROCESS_ROUTE,
UNISOLATE_HOST_ROUTE,
UNISOLATE_HOST_ROUTE_V2,
UPLOAD_ROUTE,
} from '../../../../common/endpoint/constants';
@ -73,58 +69,6 @@ export function registerResponseActionRoutes(
) {
const logger = endpointContext.logFactory.get('hostIsolation');
/**
* @deprecated use ISOLATE_HOST_ROUTE_V2 instead
*/
router.versioned
.post({
access: 'public',
path: ISOLATE_HOST_ROUTE,
security: {
authz: {
requiredPrivileges: ['securitySolution'],
},
},
options: { authRequired: true },
})
.addVersion(
{
version: '2023-10-31',
validate: {
request: IsolateRouteRequestSchema,
},
},
withEndpointAuthz({ all: ['canIsolateHost'] }, logger, redirectHandler(ISOLATE_HOST_ROUTE_V2))
);
/**
* @deprecated use RELEASE_HOST_ROUTE instead
*/
router.versioned
.post({
access: 'public',
path: UNISOLATE_HOST_ROUTE,
security: {
authz: {
requiredPrivileges: ['securitySolution'],
},
},
options: { authRequired: true },
})
.addVersion(
{
version: '2023-10-31',
validate: {
request: UnisolateRouteRequestSchema,
},
},
withEndpointAuthz(
{ all: ['canUnIsolateHost'] },
logger,
redirectHandler(UNISOLATE_HOST_ROUTE_V2)
)
);
router.versioned
.post({
access: 'public',
@ -475,20 +419,3 @@ async function handleActionCreation(
);
}
}
function redirectHandler(
location: string
): RequestHandler<
unknown,
unknown,
TypeOf<typeof NoParametersRequestSchema.body>,
SecuritySolutionRequestHandlerContext
> {
return async (context, _req, res) => {
const basePath = (await context.securitySolution).getServerBasePath();
return res.custom({
statusCode: 308,
headers: { location: `${basePath}${location}` },
});
};
}

View file

@ -24,7 +24,6 @@ import {
HOST_METADATA_GET_ROUTE,
HOST_METADATA_LIST_ROUTE,
METADATA_TRANSFORMS_STATUS_INTERNAL_ROUTE,
METADATA_TRANSFORMS_STATUS_ROUTE,
} from '../../../../common/endpoint/constants';
import { withEndpointAuthz } from '../with_endpoint_authz';
@ -95,31 +94,6 @@ export function registerEndpointRoutes(
)
);
router.versioned
.get({
access: 'public',
path: METADATA_TRANSFORMS_STATUS_ROUTE,
security: {
authz: {
requiredPrivileges: ['securitySolution'],
},
},
options: { authRequired: true },
// @ts-expect-error TODO(https://github.com/elastic/kibana/issues/196095): Replace {RouteDeprecationInfo}
deprecated: true,
})
.addVersion(
{
version: '2023-10-31',
validate: false,
},
withEndpointAuthz(
{ all: ['canReadSecuritySolution'] },
logger,
getMetadataTransformStatsHandler(endpointAppContext, logger)
)
);
router.versioned
.get({
access: 'internal',

View file

@ -7,12 +7,11 @@
import { EndpointAppContextService } from '../../endpoint_app_context_services';
import {
createMockEndpointAppContext,
createMockEndpointAppContextServiceSetupContract,
createMockEndpointAppContextServiceStartContract,
createRouteHandlerContext,
} from '../../mocks';
import { getHostPolicyResponseHandler, getAgentPolicySummaryHandler } from './handlers';
import { getHostPolicyResponseHandler } from './handlers';
import type { KibanaResponseFactory, SavedObjectsClientContract } from '@kbn/core/server';
import {
elasticsearchServiceMock,
@ -23,8 +22,6 @@ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import type { GetHostPolicyResponse, HostPolicyResponse } from '../../../../common/endpoint/types';
import { EndpointDocGenerator } from '../../../../common/endpoint/generate_data';
import { requestContextMock } from '../../../lib/detection_engine/routes/__mocks__';
import type { Agent } from '@kbn/fleet-plugin/common/types/models';
import type { AgentClient } from '@kbn/fleet-plugin/server/services';
import { get } from 'lodash';
import type { ScopedClusterClientMock } from '@kbn/core-elasticsearch-client-server-mocks';
import type { TypeOf } from '@kbn/config-schema';
@ -127,141 +124,6 @@ describe('test policy response handler', () => {
expect(getInternalFleetServicesSpy).toHaveBeenCalledWith('foo');
});
});
describe('test agent policy summary handler', () => {
let mockAgentClient: jest.Mocked<AgentClient>;
let agentListResult: {
agents: Agent[];
total: number;
page: number;
perPage: number;
};
let emptyAgentListResult: {
agents: Agent[];
total: number;
page: number;
perPage: number;
};
beforeEach(() => {
mockScopedClient = elasticsearchServiceMock.createScopedClusterClient();
mockSavedObjectClient = savedObjectsClientMock.create();
mockResponse = httpServerMock.createResponseFactory();
endpointAppContextService = new EndpointAppContextService();
emptyAgentListResult = {
agents: [],
total: 2,
page: 1,
perPage: 1,
};
agentListResult = {
agents: [
{
local_metadata: {
elastic: {
agent: {
version: '8.0.0',
},
},
},
} as unknown as Agent,
{
local_metadata: {
elastic: {
agent: {
version: '8.0.0',
},
},
},
} as unknown as Agent,
{
local_metadata: {
elastic: {
agent: {
version: '8.1.0',
},
},
},
} as unknown as Agent,
],
total: 2,
page: 1,
perPage: 1,
};
endpointAppContextService.setup(createMockEndpointAppContextServiceSetupContract());
endpointAppContextService.start({
...createMockEndpointAppContextServiceStartContract(),
});
mockAgentClient = endpointAppContextService.getInternalFleetServices()
.agent as jest.Mocked<AgentClient>;
});
afterEach(() => endpointAppContextService.stop());
it('should return the summary of all the agent with the given policy name', async () => {
mockAgentClient.listAgents
.mockImplementation(() => Promise.resolve(emptyAgentListResult))
.mockImplementationOnce(() => Promise.resolve(agentListResult));
const policySummarysHandler = getAgentPolicySummaryHandler({
...createMockEndpointAppContext(),
service: endpointAppContextService,
});
const mockRequest = httpServerMock.createKibanaRequest({
query: { policy_id: '41a1b470-221b-11eb-8fba-fb9c0d46ace3', package_name: 'endpoint' },
});
await policySummarysHandler(
requestContextMock.convertContext(
createRouteHandlerContext(mockScopedClient, mockSavedObjectClient)
),
mockRequest,
mockResponse
);
expect(mockResponse.ok).toBeCalled();
expect(mockResponse.ok.mock.calls[0][0]?.body).toEqual({
summary_response: {
policy_id: '41a1b470-221b-11eb-8fba-fb9c0d46ace3',
package: 'endpoint',
versions_count: { '8.0.0': 2, '8.1.0': 1 },
},
});
});
it('should return the agent summary', async () => {
mockAgentClient.listAgents
.mockImplementationOnce(() => Promise.resolve(agentListResult))
.mockImplementationOnce(() => Promise.resolve(emptyAgentListResult));
const agentPolicySummaryHandler = getAgentPolicySummaryHandler({
...createMockEndpointAppContext(),
service: endpointAppContextService,
});
const mockRequest = httpServerMock.createKibanaRequest({
query: { package_name: 'endpoint' },
});
await agentPolicySummaryHandler(
requestContextMock.convertContext(
createRouteHandlerContext(mockScopedClient, mockSavedObjectClient)
),
mockRequest,
mockResponse
);
expect(mockResponse.ok).toBeCalled();
expect(mockResponse.ok.mock.calls[0][0]?.body).toEqual({
summary_response: {
package: 'endpoint',
versions_count: { '8.0.0': 2, '8.1.0': 1 },
},
});
});
});
});
/**

View file

@ -10,13 +10,8 @@ import type { TypeOf } from '@kbn/config-schema';
import type { SecuritySolutionRequestHandlerContext } from '../../../types';
import type { EndpointAppContextService } from '../../endpoint_app_context_services';
import { errorHandler } from '../error_handler';
import type {
GetPolicyResponseSchema,
GetAgentPolicySummaryRequestSchema,
} from '../../../../common/api/endpoint';
import type { EndpointAppContext } from '../../types';
import { getAgentPolicySummary, getPolicyResponseByAgentId } from './service';
import type { GetAgentSummaryResponse } from '../../../../common/endpoint/types';
import type { GetPolicyResponseSchema } from '../../../../common/api/endpoint';
import { getPolicyResponseByAgentId } from './service';
import { NotFoundError } from '../../errors';
export const getHostPolicyResponseHandler = function (
@ -50,30 +45,3 @@ export const getHostPolicyResponseHandler = function (
}
};
};
export const getAgentPolicySummaryHandler = function (
endpointAppContext: EndpointAppContext
): RequestHandler<undefined, TypeOf<typeof GetAgentPolicySummaryRequestSchema.query>, undefined> {
return async (_, request, response) => {
const result = await getAgentPolicySummary(
endpointAppContext,
request,
request.query.package_name,
request.query?.policy_id || undefined
);
const responseBody = {
package: request.query.package_name,
versions_count: { ...result },
};
const body: GetAgentSummaryResponse = {
summary_response: request.query?.policy_id
? { ...responseBody, ...{ policy_id: request.query?.policy_id } }
: responseBody,
};
return response.ok({
body,
});
};
};

View file

@ -5,16 +5,10 @@
* 2.0.
*/
import {
GetPolicyResponseSchema,
GetAgentPolicySummaryRequestSchema,
} from '../../../../common/api/endpoint';
import { GetPolicyResponseSchema } from '../../../../common/api/endpoint';
import type { EndpointAppContext } from '../../types';
import { getHostPolicyResponseHandler, getAgentPolicySummaryHandler } from './handlers';
import {
AGENT_POLICY_SUMMARY_ROUTE,
BASE_POLICY_RESPONSE_ROUTE,
} from '../../../../common/endpoint/constants';
import { getHostPolicyResponseHandler } from './handlers';
import { BASE_POLICY_RESPONSE_ROUTE } from '../../../../common/endpoint/constants';
import { withEndpointAuthz } from '../with_endpoint_authz';
import type { SecuritySolutionPluginRouter } from '../../../types';
@ -45,29 +39,4 @@ export function registerPolicyRoutes(
getHostPolicyResponseHandler(endpointAppContext.service)
)
);
/**
* @deprecated
* @removeBy 9.0.0
*
*/
router.versioned
.get({
access: 'public',
path: AGENT_POLICY_SUMMARY_ROUTE,
options: { authRequired: true },
})
.addVersion(
{
version: '2023-10-31',
validate: {
request: GetAgentPolicySummaryRequestSchema,
},
},
withEndpointAuthz(
{ all: ['canAccessEndpointManagement'] },
logger,
getAgentPolicySummaryHandler(endpointAppContext)
)
);
}

View file

@ -68,38 +68,6 @@ export async function getPolicyResponseByAgentId(
return undefined;
}
const transformAgentVersionMap = (versionMap: Map<string, number>): { [key: string]: number } => {
const data: { [key: string]: number } = {};
versionMap.forEach((value, key) => {
data[key] = value;
});
return data;
};
export async function getAgentPolicySummary(
endpointAppContext: EndpointAppContext,
request: KibanaRequest,
packageName: string,
policyId?: string,
pageSize: number = 1000
): Promise<{ [key: string]: number }> {
const agentQuery = `packages:"${packageName}"`;
if (policyId) {
return transformAgentVersionMap(
await agentVersionsMap(
endpointAppContext,
request,
`${agentQuery} AND policy_id:${policyId}`,
pageSize
)
);
}
return transformAgentVersionMap(
await agentVersionsMap(endpointAppContext, request, agentQuery, pageSize)
);
}
export async function agentVersionsMap(
endpointAppContext: EndpointAppContext,
request: KibanaRequest,

View file

@ -24,7 +24,6 @@ import type { EndpointAppContext } from '../../types';
import {
eventsIndexPattern,
SUGGESTIONS_INTERNAL_ROUTE,
SUGGESTIONS_ROUTE,
} from '../../../../common/endpoint/constants';
import { withEndpointAuthz } from '../with_endpoint_authz';
import { errorHandler } from '../error_handler';
@ -38,33 +37,6 @@ export function registerEndpointSuggestionsRoutes(
config$: Observable<ConfigSchema>,
endpointContext: EndpointAppContext
) {
router.versioned
.post({
access: 'public',
path: SUGGESTIONS_ROUTE,
security: {
authz: {
requiredPrivileges: ['securitySolution'],
},
},
options: { authRequired: true },
// @ts-expect-error TODO(https://github.com/elastic/kibana/issues/196095): Replace {RouteDeprecationInfo}
deprecated: true,
})
.addVersion(
{
version: '2023-10-31',
validate: {
request: EndpointSuggestionsSchema,
},
},
withEndpointAuthz(
{ any: ['canWriteEventFilters'] },
endpointContext.logFactory.get('endpointSuggestions'),
getEndpointSuggestionsRequestHandler(config$, getLogger(endpointContext))
)
);
router.versioned
.post({
access: 'internal',

View file

@ -1,288 +0,0 @@
/*
* 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 type { Logger } from '@kbn/core/server';
import type * as estypes from '@elastic/elasticsearch/lib/api/types';
import type { TransportResult } from '@elastic/elasticsearch';
import { AGENT_ACTIONS_INDEX, AGENT_ACTIONS_RESULTS_INDEX } from '@kbn/fleet-plugin/common';
import {
ENDPOINT_ACTION_RESPONSES_INDEX_PATTERN,
ENDPOINT_ACTIONS_DS,
ENDPOINT_ACTIONS_INDEX,
} from '../../../../common/endpoint/constants';
import type { SecuritySolutionRequestHandlerContext } from '../../../types';
import type {
ActivityLog,
ActivityLogEntry,
EndpointAction,
EndpointActionResponse,
LogsEndpointAction,
LogsEndpointActionResponse,
} from '../../../../common/endpoint/types';
import { doesLogsEndpointActionsIndexExist } from '../../utils';
import {
categorizeActionResults,
categorizeResponseResults,
getDateFilters,
getUniqueLogData,
} from './utils';
import { ACTION_REQUEST_INDICES, ACTION_RESPONSE_INDICES } from './constants';
const queryOptions = {
headers: {
'X-elastic-product-origin': 'fleet',
},
ignore: [404],
};
/**
* Used only for the deprecated `/api/endpoint/action_log/{agent_id}` legacy API route
*
* Use newer response action services instead
*
* @deprecated
*/
export const getAuditLogResponse = async ({
elasticAgentId,
page,
pageSize,
startDate,
endDate,
context,
logger,
}: {
elasticAgentId: string;
page: number;
pageSize: number;
startDate: string;
endDate: string;
context: SecuritySolutionRequestHandlerContext;
logger: Logger;
}): Promise<ActivityLog> => {
const size = Math.floor(pageSize / 2);
const from = page <= 1 ? 0 : page * size - size + 1;
const data = await getActivityLog({
context,
from,
size,
startDate,
endDate,
elasticAgentId,
logger,
});
return {
page,
pageSize,
startDate,
endDate,
data,
};
};
const getActivityLog = async ({
context,
size,
from,
startDate,
endDate,
elasticAgentId,
logger,
}: {
context: SecuritySolutionRequestHandlerContext;
elasticAgentId: string;
size: number;
from: number;
startDate: string;
endDate: string;
logger: Logger;
}): Promise<ActivityLogEntry[]> => {
let actionsResult: TransportResult<estypes.SearchResponse<unknown>, unknown>;
let responsesResult: TransportResult<estypes.SearchResponse<unknown>, unknown>;
try {
// fetch actions with matching agent_id
const { actionIds, actionRequests } = await getActionRequestsResult({
context,
logger,
elasticAgentId,
startDate,
endDate,
size,
from,
});
actionsResult = actionRequests;
// fetch responses with matching unique set of `action_id`s
responsesResult = await getActionResponsesResult({
actionIds: [...new Set(actionIds)], // de-dupe `action_id`s
context,
logger,
elasticAgentId,
startDate,
endDate,
});
} catch (error) {
logger.error(error);
throw error;
}
if (actionsResult?.statusCode !== 200) {
logger.error(`Error fetching actions log for agent_id ${elasticAgentId}`);
throw new Error(`Error fetching actions log for agent_id ${elasticAgentId}`);
}
// label record as `action`, `fleetAction`
const responses = categorizeResponseResults({
results: responsesResult?.body?.hits?.hits as Array<
estypes.SearchHit<EndpointActionResponse | LogsEndpointActionResponse>
>,
});
// label record as `response`, `fleetResponse`
const actions = categorizeActionResults({
results: actionsResult?.body?.hits?.hits as Array<
estypes.SearchHit<EndpointAction | LogsEndpointAction>
>,
});
// filter out the duplicate endpoint actions that also have fleetActions
// include endpoint actions that have no fleet actions
const uniqueLogData = getUniqueLogData([...responses, ...actions]);
// sort by @timestamp in desc order, newest first
const sortedData = getTimeSortedData(uniqueLogData);
return sortedData;
};
const getTimeSortedData = (data: ActivityLog['data']): ActivityLog['data'] => {
return data.sort((a, b) =>
new Date(b.item.data['@timestamp']) > new Date(a.item.data['@timestamp']) ? 1 : -1
);
};
const getActionRequestsResult = async ({
context,
logger,
elasticAgentId,
startDate,
endDate,
size,
from,
}: {
context: SecuritySolutionRequestHandlerContext;
logger: Logger;
elasticAgentId: string;
startDate: string;
endDate: string;
size: number;
from: number;
}): Promise<{
actionIds: string[];
actionRequests: TransportResult<estypes.SearchResponse<unknown>, unknown>;
}> => {
const dateFilters = getDateFilters({ startDate, endDate });
const baseActionFilters = [
{ term: { agents: elasticAgentId } },
{ term: { input_type: 'endpoint' } },
{ term: { type: 'INPUT_ACTION' } },
];
const actionsFilters = [...baseActionFilters, ...dateFilters];
const esClient = (await context.core).elasticsearch.client.asInternalUser;
const hasLogsEndpointActionsIndex = await doesLogsEndpointActionsIndexExist({
esClient,
logger,
indexName: ENDPOINT_ACTIONS_INDEX,
});
const actionsSearchQuery: estypes.SearchRequest = {
index: hasLogsEndpointActionsIndex ? ACTION_REQUEST_INDICES : AGENT_ACTIONS_INDEX,
size,
from,
query: {
bool: {
filter: actionsFilters,
},
},
sort: [
{
'@timestamp': {
order: 'desc',
},
},
],
};
let actionRequests: TransportResult<estypes.SearchResponse<unknown>, unknown>;
try {
actionRequests = await esClient.search(actionsSearchQuery, { ...queryOptions, meta: true });
const actionIds = actionRequests?.body?.hits?.hits?.map((e) => {
return e._index.includes(ENDPOINT_ACTIONS_DS)
? (e._source as LogsEndpointAction).EndpointActions.action_id
: (e._source as EndpointAction).action_id;
});
return { actionIds, actionRequests };
} catch (error) {
logger.error(error);
throw error;
}
};
const getActionResponsesResult = async ({
context,
logger,
elasticAgentId,
actionIds,
startDate,
endDate,
}: {
context: SecuritySolutionRequestHandlerContext;
logger: Logger;
elasticAgentId: string;
actionIds: string[];
startDate: string;
endDate: string;
}): Promise<TransportResult<estypes.SearchResponse<unknown>, unknown>> => {
const dateFilters = getDateFilters({ startDate, endDate });
const baseResponsesFilter = [
{ term: { agent_id: elasticAgentId } },
{ terms: { action_id: actionIds } },
];
const responsesFilters = [...baseResponsesFilter, ...dateFilters];
const esClient = (await context.core).elasticsearch.client.asInternalUser;
const hasLogsEndpointActionResponsesIndex = await doesLogsEndpointActionsIndexExist({
esClient,
logger,
indexName: ENDPOINT_ACTION_RESPONSES_INDEX_PATTERN,
});
const responsesSearchQuery: estypes.SearchRequest = {
index: hasLogsEndpointActionResponsesIndex
? ACTION_RESPONSE_INDICES
: AGENT_ACTIONS_RESULTS_INDEX,
size: 1000,
query: {
bool: {
filter: responsesFilters,
},
},
};
let actionResponses: TransportResult<estypes.SearchResponse<unknown>, unknown>;
try {
actionResponses = await esClient.search(responsesSearchQuery, { ...queryOptions, meta: true });
} catch (error) {
logger.error(error);
throw error;
}
return actionResponses;
};

View file

@ -56,12 +56,10 @@ import { EndpointGetActionsStatusRequestQueryInput } from '@kbn/security-solutio
import { EndpointGetFileActionRequestBodyInput } from '@kbn/security-solution-plugin/common/api/endpoint/actions/response_actions/get_file/get_file.gen';
import { EndpointGetProcessesActionRequestBodyInput } from '@kbn/security-solution-plugin/common/api/endpoint/actions/response_actions/running_procs/running_procs.gen';
import { EndpointIsolateActionRequestBodyInput } from '@kbn/security-solution-plugin/common/api/endpoint/actions/response_actions/isolate/isolate.gen';
import { EndpointIsolateRedirectRequestBodyInput } from '@kbn/security-solution-plugin/common/api/endpoint/actions/response_actions/isolate/deprecated_isolate.gen';
import { EndpointKillProcessActionRequestBodyInput } from '@kbn/security-solution-plugin/common/api/endpoint/actions/response_actions/kill_process/kill_process.gen';
import { EndpointScanActionRequestBodyInput } from '@kbn/security-solution-plugin/common/api/endpoint/actions/response_actions/scan/scan.gen';
import { EndpointSuspendProcessActionRequestBodyInput } from '@kbn/security-solution-plugin/common/api/endpoint/actions/response_actions/suspend_process/suspend_process.gen';
import { EndpointUnisolateActionRequestBodyInput } from '@kbn/security-solution-plugin/common/api/endpoint/actions/response_actions/unisolate/unisolate.gen';
import { EndpointUnisolateRedirectRequestBodyInput } from '@kbn/security-solution-plugin/common/api/endpoint/actions/response_actions/unisolate/deprecated_unisolate.gen';
import { EndpointUploadActionRequestBodyInput } from '@kbn/security-solution-plugin/common/api/endpoint/actions/response_actions/upload/upload.gen';
import {
ExportRulesRequestQueryInput,
@ -74,7 +72,6 @@ import {
import { FinalizeAlertsMigrationRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration.gen';
import { FindAssetCriticalityRecordsRequestQueryInput } from '@kbn/security-solution-plugin/common/api/entity_analytics/asset_criticality/list_asset_criticality.gen';
import { FindRulesRequestQueryInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/find_rules/find_rules_route.gen';
import { GetAgentPolicySummaryRequestQueryInput } from '@kbn/security-solution-plugin/common/api/endpoint/policy/deprecated_agent_policy_summary.gen';
import { GetAssetCriticalityRecordRequestQueryInput } from '@kbn/security-solution-plugin/common/api/entity_analytics/asset_criticality/get_asset_criticality.gen';
import { GetDraftTimelinesRequestQueryInput } from '@kbn/security-solution-plugin/common/api/timeline/get_draft_timelines/get_draft_timelines_route.gen';
import { GetEndpointMetadataListRequestQueryInput } from '@kbn/security-solution-plugin/common/api/endpoint/metadata/get_metadata.gen';
@ -614,20 +611,6 @@ If a record already exists for the specified entity, that record is overwritten
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send(props.body as object);
},
/**
* Isolate an endpoint from the network.
> info
> This URL will return a 308 permanent redirect to `POST <kibana host>:<port>/api/endpoint/action/isolate`.
*/
endpointIsolateRedirect(props: EndpointIsolateRedirectProps, kibanaSpace: string = 'default') {
return supertest
.post(routeWithNamespace('/api/endpoint/isolate', kibanaSpace))
.set('kbn-xsrf', 'true')
.set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send(props.body as object);
},
/**
* Terminate a running process on an endpoint.
*/
@ -678,23 +661,6 @@ If a record already exists for the specified entity, that record is overwritten
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send(props.body as object);
},
/**
* Release an isolated endpoint, allowing it to rejoin a network.
> info
> This URL will return a 308 permanent redirect to `POST <kibana host>:<port>/api/endpoint/action/unisolate`.
*/
endpointUnisolateRedirect(
props: EndpointUnisolateRedirectProps,
kibanaSpace: string = 'default'
) {
return supertest
.post(routeWithNamespace('/api/endpoint/unisolate', kibanaSpace))
.set('kbn-xsrf', 'true')
.set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send(props.body as object);
},
/**
* Upload a file to an endpoint.
*/
@ -781,14 +747,6 @@ finalize it.
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.query(props.query);
},
getAgentPolicySummary(props: GetAgentPolicySummaryProps, kibanaSpace: string = 'default') {
return supertest
.get(routeWithNamespace('/api/endpoint/policy/summaries', kibanaSpace))
.set('kbn-xsrf', 'true')
.set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.query(props.query);
},
/**
* Retrieves the rule migrations stats for all migrations stored in the system
*/
@ -843,7 +801,7 @@ finalize it.
return supertest
.post(
routeWithNamespace(
replaceParams('/api/endpoint/suggestions/{suggestion_type}', props.params),
replaceParams('/internal/api/endpoint/suggestions/{suggestion_type}', props.params),
kibanaSpace
)
)
@ -1535,9 +1493,6 @@ export interface EndpointGetProcessesActionProps {
export interface EndpointIsolateActionProps {
body: EndpointIsolateActionRequestBodyInput;
}
export interface EndpointIsolateRedirectProps {
body: EndpointIsolateRedirectRequestBodyInput;
}
export interface EndpointKillProcessActionProps {
body: EndpointKillProcessActionRequestBodyInput;
}
@ -1550,9 +1505,6 @@ export interface EndpointSuspendProcessActionProps {
export interface EndpointUnisolateActionProps {
body: EndpointUnisolateActionRequestBodyInput;
}
export interface EndpointUnisolateRedirectProps {
body: EndpointUnisolateRedirectRequestBodyInput;
}
export interface EndpointUploadActionProps {
body: EndpointUploadActionRequestBodyInput;
}
@ -1573,9 +1525,6 @@ export interface FindAssetCriticalityRecordsProps {
export interface FindRulesProps {
query: FindRulesRequestQueryInput;
}
export interface GetAgentPolicySummaryProps {
query: GetAgentPolicySummaryRequestQueryInput;
}
export interface GetAssetCriticalityRecordProps {
query: GetAssetCriticalityRecordRequestQueryInput;
}

View file

@ -9,7 +9,6 @@ import { wrapErrorAndRejectPromise } from '@kbn/security-solution-plugin/common/
import {
ACTION_DETAILS_ROUTE,
ACTION_STATUS_ROUTE,
AGENT_POLICY_SUMMARY_ROUTE,
BASE_ENDPOINT_ACTION_ROUTE,
BASE_POLICY_RESPONSE_ROUTE,
EXECUTE_ROUTE,
@ -145,15 +144,6 @@ export default function ({ getService }: FtrProviderContext) {
},
];
const superuserApiList: ApiCallsInterface[] = [
{
method: 'get',
path: `${AGENT_POLICY_SUMMARY_ROUTE}?package_name=endpoint`,
version: '2023-10-31',
body: undefined,
},
];
function replacePathIds(path: string) {
return path.replace('{action_id}', actionId).replace('{agentId}', agentId);
}
@ -188,7 +178,6 @@ export default function ({ getService }: FtrProviderContext) {
...canReadActionsLogManagementApiList,
...canIsolateHostApiList,
...canWriteProcessOperationsApiList,
...superuserApiList,
]) {
it(`should return 403 when [${apiListItem.method.toUpperCase()} ${
apiListItem.path
@ -224,11 +213,7 @@ export default function ({ getService }: FtrProviderContext) {
});
describe('with minimal_all and actions_log_management_read', () => {
for (const apiListItem of [
...canIsolateHostApiList,
...canWriteProcessOperationsApiList,
...superuserApiList,
]) {
for (const apiListItem of [...canIsolateHostApiList, ...canWriteProcessOperationsApiList]) {
it(`should return 403 when [${apiListItem.method.toUpperCase()} ${
apiListItem.path
}]`, async () => {
@ -265,24 +250,6 @@ export default function ({ getService }: FtrProviderContext) {
});
describe('with minimal_all, actions_log_management_all, host_isolation_all, and process_operations_all', () => {
for (const apiListItem of superuserApiList) {
it(`should return 403 when [${apiListItem.method.toUpperCase()} ${
apiListItem.path
}]`, async () => {
await endpointOperationsAnalystSupertest[apiListItem.method](
replacePathIds(apiListItem.path)
)
.set('kbn-xsrf', 'xxx')
.send(getBodyPayload(apiListItem))
.expect(403, {
statusCode: 403,
error: 'Forbidden',
message: 'Endpoint authorization failure',
})
.catch(wrapErrorAndRejectPromise);
});
}
for (const apiListItem of [
...canReadSecuritySolutionApiList,
...canReadActionsLogManagementApiList,
@ -330,17 +297,6 @@ export default function ({ getService }: FtrProviderContext) {
.expect(200);
});
}
for (const apiListItem of [...superuserApiList]) {
// Admin user has no access to these APIs
it(`@skipInServerless should return 200 when [${apiListItem.method.toUpperCase()} ${
apiListItem.path
}]`, async () => {
await adminSupertest[apiListItem.method](replacePathIds(apiListItem.path))
.set('kbn-xsrf', 'xxx')
.send(getBodyPayload(apiListItem))
.expect(200);
});
}
});
});
}