diff --git a/x-pack/plugins/security_solution/common/endpoint/types/index.ts b/x-pack/plugins/security_solution/common/endpoint/types/index.ts index 1e0d798cf7f07d..7a253ef2e32522 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/index.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/index.ts @@ -402,6 +402,11 @@ export enum HostStatus { * Host is inactive as indicated by its checkin status during the last checkin window */ INACTIVE = 'inactive', + + /** + * Host is unenrolled + */ + UNENROLLED = 'unenrolled', } export enum MetadataQueryStrategyVersions { 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 f93721349fdac0..d7091059012151 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 @@ -20,7 +20,7 @@ export const AgentStatus = React.memo(({ hostStatus }: { hostStatus: HostStatus > diff --git a/x-pack/plugins/security_solution/public/detections/components/host_isolation/take_action_dropdown.tsx b/x-pack/plugins/security_solution/public/detections/components/host_isolation/take_action_dropdown.tsx index a10ad901441ea5..1404f7927d6ec8 100644 --- a/x-pack/plugins/security_solution/public/detections/components/host_isolation/take_action_dropdown.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/host_isolation/take_action_dropdown.tsx @@ -10,6 +10,7 @@ import { EuiContextMenuItem, EuiContextMenuPanel, EuiButton, EuiPopover } from ' import { ISOLATE_HOST, UNISOLATE_HOST } from './translations'; import { TAKE_ACTION } from '../alerts_table/alerts_utility_bar/translations'; import { useHostIsolationStatus } from '../../containers/detection_engine/alerts/use_host_isolation_status'; +import { HostStatus } from '../../../../common/endpoint/types'; export const TakeActionDropdown = React.memo( ({ @@ -19,7 +20,9 @@ export const TakeActionDropdown = React.memo( onChange: (action: 'isolateHost' | 'unisolateHost') => void; agentId: string; }) => { - const { loading, isIsolated: isolationStatus } = useHostIsolationStatus({ agentId }); + const { loading, isIsolated: isolationStatus, agentStatus } = useHostIsolationStatus({ + agentId, + }); const [isPopoverOpen, setIsPopoverOpen] = useState(false); const closePopoverHandler = useCallback(() => { @@ -41,7 +44,7 @@ export const TakeActionDropdown = React.memo( iconSide="right" fill iconType="arrowDown" - disabled={loading} + disabled={loading || agentStatus === HostStatus.UNENROLLED} onClick={() => { setIsPopoverOpen(!isPopoverOpen); }} @@ -49,7 +52,7 @@ export const TakeActionDropdown = React.memo( {TAKE_ACTION} ); - }, [isPopoverOpen, loading]); + }, [isPopoverOpen, loading, agentStatus]); return ( { const [isIsolated, setIsIsolated] = useState(false); - const [agentStatus, setAgentStatus] = useState(HostStatus.UNHEALTHY); + const [agentStatus, setAgentStatus] = useState(); const [pendingIsolation, setPendingIsolation] = useState(0); const [pendingUnisolation, setPendingUnisolation] = useState(0); const [loading, setLoading] = useState(false); - const { addError } = useAppToasts(); - useEffect(() => { const abortCtrl = new AbortController(); // isMounted tracks if a component is mounted before changing state @@ -55,7 +51,10 @@ export const useHostIsolationStatus = ({ if (error.name === 'AbortError') { return; } - addError(error.message, { title: ISOLATION_STATUS_FAILURE }); + + if (isMounted && error.body.statusCode === 404) { + setAgentStatus(HostStatus.UNENROLLED); + } } try { @@ -65,7 +64,8 @@ export const useHostIsolationStatus = ({ setPendingUnisolation(data[0].pending_actions?.unisolate ?? 0); } } catch (error) { - addError(error.message, { title: ISOLATION_PENDING_FAILURE }); + // silently catch non-user initiated error + return; } if (isMounted) { @@ -87,6 +87,6 @@ export const useHostIsolationStatus = ({ isMounted = false; abortCtrl.abort(); }; - }, [addError, agentId]); + }, [agentId]); return { loading, isIsolated, agentStatus, pendingIsolation, pendingUnisolation }; }; diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/host_constants.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/host_constants.ts index fb9661b509a33c..45cf7d725443d0 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/host_constants.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/host_constants.ts @@ -18,6 +18,7 @@ export const HOST_STATUS_TO_BADGE_COLOR = Object.freeze< [HostStatus.UPDATING]: 'primary', [HostStatus.OFFLINE]: 'default', [HostStatus.INACTIVE]: 'default', + [HostStatus.UNENROLLED]: 'default', }); export const POLICY_STATUS_TO_HEALTH_COLOR = Object.freeze< diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/agent_statuses.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/agent_statuses.tsx index 2c88b305c7d05f..dac10f46487841 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/agent_statuses.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/agent_statuses.tsx @@ -6,11 +6,12 @@ */ import React from 'react'; -import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui'; import { DefaultDraggable } from '../../../../../common/components/draggables'; import { EndpointHostIsolationStatus } from '../../../../../common/components/endpoint/host_isolation'; import { useHostIsolationStatus } from '../../../../../detections/containers/detection_engine/alerts/use_host_isolation_status'; import { AgentStatus } from '../../../../../common/components/endpoint/agent_status'; +import { EMPTY_STATUS } from './translations'; export const AgentStatuses = React.memo( ({ @@ -33,16 +34,22 @@ export const AgentStatuses = React.memo( const isolationFieldName = 'host.isolation'; return ( - - - - - + {agentStatus !== undefined ? ( + + + + + + ) : ( + +

{EMPTY_STATUS}

+
+ )}