Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
9c77449
[Security Solution] action not allowed (405) is shown for Duplicating…
e40pud Mar 13, 2024
04350e9
Merge branch 'main' into security/bugfix/177814-endpoint-lists
kibanamachine Mar 13, 2024
7f2e3fc
Merge branch 'main' into security/bugfix/177814-endpoint-lists
kibanamachine Mar 18, 2024
2ba871c
Merge branch 'main' into security/bugfix/177814-endpoint-lists
kibanamachine Apr 2, 2024
589284a
Merge branch 'main' into security/bugfix/177814-endpoint-lists
kibanamachine Apr 5, 2024
647772d
Merge branch 'main' into security/bugfix/177814-endpoint-lists
kibanamachine Apr 8, 2024
190510b
Merge branch 'main' into security/bugfix/177814-endpoint-lists
yctercero Apr 9, 2024
7a96a49
Merge branch 'main' into security/bugfix/177814-endpoint-lists
kibanamachine Apr 10, 2024
66a2fe2
Merge branch 'main' into security/bugfix/177814-endpoint-lists
kibanamachine Apr 11, 2024
1aaf772
Merge branch 'main' into security/bugfix/177814-endpoint-lists
kibanamachine Apr 12, 2024
d5334b7
Merge branch 'main' into security/bugfix/177814-endpoint-lists
kibanamachine Apr 15, 2024
950340f
Disabled create new list checkbox
e40pud Apr 10, 2024
147a21d
Merge branch 'main' into security/bugfix/177814-endpoint-lists
kibanamachine Apr 17, 2024
fdeca73
Merge branch 'main' into security/bugfix/177814-endpoint-lists
kibanamachine Apr 22, 2024
8503eca
Merge branch 'main' into security/bugfix/177814-endpoint-lists
kibanamachine Apr 22, 2024
7b73003
Merge branch 'main' into security/bugfix/177814-endpoint-lists
kibanamachine Apr 24, 2024
adc17e9
Merge branch 'main' into security/bugfix/177814-endpoint-lists
kibanamachine Apr 25, 2024
3203945
Adjust the message to follow guidelines
e40pud Apr 25, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ import {
EuiFlyoutFooter,
EuiTextColor,
EuiFlyout,
EuiToolTip,
} from '@elastic/eui';
import type {
BulkErrorSchema,
ImportExceptionsResponseSchema,
} from '@kbn/securitysolution-io-ts-list-types';
import { ENDPOINT_LIST_ID } from '@kbn/securitysolution-list-constants';
import type { HttpSetup } from '@kbn/core-http-browser';
import type { ToastInput, Toast, ErrorToastOptions } from '@kbn/core-notifications-browser';

