[Security Solution] bubble up linux deadlock errors (#136241)

This commit is contained in:
Joey F. Poon 2022-07-25 16:58:24 -05:00 committed by GitHub
parent 1967117c4f
commit 3515e6f22c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 94 additions and 14 deletions

View file

@ -343,6 +343,7 @@ export const getDocLinks = ({ kibanaBranch }: GetDocLinkOptions): DocLinks => {
policyResponseTroubleshooting: {
full_disk_access: `${SECURITY_SOLUTION_DOCS}deploy-elastic-endpoint.html#enable-fda-endpoint`,
macos_system_ext: `${SECURITY_SOLUTION_DOCS}deploy-elastic-endpoint.html#system-extension-endpoint`,
linux_deadlock: `${SECURITY_SOLUTION_DOCS}ts-management.html`,
},
},
query: {

View file

@ -248,6 +248,7 @@ export interface DocLinks {
readonly policyResponseTroubleshooting: {
full_disk_access: string;
macos_system_ext: string;
linux_deadlock: string;
};
readonly threatIntelInt: string;
};

View file

@ -113,7 +113,7 @@ type PolicyResponseAction =
| 'workflow'
| 'full_disk_access';
const policyResponseTitles = Object.freeze(
export const policyResponseTitles = Object.freeze(
new Map<PolicyResponseAction | string, string>([
[
'configure_dns_events',
@ -327,6 +327,12 @@ const policyResponseTitles = Object.freeze(
defaultMessage: 'Permissions required',
}),
],
[
'linux_deadlock',
i18n.translate('xpack.securitySolution.endpoint.details.policyResponse.linux_deadlock', {
defaultMessage: 'Disabled to avoid potential system deadlock',
}),
],
])
);
@ -361,7 +367,7 @@ const policyResponseStatuses = Object.freeze(
])
);
const descriptions = Object.freeze(
export const descriptions = Object.freeze(
new Map<Partial<PolicyResponseAction> | string, string>([
[
'full_disk_access',
@ -382,6 +388,11 @@ const descriptions = Object.freeze(
}
),
],
[
'linux_deadlock',
// intentionally blank for now: https://github.com/elastic/security-team/issues/4264#issuecomment-1194136633
'',
],
])
);
@ -405,9 +416,24 @@ const linkTexts = Object.freeze(
}
),
],
[
'linux_deadlock',
i18n.translate(
'xpack.securitySolution.endpoint.details.policyResponse.link.text.linux_deadlock',
{
defaultMessage: ' Learn more.',
}
),
],
])
);
export const LINUX_DEADLOCK_MESSAGE = 'Disabled due to potential system deadlock';
const LINUX_DEADLOCK_ACTION_ERRORS: Set<string> = new Set([
'load_malware_model',
'configure_malware',
]);
function isMacosFullDiskAccessError(os: string, policyAction: HostPolicyResponseAppliedAction) {
return os === 'macos' && policyAction.name === 'full_disk_access';
}
@ -420,6 +446,14 @@ function isMacosSystemExtensionError(os: string, policyAction: HostPolicyRespons
);
}
function isLinuxDeadlockError(os: string, policyAction: HostPolicyResponseAppliedAction) {
return (
os === 'linux' &&
LINUX_DEADLOCK_ACTION_ERRORS.has(policyAction.name) &&
policyAction.message === LINUX_DEADLOCK_MESSAGE
);
}
export class PolicyResponseActionFormatter {
public key: string;
public title: string;
@ -455,11 +489,11 @@ export class PolicyResponseActionFormatter {
}
public get isGeneric(): boolean {
if (isMacosFullDiskAccessError(this.os, this.policyResponseAppliedAction)) {
return true;
}
if (isMacosSystemExtensionError(this.os, this.policyResponseAppliedAction)) {
if (
isMacosFullDiskAccessError(this.os, this.policyResponseAppliedAction) ||
isMacosSystemExtensionError(this.os, this.policyResponseAppliedAction) ||
isLinuxDeadlockError(this.os, this.policyResponseAppliedAction)
) {
return true;
}
@ -471,6 +505,10 @@ export class PolicyResponseActionFormatter {
return 'macos_system_ext';
}
if (isLinuxDeadlockError(this.os, this.policyResponseAppliedAction)) {
return 'linux_deadlock';
}
return this.policyResponseAppliedAction
.name as keyof DocLinks['securitySolution']['policyResponseTroubleshooting'];
}

View file

@ -19,6 +19,11 @@ import type {
} from '../../../../common/endpoint/types';
import { EndpointDocGenerator } from '../../../../common/endpoint/generate_data';
import { useGetEndpointDetails } from '../../hooks';
import {
descriptions,
LINUX_DEADLOCK_MESSAGE,
policyResponseTitles,
} from './policy_response_friendly_names';
jest.mock('../../hooks/endpoint/use_get_endpoint_policy_response');
jest.mock('../../hooks/endpoint/use_get_endpoint_details');
@ -96,7 +101,7 @@ describe('when on the policy response', () => {
props?: Partial<PolicyResponseWrapperProps>
) => ReturnType<AppContextTestRender['render']>;
let renderOpenedTree: () => Promise<ReturnType<AppContextTestRender['render']>>;
const runMock = (customPolicyResponse?: HostPolicyResponse): void => {
const runMock = (customPolicyResponse?: HostPolicyResponse, os = 'macOS'): void => {
commonPolicyResponse = customPolicyResponse ?? createPolicyResponse();
useGetEndpointPolicyResponseMock.mockReturnValue({
data: { policy_response: commonPolicyResponse },
@ -106,7 +111,7 @@ describe('when on the policy response', () => {
});
useGetEndpointDetailsMock.mockReturnValue({
data: {
metadata: { host: { os: { name: 'macOS' } } },
metadata: { host: { os: { name: os } } },
},
isLoading: false,
isFetching: false,
@ -301,21 +306,56 @@ describe('when on the policy response', () => {
const component = await renderOpenedTree();
const macosSystemExtTitle = 'Permissions required';
const calloutTitles = component
.queryAllByTestId('endpointPolicyResponseErrorCallOut')
.filter((calloutTitle) => calloutTitle.innerHTML.includes(macosSystemExtTitle));
.filter((calloutTitle) =>
calloutTitle.innerHTML.includes(policyResponseTitles.get('macos_system_ext')!)
);
expect(calloutTitles.length).toEqual(2);
const macosSystemExtMessage =
'You must enable the Mac system extension for Elastic Endpoint on your machine.';
const calloutMessages = component
.queryAllByTestId('endpointPolicyResponseErrorCallOut')
.filter((calloutMessage) => calloutMessage.innerHTML.includes(macosSystemExtMessage));
.filter((calloutMessage) =>
calloutMessage.innerHTML.includes(descriptions.get('macos_system_ext')!)
);
expect(calloutMessages.length).toEqual(2);
const calloutLinks = component.queryAllByTestId('endpointPolicyResponseErrorCallOutLink');
expect(calloutLinks.length).toEqual(2);
});
it.each(['load_malware_model', 'configure_malware'])(
'should display correct description and link for linux_deadlock with %s failure',
async (actionName: string) => {
policyResponse = createPolicyResponse(HostPolicyResponseActionStatus.failure, [
{
name: actionName,
message: LINUX_DEADLOCK_MESSAGE,
status: HostPolicyResponseActionStatus.failure,
},
]);
runMock(policyResponse, 'Linux');
const component = await renderOpenedTree();
const calloutTitles = component
.queryAllByTestId('endpointPolicyResponseErrorCallOut')
.filter((calloutTitle) =>
calloutTitle.innerHTML.includes(policyResponseTitles.get('linux_deadlock')!)
);
expect(calloutTitles.length).toEqual(2);
// uncomment once we have an actual description
// const calloutMessages = component
// .queryAllByTestId('endpointPolicyResponseErrorCallOut')
// .filter((calloutMessage) =>
// calloutMessage.innerHTML.includes(descriptions.get('linux_deadlock')!)
// );
// expect(calloutMessages.length).toEqual(2);
const calloutLinks = component.queryAllByTestId('endpointPolicyResponseErrorCallOutLink');
expect(calloutLinks.length).toEqual(2);
}
);
});
});