Skip to content

Commit

Permalink
[Security Solution] [Endpoint] Add blocklist tab in policy view (#127458
Browse files Browse the repository at this point in the history
)

* Adds blocklists tab in policy detail view

* Fixes wrong .id on normalize function

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
dasansol92 and kibanamachine authored Mar 14, 2022
1 parent 56c38b6 commit 6d87f12
Show file tree
Hide file tree
Showing 9 changed files with 295 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const MANAGEMENT_ROUTING_POLICY_DETAILS_FORM_PATH = `${MANAGEMENT_PATH}/:
export const MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId/trustedApps`;
export const MANAGEMENT_ROUTING_POLICY_DETAILS_EVENT_FILTERS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId/eventFilters`;
export const MANAGEMENT_ROUTING_POLICY_DETAILS_HOST_ISOLATION_EXCEPTIONS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId/hostIsolationExceptions`;
export const MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId/blocklists`;
/** @deprecated use the paths defined above instead */
export const MANAGEMENT_ROUTING_POLICY_DETAILS_PATH_OLD = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId`;
export const MANAGEMENT_ROUTING_TRUSTED_APPS_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.trustedApps})`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { isEmpty } from 'lodash/fp';
import querystring from 'querystring';
import { generatePath } from 'react-router-dom';
import { appendSearch } from '../../common/components/link_to/helpers';
import { ArtifactListPageUrlParams } from '../components/artifact_list_page';
import { EndpointIndexUIQueryParams } from '../pages/endpoint_hosts/types';
import { EventFiltersPageLocation } from '../pages/event_filters/types';
import { HostIsolationExceptionsPageLocation } from '../pages/host_isolation_exceptions/types';
Expand All @@ -29,6 +30,8 @@ import {
MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_EVENT_FILTERS_PATH,
MANAGEMENT_ROUTING_TRUSTED_APPS_PATH,
MANAGEMENT_ROUTING_BLOCKLIST_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH,
} from './constants';

// Taken from: https://github.com/microsoft/TypeScript/issues/12936#issuecomment-559034150
Expand Down Expand Up @@ -215,6 +218,29 @@ const normalizeEventFiltersPageLocation = (
}
};

const normalizBlocklistsPageLocation = (
location?: Partial<ArtifactListPageUrlParams>
): Partial<ArtifactListPageUrlParams> => {
if (location) {
return {
...(!isDefaultOrMissing(location.page, MANAGEMENT_DEFAULT_PAGE)
? { page: location.page }
: {}),
...(!isDefaultOrMissing(location.pageSize, MANAGEMENT_DEFAULT_PAGE_SIZE)
? { pageSize: location.pageSize }
: {}),
...(!isDefaultOrMissing(location.show, undefined) ? { show: location.show } : {}),
...(!isDefaultOrMissing(location.itemId, undefined) ? { id: location.itemId } : {}),
...(!isDefaultOrMissing(location.filter, '') ? { filter: location.filter } : ''),
...(!isDefaultOrMissing(location.includedPolicies, '')
? { includedPolicies: location.includedPolicies }
: ''),
};
} else {
return {};
}
};

const normalizeHostIsolationExceptionsPageLocation = (
location?: Partial<HostIsolationExceptionsPageLocation>
): Partial<EventFiltersPageLocation> => {
Expand Down Expand Up @@ -407,3 +433,24 @@ export const getPolicyHostIsolationExceptionsPath = (
querystring.stringify(normalizePolicyDetailsArtifactsListPageLocation(location))
)}`;
};

export const getBlocklistsListPath = (location?: Partial<ArtifactListPageUrlParams>): string => {
const path = generatePath(MANAGEMENT_ROUTING_BLOCKLIST_PATH, {
tabName: AdministrationSubTab.blocklist,
});

return `${path}${appendSearch(querystring.stringify(normalizBlocklistsPageLocation(location)))}`;
};

export const getPolicyBlocklistsPath = (
policyId: string,
location?: Partial<PolicyDetailsArtifactsPageLocation>
) => {
const path = generatePath(MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH, {
tabName: AdministrationSubTab.policies,
policyId,
});
return `${path}${appendSearch(
querystring.stringify(normalizePolicyDetailsArtifactsListPageLocation(location))
)}`;
};
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,12 @@ export const BLOCKLISTS_LIST_DEFINITION: CreateExceptionListSchema = {
list_id: ENDPOINT_BLOCKLISTS_LIST_ID,
type: BLOCKLISTS_LIST_TYPE,
};