Expand Down Expand Up @@ -58,6 +60,7 @@ export const ImportExceptionListFlyout = React.memo(
const [overwrite, setOverwrite] = useState(false);
const [asNewList, setAsNewList] = useState(false);
const [alreadyExistingItem, setAlreadyExistingItem] = useState(false);
const [endpointListImporting, setEndpointListImporting] = useState(false);

const resetForm = useCallback(() => {
if (filePickerRef.current?.fileInput) {
Expand All @@ -66,6 +69,7 @@ export const ImportExceptionListFlyout = React.memo(
}
setFiles(null);
setAlreadyExistingItem(false);
setEndpointListImporting(false);
setAsNewList(false);
setOverwrite(false);
}, []);
Expand Down Expand Up @@ -128,6 +132,13 @@ export const ImportExceptionListFlyout = React.memo(
importExceptionListState?.result?.errors.forEach((err) => {
if (err.error.message.includes('already exists')) {
setAlreadyExistingItem(true);
if (
err.error.message.includes(
`Found that list_id: "${ENDPOINT_LIST_ID}" already exists`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's not an ideal way, of parsing exception messages like that, because the message can change, and this code will not work after.

Do we have any type or other identifier from API?

Copy link
Copy Markdown
Contributor Author

@e40pud e40pud Apr 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, there is no type. We only create a message with the list ID which already exists and pass it as an error message here https://github.com/elastic/kibana/blob/main/x-pack/plugins/lists/server/services/exception_lists/utils/import/sort_exception_lists_to_create_update.ts#L135

That's why we also do similar string check in line 133 above.

)
) {
setEndpointListImporting(true);
}
}
errorsToDisplay.push(err);
});
Expand Down Expand Up @@ -190,16 +201,22 @@ export const ImportExceptionListFlyout = React.memo(
setAsNewList(false);
}}
/>
<EuiCheckbox
id={'createNewListCheckbox'}
label={i18n.IMPORT_EXCEPTION_LIST_AS_NEW_LIST}
data-test-subj="importExceptionListCreateNewCheckbox"
checked={asNewList}
onChange={(e) => {
setAsNewList(!asNewList);
setOverwrite(false);
}}
/>
<EuiToolTip
position="bottom"
content={endpointListImporting ? i18n.IMPORT_EXCEPTION_ENDPOINT_LIST_WARNING : ''}
>
<EuiCheckbox
id={'createNewListCheckbox'}
label={i18n.IMPORT_EXCEPTION_LIST_AS_NEW_LIST}
data-test-subj="importExceptionListCreateNewCheckbox"
checked={asNewList}
disabled={endpointListImporting}
onChange={(e) => {
setAsNewList(!asNewList);
setOverwrite(false);
}}
/>
</EuiToolTip>
</>
)}
</EuiFlyoutBody>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const importExceptionList = async ({
formData.append('file', file as Blob);

const res = await http.post<ImportExceptionsResponseSchema>(`${EXCEPTION_LIST_URL}/_import`, {
version: '2023-10-31',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth mentioning in the description that this PR also addresses an issue with a missed version header.

body: formData,
query: { overwrite, overwrite_exceptions: overwriteExceptions, as_new_list: asNewList },
headers: { 'Content-Type': undefined },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,13 @@ export const IMPORT_EXCEPTION_LIST_AS_NEW_LIST = i18n.translate(
}
);

export const IMPORT_EXCEPTION_ENDPOINT_LIST_WARNING = i18n.translate(
'xpack.securitySolution.exceptionsTable.importExceptionEndpointListWarning',
{
defaultMessage: 'Multiple exception lists for Endpoint Security are not allowed.',
}
);

export const READ_ONLY_BADGE_TOOLTIP = i18n.translate(
'xpack.securitySolution.exceptions.badge.readOnly.tooltip',
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,68 +16,92 @@ import {
importExceptionListWithSelectingCreateNewOption,
validateImportExceptionListWentSuccessfully,
validateImportExceptionListFailedBecauseExistingListFound,
validateImportExceptionListCreateNewOptionDisabled,
} from '../../../../../../tasks/exceptions_table';
import { login } from '../../../../../../tasks/login';
import { visit } from '../../../../../../tasks/navigation';
import { EXCEPTIONS_URL } from '../../../../../../urls/navigation';

describe('Import Lists', { tags: ['@ess', '@serverless', '@skipInServerless'] }, () => {
const LIST_TO_IMPORT_FILENAME = 'cypress/fixtures/7_16_exception_list.ndjson';
const ENDPOINT_LIST_TO_IMPORT_FILENAME = 'cypress/fixtures/endpoint_exception_list.ndjson';
beforeEach(() => {
login();
visit(EXCEPTIONS_URL);
waitForExceptionsTableToBeLoaded();
cy.intercept(/(\/api\/exception_lists\/_import)/).as('import');
});

it('Should import exception list successfully if the list does not exist', () => {
importExceptionLists(LIST_TO_IMPORT_FILENAME);
describe('Exception Lists', () => {
it('Should import exception list successfully if the list does not exist', () => {
importExceptionLists(LIST_TO_IMPORT_FILENAME);

validateImportExceptionListWentSuccessfully();
validateImportExceptionListWentSuccessfully();

cy.get(IMPORT_SHARED_EXCEPTION_LISTS_CLOSE_BTN).click();
cy.get(IMPORT_SHARED_EXCEPTION_LISTS_CLOSE_BTN).click();

// Validate table items count
cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '1');
});
// Validate table items count
cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '1');
});

it('Should not import exception list if it exists', () => {
importExceptionLists(LIST_TO_IMPORT_FILENAME);
it('Should not import exception list if it exists', () => {
importExceptionLists(LIST_TO_IMPORT_FILENAME);

validateImportExceptionListFailedBecauseExistingListFound();
validateImportExceptionListFailedBecauseExistingListFound();

// Validate table items count
cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '1');
});
// Validate table items count
cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '1');
});

it('Should import exception list if it exists but the user selected overwrite checkbox', () => {
importExceptionLists(LIST_TO_IMPORT_FILENAME);

validateImportExceptionListFailedBecauseExistingListFound();

// Validate table items count
cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '1');

importExceptionListWithSelectingOverwriteExistingOption();

validateImportExceptionListWentSuccessfully();

it('Should import exception list if it exists but the user selected overwrite checkbox', () => {
importExceptionLists(LIST_TO_IMPORT_FILENAME);
// Validate table items count
cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '1');
});

validateImportExceptionListFailedBecauseExistingListFound();
it('Should import exception list if it exists but the user selected create new checkbox', () => {
importExceptionLists(LIST_TO_IMPORT_FILENAME);

// Validate table items count
cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '1');
validateImportExceptionListFailedBecauseExistingListFound();

importExceptionListWithSelectingOverwriteExistingOption();
// Validate table items count
cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '1');

validateImportExceptionListWentSuccessfully();
importExceptionListWithSelectingCreateNewOption();

// Validate table items count
cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '1');
validateImportExceptionListWentSuccessfully();
// Validate table items count
cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '2');
});
});

