From ac32a056ef6897d0b685da8b444c399294a5e53e Mon Sep 17 00:00:00 2001 From: Pablo Machado Date: Thu, 14 Nov 2024 14:55:21 +0100 Subject: [PATCH] [SecuritySolution] Update file validation because the file type is empty on windows (#199791) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Bug: On Windows, we can't select TSV files or drag them to the file picker. This error happens because we have a validation for the file type, and for some reason, on Windows, it is an empty string 🤡 . I updated the file validation logic to allow empty strings for file types and added one extra value to the acceptable types, `.tsv`. So, when the mime type checks fail, it will accept any files with the `tsv` extension. I desk-tested it on Windows-edge, Windows-chrome, Mac-chrome and it works. ### How to test it? * ON A WINDOWS MACHINE * Open the security solution app and navigate to the entity store page * Drag a TSV file created on a Windows machine; the file should be accepted * Click on the "select file" button and select a TSV file created on a Windows machine * Both methods should allow you to select the file, and you should be able to proceed with the bulk upload #### Do I need to checkout your code and start kibana? If you are a lazy person like me, you can test the feature using the cloud deployment [here](https://kibana-pr-199791.kb.us-west2.gcp.elastic-cloud.com/app/security/entity_analytics_entity_store). You can get the login/password using Vault. The instructions are on the latest Cloud Deployment link, or ask me for credentials. #### What if I don't have a Windows machine? Buy one. I am kidding. 🤡 You can follow [this tutorial](https://github.com/elastic/security-team/blob/main/tools/sec-eng-prod/sep-vms/README.md#setup) to deploy it to gcloud, and connect to it using RDP. But If you are lazy like me, you can ask me for my Windows 11 cloud deployment credentials. _Obs. You need an app to access the cloud deployment via RDP. The "Windows App" can be easily downloaded from the App Store on Mac._ ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --- .../asset_criticality_file_uploader/constants.ts | 8 +++++++- .../asset_criticality_file_uploader/hooks.test.ts | 3 ++- .../asset_criticality_file_uploader/validations.test.ts | 8 ++++++++ .../asset_criticality_file_uploader/validations.ts | 5 ++++- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/constants.ts b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/constants.ts index c64128274aa3d..966068eb4c074 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/constants.ts +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/constants.ts @@ -5,5 +5,11 @@ * 2.0. */ -export const SUPPORTED_FILE_TYPES = ['text/csv', 'text/plain', 'text/tab-separated-values']; +export const SUPPORTED_FILE_TYPES = [ + 'text/csv', + 'text/plain', + 'text/tab-separated-values', + '.tsv', // Useful for Windows when it can't recognise the file extension. + '.csv', // Useful for Windows when it can't recognise the file extension. +]; export const SUPPORTED_FILE_EXTENSIONS = ['CSV', 'TXT', 'TSV']; diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/hooks.test.ts b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/hooks.test.ts index 675535365a0b0..a3b9a2e0ce24e 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/hooks.test.ts +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/hooks.test.ts @@ -37,12 +37,13 @@ describe('useFileValidation', () => { test('should call onError when an error occurs', () => { const onErrorMock = jest.fn(); const onCompleteMock = jest.fn(); + const invalidFileType = 'invalid file type'; const { result } = renderHook( () => useFileValidation({ onError: onErrorMock, onComplete: onCompleteMock }), { wrapper: TestProviders } ); - result.current(new File([invalidLine], 'test.csv')); + result.current(new File([invalidLine], 'test.csv', { type: invalidFileType })); expect(onErrorMock).toHaveBeenCalled(); expect(onCompleteMock).not.toHaveBeenCalled(); diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/validations.test.ts b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/validations.test.ts index 4e742d4d92505..4a77e024528dd 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/validations.test.ts +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/validations.test.ts @@ -56,6 +56,14 @@ describe('validateFile', () => { expect(result.valid).toBe(true); }); + it('should return valid if the mime type is empty (Windows)', () => { + const file = new File(['file content'], 'test.csv', { type: '' }); + + const result = validateFile(file, formatBytes); + + expect(result.valid).toBe(true); + }); + it('should return an error message if the file type is invalid', () => { const file = new File(['file content'], 'test.txt', { type: 'invalid-type' }); diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/validations.ts b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/validations.ts index 06018a2496768..6f8bd8fb816bf 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/validations.ts +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/validations.ts @@ -53,7 +53,10 @@ export const validateFile = ( file: File, formatBytes: (bytes: number) => string ): { valid: false; errorMessage: string; code: string } | { valid: true } => { - if (!SUPPORTED_FILE_TYPES.includes(file.type)) { + if ( + file.type !== '' && // file.type might be an empty string on windows + !SUPPORTED_FILE_TYPES.includes(file.type) + ) { return { valid: false, code: 'unsupported_file_type',