export const SEARCHABLE_FIELDS: Readonly<string[]> = [
`name`,
`description`,
'item_id',
`entries.value`,
`entries.entries.value`,
`comments.comment`,
];
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
MANAGEMENT_ROUTING_POLICY_DETAILS_PATH_OLD,
MANAGEMENT_ROUTING_POLICY_DETAILS_HOST_ISOLATION_EXCEPTIONS_PATH,
MANAGEMENT_ROUTING_POLICIES_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH,
} from '../../common/constants';
import { NotFoundPage } from '../../../app/404';
import { getPolicyDetailPath } from '../../common/routing';
Expand All @@ -30,6 +31,7 @@ export const PolicyContainer = memo(() => {
MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_EVENT_FILTERS_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_HOST_ISOLATION_EXCEPTIONS_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH,
]}
exact
component={PolicyDetails}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
MANAGEMENT_ROUTING_POLICY_DETAILS_HOST_ISOLATION_EXCEPTIONS_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_EVENT_FILTERS_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH,
} from '../../../../../common/constants';
import { PolicyDetailsSelector, PolicyDetailsState } from '../../../types';

Expand Down Expand Up @@ -76,3 +77,16 @@ export const isOnHostIsolationExceptionsView: PolicyDetailsSelector<boolean> = c
);
}
);

