Skip to content

Commit a24c33d

Browse files
[EDR Workflows][Move endpoint exceptions] Endpoint Exceptions page added (#232388)
## Summary This PR adds the Endpoint Exceptions list page: - accessible from - Manage sidebar (ess classic solution view) / Endpoint Exceptions - Administration landing page (ess classic solution view) / Endpoint Exceptions - Assets sidebar (serverless, ess security solution view) - or directly: `/app/security/administration/endpoint_exceptions` - it lists existing Endpoint Exceptions - items are searchable - items are deletable - add/edit form is only a placeholder so far, they can be created/edited under Rules / Shared exception lists > [!important] > Moving Endpoint Exceptions is behind feature flag, so until it is not released, existing behavior (accessing EE from shared exception lists page etc.) should be intact. This is hopefully enforced by existing tests (e.g. #229469) and new ones in `x-pack/solutions/security/plugins/security_solution/public/management/cypress/e2e/artifacts/endpoint_exceptions.no_ff.cy.ts` ## Dev notes - Endpoint exceptions are already added to `ENDPOINT_ARTIFACT_LISTS` (c8560ca), to allow artifact list page creating the list on page load in case it does not exist. It exists usually, created by [`TelemetryReceiver`](https://github.com/elastic/kibana/blob/main/x-pack/solutions/security/plugins/security_solution/server/lib/telemetry/receiver.ts#L691) class. - To keep existing behavior, Endpoint exceptions are removed on-the-fly from the array, see the same commit. - I didn't add a lot of tests testing the new functionalities - I plan to have them tested with the existing [`artifacts_rbac_runner.ts`](https://github.com/elastic/kibana/blob/main/x-pack/solutions/security/plugins/security_solution/public/management/cypress/support/artifacts_rbac_runner.ts), similarly to other artifacts. This is possible after having the form and separate Endpoint Exceptions sub-feature privilege in place. ## Testing Enable feature flag in `kibana.dev.yml`: ``` xpack.securitySolution.enableExperimental: - endpointExceptionsMovedUnderManagement ``` ## Screenshots <img width="1110" height="792" alt="image" src="https://github.com/user-attachments/assets/a392a082-64d9-4c1e-b55c-8d4e730ce13c" /> <img width="1185" height="818" alt="image" src="https://github.com/user-attachments/assets/dd7111b4-deb5-4940-82c8-b6eb19987496" /> <img width="1183" height="815" alt="image" src="https://github.com/user-attachments/assets/53dfed0a-92ab-4ca1-8772-0f0e95703972" /> ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md) - [x] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: kibanamachine <[email protected]>
1 parent 0bbed22 commit a24c33d

File tree

32 files changed

+530
-111
lines changed

32 files changed

+530
-111
lines changed

src/core/server/integration_tests/ci_checks/saved_objects/check_registered_types.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -616,14 +616,14 @@ describe('checking migration metadata changes on all registered SO types', () =>
616616
"exception-list|global: 2fc362be1e05f3e803d39cb797e9ea43e9478345",
617617
"exception-list|mappings: 1f3416248aa7578d5991d999e03203cc58baa672",
618618
"exception-list|schemas: da39a3ee5e6b4b0d3255bfef95601890afd80709",
619-
"exception-list|7.12.0: 3cffb58252bde867d70b355d53761c24ef628037",
620-
"exception-list|7.10.0: 8387f4bc4f3cf15a5f7bb2d2ddb8615c48d367a6",
619+
"exception-list|7.12.0: 8fb1a0cfe64b45f6d2f0381d1423a8729ce25b33",
620+
"exception-list|7.10.0: d2e0295e197370f4f1ea94c42123de72a4743cc7",
621621
"===============================================================",
622622
"exception-list-agnostic|global: 1ffcd5258404959329b6eae33af667176d823b33",
623623
"exception-list-agnostic|mappings: 1f3416248aa7578d5991d999e03203cc58baa672",
624624
"exception-list-agnostic|schemas: da39a3ee5e6b4b0d3255bfef95601890afd80709",
625-
"exception-list-agnostic|7.12.0: 3cffb58252bde867d70b355d53761c24ef628037",
626-
"exception-list-agnostic|7.10.0: 8387f4bc4f3cf15a5f7bb2d2ddb8615c48d367a6",
625+
"exception-list-agnostic|7.12.0: 8fb1a0cfe64b45f6d2f0381d1423a8729ce25b33",
626+
"exception-list-agnostic|7.10.0: d2e0295e197370f4f1ea94c42123de72a4743cc7",
627627
"========================================================================",
628628
"favorites|global: 220670249bb4ea98fc6f412e6712a6ae1404585e",
629629
"favorites|mappings: 0632fece42d46938b33f6d3f76a4d9951ce29d4e",

x-pack/solutions/security/packages/kbn-securitysolution-list-constants/index.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,6 @@ export const ENDPOINT_LIST_URL = '/api/endpoint_list';
5353
*/
5454
export const ENDPOINT_LIST_ITEM_URL = '/api/endpoint_list/items';
5555

56-
/**
57-
* This ID is used for _both_ the Saved Object ID and for the list_id
58-
* for the single global space agnostic endpoint list
59-
*/
60-
export const ENDPOINT_LIST_ID = 'endpoint_list';
61-
62-
/** The name of the single global space agnostic endpoint list */
63-
export const ENDPOINT_LIST_NAME = 'Endpoint Security Exception List';
64-
65-
/** The description of the single global space agnostic endpoint list */
66-
export const ENDPOINT_LIST_DESCRIPTION = 'Endpoint Security Exception List';
67-
6856
export const MAX_EXCEPTION_LIST_SIZE = 10000;
6957

7058
export const MAXIMUM_SMALL_VALUE_LIST_SIZE = 65536;
@@ -75,6 +63,11 @@ export const MAXIMUM_SMALL_IP_RANGE_VALUE_LIST_DASH_SIZE = 200;
7563
* List definitions for Endpoint Artifact
7664
*/
7765
export const ENDPOINT_ARTIFACT_LISTS = deepFreeze({
66+
endpointExceptions: {
67+
id: 'endpoint_list',
68+
name: 'Endpoint Security Exception List',
69+
description: 'Endpoint Security Exception List',
70+
},
7871
trustedApps: {
7972
id: 'endpoint_trusted_apps',
8073
name: 'Endpoint Security Trusted Apps List',
@@ -109,6 +102,13 @@ export const ENDPOINT_ARTIFACT_LIST_IDS = Object.freeze(
109102
Object.values(ENDPOINT_ARTIFACT_LISTS).map(({ id }) => id)
110103
);
111104

105+
/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead.
106+
*
107+
* This ID is used for _both_ the Saved Object ID and for the list_id
108+
* for the single global space agnostic endpoint list
109+
*/
110+
export const ENDPOINT_LIST_ID = ENDPOINT_ARTIFACT_LISTS.endpointExceptions.id;
111+
112112
/** @deprecated Use `ENDPOINT_ARTIFACT_LISTS` instead */
113113
export const ENDPOINT_TRUSTED_APPS_LIST_ID = ENDPOINT_ARTIFACT_LISTS.trustedApps.id;
114114

x-pack/solutions/security/plugins/lists/server/saved_objects/migrations.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ import type {
1414
entry,
1515
} from '@kbn/securitysolution-io-ts-list-types';
1616
import { entriesNested } from '@kbn/securitysolution-io-ts-list-types';
17-
import {
18-
ENDPOINT_LIST_ID,
19-
ENDPOINT_TRUSTED_APPS_LIST_ID,
20-
} from '@kbn/securitysolution-list-constants';
17+
import { ENDPOINT_ARTIFACT_LISTS } from '@kbn/securitysolution-list-constants';
2118

2219
import type { ExceptionListSoSchema } from '../schemas/saved_objects';
2320

@@ -58,7 +55,12 @@ export const migrations = {
5855
attributes: {
5956
...doc.attributes,
6057
...(doc.attributes.entries &&
61-
[ENDPOINT_LIST_ID, ENDPOINT_TRUSTED_APPS_LIST_ID].includes(doc.attributes.list_id) && {
58+
(
59+
[
60+
ENDPOINT_ARTIFACT_LISTS.endpointExceptions.id,
61+
ENDPOINT_ARTIFACT_LISTS.trustedApps.id,
62+
] as string[]
63+
).includes(doc.attributes.list_id) && {
6264
entries: (doc.attributes.entries as EntriesArray).map<EntryType>(migrateEntry),
6365
}),
6466
...(doc.attributes._tags &&
@@ -72,7 +74,7 @@ export const migrations = {
7274
'7.12.0': (
7375
doc: SavedObjectUnsanitizedDoc<ExceptionListSoSchema>
7476
): SavedObjectSanitizedDoc<ExceptionListSoSchema> => {
75-
if (doc.attributes.list_id === ENDPOINT_TRUSTED_APPS_LIST_ID) {
77+
if (doc.attributes.list_id === ENDPOINT_ARTIFACT_LISTS.trustedApps.id) {
7678
return {
7779
...doc,
7880
...{

x-pack/solutions/security/plugins/lists/server/services/exception_lists/create_endpoint_list.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,7 @@ import { v4 as uuidv4 } from 'uuid';
1111
import type { Version } from '@kbn/securitysolution-io-ts-types';
1212
import type { ExceptionListSchema } from '@kbn/securitysolution-io-ts-list-types';
1313
import { getSavedObjectType } from '@kbn/securitysolution-list-utils';
14-
import {
15-
ENDPOINT_LIST_DESCRIPTION,
16-
ENDPOINT_LIST_ID,
17-
ENDPOINT_LIST_NAME,
18-
} from '@kbn/securitysolution-list-constants';
14+
import { ENDPOINT_ARTIFACT_LISTS } from '@kbn/securitysolution-list-constants';
1915

2016
import type { ExceptionListSoSchema } from '../../schemas/saved_objects';
2117

@@ -43,15 +39,15 @@ export const createEndpointList = async ({
4339
comments: undefined,
4440
created_at: dateNow,
4541
created_by: user,
46-
description: ENDPOINT_LIST_DESCRIPTION,
42+
description: ENDPOINT_ARTIFACT_LISTS.endpointExceptions.description,
4743
entries: undefined,
4844
expire_time: undefined,
4945
immutable: false,
5046
item_id: undefined,
51-
list_id: ENDPOINT_LIST_ID,
47+
list_id: ENDPOINT_ARTIFACT_LISTS.endpointExceptions.id,
5248
list_type: 'list',
5349
meta: undefined,
54-
name: ENDPOINT_LIST_NAME,
50+
name: ENDPOINT_ARTIFACT_LISTS.endpointExceptions.name,
5551
os_types: [],
5652
tags: [],
5753
tie_breaker_id: tieBreaker ?? uuidv4(),
@@ -61,7 +57,7 @@ export const createEndpointList = async ({
6157
},
6258
{
6359
// We intentionally hard coding the id so that there can only be one exception list within the space
64-
id: ENDPOINT_LIST_ID,
60+
id: ENDPOINT_ARTIFACT_LISTS.endpointExceptions.id,
6561
}
6662
);
6763
return transformSavedObjectToExceptionList({ savedObject });

x-pack/solutions/security/plugins/security_solution/common/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ export const APP_ALERTS_PATH = `${APP_PATH}${ALERTS_PATH}` as const;
139139
export const APP_CASES_PATH = `${APP_PATH}${CASES_PATH}` as const;
140140
export const APP_ENDPOINTS_PATH = `${APP_PATH}${ENDPOINTS_PATH}` as const;
141141
export const APP_POLICIES_PATH = `${APP_PATH}${POLICIES_PATH}` as const;
142+
export const APP_ENDPOINT_EXCEPTIONS_PATH = `${APP_PATH}${ENDPOINT_EXCEPTIONS_PATH}` as const;
143+
export const APP_MANAGE_PATH = `${APP_PATH}${MANAGE_PATH}` as const;
142144
export const APP_TRUSTED_APPS_PATH = `${APP_PATH}${TRUSTED_APPS_PATH}` as const;
143145
export const APP_EVENT_FILTERS_PATH = `${APP_PATH}${EVENT_FILTERS_PATH}` as const;
144146
export const APP_HOST_ISOLATION_EXCEPTIONS_PATH =

x-pack/solutions/security/plugins/security_solution/public/exceptions/api/list_api.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type { HttpSetup } from '@kbn/core-http-browser';
1111
import { getFilters } from '@kbn/securitysolution-list-utils';
1212
import type { List, ListArray } from '@kbn/securitysolution-io-ts-list-types';
1313
import { asyncForEach } from '@kbn/std';
14+
import { ENDPOINT_ARTIFACT_LISTS } from '@kbn/securitysolution-list-constants';
1415
import { ALL_ENDPOINT_ARTIFACT_LIST_IDS } from '../../../common/endpoint/service/artifacts/constants';
1516
import type {
1617
FetchListById,
@@ -27,7 +28,9 @@ export const getListById = async ({ id, http }: FetchListById) => {
2728
const filters = getFilters({
2829
filters: { list_id: id },
2930
namespaceTypes: ['single', 'agnostic'],
30-
hideLists: ALL_ENDPOINT_ARTIFACT_LIST_IDS,
31+
hideLists: ALL_ENDPOINT_ARTIFACT_LIST_IDS.filter(
32+
(listId) => listId !== ENDPOINT_ARTIFACT_LISTS.endpointExceptions.id // todo: remove when removing endpoint exceptions from detections pages
33+
),
3134
});
3235
const namespaceTypes = ['single', 'agnostic'].join();
3336

x-pack/solutions/security/plugins/security_solution/public/exceptions/hooks/use_list_detail_view/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { ViewerStatus } from '@kbn/securitysolution-exception-list-components';
1414
import type { ExceptionListSchema, NamespaceType } from '@kbn/securitysolution-io-ts-list-types';
1515
import { useApi } from '@kbn/securitysolution-list-hooks';
1616
import { isEqual } from 'lodash';
17+
import { ENDPOINT_ARTIFACT_LISTS } from '@kbn/securitysolution-list-constants';
1718
import { ALL_ENDPOINT_ARTIFACT_LIST_IDS } from '../../../../common/endpoint/service/artifacts/constants';
1819
import { useUserData } from '../../../detections/components/user_info';
1920
import { APP_UI_ID, SecurityPageName } from '../../../../common/constants';
@@ -114,7 +115,10 @@ export const useListDetailsView = (exceptionListId: string) => {
114115

115116
const initializeList = useCallback(async () => {
116117
try {
117-
if ((ALL_ENDPOINT_ARTIFACT_LIST_IDS as string[]).includes(exceptionListId))
118+
const endpointArtifactIds = ALL_ENDPOINT_ARTIFACT_LIST_IDS.filter(
119+
(listId) => listId !== ENDPOINT_ARTIFACT_LISTS.endpointExceptions.id
120+
);
121+
if ((endpointArtifactIds as string[]).includes(exceptionListId))
118122
return setInvalidListId(true);
119123
setIsLoading(true);
120124

x-pack/solutions/security/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
2929
import { useApi, useExceptionLists } from '@kbn/securitysolution-list-hooks';
3030
import { EmptyViewerState, ViewerStatus } from '@kbn/securitysolution-exception-list-components';
3131

32+
import { ENDPOINT_ARTIFACT_LISTS } from '@kbn/securitysolution-list-constants';
3233
import { AutoDownload } from '../../../common/components/auto_download/auto_download';
3334
import { useKibana } from '../../../common/lib/kibana';
3435
import { useAppToasts } from '../../../common/hooks/use_app_toasts';
@@ -133,7 +134,9 @@ export const SharedLists = React.memo(() => {
133134
http,
134135
namespaceTypes: ['single', 'agnostic'],
135136
notifications,
136-
hideLists: ALL_ENDPOINT_ARTIFACT_LIST_IDS,
137+
hideLists: ALL_ENDPOINT_ARTIFACT_LIST_IDS.filter(
138+
(listId) => listId !== ENDPOINT_ARTIFACT_LISTS.endpointExceptions.id
139+
),
137140
});
138141
const [loadingTableInfo, exceptionListsWithRuleRefs, exceptionsListsRef] = useAllExceptionLists({
139142
exceptionLists: exceptions ?? [],

x-pack/solutions/security/plugins/security_solution/public/management/common/breadcrumbs.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
ENDPOINTS_TAB,
1212
EVENT_FILTERS_TAB,
1313
POLICIES_TAB,
14+
ENDPOINT_EXCEPTIONS_TAB,
1415
TRUSTED_APPS_TAB,
1516
TRUSTED_DEVICES_TAB,
1617
} from './translations';
@@ -26,6 +27,7 @@ import {
2627
const TabNameMappedToI18nKey: Record<AdministrationSubTab, string> = {
2728
[AdministrationSubTab.endpoints]: ENDPOINTS_TAB,
2829
[AdministrationSubTab.policies]: POLICIES_TAB,
30+
[AdministrationSubTab.endpointExceptions]: ENDPOINT_EXCEPTIONS_TAB,
2931
[AdministrationSubTab.trustedApps]: TRUSTED_APPS_TAB,
3032
[AdministrationSubTab.trustedDevices]: TRUSTED_DEVICES_TAB,
3133
[AdministrationSubTab.eventFilters]: EVENT_FILTERS_TAB,

x-pack/solutions/security/plugins/security_solution/public/management/common/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export const MANAGEMENT_ROUTING_POLICY_DETAILS_PROTECTION_UPDATES_PATH = `${MANA
2222
export const MANAGEMENT_ROUTING_NOTES_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.notes})`;
2323
/** @deprecated use the paths defined above instead */
2424
export const MANAGEMENT_ROUTING_POLICY_DETAILS_PATH_OLD = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId`;
25+
export const MANAGEMENT_ROUTING_ENDPOINT_EXCEPTIONS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.endpointExceptions})`;
2526
export const MANAGEMENT_ROUTING_TRUSTED_APPS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.trustedApps})`;
2627
export const MANAGEMENT_ROUTING_TRUSTED_DEVICES_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.trustedDevices})`;
2728
export const MANAGEMENT_ROUTING_EVENT_FILTERS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.eventFilters})`;

0 commit comments

Comments
 (0)