diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/agent_status.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/agent_status.tsx index 7b7a9c5fb9e565..150189e273cb31 100644 --- a/x-pack/plugins/security_solution/public/common/components/endpoint/agent_status.tsx +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/agent_status.tsx @@ -7,9 +7,9 @@ import React from 'react'; import { EuiBadge } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; import type { HostStatus } from '../../../../common/endpoint/types'; import { HOST_STATUS_TO_BADGE_COLOR } from '../../../management/pages/endpoint_hosts/view/host_constants'; +import { getAgentStatusText } from './agent_status_text'; export const AgentStatus = React.memo(({ hostStatus }: { hostStatus: HostStatus }) => { return ( @@ -18,11 +18,7 @@ export const AgentStatus = React.memo(({ hostStatus }: { hostStatus: HostStatus data-test-subj="rowHostStatus" className="eui-textTruncate" > - + {getAgentStatusText(hostStatus)} ); }); diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/agent_status_text.ts b/x-pack/plugins/security_solution/public/common/components/endpoint/agent_status_text.ts new file mode 100644 index 00000000000000..45ffd9a90ce93d --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/endpoint/agent_status_text.ts @@ -0,0 +1,17 @@ +/* + * 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 type { HostStatus } from '../../../../common/endpoint/types'; + +export const getAgentStatusText = (hostStatus: HostStatus) => { + return i18n.translate('xpack.securitySolution.endpoint.list.hostStatusValue', { + defaultMessage: + '{hostStatus, select, healthy {Healthy} unhealthy {Unhealthy} updating {Updating} offline {Offline} inactive {Inactive} unenrolled {Unenrolled} other {Unhealthy}}', + values: { hostStatus }, + }); +}; diff --git a/x-pack/plugins/security_solution/public/management/components/console/components/bad_argument.tsx b/x-pack/plugins/security_solution/public/management/components/console/components/bad_argument.tsx index be9600da0b7060..3eccdd5ab7ca51 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/components/bad_argument.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/components/bad_argument.tsx @@ -54,6 +54,7 @@ export const BadArgument = memo
+ >(({ commandDef }) => { const usageHelp = useMemo(() => { - return getArgumentsForCommand(commandDef).map((usage) => { + return getArgumentsForCommand(commandDef).map((usage, index) => { return ( - + <> + {index > 0 && } {`${commandDef.name} ${usage}`} - + ); }); }, [commandDef]); @@ -139,7 +140,7 @@ export const CommandUsage = memo(({ commandDef }) => { )); return ( <> - + {commandDef.args && ( ( {header} - - {children} - + + {children}
); } diff --git a/x-pack/plugins/security_solution/public/management/components/console/console.tsx b/x-pack/plugins/security_solution/public/management/components/console/console.tsx index 9c2c4eb70c4cea..e8fa86ffda83ae 100644 --- a/x-pack/plugins/security_solution/public/management/components/console/console.tsx +++ b/x-pack/plugins/security_solution/public/management/components/console/console.tsx @@ -85,10 +85,12 @@ const ConsoleWindow = styled.div` &.euiDescriptionList { > .euiDescriptionList__title { width: 20%; + margin-top: ${({ theme: { eui } }) => eui.euiSizeS}; } > .euiDescriptionList__description { width: 80%; + margin-top: ${({ theme: { eui } }) => eui.euiSizeS}; } } } diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/endpoint_response_actions_console_commands.ts b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/endpoint_response_actions_console_commands.ts index 5b0d1bd0de3496..fec61d55c5e525 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/endpoint_response_actions_console_commands.ts +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/endpoint_response_actions_console_commands.ts @@ -74,7 +74,7 @@ export const getEndpointResponseActionsConsoleCommands = ( { name: 'kill-process', about: i18n.translate('xpack.securitySolution.endpointConsoleCommands.killProcess.about', { - defaultMessage: 'Kill a running process', + defaultMessage: 'Kill a running process. Accepts either a PID or an entity id.', }), RenderComponent: KillProcessActionResult, meta: { @@ -97,8 +97,7 @@ export const getEndpointResponseActionsConsoleCommands = ( allowMultiples: false, exclusiveOr: true, about: i18n.translate('xpack.securitySolution.endpointConsoleCommands.pid.arg.comment', { - defaultMessage: - 'A PID representing the process to kill. You can enter a pid or an entity id, but not both.', + defaultMessage: 'A PID representing the process to kill', }), validate: emptyArgumentValidator, }, @@ -109,8 +108,7 @@ export const getEndpointResponseActionsConsoleCommands = ( about: i18n.translate( 'xpack.securitySolution.endpointConsoleCommands.entityId.arg.comment', { - defaultMessage: - 'An entity id representing the process to kill. You can enter a pid or an entity id, but not both.', + defaultMessage: 'An entity id representing the process to kill', } ), validate: emptyArgumentValidator, @@ -120,7 +118,7 @@ export const getEndpointResponseActionsConsoleCommands = ( { name: 'suspend-process', about: i18n.translate('xpack.securitySolution.endpointConsoleCommands.suspendProcess.about', { - defaultMessage: 'Suspend a running process', + defaultMessage: 'Suspend a running process. Accepts either a PID or an entity id.', }), RenderComponent: SuspendProcessActionResult, meta: { @@ -145,8 +143,7 @@ export const getEndpointResponseActionsConsoleCommands = ( about: i18n.translate( 'xpack.securitySolution.endpointConsoleCommands.suspendProcess.pid.arg.comment', { - defaultMessage: - 'A PID representing the process to suspend. You can enter a pid or an entity id, but not both.', + defaultMessage: 'A PID representing the process to suspend', } ), validate: emptyArgumentValidator, @@ -158,8 +155,7 @@ export const getEndpointResponseActionsConsoleCommands = ( about: i18n.translate( 'xpack.securitySolution.endpointConsoleCommands.suspendProcess.entityId.arg.comment', { - defaultMessage: - 'An entity id representing the process to suspend. You can enter a pid or an entity id, but not both.', + defaultMessage: 'An entity id representing the process to suspend', } ), validate: emptyArgumentValidator, diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/status_action.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/status_action.tsx index efc1785daf128d..d8b06ec234ac27 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/status_action.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/status_action.tsx @@ -5,9 +5,8 @@ * 2.0. */ -import React, { memo, useEffect, useMemo } from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; +import React, { memo, useEffect, useMemo, useCallback } from 'react'; +import { EuiDescriptionList } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import type { HttpFetchError } from '@kbn/core/public'; import { v4 as uuidV4 } from 'uuid'; @@ -16,11 +15,12 @@ import type { EndpointCommandDefinitionMeta } from './types'; import type { EndpointHostIsolationStatusProps } from '../../../common/components/endpoint/host_isolation'; import { useGetEndpointPendingActionsSummary } from '../../hooks/endpoint/use_get_endpoint_pending_actions_summary'; import { FormattedDate } from '../../../common/components/formatted_date'; -import { EndpointAppliedPolicyStatus } from '../endpoint_applied_policy_status'; -import { EndpointAgentAndIsolationStatus } from '../endpoint_agent_and_isolation_status'; import { useGetEndpointDetails } from '../../hooks'; import type { CommandExecutionComponentProps } from '../console/types'; import { FormattedError } from '../formatted_error'; +import { ConsoleCodeBlock } from '../console/components/console_code_block'; +import { POLICY_STATUS_TO_TEXT } from '../../pages/endpoint_hosts/view/host_constants'; +import { getAgentStatusText } from '../../../common/components/endpoint/agent_status_text'; export const EndpointStatusActionResult = memo< CommandExecutionComponentProps< @@ -50,7 +50,7 @@ export const EndpointStatusActionResult = memo< const { data: fetchedPendingActionsSummary } = useGetEndpointPendingActionsSummary([endpointId], { enabled: isPending, - queryKey, + queryKey: [queryKey, endpointId], }); const pendingIsolationActions = useMemo< @@ -115,6 +115,114 @@ export const EndpointStatusActionResult = memo< } }, [fetchedPendingActionsSummary, setStore]); + const getStatusDescriptionList = useCallback(() => { + if (!endpointDetails) { + return undefined; + } + + const agentStatus = () => { + let isolateStatus = ''; + + if (pendingIsolationActions.pendingIsolate > 0) { + isolateStatus = i18n.translate( + 'xpack.securitySolution.endpointResponseActions.status.isolating', + { + defaultMessage: 'Isolating', + } + ); + } else if (pendingIsolationActions.pendingUnIsolate > 0) { + isolateStatus = i18n.translate( + 'xpack.securitySolution.endpointResponseActions.status.releasing', + { + defaultMessage: 'Releasing', + } + ); + } else if (endpointDetails?.metadata.Endpoint.state?.isolation) { + isolateStatus = i18n.translate( + 'xpack.securitySolution.endpointResponseActions.status.isolated', + { + defaultMessage: 'Isolated', + } + ); + } + + return `${getAgentStatusText(endpointDetails.host_status)}${ + isolateStatus.length > 0 ? ` - ${isolateStatus}` : '' + }`; + }; + + const statusData = [ + { + title: ( + + {i18n.translate('xpack.securitySolution.endpointResponseActions.status.agentStatus', { + defaultMessage: 'Agent status', + })} + + ), + description: {agentStatus()}, + }, + { + title: ( + + {i18n.translate('xpack.securitySolution.endpointResponseActions.status.version', { + defaultMessage: 'Version', + })} + + ), + description: endpointDetails.metadata.agent.version, + }, + { + title: ( + + {i18n.translate('xpack.securitySolution.endpointResponseActions.status.policyStatus', { + defaultMessage: 'Policy status', + })} + + ), + description: ( + + {POLICY_STATUS_TO_TEXT[endpointDetails.metadata.Endpoint.policy.applied.status]} + + ), + }, + { + title: ( + + {i18n.translate('xpack.securitySolution.endpointResponseActions.status.lastActive', { + defaultMessage: 'Last active', + })} + + ), + description: ( + + + + ), + }, + ]; + return ( + + ); + }, [ + pendingIsolationActions.pendingIsolate, + pendingIsolationActions.pendingUnIsolate, + endpointDetails, + ]); + if (detailsFetchError) { return ( @@ -127,62 +235,6 @@ export const EndpointStatusActionResult = memo< return ; } - return ( - - - - - - - - - - - - - {endpointDetails.metadata.agent.version} - - - - - - - - - - - - - - - - - - ); + return {getStatusDescriptionList()}; }); EndpointStatusActionResult.displayName = 'EndpointStatusActionResult'; diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_list.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_list.tsx index 74c52f1be973bc..169128a373976f 100644 --- a/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_list.tsx +++ b/x-pack/plugins/security_solution/public/management/components/endpoint_response_actions_list/response_actions_list.tsx @@ -22,7 +22,6 @@ import { EuiCodeBlock, EuiToolTip, RIGHT_ALIGNMENT, - EuiFlexGrid, } from '@elastic/eui'; import { euiStyled, css } from '@kbn/kibana-react-plugin/common'; @@ -57,17 +56,24 @@ const StyledFacetButton = euiStyled(EuiFacetButton)` `; const customDescriptionListCss = css` - dt, - dd { - color: ${(props) => props.theme.eui.euiColorDarkShade} !important; - font-size: ${(props) => props.theme.eui.euiFontSizeXS} !important; - } - dt { - font-weight: ${(props) => props.theme.eui.euiFontWeightSemiBold}; + &.euiDescriptionList { + > .euiDescriptionList__title { + color: ${(props) => props.theme.eui.euiColorDarkShade}; + font-size: ${(props) => props.theme.eui.euiFontSizeXS}; + margin-top: ${(props) => props.theme.eui.euiSizeS}; + } + + > .euiDescriptionList__description { + font-weight: ${(props) => props.theme.eui.euiFontWeightSemiBold}; + margin-top: ${(props) => props.theme.eui.euiSizeS}; + } } `; -const StyledDescriptionList = euiStyled(EuiDescriptionList).attrs({ compressed: true })` +const StyledDescriptionList = euiStyled(EuiDescriptionList).attrs({ + compressed: true, + type: 'column', +})` ${customDescriptionListCss} `; @@ -164,38 +170,39 @@ export const ResponseActionsList = memo< : undefined; const command = getCommand(_command); - const descriptionListLeft = [ + const dataList = [ { title: OUTPUT_MESSAGES.expandSection.placedAt, description: `${startedAt}`, }, - { - title: OUTPUT_MESSAGES.expandSection.input, - description: `${command}`, - }, - ]; - - const descriptionListCenter = [ { title: OUTPUT_MESSAGES.expandSection.startedAt, description: `${startedAt}`, }, - { - title: OUTPUT_MESSAGES.expandSection.parameters, - description: parametersList ? parametersList : emptyValue, - }, - ]; - - const descriptionListRight = [ { title: OUTPUT_MESSAGES.expandSection.completedAt, description: `${completedAt ?? emptyValue}`, }, - ]; + { + title: OUTPUT_MESSAGES.expandSection.input, + description: `${command}`, + }, + { + title: OUTPUT_MESSAGES.expandSection.parameters, + description: parametersList ? parametersList : emptyValue, + }, + ].map(({ title, description }) => { + return { + title: {title}, + description: {description}, + }; + }); const outputList = [ { - title: OUTPUT_MESSAGES.expandSection.output, + title: ( + {`${OUTPUT_MESSAGES.expandSection.output}:`} + ), description: ( // codeblock for output @@ -218,32 +225,10 @@ export const ResponseActionsList = memo< direction="column" style={{ maxHeight: 270, overflowY: 'auto' }} className="eui-yScrollWithShadows" + gutterSize="s" > - - {[descriptionListLeft, descriptionListCenter, descriptionListRight].map( - (_list, i) => { - const list = _list.map((l) => { - const isParameters = l.title === OUTPUT_MESSAGES.expandSection.parameters; - return { - title: l.title, - description: isParameters ? ( - // codeblock for parameters - {l.description} - ) : ( - l.description - ), - }; - }); - - return ( - - - - ); - } - )} - + diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/__snapshots__/netflow_row_renderer.test.tsx.snap b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/__snapshots__/netflow_row_renderer.test.tsx.snap index 9fb449fdc8ee08..4839dc736fec3b 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/__snapshots__/netflow_row_renderer.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/__snapshots__/netflow_row_renderer.test.tsx.snap @@ -2,12 +2,7 @@ exports[`netflowRowRenderer renders correctly against snapshot 1`] = ` - .c15 svg { - position: relative; - top: -1px; -} - -.c0 { + .c0 { font-size: 12px; line-height: 1.5; padding-left: 12px; @@ -20,6 +15,11 @@ exports[`netflowRowRenderer renders correctly against snapshot 1`] = ` border-radius: 4px; } +.c15 svg { + position: relative; + top: -1px; +} + .c13, .c13 * { display: inline-block;