-
Notifications
You must be signed in to change notification settings - Fork 8.1k
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] Adds a version and OS check for Host Isolation #103026
Changes from all commits
961d930
7c425fe
fc8d3ac
bf5d968
af57cc1
bdcda87
4b2f3c6
a240ddb
2d22901
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -51,7 +51,7 @@ export const ANCESTRY_LIMIT: number = 2; | |
|
||
const Windows: OSFields[] = [ | ||
{ | ||
name: 'windows 10.0', | ||
name: 'Windows', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update the |
||
full: 'Windows 10', | ||
version: '10.0', | ||
platform: 'Windows', | ||
|
@@ -61,7 +61,7 @@ const Windows: OSFields[] = [ | |
}, | ||
}, | ||
{ | ||
name: 'windows 10.0', | ||
name: 'Windows', | ||
full: 'Windows Server 2016', | ||
version: '10.0', | ||
platform: 'Windows', | ||
|
@@ -71,7 +71,7 @@ const Windows: OSFields[] = [ | |
}, | ||
}, | ||
{ | ||
name: 'windows 6.2', | ||
name: 'Windows', | ||
full: 'Windows Server 2012', | ||
version: '6.2', | ||
platform: 'Windows', | ||
|
@@ -81,7 +81,7 @@ const Windows: OSFields[] = [ | |
}, | ||
}, | ||
{ | ||
name: 'windows 6.3', | ||
name: 'Windows', | ||
full: 'Windows Server 2012R2', | ||
version: '6.3', | ||
platform: 'Windows', | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* 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 { isVersionSupported, isOsSupported, isIsolationSupported } from './utils'; | ||
|
||
describe('Host Isolation utils isVersionSupported', () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not necessary to take action: Jest support table tests which makes these kind of repetitive tests easier to read and write. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Example:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks for the tip, I didn't know that! I've refactored my tests to reflect it. |
||
test.each` | ||
a | b | expected | ||
${'8.14.0'} | ${'7.13.0'} | ${true} | ||
${'7.14.0'} | ${'7.13.0'} | ${true} | ||
${'7.14.1'} | ${'7.14.0'} | ${true} | ||
${'8.14.0'} | ${'9.14.0'} | ${false} | ||
${'7.13.0'} | ${'7.14.0'} | ${false} | ||
${'7.14.0'} | ${'7.14.1'} | ${false} | ||
${'7.14.0'} | ${'7.14.0'} | ${true} | ||
${'7.14.0-SNAPSHOT'} | ${'7.14.0'} | ${true} | ||
${'7.14.0-SNAPSHOT-beta'} | ${'7.14.0'} | ${true} | ||
${'7.14.0-alpha'} | ${'7.14.0'} | ${true} | ||
`('should validate that version $a is compatible($expected) to $b', ({ a, b, expected }) => { | ||
expect( | ||
isVersionSupported({ | ||
currentVersion: a, | ||
minVersionRequired: b, | ||
}) | ||
).toEqual(expected); | ||
}); | ||
}); | ||
|
||
describe('Host Isolation utils isOsSupported', () => { | ||
test.each` | ||
a | b | expected | ||
${'linux'} | ${['macos', 'linux']} | ${true} | ||
${'linux'} | ${['macos', 'windows']} | ${false} | ||
`('should validate that os $a is compatible($expected) to $b', ({ a, b, expected }) => { | ||
expect( | ||
isOsSupported({ | ||
currentOs: a, | ||
supportedOss: b, | ||
}) | ||
).toEqual(expected); | ||
}); | ||
}); | ||
|
||
describe('Host Isolation utils isIsolationSupported', () => { | ||
test.each` | ||
a | b | expected | ||
${'windows'} | ${'7.14.0'} | ${true} | ||
${'linux'} | ${'7.13.0'} | ${false} | ||
${'linux'} | ${'7.14.0'} | ${false} | ||
${'macos'} | ${'7.13.0'} | ${false} | ||
`( | ||
'should validate that os $a and version $b supports hostIsolation($expected)', | ||
({ a, b, expected }) => { | ||
expect( | ||
isIsolationSupported({ | ||
osName: a, | ||
version: b, | ||
}) | ||
).toEqual(expected); | ||
} | ||
); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
export const isVersionSupported = ({ | ||
currentVersion, | ||
minVersionRequired, | ||
}: { | ||
currentVersion: string; | ||
minVersionRequired: string; | ||
}) => { | ||
const parsedCurrentVersion = currentVersion.includes('-SNAPSHOT') | ||
? currentVersion.substring(0, currentVersion.indexOf('-')) | ||
: currentVersion; | ||
const tokenizedCurrent = parsedCurrentVersion | ||
.split('.') | ||
.map((token: string) => parseInt(token, 10)); | ||
const tokenizedMin = minVersionRequired.split('.').map((token: string) => parseInt(token, 10)); | ||
|
||
const versionNotSupported = tokenizedCurrent.some((token: number, index: number) => { | ||
return token < tokenizedMin[index]; | ||
}); | ||
|
||
return !versionNotSupported; | ||
}; | ||
|
||
export const isOsSupported = ({ | ||
currentOs, | ||
supportedOss, | ||
}: { | ||
currentOs: string; | ||
supportedOss: string[]; | ||
}) => { | ||
return supportedOss.some((os) => currentOs === os); | ||
}; | ||
|
||
export const isIsolationSupported = ({ osName, version }: { osName: string; version: string }) => { | ||
const normalizedOs = osName.toLowerCase(); | ||
return ( | ||
isOsSupported({ currentOs: normalizedOs, supportedOss: ['macos', 'windows'] }) && | ||
isVersionSupported({ currentVersion: version, minVersionRequired: '7.14.0' }) | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,7 @@ import { | |
} from '../../../../detections/components/host_isolation/translations'; | ||
import { ALERT_DETAILS } from './translations'; | ||
import { useIsolationPrivileges } from '../../../../common/hooks/endpoint/use_isolate_privileges'; | ||
import { isIsolationSupported } from '../../../../../common/endpoint/service/host_isolation/utils'; | ||
import { endpointAlertCheck } from '../../../../common/utils/endpoint_alert_check'; | ||
import { useWithCaseDetailsRefresh } from '../../../../common/components/endpoint/host_isolation/endpoint_host_isolation_cases_context'; | ||
|
||
|
@@ -102,6 +103,22 @@ const EventDetailsPanelComponent: React.FC<EventDetailsPanelProps> = ({ | |
return findAgentId ? findAgentId[0] : ''; | ||
}, [detailsData]); | ||
|
||
const hostOsFamily = useMemo(() => { | ||
const findOsName = find({ category: 'host', field: 'host.os.name' }, detailsData)?.values; | ||
return findOsName ? findOsName[0] : ''; | ||
}, [detailsData]); | ||
|
||
const agentVersion = useMemo(() => { | ||
const findAgentVersion = find({ category: 'agent', field: 'agent.version' }, detailsData) | ||
?.values; | ||
return findAgentVersion ? findAgentVersion[0] : ''; | ||
}, [detailsData]); | ||
|
||
const isolationSupported = isIsolationSupported({ | ||
osName: hostOsFamily, | ||
version: agentVersion, | ||
}); | ||
|
||
const backToAlertDetailsLink = useMemo(() => { | ||
return ( | ||
<> | ||
|
@@ -164,15 +181,18 @@ const EventDetailsPanelComponent: React.FC<EventDetailsPanelProps> = ({ | |
/> | ||
)} | ||
</StyledEuiFlyoutBody> | ||
{isIsolationAllowed && isEndpointAlert && isHostIsolationPanelOpen === false && ( | ||
<EuiFlyoutFooter> | ||
<EuiFlexGroup justifyContent="flexEnd"> | ||
<EuiFlexItem grow={false}> | ||
<TakeActionDropdown onChange={showHostIsolationPanel} agentId={agentId} /> | ||
</EuiFlexItem> | ||
</EuiFlexGroup> | ||
</EuiFlyoutFooter> | ||
)} | ||
{isIsolationAllowed && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have a concern about hiding the TakeActionDropdown in its entirety. Are we planning to use this dropdown to add more actions later other than isolate? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @academo we will add new actions in the future, but currently there is just the one. We would revisit this check when the time comes |
||
isEndpointAlert && | ||
isolationSupported && | ||
isHostIsolationPanelOpen === false && ( | ||
<EuiFlyoutFooter> | ||
<EuiFlexGroup justifyContent="flexEnd"> | ||
<EuiFlexItem grow={false}> | ||
<TakeActionDropdown onChange={showHostIsolationPanel} agentId={agentId} /> | ||
</EuiFlexItem> | ||
</EuiFlexGroup> | ||
</EuiFlyoutFooter> | ||
)} | ||
</> | ||
) : ( | ||
<> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make the version generator possible to be 7.14.0+ to ensure fake docs will pass the version check.