it('Should import exception list if it exists but the user selected create new checkbox', () => {
importExceptionLists(LIST_TO_IMPORT_FILENAME);
describe('Endpoint Security Exception List', () => {
before(() => {
login();
visit(EXCEPTIONS_URL);

validateImportExceptionListFailedBecauseExistingListFound();
// Make sure we have Endpoint Security Exception List
importExceptionLists(ENDPOINT_LIST_TO_IMPORT_FILENAME);
});

// Validate table items count
cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '1');
it('Should not allow to import or create a second Endpoint Security Exception List', () => {
// Try to import another Endpoint Security Exception List
importExceptionLists(ENDPOINT_LIST_TO_IMPORT_FILENAME);

importExceptionListWithSelectingCreateNewOption();
validateImportExceptionListFailedBecauseExistingListFound();

validateImportExceptionListWentSuccessfully();
// Validate table items count
cy.contains(EXCEPTIONS_TABLE_SHOWING_LISTS, '2');
// Validate that "Create new list" option is disabled
validateImportExceptionListCreateNewOptionDisabled();
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{"_version":"WzUxOTM4LDE1XQ==","created_at":"2024-03-18T14:11:18.125Z","created_by":"kibana","description":"Endpoint Security Exception List","id":"endpoint_list","immutable":false,"list_id":"endpoint_list","name":"Endpoint Security Exception List","namespace_type":"agnostic","os_types":[],"tags":[],"tie_breaker_id":"04deda68-7162-4349-8e34-c315bb9f896f","type":"endpoint","updated_at":"2024-03-19T12:57:31.911Z","updated_by":"elastic","version":1}
{"exported_exception_list_count":1,"exported_exception_list_item_count":0,"missing_exception_list_item_count":0,"missing_exception_list_items":[],"missing_exception_lists":[],"missing_exception_lists_count":0}
Original file line number Diff line number Diff line change
Expand Up @@ -295,3 +295,7 @@ export const validateImportExceptionListFailedBecauseExistingListFound = () => {
cy.get(TOASTER_BODY).should('contain', 'Found that list_id');
});
};

export const validateImportExceptionListCreateNewOptionDisabled = () => {
cy.get(IMPORT_SHARED_EXCEPTION_LISTS_OVERWRITE_CREATE_NEW_CHECKBOX).should('be.disabled');
};