/** Returns a boolean of whether the user is on the blocklists page or not */
export const isOnBlocklistsView: PolicyDetailsSelector<boolean> = createSelector(
getUrlLocationPathname,
(pathname) => {
return (
matchPath(pathname ?? '', {
path: MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH,
exact: true,
}) !== null
);
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
MANAGEMENT_ROUTING_POLICY_DETAILS_HOST_ISOLATION_EXCEPTIONS_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_EVENT_FILTERS_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH,
} from '../../../../../common/constants';
import { ManagementRoutePolicyDetailsParams } from '../../../../../types';
import { getPolicyDataForUpdate } from '../../../../../../../common/endpoint/service/policy';
Expand All @@ -31,6 +32,7 @@ import {
isOnPolicyEventFiltersView,
isOnHostIsolationExceptionsView,
isOnPolicyFormView,
isOnBlocklistsView,
} from './policy_common_selectors';

/** Returns the policy details */
Expand Down Expand Up @@ -93,7 +95,8 @@ export const isOnPolicyDetailsPage = (state: Immutable<PolicyDetailsState>) =>
isOnPolicyFormView(state) ||
isOnPolicyTrustedAppsView(state) ||
isOnPolicyEventFiltersView(state) ||
isOnHostIsolationExceptionsView(state);
isOnHostIsolationExceptionsView(state) ||
isOnBlocklistsView(state);

/** Returns the license info fetched from the license service */
export const license = (state: Immutable<PolicyDetailsState>) => {
Expand All @@ -111,6 +114,7 @@ export const policyIdFromParams: (state: Immutable<PolicyDetailsState>) => strin
MANAGEMENT_ROUTING_POLICY_DETAILS_TRUSTED_APPS_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_EVENT_FILTERS_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_HOST_ISOLATION_EXCEPTIONS_PATH,
MANAGEMENT_ROUTING_POLICY_DETAILS_BLOCKLISTS_PATH,
],
exact: true,
})?.params?.policyId ?? ''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useCallback } from 'react';
import { useHistory } from 'react-router-dom';
import { useSelector } from 'react-redux';
import {
ENDPOINT_BLOCKLISTS_LIST_ID,
ENDPOINT_EVENT_FILTERS_LIST_ID,
ENDPOINT_TRUSTED_APPS_LIST_ID,
} from '@kbn/securitysolution-list-constants';
Expand All @@ -19,6 +20,7 @@ import {
MANAGEMENT_STORE_POLICY_DETAILS_NAMESPACE,
} from '../../../common/constants';
import {
getPolicyBlocklistsPath,
getPolicyDetailsArtifactsListPath,
getPolicyEventFiltersPath,
getPolicyHostIsolationExceptionsPath,
Expand Down Expand Up @@ -79,6 +81,11 @@ export function usePolicyDetailsArtifactsNavigateCallback(listId: string) {
...location,
...args,
});
} else if (listId === ENDPOINT_BLOCKLISTS_LIST_ID) {
return getPolicyBlocklistsPath(policyId, {
...location,
...args,
});
} else {
return getPolicyHostIsolationExceptionsPath(policyId, {
...location,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';

export const POLICY_ARTIFACT_BLOCKLISTS_LABELS = Object.freeze({
deleteModalTitle: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.list.removeDialog.title',
{
defaultMessage: 'Remove blocklist from policy',
}
),
deleteModalImpactInfo: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.list.removeDialog.messageCallout',
{
defaultMessage:
'This blocklist will be removed only from this policy and can still be found and managed from the artifact page.',
}
),
deleteModalErrorMessage: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.list.removeDialog.errorToastTitle',
{
defaultMessage: 'Error while attempting to remove blocklist',
}
),
flyoutWarningCalloutMessage: (maxNumber: number) =>
i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.layout.flyout.searchWarning.text',
{
defaultMessage:
'Only the first {maxNumber} blocklists are displayed. Please use the search bar to refine the results.',
values: { maxNumber },
}
),
flyoutNoArtifactsToBeAssignedMessage: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.layout.flyout.noAssignable',
{
defaultMessage: 'There are no blocklists that can be assigned to this policy.',
}
),
flyoutTitle: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.layout.flyout.title',
{
defaultMessage: 'Assign blocklists',
}
),
flyoutSubtitle: (policyName: string): string =>
i18n.translate('xpack.securitySolution.endpoint.policy.blocklists.layout.flyout.subtitle', {
defaultMessage: 'Select blocklists to add to {policyName}',
values: { policyName },
}),
flyoutSearchPlaceholder: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.layout.search.label',
{
defaultMessage: 'Search blocklists',
}
),
flyoutErrorMessage: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.layout.flyout.toastError.text',
{
defaultMessage: `An error occurred updating blocklists`,
}
),
flyoutSuccessMessageText: (updatedExceptions: ExceptionListItemSchema[]): string =>
updatedExceptions.length > 1
? i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.layout.flyout.toastSuccess.textMultiples',
{
defaultMessage: '{count} blocklists have been added to your list.',
values: { count: updatedExceptions.length },
}
)
: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.layout.flyout.toastSuccess.textSingle',
{
defaultMessage: '"{name}" has been added to your blocklist list.',
values: { name: updatedExceptions[0].name },
}
),
emptyUnassignedTitle: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.empty.unassigned.title',
{ defaultMessage: 'No assigned blocklists' }
),
emptyUnassignedMessage: (policyName: string): string =>
i18n.translate('xpack.securitySolution.endpoint.policy.blocklists.empty.unassigned.content', {
defaultMessage:
'There are currently no blocklists assigned to {policyName}. Assign blocklists now or add and manage them on the blocklists page.',
values: { policyName },
}),
emptyUnassignedPrimaryActionButtonTitle: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.empty.unassigned.primaryAction',
{
defaultMessage: 'Assign blocklists',
}
),
emptyUnassignedSecondaryActionButtonTitle: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.empty.unassigned.secondaryAction',
{
defaultMessage: 'Manage blocklists',
}
),
emptyUnexistingTitle: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.empty.unexisting.title',
{ defaultMessage: 'No blocklists exist' }
),
emptyUnexistingMessage: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.empty.unexisting.content',
{
defaultMessage: 'There are currently no blocklists applied to your endpoints.',
}
),
emptyUnexistingPrimaryActionButtonTitle: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.empty.unexisting.action',
{ defaultMessage: 'Add blocklists' }
),
listTotalItemCountMessage: (totalItemsCount: number): string =>
i18n.translate('xpack.securitySolution.endpoint.policy.blocklists.list.totalItemCount', {
defaultMessage: 'Showing {totalItemsCount, plural, one {# blocklist} other {# blocklists}}',
values: { totalItemsCount },
}),
listRemoveActionNotAllowedMessage: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.list.removeActionNotAllowed',
{
defaultMessage: 'Globally applied blocklist cannot be removed from policy.',
}
),
listSearchPlaceholderMessage: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.list.search.placeholder',
{
defaultMessage: `Search on the fields below: name, description, IP`,
}
),
layoutTitle: i18n.translate('xpack.securitySolution.endpoint.policy.blocklists.layout.title', {
defaultMessage: 'Assigned blocklists',
}),
layoutAssignButtonTitle: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.layout.assignToPolicy',
{
defaultMessage: 'Assign blocklists to policy',
}
),
layoutViewAllLinkMessage: i18n.translate(
'xpack.securitySolution.endpoint.policy.blocklists.layout.about.viewAllLinkLabel',
{
defaultMessage: 'view all blocklists',
}
),
});
Loading

0 comments on commit 6d87f12

Please sign in to comment.