Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution][Notes] - move notes management page under manage section instead of timeline #194250

Merged
merged 2 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/deeplinks/security/deep_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,5 @@ export enum SecurityPageName {
entityAnalyticsManagement = 'entity_analytics-management',
entityAnalyticsAssetClassification = 'entity_analytics-asset-classification',
coverageOverview = 'coverage-overview',
notesManagement = 'notes-management',
notes = 'notes',
}
2 changes: 1 addition & 1 deletion x-pack/plugins/security_solution/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export const APP_HOST_ISOLATION_EXCEPTIONS_PATH =
export const APP_BLOCKLIST_PATH = `${APP_PATH}${BLOCKLIST_PATH}` as const;
export const APP_RESPONSE_ACTIONS_HISTORY_PATH =
`${APP_PATH}${RESPONSE_ACTIONS_HISTORY_PATH}` as const;
export const NOTES_MANAGEMENT_PATH = `/notes_management` as const;
export const NOTES_PATH = `${MANAGEMENT_PATH}/notes` as const;

// cloud logs to exclude from default index pattern
export const EXCLUDE_ELASTIC_CLOUD_INDICES = ['-*elastic-cloud-logs-*'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@
*/

import { SecurityPageName } from '@kbn/security-solution-navigation';
import { cloneDeep, remove } from 'lodash';
import { cloneDeep, remove, find } from 'lodash';
import type { AppLinkItems, LinkItem } from '../../../common/links/types';
import { createInvestigationsLinkFromTimeline } from './sections/investigations_links';
import {
createInvestigationsLinkFromNotes,
createInvestigationsLinkFromTimeline,
updateInvestigationsLinkFromNotes,
} from './sections/investigations_links';
import { mlAppLink } from './sections/ml_links';
import { createAssetsLinkFromManage } from './sections/assets_links';
import { createSettingsLinksFromManage } from './sections/settings_links';
Expand All @@ -26,6 +30,19 @@ export const solutionAppLinksSwitcher = (appLinks: AppLinkItems): AppLinkItems =
solutionAppLinks.push(createInvestigationsLinkFromTimeline(timelineLinkItem));
}

// Remove note link
const investigationsLinkItem = find(solutionAppLinks, { id: SecurityPageName.investigations });
const [noteLinkItem] = remove(solutionAppLinks, { id: SecurityPageName.notes });
if (noteLinkItem) {
if (!investigationsLinkItem) {
solutionAppLinks.push(createInvestigationsLinkFromNotes(noteLinkItem));
} else {
solutionAppLinks.push(
updateInvestigationsLinkFromNotes(investigationsLinkItem, noteLinkItem)
);
}
}

// Remove manage link
const [manageLinkItem] = remove(solutionAppLinks, { id: SecurityPageName.administration });

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import { ExternalPageName, SecurityPageName } from '@kbn/security-solution-navigation';
import IconFilebeatChart from './icons/filebeat_chart';
import { INVESTIGATIONS_PATH } from '../../../../../common/constants';
import { SERVER_APP_ID } from '../../../../../common';
import type { LinkItem } from '../../../../common/links/types';
Expand All @@ -21,7 +22,7 @@ const investigationsAppLink: LinkItem = {
capabilities: [`${SERVER_APP_ID}.show`],
hideTimeline: true,
skipUrlState: true,
links: [], // timeline link are added in createInvestigationsLinkFromTimeline
links: [], // timeline and note links are added via the methods below
};

export const createInvestigationsLinkFromTimeline = (timelineLink: LinkItem): LinkItem => {
Expand All @@ -33,6 +34,29 @@ export const createInvestigationsLinkFromTimeline = (timelineLink: LinkItem): Li
};
};

export const createInvestigationsLinkFromNotes = (noteLink: LinkItem): LinkItem => {
return {
...investigationsAppLink,
links: [{ ...noteLink, description: i18n.NOTE_DESCRIPTION, landingIcon: IconTimelineLazy }],
};
};

export const updateInvestigationsLinkFromNotes = (
investigationsLink: LinkItem,
noteLink: LinkItem
): LinkItem => {
const currentLinks = investigationsLink.links ?? [];
currentLinks.push({
...noteLink,
description: i18n.NOTE_DESCRIPTION,
landingIcon: IconFilebeatChart,
});
return {
...investigationsLink,
links: currentLinks,
};
};

// navLinks define the navigation links for the Security Solution pages and External pages as well
export const investigationsNavLinks: SolutionNavLink[] = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ export const TIMELINE_DESCRIPTION = i18n.translate(
}
);

export const NOTE_DESCRIPTION = i18n.translate(
'xpack.securitySolution.navLinks.investigations.note.title',
{
defaultMessage: 'Oversee, revise and revisit the annotations within each document and timeline',
}
);

