wazuh-dashboard-plugins
wazuh-dashboard-plugins copied to clipboard
Custom branding: assets upload
Description
In order to ease the white-label process to the user, file upload for images and logos needs to be implemented.
Tasks
- [ ] (1) Design and implement backend endpoints to allow read/write operations for custom branding
- [ ] (2) Adapt the UI to allow the upload of images and icons.
We won't let the user select the name or folder of the file, just upload one, or reset to the original.
The tasks above might be elevated to issues, for the time being, this is what it's required:
-
GET, PUT & DELETE operations to read, upload and reset custom imagery. No files are created or removed, only read and overwritten. See the parent issue for details. We need to be very careful with these endpoints in terms of security. The image must be validated in the backend (format and dimensions). Their names and paths must be decided beforehand, by the backend.
-
Replace the text inputs by file pickers from the EUI framework. Validate the files in the frontend (format and dimensions). Send the files to the new endpoints.
Depends on: #4443
Proposal
The previous settings to customize the subpath where the assets were exposed in the plugin platform server are no longer necessary.
Design specifications
The configuration of these settings will be done in the Settings/Configuration
section of the UI.
These settings will use a file picker to drag or select the file. It should validate the supported extensions of the input file (this could change in the future of the implementation).
If the setting is configured, the UI will display a preview of the image and a button besides it to remove the image.
It is required to create new backend endpoints to manage the upload and removal of the assets.
Tasks
- [x] Define where the assets are saved.
<PLUGIN_PATH>/assets/custom/<type>
. For the images,<type>
isimages
- [x] Remove the settings related to the logo customizations from the plugin configuration file.
- [x] Update the plugin configuration with these new values. This affects how the app reads the configuration (new models and validation need to be created).
- [x] Implement access control to the assets (URL of the exposed static file or file system path)
- [x] Implement the UI with new input components. File pickers will be used for the imagery.
When custom images are set, the following UI components are added:
- [x] Image preview
- [x] Remove button
- [x] Implement backend endpoints to manage the upload and removal of these assets
- [x] Implement backend endpoint to upload custom imagery and branding texts.
- [x] Implement backend endpoint to remove custom imagery and branding texts.
- [x] Implement new logic to manage these settings from the UI.
- [x] Provide support for the required file extensions (.png, .svg, .jpeg) (not final).
- [x] Provide suggestions for image dimensions.
- [x] Validate the uploaded file extensions
- [x] in the frontend.
- [x] in the backend.
- [x] Validate the images do not exceed the maximum size. 1MB.
- [x] Tests
Details of the new plugin's settings
Due to the new design, the current logo customization will be removed, as file upload was not possible. Also, we want to support multiple file extensions to make it easier for the final user. As a consequence, the plugin will need to be aware of the file extension being used. In case of having several extensions for the same image, one, and only one of them must be used (priorities have to be defined yet). The UI must be aware of this selected setting in order to use the correct content type in the image preview.
An approach to this requirement would be to return this information in the same backend endpoint call that returns the plugin's settings (GET /utils/configuration
). To do this, we'll need to compare:
- the settings defined in the plugin's configuration file.
- the custom assets stored in the expected path.
These changes will be implemented in the getConfiguration
backend service and the mentioned route to get the plugin's configuration.
Specifications of endpoints to manage the assets
Target path: <PLUGIN_PATH>/assets/custom/images/<custom-logo>
We need to study if it's possible to store the custom assets in a directory that is not affected by the pulgin's update (persistence). For example:
<PLUGIN_PLATFORM_PATH>/data/wazuh/assets
. This requires exposing this directory (research if this is possible).
File upload
- Route:
PUT /utils/configuration/files/<custom-logo>
- Pre-conditions:
- authenticated user (if the plugin platform security is enabled)
- valid API token
-
administrator
API role
- Body:
-
file
: raw image data
-
- Actions:
- Save the file in the target path, using the hard-coded filename and overwriting any existing custom image.
File removal
- Route:
DELETE /utils/configuration/files/<custom-logo>
- Pre-conditions:
- authenticated user (if the plugin platform security is enabled)
- valid API token
-
administrator
API role
- Actions:
- Overwrite the custom image with the official Wazuh imagery.
UI design
The following things have been done:
- A file picker input component has been added, linked to the new plugin's settings (custom imagery)
- Add image preview, if present.
- Add remove button and confirmation prompt, if custom images are set.
Screenshots
- Addition of file pickers
- UI preview when custom images are set
- Hovering the remove icon
- Confirmation to remove the custom image
Changes in the specification
- The settings related to the image customization should be kept in the plugin's configuration file.
Tasks
- [x] Add back the settings in the configuration file, and adapt the current changes to allow these settings again.
Latest changes:
- Removed the composition of settings. Now all the settings are retrieved from the configuration file.
- Adapted the
getConfiguration
backend service. - Adapted the upload and removal of custom files.
- Adapted the
- Added validation of the parameter's types for the new backend endpoints.
- Added new properties to the setting's schema in order to do the following:
- define the filename of the images (cannot be changed by the users for security reasons)
- define how the image will be stored, and where (path)
- define how the URL of the asset will be resolved (public assets' directory)
- to manage how to store the file, define the filename to save in the file system and
- Refactorized the input components to be reusable.
- Uncoupled the preview image and the update button components when custom imagery is used.
- UI preview when custom images are set
Question: can the remove button be removed?? The file picker already has an option to remove the file, if it works, then the remove button is redundant.
- UI preview when custom images are set
Question: can the remove button be removed?? The file picker already has an option to remove the file, if it works, then the remove button is redundant.
The button to Remove
the file from the file picker only appear if there is a selected file. If the setting is set, and the user goes to Settings/Configuration
, the file picker has no selected file, it is empty.
Changes
- The inputs from the file pickers are now cleaned when the configuration has been saved.
There is an error displayed in the console when using the
removeFiles
method of theEuiFilePicker
component.
Limit the size of the uploaded file
We can limit the maximum size of the uploaded file by defining the options.body.maxBytes
route property.
router.put(
{
path: '/utils/configuration/files/{key}',
validate: validation,
options: {
body: {
maxBytes: <MAXIMUM_BYTES_PAYLOAD_UPLOAD_CUSTOM_FILE>,
},
}
},
handler
);
Information about the routes' options: https://github.com/elastic/kibana/blob/v7.10.2/src/core/server/http/router/route.ts#L81-L86
But the user can define a global value for using server.maxPayload
(Kibana 7.10.2). Default: 1048576
.
Do we want to set this value for the endpoint to upload the custom images? What value in bytes?
New requirement
- [x] Limit the maximum body size to upload files to 1 MB
Changes
Frontend
- Add size validation of the selected file of the file picker
Backend
- Add size validation of the request payload size. :exclamation: The endpoint receives more information than the file, so its value limits the total size. This difference does that the frontend validates successfully a file whose size is the same or near to the limit, and when saving the configuration, the backend throws a validation error.
Changes
Frontend
- Add size validation of the selected file of the file picker
![]()
Backend
- Add size validation of the request payload size. exclamation The endpoint receives more information than the file, so its value limits the total size. This difference does that the frontend validates successfully a file whose size is the same or near to the limit, and when saving the configuration, the backend throws a validation error.
Can the unit be megabytes, or at least kilobytes?
Changes
Frontend
- Add size validation of the selected file of the file picker
![]()
Backend
- Add size validation of the request payload size. exclamation The endpoint receives more information than the file, so its value limits the total size. This difference does that the frontend validates successfully a file whose size is the same or near to the limit, and when saving the configuration, the backend throws a validation error.
Can the unit be megabytes, or at least kilobytes?
I added a service to format the value to a meaningful unit.
Screenshots
TR:
Screencast from 26-10-22 10:34:07.webm
Screencast from 26-10-22 10:49:12.webm
Detected Problems: I can't used an SVG file to PDF logo. Used File:
't used an SVG file to PDF logo
The customization.logo.reports
setting can not use an SVG image.