export const OSQUERY_TITLE = i18n.translate(
'xpack.securitySolution.navLinks.investigations.osquery.title',
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const ENTITY_ANALYTICS_RISK_SCORE = i18n.translate(
}
);

export const NOTES = i18n.translate('xpack.securitySolution.navigation.notesManagement', {
export const NOTES = i18n.translate('xpack.securitySolution.navigation.notes', {
defaultMessage: 'Notes',
});

Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/security_solution/public/app_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
import type { CoreStart } from '@kbn/core/public';

import { links as notesLink } from './notes/links';
import { links as attackDiscoveryLinks } from './attack_discovery/links';
import type { AppLinkItems } from './common/links/types';
import { indicatorsLinks } from './threat_intelligence/links';
Expand Down Expand Up @@ -35,6 +36,7 @@ export const appLinks: AppLinkItems = Object.freeze([
rulesLinks,
gettingStartedLinks,
managementLinks,
notesLink,
]);

export const getFilteredLinks = async (
Expand All @@ -55,5 +57,6 @@ export const getFilteredLinks = async (
rulesLinks,
gettingStartedLinks,
managementFilteredLinks,
notesLink,
]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { isEmpty } from 'lodash/fp';
import type { TimelineType } from '../../../../common/api/timeline';
import { appendSearch } from './helpers';

export const getTimelineTabsUrl = (tabName: TimelineType | 'notes', search?: string) =>
export const getTimelineTabsUrl = (tabName: TimelineType, search?: string) =>
`/${tabName}${appendSearch(search)}`;

export const getTimelineUrl = (id: string, graphEventId?: string) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
BLOCKLIST,
RESPONSE_ACTIONS_HISTORY,
PROTECTION_UPDATES,
NOTES,
} from '../../app/translations';

const TabNameMappedToI18nKey: Record<AdministrationSubTab, string> = {
Expand All @@ -25,6 +26,7 @@ const TabNameMappedToI18nKey: Record<AdministrationSubTab, string> = {
[AdministrationSubTab.blocklist]: BLOCKLIST,
[AdministrationSubTab.responseActionsHistory]: RESPONSE_ACTIONS_HISTORY,
[AdministrationSubTab.protectionUpdates]: PROTECTION_UPDATES,
[AdministrationSubTab.notes]: NOTES,
};

export function getTrailingBreadcrumbs(params: AdministrationRouteSpyState): ChromeBreadcrumb[] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const MANAGEMENT_ROUTING_POLICY_DETAILS_EVENT_FILTERS_PATH = `${MANAGEMEN
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`;
export const MANAGEMENT_ROUTING_POLICY_DETAILS_PROTECTION_UPDATES_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.policies})/:policyId/protectionUpdates`;
export const MANAGEMENT_ROUTING_NOTES_PATH = `${MANAGEMENT_PATH}/:tabName(${AdministrationSubTab.notes})`;
/** @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
22 changes: 22 additions & 0 deletions x-pack/plugins/security_solution/public/management/links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import type { CoreStart } from '@kbn/core/public';
import { i18n } from '@kbn/i18n';

import IconFilebeatChart from '../app/solution_navigation/links/sections/icons/filebeat_chart';
import { checkArtifactHasData } from './services/exceptions_list/check_artifact_has_data';
import {
calculateEndpointAuthz,
Expand All @@ -22,6 +23,7 @@ import {
EVENT_FILTERS_PATH,
HOST_ISOLATION_EXCEPTIONS_PATH,
MANAGE_PATH,
NOTES_PATH,
POLICIES_PATH,
RESPONSE_ACTIONS_HISTORY_PATH,
SecurityPageName,
Expand All @@ -39,6 +41,7 @@ import {
TRUSTED_APPLICATIONS,
ENTITY_ANALYTICS_RISK_SCORE,
ASSET_CRITICALITY,
NOTES,
} from '../app/translations';
import { licenseService } from '../common/hooks/use_license';
import type { LinkItem } from '../common/links/types';
Expand Down Expand Up @@ -85,6 +88,12 @@ const categories = [
}),
linkIds: [SecurityPageName.cloudDefendPolicies],
},
{
label: i18n.translate('xpack.securitySolution.appLinks.category.investigations', {
defaultMessage: 'Investigations',
}),
linkIds: [SecurityPageName.notes],
},
];

export const links: LinkItem = {
Expand Down Expand Up @@ -215,6 +224,19 @@ export const links: LinkItem = {
hideTimeline: true,
},
cloudDefendLink,
{
id: SecurityPageName.notes,
title: NOTES,
description: i18n.translate('xpack.securitySolution.appLinks.notesDescription', {
defaultMessage:
'Oversee, revise and revisit the annotations within each document and timeline.',
}),
landingIcon: IconFilebeatChart,
path: NOTES_PATH,
skipUrlState: true,
hideTimeline: true,
experimentalKey: 'securitySolutionNotesEnabled',
},
],
};

Expand Down
11 changes: 11 additions & 0 deletions x-pack/plugins/security_solution/public/management/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Routes, Route } from '@kbn/shared-ux-router';
import { TrackApplicationView } from '@kbn/usage-collection-plugin/public';
import { EuiEmptyPrompt, EuiLoadingLogo } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { NotesContainer } from './notes';
import { ManagementEmptyStateWrapper } from '../components/management_empty_state_wrapper';
import {
MANAGEMENT_ROUTING_ENDPOINTS_PATH,
Expand All @@ -20,6 +21,7 @@ import {
MANAGEMENT_ROUTING_TRUSTED_APPS_PATH,
MANAGEMENT_ROUTING_BLOCKLIST_PATH,
MANAGEMENT_ROUTING_RESPONSE_ACTIONS_HISTORY_PATH,
MANAGEMENT_ROUTING_NOTES_PATH,
} from '../common/constants';
import { NotFoundPage } from '../../app/404';
import { EndpointsContainer } from './endpoint_hosts';
Expand Down Expand Up @@ -77,6 +79,13 @@ const ResponseActionsTelemetry = () => (
</TrackApplicationView>
);

const NotesTelemetry = () => (
<TrackApplicationView viewId={SecurityPageName.notes}>
<NotesContainer />
<SpyRoute pageName={SecurityPageName.notes} />
</TrackApplicationView>
);

export const ManagementContainer = memo(() => {
const {
loading,
Expand Down Expand Up @@ -148,6 +157,8 @@ export const ManagementContainer = memo(() => {
hasPrivilege={canReadActionsLogManagement}
/>

<Route path={MANAGEMENT_ROUTING_NOTES_PATH} component={NotesTelemetry} />

{canReadEndpointList && (
<Route path={MANAGEMENT_PATH} exact>
<Redirect to={getEndpointListPath({ name: 'endpointList' })} />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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 { Routes, Route } from '@kbn/shared-ux-router';
import React from 'react';
import { NoteManagementPage } from '../../../notes';
import { NotFoundPage } from '../../../app/404';
import { MANAGEMENT_ROUTING_NOTES_PATH } from '../../common/constants';

export const NotesContainer = () => {
return (
<Routes>
<Route path={MANAGEMENT_ROUTING_NOTES_PATH} exact component={NoteManagementPage} />
<Route path="*" component={NotFoundPage} />
</Routes>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export enum AdministrationSubTab {
blocklist = 'blocklist',
responseActionsHistory = 'response_actions_history',
protectionUpdates = 'protection_updates',
notes = 'notes',
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,56 +14,10 @@ export const BATCH_ACTIONS = i18n.translate(
}
);

export const CREATED_COLUMN = i18n.translate(
'xpack.securitySolution.notes.management.createdColumnTitle',
{
defaultMessage: 'Created',
}
);

export const CREATED_BY_COLUMN = i18n.translate(
'xpack.securitySolution.notes.management.createdByColumnTitle',
{
defaultMessage: 'Created by',
}
);

export const EVENT_ID_COLUMN = i18n.translate(
'xpack.securitySolution.notes.management.eventIdColumnTitle',
{
defaultMessage: 'View Document',
}
);

export const TIMELINE_ID_COLUMN = i18n.translate(
'xpack.securitySolution.notes.management.timelineColumnTitle',
{
defaultMessage: 'Timeline',
}
);

export const NOTE_CONTENT_COLUMN = i18n.translate(
'xpack.securitySolution.notes.management.noteContentColumnTitle',
{
defaultMessage: 'Note content',
}
);

export const DELETE = i18n.translate('xpack.securitySolution.notes.management.deleteAction', {
defaultMessage: 'Delete',
});

export const DELETE_SINGLE_NOTE_DESCRIPTION = i18n.translate(
'xpack.securitySolution.notes.management.deleteDescription',
{
defaultMessage: 'Delete this note',
}
);

export const TABLE_ERROR = i18n.translate('xpack.securitySolution.notes.management.tableError', {
defaultMessage: 'Unable to load notes',
});

export const DELETE_NOTES_MODAL_TITLE = i18n.translate(
'xpack.securitySolution.notes.management.deleteNotesModalTitle',
{
Expand Down Expand Up @@ -96,13 +50,6 @@ export const REFRESH = i18n.translate('xpack.securitySolution.notes.management.r
defaultMessage: 'Refresh',
});

export const OPEN_TIMELINE = i18n.translate(
'xpack.securitySolution.notes.management.openTimeline',
{
defaultMessage: 'Open timeline',
}
);

export const VIEW_EVENT_IN_TIMELINE = i18n.translate(
'xpack.securitySolution.notes.management.viewEventInTimeline',
{
Expand Down
Loading