diff --git a/.eslintrc.json b/.eslintrc.json
index 19490d613a..585dfa8951 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -2,6 +2,7 @@
"root": true,
"env": {
"browser": true,
+ "es2021": true,
"node": true,
"jest": true
},
@@ -32,7 +33,7 @@
"typescript": {}
},
"react": {
- "version": "16.12.0"
+ "version": "16.14.0"
}
},
"ignorePatterns": [
@@ -51,6 +52,15 @@
"spaced-comment": "error",
"no-duplicate-imports": "error",
"no-await-in-loop": "error",
+ "no-use-before-define": [
+ "error",
+ {
+ "functions": true,
+ "classes": true,
+ "variables": true,
+ "allowNamedExports": false
+ }
+ ],
"block-scoped-var": "error",
"curly": "error",
"default-case": "error",
diff --git a/.gitignore b/.gitignore
index 7f82c6b254..2cc137cef8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,9 +68,20 @@ typings/
# dotenv environment variables file
.env
-package-lock.json
target/
build/
yarn.lock
+
+cypress/node_modules/
+cypress/.idea/
+cypress/cypress.env.json
+cypress/report/
+cypress/cookies.json
+
+# Customization plugin assets
+public/assets/custom/*
+
+# Mac files
+.DS_Store
\ No newline at end of file
diff --git a/.kibana-plugin-helpers.bak.json b/.kibana-plugin-helpers.bak.json
deleted file mode 100644
index 99388baf94..0000000000
--- a/.kibana-plugin-helpers.bak.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "buildSourcePatterns": [
- "package.json",
- "LICENSE",
- "tsconfig.json",
- "index.js",
- "init.js",
- "server/**/*",
- "public/**/*",
- "common/**/*"
- ]
-}
diff --git a/.nvmrc b/.nvmrc
index 2baa2d433a..a3eb5a03fa 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-10.23.1
+14.20.0
diff --git a/.kibana-plugin-helpers.json b/.opensearch_dashboards-plugin-helpers.json
similarity index 82%
rename from .kibana-plugin-helpers.json
rename to .opensearch_dashboards-plugin-helpers.json
index acf46815e3..54e43ee80a 100644
--- a/.kibana-plugin-helpers.json
+++ b/.opensearch_dashboards-plugin-helpers.json
@@ -2,7 +2,7 @@
"serverSourcePatterns": [
"package.json",
"yarn.lock",
- "kibana.json",
+ "opensearch_dashboards.json",
"LICENSE",
"{common,server,target}/**/*",
"!*test*",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3e705caf96..0bba3b6c96 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,29 +2,139 @@
All notable changes to the Wazuh app project will be documented in this file.
-## Wazuh v4.3.10 - Kibana 7.10.2, 7.16.x, 7.17.x - Revision 4311
+## Wazuh v4.5.0 - OpenSearch Dashboards 2.3.0 - Revision 4500
+
+### Added
+
+- Added rel="noopener noreferrer" in documentation links. [#5197](https://github.com/wazuh/wazuh-kibana-app/pull/5197)
+- Added `ignore` and `restrict` options to Syslog configuration. [#5203](https://github.com/wazuh/wazuh-kibana-app/pull/5203)
+
+### Changed
+
+- Changed of regular expression in RBAC. [#5201](https://github.com/wazuh/wazuh-kibana-app/pull/5201)
+
+### Fixed
+
+- Fixed trailing hyphen character for OS value in the list of agents [#4828](https://github.com/wazuh/wazuh-kibana-app/pull/4828)
+- Fixed an issue that caused incorrect visualization of IPv6 addresses ([#4909](https://github.com/wazuh/wazuh-kibana-app/pull/4909)).
+- Fixed several typos in the code, by @jctello [#4911](https://github.com/wazuh/wazuh-kibana-app/pull/4911)
+- Fixed the display of more than one protocol in the Global configuration section [#4917](https://github.com/wazuh/wazuh-kibana-app/pull/4917)
+- Handling endpoint response was done when there is no data to show [#4918](https://github.com/wazuh/wazuh-kibana-app/pull/4918)
+- Fixed references to Elasticsearch in Wazuh-stack plugin [4894](https://github.com/wazuh/wazuh-kibana-app/pull/4894)
+- Fixed the 2 errors that appeared in console in Settings>Configuration section. [#5135](https://github.com/wazuh/wazuh-kibana-app/pull/5135)
+
+## Wazuh v4.4.0 - OpenSearch Dashboards 2.3.0 - Revision 4400
+
+### Added
+
+- Added the option to sort by the agents count in the group table. [#4323](https://github.com/wazuh/wazuh-kibana-app/pull/4323)
+- Added agent synchronization status in the agent module. [#3874](https://github.com/wazuh/wazuh-kibana-app/pull/3874) [#5143](https://github.com/wazuh/wazuh-kibana-app/pull/5143) [#5177](https://github.com/wazuh/wazuh-kibana-app/pull/5177)
+- The input name was added and when the user adds a value the variable WAZUH_AGENT_NAME with its value appears in the installation command. [#4739](https://github.com/wazuh/wazuh-kibana-app/pull/4739)
+- Redesign the SCA table from agent's dashboard [#4512](https://github.com/wazuh/wazuh-kibana-app/pull/4512)
+- Enhanced the plugin setting description displayed in the UI and the configuration file. [#4501](https://github.com/wazuh/wazuh-kibana-app/pull/4501)
+- Added validation to the plugin settings in the form of `Settings/Configuration` and the endpoint to update the plugin configuration [#4503](https://github.com/wazuh/wazuh-kibana-app/pull/4503)[#4785](https://github.com/wazuh/wazuh-kibana-app/pull/4785)
+- Added new plugin settings to customize the header and footer on the PDF reports [#4505](https://github.com/wazuh/wazuh-kibana-app/pull/4505)[#4798](https://github.com/wazuh/wazuh-kibana-app/pull/4798)[#4805](https://github.com/wazuh/wazuh-kibana-app/pull/4805)
+- Added a new plugin setting to enable or disable the customization [#4507](https://github.com/wazuh/wazuh-kibana-app/pull/4507)
+- Added the ability to upload an image for the `customization.logo.*` settings in `Settings/Configuration` [#4504](https://github.com/wazuh/wazuh-kibana-app/pull/4504)
+- Added macOS version to wizard deploy agent [#4867](https://github.com/wazuh/wazuh-kibana-app/pull/4867)
+- Added powerPC architecture in redhat7, in the section 'Deploy new agent'. [#4833](https://github.com/wazuh/wazuh-kibana-app/pull/4833)
+- Added a centralized service to handle the requests [#4831](https://github.com/wazuh/wazuh-kibana-app/pull/4831)
+- Added data-test-subj create policy [#4873](https://github.com/wazuh/wazuh-kibana-app/pull/4873)
+- Added extra steps message and new command for windows xp and windows server 2008, added alpine agent with all its steps. [#4933](https://github.com/wazuh/wazuh-kibana-app/pull/4933)
+- Deploy new agent section: Added link for additional steps to alpine os. [#4933](https://github.com/wazuh/wazuh-kibana-app/pull/4933)
+- Added file saving conditions in File Editor [#4970](https://github.com/wazuh/wazuh-kibana-app/pull/4970)
+- Added character validation to avoid invalid agent names in the section 'Deploy new agent'. [#5021](https://github.com/wazuh/wazuh-kibana-app/pull/5021) [#5028](https://github.com/wazuh/wazuh-kibana-app/pull/5028)
+- Added default selected options in Deploy Agent page [#5063](https://github.com/wazuh/wazuh-kibana-app/pull/5063)
+- Added server address and wazuh protocol definition in Deploy agent section [#5166](https://github.com/wazuh/wazuh-kibana-app/pull/5166)
+
+### Changed
+
+- Changed the HTTP verb from `GET` to `POST` in the requests to login to the Wazuh API [#4103](https://github.com/wazuh/wazuh-kibana-app/pull/4103)
+- Improved alerts summary performance [#4376](https://github.com/wazuh/wazuh-kibana-app/pull/4376) [#5071](https://github.com/wazuh/wazuh-kibana-app/pull/5071) [#5131](https://github.com/wazuh/wazuh-kibana-app/pull/5131)
+- Improved Agents Overview performance [#4363](https://github.com/wazuh/wazuh-kibana-app/pull/4363) [#5076](https://github.com/wazuh/wazuh-kibana-app/pull/5076)
+- Improved the message displayed when there is a versions mismatch between the Wazuh API and the Wazuh APP [#4529](https://github.com/wazuh/wazuh-kibana-app/pull/4529) [#4964](https://github.com/wazuh/wazuh-kibana-app/pull/4964)
+- Independently load each dashboard from the `Agents Overview` page [#4363](https://github.com/wazuh/wazuh-kibana-app/pull/4363)
+- The endpoint `/agents/summary/status` response was adapted. [#3874](https://github.com/wazuh/wazuh-kibana-app/pull/3874)
+- Updated and added operating systems, versions, architectures commands of Install and enroll the agent and commands of Start the agent in the deploy new agent section [#4458](https://github.com/wazuh/wazuh-kibana-app/pull/4458)
+- Added cluster's IP and protocol as suggestions in the agent deployment wizard. [#4776](https://github.com/wazuh/wazuh-kibana-app/pull/4776) [#4954](https://github.com/wazuh/wazuh-kibana-app/pull/4954)
+- Show OS name and OS version in the agent installation wizard. [#4851](https://github.com/wazuh/wazuh-kibana-app/pull/4851)
+- Changed the endpoint that updates the plugin configuration to support multiple settings. [#4501](https://github.com/wazuh/wazuh-kibana-app/pull/4501)
+- Updated the `winston` dependency to `3.5.1` [#4985](https://github.com/wazuh/wazuh-kibana-app/pull/4985)
+- Updated the `pdfmake` dependency to `0.2.6` [#4985](https://github.com/wazuh/wazuh-kibana-app/pull/4985)
+- The button to export the app logs is now disabled when there are no results, instead of showing an error toast [#4992](https://github.com/wazuh/wazuh-kibana-app/pull/4992)
+- Unify the SCA check result label name [#5031](https://github.com/wazuh/wazuh-kibana-app/pull/5031)
+- Updated `mocha` dependency to `10.1.0` [#5062](https://github.com/wazuh/wazuh-kibana-app/pull/5062)
+- Updated `pdfmake` dependency to `0.2.7` [#5062](https://github.com/wazuh/wazuh-kibana-app/pull/5062)
+
+### Fixed
+
+- Fixed nested fields filtering in dashboards tables and KPIs [#4425](https://github.com/wazuh/wazuh-kibana-app/pull/4425)
+- Fixed nested field rendering in security alerts table details [#4428](https://github.com/wazuh/wazuh-kibana-app/pull/4428)
+- Fixed a bug where the Wazuh logo was used instead of the custom one [#4539](https://github.com/wazuh/wazuh-kibana-app/pull/4539)
+- Fixed rendering problems of the `Agent Overview` section in low resolutions [#4516](https://github.com/wazuh/wazuh-kibana-app/pull/4516)
+- Fixed issue when logging out from Wazuh when SAML is enabled [#4595](https://github.com/wazuh/wazuh-kibana-app/issues/4595)
+- Fixed server errors with code 500 when the Wazuh API is not reachable / up. [#4710](https://github.com/wazuh/wazuh-kibana-app/pull/4710) [#4728](https://github.com/wazuh/wazuh-kibana-app/pull/4728) [#4971](https://github.com/wazuh/wazuh-kibana-app/pull/4971)
+- Fixed pagination to SCA table [#4653](https://github.com/wazuh/wazuh-kibana-app/issues/4653) [#5010](https://github.com/wazuh/wazuh-kibana-app/pull/5010)
+- Fixed WAZUH_PROTOCOL param suggestion [#4849](https://github.com/wazuh/wazuh-kibana-app/pull/4849)
+- Raspbian OS, Ubuntu, Amazon Linux and Amazon Linux 2 commands in the wizard deploy agent now change when a different architecture is selected [#4876](https://github.com/wazuh/wazuh-kibana-app/pull/4876) [#4880](https://github.com/wazuh/wazuh-kibana-app/pull/4880)
+- Disabled unmapped fields filter in Security Events alerts table [#4929](https://github.com/wazuh/wazuh-kibana-app/pull/4929)
+- Deploy new agent section: Fixed the way macos versions and architectures were displayed, fixed the way agents were displayed, fixed the way ubuntu versions were displayed. [#4933](https://github.com/wazuh/wazuh-kibana-app/pull/4933)
+- Fixed agent deployment instructions for HP-UX and Solaris. [#4943](https://github.com/wazuh/wazuh-kibana-app/pull/4943)
+- Fixed a bug that caused the flyouts to close when clicking inside them [#4638](https://github.com/wazuh/wazuh-kibana-app/pull/4638) [#5046](https://github.com/wazuh/wazuh-kibana-app/pull/5046)
+- Fixed the manager option in the agent deployment section [#4981](https://github.com/wazuh/wazuh-kibana-app/pull/4981)
+- Fixed Inventory checks table filters by stats [#4999](https://github.com/wazuh/wazuh-kibana-app/pull/4999) [#5031](https://github.com/wazuh/wazuh-kibana-app/pull/5031)
+- Fixed commands in the deploy new agent section(most of the commands are missing '-1') [#4962](https://github.com/wazuh/wazuh-kibana-app/pull/4962)
+- Fixed agent installation command for macOS in the deploy new agent section. [#4968](https://github.com/wazuh/wazuh-kibana-app/pull/4968)
+- Deploy new agent section: Fixed the way macos versions and architectures were displayed, fixed the way agents were displayed, fixed the way ubuntu versions were displayed. [#4933](https://github.com/wazuh/wazuh-kibana-app/pull/4933)
+- Fixed agent deployment instructions for HP-UX and Solaris. [#4943](https://github.com/wazuh/wazuh-kibana-app/pull/4943)
+- Fixed Inventory checks table filters by stats [#4999](https://github.com/wazuh/wazuh-kibana-app/pull/4999)
+- Fixed agent graph in opensearch dashboard [#4942](https://github.com/wazuh/wazuh-kibana-app/pull/4942)
+- Fixed commands in the deploy new agent section(most of the commands are missing '-1') [#4962](https://github.com/wazuh/wazuh-kibana-app/pull/4962)
+- Fixed agent installation command for macOS in the deploy new agent section. [#4968](https://github.com/wazuh/wazuh-kibana-app/pull/4968)
+- Fixed commands in the deploy new agent section(most of the commands are missing '-1') [#4984](https://github.com/wazuh/wazuh-kibana-app/pull/4984)
+- Fixed vulnerabilities default last scan date formatter [#4975](https://github.com/wazuh/wazuh-kibana-app/pull/4975)
+- A solaris command has been fixed [#5035](https://github.com/wazuh/wazuh-kibana-app/pull/5035)
+- Fixed commands: Aix, OpenSUSE, Alpine, Suse11, Fedora, HP, Oracle Linux 5, Amazon Linux 2, Centos5. Changed the word 'or higher' in buttons to '+'.Fixed validations for Hp, Solaris and Alpine. [#5045](https://github.com/wazuh/wazuh-kibana-app/pull/5045)
+- Fixed error in Github module PDF report. [#5069](https://github.com/wazuh/wazuh-kibana-app/pull/5069)
+- Fixed password input in deploy new agent section [#5098](https://github.com/wazuh/wazuh-kibana-app/pull/5098)
+- Fixed error when clicking on the selectors of agents in the group agents management [#5094](https://github.com/wazuh/wazuh-kibana-app/pull/5094)
+- Fixed menu content panel is displayed in the wrong place. [5092](https://github.com/wazuh/wazuh-kibana-app/pull/5092)
+- Fixed greyed and disabled menu section names [#5101](https://github.com/wazuh/wazuh-kibana-app/pull/5101)
+- Fixed mispelling in the NIST module [#5107](https://github.com/wazuh/wazuh-kibana-app/pull/5107)
+- Fixed Statistic cronjob bulk document insert [#5150](https://github.com/wazuh/wazuh-kibana-app/pull/5150)
+- Fixed the style of the buttons showing more event information in the event view table. [#5137](https://github.com/wazuh/wazuh-kibana-app/pull/5137)
+- Fixed Inventory module for solaris agents [#5144](https://github.com/wazuh/wazuh-kibana-app/pull/5144)
+- Fixed the module information button in Office365 and Github Panel tab to open the nav drawer. [#5167](https://github.com/wazuh/wazuh-kibana-app/pull/5167)
+
+### Removed
+
+- Removed custom styles from kibana 7.9.0 [#4491](https://github.com/wazuh/wazuh-kibana-app/pull/4491)
+- Removed the `angular-chart.js` dependency [#4985](https://github.com/wazuh/wazuh-kibana-app/pull/4985)
+- Remove the `pug-loader` dependency [#5062](https://github.com/wazuh/wazuh-kibana-app/pull/5062) [#5089](https://github.com/wazuh/wazuh-kibana-app/pull/5089)
+
+## Wazuh v4.3.10 - OpenSearch Dashboards 1.2.0 - Revision 4311
### Fixed
- Fixed issue when logging out from Wazuh when SAML is enabled [#4815](https://github.com/wazuh/wazuh-kibana-app/issues/4815)
-## Wazuh v4.3.9 - Kibana 7.10.2, 7.16.x, 7.17.x - Revision 4310
+## Wazuh v4.3.9 - OpenSearch Dashboards 1.2.0 - Revision 4310
### Added
- Support for Wazuh 4.3.9
-## Wazuh v4.3.8 - Kibana 7.10.2, 7.16.x, 7.17.x - Revision 4309
+## Wazuh v4.3.8 - OpenSearch Dashboards 1.2.0 - Revision 4309
### Added
- Support for Wazuh 4.3.8
-## Wazuh v4.3.7 - Kibana 7.10.2, 7.16.x, 7.17.x - Revision 4308
+## Wazuh v4.3.7 - OpenSearch Dashboards 1.2.0 - Revision 4308
### Fixed
-- Wazuh.yml review: fixed link to web documentation, improved in-file documentation and fixed some grammatical errors. [#4378](https://github.com/wazuh/wazuh-kibana-app/pull/4378) [#4399](https://github.com/wazuh/wazuh-kibana-app/pull/4399)
+- Wazuh.yml review: fixed link to web documentation, improved in-file documentation and fixed some grammatical errors. [#4378](https://github.com/wazuh/wazuh-kibana-app/pull/4378) [#4399](https://github.com/wazuh/wazuh-kibana-app/pull/4399)
- Fixed an error during the generation of a group's report, if the request to the Wazuh API fails [#4350](https://github.com/wazuh/wazuh-kibana-app/pull/4350)
- Fixed a problem with the group's report, when the group has no agents [#4350](https://github.com/wazuh/wazuh-kibana-app/pull/4350)
- Fixed path in logo customization section [#4352](https://github.com/wazuh/wazuh-kibana-app/pull/4352)
@@ -34,11 +144,11 @@ All notable changes to the Wazuh app project will be documented in this file.
- Fixed searchbar error on SCA Inventory table [#4367](https://github.com/wazuh/wazuh-kibana-app/pull/4367)
- Fixed a routes loop when reinstalling Wazuh indexer [#4373](https://github.com/wazuh/wazuh-kibana-app/pull/4373)
-# Removed
+### Removed
- Removed the use of `manager_host` field related to agent information of Wazuh API responses, which is obsolete [#4350](https://github.com/wazuh/wazuh-kibana-app/pull/4350)
-## Wazuh v4.3.6 - Kibana 7.10.2, 7.16.x, 7.17.x - Revision 4307
+## Wazuh v4.3.6 - OpenSearch Dashboards 1.2.0 - Revision 4307
### Fixed
@@ -51,7 +161,7 @@ All notable changes to the Wazuh app project will be documented in this file.
- Fix Rules, Decoders and CDB lists uploaders to show errors appropriately [#4307](https://github.com/wazuh/wazuh-kibana-app/pull/4307)
- Sanitize report's inputs and usernames [#4330](https://github.com/wazuh/wazuh-kibana-app/pull/4330)
-## Wazuh v4.3.5 - Kibana 7.10.2, 7.16.x, 7.17.x - Revision 4306
+## Wazuh v4.3.5 - OpenSearch Dashboards 1.2.0 - Revision 4306
### Added
@@ -75,7 +185,7 @@ All notable changes to the Wazuh app project will be documented in this file.
- Fixed an error related to `API not available` when saving the manager configuration and restarting the manager from `Management/Configuration/Edit configuration` on manager mode [#4264](https://github.com/wazuh/wazuh-kibana-app/pull/4264)
- Fixed a UI problem that required scrolling to see the logs in Management/Logs and Settings/Logs [#4253](https://github.com/wazuh/wazuh-kibana-app/pull/4253)
-## Wazuh v4.3.4 - Kibana 7.10.2, 7.16.x, 7.17.x - Revision 4305
+## Wazuh v4.3.4 - OpenSearch Dashboards 1.2.0 - Revision 4305
### Added
@@ -97,25 +207,19 @@ All notable changes to the Wazuh app project will be documented in this file.
- Fixed import of an empty rule or decoder file [#4176](https://github.com/wazuh/wazuh-kibana-app/pull/4176)
- Fixed overwriting of rule and decoder imports [#4180](https://github.com/wazuh/wazuh-kibana-app/pull/4180)
-## Wazuh v4.3.3 - Kibana 7.10.2, 7.16.x, 7.17.x - Revision 4304
+## Wazuh v4.3.3 - OpenSearch Dashboards 1.2.0 - Revision 4304
### Fixed
-- Fixed Wazuh Dashboard troubleshooting url [#4150](https://github.com/wazuh/wazuh-kibana-app/pull/4150)
+- Fixed Wazuh Dashboard troubleshooting url [#4151](https://github.com/wazuh/wazuh-kibana-app/pull/4151)
-## Wazuh v4.3.2 - Kibana 7.10.2 , 7.16.x, 7.17.x - Revision 4303
+## Wazuh v4.3.2 - OpenSearch Dashboards 1.2.0 - Revision 4303
### Added
- Support for Wazuh 4.3.2
-## Wazuh v4.2.7 - Kibana 7.10.2, 7.11.2, 7.12.1, 7.13.0, 7.13.1, 7.13.2, 7.13.3, 7.13.4, 7.14.0, 7.14.1, 7.14.2 - Revision 4208
-
-### Added
-
-- Support for Wazuh 4.2.7
-
-## Wazuh v4.3.1 - Kibana 7.10.2 , 7.16.x, 7.17.x - Revision 4302
+## Wazuh v4.3.1 - OpenSearch Dashboards 1.2.0 - Revision 4302
### Added
@@ -126,12 +230,11 @@ All notable changes to the Wazuh app project will be documented in this file.
- Fixed the falsy values are displayed as not defined and enhanced the output of `Ruleset Test` [#4141](https://github.com/wazuh/wazuh-kibana-app/pull/4141)
-## Wazuh v4.3.0 - Kibana 7.10.2, 7.16.x, 7.17.x - Revision 4301
+## Wazuh v4.3.0 - OpenSearch Dashboards 1.2.0 - Revision 4301
### Added
-- Support for Kibana 7.16.x
-- Support for Kibana 7.17.x
+- Support for OpenSearch Dashboards 1.2.0
- Added GitHub and Office365 modules [#3557](https://github.com/wazuh/wazuh-kibana-app/pull/3557)
- Added a new `Panel` module tab for GitHub and Office365 modules
[#3541](https://github.com/wazuh/wazuh-kibana-app/pull/3541)
@@ -183,6 +286,7 @@ All notable changes to the Wazuh app project will be documented in this file.
- Run `template` and `fields` checks in the health check depends on the app configuration [#3783](https://github.com/wazuh/wazuh-kibana-app/pull/3783)
- Added a toast message when there is an error creating a new group [#3804](https://github.com/wazuh/wazuh-kibana-app/pull/3804)
- Added a step to start the agent to the deploy new Windowns agent guide [#3846](https://github.com/wazuh/wazuh-kibana-app/pull/3846)
+- Added agents windows events config tab [#3905](https://github.com/wazuh/wazuh-kibana-app/pull/3905)
- Added 3 new panels to `Vulnerabilities/Inventory` [#3893](https://github.com/wazuh/wazuh-kibana-app/pull/3893)
- Added new fields of `Vulnerabilities` to the details flyout [#3893](https://github.com/wazuh/wazuh-kibana-app/pull/3893) [#3908](https://github.com/wazuh/wazuh-kibana-app/pull/3908)
- Added missing fields used in visualizations to the known fiels related to alerts [#3924](https://github.com/wazuh/wazuh-kibana-app/pull/3924)
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000..24d9ab4370
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,11 @@
+# Generate tags for a release automatically.
+# Update the tag.py file before running this script.
+
+prebuild:
+ @echo "- Updating project's versions ..."
+ @node scripts/generate-build-version
+
+tags:
+ @echo "- Generating Git tags ..."
+ @python3 scripts/tag.py
+
diff --git a/README.md b/README.md
index 4b30cae5af..750366620e 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,11 @@
-# Wazuh Kibana App
+# Wazuh OpenSearch Dashboards App
[](https://wazuh.com/community/join-us-on-slack/)
[](https://groups.google.com/forum/#!forum/wazuh)
[](https://documentation.wazuh.com)
[](https://wazuh.com)
-This repository contains the Wazuh Kibana plugin, from which you can navigate through the Wazuh data using visualizations in a simple and understandable way. It also allows you to manage the configuration and capabilities of the Wazuh server.
+This repository contains the Wazuh OpenSearch Dashboards plugin, from which you can navigate through the Wazuh data using visualizations in a simple and understandable way. It also allows you to manage the configuration and capabilities of the Wazuh server.
Wazuh is a security detection, visibility, and compliance open source project. Wazuh helps you to gain deeper security visibility into your infrastructure by monitoring hosts at an operating system and application level.
@@ -13,7 +13,7 @@ You can learn more about it here [wazuh.com](https://wazuh.com/)
## Description
-This plugin for Kibana allows you to visualize and analyze Wazuh alerts stored in Elasticsearch and provides the following capabilities:
+This plugin for OpenSearch Dashboards allows you to visualize and analyze Wazuh alerts stored in OpenSearch and provides the following capabilities:
- Search alerts classified by modules and filter them using the different views. You will be able to explore the alerts both at Wazuh cluster level, and in a particular agent. The modules, divided into the following use cases, are:
- Security Information Management
@@ -89,139 +89,9 @@ This plugin for Kibana allows you to visualize and analyze Wazuh alerts stored i
## Requisites
-- Wazuh HIDS 4.3.10
-- Kibana 7.10.2
-- Elasticsearch 7.10.2
-
-## Installation
-
-Ensure that the directory `/usr/share/kibana/data` exists
-If not create it:
-
-```
-mkdir /usr/share/kibana/data
-chown -R kibana:kibana /usr/share/kibana/data
-```
-
-Install the Wazuh app plugin for Kibana
-
-```
-cd /usr/share/kibana
-sudo -u kibana bin/kibana-plugin install https://packages.wazuh.com/4.x/ui/kibana/wazuh_kibana-4.3.10_7.10.2-1.zip
-```
-
-Restart Kibana
-
-- Systemd:
-
-```
-systemctl restart kibana
-```
-
-- SysV Init:
-
-```
-service kibana restart
-```
-
-## Upgrade
-
-Note: Since Wazuh 4.0.4 release revision 4016 (regardless of the Elastic Stack version) the location of the wazuh.yml has been moved from `/usr/share/kibana/optimize/wazuh/config/wazuh.yml` to `/usr/share/kibana/data/wazuh/config/wazuh.yml`.
-
-Since Wazuh 3.12.0 release (regardless of the Elastic Stack version) the location of the wazuh.yml has been moved from `/usr/share/kibana/plugins/wazuh/wazuh.yml` to `/usr/share/kibana/data/wazuh/config/wazuh.yml`.
-
-Stop Kibana
-
-- Systemd:
-
-```
-systemctl stop kibana
-```
-
-- SysV Init:
-
-```
-service kibana stop
-```
-Ensure that the directory `/usr/share/kibana/data` exists
-If not create it:
-
-```
-mkdir /usr/share/kibana/data
-```
-
-### From 3.11.x
-Copy the `wazuh.yml` to its new location.
-
-```
-mkdir -p /usr/share/kibana/data/wazuh/config
-cp /usr/share/kibana/plugins/wazuh/wazuh.yml /usr/share/kibana/optimize/wazuh/config/wazuh.yml
-```
-### From 4.0.4 - 4016
-Copy the `wazuh.yml` to its new location.
-
-```
-mkdir -p /usr/share/kibana/data/wazuh/config
-cp /usr/share/kibana/optimize/wazuh/config/wazuh.yml /usr/share/kibana/data/wazuh/config/wazuh.yml
-```
-
-```
-mkdir -p /usr/share/kibana/data/wazuh/config
-cp /usr/share/kibana/optimize/wazuh/config/wazuh.yml /usr/share/kibana/data/wazuh/config/wazuh.yml
-```
-
-Remove the Wazuh app using the kibana-plugin tool
-
-```
-cd /usr/share/kibana/
-sudo -u kibana bin/kibana-plugin remove wazuh
-```
-
-Remove generated bundles
-
-```
-rm -rf /usr/share/kibana/optimize/bundles
-```
-
-Update file permissions. This will prevent errors when generating new bundles or updating the app:
-
-```
-chown -R kibana:kibana /usr/share/kibana/data
-chown -R kibana:kibana /usr/share/kibana/plugins
-```
-
-Install the Wazuh app
-
-```
-cd /usr/share/kibana/
-sudo -u kibana bin/kibana-plugin install https://packages.wazuh.com/4.x/ui/kibana/wazuh_kibana-4.3.10_7.10.2-1.zip
-```
-
-Update configuration file permissions.
-
-```
-sudo chown kibana:kibana /usr/share/kibana/data/wazuh/config/wazuh.yml
-sudo chmod 600 /usr/share/kibana/data/wazuh/config/wazuh.yml
-```
-
-Restart Kibana
-
-- Systemd:
-
-```
-systemctl restart kibana
-```
-
-- SysV Init:
-
-```
-service kibana restart
-```
-
-
-## Wazuh - Kibana - Open Distro version compatibility matrix
-
-The compatibility matrix is avaliable in the repository [wiki](https://github.com/wazuh/wazuh-kibana-app/wiki/Compatibility).
+- Wazuh HIDS 4.5.0
+- Wazuh dashboard 4.5.0
+- Wazuh indexer 4.5.0
## Contribute
diff --git a/common/api-info/endpoints.json b/common/api-info/endpoints.json
index a08c83ac0e..c75ae31920 100644
--- a/common/api-info/endpoints.json
+++ b/common/api-info/endpoints.json
@@ -4,7 +4,7 @@
"endpoints": [
{
"name": "/",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.default_controller.default_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.default_controller.default_info",
"description": "Return basic information about the API",
"summary": "Get API info",
"tags": [
@@ -23,7 +23,7 @@
},
{
"name": "/agents",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agents",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agents",
"description": "Return information about all available agents or a list of them",
"summary": "List agents",
"tags": [
@@ -52,6 +52,17 @@
"format": "group_names"
}
},
+ {
+ "name": "group_config_status",
+ "description": "Agent groups configuration sync status",
+ "schema": {
+ "type": "string",
+ "enum": [
+ "synced",
+ "not synced"
+ ]
+ }
+ },
{
"name": "ip",
"description": "Filter by the IP used by the agent to communicate with the manager. If it's not available, it will have the same value as registerIP",
@@ -206,7 +217,7 @@
},
{
"name": "version",
- "description": "Filter by agents version",
+ "description": "Filter by agents version using one of the following formats: 'X.Y.Z', 'vX.Y.Z', 'wazuh X.Y.Z' or 'wazuh vX.Y.Z'. For example: '4.4.0'",
"schema": {
"type": "string",
"format": "alphanumeric"
@@ -224,7 +235,7 @@
},
{
"name": "/agents/:agent_id/config/:component/:configuration",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_config",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_config",
"description": "Return the active configuration the agent is currently using. This can be different from the configuration present in the configuration file, if it has been modified and the agent has not been restarted yet",
"summary": "Get active configuration",
"tags": [
@@ -261,13 +272,14 @@
"monitor",
"request",
"syscheck",
+ "wazuh-db",
"wmodules"
]
}
},
{
"name": ":configuration",
- "description": "
Selected agent's configuration to read. The configuration to read depends on the selected component.\nThe following table shows all available combinations of component and configuration values:
\n\n\n\nComponent \nConfiguration \nTag \n \n \n\n\nagent \nclient \n<client>
\n \n\nagent \nbuffer \n<client_buffer>
\n \n\nagent \nlabels \n<labels>
\n \n\nagent \ninternal \n<agent>
, <monitord>
, <remoted>
\n \n\nagentless \nagentless \n<agentless>
\n \n\nanalysis \nglobal \n<global>
\n \n\nanalysis \nactive_response \n<active-response>
\n \n\nanalysis \nalerts \n<alerts>
\n \n\nanalysis \ncommand \n<command>
\n \n\nanalysis \nrules \n<rule>
\n \n\nanalysis \ndecoders \n<decoder>
\n \n\nanalysis \ninternal \n<analysisd>
\n \n\nauth \nauth \n<auth>
\n \n\ncom \nactive-response \n<active-response>
\n \n\ncom \nlogging \n<logging>
\n \n\ncom \ninternal \n<execd>
\n \n\ncom \ncluster \n<cluster>
\n \n\ncsyslog \ncsyslog \n<csyslog_output>
\n \n\nintegrator \nintegration \n<integration>
\n \n\nlogcollector \nlocalfile \n<localfile>
\n \n\nlogcollector \nsocket \n<socket>
\n \n\nlogcollector \ninternal \n<logcollector>
\n \n\nmail \nglobal \n<global><email...>
\n \n\nmail \nalerts \n<email_alerts>
\n \n\nmail \ninternal \n<maild>
\n \n\nmonitor \nglobal \n<global>
\n \n\nmonitor \ninternal \n<monitord>
\n \n\nmonitor \ninternal \n<reports>
\n \n\nrequest \nglobal \n<global>
\n \n\nrequest \nremote \n<remote>
\n \n\nrequest \ninternal \n<remoted>
\n \n\nsyscheck \nsyscheck \n<syscheck>
\n \n\nsyscheck \nrootcheck \n<rootcheck>
\n \n\nsyscheck \ninternal \n<syscheck>
, <rootcheck>
\n \n\nwmodules \nwmodules \n<wodle>
\n \n \n
\n",
+ "description": "Selected agent's configuration to read. The configuration to read depends on the selected component.\nThe following table shows all available combinations of component and configuration values:
\n\n\n\nComponent \nConfiguration \nTag \n \n \n\n\nagent \nclient \n<client>
\n \n\nagent \nbuffer \n<client_buffer>
\n \n\nagent \nlabels \n<labels>
\n \n\nagent \ninternal \n<agent>
, <monitord>
, <remoted>
\n \n\nagentless \nagentless \n<agentless>
\n \n\nanalysis \nglobal \n<global>
\n \n\nanalysis \nactive_response \n<active-response>
\n \n\nanalysis \nalerts \n<alerts>
\n \n\nanalysis \ncommand \n<command>
\n \n\nanalysis \nrules \n<rule>
\n \n\nanalysis \ndecoders \n<decoder>
\n \n\nanalysis \ninternal \n<analysisd>
\n \n\nanalysis \nrule_test \n<rule_test>
\n \n\nauth \nauth \n<auth>
\n \n\ncom \nactive-response \n<active-response>
\n \n\ncom \nlogging \n<logging>
\n \n\ncom \ninternal \n<execd>
\n \n\ncom \ncluster \n<cluster>
\n \n\ncsyslog \ncsyslog \n<csyslog_output>
\n \n\nintegrator \nintegration \n<integration>
\n \n\nlogcollector \nlocalfile \n<localfile>
\n \n\nlogcollector \nsocket \n<socket>
\n \n\nlogcollector \ninternal \n<logcollector>
\n \n\nmail \nglobal \n<global><email...>
\n \n\nmail \nalerts \n<email_alerts>
\n \n\nmail \ninternal \n<maild>
\n \n\nmonitor \nglobal \n<global>
\n \n\nmonitor \ninternal \n<monitord>
\n \n\nmonitor \ninternal \n<reports>
\n \n\nrequest \nglobal \n<global>
\n \n\nrequest \nremote \n<remote>
\n \n\nrequest \ninternal \n<remoted>
\n \n\nsyscheck \nsyscheck \n<syscheck>
\n \n\nsyscheck \nrootcheck \n<rootcheck>
\n \n\nsyscheck \ninternal \n<syscheck>
, <rootcheck>
\n \n\nwazuh-db \ninternal \n<wazuh_db>
\n \n\nwazuh-db \nwdb \n<wdb>
\n \n\nwmodules \nwmodules \n<wodle>
\n \n \n
\n",
"required": true,
"schema": {
"type": "string",
@@ -295,7 +307,9 @@
"remote",
"syscheck",
"rootcheck",
- "wmodules"
+ "wdb",
+ "wmodules",
+ "rule_test"
]
}
}
@@ -319,9 +333,63 @@
}
]
},
+ {
+ "name": "/agents/:agent_id/daemons/stats",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_daemon_stats",
+ "description": "Return Wazuh statistical information from specified daemons in a specified agent",
+ "summary": "Get Wazuh daemon stats from an agent",
+ "tags": [
+ "Agents"
+ ],
+ "args": [
+ {
+ "name": ":agent_id",
+ "description": "Agent ID. All possible values from 000 onwards",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "minLength": 3,
+ "description": "Agent ID",
+ "format": "numbers"
+ }
+ }
+ ],
+ "query": [
+ {
+ "name": "daemons_list",
+ "description": "List of daemon names (separated by comma), all daemons selected by default if not specified",
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "wazuh-analysisd",
+ "wazuh-remoted"
+ ]
+ }
+ }
+ },
+ {
+ "name": "pretty",
+ "description": "Show results in human-readable format",
+ "schema": {
+ "type": "boolean",
+ "default": false
+ }
+ },
+ {
+ "name": "wait_for_complete",
+ "description": "Disable timeout response",
+ "schema": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ ]
+ },
{
"name": "/agents/:agent_id/group/is_sync",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_sync_agent",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_sync_agent",
"description": "Return whether the agent configuration has been synchronized with the agent or not. This can be useful to check after updating a group configuration",
"summary": "Get configuration sync status",
"tags": [
@@ -361,7 +429,7 @@
},
{
"name": "/agents/:agent_id/key",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_key",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_key",
"description": "Return the key of an agent",
"summary": "Get key",
"tags": [
@@ -401,7 +469,7 @@
},
{
"name": "/agents/:agent_id/stats/:component",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_component_stats",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_component_stats",
"description": "Return Wazuh's {component} statistical information from agent {agent_id}",
"summary": "Get agent's component stats",
"tags": [
@@ -453,7 +521,7 @@
},
{
"name": "/agents/no_group",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_no_group",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_no_group",
"description": "Return a list with all the available agents without an assigned group",
"summary": "List agents without group",
"tags": [
@@ -535,7 +603,7 @@
},
{
"name": "/agents/outdated",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_outdated",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_outdated",
"description": "Return the list of outdated agents",
"summary": "List outdated agents",
"tags": [
@@ -606,7 +674,7 @@
},
{
"name": "/agents/stats/distinct",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_fields",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_fields",
"description": "Return all the different combinations that agents have for the selected fields. It also indicates the total number of agents that have each combination",
"summary": "List agents distinct",
"tags": [
@@ -688,7 +756,7 @@
},
{
"name": "/agents/summary/os",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_summary_os",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_summary_os",
"description": "Return a summary of the OS of available agents",
"summary": "Summarize agents OS",
"tags": [
@@ -715,8 +783,8 @@
},
{
"name": "/agents/summary/status",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_summary_status",
- "description": "Return a summary of the status of available agents",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_summary_status",
+ "description": "Return a summary of the connection and groups configuration synchronization statuses of available agents",
"summary": "Summarize agents status",
"tags": [
"Agents"
@@ -742,7 +810,7 @@
},
{
"name": "/agents/upgrade_result",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_upgrade",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agent_upgrade",
"description": "Return the agents upgrade results",
"summary": "Get upgrade results",
"tags": [
@@ -852,7 +920,7 @@
},
{
"name": "version",
- "description": "Filter by agents version",
+ "description": "Filter by agents version using one of the following formats: 'X.Y.Z', 'vX.Y.Z', 'wazuh X.Y.Z' or 'wazuh vX.Y.Z'. For example: '4.4.0'",
"schema": {
"type": "string",
"format": "alphanumeric"
@@ -870,7 +938,7 @@
},
{
"name": "/ciscat/:agent_id/results",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.ciscat_controller.get_agents_ciscat_results",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.ciscat_controller.get_agents_ciscat_results",
"description": "Return the agent's ciscat results info",
"summary": "Get results",
"tags": [
@@ -1034,7 +1102,7 @@
},
{
"name": "/cluster/:node_id/configuration",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_configuration_node",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_configuration_node",
"description": "Return wazuh configuration used in node {node_id}. The 'section' and 'field' parameters will be ignored if 'raw' parameter is provided.",
"summary": "Get node config",
"tags": [
@@ -1105,7 +1173,6 @@
"socket",
"syscheck",
"syslog_output",
- "agent-key-polling",
"aws-s3",
"azure-logs",
"cis-cat",
@@ -1129,7 +1196,7 @@
},
{
"name": "/cluster/:node_id/configuration/:component/:configuration",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_node_config",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_node_config",
"description": "Return the requested configuration in JSON format for the specified node",
"summary": "Get node active configuration",
"tags": [
@@ -1155,13 +1222,14 @@
"monitor",
"request",
"syscheck",
+ "wazuh-db",
"wmodules"
]
}
},
{
"name": ":configuration",
- "description": "Selected agent's configuration to read. The configuration to read depends on the selected component.\nThe following table shows all available combinations of component and configuration values:
\n\n\n\nComponent \nConfiguration \nTag \n \n \n\n\nagent \nclient \n<client>
\n \n\nagent \nbuffer \n<client_buffer>
\n \n\nagent \nlabels \n<labels>
\n \n\nagent \ninternal \n<agent>
, <monitord>
, <remoted>
\n \n\nagentless \nagentless \n<agentless>
\n \n\nanalysis \nglobal \n<global>
\n \n\nanalysis \nactive_response \n<active-response>
\n \n\nanalysis \nalerts \n<alerts>
\n \n\nanalysis \ncommand \n<command>
\n \n\nanalysis \nrules \n<rule>
\n \n\nanalysis \ndecoders \n<decoder>
\n \n\nanalysis \ninternal \n<analysisd>
\n \n\nauth \nauth \n<auth>
\n \n\ncom \nactive-response \n<active-response>
\n \n\ncom \nlogging \n<logging>
\n \n\ncom \ninternal \n<execd>
\n \n\ncom \ncluster \n<cluster>
\n \n\ncsyslog \ncsyslog \n<csyslog_output>
\n \n\nintegrator \nintegration \n<integration>
\n \n\nlogcollector \nlocalfile \n<localfile>
\n \n\nlogcollector \nsocket \n<socket>
\n \n\nlogcollector \ninternal \n<logcollector>
\n \n\nmail \nglobal \n<global><email...>
\n \n\nmail \nalerts \n<email_alerts>
\n \n\nmail \ninternal \n<maild>
\n \n\nmonitor \nglobal \n<global>
\n \n\nmonitor \ninternal \n<monitord>
\n \n\nmonitor \ninternal \n<reports>
\n \n\nrequest \nglobal \n<global>
\n \n\nrequest \nremote \n<remote>
\n \n\nrequest \ninternal \n<remoted>
\n \n\nsyscheck \nsyscheck \n<syscheck>
\n \n\nsyscheck \nrootcheck \n<rootcheck>
\n \n\nsyscheck \ninternal \n<syscheck>
, <rootcheck>
\n \n\nwmodules \nwmodules \n<wodle>
\n \n \n
\n",
+ "description": "Selected agent's configuration to read. The configuration to read depends on the selected component.\nThe following table shows all available combinations of component and configuration values:
\n\n\n\nComponent \nConfiguration \nTag \n \n \n\n\nagent \nclient \n<client>
\n \n\nagent \nbuffer \n<client_buffer>
\n \n\nagent \nlabels \n<labels>
\n \n\nagent \ninternal \n<agent>
, <monitord>
, <remoted>
\n \n\nagentless \nagentless \n<agentless>
\n \n\nanalysis \nglobal \n<global>
\n \n\nanalysis \nactive_response \n<active-response>
\n \n\nanalysis \nalerts \n<alerts>
\n \n\nanalysis \ncommand \n<command>
\n \n\nanalysis \nrules \n<rule>
\n \n\nanalysis \ndecoders \n<decoder>
\n \n\nanalysis \ninternal \n<analysisd>
\n \n\nanalysis \nrule_test \n<rule_test>
\n \n\nauth \nauth \n<auth>
\n \n\ncom \nactive-response \n<active-response>
\n \n\ncom \nlogging \n<logging>
\n \n\ncom \ninternal \n<execd>
\n \n\ncom \ncluster \n<cluster>
\n \n\ncsyslog \ncsyslog \n<csyslog_output>
\n \n\nintegrator \nintegration \n<integration>
\n \n\nlogcollector \nlocalfile \n<localfile>
\n \n\nlogcollector \nsocket \n<socket>
\n \n\nlogcollector \ninternal \n<logcollector>
\n \n\nmail \nglobal \n<global><email...>
\n \n\nmail \nalerts \n<email_alerts>
\n \n\nmail \ninternal \n<maild>
\n \n\nmonitor \nglobal \n<global>
\n \n\nmonitor \ninternal \n<monitord>
\n \n\nmonitor \ninternal \n<reports>
\n \n\nrequest \nglobal \n<global>
\n \n\nrequest \nremote \n<remote>
\n \n\nrequest \ninternal \n<remoted>
\n \n\nsyscheck \nsyscheck \n<syscheck>
\n \n\nsyscheck \nrootcheck \n<rootcheck>
\n \n\nsyscheck \ninternal \n<syscheck>
, <rootcheck>
\n \n\nwazuh-db \ninternal \n<wazuh_db>
\n \n\nwazuh-db \nwdb \n<wdb>
\n \n\nwmodules \nwmodules \n<wodle>
\n \n \n
\n",
"required": true,
"schema": {
"type": "string",
@@ -1189,7 +1257,9 @@
"remote",
"syscheck",
"rootcheck",
- "wmodules"
+ "wdb",
+ "wmodules",
+ "rule_test"
]
}
},
@@ -1222,9 +1292,62 @@
}
]
},
+ {
+ "name": "/cluster/:node_id/daemons/stats",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_daemon_stats_node",
+ "description": "Return Wazuh statistical information from specified daemons in a specified cluster node",
+ "summary": "Get Wazuh daemon stats from a cluster node",
+ "tags": [
+ "Cluster"
+ ],
+ "args": [
+ {
+ "name": ":node_id",
+ "description": "Cluster node name",
+ "required": true,
+ "schema": {
+ "type": "string",
+ "format": "names"
+ }
+ }
+ ],
+ "query": [
+ {
+ "name": "daemons_list",
+ "description": "List of daemon names (separated by comma), all daemons selected by default if not specified",
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "wazuh-analysisd",
+ "wazuh-remoted",
+ "wazuh-db"
+ ]
+ }
+ }
+ },
+ {
+ "name": "pretty",
+ "description": "Show results in human-readable format",
+ "schema": {
+ "type": "boolean",
+ "default": false
+ }
+ },
+ {
+ "name": "wait_for_complete",
+ "description": "Disable timeout response",
+ "schema": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ ]
+ },
{
"name": "/cluster/:node_id/info",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_info_node",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_info_node",
"description": "Return basic information about a specified node such as version, compilation date, installation path",
"summary": "Get node info",
"tags": [
@@ -1262,7 +1385,7 @@
},
{
"name": "/cluster/:node_id/logs",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_log_node",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_log_node",
"description": "Return the last 2000 wazuh log entries in the specified node",
"summary": "Get node logs",
"tags": [
@@ -1367,7 +1490,7 @@
},
{
"name": "/cluster/:node_id/logs/summary",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_log_summary_node",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_log_summary_node",
"description": "Return a summary of the last 2000 wazuh log entries in the specified node",
"summary": "Get node logs summary",
"tags": [
@@ -1405,7 +1528,7 @@
},
{
"name": "/cluster/:node_id/stats",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_stats_node",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_stats_node",
"description": "Return Wazuh statistical information in node {node_id} for the current or specified date",
"summary": "Get node stats",
"tags": [
@@ -1451,7 +1574,7 @@
},
{
"name": "/cluster/:node_id/stats/analysisd",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_stats_analysisd_node",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_stats_analysisd_node",
"description": "Return Wazuh analysisd statistical information in node {node_id}",
"summary": "Get node stats analysisd",
"tags": [
@@ -1489,7 +1612,7 @@
},
{
"name": "/cluster/:node_id/stats/hourly",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_stats_hourly_node",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_stats_hourly_node",
"description": "Return Wazuh statistical information in node {node_id} per hour. Each number in the averages field represents the average of alerts per hour",
"summary": "Get node stats hour",
"tags": [
@@ -1527,7 +1650,7 @@
},
{
"name": "/cluster/:node_id/stats/remoted",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_stats_remoted_node",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_stats_remoted_node",
"description": "Return Wazuh remoted statistical information in node {node_id}",
"summary": "Get node stats remoted",
"tags": [
@@ -1565,7 +1688,7 @@
},
{
"name": "/cluster/:node_id/stats/weekly",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_stats_weekly_node",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_stats_weekly_node",
"description": "Return Wazuh statistical information in node {node_id} per week. Each number in the averages field represents the average of alerts per hour for that specific day",
"summary": "Get node stats week",
"tags": [
@@ -1603,7 +1726,7 @@
},
{
"name": "/cluster/:node_id/status",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_status_node",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_status_node",
"description": "Return the status of all Wazuh daemons in node node_id",
"summary": "Get node status",
"tags": [
@@ -1641,7 +1764,7 @@
},
{
"name": "/cluster/api/config",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_api_config",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_api_config",
"description": "Return the API configuration of all nodes (or a list of them) in JSON format",
"summary": "Get nodes API config",
"tags": [
@@ -1678,7 +1801,7 @@
},
{
"name": "/cluster/configuration/validation",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_conf_validation",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_conf_validation",
"description": "Return whether the Wazuh configuration is correct or not in all cluster nodes or a list of them",
"summary": "Check nodes config",
"tags": [
@@ -1715,7 +1838,7 @@
},
{
"name": "/cluster/healthcheck",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_healthcheck",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_healthcheck",
"description": "Return cluster healthcheck information for all nodes or a list of them. Such information includes last keep alive, last synchronization time and number of agents reporting on each node",
"summary": "Get nodes healthcheck",
"tags": [
@@ -1752,7 +1875,7 @@
},
{
"name": "/cluster/local/config",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_config",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_config",
"description": "Return the current node cluster configuration",
"summary": "Get local node config",
"tags": [
@@ -1779,7 +1902,7 @@
},
{
"name": "/cluster/local/info",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_cluster_node",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_cluster_node",
"description": "Return basic information about the cluster node receiving the request",
"summary": "Get local node info",
"tags": [
@@ -1806,7 +1929,7 @@
},
{
"name": "/cluster/nodes",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_cluster_nodes",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_cluster_nodes",
"description": "Get information about all nodes in the cluster or a list of them",
"summary": "Get nodes info",
"tags": [
@@ -1907,9 +2030,46 @@
}
]
},
+ {
+ "name": "/cluster/ruleset/synchronization",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_nodes_ruleset_sync_status",
+ "description": "Return ruleset synchronization status for all nodes or a list of them. This synchronization only covers the user custom ruleset",
+ "summary": "Get cluster nodes ruleset synchronization status",
+ "tags": [
+ "Cluster"
+ ],
+ "query": [
+ {
+ "name": "nodes_list",
+ "description": "List of node IDs (separated by comma), all nodes selected by default if not specified",
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ {
+ "name": "pretty",
+ "description": "Show results in human-readable format",
+ "schema": {
+ "type": "boolean",
+ "default": false
+ }
+ },
+ {
+ "name": "wait_for_complete",
+ "description": "Disable timeout response",
+ "schema": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ ]
+ },
{
"name": "/cluster/status",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_status",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.get_status",
"description": "Return information about the cluster status",
"summary": "Get cluster status",
"tags": [
@@ -1936,7 +2096,7 @@
},
{
"name": "/decoders",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.decoder_controller.get_decoders",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.decoder_controller.get_decoders",
"description": "Return information about all decoders included in ossec.conf. This information include decoder's route, decoder's name, decoder's file among others",
"summary": "List decoders",
"tags": [
@@ -2061,7 +2221,7 @@
},
{
"name": "/decoders/files",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.decoder_controller.get_decoders_files",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.decoder_controller.get_decoders_files",
"description": "Return information about all decoders files used in Wazuh. This information include decoder's file, decoder's route and decoder's status among others",
"summary": "Get files",
"tags": [
@@ -2157,7 +2317,7 @@
},
{
"name": "/decoders/files/:filename",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.decoder_controller.get_file",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.decoder_controller.get_file",
"description": "Get the content of a specified decoder file",
"summary": "Get decoders file content",
"tags": [
@@ -2203,7 +2363,7 @@
},
{
"name": "/decoders/parents",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.decoder_controller.get_decoders_parents",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.decoder_controller.get_decoders_parents",
"description": "Return information about all parent decoders. A parent decoder is a decoder used as base of other decoders",
"summary": "Get parent decoders",
"tags": [
@@ -2278,7 +2438,7 @@
},
{
"name": "/experimental/ciscat/results",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_cis_cat_results",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_cis_cat_results",
"description": "Return CIS-CAT results for all agents or a list of them",
"summary": "Get agents CIS-CAT results",
"tags": [
@@ -2435,7 +2595,7 @@
},
{
"name": "/experimental/syscollector/hardware",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_hardware_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_hardware_info",
"description": "Return all agents (or a list of them) hardware info. This information include cpu, ram, scan info among others of all agents",
"summary": "Get agents hardware",
"tags": [
@@ -2574,7 +2734,7 @@
},
{
"name": "/experimental/syscollector/hotfixes",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_hotfixes_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_hotfixes_info",
"description": "Return all agents (or a list of them) hotfixes info",
"summary": "Get agents hotfixes",
"tags": [
@@ -2669,7 +2829,7 @@
},
{
"name": "/experimental/syscollector/netaddr",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_network_address_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_network_address_info",
"description": "Return all agents (or a list of them) IPv4 and IPv6 addresses associated to their network interfaces. This information include used IP protocol, interface, and IP address among others",
"summary": "Get agents netaddr",
"tags": [
@@ -2789,7 +2949,7 @@
},
{
"name": "/experimental/syscollector/netiface",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_network_interface_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_network_interface_info",
"description": "Return all agents (or a list of them) network interfaces. This information includes rx, scan, tx info and some network information among other",
"summary": "Get agents netiface",
"tags": [
@@ -2990,7 +3150,7 @@
},
{
"name": "/experimental/syscollector/netproto",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_network_protocol_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_network_protocol_info",
"description": "Return all agents (or a list of them) routing configuration for each network interface. This information includes interface, type protocol information among other",
"summary": "Get agents netproto",
"tags": [
@@ -3116,7 +3276,7 @@
},
{
"name": "/experimental/syscollector/os",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_os_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_os_info",
"description": "Return all agents (or a list of them) OS info. This information includes os information, architecture information among other",
"summary": "Get agents OS",
"tags": [
@@ -3226,7 +3386,7 @@
},
{
"name": "version",
- "description": "Filter by agents version",
+ "description": "Filter by agents version using one of the following formats: 'X.Y.Z', 'vX.Y.Z', 'wazuh X.Y.Z' or 'wazuh vX.Y.Z'. For example: '4.4.0'",
"schema": {
"type": "string",
"format": "alphanumeric"
@@ -3244,7 +3404,7 @@
},
{
"name": "/experimental/syscollector/packages",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_packages_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_packages_info",
"description": "Return all agents (or a list of them) packages info. This information includes name, section, size, and priority information of all packages among other",
"summary": "Get agents packages",
"tags": [
@@ -3370,7 +3530,7 @@
},
{
"name": "/experimental/syscollector/ports",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_ports_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_ports_info",
"description": "Return all agents (or a list of them) ports info. This information includes local IP, Remote IP, protocol information among other",
"summary": "Get agents ports",
"tags": [
@@ -3522,7 +3682,7 @@
},
{
"name": "/experimental/syscollector/processes",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_processes_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.experimental_controller.get_processes_info",
"description": "Return all agents (or a list of them) processes info",
"summary": "Get agents processes",
"tags": [
@@ -3722,7 +3882,7 @@
},
{
"name": "/groups",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_list_group",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_list_group",
"description": "Get information about all groups or a list of them. Returns a list containing basic information about each group such as number of agents belonging to the group and the checksums of the configuration and shared files",
"summary": "Get groups",
"tags": [
@@ -3819,7 +3979,7 @@
},
{
"name": "/groups/:group_id/agents",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agents_in_group",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_agents_in_group",
"description": "Return the list of agents that belong to the specified group",
"summary": "Get agents in a group",
"tags": [
@@ -3930,7 +4090,7 @@
},
{
"name": "/groups/:group_id/configuration",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_group_config",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_group_config",
"description": "Return the group configuration defined in the `agent.conf` file",
"summary": "Get group configuration",
"tags": [
@@ -3990,7 +4150,7 @@
},
{
"name": "/groups/:group_id/files",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_group_files",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_group_files",
"description": "Return the files placed under the group directory",
"summary": "Get group files",
"tags": [
@@ -4087,7 +4247,7 @@
},
{
"name": "/groups/:group_id/files/:file_name/json",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_group_file_json",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_group_file_json",
"description": "Return the content of the specified group file parsed to JSON",
"summary": "Get a file in group",
"tags": [
@@ -4151,7 +4311,7 @@
},
{
"name": "/groups/:group_id/files/:file_name/xml",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_group_file_xml",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.get_group_file_xml",
"description": "Return the contents of the specified group file parsed to XML",
"summary": "Get a file in group",
"tags": [
@@ -4215,7 +4375,7 @@
},
{
"name": "/lists",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cdb_list_controller.get_lists",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cdb_list_controller.get_lists",
"description": "Return the contents of all CDB lists. Optionally, the result can be filtered by several criteria. See available parameters for more details",
"summary": "Get CDB lists info",
"tags": [
@@ -4309,7 +4469,7 @@
},
{
"name": "/lists/files",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cdb_list_controller.get_lists_files",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cdb_list_controller.get_lists_files",
"description": "Return the path from all CDB lists. Use this method to know all the CDB lists and their location in the filesystem relative to Wazuh installation folder",
"summary": "Get CDB lists files",
"tags": [
@@ -4392,7 +4552,7 @@
},
{
"name": "/lists/files/:filename",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cdb_list_controller.get_file",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cdb_list_controller.get_file",
"description": "Return the content of a CDB list file. Only the filename can be specified. It will be searched recursively if not found",
"summary": "Get CDB list file content",
"tags": [
@@ -4438,7 +4598,7 @@
},
{
"name": "/manager/api/config",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_api_config",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_api_config",
"description": "Return the local API configuration in JSON format",
"summary": "Get API config",
"tags": [
@@ -4465,7 +4625,7 @@
},
{
"name": "/manager/configuration",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_configuration",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_configuration",
"description": "Return wazuh configuration used. The 'section' and 'field' parameters will be ignored if 'raw' parameter is provided.",
"summary": "Get configuration",
"tags": [
@@ -4525,7 +4685,6 @@
"socket",
"syscheck",
"syslog_output",
- "agent-key-polling",
"aws-s3",
"azure-logs",
"cis-cat",
@@ -4549,7 +4708,7 @@
},
{
"name": "/manager/configuration/:component/:configuration",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_manager_config_ondemand",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_manager_config_ondemand",
"description": "Return the requested active configuration in JSON format",
"summary": "Get active configuration",
"tags": [
@@ -4575,13 +4734,14 @@
"monitor",
"request",
"syscheck",
+ "wazuh-db",
"wmodules"
]
}
},
{
"name": ":configuration",
- "description": "Selected agent's configuration to read. The configuration to read depends on the selected component.\nThe following table shows all available combinations of component and configuration values:
\n\n\n\nComponent \nConfiguration \nTag \n \n \n\n\nagent \nclient \n<client>
\n \n\nagent \nbuffer \n<client_buffer>
\n \n\nagent \nlabels \n<labels>
\n \n\nagent \ninternal \n<agent>
, <monitord>
, <remoted>
\n \n\nagentless \nagentless \n<agentless>
\n \n\nanalysis \nglobal \n<global>
\n \n\nanalysis \nactive_response \n<active-response>
\n \n\nanalysis \nalerts \n<alerts>
\n \n\nanalysis \ncommand \n<command>
\n \n\nanalysis \nrules \n<rule>
\n \n\nanalysis \ndecoders \n<decoder>
\n \n\nanalysis \ninternal \n<analysisd>
\n \n\nauth \nauth \n<auth>
\n \n\ncom \nactive-response \n<active-response>
\n \n\ncom \nlogging \n<logging>
\n \n\ncom \ninternal \n<execd>
\n \n\ncom \ncluster \n<cluster>
\n \n\ncsyslog \ncsyslog \n<csyslog_output>
\n \n\nintegrator \nintegration \n<integration>
\n \n\nlogcollector \nlocalfile \n<localfile>
\n \n\nlogcollector \nsocket \n<socket>
\n \n\nlogcollector \ninternal \n<logcollector>
\n \n\nmail \nglobal \n<global><email...>
\n \n\nmail \nalerts \n<email_alerts>
\n \n\nmail \ninternal \n<maild>
\n \n\nmonitor \nglobal \n<global>
\n \n\nmonitor \ninternal \n<monitord>
\n \n\nmonitor \ninternal \n<reports>
\n \n\nrequest \nglobal \n<global>
\n \n\nrequest \nremote \n<remote>
\n \n\nrequest \ninternal \n<remoted>
\n \n\nsyscheck \nsyscheck \n<syscheck>
\n \n\nsyscheck \nrootcheck \n<rootcheck>
\n \n\nsyscheck \ninternal \n<syscheck>
, <rootcheck>
\n \n\nwmodules \nwmodules \n<wodle>
\n \n \n
\n",
+ "description": "Selected agent's configuration to read. The configuration to read depends on the selected component.\nThe following table shows all available combinations of component and configuration values:
\n\n\n\nComponent \nConfiguration \nTag \n \n \n\n\nagent \nclient \n<client>
\n \n\nagent \nbuffer \n<client_buffer>
\n \n\nagent \nlabels \n<labels>
\n \n\nagent \ninternal \n<agent>
, <monitord>
, <remoted>
\n \n\nagentless \nagentless \n<agentless>
\n \n\nanalysis \nglobal \n<global>
\n \n\nanalysis \nactive_response \n<active-response>
\n \n\nanalysis \nalerts \n<alerts>
\n \n\nanalysis \ncommand \n<command>
\n \n\nanalysis \nrules \n<rule>
\n \n\nanalysis \ndecoders \n<decoder>
\n \n\nanalysis \ninternal \n<analysisd>
\n \n\nanalysis \nrule_test \n<rule_test>
\n \n\nauth \nauth \n<auth>
\n \n\ncom \nactive-response \n<active-response>
\n \n\ncom \nlogging \n<logging>
\n \n\ncom \ninternal \n<execd>
\n \n\ncom \ncluster \n<cluster>
\n \n\ncsyslog \ncsyslog \n<csyslog_output>
\n \n\nintegrator \nintegration \n<integration>
\n \n\nlogcollector \nlocalfile \n<localfile>
\n \n\nlogcollector \nsocket \n<socket>
\n \n\nlogcollector \ninternal \n<logcollector>
\n \n\nmail \nglobal \n<global><email...>
\n \n\nmail \nalerts \n<email_alerts>
\n \n\nmail \ninternal \n<maild>
\n \n\nmonitor \nglobal \n<global>
\n \n\nmonitor \ninternal \n<monitord>
\n \n\nmonitor \ninternal \n<reports>
\n \n\nrequest \nglobal \n<global>
\n \n\nrequest \nremote \n<remote>
\n \n\nrequest \ninternal \n<remoted>
\n \n\nsyscheck \nsyscheck \n<syscheck>
\n \n\nsyscheck \nrootcheck \n<rootcheck>
\n \n\nsyscheck \ninternal \n<syscheck>
, <rootcheck>
\n \n\nwazuh-db \ninternal \n<wazuh_db>
\n \n\nwazuh-db \nwdb \n<wdb>
\n \n\nwmodules \nwmodules \n<wodle>
\n \n \n
\n",
"required": true,
"schema": {
"type": "string",
@@ -4609,7 +4769,9 @@
"remote",
"syscheck",
"rootcheck",
- "wmodules"
+ "wdb",
+ "wmodules",
+ "rule_test"
]
}
}
@@ -4635,7 +4797,7 @@
},
{
"name": "/manager/configuration/validation",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_conf_validation",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_conf_validation",
"description": "Return whether the Wazuh configuration is correct",
"summary": "Check config",
"tags": [
@@ -4660,9 +4822,51 @@
}
]
},
+ {
+ "name": "/manager/daemons/stats",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_daemon_stats",
+ "description": "Return Wazuh statistical information from specified daemons",
+ "summary": "Get Wazuh daemon stats",
+ "tags": [
+ "Manager"
+ ],
+ "query": [
+ {
+ "name": "daemons_list",
+ "description": "List of daemon names (separated by comma), all daemons selected by default if not specified",
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "enum": [
+ "wazuh-analysisd",
+ "wazuh-remoted",
+ "wazuh-db"
+ ]
+ }
+ }
+ },
+ {
+ "name": "pretty",
+ "description": "Show results in human-readable format",
+ "schema": {
+ "type": "boolean",
+ "default": false
+ }
+ },
+ {
+ "name": "wait_for_complete",
+ "description": "Disable timeout response",
+ "schema": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ ]
+ },
{
"name": "/manager/info",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_info",
"description": "Return basic information such as version, compilation date, installation path",
"summary": "Get information",
"tags": [
@@ -4689,7 +4893,7 @@
},
{
"name": "/manager/logs",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_log",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_log",
"description": "Return the last 2000 wazuh log entries",
"summary": "Get logs",
"tags": [
@@ -4783,7 +4987,7 @@
},
{
"name": "/manager/logs/summary",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_log_summary",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_log_summary",
"description": "Return a summary of the last 2000 wazuh log entries",
"summary": "Get logs summary",
"tags": [
@@ -4810,7 +5014,7 @@
},
{
"name": "/manager/stats",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_stats",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_stats",
"description": "Return Wazuh statistical information for the current or specified date",
"summary": "Get stats",
"tags": [
@@ -4845,7 +5049,7 @@
},
{
"name": "/manager/stats/analysisd",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_stats_analysisd",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_stats_analysisd",
"description": "Return Wazuh analysisd statistical information",
"summary": "Get stats analysisd",
"tags": [
@@ -4872,7 +5076,7 @@
},
{
"name": "/manager/stats/hourly",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_stats_hourly",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_stats_hourly",
"description": "Return Wazuh statistical information per hour. Each number in the averages field represents the average of alerts per hour",
"summary": "Get stats hour",
"tags": [
@@ -4899,7 +5103,7 @@
},
{
"name": "/manager/stats/remoted",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_stats_remoted",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_stats_remoted",
"description": "Return Wazuh remoted statistical information",
"summary": "Get stats remoted",
"tags": [
@@ -4926,7 +5130,7 @@
},
{
"name": "/manager/stats/weekly",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_stats_weekly",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_stats_weekly",
"description": "Return Wazuh statistical information per week. Each number in the averages field represents the average of alerts per hour for that specific day",
"summary": "Get stats week",
"tags": [
@@ -4953,7 +5157,7 @@
},
{
"name": "/manager/status",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_status",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.get_status",
"description": "Return the status of all Wazuh daemons",
"summary": "Get status",
"tags": [
@@ -4980,7 +5184,7 @@
},
{
"name": "/mitre/groups",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.mitre_controller.get_groups",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.mitre_controller.get_groups",
"description": "Return the groups from MITRE database",
"summary": "Get MITRE groups",
"tags": [
@@ -5073,7 +5277,7 @@
},
{
"name": "/mitre/metadata",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.mitre_controller.get_metadata",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.mitre_controller.get_metadata",
"description": "Return the metadata from MITRE database",
"summary": "Get MITRE metadata",
"tags": [
@@ -5100,7 +5304,7 @@
},
{
"name": "/mitre/mitigations",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.mitre_controller.get_mitigations",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.mitre_controller.get_mitigations",
"description": "Return the mitigations from MITRE database",
"summary": "Get MITRE mitigations",
"tags": [
@@ -5193,7 +5397,7 @@
},
{
"name": "/mitre/references",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.mitre_controller.get_references",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.mitre_controller.get_references",
"description": "Return the references from MITRE database",
"summary": "Get MITRE references",
"tags": [
@@ -5286,7 +5490,7 @@
},
{
"name": "/mitre/software",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.mitre_controller.get_software",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.mitre_controller.get_software",
"description": "Return the software from MITRE database",
"summary": "Get MITRE software",
"tags": [
@@ -5379,7 +5583,7 @@
},
{
"name": "/mitre/tactics",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.mitre_controller.get_tactics",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.mitre_controller.get_tactics",
"description": "Return the tactics from MITRE database",
"summary": "Get MITRE tactics",
"tags": [
@@ -5472,7 +5676,7 @@
},
{
"name": "/mitre/techniques",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.mitre_controller.get_techniques",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.mitre_controller.get_techniques",
"description": "Return the techniques from MITRE database",
"summary": "Get MITRE techniques",
"tags": [
@@ -5565,7 +5769,7 @@
},
{
"name": "/overview/agents",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.overview_controller.get_overview_agents",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.overview_controller.get_overview_agents",
"description": "Return a dictionary with a full agents overview",
"summary": "Get agents overview",
"tags": [
@@ -5592,7 +5796,7 @@
},
{
"name": "/rootcheck/:agent_id",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.rootcheck_controller.get_rootcheck_agent",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.rootcheck_controller.get_rootcheck_agent",
"description": "Return the rootcheck database of an agent",
"summary": "Get results",
"tags": [
@@ -5719,7 +5923,7 @@
},
{
"name": "/rootcheck/:agent_id/last_scan",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.rootcheck_controller.get_last_scan_agent",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.rootcheck_controller.get_last_scan_agent",
"description": "Return the timestamp of the last rootcheck scan of an agent",
"summary": "Get last scan datetime",
"tags": [
@@ -5759,7 +5963,7 @@
},
{
"name": "/rules",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.rule_controller.get_rules",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.rule_controller.get_rules",
"description": "Return a list containing information about each rule such as file where it's defined, description, rule group, status, etc",
"summary": "List rules",
"tags": [
@@ -5957,7 +6161,7 @@
},
{
"name": "/rules/files",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.rule_controller.get_rules_files",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.rule_controller.get_rules_files",
"description": "Return a list containing all files used to define rules and their status",
"summary": "Get files",
"tags": [
@@ -6053,7 +6257,7 @@
},
{
"name": "/rules/files/:filename",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.rule_controller.get_file",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.rule_controller.get_file",
"description": "Get the content of a specified rule in the ruleset",
"summary": "Get rules file content",
"tags": [
@@ -6099,7 +6303,7 @@
},
{
"name": "/rules/groups",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.rule_controller.get_rules_groups",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.rule_controller.get_rules_groups",
"description": "Return a list containing all rule groups names",
"summary": "Get groups",
"tags": [
@@ -6163,7 +6367,7 @@
},
{
"name": "/rules/requirement/:requirement",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.rule_controller.get_rules_requirement",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.rule_controller.get_rules_requirement",
"description": "Return all specified requirement names defined in the Wazuh ruleset",
"summary": "Get requirements",
"tags": [
@@ -6245,7 +6449,7 @@
},
{
"name": "/sca/:agent_id",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.sca_controller.get_sca_agent",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.sca_controller.get_sca_agent",
"description": "Return the security SCA database of an agent",
"summary": "Get results",
"tags": [
@@ -6273,6 +6477,14 @@
"format": "alphanumeric_symbols"
}
},
+ {
+ "name": "distinct",
+ "description": "Look for distinct values.",
+ "schema": {
+ "type": "boolean",
+ "default": false
+ }
+ },
{
"name": "limit",
"description": "Maximum number of elements to return. Although up to 100.000 can be specified, it is recommended not to exceed 500 elements. Responses may be slower the more this number is exceeded. ",
@@ -6331,6 +6543,17 @@
"format": "search"
}
},
+ {
+ "name": "select",
+ "description": "Select which fields to return (separated by comma). Use '.' for nested fields. For example, '{field1: field2}' may be selected with 'field1.field2'",
+ "schema": {
+ "type": "array",
+ "items": {
+ "type": "string",
+ "format": "names"
+ }
+ }
+ },
{
"name": "sort",
"description": "Sort the collection by a field or fields (separated by comma). Use +/- at the beggining to list in ascending or descending order. Use '.' for nested fields. For example, '{field1: field2}' may be selected with 'field1.field2'",
@@ -6351,7 +6574,7 @@
},
{
"name": "/sca/:agent_id/checks/:policy_id",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.sca_controller.get_sca_checks",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.sca_controller.get_sca_checks",
"description": "Return the policy monitoring alerts for a given policy",
"summary": "Get policy checks",
"tags": [
@@ -6410,6 +6633,14 @@
"type": "string"
}
},
+ {
+ "name": "distinct",
+ "description": "Look for distinct values.",
+ "schema": {
+ "type": "boolean",
+ "default": false
+ }
+ },
{
"name": "file",
"description": "Filter by full path",
@@ -6518,19 +6749,22 @@
}
},
{
- "name": "sort",
- "description": "Sort the collection by a field or fields (separated by comma). Use +/- at the beggining to list in ascending or descending order. Use '.' for nested fields. For example, '{field1: field2}' may be selected with 'field1.field2'",
+ "name": "select",
+ "description": "Select which fields to return (separated by comma). Use '.' for nested fields. For example, '{field1: field2}' may be selected with 'field1.field2'",
"schema": {
- "type": "string",
- "format": "sort"
+ "type": "array",
+ "items": {
+ "type": "string",
+ "format": "names"
+ }
}
},
{
- "name": "status",
- "description": "Filter by status",
+ "name": "sort",
+ "description": "Sort the collection by a field or fields (separated by comma). Use +/- at the beggining to list in ascending or descending order. Use '.' for nested fields. For example, '{field1: field2}' may be selected with 'field1.field2'",
"schema": {
"type": "string",
- "format": "alphanumeric"
+ "format": "sort"
}
},
{
@@ -6553,7 +6787,7 @@
},
{
"name": "/security/actions",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.get_rbac_actions",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.get_rbac_actions",
"description": "Get all RBAC actions, including the potential related resources and endpoints.",
"summary": "List RBAC actions",
"tags": [
@@ -6579,7 +6813,7 @@
},
{
"name": "/security/config",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.get_security_config",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.get_security_config",
"description": "Return the security configuration in JSON format",
"summary": "Get security config",
"tags": [
@@ -6606,7 +6840,7 @@
},
{
"name": "/security/policies",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.get_policies",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.get_policies",
"description": "Get all policies in the system, including the administrator policy",
"summary": "List policies",
"tags": [
@@ -6693,7 +6927,7 @@
},
{
"name": "/security/resources",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.get_rbac_resources",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.get_rbac_resources",
"description": "This method should be called to get all current defined RBAC resources.",
"summary": "List RBAC resources",
"tags": [
@@ -6732,7 +6966,7 @@
},
{
"name": "/security/roles",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.get_roles",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.get_roles",
"description": "For a specific list, indicate the ids separated by commas. Example: ?role_ids=1,2,3",
"summary": "List roles",
"tags": [
@@ -6819,7 +7053,7 @@
},
{
"name": "/security/rules",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.get_rules",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.get_rules",
"description": "Get a list of security rules from the system or all of them. These rules must be mapped with roles to obtain certain access privileges. For a specific list, indicate the ids separated by commas. Example: ?rule_ids=1,2,3",
"summary": "List security rules",
"tags": [
@@ -6906,7 +7140,7 @@
},
{
"name": "/security/user/authenticate",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.login_user",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.deprecated_login_user",
"description": "This method should be called to get an API token. This token will expire after auth_token_exp_timeout seconds (default: 900). This value can be changed using PUT /security/config",
"summary": "Login",
"tags": [
@@ -6925,7 +7159,7 @@
},
{
"name": "/security/users",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.get_users",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.get_users",
"description": "Get the information of a specified user",
"summary": "List users",
"tags": [
@@ -7012,7 +7246,7 @@
},
{
"name": "/security/users/me",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.get_user_me",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.get_user_me",
"description": "Get the information of the current user",
"summary": "Get current user info",
"tags": [
@@ -7039,7 +7273,7 @@
},
{
"name": "/security/users/me/policies",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.get_user_me_policies",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.get_user_me_policies",
"description": "Get the processed policies information for the current user",
"summary": "Get current user processed policies",
"tags": [
@@ -7058,7 +7292,7 @@
},
{
"name": "/syscheck/:agent_id",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.syscheck_controller.get_syscheck_agent",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.syscheck_controller.get_syscheck_agent",
"description": "Return FIM findings in the specified agent",
"summary": "Get results",
"tags": [
@@ -7248,7 +7482,7 @@
},
{
"name": "/syscheck/:agent_id/last_scan",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.syscheck_controller.get_last_scan_agent",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.syscheck_controller.get_last_scan_agent",
"description": "Return when the last syscheck scan started and ended. If the scan is still in progress the end date will be unknown",
"summary": "Get last scan datetime",
"tags": [
@@ -7288,7 +7522,7 @@
},
{
"name": "/syscollector/:agent_id/hardware",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_hardware_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_hardware_info",
"description": "Return the agent's hardware info. This information include cpu, ram, scan info among others",
"summary": "Get agent hardware",
"tags": [
@@ -7339,7 +7573,7 @@
},
{
"name": "/syscollector/:agent_id/hotfixes",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_hotfix_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_hotfix_info",
"description": "Return all hotfixes installed by Microsoft(R) in Windows(R) systems (KB... fixes)",
"summary": "Get agent hotfixes",
"tags": [
@@ -7441,7 +7675,7 @@
},
{
"name": "/syscollector/:agent_id/netaddr",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_network_address_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_network_address_info",
"description": "Return the agent's network address info. This information include used IP protocol, interface, IP address among others",
"summary": "Get agent netaddr",
"tags": [
@@ -7576,7 +7810,7 @@
},
{
"name": "/syscollector/:agent_id/netiface",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_network_interface_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_network_interface_info",
"description": "Return the agent's network interface info. This information include rx, scan, tx info and some network information among others",
"summary": "Get agent netiface",
"tags": [
@@ -7783,7 +8017,7 @@
},
{
"name": "/syscollector/:agent_id/netproto",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_network_protocol_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_network_protocol_info",
"description": "Return the agent's routing configuration for each network interface",
"summary": "Get agent netproto",
"tags": [
@@ -7916,7 +8150,7 @@
},
{
"name": "/syscollector/:agent_id/os",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_os_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_os_info",
"description": "Return the agent's OS info. This information include os information, architecture information among others of all agents",
"summary": "Get agent OS",
"tags": [
@@ -7967,7 +8201,7 @@
},
{
"name": "/syscollector/:agent_id/packages",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_packages_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_packages_info",
"description": "Return the agent's packages info. This information include name, section, size, priority information of all packages among others",
"summary": "Get agent packages",
"tags": [
@@ -8100,7 +8334,7 @@
},
{
"name": "/syscollector/:agent_id/ports",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_ports_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_ports_info",
"description": "Return the agent's ports info. This information include local IP, Remote IP, protocol information among others",
"summary": "Get agent ports",
"tags": [
@@ -8259,7 +8493,7 @@
},
{
"name": "/syscollector/:agent_id/processes",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_processes_info",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.syscollector_controller.get_processes_info",
"description": "Return the agent's processes info",
"summary": "Get agent processes",
"tags": [
@@ -8466,7 +8700,7 @@
},
{
"name": "/tasks/status",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.task_controller.get_tasks_status",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.task_controller.get_tasks_status",
"description": "Returns all available information about the specified tasks",
"summary": "List tasks",
"tags": [
@@ -8605,7 +8839,7 @@
},
{
"name": "/vulnerability/:agent_id",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.vulnerability_controller.get_vulnerability_agent",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.vulnerability_controller.get_vulnerability_agent",
"description": "Return the vulnerabilities of an agent",
"summary": "Get vulnerabilities",
"tags": [
@@ -8771,7 +9005,7 @@
},
{
"name": "/vulnerability/:agent_id/last_scan",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.vulnerability_controller.get_last_scan_agent",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.vulnerability_controller.get_last_scan_agent",
"description": "Return when the last full and partial vulnerability scan of a specified agent ended.",
"summary": "Get last scan datetime",
"tags": [
@@ -8811,7 +9045,7 @@
},
{
"name": "/vulnerability/:agent_id/summary/:field",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.vulnerability_controller.get_vulnerabilities_field_summary",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.vulnerability_controller.get_vulnerabilities_field_summary",
"description": "Return a summary of the vulnerabilities' field of an agent",
"summary": "Get agent vulnerabilities' field summary",
"tags": [
@@ -8892,7 +9126,7 @@
"endpoints": [
{
"name": "/active-response",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.active_response_controller.run_command",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.active_response_controller.run_command",
"description": "Run an Active Response command on all agents or a list of them",
"summary": "Run command",
"tags": [
@@ -8942,7 +9176,8 @@
},
"command": {
"description": "Command running in the agent. If this value starts by `!`, then it refers to a script name instead of a command name",
- "type": "string"
+ "type": "string",
+ "format": "active_response_command"
},
"custom": {
"description": "Whether the specified command is a custom command or not",
@@ -8967,7 +9202,7 @@
},
{
"name": "/agents/:agent_id/group/:group_id",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.put_agent_single_group",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.put_agent_single_group",
"description": "Assign an agent to a specified group",
"summary": "Assign agent to group",
"tags": [
@@ -9024,7 +9259,7 @@
},
{
"name": "/agents/:agent_id/restart",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.restart_agent",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.restart_agent",
"description": "Restart the specified agent",
"summary": "Restart agent",
"tags": [
@@ -9064,7 +9299,7 @@
},
{
"name": "/agents/group",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.put_multiple_agent_single_group",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.put_multiple_agent_single_group",
"description": "Assign all agents or a list of them to the specified group",
"summary": "Assign agents to group",
"tags": [
@@ -9121,7 +9356,7 @@
},
{
"name": "/agents/group/:group_id/restart",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.restart_agents_by_group",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.restart_agents_by_group",
"description": "Restart all agents which belong to a given group",
"summary": "Restart agents in group",
"tags": [
@@ -9160,7 +9395,7 @@
},
{
"name": "/agents/node/:node_id/restart",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.restart_agents_by_node",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.restart_agents_by_node",
"description": "Restart all agents which belong to a specific given node",
"summary": "Restart agents in node",
"tags": [
@@ -9198,7 +9433,7 @@
},
{
"name": "/agents/reconnect",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.reconnect_agents",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.reconnect_agents",
"description": "Force reconnect all agents or a list of them",
"summary": "Force reconnect agents",
"tags": [
@@ -9238,7 +9473,7 @@
},
{
"name": "/agents/restart",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.restart_agents",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.restart_agents",
"description": "Restart all agents or a list of them",
"summary": "Restart agents",
"tags": [
@@ -9278,7 +9513,7 @@
},
{
"name": "/agents/upgrade",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.put_upgrade_agents",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.put_upgrade_agents",
"description": "Upgrade agents using a WPK file from online repository. When upgrading more than 3000 agents at the same time, it's highly recommended to use the parameter `wait_for_complete` set to `true` to avoid a possible API timeout",
"summary": "Upgrade agents",
"tags": [
@@ -9413,7 +9648,7 @@
},
{
"name": "version",
- "description": "Filter by agents version",
+ "description": "Filter by agents version using one of the following formats: 'X.Y.Z', 'vX.Y.Z', 'wazuh X.Y.Z' or 'wazuh vX.Y.Z'. For example: '4.4.0'",
"schema": {
"type": "string",
"format": "alphanumeric"
@@ -9439,7 +9674,7 @@
},
{
"name": "/agents/upgrade_custom",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.put_upgrade_custom_agents",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.put_upgrade_custom_agents",
"description": "Upgrade the agents using a local WPK file. When upgrading more than 3000 agents at the same time, it's highly recommended to use the parameter `wait_for_complete` set to `true` to avoid a possible API timeout",
"summary": "Upgrade agents custom",
"tags": [
@@ -9567,7 +9802,7 @@
},
{
"name": "version",
- "description": "Filter by agents version",
+ "description": "Filter by agents version using one of the following formats: 'X.Y.Z', 'vX.Y.Z', 'wazuh X.Y.Z' or 'wazuh vX.Y.Z'. For example: '4.4.0'",
"schema": {
"type": "string",
"format": "alphanumeric"
@@ -9585,7 +9820,7 @@
},
{
"name": "/cluster/:node_id/configuration",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.update_configuration",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.update_configuration",
"description": "Replace wazuh configuration for the given node with the data contained in the API request",
"summary": "Update node configuration",
"tags": [
@@ -9623,7 +9858,7 @@
},
{
"name": "/cluster/restart",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cluster_controller.put_restart",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cluster_controller.put_restart",
"description": "Restart all nodes in the cluster or a list of them",
"summary": "Restart nodes",
"tags": [
@@ -9660,7 +9895,7 @@
},
{
"name": "/decoders/files/:filename",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.decoder_controller.put_file",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.decoder_controller.put_file",
"description": "Upload or replace a user decoder file content",
"summary": "Update decoders file",
"tags": [
@@ -9706,7 +9941,7 @@
},
{
"name": "/groups/:group_id/configuration",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.put_group_config",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.put_group_config",
"description": "Update an specified group's configuration. This API call expects a full valid XML file with the shared configuration tags/syntax",
"summary": "Update group configuration",
"tags": [
@@ -9745,7 +9980,7 @@
},
{
"name": "/lists/files/:filename",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cdb_list_controller.put_file",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cdb_list_controller.put_file",
"description": "Replace or upload a CDB list file with the data contained in the API request",
"summary": "Update CDB list file",
"tags": [
@@ -9791,7 +10026,7 @@
},
{
"name": "/logtest",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.logtest_controller.run_logtest_tool",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.logtest_controller.run_logtest_tool",
"description": "Run logtest tool to check if a specified log raises any alert among other information",
"summary": "Run logtest",
"tags": [
@@ -9846,7 +10081,7 @@
},
{
"name": "/manager/configuration",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.update_configuration",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.update_configuration",
"description": "Replace Wazuh configuration with the data contained in the API request",
"summary": "Update Wazuh configuration",
"tags": [
@@ -9873,7 +10108,7 @@
},
{
"name": "/manager/restart",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.manager_controller.put_restart",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.manager_controller.put_restart",
"description": "Restart the wazuh manager",
"summary": "Restart manager",
"tags": [
@@ -9900,7 +10135,7 @@
},
{
"name": "/rootcheck",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.rootcheck_controller.put_rootcheck",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.rootcheck_controller.put_rootcheck",
"description": "Run rootcheck scan in all agents or a list of them",
"summary": "Run scan",
"tags": [
@@ -9940,7 +10175,7 @@
},
{
"name": "/rules/files/:filename",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.rule_controller.put_file",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.rule_controller.put_file",
"description": "Upload or replace a user ruleset file content",
"summary": "Update rules file",
"tags": [
@@ -9986,7 +10221,7 @@
},
{
"name": "/security/config",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.put_security_config",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.put_security_config",
"description": "Update the security configuration with the data contained in the API request",
"summary": "Update security config",
"tags": [
@@ -10037,7 +10272,7 @@
},
{
"name": "/security/policies/:policy_id",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.update_policy",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.update_policy",
"description": "Modify a policy, at least one property must be indicated",
"summary": "Update policy",
"tags": [
@@ -10118,7 +10353,7 @@
},
{
"name": "/security/roles/:role_id",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.update_role",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.update_role",
"description": "Modify a role, cannot modify associated policies in this endpoint, at least one property must be indicated",
"summary": "Update role",
"tags": [
@@ -10170,7 +10405,7 @@
},
{
"name": "/security/rules/:rule_id",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.update_rule",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.update_rule",
"description": "Modify a security rule by specifying its ID",
"summary": "Update security rule",
"tags": [
@@ -10226,7 +10461,7 @@
},
{
"name": "/security/user/revoke",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.revoke_all_tokens",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.revoke_all_tokens",
"description": "This method should be called to revoke all active JWT tokens",
"summary": "Revoke JWT tokens",
"tags": [
@@ -10235,7 +10470,7 @@
},
{
"name": "/security/users/:user_id",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.update_user",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.update_user",
"description": "Modify a user's password by specifying their ID",
"summary": "Update users",
"tags": [
@@ -10281,7 +10516,7 @@
},
{
"name": "/security/users/:user_id/run_as",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.edit_run_as",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.edit_run_as",
"description": "Modify a user's allow_run_as flag by specifying their ID",
"summary": "Enable/Disable run_as",
"tags": [
@@ -10328,7 +10563,7 @@
},
{
"name": "/syscheck",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.syscheck_controller.put_syscheck",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.syscheck_controller.put_syscheck",
"description": "Run FIM scan in all agents",
"summary": "Run scan",
"tags": [
@@ -10365,6 +10600,33 @@
}
}
]
+ },
+ {
+ "name": "/vulnerability",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.vulnerability_controller.run_vulnerability_scan",
+ "description": "Run a vulnerability detector scan in all nodes",
+ "summary": "Run vulnerability detector scan",
+ "tags": [
+ "Vulnerability"
+ ],
+ "query": [
+ {
+ "name": "pretty",
+ "description": "Show results in human-readable format",
+ "schema": {
+ "type": "boolean",
+ "default": false
+ }
+ },
+ {
+ "name": "wait_for_complete",
+ "description": "Disable timeout response",
+ "schema": {
+ "type": "boolean",
+ "default": false
+ }
+ }
+ ]
}
]
},
@@ -10373,7 +10635,7 @@
"endpoints": [
{
"name": "/agents",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.add_agent",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.add_agent",
"description": "Add a new agent",
"summary": "Add agent",
"tags": [
@@ -10414,7 +10676,7 @@
},
{
"name": "/agents/insert",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.insert_agent",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.insert_agent",
"description": "Add an agent specifying its name, ID and IP. If an agent with the same name, the same ID or the same IP already exists, replace it using the `force` parameter",
"summary": "Add agent full",
"tags": [
@@ -10504,7 +10766,7 @@
},
{
"name": "/agents/insert/quick",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.post_new_agent",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.post_new_agent",
"description": "Add a new agent with name `agent_name`. This agent will use `any` as IP",
"summary": "Add agent quick",
"tags": [
@@ -10541,7 +10803,7 @@
},
{
"name": "/groups",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.post_group",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.post_group",
"description": "Create a new group",
"summary": "Create a group",
"tags": [
@@ -10568,15 +10830,16 @@
"body": [
{
"name": "group_id",
- "description": "Group name",
+ "description": "Group name. It can contain any of the characters between a-z, A-Z, 0-9, '_', '-' and '.'. Names '.' and '..' are restricted.",
"type": "string",
- "format": "group_names"
+ "format": "group_names",
+ "maxLength": 128
}
]
},
{
"name": "/security/policies",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.add_policy",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.add_policy",
"description": "Add a new policy, all fields need to be specified",
"summary": "Add policy",
"tags": [
@@ -10649,7 +10912,7 @@
},
{
"name": "/security/roles",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.add_role",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.add_role",
"description": "Add a new role, all fields need to be specified",
"summary": "Add role",
"tags": [
@@ -10692,7 +10955,7 @@
},
{
"name": "/security/roles/:role_id/policies",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.set_role_policy",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.set_role_policy",
"description": "Create a specified relation role-policy, one role may have multiples policies",
"summary": "Add policies to role",
"tags": [
@@ -10753,7 +11016,7 @@
},
{
"name": "/security/roles/:role_id/rules",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.set_role_rule",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.set_role_rule",
"description": "Create a specific role-rule relation. One role may have multiple security rules",
"summary": "Add security rules to role",
"tags": [
@@ -10805,7 +11068,7 @@
},
{
"name": "/security/rules",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.add_rule",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.add_rule",
"description": "Add a new security rule",
"summary": "Add security rule",
"tags": [
@@ -10851,9 +11114,28 @@
}
]
},
+ {
+ "name": "/security/user/authenticate",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.login_user",
+ "description": "This method should be called to get an API token. This token will expire after auth_token_exp_timeout seconds (default: 900). This value can be changed using PUT /security/config",
+ "summary": "Login",
+ "tags": [
+ "Security"
+ ],
+ "query": [
+ {
+ "name": "raw",
+ "description": "Format response in plain text",
+ "required": false,
+ "schema": {
+ "type": "boolean"
+ }
+ }
+ ]
+ },
{
"name": "/security/user/authenticate/run_as",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.run_as_login",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.run_as_login",
"description": "This method should be called to get an API token using an authorization context body. This token will expire after auth_token_exp_timeout seconds (default: 900). This value can be changed using PUT /security/config",
"summary": "Login auth_context",
"tags": [
@@ -10878,7 +11160,7 @@
},
{
"name": "/security/users",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.create_user",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.create_user",
"description": "Add a new API user to the system",
"summary": "Add user",
"tags": [
@@ -10919,7 +11201,7 @@
},
{
"name": "/security/users/:user_id/roles",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.set_user_role",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.set_user_role",
"description": "Create a specified relation role-policy, one user may have multiples roles",
"summary": "Add roles to user",
"tags": [
@@ -10985,7 +11267,7 @@
"endpoints": [
{
"name": "/agents",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.delete_agents",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.delete_agents",
"description": "Delete all agents or a list of them based on optional criteria",
"summary": "Delete agents",
"tags": [
@@ -11132,7 +11414,7 @@
},
{
"name": "version",
- "description": "Filter by agents version",
+ "description": "Filter by agents version using one of the following formats: 'X.Y.Z', 'vX.Y.Z', 'wazuh X.Y.Z' or 'wazuh vX.Y.Z'. For example: '4.4.0'",
"schema": {
"type": "string",
"format": "alphanumeric"
@@ -11150,7 +11432,7 @@
},
{
"name": "/agents/:agent_id/group",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.delete_single_agent_multiple_groups",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.delete_single_agent_multiple_groups",
"description": "Remove the agent from all groups or a list of them. The agent will automatically revert to the default group if it is removed from all its assigned groups",
"summary": "Remove agent from groups",
"tags": [
@@ -11202,7 +11484,7 @@
},
{
"name": "/agents/:agent_id/group/:group_id",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.delete_single_agent_single_group",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.delete_single_agent_single_group",
"description": "Remove an agent from a specified group. If the agent belongs to several groups, only the specified group will be deleted.",
"summary": "Remove agent from group",
"tags": [
@@ -11252,7 +11534,7 @@
},
{
"name": "/agents/group",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.delete_multiple_agent_single_group",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.delete_multiple_agent_single_group",
"description": "Remove all agents assignment or a list of them from the specified group",
"summary": "Remove agents from group",
"tags": [
@@ -11303,7 +11585,7 @@
},
{
"name": "/decoders/files/:filename",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.decoder_controller.delete_file",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.decoder_controller.delete_file",
"description": "Delete a specified decoder file",
"summary": "Delete decoders file",
"tags": [
@@ -11341,7 +11623,7 @@
},
{
"name": "/experimental/rootcheck",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.experimental_controller.clear_rootcheck_database",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.experimental_controller.clear_rootcheck_database",
"description": "Clear rootcheck database for all agents or a list of them",
"summary": "Clear rootcheck results",
"tags": [
@@ -11382,7 +11664,7 @@
},
{
"name": "/experimental/syscheck",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.experimental_controller.clear_syscheck_database",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.experimental_controller.clear_syscheck_database",
"description": "Clear the syscheck database for all agents or a list of them",
"summary": "Clear agents FIM results",
"tags": [
@@ -11423,7 +11705,7 @@
},
{
"name": "/groups",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.agent_controller.delete_groups",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.agent_controller.delete_groups",
"description": "Delete all groups or a list of them",
"summary": "Delete groups",
"tags": [
@@ -11464,7 +11746,7 @@
},
{
"name": "/lists/files/:filename",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.cdb_list_controller.delete_file",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.cdb_list_controller.delete_file",
"description": "Delete a specified CDB list file. Only the filename can be specified. It will be searched recursively if not found",
"summary": "Delete CDB list file",
"tags": [
@@ -11502,7 +11784,7 @@
},
{
"name": "/logtest/sessions/:token",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.logtest_controller.end_logtest_session",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.logtest_controller.end_logtest_session",
"description": "Delete the saved logtest session corresponding to {token}",
"summary": "End session",
"tags": [
@@ -11540,7 +11822,7 @@
},
{
"name": "/rootcheck/:agent_id",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.rootcheck_controller.delete_rootcheck",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.rootcheck_controller.delete_rootcheck",
"description": "Clear an agent's rootcheck database",
"summary": "Clear results",
"tags": [
@@ -11580,7 +11862,7 @@
},
{
"name": "/rules/files/:filename",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.rule_controller.delete_file",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.rule_controller.delete_file",
"description": "Delete a specified rule file",
"summary": "Delete rules file",
"tags": [
@@ -11618,7 +11900,7 @@
},
{
"name": "/security/config",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.delete_security_config",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.delete_security_config",
"description": "Replaces the security configuration with the original one",
"summary": "Restore default security config",
"tags": [
@@ -11645,7 +11927,7 @@
},
{
"name": "/security/policies",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.remove_policies",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.remove_policies",
"description": "Delete a list of policies or all policies in the system, roles linked to policies are not going to be removed",
"summary": "Delete policies",
"tags": [
@@ -11685,7 +11967,7 @@
},
{
"name": "/security/roles",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.remove_roles",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.remove_roles",
"description": "Policies linked to roles are not going to be removed",
"summary": "Delete roles",
"tags": [
@@ -11725,7 +12007,7 @@
},
{
"name": "/security/roles/:role_id/policies",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.remove_role_policy",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.remove_role_policy",
"description": "Delete a specified relation role-policy",
"summary": "Remove policies from role",
"tags": [
@@ -11777,7 +12059,7 @@
},
{
"name": "/security/roles/:role_id/rules",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.remove_role_rule",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.remove_role_rule",
"description": "Delete a specific role-rule relation",
"summary": "Remove security rules from role",
"tags": [
@@ -11829,7 +12111,7 @@
},
{
"name": "/security/rules",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.remove_rules",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.remove_rules",
"description": "Delete a list of security rules or all security rules in the system, roles linked to rules are not going to be deleted",
"summary": "Delete security rules",
"tags": [
@@ -11869,7 +12151,7 @@
},
{
"name": "/security/user/authenticate",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.logout_user",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.logout_user",
"description": "This method should be called to invalidate all the current user's tokens",
"summary": "Logout current user",
"tags": [
@@ -11878,7 +12160,7 @@
},
{
"name": "/security/users",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.delete_users",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.delete_users",
"description": "Delete a list of users by specifying their IDs",
"summary": "Delete users",
"tags": [
@@ -11918,7 +12200,7 @@
},
{
"name": "/security/users/:user_id/roles",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.security_controller.remove_user_role",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.security_controller.remove_user_role",
"description": "Delete a specified relation user-roles",
"summary": "Remove roles from user",
"tags": [
@@ -11970,7 +12252,7 @@
},
{
"name": "/syscheck/:agent_id",
- "documentation": "https://documentation.wazuh.com/4.3/user-manual/api/reference.html#operation/api.controllers.syscheck_controller.delete_syscheck_agent",
+ "documentation": "https://documentation.wazuh.com/4.4/user-manual/api/reference.html#operation/api.controllers.syscheck_controller.delete_syscheck_agent",
"description": "Clear file integrity monitoring scan results for a specified agent. Only available for agents < 3.12.0, it doesn't apply for more recent ones",
"summary": "Clear results",
"tags": [
diff --git a/common/api-info/security-actions.json b/common/api-info/security-actions.json
index d0c1fb0d66..035696e9ce 100644
--- a/common/api-info/security-actions.json
+++ b/common/api-info/security-actions.json
@@ -59,6 +59,7 @@
"GET /agents/{agent_id}/config/{component}/{configuration}",
"GET /agents/{agent_id}/group/is_sync",
"GET /agents/{agent_id}/key",
+ "GET /agents/{agent_id}/daemons/stats",
"GET /agents/{agent_id}/stats/{component}",
"GET /groups/{group_id}/agents",
"GET /agents/no_group",
@@ -280,10 +281,12 @@
"GET /cluster/local/info",
"GET /cluster/nodes",
"GET /cluster/healthcheck",
+ "GET /cluster/ruleset/synchronization",
"GET /cluster/local/config",
"GET /cluster/{node_id}/status",
"GET /cluster/{node_id}/info",
"GET /cluster/{node_id}/configuration",
+ "GET /cluster/{node_id}/daemons/stats",
"GET /cluster/{node_id}/stats",
"GET /cluster/{node_id}/stats/hourly",
"GET /cluster/{node_id}/stats/weekly",
@@ -505,6 +508,7 @@
"GET /manager/status",
"GET /manager/info",
"GET /manager/configuration",
+ "GET /manager/daemons/stats",
"GET /manager/stats",
"GET /manager/stats/hourly",
"GET /manager/stats/weekly",
@@ -1085,6 +1089,24 @@
"GET /tasks/status"
]
},
+ "vulnerability:run": {
+ "description": "Allow running a vulnerability detector scan",
+ "resources": [
+ "*:*"
+ ],
+ "example": {
+ "actions": [
+ "vulnerability:run"
+ ],
+ "resources": [
+ "*:*:*"
+ ],
+ "effect": "allow"
+ },
+ "related_endpoints": [
+ "PUT /vulnerability"
+ ]
+ },
"vulnerability:read": {
"description": "Allow reading agents' vulnerabilities information",
"resources": [
diff --git a/common/compliance-requirements/pci-requirements.ts b/common/compliance-requirements/pci-requirements.ts
index a1c9a7276a..49e8a2f090 100644
--- a/common/compliance-requirements/pci-requirements.ts
+++ b/common/compliance-requirements/pci-requirements.ts
@@ -34,7 +34,7 @@ export const pciRequirementsFile = {
'6.5':
'Address common coding vulnerabilities in software development processes as follows:Train developers in secure coding techniques, including how to avoid common coding vulnerabilities, and understanding how sensitive data is handled in memory. Develop applications based on secure coding guidelines. ',
'6.5.1':
- 'Injection flaws, particularly SQL injection. Also consider OS Command Injection, LDAP and XPath injection flaws as well as other injection flaws.',
+ 'Injection flaws, particularly SQL injection. Also consider Operating System Command Injection, LDAP and XPath injection flaws as well as other injection flaws.',
'6.5.2': 'Buffer overflows',
'6.5.5': 'Improper error handling',
'6.5.7': 'Cross-site scripting (XSS)',
diff --git a/common/config-equivalences.js b/common/config-equivalences.js
index 0441e3f8b1..f2254802fd 100644
--- a/common/config-equivalences.js
+++ b/common/config-equivalences.js
@@ -97,7 +97,6 @@ export const nameEquivalence = {
timeout: 'Request timeout',
'ip.selector': 'IP selector',
'ip.ignore': 'IP ignore',
- 'xpack.rbac.enabled': 'X-Pack RBAC',
'wazuh.monitoring.enabled': 'Status',
'wazuh.monitoring.frequency': 'Frequency',
'wazuh.monitoring.shards': 'Index shards',
@@ -187,7 +186,6 @@ export const formEquivalence = {
timeout: { type: NUMBER },
'ip.selector': { type: BOOLEAN },
'ip.ignore': { type: ARRAY },
- 'xpack.rbac.enabled': { type: BOOLEAN },
'wazuh.monitoring.enabled': { type: BOOLEAN },
'wazuh.monitoring.frequency': { type: NUMBER },
'wazuh.monitoring.shards': { type: NUMBER },
diff --git a/common/constants.ts b/common/constants.ts
index 09d7b60ba9..6832a172be 100644
--- a/common/constants.ts
+++ b/common/constants.ts
@@ -11,10 +11,12 @@
*/
import path from 'path';
import { version } from '../package.json';
+import { validate as validateNodeCronInterval } from 'node-cron';
+import { SettingsValidator } from '../common/services/settings-validator';
// Plugin
export const PLUGIN_VERSION = version;
-export const PLUGIN_VERSION_SHORT = version.split('.').splice(0,2).join('.');
+export const PLUGIN_VERSION_SHORT = version.split('.').splice(0, 2).join('.');
// Index patterns - Wazuh alerts
export const WAZUH_INDEX_TYPE_ALERTS = 'alerts';
@@ -90,38 +92,14 @@ export const WAZUH_SAMPLE_ALERTS_CATEGORIES_TYPE_ALERTS = {
};
// Security
-export const WAZUH_SECURITY_PLUGIN_XPACK_SECURITY = 'X-Pack Security';
-export const WAZUH_SECURITY_PLUGIN_OPEN_DISTRO_FOR_ELASTICSEARCH = 'Open Distro for Elasticsearch';
+export const WAZUH_SECURITY_PLUGIN_OPENSEARCH_DASHBOARDS_SECURITY = 'OpenSearch Dashboards Security';
export const WAZUH_SECURITY_PLUGINS = [
- WAZUH_SECURITY_PLUGIN_XPACK_SECURITY,
- WAZUH_SECURITY_PLUGIN_OPEN_DISTRO_FOR_ELASTICSEARCH,
+ WAZUH_SECURITY_PLUGIN_OPENSEARCH_DASHBOARDS_SECURITY,
];
// App configuration
export const WAZUH_CONFIGURATION_CACHE_TIME = 10000; // time in ms;
-export const WAZUH_CONFIGURATION_SETTINGS_NEED_RESTART = [
- 'wazuh.monitoring.enabled',
- 'wazuh.monitoring.frequency',
- 'cron.statistics.interval',
- 'logs.level',
-];
-export const WAZUH_CONFIGURATION_SETTINGS_NEED_HEALTH_CHECK = [
- 'pattern',
- 'wazuh.monitoring.replicas',
- 'wazuh.monitoring.creation',
- 'wazuh.monitoring.pattern',
- 'alerts.sample.prefix',
- 'cron.statistics.index.name',
- 'cron.statistics.index.creation',
- 'cron.statistics.index.shards',
- 'cron.statistics.index.replicas',
- 'wazuh.monitoring.shards',
-];
-export const WAZUH_CONFIGURATION_SETTINGS_NEED_RELOAD = [
- 'hideManagerAlerts',
- 'customization.logo.sidebar'
-];
// Reserved ids for Users/Role mapping
export const WAZUH_API_RESERVED_ID_LOWER_THAN = 100;
@@ -176,61 +154,6 @@ export const WAZUH_DATA_DOWNLOADS_REPORTS_DIRECTORY_PATH = path.join(
// Queue
export const WAZUH_QUEUE_CRON_FREQ = '*/15 * * * * *'; // Every 15 seconds
-// Default App Config
-export const WAZUH_DEFAULT_APP_CONFIG = {
- pattern: WAZUH_ALERTS_PATTERN,
- 'checks.pattern': true,
- 'checks.template': true,
- 'checks.api': true,
- 'checks.setup': true,
- 'checks.fields': true,
- 'checks.metaFields': true,
- 'checks.maxBuckets': true,
- 'checks.timeFilter': true,
- 'extensions.pci': true,
- 'extensions.gdpr': true,
- 'extensions.hipaa': true,
- 'extensions.nist': true,
- 'extensions.tsc': true,
- 'extensions.audit': true,
- 'extensions.oscap': false,
- 'extensions.ciscat': false,
- 'extensions.aws': false,
- 'extensions.office': false,
- 'extensions.github': false,
- 'extensions.gcp': false,
- 'extensions.virustotal': false,
- 'extensions.osquery': false,
- 'extensions.docker': false,
- timeout: 20000,
- 'ip.selector': true,
- 'ip.ignore': [],
- 'xpack.rbac.enabled': true,
- 'wazuh.monitoring.enabled': WAZUH_MONITORING_DEFAULT_ENABLED,
- 'wazuh.monitoring.frequency': WAZUH_MONITORING_DEFAULT_FREQUENCY,
- 'wazuh.monitoring.shards': WAZUH_MONITORING_DEFAULT_INDICES_SHARDS,
- 'wazuh.monitoring.replicas': WAZUH_MONITORING_DEFAULT_INDICES_REPLICAS,
- 'wazuh.monitoring.creation': WAZUH_MONITORING_DEFAULT_CREATION,
- 'wazuh.monitoring.pattern': WAZUH_MONITORING_PATTERN,
- 'cron.prefix': WAZUH_STATISTICS_DEFAULT_PREFIX,
- 'cron.statistics.status': WAZUH_STATISTICS_DEFAULT_STATUS,
- 'cron.statistics.apis': [],
- 'cron.statistics.interval': WAZUH_STATISTICS_DEFAULT_CRON_FREQ,
- 'cron.statistics.index.name': WAZUH_STATISTICS_DEFAULT_NAME,
- 'cron.statistics.index.creation': WAZUH_STATISTICS_DEFAULT_CREATION,
- 'cron.statistics.index.shards': WAZUH_STATISTICS_DEFAULT_INDICES_SHARDS,
- 'cron.statistics.index.replicas': WAZUH_STATISTICS_DEFAULT_INDICES_REPLICAS,
- 'alerts.sample.prefix': WAZUH_SAMPLE_ALERT_PREFIX,
- hideManagerAlerts: false,
- 'logs.level': 'info',
- 'enrollment.dns': '',
- 'enrollment.password': '',
- 'customization.logo.app': '',
- 'customization.logo.sidebar': '',
- 'customization.logo.healthcheck':'',
- 'customization.logo.reports': ''
-};
-
// Wazuh errors
export const WAZUH_ERROR_DAEMONS_NOT_READY = 'ERROR3099';
@@ -329,7 +252,7 @@ export const PLUGIN_PLATFORM_SETTING_NAME_TIME_FILTER = 'timepicker:timeDefaults
// Default maxBuckets set by the app
export const WAZUH_PLUGIN_PLATFORM_SETTING_MAX_BUCKETS = 200000;
-export const PLUGIN_PLATFORM_SETTING_NAME_MAX_BUCKETS = 'timelion:max_buckets';
+export const PLUGIN_PLATFORM_SETTING_NAME_MAX_BUCKETS = 'timeline:max_buckets';
// Default metaFields set by the app
export const WAZUH_PLUGIN_PLATFORM_SETTING_METAFIELDS = ['_source', '_index'];
@@ -359,19 +282,23 @@ export const REPORTS_PAGE_FOOTER_TEXT = 'Copyright © 2022 Wazuh, Inc.';
export const REPORTS_PAGE_HEADER_TEXT = 'info@wazuh.com\nhttps://wazuh.com';
// Plugin platform
-export const PLUGIN_PLATFORM_NAME = 'Kibana';
-export const PLUGIN_PLATFORM_BASE_INSTALLATION_PATH = '/usr/share/kibana/data/wazuh/';
-export const PLUGIN_PLATFORM_INSTALLATION_USER = 'kibana';
-export const PLUGIN_PLATFORM_INSTALLATION_USER_GROUP = 'kibana';
+export const PLUGIN_PLATFORM_NAME = 'Wazuh dashboard';
+export const PLUGIN_PLATFORM_BASE_INSTALLATION_PATH = '/usr/share/wazuh-dashboard/data/wazuh/';
+export const PLUGIN_PLATFORM_INSTALLATION_USER = 'wazuh-dashboard';
+export const PLUGIN_PLATFORM_INSTALLATION_USER_GROUP = 'wazuh-dashboard';
export const PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_UPGRADE_PLATFORM = 'upgrade-guide';
-export const PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING = 'user-manual/elasticsearch/troubleshooting.html';
+export const PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING = 'user-manual/wazuh-dashboard/troubleshooting.html';
export const PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_APP_CONFIGURATION = 'user-manual/wazuh-dashboard/config-file.html';
-export const PLUGIN_PLATFORM_URL_GUIDE = 'https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html';
-export const PLUGIN_PLATFORM_URL_GUIDE_TITLE = 'Elastic guide';
+export const PLUGIN_PLATFORM_URL_GUIDE = 'https://opensearch.org/docs/1.2/opensearch/index/';
+export const PLUGIN_PLATFORM_URL_GUIDE_TITLE = 'OpenSearch guide';
+
export const PLUGIN_PLATFORM_REQUEST_HEADERS = {
- 'kbn-xsrf': 'kibana'
+ 'osd-xsrf': 'kibana'
};
+// Plugin app
+export const PLUGIN_APP_NAME = 'Wazuh dashboard';
+
// UI
export const API_NAME_AGENT_STATUS = {
ACTIVE: 'active',
@@ -400,11 +327,1602 @@ export const UI_ORDER_AGENT_STATUS = [
API_NAME_AGENT_STATUS.ACTIVE,
API_NAME_AGENT_STATUS.DISCONNECTED,
API_NAME_AGENT_STATUS.PENDING,
- API_NAME_AGENT_STATUS.NEVER_CONNECTED
-];
+ API_NAME_AGENT_STATUS.NEVER_CONNECTED
+]
+
+export const AGENT_SYNCED_STATUS = {
+ SYNCED: 'synced',
+ NOT_SYNCED: 'not synced',
+}
// Documentation
export const DOCUMENTATION_WEB_BASE_URL = "https://documentation.wazuh.com";
// Default Elasticsearch user name context
export const ELASTIC_NAME = 'elastic';
+
+// Default Wazuh indexer name
+export const WAZUH_INDEXER_NAME = 'Wazuh indexer';
+
+// Customization
+export const CUSTOMIZATION_ENDPOINT_PAYLOAD_UPLOAD_CUSTOM_FILE_MAXIMUM_BYTES = 1048576;
+
+// Plugin settings
+export enum SettingCategory {
+ GENERAL,
+ HEALTH_CHECK,
+ EXTENSIONS,
+ MONITORING,
+ STATISTICS,
+ SECURITY,
+ CUSTOMIZATION,
+};
+
+type TPluginSettingOptionsTextArea = {
+ maxRows?: number
+ minRows?: number
+ maxLength?: number
+};
+
+type TPluginSettingOptionsSelect = {
+ select: { text: string, value: any }[]
+};
+
+type TPluginSettingOptionsEditor = {
+ editor: {
+ language: string
+ }
+};
+
+type TPluginSettingOptionsFile = {
+ file: {
+ type: 'image'
+ extensions?: string[]
+ size?: {
+ maxBytes?: number
+ minBytes?: number
+ }
+ recommended?: {
+ dimensions?: {
+ width: number,
+ height: number,
+ unit: string
+ }
+ }
+ store?: {
+ relativePathFileSystem: string
+ filename: string
+ resolveStaticURL: (filename: string) => string
+ }
+ }
+};
+
+type TPluginSettingOptionsNumber = {
+ number: {
+ min?: number
+ max?: number
+ integer?: boolean
+ }
+};
+
+type TPluginSettingOptionsSwitch = {
+ switch: {
+ values: {
+ disabled: { label?: string, value: any },
+ enabled: { label?: string, value: any },
+ }
+ }
+};
+
+export enum EpluginSettingType {
+ text = 'text',
+ textarea = 'textarea',
+ switch = 'switch',
+ number = 'number',
+ editor = 'editor',
+ select = 'select',
+ filepicker = 'filepicker'
+};
+
+export type TPluginSetting = {
+ // Define the text displayed in the UI.
+ title: string
+ // Description.
+ description: string
+ // Category.
+ category: SettingCategory
+ // Type.
+ type: EpluginSettingType
+ // Default value.
+ defaultValue: any
+ // Default value if it is not set. It has preference over `default`.
+ defaultValueIfNotSet?: any
+ // Configurable from the configuration file.
+ isConfigurableFromFile: boolean
+ // Configurable from the UI (Settings/Configuration).
+ isConfigurableFromUI: boolean
+ // Modify the setting requires running the plugin health check (frontend).
+ requiresRunningHealthCheck?: boolean
+ // Modify the setting requires reloading the browser tab (frontend).
+ requiresReloadingBrowserTab?: boolean
+ // Modify the setting requires restarting the plugin platform to take effect.
+ requiresRestartingPluginPlatform?: boolean
+ // Define options related to the `type`.
+ options?:
+ TPluginSettingOptionsEditor |
+ TPluginSettingOptionsFile |
+ TPluginSettingOptionsNumber |
+ TPluginSettingOptionsSelect |
+ TPluginSettingOptionsSwitch |
+ TPluginSettingOptionsTextArea
+ // Transform the input value. The result is saved in the form global state of Settings/Configuration
+ uiFormTransformChangedInputValue?: (value: any) => any
+ // Transform the configuration value or default as initial value for the input in Settings/Configuration
+ uiFormTransformConfigurationValueToInputValue?: (value: any) => any
+ // Transform the input value changed in the form of Settings/Configuration and returned in the `changed` property of the hook useForm
+ uiFormTransformInputValueToConfigurationValue?: (value: any) => any
+ // Validate the value in the form of Settings/Configuration. It returns a string if there is some validation error.
+ validate?: (value: any) => string | undefined
+ // Validate function creator to validate the setting in the backend. It uses `schema` of the `@kbn/config-schema` package.
+ validateBackend?: (schema: any) => (value: unknown) => string | undefined
+};
+
+export type TPluginSettingWithKey = TPluginSetting & { key: TPluginSettingKey };
+export type TPluginSettingCategory = {
+ title: string
+ description?: string
+ documentationLink?: string
+ renderOrder?: number
+};
+
+export const PLUGIN_SETTINGS_CATEGORIES: { [category: number]: TPluginSettingCategory } = {
+ [SettingCategory.HEALTH_CHECK]: {
+ title: 'Health check',
+ description: "Checks will be executed by the app's Healthcheck.",
+ renderOrder: SettingCategory.HEALTH_CHECK,
+ },
+ [SettingCategory.GENERAL]: {
+ title: 'General',
+ description: "Basic app settings related to alerts index pattern, hide the manager alerts in the dashboards, logs level and more.",
+ renderOrder: SettingCategory.GENERAL,
+ },
+ [SettingCategory.EXTENSIONS]: {
+ title: 'Initial display state of the modules of the new API host entries.',
+ description: "Extensions.",
+ },
+ [SettingCategory.SECURITY]: {
+ title: 'Security',
+ description: "Application security options such as unauthorized roles.",
+ renderOrder: SettingCategory.SECURITY,
+ },
+ [SettingCategory.MONITORING]: {
+ title: 'Task:Monitoring',
+ description: "Options related to the agent status monitoring job and its storage in indexes.",
+ renderOrder: SettingCategory.MONITORING,
+ },
+ [SettingCategory.STATISTICS]: {
+ title: 'Task:Statistics',
+ description: "Options related to the daemons manager monitoring job and their storage in indexes..",
+ renderOrder: SettingCategory.STATISTICS,
+ },
+ [SettingCategory.CUSTOMIZATION]: {
+ title: 'Custom branding',
+ description: "If you want to use custom branding elements such as logos, you can do so by editing the settings below.",
+ documentationLink: 'user-manual/wazuh-dashboard/white-labeling.html',
+ renderOrder: SettingCategory.CUSTOMIZATION,
+ }
+};
+
+export const PLUGIN_SETTINGS: { [key: string]: TPluginSetting } = {
+ "alerts.sample.prefix": {
+ title: "Sample alerts prefix",
+ description: "Define the index name prefix of sample alerts. It must match the template used by the index pattern to avoid unknown fields in dashboards.",
+ category: SettingCategory.GENERAL,
+ type: EpluginSettingType.text,
+ defaultValue: WAZUH_SAMPLE_ALERT_PREFIX,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresRunningHealthCheck: true,
+ // Validation: https://github.com/elastic/elasticsearch/blob/v7.10.2/docs/reference/indices/create-index.asciidoc
+ validate: SettingsValidator.compose(
+ SettingsValidator.isNotEmptyString,
+ SettingsValidator.hasNoSpaces,
+ SettingsValidator.noStartsWithString('-', '_', '+', '.'),
+ SettingsValidator.hasNotInvalidCharacters('\\', '/', '?', '"', '<', '>', '|', ',', '#', '*')
+ ),
+ validateBackend: function(schema){
+ return schema.string({validate: this.validate});
+ },
+ },
+ "checks.api": {
+ title: "API connection",
+ description: "Enable or disable the API health check when opening the app.",
+ category: SettingCategory.HEALTH_CHECK,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "checks.fields": {
+ title: "Known fields",
+ description: "Enable or disable the known fields health check when opening the app.",
+ category: SettingCategory.HEALTH_CHECK,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "checks.maxBuckets": {
+ title: "Set max buckets to 200000",
+ description: "Change the default value of the plugin platform max buckets configuration.",
+ category: SettingCategory.HEALTH_CHECK,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ },
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "checks.metaFields": {
+ title: "Remove meta fields",
+ description: "Change the default value of the plugin platform metaField configuration.",
+ category: SettingCategory.HEALTH_CHECK,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "checks.pattern": {
+ title: "Index pattern",
+ description: "Enable or disable the index pattern health check when opening the app.",
+ category: SettingCategory.HEALTH_CHECK,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "checks.setup": {
+ title: "API version",
+ description: "Enable or disable the setup health check when opening the app.",
+ category: SettingCategory.HEALTH_CHECK,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "checks.template": {
+ title: "Index template",
+ description: "Enable or disable the template health check when opening the app.",
+ category: SettingCategory.HEALTH_CHECK,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "checks.timeFilter": {
+ title: "Set time filter to 24h",
+ description: "Change the default value of the plugin platform timeFilter configuration.",
+ category: SettingCategory.HEALTH_CHECK,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "cron.prefix": {
+ title: "Cron prefix",
+ description: "Define the index prefix of predefined jobs.",
+ category: SettingCategory.GENERAL,
+ type: EpluginSettingType.text,
+ defaultValue: WAZUH_STATISTICS_DEFAULT_PREFIX,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ // Validation: https://github.com/elastic/elasticsearch/blob/v7.10.2/docs/reference/indices/create-index.asciidoc
+ validate: SettingsValidator.compose(
+ SettingsValidator.isNotEmptyString,
+ SettingsValidator.hasNoSpaces,
+ SettingsValidator.noStartsWithString('-', '_', '+', '.'),
+ SettingsValidator.hasNotInvalidCharacters('\\', '/', '?', '"', '<', '>', '|', ',', '#', '*')
+ ),
+ validateBackend: function(schema){
+ return schema.string({validate: this.validate});
+ },
+ },
+ "cron.statistics.apis": {
+ title: "Includes APIs",
+ description: "Enter the ID of the hosts you want to save data from, leave this empty to run the task on every host.",
+ category: SettingCategory.STATISTICS,
+ type: EpluginSettingType.editor,
+ defaultValue: [],
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ editor: {
+ language: 'json'
+ }
+ },
+ uiFormTransformConfigurationValueToInputValue: function (value: any): any {
+ return JSON.stringify(value);
+ },
+ uiFormTransformInputValueToConfigurationValue: function (value: string): any {
+ try {
+ return JSON.parse(value);
+ } catch (error) {
+ return value;
+ };
+ },
+ validate: SettingsValidator.json(SettingsValidator.compose(
+ SettingsValidator.array(SettingsValidator.compose(
+ SettingsValidator.isString,
+ SettingsValidator.isNotEmptyString,
+ SettingsValidator.hasNoSpaces,
+ )),
+ )),
+ validateBackend: function(schema){
+ return schema.arrayOf(schema.string({validate: SettingsValidator.compose(
+ SettingsValidator.isNotEmptyString,
+ SettingsValidator.hasNoSpaces,
+ )}));
+ },
+ },
+ "cron.statistics.index.creation": {
+ title: "Index creation",
+ description: "Define the interval in which a new index will be created.",
+ category: SettingCategory.STATISTICS,
+ type: EpluginSettingType.select,
+ options: {
+ select: [
+ {
+ text: "Hourly",
+ value: "h"
+ },
+ {
+ text: "Daily",
+ value: "d"
+ },
+ {
+ text: "Weekly",
+ value: "w"
+ },
+ {
+ text: "Monthly",
+ value: "m"
+ }
+ ]
+ },
+ defaultValue: WAZUH_STATISTICS_DEFAULT_CREATION,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresRunningHealthCheck: true,
+ validate: function (value){
+ return SettingsValidator.literal(this.options.select.map(({value}) => value))(value)
+ },
+ validateBackend: function(schema){
+ return schema.oneOf(this.options.select.map(({value}) => schema.literal(value)));
+ },
+ },
+ "cron.statistics.index.name": {
+ title: "Index name",
+ description: "Define the name of the index in which the documents will be saved.",
+ category: SettingCategory.STATISTICS,
+ type: EpluginSettingType.text,
+ defaultValue: WAZUH_STATISTICS_DEFAULT_NAME,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresRunningHealthCheck: true,
+ // Validation: https://github.com/elastic/elasticsearch/blob/v7.10.2/docs/reference/indices/create-index.asciidoc
+ validate: SettingsValidator.compose(
+ SettingsValidator.isNotEmptyString,
+ SettingsValidator.hasNoSpaces,
+ SettingsValidator.noStartsWithString('-', '_', '+', '.'),
+ SettingsValidator.hasNotInvalidCharacters('\\', '/', '?', '"', '<', '>', '|', ',', '#', '*')
+ ),
+ validateBackend: function(schema){
+ return schema.string({validate: this.validate});
+ },
+ },
+ "cron.statistics.index.replicas": {
+ title: "Index replicas",
+ description: "Define the number of replicas to use for the statistics indices.",
+ category: SettingCategory.STATISTICS,
+ type: EpluginSettingType.number,
+ defaultValue: WAZUH_STATISTICS_DEFAULT_INDICES_REPLICAS,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresRunningHealthCheck: true,
+ options: {
+ number: {
+ min: 0,
+ integer: true
+ }
+ },
+ uiFormTransformConfigurationValueToInputValue: function (value: number): string {
+ return String(value);
+ },
+ uiFormTransformInputValueToConfigurationValue: function (value: string): number {
+ return Number(value);
+ },
+ validate: function(value){
+ return SettingsValidator.number(this.options.number)(value)
+ },
+ validateBackend: function(schema){
+ return schema.number({validate: this.validate.bind(this)});
+ },
+ },
+ "cron.statistics.index.shards": {
+ title: "Index shards",
+ description: "Define the number of shards to use for the statistics indices.",
+ category: SettingCategory.STATISTICS,
+ type: EpluginSettingType.number,
+ defaultValue: WAZUH_STATISTICS_DEFAULT_INDICES_SHARDS,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresRunningHealthCheck: true,
+ options: {
+ number: {
+ min: 1,
+ integer: true
+ }
+ },
+ uiFormTransformConfigurationValueToInputValue: function (value: number) {
+ return String(value)
+ },
+ uiFormTransformInputValueToConfigurationValue: function (value: string): number {
+ return Number(value);
+ },
+ validate: function(value){
+ return SettingsValidator.number(this.options.number)(value)
+ },
+ validateBackend: function(schema){
+ return schema.number({validate: this.validate.bind(this)});
+ },
+ },
+ "cron.statistics.interval": {
+ title: "Interval",
+ description: "Define the frequency of task execution using cron schedule expressions.",
+ category: SettingCategory.STATISTICS,
+ type: EpluginSettingType.text,
+ defaultValue: WAZUH_STATISTICS_DEFAULT_CRON_FREQ,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresRestartingPluginPlatform: true,
+ validate: function(value: string){
+ return validateNodeCronInterval(value) ? undefined : "Interval is not valid."
+ },
+ validateBackend: function(schema){
+ return schema.string({validate: this.validate});
+ },
+ },
+ "cron.statistics.status": {
+ title: "Status",
+ description: "Enable or disable the statistics tasks.",
+ category: SettingCategory.STATISTICS,
+ type: EpluginSettingType.switch,
+ defaultValue: WAZUH_STATISTICS_DEFAULT_STATUS,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "customization.enabled": {
+ title: "Status",
+ description: "Enable or disable the customization.",
+ category: SettingCategory.CUSTOMIZATION,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresReloadingBrowserTab: true,
+ options: {
+ switch: {
+ values: {
+ disabled: {label: 'false', value: false},
+ enabled: {label: 'true', value: true},
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function(value: boolean | string): boolean{
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "customization.logo.app": {
+ title: "App main logo",
+ description: `This logo is used in the app main menu, at the top left corner.`,
+ category: SettingCategory.CUSTOMIZATION,
+ type: EpluginSettingType.filepicker,
+ defaultValue: "",
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ file: {
+ type: 'image',
+ extensions: ['.jpeg', '.jpg', '.png', '.svg'],
+ size: {
+ maxBytes: CUSTOMIZATION_ENDPOINT_PAYLOAD_UPLOAD_CUSTOM_FILE_MAXIMUM_BYTES,
+ },
+ recommended: {
+ dimensions: {
+ width: 300,
+ height: 70,
+ unit: 'px'
+ }
+ },
+ store: {
+ relativePathFileSystem: 'public/assets/custom/images',
+ filename: 'customization.logo.app',
+ resolveStaticURL: (filename: string) => `custom/images/${filename}?v=${Date.now()}`
+ // ?v=${Date.now()} is used to force the browser to reload the image when a new file is uploaded
+ }
+ }
+ },
+ validate: function(value){
+ return SettingsValidator.compose(
+ SettingsValidator.filePickerFileSize({...this.options.file.size, meaningfulUnit: true}),
+ SettingsValidator.filePickerSupportedExtensions(this.options.file.extensions)
+ )(value)
+ },
+ },
+ "customization.logo.healthcheck": {
+ title: "Healthcheck logo",
+ description: `This logo is displayed during the Healthcheck routine of the app.`,
+ category: SettingCategory.CUSTOMIZATION,
+ type: EpluginSettingType.filepicker,
+ defaultValue: "",
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ file: {
+ type: 'image',
+ extensions: ['.jpeg', '.jpg', '.png', '.svg'],
+ size: {
+ maxBytes: CUSTOMIZATION_ENDPOINT_PAYLOAD_UPLOAD_CUSTOM_FILE_MAXIMUM_BYTES,
+ },
+ recommended: {
+ dimensions: {
+ width: 300,
+ height: 70,
+ unit: 'px'
+ }
+ },
+ store: {
+ relativePathFileSystem: 'public/assets/custom/images',
+ filename: 'customization.logo.healthcheck',
+ resolveStaticURL: (filename: string) => `custom/images/${filename}?v=${Date.now()}`
+ // ?v=${Date.now()} is used to force the browser to reload the image when a new file is uploaded
+ }
+ }
+ },
+ validate: function(value){
+ return SettingsValidator.compose(
+ SettingsValidator.filePickerFileSize({...this.options.file.size, meaningfulUnit: true}),
+ SettingsValidator.filePickerSupportedExtensions(this.options.file.extensions)
+ )(value)
+ },
+ },
+ "customization.logo.reports": {
+ title: "PDF reports logo",
+ description: `This logo is used in the PDF reports generated by the app. It's placed at the top left corner of every page of the PDF.`,
+ category: SettingCategory.CUSTOMIZATION,
+ type: EpluginSettingType.filepicker,
+ defaultValue: "",
+ defaultValueIfNotSet: REPORTS_LOGO_IMAGE_ASSETS_RELATIVE_PATH,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ file: {
+ type: 'image',
+ extensions: ['.jpeg', '.jpg', '.png'],
+ size: {
+ maxBytes: CUSTOMIZATION_ENDPOINT_PAYLOAD_UPLOAD_CUSTOM_FILE_MAXIMUM_BYTES,
+ },
+ recommended: {
+ dimensions: {
+ width: 190,
+ height: 40,
+ unit: 'px'
+ }
+ },
+ store: {
+ relativePathFileSystem: 'public/assets/custom/images',
+ filename: 'customization.logo.reports',
+ resolveStaticURL: (filename: string) => `custom/images/${filename}`
+ }
+ }
+ },
+ validate: function(value){
+ return SettingsValidator.compose(
+ SettingsValidator.filePickerFileSize({...this.options.file.size, meaningfulUnit: true}),
+ SettingsValidator.filePickerSupportedExtensions(this.options.file.extensions)
+ )(value)
+ },
+ },
+ "customization.logo.sidebar": {
+ title: "Navigation drawer logo",
+ description: `This is the logo for the app to display in the platform's navigation drawer, this is, the main sidebar collapsible menu.`,
+ category: SettingCategory.CUSTOMIZATION,
+ type: EpluginSettingType.filepicker,
+ defaultValue: "",
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresReloadingBrowserTab: true,
+ options: {
+ file: {
+ type: 'image',
+ extensions: ['.jpeg', '.jpg', '.png', '.svg'],
+ size: {
+ maxBytes: CUSTOMIZATION_ENDPOINT_PAYLOAD_UPLOAD_CUSTOM_FILE_MAXIMUM_BYTES,
+ },
+ recommended: {
+ dimensions: {
+ width: 80,
+ height: 80,
+ unit: 'px'
+ }
+ },
+ store: {
+ relativePathFileSystem: 'public/assets/custom/images',
+ filename: 'customization.logo.sidebar',
+ resolveStaticURL: (filename: string) => `custom/images/${filename}?v=${Date.now()}`
+ // ?v=${Date.now()} is used to force the browser to reload the image when a new file is uploaded
+ }
+ }
+ },
+ validate: function(value){
+ return SettingsValidator.compose(
+ SettingsValidator.filePickerFileSize({...this.options.file.size, meaningfulUnit: true}),
+ SettingsValidator.filePickerSupportedExtensions(this.options.file.extensions)
+ )(value)
+ },
+ },
+ "customization.reports.footer": {
+ title: "Reports footer",
+ description: "Set the footer of the reports.",
+ category: SettingCategory.CUSTOMIZATION,
+ type: EpluginSettingType.textarea,
+ defaultValue: "",
+ defaultValueIfNotSet: REPORTS_PAGE_FOOTER_TEXT,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: { maxRows: 2, maxLength: 50 },
+ validate: function (value) {
+ return SettingsValidator.multipleLinesString({
+ maxRows: this.options?.maxRows,
+ maxLength: this.options?.maxLength
+ })(value)
+ },
+ validateBackend: function (schema) {
+ return schema.string({ validate: this.validate.bind(this) });
+ },
+ },
+ "customization.reports.header": {
+ title: "Reports header",
+ description: "Set the header of the reports.",
+ category: SettingCategory.CUSTOMIZATION,
+ type: EpluginSettingType.textarea,
+ defaultValue: "",
+ defaultValueIfNotSet: REPORTS_PAGE_HEADER_TEXT,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: { maxRows: 3, maxLength: 40 },
+ validate: function (value) {
+ return SettingsValidator.multipleLinesString({
+ maxRows: this.options?.maxRows,
+ maxLength: this.options?.maxLength
+ })(value)
+ },
+ validateBackend: function(schema){
+ return schema.string({validate: this.validate.bind(this)});
+ },
+ },
+ "disabled_roles": {
+ title: "Disable roles",
+ description: "Disabled the plugin visibility for users with the roles.",
+ category: SettingCategory.SECURITY,
+ type: EpluginSettingType.editor,
+ defaultValue: [],
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ editor: {
+ language: 'json'
+ }
+ },
+ uiFormTransformConfigurationValueToInputValue: function (value: any): any {
+ return JSON.stringify(value);
+ },
+ uiFormTransformInputValueToConfigurationValue: function (value: string): any {
+ try {
+ return JSON.parse(value);
+ } catch (error) {
+ return value;
+ };
+ },
+ validate: SettingsValidator.json(SettingsValidator.compose(
+ SettingsValidator.array(SettingsValidator.compose(
+ SettingsValidator.isString,
+ SettingsValidator.isNotEmptyString,
+ SettingsValidator.hasNoSpaces,
+ )),
+ )),
+ validateBackend: function(schema){
+ return schema.arrayOf(schema.string({validate: SettingsValidator.compose(
+ SettingsValidator.isNotEmptyString,
+ SettingsValidator.hasNoSpaces,
+ )}));
+ },
+ },
+ "enrollment.dns": {
+ title: "Enrollment DNS",
+ description: "Specifies the Wazuh registration server, used for the agent enrollment.",
+ category: SettingCategory.GENERAL,
+ type: EpluginSettingType.text,
+ defaultValue: "",
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ validate: SettingsValidator.hasNoSpaces,
+ validateBackend: function(schema){
+ return schema.string({validate: this.validate});
+ },
+ },
+ "enrollment.password": {
+ title: "Enrollment password",
+ description: "Specifies the password used to authenticate during the agent enrollment.",
+ category: SettingCategory.GENERAL,
+ type: EpluginSettingType.text,
+ defaultValue: "",
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ validate: SettingsValidator.isNotEmptyString,
+ validateBackend: function(schema){
+ return schema.string({validate: this.validate});
+ },
+ },
+ "extensions.audit": {
+ title: "System auditing",
+ description: "Enable or disable the Audit tab on Overview and Agents.",
+ category: SettingCategory.EXTENSIONS,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "extensions.aws": {
+ title: "Amazon AWS",
+ description: "Enable or disable the Amazon (AWS) tab on Overview.",
+ category: SettingCategory.EXTENSIONS,
+ type: EpluginSettingType.switch,
+ defaultValue: false,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "extensions.ciscat": {
+ title: "CIS-CAT",
+ description: "Enable or disable the CIS-CAT tab on Overview and Agents.",
+ category: SettingCategory.EXTENSIONS,
+ type: EpluginSettingType.switch,
+ defaultValue: false,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "extensions.docker": {
+ title: "Docker listener",
+ description: "Enable or disable the Docker listener tab on Overview and Agents.",
+ category: SettingCategory.EXTENSIONS,
+ type: EpluginSettingType.switch,
+ defaultValue: false,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "extensions.gcp": {
+ title: "Google Cloud platform",
+ description: "Enable or disable the Google Cloud Platform tab on Overview.",
+ category: SettingCategory.EXTENSIONS,
+ type: EpluginSettingType.switch,
+ defaultValue: false,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "extensions.gdpr": {
+ title: "GDPR",
+ description: "Enable or disable the GDPR tab on Overview and Agents.",
+ category: SettingCategory.EXTENSIONS,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "extensions.hipaa": {
+ title: "Hipaa",
+ description: "Enable or disable the HIPAA tab on Overview and Agents.",
+ category: SettingCategory.EXTENSIONS,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "extensions.nist": {
+ title: "NIST",
+ description: "Enable or disable the NIST 800-53 tab on Overview and Agents.",
+ category: SettingCategory.EXTENSIONS,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "extensions.oscap": {
+ title: "OSCAP",
+ description: "Enable or disable the Open SCAP tab on Overview and Agents.",
+ category: SettingCategory.EXTENSIONS,
+ type: EpluginSettingType.switch,
+ defaultValue: false,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "extensions.osquery": {
+ title: "Osquery",
+ description: "Enable or disable the Osquery tab on Overview and Agents.",
+ category: SettingCategory.EXTENSIONS,
+ type: EpluginSettingType.switch,
+ defaultValue: false,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "extensions.pci": {
+ title: "PCI DSS",
+ description: "Enable or disable the PCI DSS tab on Overview and Agents.",
+ category: SettingCategory.EXTENSIONS,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "extensions.tsc": {
+ title: "TSC",
+ description: "Enable or disable the TSC tab on Overview and Agents.",
+ category: SettingCategory.EXTENSIONS,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "extensions.virustotal": {
+ title: "Virustotal",
+ description: "Enable or disable the VirusTotal tab on Overview and Agents.",
+ category: SettingCategory.EXTENSIONS,
+ type: EpluginSettingType.switch,
+ defaultValue: false,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "hideManagerAlerts": {
+ title: "Hide manager alerts",
+ description: "Hide the alerts of the manager in every dashboard.",
+ category: SettingCategory.GENERAL,
+ type: EpluginSettingType.switch,
+ defaultValue: false,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresReloadingBrowserTab: true,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "ip.ignore": {
+ title: "Index pattern ignore",
+ description: "Disable certain index pattern names from being available in index pattern selector.",
+ category: SettingCategory.GENERAL,
+ type: EpluginSettingType.editor,
+ defaultValue: [],
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ editor: {
+ language: 'json'
+ }
+ },
+ uiFormTransformConfigurationValueToInputValue: function (value: any): any {
+ return JSON.stringify(value);
+ },
+ uiFormTransformInputValueToConfigurationValue: function (value: string): any {
+ try {
+ return JSON.parse(value);
+ } catch (error) {
+ return value;
+ };
+ },
+ // Validation: https://github.com/elastic/elasticsearch/blob/v7.10.2/docs/reference/indices/create-index.asciidoc
+ validate: SettingsValidator.json(SettingsValidator.compose(
+ SettingsValidator.array(SettingsValidator.compose(
+ SettingsValidator.isString,
+ SettingsValidator.isNotEmptyString,
+ SettingsValidator.hasNoSpaces,
+ SettingsValidator.noLiteralString('.', '..'),
+ SettingsValidator.noStartsWithString('-', '_', '+', '.'),
+ SettingsValidator.hasNotInvalidCharacters('\\', '/', '?', '"', '<', '>', '|', ',', '#')
+ )),
+ )),
+ validateBackend: function(schema){
+ return schema.arrayOf(schema.string({validate: SettingsValidator.compose(
+ SettingsValidator.isNotEmptyString,
+ SettingsValidator.hasNoSpaces,
+ SettingsValidator.noLiteralString('.', '..'),
+ SettingsValidator.noStartsWithString('-', '_', '+', '.'),
+ SettingsValidator.hasNotInvalidCharacters('\\', '/', '?', '"', '<', '>', '|', ',', '#')
+ )}));
+ },
+ },
+ "ip.selector": {
+ title: "IP selector",
+ description: "Define if the user is allowed to change the selected index pattern directly from the top menu bar.",
+ category: SettingCategory.GENERAL,
+ type: EpluginSettingType.switch,
+ defaultValue: true,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: false,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "logs.level": {
+ title: "Log level",
+ description: "Logging level of the App.",
+ category: SettingCategory.GENERAL,
+ type: EpluginSettingType.select,
+ options: {
+ select: [
+ {
+ text: "Info",
+ value: "info"
+ },
+ {
+ text: "Debug",
+ value: "debug"
+ }
+ ]
+ },
+ defaultValue: "info",
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresRestartingPluginPlatform: true,
+ validate: function (value){
+ return SettingsValidator.literal(this.options.select.map(({value}) => value))(value)
+ },
+ validateBackend: function(schema){
+ return schema.oneOf(this.options.select.map(({value}) => schema.literal(value)));
+ },
+ },
+ "pattern": {
+ title: "Index pattern",
+ description: "Default index pattern to use on the app. If there's no valid index pattern, the app will automatically create one with the name indicated in this option.",
+ category: SettingCategory.GENERAL,
+ type: EpluginSettingType.text,
+ defaultValue: WAZUH_ALERTS_PATTERN,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresRunningHealthCheck: true,
+ // Validation: https://github.com/elastic/elasticsearch/blob/v7.10.2/docs/reference/indices/create-index.asciidoc
+ validate: SettingsValidator.compose(
+ SettingsValidator.isNotEmptyString,
+ SettingsValidator.hasNoSpaces,
+ SettingsValidator.noLiteralString('.', '..'),
+ SettingsValidator.noStartsWithString('-', '_', '+', '.'),
+ SettingsValidator.hasNotInvalidCharacters('\\', '/', '?', '"', '<', '>', '|', ',', '#')
+ ),
+ validateBackend: function(schema){
+ return schema.string({validate: this.validate});
+ },
+ },
+ "timeout": {
+ title: "Request timeout",
+ description: "Maximum time, in milliseconds, the app will wait for an API response when making requests to it. It will be ignored if the value is set under 1500 milliseconds.",
+ category: SettingCategory.GENERAL,
+ type: EpluginSettingType.number,
+ defaultValue: 20000,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ options: {
+ number: {
+ min: 1500,
+ integer: true
+ }
+ },
+ uiFormTransformConfigurationValueToInputValue: function (value: number) {
+ return String(value)
+ },
+ uiFormTransformInputValueToConfigurationValue: function (value: string): number {
+ return Number(value);
+ },
+ validate: function(value){
+ return SettingsValidator.number(this.options.number)(value);
+ },
+ validateBackend: function(schema){
+ return schema.number({validate: this.validate.bind(this)});
+ },
+ },
+ "wazuh.monitoring.creation": {
+ title: "Index creation",
+ description: "Define the interval in which a new wazuh-monitoring index will be created.",
+ category: SettingCategory.MONITORING,
+ type: EpluginSettingType.select,
+ options: {
+ select: [
+ {
+ text: "Hourly",
+ value: "h"
+ },
+ {
+ text: "Daily",
+ value: "d"
+ },
+ {
+ text: "Weekly",
+ value: "w"
+ },
+ {
+ text: "Monthly",
+ value: "m"
+ }
+ ]
+ },
+ defaultValue: WAZUH_MONITORING_DEFAULT_CREATION,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresRunningHealthCheck: true,
+ validate: function (value){
+ return SettingsValidator.literal(this.options.select.map(({value}) => value))(value)
+ },
+ validateBackend: function(schema){
+ return schema.oneOf(this.options.select.map(({value}) => schema.literal(value)));
+ },
+ },
+ "wazuh.monitoring.enabled": {
+ title: "Status",
+ description: "Enable or disable the wazuh-monitoring index creation and/or visualization.",
+ category: SettingCategory.MONITORING,
+ type: EpluginSettingType.switch,
+ defaultValue: WAZUH_MONITORING_DEFAULT_ENABLED,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresRestartingPluginPlatform: true,
+ options: {
+ switch: {
+ values: {
+ disabled: { label: 'false', value: false },
+ enabled: { label: 'true', value: true },
+ }
+ }
+ },
+ uiFormTransformChangedInputValue: function (value: boolean | string): boolean {
+ return Boolean(value);
+ },
+ validate: SettingsValidator.isBoolean,
+ validateBackend: function(schema){
+ return schema.boolean();
+ },
+ },
+ "wazuh.monitoring.frequency": {
+ title: "Frequency",
+ description: "Frequency, in seconds, of API requests to get the state of the agents and create a new document in the wazuh-monitoring index with this data.",
+ category: SettingCategory.MONITORING,
+ type: EpluginSettingType.number,
+ defaultValue: WAZUH_MONITORING_DEFAULT_FREQUENCY,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresRestartingPluginPlatform: true,
+ options: {
+ number: {
+ min: 60,
+ integer: true
+ }
+ },
+ uiFormTransformConfigurationValueToInputValue: function (value: number) {
+ return String(value)
+ },
+ uiFormTransformInputValueToConfigurationValue: function (value: string): number {
+ return Number(value);
+ },
+ validate: function(value){
+ return SettingsValidator.number(this.options.number)(value);
+ },
+ validateBackend: function(schema){
+ return schema.number({validate: this.validate.bind(this)});
+ },
+ },
+ "wazuh.monitoring.pattern": {
+ title: "Index pattern",
+ description: "Default index pattern to use for Wazuh monitoring.",
+ category: SettingCategory.MONITORING,
+ type: EpluginSettingType.text,
+ defaultValue: WAZUH_MONITORING_PATTERN,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresRunningHealthCheck: true,
+ validate: SettingsValidator.compose(
+ SettingsValidator.isNotEmptyString,
+ SettingsValidator.hasNoSpaces,
+ SettingsValidator.noLiteralString('.', '..'),
+ SettingsValidator.noStartsWithString('-', '_', '+', '.'),
+ SettingsValidator.hasNotInvalidCharacters('\\', '/', '?', '"', '<', '>', '|', ',', '#')
+ ),
+ validateBackend: function(schema){
+ return schema.string({minLength: 1, validate: this.validate});
+ },
+ },
+ "wazuh.monitoring.replicas": {
+ title: "Index replicas",
+ description: "Define the number of replicas to use for the wazuh-monitoring-* indices.",
+ category: SettingCategory.MONITORING,
+ type: EpluginSettingType.number,
+ defaultValue: WAZUH_MONITORING_DEFAULT_INDICES_REPLICAS,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresRunningHealthCheck: true,
+ options: {
+ number: {
+ min: 0,
+ integer: true
+ }
+ },
+ uiFormTransformConfigurationValueToInputValue: function (value: number) {
+ return String(value)
+ },
+ uiFormTransformInputValueToConfigurationValue: function (value: string): number {
+ return Number(value);
+ },
+ validate: function(value){
+ return SettingsValidator.number(this.options.number)(value);
+ },
+ validateBackend: function(schema){
+ return schema.number({validate: this.validate.bind(this)});
+ },
+ },
+ "wazuh.monitoring.shards": {
+ title: "Index shards",
+ description: "Define the number of shards to use for the wazuh-monitoring-* indices.",
+ category: SettingCategory.MONITORING,
+ type: EpluginSettingType.number,
+ defaultValue: WAZUH_MONITORING_DEFAULT_INDICES_SHARDS,
+ isConfigurableFromFile: true,
+ isConfigurableFromUI: true,
+ requiresRunningHealthCheck: true,
+ options: {
+ number: {
+ min: 1,
+ integer: true
+ }
+ },
+ uiFormTransformConfigurationValueToInputValue: function (value: number) {
+ return String(value)
+ },
+ uiFormTransformInputValueToConfigurationValue: function (value: string): number {
+ return Number(value);
+ },
+ validate: function(value){
+ return SettingsValidator.number(this.options.number)(value);
+ },
+ validateBackend: function(schema){
+ return schema.number({validate: this.validate.bind(this)});
+ },
+ }
+};
+
+export type TPluginSettingKey = keyof typeof PLUGIN_SETTINGS;
+
+export enum HTTP_STATUS_CODES {
+ CONTINUE = 100,
+ SWITCHING_PROTOCOLS = 101,
+ PROCESSING = 102,
+ OK = 200,
+ CREATED = 201,
+ ACCEPTED = 202,
+ NON_AUTHORITATIVE_INFORMATION = 203,
+ NO_CONTENT = 204,
+ RESET_CONTENT = 205,
+ PARTIAL_CONTENT = 206,
+ MULTI_STATUS = 207,
+ MULTIPLE_CHOICES = 300,
+ MOVED_PERMANENTLY = 301,
+ MOVED_TEMPORARILY = 302,
+ SEE_OTHER = 303,
+ NOT_MODIFIED = 304,
+ USE_PROXY = 305,
+ TEMPORARY_REDIRECT = 307,
+ PERMANENT_REDIRECT = 308,
+ BAD_REQUEST = 400,
+ UNAUTHORIZED = 401,
+ PAYMENT_REQUIRED = 402,
+ FORBIDDEN = 403,
+ NOT_FOUND = 404,
+ METHOD_NOT_ALLOWED = 405,
+ NOT_ACCEPTABLE = 406,
+ PROXY_AUTHENTICATION_REQUIRED = 407,
+ REQUEST_TIMEOUT = 408,
+ CONFLICT = 409,
+ GONE = 410,
+ LENGTH_REQUIRED = 411,
+ PRECONDITION_FAILED = 412,
+ REQUEST_TOO_LONG = 413,
+ REQUEST_URI_TOO_LONG = 414,
+ UNSUPPORTED_MEDIA_TYPE = 415,
+ REQUESTED_RANGE_NOT_SATISFIABLE = 416,
+ EXPECTATION_FAILED = 417,
+ IM_A_TEAPOT = 418,
+ INSUFFICIENT_SPACE_ON_RESOURCE = 419,
+ METHOD_FAILURE = 420,
+ MISDIRECTED_REQUEST = 421,
+ UNPROCESSABLE_ENTITY = 422,
+ LOCKED = 423,
+ FAILED_DEPENDENCY = 424,
+ PRECONDITION_REQUIRED = 428,
+ TOO_MANY_REQUESTS = 429,
+ REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
+ UNAVAILABLE_FOR_LEGAL_REASONS = 451,
+ INTERNAL_SERVER_ERROR = 500,
+ NOT_IMPLEMENTED = 501,
+ BAD_GATEWAY = 502,
+ SERVICE_UNAVAILABLE = 503,
+ GATEWAY_TIMEOUT = 504,
+ HTTP_VERSION_NOT_SUPPORTED = 505,
+ INSUFFICIENT_STORAGE = 507,
+ NETWORK_AUTHENTICATION_REQUIRED = 511
+}
+
+// Module Security configuration assessment
+export const MODULE_SCA_CHECK_RESULT_LABEL = {
+ passed: 'Passed',
+ failed: 'Failed',
+ 'not applicable': 'Not applicable'
+}
diff --git a/common/csv-key-equivalence.ts b/common/csv-key-equivalence.ts
index e4cf0aa711..d014c5271e 100644
--- a/common/csv-key-equivalence.ts
+++ b/common/csv-key-equivalence.ts
@@ -25,7 +25,7 @@ export const KeyEquivalence: {[key: string]: string} = {
'os.uname': 'OS uname',
status: 'Status',
group: 'Group',
- ip: 'IP',
+ ip: 'IP address',
description: 'Description',
tag: 'Tag',
level: 'Level',
@@ -52,7 +52,7 @@ export const KeyEquivalence: {[key: string]: string} = {
dateAdd: 'Registration date',
manager: 'Manager',
lastKeepAlive: 'Last keep alive',
- os: 'OS',
+ os: 'Operating system',
path: 'Path',
details: 'Details',
position: 'Position',
@@ -72,7 +72,7 @@ export const KeyEquivalence: {[key: string]: string} = {
address: 'Address',
protocol: 'Protocol',
netmask: 'Netmask',
- 'local.ip': 'Local IP',
+ 'local.ip': 'Local IP address',
'remote.ip': 'Remote IP',
'local.port': 'Local port',
'remote.port': 'Remote port',
diff --git a/common/plugin-settings.test.ts b/common/plugin-settings.test.ts
new file mode 100644
index 0000000000..2e06257c87
--- /dev/null
+++ b/common/plugin-settings.test.ts
@@ -0,0 +1,252 @@
+import { PLUGIN_SETTINGS } from "./constants";
+
+describe('[settings] Input validation', () => {
+ it.each`
+ setting | value | expectedValidation
+ ${'alerts.sample.prefix'} | ${'test'} | ${undefined}
+ ${'alerts.sample.prefix'} | ${''} | ${"Value can not be empty."}
+ ${'alerts.sample.prefix'} | ${'test space'} | ${"No whitespaces allowed."}
+ ${'alerts.sample.prefix'} | ${'-test'} | ${"It can't start with: -, _, +, .."}
+ ${'alerts.sample.prefix'} | ${'_test'} | ${"It can't start with: -, _, +, .."}
+ ${'alerts.sample.prefix'} | ${'+test'} | ${"It can't start with: -, _, +, .."}
+ ${'alerts.sample.prefix'} | ${'.test'} | ${"It can't start with: -, _, +, .."}
+ ${'alerts.sample.prefix'} | ${'test\\'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test/'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test?'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test"'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test<'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test>'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test|'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test,'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test#'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test*'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'checks.api'} | ${true} | ${undefined}
+ ${'checks.api'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'checks.fields'} | ${true} | ${undefined}
+ ${'checks.fields'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'checks.maxBuckets'} | ${true} | ${undefined}
+ ${'checks.maxBuckets'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'checks.pattern'} | ${true} | ${undefined}
+ ${'checks.pattern'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'checks.setup'} | ${true} | ${undefined}
+ ${'checks.setup'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'checks.template'} | ${true} | ${undefined}
+ ${'checks.template'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'checks.timeFilter'} | ${true} | ${undefined}
+ ${'checks.timeFilter'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'cron.prefix'} | ${'test'} | ${undefined}
+ ${'cron.prefix'} | ${'test space'} | ${"No whitespaces allowed."}
+ ${'cron.prefix'} | ${''} | ${"Value can not be empty."}
+ ${'cron.prefix'} | ${'-test'} | ${"It can't start with: -, _, +, .."}
+ ${'cron.prefix'} | ${'_test'} | ${"It can't start with: -, _, +, .."}
+ ${'cron.prefix'} | ${'+test'} | ${"It can't start with: -, _, +, .."}
+ ${'cron.prefix'} | ${'.test'} | ${"It can't start with: -, _, +, .."}
+ ${'cron.prefix'} | ${'test\\'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test/'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test?'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test"'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test<'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test>'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test|'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test,'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test#'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test*'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.apis'} | ${['test']} | ${undefined}
+ ${'cron.statistics.apis'} | ${['test ']} | ${"No whitespaces allowed."}
+ ${'cron.statistics.apis'} | ${['']} | ${"Value can not be empty."}
+ ${'cron.statistics.apis'} | ${['test', 4]} | ${"Value is not a string."}
+ ${'cron.statistics.apis'} | ${'test space'} | ${"Value is not a valid list."}
+ ${'cron.statistics.apis'} | ${true} | ${"Value is not a valid list."}
+ ${'cron.statistics.index.creation'} | ${'h'} | ${undefined}
+ ${'cron.statistics.index.creation'} | ${'d'} | ${undefined}
+ ${'cron.statistics.index.creation'} | ${'w'} | ${undefined}
+ ${'cron.statistics.index.creation'} | ${'m'} | ${undefined}
+ ${'cron.statistics.index.creation'} | ${'test'} | ${"Invalid value. Allowed values: h, d, w, m."}
+ ${'cron.statistics.index.name'} | ${'test'} | ${undefined}
+ ${'cron.statistics.index.name'} | ${''} | ${"Value can not be empty."}
+ ${'cron.statistics.index.name'} | ${'test space'} | ${"No whitespaces allowed."}
+ ${'cron.statistics.index.name'} | ${'-test'} | ${"It can't start with: -, _, +, .."}
+ ${'cron.statistics.index.name'} | ${'_test'} | ${"It can't start with: -, _, +, .."}
+ ${'cron.statistics.index.name'} | ${'+test'} | ${"It can't start with: -, _, +, .."}
+ ${'cron.statistics.index.name'} | ${'.test'} | ${"It can't start with: -, _, +, .."}
+ ${'cron.statistics.index.name'} | ${'test\\'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test/'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test?'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test"'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test<'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test>'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test|'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test,'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test#'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test*'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.replicas'} | ${0} | ${undefined}
+ ${'cron.statistics.index.replicas'} | ${-1} | ${"Value should be greater or equal than 0."}
+ ${'cron.statistics.index.replicas'} | ${'1.2'} | ${'Number should be an integer.'}
+ ${'cron.statistics.index.replicas'} | ${1.2} | ${'Number should be an integer.'}
+ ${'cron.statistics.index.shards'} | ${1} | ${undefined}
+ ${'cron.statistics.index.shards'} | ${-1} | ${"Value should be greater or equal than 1."}
+ ${'cron.statistics.index.shards'} | ${'1.2'} | ${'Number should be an integer.'}
+ ${'cron.statistics.index.shards'} | ${1.2} | ${'Number should be an integer.'}
+ ${'cron.statistics.interval'} | ${'0 */5 * * * *'} | ${undefined}
+ ${'cron.statistics.interval'} | ${'0 */5 * * *'} | ${undefined}
+ ${'cron.statistics.interval'} | ${'custom'} | ${"Interval is not valid."}
+ ${'cron.statistics.interval'} | ${true} | ${"Interval is not valid."}
+ ${'cron.statistics.status'} | ${true} | ${undefined}
+ ${'cron.statistics.status'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'customization.enabled'} | ${true} | ${undefined}
+ ${'customization.logo.app'} | ${{size: 124000, name: 'image.jpg'}} | ${undefined}
+ ${'customization.logo.app'} | ${{size: 124000, name: 'image.jpeg'}} | ${undefined}
+ ${'customization.logo.app'} | ${{size: 124000, name: 'image.png'}} | ${undefined}
+ ${'customization.logo.app'} | ${{size: 124000, name: 'image.svg'}} | ${undefined}
+ ${'customization.logo.app'} | ${{size: 124000, name: 'image.txt'}} | ${'File extension is invalid. Allowed file extensions: .jpeg, .jpg, .png, .svg.'}
+ ${'customization.logo.app'} | ${{size: 1240000, name: 'image.txt'}} | ${'File size should be lower or equal than 1 MB.'}
+ ${'customization.logo.healthcheck'} | ${{size: 124000, name: 'image.jpg'}} | ${undefined}
+ ${'customization.logo.healthcheck'} | ${{size: 124000, name: 'image.jpeg'}} | ${undefined}
+ ${'customization.logo.healthcheck'} | ${{size: 124000, name: 'image.png'}} | ${undefined}
+ ${'customization.logo.healthcheck'} | ${{size: 124000, name: 'image.svg'}} | ${undefined}
+ ${'customization.logo.healthcheck'} | ${{size: 124000, name: 'image.txt'}} | ${'File extension is invalid. Allowed file extensions: .jpeg, .jpg, .png, .svg.'}
+ ${'customization.logo.healthcheck'} | ${{size: 1240000, name: 'image.txt'}} | ${'File size should be lower or equal than 1 MB.'}
+ ${'customization.logo.reports'} | ${{size: 124000, name: 'image.jpg'}} | ${undefined}
+ ${'customization.logo.reports'} | ${{size: 124000, name: 'image.jpeg'}} | ${undefined}
+ ${'customization.logo.reports'} | ${{size: 124000, name: 'image.png'}} | ${undefined}
+ ${'customization.logo.reports'} | ${{size: 124000, name: 'image.svg'}} | ${'File extension is invalid. Allowed file extensions: .jpeg, .jpg, .png.'}
+ ${'customization.logo.reports'} | ${{size: 124000, name: 'image.txt'}} | ${'File extension is invalid. Allowed file extensions: .jpeg, .jpg, .png.'}
+ ${'customization.logo.reports'} | ${{size: 1240000, name: 'image.txt'}} | ${'File size should be lower or equal than 1 MB.'}
+ ${'customization.logo.sidebar'} | ${{size: 124000, name: 'image.jpg'}} | ${undefined}
+ ${'customization.logo.sidebar'} | ${{size: 124000, name: 'image.jpeg'}} | ${undefined}
+ ${'customization.logo.sidebar'} | ${{size: 124000, name: 'image.png'}} | ${undefined}
+ ${'customization.logo.sidebar'} | ${{size: 124000, name: 'image.svg'}} | ${undefined}
+ ${'customization.logo.sidebar'} | ${{size: 124000, name: 'image.txt'}} | ${'File extension is invalid. Allowed file extensions: .jpeg, .jpg, .png, .svg.'}
+ ${'customization.logo.sidebar'} | ${{size: 1240000, name: 'image.txt'}} | ${'File size should be lower or equal than 1 MB.'}
+ ${'customization.reports.footer'} | ${'Test'} | ${undefined}
+ ${'customization.reports.footer'} | ${'Test\nTest'} | ${undefined}
+ ${'customization.reports.footer'} | ${'Test\nTest\nTest\nTest\nTest'} | ${'The string should have less or equal to 2 line/s.'}
+ ${'customization.reports.footer'} | ${'Line with 30 characters \nTest'} | ${undefined}
+ ${'customization.reports.footer'} | ${'Testing maximum length of a line of more than 50 characters\nTest'} | ${"The maximum length of a line is 50 characters."}
+ ${'customization.reports.header'} | ${'Test'} | ${undefined}
+ ${'customization.reports.header'} | ${'Test\nTest'} | ${undefined}
+ ${'customization.reports.header'} | ${'Test\nTest\nTest\nTest\nTest'} | ${'The string should have less or equal to 3 line/s.'}
+ ${'customization.reports.header'} | ${'Line with 20 charact\nTest'} | ${undefined}
+ ${'customization.reports.header'} | ${'Testing maximum length of a line of 40 characters\nTest'} | ${"The maximum length of a line is 40 characters."}
+ ${'disabled_roles'} | ${['test']} | ${undefined}
+ ${'disabled_roles'} | ${['']} | ${'Value can not be empty.'}
+ ${'disabled_roles'} | ${['test space']} | ${"No whitespaces allowed."}
+ ${'disabled_roles'} | ${['test', 4]} | ${"Value is not a string."}
+ ${'enrollment.dns'} | ${'test'} | ${undefined}
+ ${'enrollment.dns'} | ${''} | ${undefined}
+ ${'enrollment.dns'} | ${'test space'} | ${"No whitespaces allowed."}
+ ${'enrollment.password'} | ${'test'} | ${undefined}
+ ${'enrollment.password'} | ${''} | ${"Value can not be empty."}
+ ${'enrollment.password'} | ${'test space'} | ${undefined}
+ ${'extensions.audit'} | ${true} | ${undefined}
+ ${'extensions.audit'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'extensions.aws'} | ${true} | ${undefined}
+ ${'extensions.aws'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'extensions.ciscat'} | ${true} | ${undefined}
+ ${'extensions.ciscat'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'extensions.gcp'} | ${true} | ${undefined}
+ ${'extensions.gcp'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'extensions.gdpr'} | ${true} | ${undefined}
+ ${'extensions.gdpr'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'extensions.hipaa'} | ${true} | ${undefined}
+ ${'extensions.hipaa'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'extensions.nist'} | ${true} | ${undefined}
+ ${'extensions.nist'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'extensions.oscap'} | ${true} | ${undefined}
+ ${'extensions.oscap'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'extensions.osquery'} | ${true} | ${undefined}
+ ${'extensions.osquery'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'extensions.pci'} | ${true} | ${undefined}
+ ${'extensions.pci'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'extensions.tsc'} | ${true} | ${undefined}
+ ${'extensions.tsc'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'extensions.virustotal'} | ${true} | ${undefined}
+ ${'extensions.virustotal'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'ip.ignore'} | ${['test']} | ${undefined}
+ ${'ip.ignore'} | ${['test*']} | ${undefined}
+ ${'ip.ignore'} | ${['']} | ${'Value can not be empty.'}
+ ${'ip.ignore'} | ${['test space']} | ${"No whitespaces allowed."}
+ ${'ip.ignore'} | ${true} | ${"Value is not a valid list."}
+ ${'ip.ignore'} | ${['-test']} | ${"It can't start with: -, _, +, .."}
+ ${'ip.ignore'} | ${['_test']} | ${"It can't start with: -, _, +, .."}
+ ${'ip.ignore'} | ${['+test']} | ${"It can't start with: -, _, +, .."}
+ ${'ip.ignore'} | ${['.test']} | ${"It can't start with: -, _, +, .."}
+ ${'ip.ignore'} | ${['test\\']} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test/']} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test?']} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test"']} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test<']} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test>']} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test|']} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test,']} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test#']} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test', 'test#']} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.selector'} | ${true} | ${undefined}
+ ${'ip.selector'} | ${''} | ${'It should be a boolean. Allowed values: true or false.'}
+ ${'logs.level'} | ${'info'} | ${undefined}
+ ${'logs.level'} | ${'debug'} | ${undefined}
+ ${'logs.level'} | ${''} | ${'Invalid value. Allowed values: info, debug.'}
+ ${'pattern'} | ${'test'} | ${undefined}
+ ${'pattern'} | ${'test*'} | ${undefined}
+ ${'pattern'} | ${''} | ${'Value can not be empty.'}
+ ${'pattern'} | ${'test space'} | ${"No whitespaces allowed."}
+ ${'pattern'} | ${'-test'} | ${"It can't start with: -, _, +, .."}
+ ${'pattern'} | ${'_test'} | ${"It can't start with: -, _, +, .."}
+ ${'pattern'} | ${'+test'} | ${"It can't start with: -, _, +, .."}
+ ${'pattern'} | ${'.test'} | ${"It can't start with: -, _, +, .."}
+ ${'pattern'} | ${'test\\'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test/'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test?'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test"'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test<'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test>'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test|'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test,'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test#'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'timeout'} | ${15000} | ${undefined}
+ ${'timeout'} | ${1000} | ${'Value should be greater or equal than 1500.'}
+ ${'timeout'} | ${''} | ${'Value should be greater or equal than 1500.'}
+ ${'timeout'} | ${'1.2'} | ${'Number should be an integer.'}
+ ${'timeout'} | ${1.2} | ${'Number should be an integer.'}
+ ${'wazuh.monitoring.creation'} | ${'h'} | ${undefined}
+ ${'wazuh.monitoring.creation'} | ${'d'} | ${undefined}
+ ${'wazuh.monitoring.creation'} | ${'w'} | ${undefined}
+ ${'wazuh.monitoring.creation'} | ${'m'} | ${undefined}
+ ${'wazuh.monitoring.creation'} | ${'test'} | ${"Invalid value. Allowed values: h, d, w, m."}
+ ${'wazuh.monitoring.enabled'} | ${true} | ${undefined}
+ ${'wazuh.monitoring.frequency'} | ${100} | ${undefined}
+ ${'wazuh.monitoring.frequency'} | ${40} | ${"Value should be greater or equal than 60."}
+ ${'wazuh.monitoring.frequency'} | ${'1.2'} | ${'Number should be an integer.'}
+ ${'wazuh.monitoring.frequency'} | ${1.2} | ${'Number should be an integer.'}
+ ${'wazuh.monitoring.pattern'} | ${'test'} | ${undefined}
+ ${'wazuh.monitoring.pattern'} | ${'test*'} | ${undefined}
+ ${'wazuh.monitoring.pattern'} | ${''} | ${'Value can not be empty.'}
+ ${'wazuh.monitoring.pattern'} | ${'-test'} | ${"It can't start with: -, _, +, .."}
+ ${'wazuh.monitoring.pattern'} | ${'_test'} | ${"It can't start with: -, _, +, .."}
+ ${'wazuh.monitoring.pattern'} | ${'+test'} | ${"It can't start with: -, _, +, .."}
+ ${'wazuh.monitoring.pattern'} | ${'.test'} | ${"It can't start with: -, _, +, .."}
+ ${'wazuh.monitoring.pattern'} | ${'test\\'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test/'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test?'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test"'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test<'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test>'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test|'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test,'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test#'} | ${"It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.replicas'} | ${0} | ${undefined}
+ ${'wazuh.monitoring.replicas'} | ${-1} | ${"Value should be greater or equal than 0."}
+ ${'wazuh.monitoring.replicas'} | ${'1.2'} | ${'Number should be an integer.'}
+ ${'wazuh.monitoring.replicas'} | ${1.2} | ${'Number should be an integer.'}
+ ${'wazuh.monitoring.shards'} | ${1} | ${undefined}
+ ${'wazuh.monitoring.shards'} | ${-1} | ${"Value should be greater or equal than 1."}
+ ${'wazuh.monitoring.shards'} | ${'1.2'} | ${'Number should be an integer.'}
+ ${'wazuh.monitoring.shards'} | ${1.2} | ${'Number should be an integer.'}
+ `('$setting | $value | $expectedValidation', ({ setting, value, expectedValidation }) => {
+ expect(
+ PLUGIN_SETTINGS[setting].validate(
+ PLUGIN_SETTINGS[setting]?.uiFormTransformConfigurationValueToInputValue?.(value)
+ ?? value
+ )).toBe(expectedValidation);
+ })
+});
diff --git a/common/services/file-extension.test.ts b/common/services/file-extension.test.ts
new file mode 100644
index 0000000000..73a5e47e99
--- /dev/null
+++ b/common/services/file-extension.test.ts
@@ -0,0 +1,17 @@
+import { getFileExtensionFromBuffer } from "./file-extension";
+import fs from 'fs';
+import path from 'path';
+
+describe('getFileExtensionFromBuffer', () => {
+ it.each`
+ filepath | extension
+ ${'../../server/routes/wazuh-utils/fixtures/fixture_image_small.jpg'} | ${'jpg'}
+ ${'../../server/routes/wazuh-utils/fixtures/fixture_image_small.png'} | ${'png'}
+ ${'../../server/routes/wazuh-utils/fixtures/fixture_image_big.png'} | ${'png'}
+ ${'../../server/routes/wazuh-utils/fixtures/fixture_image_small.svg'} | ${'svg'}
+ ${'../../server/routes/wazuh-utils/fixtures/fixture_file.txt'} | ${'unknown'}
+ `(`filepath: $filepath expects to get extension: $extension`, ({ extension, filepath }) => {
+ const bufferFile = fs.readFileSync(path.join(__dirname, filepath));
+ expect(getFileExtensionFromBuffer(bufferFile)).toBe(extension);
+ });
+});
diff --git a/common/services/file-extension.ts b/common/services/file-extension.ts
new file mode 100644
index 0000000000..5f4be36b0a
--- /dev/null
+++ b/common/services/file-extension.ts
@@ -0,0 +1,23 @@
+/**
+ * Get the file extension from a file buffer. Calculates the image format by reading the first 4 bytes of the image (header)
+ * Supported types: jpeg, jpg, png, svg
+ * Additionally, this function allows checking gif images.
+ * @param buffer file buffer
+ * @returns the file extension. Example: jpg, png, svg. it Returns unknown if it can not find the extension.
+*/
+export function getFileExtensionFromBuffer(buffer: Buffer): string {
+ const imageFormat = buffer.toString('hex').substring(0, 4);
+ switch (imageFormat) {
+ case '4749':
+ return 'gif';
+ case 'ffd8':
+ return 'jpg'; // Also jpeg
+ case '8950':
+ return 'png';
+ case '3c73':
+ case '3c3f':
+ return 'svg';
+ default:
+ return 'unknown';
+ }
+};
diff --git a/common/services/file-size.test.ts b/common/services/file-size.test.ts
new file mode 100644
index 0000000000..269c215e6c
--- /dev/null
+++ b/common/services/file-size.test.ts
@@ -0,0 +1,20 @@
+import {formatBytes } from "./file-size";
+
+describe('formatBytes', () => {
+ it.each`
+ bytes | decimals | expected
+ ${1024} | ${2} | ${'1 KB'}
+ ${1023} | ${2} | ${'1023 Bytes'}
+ ${1500} | ${2} | ${'1.46 KB'}
+ ${1500} | ${1} | ${'1.5 KB'}
+ ${1500} | ${3} | ${'1.465 KB'}
+ ${1048576} | ${2} | ${'1 MB'}
+ ${1048577} | ${2} | ${'1 MB'}
+ ${1475487} | ${2} | ${'1.41 MB'}
+ ${1475487} | ${1} | ${'1.4 MB'}
+ ${1475487} | ${3} | ${'1.407 MB'}
+ ${1073741824} | ${2} | ${'1 GB'}
+ `(`bytes: $bytes | decimals: $decimals | expected: $expected`, ({ bytes, decimals, expected }) => {
+ expect(formatBytes(bytes, decimals)).toBe(expected);
+ });
+});
diff --git a/common/services/file-size.ts b/common/services/file-size.ts
new file mode 100644
index 0000000000..9ee7af30c2
--- /dev/null
+++ b/common/services/file-size.ts
@@ -0,0 +1,17 @@
+/**
+ * Format the number the bytes to the higher unit.
+ * @param bytes Bytes
+ * @param decimals Number of decimals
+ * @returns Formatted value with the unit
+ */
+export function formatBytes(bytes: number, decimals: number = 2): string {
+ if (!+bytes) return '0 Bytes';
+
+ const k = 1024;
+ const dm = decimals < 0 ? 0 : decimals;
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
+
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
+
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;
+};
\ No newline at end of file
diff --git a/common/services/settings-validator.ts b/common/services/settings-validator.ts
new file mode 100644
index 0000000000..b62675f0f9
--- /dev/null
+++ b/common/services/settings-validator.ts
@@ -0,0 +1,235 @@
+import path from 'path';
+import { formatBytes } from './file-size';
+
+export class SettingsValidator {
+ /**
+ * Create a function that is a composition of the input validations
+ * @param functions SettingsValidator functions to compose
+ * @returns composed validation
+ */
+ static compose(...functions) {
+ return function composedValidation(value) {
+ for (const fn of functions) {
+ const result = fn(value);
+ if (typeof result === 'string' && result.length > 0) {
+ return result;
+ };
+ };
+ };
+ };
+
+ /**
+ * Check the value is a string
+ * @param value
+ * @returns
+ */
+ static isString(value: unknown): string | undefined {
+ return typeof value === 'string' ? undefined : "Value is not a string.";
+ };
+
+ /**
+ * Check the string has no spaces
+ * @param value
+ * @returns
+ */
+ static hasNoSpaces(value: string): string | undefined {
+ return /^\S*$/.test(value) ? undefined : "No whitespaces allowed.";
+ };
+
+ /**
+ * Check the string has no empty
+ * @param value
+ * @returns
+ */
+ static isNotEmptyString(value: string): string | undefined {
+ if (typeof value === 'string') {
+ if (value.length === 0) {
+ return "Value can not be empty."
+ } else {
+ return undefined;
+ }
+ };
+ };
+
+ /**
+ * Check the number of string lines is limited
+ * @param options
+ * @returns
+ */
+ static multipleLinesString(options: { minRows?: number, maxRows?: number, maxLength?: number } = {}) {
+ return function (value: number) {
+ const lines = value.split(/\r\n|\r|\n/).length;
+ if (typeof options.maxLength !== 'undefined' && value.split('\n').some(line => line.length > options.maxLength)) {
+ return `The maximum length of a line is ${options.maxLength} characters.`;
+ };
+ if (typeof options.minRows !== 'undefined' && lines < options.minRows) {
+ return `The string should have more or ${options.minRows} line/s.`;
+ };
+ if (typeof options.maxRows !== 'undefined' && lines > options.maxRows) {
+ return `The string should have less or equal to ${options.maxRows} line/s.`;
+ };
+ }
+ };
+
+ /**
+ * Creates a function that checks the string does not contain some characters
+ * @param invalidCharacters
+ * @returns
+ */
+ static hasNotInvalidCharacters(...invalidCharacters: string[]) {
+ return function (value: string): string | undefined {
+ return invalidCharacters.some(invalidCharacter => value.includes(invalidCharacter))
+ ? `It can't contain invalid characters: ${invalidCharacters.join(', ')}.`
+ : undefined;
+ };
+ };
+
+ /**
+ * Creates a function that checks the string does not start with a substring
+ * @param invalidStartingCharacters
+ * @returns
+ */
+ static noStartsWithString(...invalidStartingCharacters: string[]) {
+ return function (value: string): string | undefined {
+ return invalidStartingCharacters.some(invalidStartingCharacter => value.startsWith(invalidStartingCharacter))
+ ? `It can't start with: ${invalidStartingCharacters.join(', ')}.`
+ : undefined;
+ };
+ };
+
+ /**
+ * Creates a function that checks the string is not equals to some values
+ * @param invalidLiterals
+ * @returns
+ */
+ static noLiteralString(...invalidLiterals: string[]) {
+ return function (value: string): string | undefined {
+ return invalidLiterals.some(invalidLiteral => value === invalidLiteral)
+ ? `It can't be: ${invalidLiterals.join(', ')}.`
+ : undefined;
+ };
+ };
+
+ /**
+ * Check the value is a boolean
+ * @param value
+ * @returns
+ */
+ static isBoolean(value: string): string | undefined {
+ return typeof value === 'boolean'
+ ? undefined
+ : "It should be a boolean. Allowed values: true or false.";
+ };
+
+ /**
+ * Check the value is a number between some optional limits
+ * @param options
+ * @returns
+ */
+ static number(options: { min?: number, max?: number, integer?: boolean } = {}) {
+ return function (value: number) {
+ if (options.integer
+ && (
+ (typeof value === 'string' ? ['.', ','].some(character => value.includes(character)) : false)
+ || !Number.isInteger(Number(value))
+ )
+ ) {
+ return 'Number should be an integer.'
+ };
+
+ const valueNumber = typeof value === 'string' ? Number(value) : value;
+
+ if (typeof options.min !== 'undefined' && valueNumber < options.min) {
+ return `Value should be greater or equal than ${options.min}.`;
+ };
+ if (typeof options.max !== 'undefined' && valueNumber > options.max) {
+ return `Value should be lower or equal than ${options.max}.`;
+ };
+ };
+ };
+
+ /**
+ * Creates a function that checks if the value is a json
+ * @param validateParsed Optional parameter to validate the parsed object
+ * @returns
+ */
+ static json(validateParsed: (object: any) => string | undefined) {
+ return function (value: string) {
+ let jsonObject;
+ // Try to parse the string as JSON
+ try {
+ jsonObject = JSON.parse(value);
+ } catch (error) {
+ return "Value can't be parsed. There is some error.";
+ };
+
+ return validateParsed ? validateParsed(jsonObject) : undefined;
+ };
+ };
+
+ /**
+ * Creates a function that checks is the value is an array and optionally validates each element
+ * @param validationElement Optional function to validate each element of the array
+ * @returns
+ */
+ static array(validationElement: (json: any) => string | undefined) {
+ return function (value: unknown[]) {
+ // Check the JSON is an array
+ if (!Array.isArray(value)) {
+ return 'Value is not a valid list.';
+ };
+
+ return validationElement
+ ? value.reduce((accum, elementValue) => {
+ if (accum) {
+ return accum;
+ };
+
+ const resultValidationElement = validationElement(elementValue);
+ if (resultValidationElement) {
+ return resultValidationElement;
+ };
+
+ return accum;
+ }, undefined)
+ : undefined;
+ };
+ };
+
+ /**
+ * Creates a function that checks if the value is equal to list of values
+ * @param literals Array of values to compare
+ * @returns
+ */
+ static literal(literals: unknown[]) {
+ return function (value: any): string | undefined {
+ return literals.includes(value) ? undefined : `Invalid value. Allowed values: ${literals.map(String).join(', ')}.`;
+ };
+ };
+
+ // FilePicker
+ static filePickerSupportedExtensions = (extensions: string[]) => (options: { name: string }) => {
+ if (typeof options === 'undefined' || typeof options.name === 'undefined') {
+ return;
+ }
+ if (!extensions.includes(path.extname(options.name))) {
+ return `File extension is invalid. Allowed file extensions: ${extensions.join(', ')}.`;
+ };
+ };
+
+ /**
+ * filePickerFileSize
+ * @param options
+ */
+ static filePickerFileSize = (options: { maxBytes?: number, minBytes?: number, meaningfulUnit?: boolean }) => (value: { size: number }) => {
+ if (typeof value === 'undefined' || typeof value.size === 'undefined') {
+ return;
+ };
+ if (typeof options.minBytes !== 'undefined' && value.size <= options.minBytes) {
+ return `File size should be greater or equal than ${options.meaningfulUnit ? formatBytes(options.minBytes) : `${options.minBytes} bytes`}.`;
+ };
+ if (typeof options.maxBytes !== 'undefined' && value.size >= options.maxBytes) {
+ return `File size should be lower or equal than ${options.meaningfulUnit ? formatBytes(options.maxBytes) : `${options.maxBytes} bytes`}.`;
+ };
+ };
+};
diff --git a/common/services/settings.test.ts b/common/services/settings.test.ts
new file mode 100644
index 0000000000..eeee05d52b
--- /dev/null
+++ b/common/services/settings.test.ts
@@ -0,0 +1,60 @@
+import {
+ formatLabelValuePair,
+ formatSettingValueToFile,
+ getCustomizationSetting
+} from "./settings";
+
+describe('[settings] Methods', () => {
+
+ describe('formatLabelValuePair: Format the label-value pairs used to display the allowed values', () => {
+ it.each`
+ label | value | expected
+ ${'TestLabel'} | ${true} | ${'true (TestLabel)'}
+ ${'true'} | ${true} | ${'true'}
+ `(`label: $label | value: $value | expected: $expected`, ({ label, expected, value }) => {
+ expect(formatLabelValuePair(label, value)).toBe(expected);
+ });
+ });
+
+ describe('formatSettingValueToFile: Format setting values to save in the configuration file', () => {
+ it.each`
+ input | expected
+ ${'test'} | ${'\"test\"'}
+ ${'test space'} | ${'\"test space\"'}
+ ${'test\nnew line'} | ${'\"test\\nnew line\"'}
+ ${''} | ${'\"\"'}
+ ${1} | ${1}
+ ${true} | ${true}
+ ${false} | ${false}
+ ${['test1']} | ${'[\"test1\"]'}
+ ${['test1', 'test2']} | ${'[\"test1\",\"test2\"]'}
+ `(`input: $input | expected: $expected`, ({ input, expected }) => {
+ expect(formatSettingValueToFile(input)).toBe(expected);
+ });
+ });
+
+ describe('getCustomizationSetting: Get the value for the "customization." settings depending on the "customization.enabled" setting', () => {
+ it.each`
+ customizationEnabled | settingKey | configValue | expected
+ ${true} | ${'customization.logo.app'} | ${'custom-image-app.png'} | ${'custom-image-app.png'}
+ ${true} | ${'customization.logo.app'} | ${''} | ${''}
+ ${false} | ${'customization.logo.app'} | ${'custom-image-app.png'} | ${''}
+ ${false} | ${'customization.logo.app'} | ${''} | ${''}
+ ${true} | ${'customization.reports.footer'} | ${'Custom footer'} | ${'Custom footer'}
+ ${true} | ${'customization.reports.footer'} | ${''} | ${'Copyright © 2022 Wazuh, Inc.'}
+ ${false} | ${'customization.reports.footer'} | ${'Custom footer'} | ${'Copyright © 2022 Wazuh, Inc.'}
+ ${false} | ${'customization.reports.footer'} | ${''} | ${'Copyright © 2022 Wazuh, Inc.'}
+ ${false} | ${'customization.reports.footer'} | ${''} | ${'Copyright © 2022 Wazuh, Inc.'}
+ ${true} | ${'customization.reports.header'} | ${'Custom header'} | ${'Custom header'}
+ ${true} | ${'customization.reports.header'} | ${''} | ${'info@wazuh.com\nhttps://wazuh.com'}
+ ${false} | ${'customization.reports.header'} | ${'Custom header'} | ${'info@wazuh.com\nhttps://wazuh.com'}
+ ${false} | ${'customization.reports.header'} | ${''} | ${'info@wazuh.com\nhttps://wazuh.com'}
+ `(`customizationEnabled: $customizationEnabled | settingKey: $settingKey | configValue: $configValue | expected: $expected`, ({ configValue, customizationEnabled, expected, settingKey }) => {
+ const configuration = {
+ 'customization.enabled': customizationEnabled,
+ [settingKey]: configValue
+ };
+ expect(getCustomizationSetting(configuration, settingKey)).toBe(expected);
+ });
+ });
+});
diff --git a/common/services/settings.ts b/common/services/settings.ts
new file mode 100644
index 0000000000..868f54c984
--- /dev/null
+++ b/common/services/settings.ts
@@ -0,0 +1,167 @@
+import {
+ PLUGIN_SETTINGS,
+ PLUGIN_SETTINGS_CATEGORIES,
+ TPluginSetting,
+ TPluginSettingKey,
+ TPluginSettingWithKey
+} from '../constants';
+import { formatBytes } from './file-size';
+
+/**
+ * Look for a configuration category setting by its name
+ * @param categoryTitle
+ * @returns category settings
+ */
+export function getCategorySettingByTitle(categoryTitle: string): any {
+ return Object.entries(PLUGIN_SETTINGS_CATEGORIES).find(([key, category]) => category?.title == categoryTitle)?.[1];
+}
+
+/**
+ * Get the default value of the plugin setting.
+ * @param setting setting key
+ * @returns setting default value. It returns `defaultValueIfNotSet` or `defaultValue`.
+ */
+export function getSettingDefaultValue(settingKey: string): any {
+ return typeof PLUGIN_SETTINGS[settingKey].defaultValueIfNotSet !== 'undefined'
+ ? PLUGIN_SETTINGS[settingKey].defaultValueIfNotSet
+ : PLUGIN_SETTINGS[settingKey].defaultValue;
+};
+
+/**
+ * Get the default settings configuration. key-value pair
+ * @returns an object with key-value pairs whose value is the default one
+ */
+export function getSettingsDefault() : {[key in TPluginSettingKey]: unknown} {
+ return Object.entries(PLUGIN_SETTINGS).reduce((accum, [pluginSettingID, pluginSettingConfiguration]) => ({
+ ...accum,
+ [pluginSettingID]: pluginSettingConfiguration.defaultValue
+ }), {});
+};
+
+/**
+ * Get the settings grouped by category
+ * @returns an object whose keys are the categories and its value is an array of setting of that category
+ */
+export function getSettingsByCategories() : {[key: string]: TPluginSetting[]} {
+ return Object.entries(PLUGIN_SETTINGS).reduce((accum, [pluginSettingID, pluginSettingConfiguration]) => ({
+ ...accum,
+ [pluginSettingConfiguration.category]: [...(accum[pluginSettingConfiguration.category] || []), { ...pluginSettingConfiguration, key: pluginSettingID }]
+ }), {});
+};
+
+/**
+ * Get the plugin settings as an array
+ * @returns an array of plugin setting denifitions including the key
+ */
+export function getSettingsDefaultList(): TPluginSettingWithKey[] {
+ return Object.entries(PLUGIN_SETTINGS).reduce((accum, [pluginSettingID, pluginSettingConfiguration]) => ([
+ ...accum,
+ { ...pluginSettingConfiguration, key: pluginSettingID }
+ ]), []);
+};
+
+/**
+ * Format the plugin setting value received in the backend to store in the plugin configuration file (.yml).
+ * @param value plugin setting value sent to the endpoint
+ * @returns valid value to .yml
+ */
+export function formatSettingValueToFile(value: any) {
+ const formatter = formatSettingValueToFileType[typeof value] || formatSettingValueToFileType.default;
+ return formatter(value);
+};
+
+const formatSettingValueToFileType = {
+ string: (value: string): string => `"${value.replace(/"/,'\\"').replace(/\n/g,'\\n')}"`, // Escape the " character and new line
+ object: (value: any): string => JSON.stringify(value),
+ default: (value: any): any => value
+};
+
+/**
+ * Group the settings by category
+ * @param settings
+ * @returns
+ */
+export function groupSettingsByCategory(settings: TPluginSettingWithKey[]){
+ const settingsSortedByCategories = settings
+ .sort((settingA, settingB) => settingA.key?.localeCompare?.(settingB.key))
+ .reduce((accum, pluginSettingConfiguration) => ({
+ ...accum,
+ [pluginSettingConfiguration.category]: [
+ ...(accum[pluginSettingConfiguration.category] || []),
+ { ...pluginSettingConfiguration }
+ ]
+ }), {});
+
+ return Object.entries(settingsSortedByCategories)
+ .map(([category, settings]) => ({ category, settings }))
+ .filter(categoryEntry => categoryEntry.settings.length);
+};
+
+/**
+ * Get the plugin setting description composed.
+ * @param options
+ * @returns
+ */
+ export function getPluginSettingDescription({description, options}: TPluginSetting): string{
+ return [
+ description,
+ ...(options?.select ? [`Allowed values: ${options.select.map(({text, value}) => formatLabelValuePair(text, value)).join(', ')}.`] : []),
+ ...(options?.switch ? [`Allowed values: ${['enabled', 'disabled'].map(s => formatLabelValuePair(options.switch.values[s].label, options.switch.values[s].value)).join(', ')}.`] : []),
+ ...(options?.number && 'min' in options.number ? [`Minimum value: ${options.number.min}.`] : []),
+ ...(options?.number && 'max' in options.number ? [`Maximum value: ${options.number.max}.`] : []),
+ // File extensions
+ ...(options?.file?.extensions ? [`Supported extensions: ${options.file.extensions.join(', ')}.`] : []),
+ // File recommended dimensions
+ ...(options?.file?.recommended?.dimensions ? [`Recommended dimensions: ${options.file.recommended.dimensions.width}x${options.file.recommended.dimensions.height}${options.file.recommended.dimensions.unit || ''}.`] : []),
+ // File size
+ ...((options?.file?.size && typeof options.file.size.minBytes !== 'undefined') ? [`Minimum file size: ${formatBytes(options.file.size.minBytes)}.`] : []),
+ ...((options?.file?.size && typeof options.file.size.maxBytes !== 'undefined') ? [`Maximum file size: ${formatBytes(options.file.size.maxBytes)}.`] : []),
+ // Multi line text
+ ...((options?.maxRows && typeof options.maxRows !== 'undefined' ? [`Maximum amount of lines: ${options.maxRows}.`] : [])),
+ ...((options?.minRows && typeof options.minRows !== 'undefined' ? [`Minimum amount of lines: ${options.minRows}.`] : [])),
+ ...((options?.maxLength && typeof options.maxLength !== 'undefined' ? [`Maximum lines length is ${options.maxLength} characters.`] : [])),
+ ].join(' ');
+};
+
+/**
+ * Format the pair value-label to display the pair. If label and the string of value are equals, only displays the value, if not, displays both.
+ * @param value
+ * @param label
+ * @returns
+ */
+export function formatLabelValuePair(label, value){
+ return label !== `${value}`
+ ? `${value} (${label})`
+ : `${value}`
+};
+
+/**
+ * Get the configuration value if the customization is enabled.
+ * @param configuration JSON object from `wazuh.yml`
+ * @param settingKey key of the setting
+ * @returns
+ */
+export function getCustomizationSetting(configuration: {[key: string]: any }, settingKey: string): any {
+ const isCustomizationEnabled = typeof configuration['customization.enabled'] === 'undefined'
+ ? getSettingDefaultValue('customization.enabled')
+ : configuration['customization.enabled'];
+ const defaultValue = getSettingDefaultValue(settingKey);
+
+ if ( isCustomizationEnabled && settingKey.startsWith('customization') && settingKey !== 'customization.enabled'){
+ return (typeof configuration[settingKey] !== 'undefined' ? resolveEmptySetting(settingKey, configuration[settingKey]) : defaultValue);
+ }else{
+ return defaultValue;
+ };
+};
+
+/**
+ * Returns the default value if not set when the setting is an empty string
+ * @param settingKey plugin setting
+ * @param value value of the plugin setting
+ * @returns
+ */
+function resolveEmptySetting(settingKey: string, value : unknown){
+ return typeof value === 'string' && value.length === 0 && PLUGIN_SETTINGS[settingKey].defaultValueIfNotSet
+ ? getSettingDefaultValue(settingKey)
+ : value;
+};
diff --git a/docker/.gitignore b/docker/.gitignore
index 18465d8ec4..0ea4bcb818 100644
--- a/docker/.gitignore
+++ b/docker/.gitignore
@@ -1,3 +1,4 @@
*.zip
*.deb
*.rpm
+.DS_Store
\ No newline at end of file
diff --git a/docker/README.md b/docker/README.md
index 6ae7fb549b..2cb18f7984 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -19,19 +19,6 @@ In general, the environment consist of:
## Pre-requisites
-> **IMPORTANT**: you will need 2 copies of the Wazuh Kibana App repository, one
-> for the Docker environments, and other one for the plugin source code in the
-> required branch (`4.x-7.16`, `4.x-wzd`, ...). Our recommendation is:
->
-> - **wazuh-kibana-docker** : on the master branch.
-> - **wazuh-kibana-app** : on any development branch. This one will be used
-> as source code and mounted as volume in the
-> platform's container.
->
-> In future releases, the containers (`4.5`) and higher, we expect that every
-> development branch will contain this folder and this duplication won't be
-> necessary anymore.
-
1. Create the `devel` network:
```bash
@@ -166,9 +153,16 @@ To setup the crendentials (**this only has to be done once**):
To build an image, use the docker build command like:
+Use the `--build-arg` flag to specify the version of Node and the version of
+the platform. The version of Node to use is defined in the `.nvmrc` file. Use
+the Node version defined in that file for the target platform version, as the
+version of Node might be increased between platfform's versions.
+
+For example, to build the image for OpenSearch Dashboards `2.6.0`:
+
```bash
cd images
-docker build -t quay.io/wazuh/image-name:version -f image-name-version.Dockerfile .
+docker build --build-arg NODE_VERSION=14.20.1 --build-arg OPENSEARCH_VERSION=2.6.0 -t quay.io/wazuh/osd-dev:2.6.0 -f osd-dev.Dockerfile .
cd ..
```
diff --git a/docker/images/kbn-dev.Dockerfile b/docker/images/kbn-dev.Dockerfile
new file mode 100644
index 0000000000..7c1275168d
--- /dev/null
+++ b/docker/images/kbn-dev.Dockerfile
@@ -0,0 +1,22 @@
+# Usage: docker build --build-arg NODE_VERSION=16.17.1 --build-arg KIBANA_VERSION=7.17.7 -t quay.io/wazuh/kbn-dev:7.17.7 -f kbn-dev.Dockerfile .
+
+ARG NODE_VERSION
+FROM node:${NODE_VERSION} AS base
+RUN npm install --global @bazel/bazelisk@1.11.0
+ARG KIBANA_VERSION
+USER node
+RUN git clone --depth 1 --branch v${KIBANA_VERSION} https://github.com/elastic/kibana /home/node/kbn
+RUN chown node.node /home/node/kbn
+
+WORKDIR /home/node/kbn
+RUN yarn kbn bootstrap
+RUN yarn config set registry http://host.docker.internal:4873 && \
+ sed -i 's/https:\/\/registry.yarnpkg.com/http:\/\/host.docker.internal:4873/g' yarn.lock
+RUN rm -rf /home/node/.cache/yarn && rm -rf /home/node/.cache/Cypress && rm -rf /home/node/.cache/ms-playwright
+RUN mkdir -p /home/node/kbn/data/wazuh/config
+
+FROM node:${NODE_VERSION}
+USER node
+COPY --from=base /home/node/ /home/node/
+WORKDIR /home/node/kbn
+
diff --git a/docker/images/osd-1.2-dev.Dockerfile b/docker/images/osd-1.2-dev.Dockerfile
deleted file mode 100644
index da6f1333ed..0000000000
--- a/docker/images/osd-1.2-dev.Dockerfile
+++ /dev/null
@@ -1,22 +0,0 @@
-FROM node:10.24.1 AS builder-osd-1.2.0
-USER node
-RUN git clone --depth 1 --branch 1.2.0 https://github.com/opensearch-project/OpenSearch-Dashboards.git /home/node/kbn
-RUN chown node.node /home/node/kbn
-
-WORKDIR /home/node/kbn
-RUN yarn config set registry http://host.docker.internal:4873 && \
- sed -i 's/https:\/\/registry.yarnpkg.com/http:\/\/host.docker.internal:4873/g' yarn.lock && \
- yarn osd bootstrap --production
-
-WORKDIR /home/node/kbn/plugins
-RUN git clone --depth 1 --branch 1.2 https://github.com/opensearch-project/security-dashboards-plugin.git
-WORKDIR /home/node/kbn/plugins/security-dashboards-plugin
-RUN yarn install
-
-RUN mkdir -p /home/node/kbn/data/wazuh/config
-
-FROM node:10.24.1
-USER node
-COPY --from=builder-osd-1.2.0 /home/node/kbn /home/node/kbn
-WORKDIR /home/node/kbn
-
diff --git a/docker/images/osd-2.0-dev.Dockerfile b/docker/images/osd-2.0-dev.Dockerfile
deleted file mode 100644
index fb7f1a4a2d..0000000000
--- a/docker/images/osd-2.0-dev.Dockerfile
+++ /dev/null
@@ -1,22 +0,0 @@
-FROM node:14.19.1 AS builder-osd-2.0.0
-USER node
-RUN git clone --depth 1 --branch 2.0.0 https://github.com/opensearch-project/OpenSearch-Dashboards.git /home/node/kbn
-RUN chown node.node /home/node/kbn
-
-WORKDIR /home/node/kbn
-RUN yarn config set registry http://host.docker.internal:4873 && \
- sed -i 's/https:\/\/registry.yarnpkg.com/http:\/\/host.docker.internal:4873/g' yarn.lock && \
- yarn osd bootstrap --production
-
-WORKDIR /home/node/kbn/plugins
-RUN git clone --depth 1 --branch 2.0.0.0 https://github.com/opensearch-project/security-dashboards-plugin.git
-WORKDIR /home/node/kbn/plugins/security-dashboards-plugin
-RUN yarn install
-
-RUN mkdir -p /home/node/kbn/data/wazuh/config
-
-FROM node:14.19.1
-USER node
-COPY --from=builder-osd-2.0.0 /home/node/kbn /home/node/kbn
-WORKDIR /home/node/kbn
-
diff --git a/docker/images/osd-2.1.0-dev.Dockerfile b/docker/images/osd-2.1.0-dev.Dockerfile
deleted file mode 100644
index 413e476129..0000000000
--- a/docker/images/osd-2.1.0-dev.Dockerfile
+++ /dev/null
@@ -1,22 +0,0 @@
-FROM node:14.19.1 AS builder-osd-2.1.0
-USER node
-RUN git clone --depth 1 --branch 2.1.0 https://github.com/opensearch-project/OpenSearch-Dashboards.git /home/node/kbn
-RUN chown node.node /home/node/kbn
-
-WORKDIR /home/node/kbn
-RUN yarn config set registry http://host.docker.internal:4873 && \
- sed -i 's/https:\/\/registry.yarnpkg.com/http:\/\/host.docker.internal:4873/g' yarn.lock && \
- yarn osd bootstrap --production
-
-WORKDIR /home/node/kbn/plugins
-RUN git clone --depth 1 --branch 2.1.0.0 https://github.com/opensearch-project/security-dashboards-plugin.git
-WORKDIR /home/node/kbn/plugins/security-dashboards-plugin
-RUN yarn install
-
-RUN mkdir -p /home/node/kbn/data/wazuh/config
-
-FROM node:14.19.1
-USER node
-COPY --from=builder-osd-2.1.0 /home/node/kbn /home/node/kbn
-WORKDIR /home/node/kbn
-
diff --git a/docker/images/osd-2.2.1-dev.Dockerfile b/docker/images/osd-2.2.1-dev.Dockerfile
deleted file mode 100644
index 86b0478461..0000000000
--- a/docker/images/osd-2.2.1-dev.Dockerfile
+++ /dev/null
@@ -1,22 +0,0 @@
-FROM node:14.20.0 AS builder-osd-2.2.1
-USER node
-RUN git clone --depth 1 --branch 2.2.1 https://github.com/opensearch-project/OpenSearch-Dashboards.git /home/node/kbn
-RUN chown node.node /home/node/kbn
-
-WORKDIR /home/node/kbn
-RUN yarn config set registry http://host.docker.internal:4873 && \
- sed -i 's/https:\/\/registry.yarnpkg.com/http:\/\/host.docker.internal:4873/g' yarn.lock && \
- yarn osd bootstrap --production
-
-WORKDIR /home/node/kbn/plugins
-RUN git clone --depth 1 --branch 2.2.1.0 https://github.com/opensearch-project/security-dashboards-plugin.git
-WORKDIR /home/node/kbn/plugins/security-dashboards-plugin
-RUN yarn install
-
-RUN mkdir -p /home/node/kbn/data/wazuh/config
-
-FROM node:14.20.0
-USER node
-COPY --from=builder-osd-2.2.1 /home/node/kbn /home/node/kbn
-WORKDIR /home/node/kbn
-
diff --git a/docker/images/osd-2.3.0-dev.Dockerfile b/docker/images/osd-2.3.0-dev.Dockerfile
deleted file mode 100644
index 09e74fa618..0000000000
--- a/docker/images/osd-2.3.0-dev.Dockerfile
+++ /dev/null
@@ -1,21 +0,0 @@
-FROM node:14.20.0 AS builder-osd-2.3.0
-USER node
-RUN git clone --depth 1 --branch 2.3.0 https://github.com/opensearch-project/OpenSearch-Dashboards.git /home/node/kbn
-RUN chown node.node /home/node/kbn
-
-WORKDIR /home/node/kbn
-RUN yarn config set registry http://host.docker.internal:4873 && \
- sed -i 's/https:\/\/registry.yarnpkg.com/http:\/\/host.docker.internal:4873/g' yarn.lock && \
- yarn osd bootstrap --production
-
-WORKDIR /home/node/kbn/plugins
-RUN git clone --depth 1 --branch 2.3.0.0 https://github.com/opensearch-project/security-dashboards-plugin.git
-WORKDIR /home/node/kbn/plugins/security-dashboards-plugin
-RUN yarn install
-
-RUN mkdir -p /home/node/kbn/data/wazuh/config
-
-FROM node:14.20.0
-USER node
-COPY --from=builder-osd-2.3.0 /home/node/kbn /home/node/kbn
-WORKDIR /home/node/kbn
diff --git a/docker/images/osd-dev.Dockerfile b/docker/images/osd-dev.Dockerfile
new file mode 100644
index 0000000000..45121a2630
--- /dev/null
+++ b/docker/images/osd-dev.Dockerfile
@@ -0,0 +1,26 @@
+# Usage: docker build --build-arg NODE_VERSION=14.20.1 --build-arg OPENSEARCH_VERSION=2.5.0 -t quay.io/wazuh/osd-dev:2.5.0 -f osd-dev.Dockerfile .
+
+ARG NODE_VERSION
+FROM node:${NODE_VERSION} AS base
+ARG OPENSEARCH_VERSION
+USER node
+RUN git clone --depth 1 --branch ${OPENSEARCH_VERSION} https://github.com/opensearch-project/OpenSearch-Dashboards.git /home/node/kbn
+RUN chown node.node /home/node/kbn
+
+WORKDIR /home/node/kbn
+RUN yarn osd bootstrap --production
+
+WORKDIR /home/node/kbn/plugins
+RUN git clone --depth 1 --branch ${OPENSEARCH_VERSION}.0 https://github.com/opensearch-project/security-dashboards-plugin.git
+WORKDIR /home/node/kbn/plugins/security-dashboards-plugin
+RUN yarn install
+
+RUN yarn config set registry http://host.docker.internal:4873 && \
+ sed -i 's/https:\/\/registry.yarnpkg.com/http:\/\/host.docker.internal:4873/g' yarn.lock
+
+RUN mkdir -p /home/node/kbn/data/wazuh/config
+
+FROM node:${NODE_VERSION}
+USER node
+COPY --from=base /home/node/kbn /home/node/kbn
+WORKDIR /home/node/kbn
diff --git a/docker/images/wzd-1.2-dev.Dockerfile b/docker/images/wzd-1.2-dev.Dockerfile
deleted file mode 100644
index da6f1333ed..0000000000
--- a/docker/images/wzd-1.2-dev.Dockerfile
+++ /dev/null
@@ -1,22 +0,0 @@
-FROM node:10.24.1 AS builder-osd-1.2.0
-USER node
-RUN git clone --depth 1 --branch 1.2.0 https://github.com/opensearch-project/OpenSearch-Dashboards.git /home/node/kbn
-RUN chown node.node /home/node/kbn
-
-WORKDIR /home/node/kbn
-RUN yarn config set registry http://host.docker.internal:4873 && \
- sed -i 's/https:\/\/registry.yarnpkg.com/http:\/\/host.docker.internal:4873/g' yarn.lock && \
- yarn osd bootstrap --production
-
-WORKDIR /home/node/kbn/plugins
-RUN git clone --depth 1 --branch 1.2 https://github.com/opensearch-project/security-dashboards-plugin.git
-WORKDIR /home/node/kbn/plugins/security-dashboards-plugin
-RUN yarn install
-
-RUN mkdir -p /home/node/kbn/data/wazuh/config
-
-FROM node:10.24.1
-USER node
-COPY --from=builder-osd-1.2.0 /home/node/kbn /home/node/kbn
-WORKDIR /home/node/kbn
-
diff --git a/docker/imposter/agents/agent.json b/docker/imposter/agents/agent.json
index d11371299b..0389d55c2c 100644
--- a/docker/imposter/agents/agent.json
+++ b/docker/imposter/agents/agent.json
@@ -1,39 +1,36 @@
{
- "data": {
- "affected_items": [
- {
- "os": {
- "arch": "x86_64",
- "codename": "stretch",
- "major": "9",
- "name": "Debian GNU/Linux",
- "platform": "debian",
- "uname": "Linux |ip-10-0-1-106 |4.9.0-9-amd64 |#1 SMP Debian 4.9.168-1+deb9u2 (2019-05-13) |x86_64",
- "version": "9"
- },
- "ip": "10.0.1.106",
- "configSum": "6f4293818ef64291ca53727fb9ab8958",
- "mergedSum": "7976a83d1aebcca09bc14459b5518ed5",
- "id": "001",
- "registerIP": "any",
- "dateAdd": "2022-08-25T16:25:53Z",
- "disconnection_time": "2022-08-25T16:36:35Z",
- "name": "Debian",
- "status": "active",
- "manager": "wazuh-manager-master-0",
- "node_name": "master",
- "group": [
- "default",
- "debian"
- ],
- "lastKeepAlive": "2022-09-12T08:48:40Z",
- "version": "Wazuh v4.3.7"
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "All selected agents information was returned",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "os": {
+ "arch": "x86_64",
+ "codename": "stretch",
+ "major": "9",
+ "name": "Debian GNU/Linux",
+ "platform": "debian",
+ "uname": "Linux |ip-10-0-1-106 |4.9.0-9-amd64 |#1 SMP Debian 4.9.168-1+deb9u2 (2019-05-13) |x86_64",
+ "version": "9"
+ },
+ "ip": "10.0.1.106",
+ "configSum": "6f4293818ef64291ca53727fb9ab8958",
+ "mergedSum": "7976a83d1aebcca09bc14459b5518ed5",
+ "id": "001",
+ "registerIP": "any",
+ "dateAdd": "2022-08-25T16:25:53Z",
+ "disconnection_time": "2022-08-25T16:36:35Z",
+ "name": "Debian",
+ "status": "active",
+ "manager": "wazuh-manager-master-0",
+ "node_name": "master",
+ "group": ["default", "debian"],
+ "lastKeepAlive": "2022-09-12T08:48:40Z",
+ "version": "Wazuh v4.5.0"
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "All selected agents information was returned",
+ "error": 0
+}
diff --git a/docker/imposter/agents/agents.js b/docker/imposter/agents/agents.js
index bebe862c54..294423b5ce 100644
--- a/docker/imposter/agents/agents.js
+++ b/docker/imposter/agents/agents.js
@@ -1,9 +1,9 @@
if (context.request.queryParams.agents_list !== undefined) {
- respond()
- .withStatusCode(200)
- .withFile('agents/agent.json')
+ respond()
+ .withStatusCode(200)
+ .withFile('agents/agent.json')
} else {
- respond()
- .withStatusCode(200)
- .withFile('agents/agents.json')
-}
\ No newline at end of file
+ respond()
+ .withStatusCode(200)
+ .withFile('agents/agents.json')
+}
diff --git a/docker/imposter/agents/agents.json b/docker/imposter/agents/agents.json
index 759a196fd0..7f3c3182e5 100644
--- a/docker/imposter/agents/agents.json
+++ b/docker/imposter/agents/agents.json
@@ -1,92 +1,95 @@
{
- "data": {
- "affected_items": [
- {
- "os": {
- "arch": "x86_64",
- "major": "2",
- "name": "Amazon Linux",
- "platform": "amzn",
- "uname": "Linux |wazuh-manager-master-0 |4.14.114-105.126.amzn2.x86_64 |#1 SMP Tue May 7 02:26:40 UTC 2019 |x86_64",
- "version": "2"
- },
- "ip": "127.0.0.1",
- "id": "000",
- "registerIP": "127.0.0.1",
- "dateAdd": "2022-08-25T16:17:46Z",
- "name": "wazuh-manager-master-0",
- "status": "active",
- "manager": "wazuh-manager-master-0",
- "node_name": "master",
- "lastKeepAlive": "9999-12-31T23:59:59Z",
- "version": "Wazuh v4.4.0",
- "group_config_status": "synced"
- },{
- "os": {
- "arch": "x86_64",
- "major": "2",
- "name": "Amazon Linux",
- "platform": "amzn",
- "uname": "Linux |wazuh-manager-master-0 |4.14.114-105.126.amzn2.x86_64 |#1 SMP Tue May 7 02:26:40 UTC 2019 |x86_64",
- "version": "2"
- },
- "ip": "127.0.0.1",
- "id": "001",
- "registerIP": "127.0.0.1",
- "dateAdd": "2022-08-25T16:17:46Z",
- "name": "wazuh-manager-master-0",
- "status": "active",
- "manager": "wazuh-manager-master-0",
- "node_name": "master",
- "lastKeepAlive": "9999-12-31T23:59:59Z",
- "version": "Wazuh v4.4.0",
- "group_config_status": "not synced"
- },{
- "os": {
- "arch": "x86_64",
- "major": "2",
- "name": "Amazon Linux",
- "platform": "amzn",
- "uname": "Linux |wazuh-manager-master-0 |4.14.114-105.126.amzn2.x86_64 |#1 SMP Tue May 7 02:26:40 UTC 2019 |x86_64",
- "version": "2"
- },
- "ip": "127.0.0.1",
- "id": "002",
- "registerIP": "127.0.0.1",
- "dateAdd": "2022-08-25T16:17:46Z",
- "name": "wazuh-manager-master-0",
- "status": "active",
- "manager": "wazuh-manager-master-0",
- "node_name": "master",
- "lastKeepAlive": "9999-12-31T23:59:59Z",
- "version": "Wazuh v4.4.0",
- "group_config_status": "synced"
- },{
- "os": {
- "arch": "x86_64",
- "major": "2",
- "name": "Amazon Linux",
- "platform": "amzn",
- "uname": "Linux |wazuh-manager-master-0 |4.14.114-105.126.amzn2.x86_64 |#1 SMP Tue May 7 02:26:40 UTC 2019 |x86_64",
- "version": "2"
- },
- "ip": "127.0.0.1",
- "id": "003",
- "registerIP": "127.0.0.1",
- "dateAdd": "2022-08-25T16:17:46Z",
- "name": "wazuh-manager-master-0",
- "status": "active",
- "manager": "wazuh-manager-master-0",
- "node_name": "master",
- "lastKeepAlive": "9999-12-31T23:59:59Z",
- "version": "Wazuh v4.4.0",
- "group_config_status": "not synced"
- }
- ],
- "total_affected_items": 4,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "All selected agents information was returned",
- "error": 0
+ "data": {
+ "affected_items": [
+ {
+ "os": {
+ "arch": "x86_64",
+ "major": "2",
+ "name": "Amazon Linux",
+ "platform": "amzn",
+ "uname": "Linux |wazuh-manager-master-0 |4.14.114-105.126.amzn2.x86_64 |#1 SMP Tue May 7 02:26:40 UTC 2019 |x86_64",
+ "version": "2"
+ },
+ "ip": "127.0.0.1",
+ "id": "000",
+ "registerIP": "127.0.0.1",
+ "dateAdd": "2022-08-25T16:17:46Z",
+ "name": "wazuh-manager-master-0",
+ "status": "active",
+ "manager": "wazuh-manager-master-0",
+ "node_name": "master",
+ "lastKeepAlive": "9999-12-31T23:59:59Z",
+ "version": "Wazuh v4.5.0",
+ "group_config_status": "synced"
+ },
+ {
+ "os": {
+ "arch": "x86_64",
+ "major": "2",
+ "name": "Amazon Linux",
+ "platform": "amzn",
+ "uname": "Linux |wazuh-manager-master-0 |4.14.114-105.126.amzn2.x86_64 |#1 SMP Tue May 7 02:26:40 UTC 2019 |x86_64",
+ "version": "2"
+ },
+ "ip": "127.0.0.1",
+ "id": "001",
+ "registerIP": "127.0.0.1",
+ "dateAdd": "2022-08-25T16:17:46Z",
+ "name": "wazuh-manager-master-0",
+ "status": "active",
+ "manager": "wazuh-manager-master-0",
+ "node_name": "master",
+ "lastKeepAlive": "9999-12-31T23:59:59Z",
+ "version": "Wazuh v4.5.0",
+ "group_config_status": "not synced"
+ },
+ {
+ "os": {
+ "arch": "x86_64",
+ "major": "2",
+ "name": "Amazon Linux",
+ "platform": "amzn",
+ "uname": "Linux |wazuh-manager-master-0 |4.14.114-105.126.amzn2.x86_64 |#1 SMP Tue May 7 02:26:40 UTC 2019 |x86_64",
+ "version": "2"
+ },
+ "ip": "127.0.0.1",
+ "id": "002",
+ "registerIP": "127.0.0.1",
+ "dateAdd": "2022-08-25T16:17:46Z",
+ "name": "wazuh-manager-master-0",
+ "status": "active",
+ "manager": "wazuh-manager-master-0",
+ "node_name": "master",
+ "lastKeepAlive": "9999-12-31T23:59:59Z",
+ "version": "Wazuh v4.5.0",
+ "group_config_status": "synced"
+ },
+ {
+ "os": {
+ "arch": "x86_64",
+ "major": "2",
+ "name": "Amazon Linux",
+ "platform": "amzn",
+ "uname": "Linux |wazuh-manager-master-0 |4.14.114-105.126.amzn2.x86_64 |#1 SMP Tue May 7 02:26:40 UTC 2019 |x86_64",
+ "version": "2"
+ },
+ "ip": "127.0.0.1",
+ "id": "003",
+ "registerIP": "127.0.0.1",
+ "dateAdd": "2022-08-25T16:17:46Z",
+ "name": "wazuh-manager-master-0",
+ "status": "active",
+ "manager": "wazuh-manager-master-0",
+ "node_name": "master",
+ "lastKeepAlive": "9999-12-31T23:59:59Z",
+ "version": "Wazuh v4.5.0",
+ "group_config_status": "not synced"
+ }
+ ],
+ "total_affected_items": 4,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "All selected agents information was returned",
+ "error": 0
}
diff --git a/docker/imposter/agents/summary_status.json b/docker/imposter/agents/summary_status.json
new file mode 100644
index 0000000000..756f178e4b
--- /dev/null
+++ b/docker/imposter/agents/summary_status.json
@@ -0,0 +1,10 @@
+{
+ "data": {
+ "active": 3,
+ "disconnected": 1,
+ "never_connected": 0,
+ "pending": 0,
+ "total": 4
+ },
+ "error": 0
+}
diff --git a/docker/imposter/api-info/api_info.json b/docker/imposter/api-info/api_info.json
index ecd9981120..0abbd7603f 100644
--- a/docker/imposter/api-info/api_info.json
+++ b/docker/imposter/api-info/api_info.json
@@ -1,10 +1,10 @@
{
"data": {
"title": "Wazuh API REST",
- "api_version": "4.4.0",
- "revision": 4400,
+ "api_version": "4.5.0",
+ "revision": 4500,
"license_name": "GPL 2.0",
- "license_url": "https://github.com/wazuh/wazuh/blob/4.4/LICENSE",
+ "license_url": "https://github.com/wazuh/wazuh/blob/4.5/LICENSE",
"hostname": "imposter",
"timestamp": "2022-06-13T17:20:03Z"
},
diff --git a/docker/imposter/cluster/cluster-logs.js b/docker/imposter/cluster/cluster-logs.js
new file mode 100644
index 0000000000..0ecd3b51b4
--- /dev/null
+++ b/docker/imposter/cluster/cluster-logs.js
@@ -0,0 +1,13 @@
+var search = context.request.queryParams.search
+
+switch (search) {
+ case 'nologs':
+ respond().withStatusCode(200).withFile('cluster/cluster_no_logs.json');
+ break;
+ case undefined:
+ respond().withStatusCode(200).withFile('cluster/cluster_logs.json');
+ break;
+ default:
+ respond().withStatusCode(200).withFile('cluster/cluster_logs.json');
+ break;
+}
diff --git a/docker/imposter/cluster/cluster_logs.json b/docker/imposter/cluster/cluster_logs.json
new file mode 100644
index 0000000000..b2c6ca66b3
--- /dev/null
+++ b/docker/imposter/cluster/cluster_logs.json
@@ -0,0 +1,29 @@
+{
+ "data": {
+ "affected_items": [
+ {
+ "timestamp": "2021-05-27T12:18:08Z",
+ "tag": "wazuh-remoted",
+ "level": "debug",
+ "description": " TCP socket 20 already in keystore. Updating..."
+ },
+ {
+ "timestamp": "2021-05-27T12:18:08Z",
+ "tag": "wazuh-remoted",
+ "level": "debug",
+ "description": " Agent '003' group is 'default'"
+ },
+ {
+ "timestamp": "2021-05-27T12:18:08Z",
+ "tag": "wazuh-remoted",
+ "level": "debug",
+ "description": " Agent '003' with group 'default' file 'merged.mg' MD5 '9a016508cea1e997ab8569f5cfab30f5'"
+ }
+ ],
+ "total_affected_items": 3,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Logs were successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/cluster_no_logs.json b/docker/imposter/cluster/cluster_no_logs.json
new file mode 100644
index 0000000000..d36e730a91
--- /dev/null
+++ b/docker/imposter/cluster/cluster_no_logs.json
@@ -0,0 +1,10 @@
+{
+ "data": {
+ "affected_items": [],
+ "total_affected_items": 0,
+ "failed_items": [],
+ "total_failed_items": 0
+ },
+ "message": "Logs read successfully in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/cluster_node_info.js b/docker/imposter/cluster/cluster_node_info.js
index 3a90b39d3f..0fc487f1a4 100644
--- a/docker/imposter/cluster/cluster_node_info.js
+++ b/docker/imposter/cluster/cluster_node_info.js
@@ -5,24 +5,20 @@ var callRestart = storeWazuh.load('callRestart');
if (callRestart) {
- if(attemptRestart < 10){
- storeWazuh.save('attempt', attemptRestart + 1);
- respond()
- .withStatusCode(200)
- .withFile('cluster/cluster_node_info_no_restart.json')
- } else {
- storeWazuh.save('attempt', 0);
- storeWazuh.save('callRestart', false);
- respond()
- .withStatusCode(200)
- .withFile('cluster/cluster_node_info.json')
- }
-} else {
+ if (attemptRestart < 10) {
+ storeWazuh.save('attempt', attemptRestart + 1);
+ respond()
+ .withStatusCode(200)
+ .withFile('cluster/cluster_node_info_no_restart.json')
+ } else {
+ storeWazuh.save('attempt', 0);
+ storeWazuh.save('callRestart', false);
respond()
- .withStatusCode(200)
- .withFile('cluster/cluster_node_info.json')
+ .withStatusCode(200)
+ .withFile('cluster/cluster_node_info.json')
+ }
+} else {
+ respond()
+ .withStatusCode(200)
+ .withFile('cluster/cluster_node_info.json')
}
-
-
-
-
diff --git a/docker/imposter/cluster/cluster_node_info.json b/docker/imposter/cluster/cluster_node_info.json
index a12f21a54a..db61b8f399 100644
--- a/docker/imposter/cluster/cluster_node_info.json
+++ b/docker/imposter/cluster/cluster_node_info.json
@@ -1,99 +1,102 @@
{
- "data": {
- "affected_items": [
- {
- "name": "master-node",
- "type": "master",
- "version": "4.3.0",
- "ip": "wazuh-master",
- "connection_date": "2020-05-27T10:50:49.175Z"
- },
- {
- "name": "worker1",
- "type": "worker",
- "version": "4.3.0",
- "ip": "172.26.0.7",
- "connection_date": "2021-05-27T10:50:51.342Z"
- },
- {
- "name": "worker2",
- "type": "worker",
- "version": "4.3.0",
- "ip": "172.26.0.6",
- "connection_date": "2021-05-27T10:48:54.093Z"
- },{
- "name": "worker3",
- "type": "worker",
- "version": "4.3.0",
- "ip": "wazuh-worker",
- "connection_date": "2021-05-27T10:50:51.342Z"
- },
- {
- "name": "worker4",
- "type": "worker",
- "version": "4.3.0",
- "ip": "172.26.0.7",
- "connection_date": "2021-05-27T10:50:51.342Z"
- },
- {
- "name": "worker5",
- "type": "worker",
- "version": "4.3.0",
- "ip": "172.26.0.6",
- "connection_date": "2021-05-27T10:48:54.093Z"
- },{
- "name": "worker6",
- "type": "worker",
- "version": "4.3.0",
- "ip": "wazuh-worker",
- "connection_date": "2021-05-27T10:50:51.342Z"
- },
- {
- "name": "worker7",
- "type": "worker",
- "version": "4.3.0",
- "ip": "172.26.0.7",
- "connection_date": "2021-05-27T10:48:54.093Z"
- },
- {
- "name": "worker8",
- "type": "worker",
- "version": "4.3.0",
- "ip": "172.26.0.6",
- "connection_date": "2021-05-27T10:50:51.342Z"
- },
- {
- "name": "worker9",
- "type": "worker",
- "version": "4.3.0",
- "ip": "wazuh-worker",
- "connection_date": "2019-05-27T10:48:54.093Z"
- },
- {
- "name": "worker10",
- "type": "worker",
- "version": "4.3.0",
- "ip": "wazuh-worker",
- "connection_date": "2022-05-27T10:48:54.093Z"
- },
- {
- "name": "worker11",
- "type": "worker",
- "version": "4.3.0",
- "ip": "172.26.0.6",
- "connection_date": "2019-05-27T10:48:54.093Z"
- },{
- "name": "worker12",
- "type": "worker",
- "version": "4.3.0",
- "ip": "wazuh-worker",
- "connection_date": "2021-05-27T10:50:51.342Z"
- }
- ],
- "total_affected_items": 3,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "All selected nodes information was returned",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "name": "master-node",
+ "type": "master",
+ "version": "4.5.0",
+ "ip": "wazuh-master",
+ "connection_date": "2020-05-27T10:50:49.175Z"
+ },
+ {
+ "name": "worker1",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "172.26.0.7",
+ "connection_date": "2021-05-27T10:50:51.342Z"
+ },
+ {
+ "name": "worker2",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "172.26.0.6",
+ "connection_date": "2021-05-27T10:48:54.093Z"
+ },
+ {
+ "name": "worker3",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "wazuh-worker",
+ "connection_date": "2021-05-27T10:50:51.342Z"
+ },
+ {
+ "name": "worker4",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "172.26.0.7",
+ "connection_date": "2021-05-27T10:50:51.342Z"
+ },
+ {
+ "name": "worker5",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "172.26.0.6",
+ "connection_date": "2021-05-27T10:48:54.093Z"
+ },
+ {
+ "name": "worker6",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "wazuh-worker",
+ "connection_date": "2021-05-27T10:50:51.342Z"
+ },
+ {
+ "name": "worker7",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "172.26.0.7",
+ "connection_date": "2021-05-27T10:48:54.093Z"
+ },
+ {
+ "name": "worker8",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "172.26.0.6",
+ "connection_date": "2021-05-27T10:50:51.342Z"
+ },
+ {
+ "name": "worker9",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "wazuh-worker",
+ "connection_date": "2019-05-27T10:48:54.093Z"
+ },
+ {
+ "name": "worker10",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "wazuh-worker",
+ "connection_date": "2022-05-27T10:48:54.093Z"
+ },
+ {
+ "name": "worker11",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "172.26.0.6",
+ "connection_date": "2019-05-27T10:48:54.093Z"
+ },
+ {
+ "name": "worker12",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "wazuh-worker",
+ "connection_date": "2021-05-27T10:50:51.342Z"
+ }
+ ],
+ "total_affected_items": 3,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "All selected nodes information was returned",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/cluster_node_info_no_restart.json b/docker/imposter/cluster/cluster_node_info_no_restart.json
index 4144513435..1bb2dc8d25 100644
--- a/docker/imposter/cluster/cluster_node_info_no_restart.json
+++ b/docker/imposter/cluster/cluster_node_info_no_restart.json
@@ -1,85 +1,88 @@
{
- "data": {
- "affected_items": [
- {
- "name": "master-node",
- "type": "master",
- "version": "4.3.0",
- "ip": "wazuh-master",
- "connection_date": "2021-05-27T10:50:49.175Z"
- },
- {
- "name": "worker1",
- "type": "worker",
- "version": "4.3.0",
- "ip": "172.26.0.7",
- "connection_date": "2021-05-27T10:50:51.342Z"
- },
- {
- "name": "worker2",
- "type": "worker",
- "version": "4.3.0",
- "ip": "172.26.0.6",
- "connection_date": "2021-05-27T10:48:54.093Z"
- },{
- "name": "worker3",
- "type": "worker",
- "version": "4.3.0",
- "ip": "wazuh-worker",
- "connection_date": "2021-05-27T10:50:51.342Z"
- },
- {
- "name": "worker4",
- "type": "worker",
- "version": "4.3.0",
- "ip": "172.26.0.7",
- "connection_date": "2021-05-27T10:50:51.342Z"
- },
- {
- "name": "worker5",
- "type": "worker",
- "version": "4.3.0",
- "ip": "172.26.0.6",
- "connection_date": "2021-05-27T10:48:54.093Z"
- },{
- "name": "worker6",
- "type": "worker",
- "version": "4.3.0",
- "ip": "wazuh-worker",
- "connection_date": "2021-05-27T10:50:51.342Z"
- },
- {
- "name": "worker7",
- "type": "worker",
- "version": "4.3.0",
- "ip": "172.26.0.7",
- "connection_date": "2021-05-27T10:48:54.093Z"
- },
- {
- "name": "worker8",
- "type": "worker",
- "version": "4.3.0",
- "ip": "172.26.0.6",
- "connection_date": "2021-05-27T10:50:51.342Z"
- },
- {
- "name": "worker11",
- "type": "worker",
- "version": "4.3.0",
- "ip": "172.26.0.6",
- "connection_date": "2019-05-27T10:48:54.093Z"
- },{
- "name": "worker12",
- "type": "worker",
- "version": "4.3.0",
- "ip": "wazuh-worker",
- "connection_date": "2019-05-27T10:50:51.342Z"
- }
- ],
- "total_affected_items": 3,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "All selected nodes information was returned",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "name": "master-node",
+ "type": "master",
+ "version": "4.5.0",
+ "ip": "wazuh-master",
+ "connection_date": "2021-05-27T10:50:49.175Z"
+ },
+ {
+ "name": "worker1",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "172.26.0.7",
+ "connection_date": "2021-05-27T10:50:51.342Z"
+ },
+ {
+ "name": "worker2",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "172.26.0.6",
+ "connection_date": "2021-05-27T10:48:54.093Z"
+ },
+ {
+ "name": "worker3",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "wazuh-worker",
+ "connection_date": "2021-05-27T10:50:51.342Z"
+ },
+ {
+ "name": "worker4",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "172.26.0.7",
+ "connection_date": "2021-05-27T10:50:51.342Z"
+ },
+ {
+ "name": "worker5",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "172.26.0.6",
+ "connection_date": "2021-05-27T10:48:54.093Z"
+ },
+ {
+ "name": "worker6",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "wazuh-worker",
+ "connection_date": "2021-05-27T10:50:51.342Z"
+ },
+ {
+ "name": "worker7",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "172.26.0.7",
+ "connection_date": "2021-05-27T10:48:54.093Z"
+ },
+ {
+ "name": "worker8",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "172.26.0.6",
+ "connection_date": "2021-05-27T10:50:51.342Z"
+ },
+ {
+ "name": "worker11",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "172.26.0.6",
+ "connection_date": "2019-05-27T10:48:54.093Z"
+ },
+ {
+ "name": "worker12",
+ "type": "worker",
+ "version": "4.5.0",
+ "ip": "wazuh-worker",
+ "connection_date": "2019-05-27T10:50:51.342Z"
+ }
+ ],
+ "total_affected_items": 3,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "All selected nodes information was returned",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/cluster_restart.js b/docker/imposter/cluster/cluster_restart.js
index e0ac27f989..be0fc66107 100644
--- a/docker/imposter/cluster/cluster_restart.js
+++ b/docker/imposter/cluster/cluster_restart.js
@@ -5,25 +5,25 @@ var callRestart = storeWazuh.load('callRestart');
storeWazuh.save('callRestart', true);
if (context.request.queryParams.nodes_list !== undefined) {
- var resp = {
- "data": {
- "affected_items":
- [
- context.request.queryParams.nodes_list
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "All selected nodes information was returned",
- "error": 0
- }
+ var resp = {
+ "data": {
+ "affected_items":
+ [
+ context.request.queryParams.nodes_list
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "All selected nodes information was returned",
+ "error": 0
+ }
- respond()
- .withStatusCode(200)
- .withData(JSON.stringify(resp))
+ respond()
+ .withStatusCode(200)
+ .withData(JSON.stringify(resp))
} else {
- respond()
- .withStatusCode(200)
- .withFile('cluster/cluster_restart.json')
-}
\ No newline at end of file
+ respond()
+ .withStatusCode(200)
+ .withFile('cluster/cluster_restart.json')
+}
diff --git a/docker/imposter/cluster/cluster_restart.json b/docker/imposter/cluster/cluster_restart.json
index b426e12c66..eac3f9f6bf 100644
--- a/docker/imposter/cluster/cluster_restart.json
+++ b/docker/imposter/cluster/cluster_restart.json
@@ -1,20 +1,19 @@
{
- "data": {
- "affected_items":
- [
- "master-node",
- "worker1",
- "worker2",
- "worker3",
- "worker4",
- "worker5",
- "worker6",
- "worker7"
- ],
- "total_affected_items": 8,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "All selected nodes information was returned",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ "master-node",
+ "worker1",
+ "worker2",
+ "worker3",
+ "worker4",
+ "worker5",
+ "worker6",
+ "worker7"
+ ],
+ "total_affected_items": 8,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "All selected nodes information was returned",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/cluster_status.json b/docker/imposter/cluster/cluster_status.json
new file mode 100644
index 0000000000..f3b1dc0329
--- /dev/null
+++ b/docker/imposter/cluster/cluster_status.json
@@ -0,0 +1,7 @@
+{
+ "data": {
+ "enabled": "yes",
+ "running": "yes"
+ },
+ "error": 0
+}
diff --git a/docker/imposter/cluster/cluster_sync.js b/docker/imposter/cluster/cluster_sync.js
index c2fb62d319..7d5af0b144 100644
--- a/docker/imposter/cluster/cluster_sync.js
+++ b/docker/imposter/cluster/cluster_sync.js
@@ -14,7 +14,3 @@ if(attemptRestart < 5){
.withStatusCode(200)
.withFile('cluster/cluster_sync.json')
}
-
-
-
-
diff --git a/docker/imposter/cluster/cluster_sync.json b/docker/imposter/cluster/cluster_sync.json
index d33d540542..7730681392 100644
--- a/docker/imposter/cluster/cluster_sync.json
+++ b/docker/imposter/cluster/cluster_sync.json
@@ -40,4 +40,4 @@
},
"message": "All selected nodes healthcheck information was returned",
"error": 0
-}
\ No newline at end of file
+}
diff --git a/docker/imposter/cluster/cluster_sync_no_sync.json b/docker/imposter/cluster/cluster_sync_no_sync.json
index d329dc0940..e8243e348d 100644
--- a/docker/imposter/cluster/cluster_sync_no_sync.json
+++ b/docker/imposter/cluster/cluster_sync_no_sync.json
@@ -40,4 +40,4 @@
},
"message": "All selected nodes healthcheck information was returned",
"error": 0
-}
\ No newline at end of file
+}
diff --git a/docker/imposter/cluster/component_configuration.js b/docker/imposter/cluster/component_configuration.js
index 6dcdc1cd4d..31447298a3 100644
--- a/docker/imposter/cluster/component_configuration.js
+++ b/docker/imposter/cluster/component_configuration.js
@@ -1,10 +1,10 @@
var path = context.request.path;
var pathArray = path.split('/')
-pathArray.splice(0,4)
-var pathFile = 'cluster/configuration/'+pathArray.join('_')+'.json'
+pathArray.splice(0, 4)
+var pathFile = 'cluster/configuration/' + pathArray.join('_') + '.json'
console.log(pathFile)
respond()
- .withStatusCode(200)
- .withFile(pathFile)
+ .withStatusCode(200)
+ .withFile(pathFile)
diff --git a/docker/imposter/cluster/configuration/analysis_active_response.json b/docker/imposter/cluster/configuration/analysis_active_response.json
index 59c6e621b5..5eec31e19f 100644
--- a/docker/imposter/cluster/configuration/analysis_active_response.json
+++ b/docker/imposter/cluster/configuration/analysis_active_response.json
@@ -1,36 +1,36 @@
{
- "data": {
- "affected_items": [
- {
- "active-response": [
- {
- "command": "firewall-drop",
- "rules_id": "100100",
- "timeout": 60,
- "level": 0,
- "location": "REMOTE_AGENT"
- },
- {
- "command": "yara",
- "rules_id": "100300,100301",
- "timeout": 0,
- "level": 0,
- "location": "REMOTE_AGENT"
- },
- {
- "command": "remove-threat",
- "rules_id": "87105",
- "timeout": 0,
- "level": 0,
- "location": "REMOTE_AGENT"
- }
- ]
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "active-response": [
+ {
+ "command": "firewall-drop",
+ "rules_id": "100100",
+ "timeout": 60,
+ "level": 0,
+ "location": "REMOTE_AGENT"
+ },
+ {
+ "command": "yara",
+ "rules_id": "100300,100301",
+ "timeout": 0,
+ "level": 0,
+ "location": "REMOTE_AGENT"
+ },
+ {
+ "command": "remove-threat",
+ "rules_id": "87105",
+ "timeout": 0,
+ "level": 0,
+ "location": "REMOTE_AGENT"
+ }
+ ]
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/analysis_alerts.json b/docker/imposter/cluster/configuration/analysis_alerts.json
index d26f8c9863..20b0ac4dbf 100644
--- a/docker/imposter/cluster/configuration/analysis_alerts.json
+++ b/docker/imposter/cluster/configuration/analysis_alerts.json
@@ -1,17 +1,17 @@
{
- "data": {
- "affected_items": [
- {
- "alerts": {
- "email_alert_level": 12,
- "log_alert_level": 3
- }
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "alerts": {
+ "email_alert_level": 12,
+ "log_alert_level": 3
+ }
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/analysis_command.json b/docker/imposter/cluster/configuration/analysis_command.json
index 5ebb733313..c4dbaa2d3a 100644
--- a/docker/imposter/cluster/configuration/analysis_command.json
+++ b/docker/imposter/cluster/configuration/analysis_command.json
@@ -1,65 +1,65 @@
{
- "data": {
- "affected_items": [
- {
- "command": [
- {
- "name": "disable-account",
- "executable": "disable-account",
- "timeout_allowed": 1
- },
- {
- "name": "restart-wazuh",
- "executable": "restart-wazuh",
- "timeout_allowed": 0
- },
- {
- "name": "firewall-drop",
- "executable": "firewall-drop",
- "timeout_allowed": 1
- },
- {
- "name": "host-deny",
- "executable": "host-deny",
- "timeout_allowed": 1
- },
- {
- "name": "route-null",
- "executable": "route-null",
- "timeout_allowed": 1
- },
- {
- "name": "win_route-null",
- "executable": "route-null.exe",
- "timeout_allowed": 1
- },
- {
- "name": "netsh",
- "executable": "netsh.exe",
- "timeout_allowed": 1
- },
- {
- "name": "firewall-drop",
- "executable": "firewall-drop",
- "timeout_allowed": 1
- },
- {
- "name": "yara",
- "executable": "yara.sh",
- "timeout_allowed": 0
- },
- {
- "name": "remove-threat",
- "executable": "remove-threat.sh",
- "timeout_allowed": 0
- }
- ]
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "command": [
+ {
+ "name": "disable-account",
+ "executable": "disable-account",
+ "timeout_allowed": 1
+ },
+ {
+ "name": "restart-wazuh",
+ "executable": "restart-wazuh",
+ "timeout_allowed": 0
+ },
+ {
+ "name": "firewall-drop",
+ "executable": "firewall-drop",
+ "timeout_allowed": 1
+ },
+ {
+ "name": "host-deny",
+ "executable": "host-deny",
+ "timeout_allowed": 1
+ },
+ {
+ "name": "route-null",
+ "executable": "route-null",
+ "timeout_allowed": 1
+ },
+ {
+ "name": "win_route-null",
+ "executable": "route-null.exe",
+ "timeout_allowed": 1
+ },
+ {
+ "name": "netsh",
+ "executable": "netsh.exe",
+ "timeout_allowed": 1
+ },
+ {
+ "name": "firewall-drop",
+ "executable": "firewall-drop",
+ "timeout_allowed": 1
+ },
+ {
+ "name": "yara",
+ "executable": "yara.sh",
+ "timeout_allowed": 0
+ },
+ {
+ "name": "remove-threat",
+ "executable": "remove-threat.sh",
+ "timeout_allowed": 0
+ }
+ ]
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/analysis_global.json b/docker/imposter/cluster/configuration/analysis_global.json
index 711ca5cc72..7a082f842e 100644
--- a/docker/imposter/cluster/configuration/analysis_global.json
+++ b/docker/imposter/cluster/configuration/analysis_global.json
@@ -1,38 +1,34 @@
{
- "data": {
- "affected_items": [
- {
- "global": {
- "email_notification": "yes",
- "email_notification":"yes",
- "email_to":"me@test.com",
- "smtp_server":"mail.test.com",
- "email_from":"wazuh@test.com",
- "logall": "no",
- "logall_json": "no",
- "integrity_checking": 8,
- "rootkit_detection": 8,
- "host_information": 8,
- "prelude_output": "no",
- "zeromq_output": "no",
- "jsonout_output": "yes",
- "alerts_log": "yes",
- "stats": 4,
- "memory_size": 8192,
- "white_list": [
- "127.0.0.1",
- "127.0.0.53",
- "localhost.localdomain"
- ],
- "rotate_interval": 0,
- "max_output_size": 0
- }
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "global": {
+ "email_notification": "yes",
+ "email_notification": "yes",
+ "email_to": "me@test.com",
+ "smtp_server": "mail.test.com",
+ "email_from": "wazuh@test.com",
+ "logall": "no",
+ "logall_json": "no",
+ "integrity_checking": 8,
+ "rootkit_detection": 8,
+ "host_information": 8,
+ "prelude_output": "no",
+ "zeromq_output": "no",
+ "jsonout_output": "yes",
+ "alerts_log": "yes",
+ "stats": 4,
+ "memory_size": 8192,
+ "white_list": ["127.0.0.1", "127.0.0.53", "localhost.localdomain"],
+ "rotate_interval": 0,
+ "max_output_size": 0
+ }
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/analysis_labels.json b/docker/imposter/cluster/configuration/analysis_labels.json
index ed69e298ce..9626416520 100644
--- a/docker/imposter/cluster/configuration/analysis_labels.json
+++ b/docker/imposter/cluster/configuration/analysis_labels.json
@@ -1,16 +1,14 @@
{
- "data": {
- "affected_items": [
- {
- "labels": [
- {"key": "test", "value": "test", "hidden": true}
- ]
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "labels": [{ "key": "test", "value": "test", "hidden": true }]
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/auth_auth.json b/docker/imposter/cluster/configuration/auth_auth.json
index 43b518dfff..275cf3536a 100644
--- a/docker/imposter/cluster/configuration/auth_auth.json
+++ b/docker/imposter/cluster/configuration/auth_auth.json
@@ -1,35 +1,35 @@
{
- "data": {
- "affected_items": [
- {
- "auth": {
- "port": 1515,
- "disabled": "no",
- "remote_enrollment": "yes",
- "use_source_ip": "no",
- "purge": "yes",
- "use_password": "no",
- "ssl_verify_host": "no",
- "ssl_auto_negotiate": "no",
- "ciphers": "HIGH:!ADH:!EXP:!MD5:!RC4:!3DES:!CAMELLIA:@STRENGTH",
- "ssl_manager_cert": "/var/ossec/etc/sslmanagertest.cert",
- "ssl_manager_key": "/var/ossec/etc/sslmanagertest.key",
- "force": {
- "enabled": "yes",
- "key_mismatch": "yes",
- "disconnected_time": {
- "enabled": "yes",
- "value": 3600
- },
- "after_registration_time": 3600
- }
- }
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "auth": {
+ "port": 1515,
+ "disabled": "no",
+ "remote_enrollment": "yes",
+ "use_source_ip": "no",
+ "purge": "yes",
+ "use_password": "no",
+ "ssl_verify_host": "no",
+ "ssl_auto_negotiate": "no",
+ "ciphers": "HIGH:!ADH:!EXP:!MD5:!RC4:!3DES:!CAMELLIA:@STRENGTH",
+ "ssl_manager_cert": "/var/ossec/etc/sslmanagertest.cert",
+ "ssl_manager_key": "/var/ossec/etc/sslmanagertest.key",
+ "force": {
+ "enabled": "yes",
+ "key_mismatch": "yes",
+ "disconnected_time": {
+ "enabled": "yes",
+ "value": 3600
+ },
+ "after_registration_time": 3600
+ }
+ }
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/com_cluster.json b/docker/imposter/cluster/configuration/com_cluster.json
index 9f07de35e1..4072ebafe8 100644
--- a/docker/imposter/cluster/configuration/com_cluster.json
+++ b/docker/imposter/cluster/configuration/com_cluster.json
@@ -1,24 +1,22 @@
{
- "data": {
- "affected_items": [
- {
- "disabled": false,
- "name": "wazuh1",
- "node_name": "master",
- "node_type": "master",
- "key": "test1234",
- "port": 1516,
- "bind_addr": "0.0.0.0",
- "nodes": [
- "0.0.0.0"
- ],
- "hidden": "no"
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "disabled": false,
+ "name": "wazuh1",
+ "node_name": "master",
+ "node_type": "master",
+ "key": "test1234",
+ "port": 1516,
+ "bind_addr": "0.0.0.0",
+ "nodes": ["0.0.0.0"],
+ "hidden": "no"
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/com_logging.json b/docker/imposter/cluster/configuration/com_logging.json
index 9d36fb65ab..b65bb9b180 100644
--- a/docker/imposter/cluster/configuration/com_logging.json
+++ b/docker/imposter/cluster/configuration/com_logging.json
@@ -1,17 +1,17 @@
{
- "data": {
- "affected_items": [
- {
- "logging": {
- "plain": "yes",
- "json": "no"
- }
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "logging": {
+ "plain": "yes",
+ "json": "no"
+ }
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/csyslog_csyslog.json b/docker/imposter/cluster/configuration/csyslog_csyslog.json
index 16d3e739c7..885e4ad5f7 100644
--- a/docker/imposter/cluster/configuration/csyslog_csyslog.json
+++ b/docker/imposter/cluster/configuration/csyslog_csyslog.json
@@ -1,17 +1,17 @@
{
- "data": {
- "affected_items": [
- {
- "syslog_output": {
- "server": "0.0.0.0",
- "level": 3
- }
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "syslog_output": {
+ "server": "0.0.0.0",
+ "level": 3
+ }
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/integrator_integration.json b/docker/imposter/cluster/configuration/integrator_integration.json
index aa3fa26d3b..06bf1b2072 100644
--- a/docker/imposter/cluster/configuration/integrator_integration.json
+++ b/docker/imposter/cluster/configuration/integrator_integration.json
@@ -1,35 +1,30 @@
{
- "data": {
- "affected_items": [
- {
- "integration": [
- {
- "name": "test",
- "hook_url": "test",
- "level": 12,
- "max_log": 165,
- "alert_format": "json"
- },
- {
- "name": "test2",
- "api_key": "test3",
- "level": 0,
- "max_log": 165,
- "rule_id": [
- 100200,
- 100201,
- 100202,
- 100203
- ],
- "alert_format": "json"
- }
- ]
- }
- ],
- "total_affected_items": 2,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "integration": [
+ {
+ "name": "test",
+ "hook_url": "test",
+ "level": 12,
+ "max_log": 165,
+ "alert_format": "json"
+ },
+ {
+ "name": "test2",
+ "api_key": "test3",
+ "level": 0,
+ "max_log": 165,
+ "rule_id": [100200, 100201, 100202, 100203],
+ "alert_format": "json"
+ }
+ ]
+ }
+ ],
+ "total_affected_items": 2,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/logcollector_localfile.json b/docker/imposter/cluster/configuration/logcollector_localfile.json
index 98a47ef639..3fb7529269 100644
--- a/docker/imposter/cluster/configuration/logcollector_localfile.json
+++ b/docker/imposter/cluster/configuration/logcollector_localfile.json
@@ -1,90 +1,74 @@
{
- "data": {
- "affected_items": [
- {
- "localfile": [
- {
- "logformat": "command",
- "command": "df -P",
- "alias": "df -P",
- "ignore_binaries": "no",
- "target": [
- "agent"
- ],
- "frequency": 360
- },
- {
- "logformat": "full_command",
- "command": "netstat -tulpn | sed 's/\\([[:alnum:]]\\+\\)\\ \\+[[:digit:]]\\+\\ \\+[[:digit:]]\\+\\ \\+\\(.*\\):\\([[:digit:]]*\\)\\ \\+\\([0-9\\.\\:\\*]\\+\\).\\+\\ \\([[:digit:]]*\\/[[:alnum:]\\-]*\\).*/\\1 \\2 == \\3 == \\4 \\5/' | sort -k 4 -g | sed 's/ == \\(.*\\) ==/:\\1/' | sed 1,2d",
- "alias": "netstat listening ports",
- "ignore_binaries": "no",
- "target": [
- "agent"
- ],
- "frequency": 360
- },
- {
- "logformat": "full_command",
- "command": "last -n 20",
- "alias": "last -n 20",
- "ignore_binaries": "no",
- "target": [
- "agent"
- ],
- "frequency": 360
- },
- {
- "file": "/var/ossec/logs/active-responses.log",
- "logformat": "syslog",
- "ignore_binaries": "no",
- "only-future-events": "yes",
- "target": [
- "agent"
- ]
- },
- {
- "file": "/var/log/messages",
- "logformat": "syslog",
- "ignore_binaries": "no",
- "only-future-events": "yes",
- "target": [
- "agent"
- ]
- },
- {
- "file": "/var/log/secure",
- "logformat": "syslog",
- "ignore_binaries": "no",
- "only-future-events": "yes",
- "target": [
- "agent"
- ]
- },
- {
- "file": "/var/log/maillog",
- "logformat": "syslog",
- "ignore_binaries": "no",
- "only-future-events": "yes",
- "target": [
- "agent"
- ]
- },
- {
- "file": "/var/log/audit/audit.log",
- "logformat": "audit",
- "ignore_binaries": "no",
- "only-future-events": "yes",
- "target": [
- "agent"
- ]
- }
- ]
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "localfile": [
+ {
+ "logformat": "command",
+ "command": "df -P",
+ "alias": "df -P",
+ "ignore_binaries": "no",
+ "target": ["agent"],
+ "frequency": 360
+ },
+ {
+ "logformat": "full_command",
+ "command": "netstat -tulpn | sed 's/\\([[:alnum:]]\\+\\)\\ \\+[[:digit:]]\\+\\ \\+[[:digit:]]\\+\\ \\+\\(.*\\):\\([[:digit:]]*\\)\\ \\+\\([0-9\\.\\:\\*]\\+\\).\\+\\ \\([[:digit:]]*\\/[[:alnum:]\\-]*\\).*/\\1 \\2 == \\3 == \\4 \\5/' | sort -k 4 -g | sed 's/ == \\(.*\\) ==/:\\1/' | sed 1,2d",
+ "alias": "netstat listening ports",
+ "ignore_binaries": "no",
+ "target": ["agent"],
+ "frequency": 360
+ },
+ {
+ "logformat": "full_command",
+ "command": "last -n 20",
+ "alias": "last -n 20",
+ "ignore_binaries": "no",
+ "target": ["agent"],
+ "frequency": 360
+ },
+ {
+ "file": "/var/ossec/logs/active-responses.log",
+ "logformat": "syslog",
+ "ignore_binaries": "no",
+ "only-future-events": "yes",
+ "target": ["agent"]
+ },
+ {
+ "file": "/var/log/messages",
+ "logformat": "syslog",
+ "ignore_binaries": "no",
+ "only-future-events": "yes",
+ "target": ["agent"]
+ },
+ {
+ "file": "/var/log/secure",
+ "logformat": "syslog",
+ "ignore_binaries": "no",
+ "only-future-events": "yes",
+ "target": ["agent"]
+ },
+ {
+ "file": "/var/log/maillog",
+ "logformat": "syslog",
+ "ignore_binaries": "no",
+ "only-future-events": "yes",
+ "target": ["agent"]
+ },
+ {
+ "file": "/var/log/audit/audit.log",
+ "logformat": "audit",
+ "ignore_binaries": "no",
+ "only-future-events": "yes",
+ "target": ["agent"]
+ }
+ ]
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/logcollector_socket.json b/docker/imposter/cluster/configuration/logcollector_socket.json
index 858bda84c5..b28f0d1b24 100644
--- a/docker/imposter/cluster/configuration/logcollector_socket.json
+++ b/docker/imposter/cluster/configuration/logcollector_socket.json
@@ -1,17 +1,19 @@
{
- "data": {
- "affected_items": [{
- "socket": {
- "name": "custom_socket",
- "location": "custom_location",
- "mode": "tcp",
- "prefix": "custom_prefix"
- }
- }],
- "total_affected_items": 0,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Could not read active configuration in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "socket": {
+ "name": "custom_socket",
+ "location": "custom_location",
+ "mode": "tcp",
+ "prefix": "custom_prefix"
+ }
+ }
+ ],
+ "total_affected_items": 0,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Could not read active configuration in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/mail_alerts.json b/docker/imposter/cluster/configuration/mail_alerts.json
index c06199b98a..740e28193f 100644
--- a/docker/imposter/cluster/configuration/mail_alerts.json
+++ b/docker/imposter/cluster/configuration/mail_alerts.json
@@ -1,18 +1,18 @@
{
- "data": {
- "affected_items": [
- {
- "email_alerts": {
- "email_to": "you@example.com",
- "level": 3,
- "do_not_delay": true
- }
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "email_alerts": {
+ "email_to": "you@example.com",
+ "level": 3,
+ "do_not_delay": true
+ }
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/mail_global.json b/docker/imposter/cluster/configuration/mail_global.json
index e2c30e05be..b733439595 100644
--- a/docker/imposter/cluster/configuration/mail_global.json
+++ b/docker/imposter/cluster/configuration/mail_global.json
@@ -1,18 +1,18 @@
{
- "data": {
- "affected_items": [
- {
- "email_alerts": {
- "email_to":"me@test.com",
- "level": 4,
- "do_not_delay": true
- }
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "email_alerts": {
+ "email_to": "me@test.com",
+ "level": 4,
+ "do_not_delay": true
+ }
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/monitor_reports.json b/docker/imposter/cluster/configuration/monitor_reports.json
index a611e47fbe..6bd7410368 100644
--- a/docker/imposter/cluster/configuration/monitor_reports.json
+++ b/docker/imposter/cluster/configuration/monitor_reports.json
@@ -1,16 +1,20 @@
{
- "data": {
- "affected_items": [{
- "reports": [{
- "category": "syscheck",
- "title": "Daily report: File changes",
- "email_to": "example@test.com"
- }]
- }],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Could not read active configuration in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "reports": [
+ {
+ "category": "syscheck",
+ "title": "Daily report: File changes",
+ "email_to": "example@test.com"
+ }
+ ]
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Could not read active configuration in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/request_remote.json b/docker/imposter/cluster/configuration/request_remote.json
index 0748bacf71..9fd427e357 100644
--- a/docker/imposter/cluster/configuration/request_remote.json
+++ b/docker/imposter/cluster/configuration/request_remote.json
@@ -1,24 +1,22 @@
{
- "data": {
- "affected_items": [
- {
- "remote": [
- {
- "connection": "secure",
- "ipv6": "no",
- "protocol": [
- "TCP"
- ],
- "port": "1514",
- "queue_size": "131072"
- }
- ]
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "remote": [
+ {
+ "connection": "secure",
+ "ipv6": "no",
+ "protocol": ["TCP"],
+ "port": "1514",
+ "queue_size": "131072"
+ }
+ ]
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/syscheck_rootcheck.json b/docker/imposter/cluster/configuration/syscheck_rootcheck.json
index 062a5df419..124af30c20 100644
--- a/docker/imposter/cluster/configuration/syscheck_rootcheck.json
+++ b/docker/imposter/cluster/configuration/syscheck_rootcheck.json
@@ -1,30 +1,30 @@
{
- "data": {
- "affected_items": [
- {
- "rootcheck": {
- "disabled": "no",
- "base_directory": "",
- "rootkit_files": "/var/ossec/etc/rootcheck/rootkit_files.txt",
- "rootkit_trojans": "/var/ossec/etc/rootcheck/rootkit_trojans.txt",
- "scanall": "no",
- "skip_nfs": "yes",
- "frequency": 43200,
- "check_dev": "yes",
- "check_files": "yes",
- "check_if": "yes",
- "check_pids": "yes",
- "check_ports": "yes",
- "check_sys": "yes",
- "check_trojans": "yes",
- "check_unixaudit": "no"
- }
- }
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "rootcheck": {
+ "disabled": "no",
+ "base_directory": "",
+ "rootkit_files": "/var/ossec/etc/rootcheck/rootkit_files.txt",
+ "rootkit_trojans": "/var/ossec/etc/rootcheck/rootkit_trojans.txt",
+ "scanall": "no",
+ "skip_nfs": "yes",
+ "frequency": 43200,
+ "check_dev": "yes",
+ "check_files": "yes",
+ "check_if": "yes",
+ "check_pids": "yes",
+ "check_ports": "yes",
+ "check_sys": "yes",
+ "check_trojans": "yes",
+ "check_unixaudit": "no"
+ }
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/syscheck_syscheck.json b/docker/imposter/cluster/configuration/syscheck_syscheck.json
index 21a36f188c..2299b61c98 100644
--- a/docker/imposter/cluster/configuration/syscheck_syscheck.json
+++ b/docker/imposter/cluster/configuration/syscheck_syscheck.json
@@ -1,178 +1,173 @@
{
- "data": {
- "affected_items": [
+ "data": {
+ "affected_items": [
+ {
+ "syscheck": {
+ "disabled": "no",
+ "frequency": 43200,
+ "skip_nfs": "yes",
+ "skip_dev": "yes",
+ "skip_sys": "yes",
+ "skip_proc": "yes",
+ "scan_on_start": "yes",
+ "max_files_per_second": 0,
+ "file_limit": {
+ "enabled": "yes",
+ "entries": 100000
+ },
+ "diff": {
+ "disk_quota": {
+ "enabled": "yes",
+ "limit": 1048576
+ },
+ "file_size": {
+ "enabled": "yes",
+ "limit": 51200
+ }
+ },
+ "directories": [
+ {
+ "opts": [
+ "check_md5sum",
+ "check_sha1sum",
+ "check_perm",
+ "check_size",
+ "check_owner",
+ "check_group",
+ "check_mtime",
+ "check_inode",
+ "realtime",
+ "check_sha256sum"
+ ],
+ "dir": "/bin",
+ "recursion_level": 256,
+ "diff_size_limit": 51200
+ },
+ {
+ "opts": [
+ "check_md5sum",
+ "check_sha1sum",
+ "check_perm",
+ "check_size",
+ "check_owner",
+ "check_group",
+ "check_mtime",
+ "check_inode",
+ "realtime",
+ "check_sha256sum"
+ ],
+ "dir": "/boot",
+ "recursion_level": 256,
+ "diff_size_limit": 51200
+ },
+ {
+ "opts": [
+ "check_md5sum",
+ "check_sha1sum",
+ "check_perm",
+ "check_size",
+ "check_owner",
+ "check_group",
+ "check_mtime",
+ "check_inode",
+ "realtime",
+ "check_sha256sum"
+ ],
+ "dir": "/etc",
+ "recursion_level": 256,
+ "diff_size_limit": 51200
+ },
+ {
+ "opts": [
+ "check_md5sum",
+ "check_sha1sum",
+ "check_perm",
+ "check_size",
+ "check_owner",
+ "check_group",
+ "check_mtime",
+ "check_inode",
+ "realtime",
+ "check_sha256sum"
+ ],
+ "dir": "/sbin",
+ "recursion_level": 256,
+ "diff_size_limit": 51200
+ },
+ {
+ "opts": [
+ "check_md5sum",
+ "check_sha1sum",
+ "check_perm",
+ "check_size",
+ "check_owner",
+ "check_group",
+ "check_mtime",
+ "check_inode",
+ "realtime",
+ "check_sha256sum"
+ ],
+ "dir": "/usr/bin",
+ "recursion_level": 256,
+ "diff_size_limit": 51200
+ },
{
- "syscheck": {
- "disabled": "no",
- "frequency": 43200,
- "skip_nfs": "yes",
- "skip_dev": "yes",
- "skip_sys": "yes",
- "skip_proc": "yes",
- "scan_on_start": "yes",
- "max_files_per_second": 0,
- "file_limit": {
- "enabled": "yes",
- "entries": 100000
- },
- "diff": {
- "disk_quota": {
- "enabled": "yes",
- "limit": 1048576
- },
- "file_size": {
- "enabled": "yes",
- "limit": 51200
- }
- },
- "directories": [
- {
- "opts": [
- "check_md5sum",
- "check_sha1sum",
- "check_perm",
- "check_size",
- "check_owner",
- "check_group",
- "check_mtime",
- "check_inode",
- "realtime",
- "check_sha256sum"
- ],
- "dir": "/bin",
- "recursion_level": 256,
- "diff_size_limit": 51200
- },
- {
- "opts": [
- "check_md5sum",
- "check_sha1sum",
- "check_perm",
- "check_size",
- "check_owner",
- "check_group",
- "check_mtime",
- "check_inode",
- "realtime",
- "check_sha256sum"
- ],
- "dir": "/boot",
- "recursion_level": 256,
- "diff_size_limit": 51200
- },
- {
- "opts": [
- "check_md5sum",
- "check_sha1sum",
- "check_perm",
- "check_size",
- "check_owner",
- "check_group",
- "check_mtime",
- "check_inode",
- "realtime",
- "check_sha256sum"
- ],
- "dir": "/etc",
- "recursion_level": 256,
- "diff_size_limit": 51200
- },
- {
- "opts": [
- "check_md5sum",
- "check_sha1sum",
- "check_perm",
- "check_size",
- "check_owner",
- "check_group",
- "check_mtime",
- "check_inode",
- "realtime",
- "check_sha256sum"
- ],
- "dir": "/sbin",
- "recursion_level": 256,
- "diff_size_limit": 51200
- },
- {
- "opts": [
- "check_md5sum",
- "check_sha1sum",
- "check_perm",
- "check_size",
- "check_owner",
- "check_group",
- "check_mtime",
- "check_inode",
- "realtime",
- "check_sha256sum"
- ],
- "dir": "/usr/bin",
- "recursion_level": 256,
- "diff_size_limit": 51200
- },
- {
- "opts": [
- "check_md5sum",
- "check_sha1sum",
- "check_perm",
- "check_size",
- "check_owner",
- "check_group",
- "check_mtime",
- "check_inode",
- "realtime",
- "check_sha256sum"
- ],
- "dir": "/usr/sbin",
- "recursion_level": 256,
- "diff_size_limit": 51200
- }
- ],
- "nodiff": [
- "/etc/ssl/private.key"
- ],
- "ignore": [
- "/etc/mtab",
- "/etc/hosts.deny",
- "/etc/mail/statistics",
- "/etc/random-seed",
- "/etc/random.seed",
- "/etc/adjtime",
- "/etc/httpd/logs",
- "/etc/utmpx",
- "/etc/wtmpx",
- "/etc/cups/certs",
- "/etc/dumpdates",
- "/etc/svc/volatile"
- ],
- "ignore_sregex": [
- ".alert$",
- ".log$|.swp$"
- ],
- "whodata": {
- "restart_audit": "yes",
- "startup_healthcheck": "yes"
- },
- "allow_remote_prefilter_cmd": "no",
- "synchronization": {
- "enabled": "yes",
- "max_interval": 3600,
- "interval": 300,
- "response_timeout": 30,
- "queue_size": 16384,
- "max_eps": 10
- },
- "max_eps": 100,
- "process_priority": 10,
- "database": "disk"
- }
+ "opts": [
+ "check_md5sum",
+ "check_sha1sum",
+ "check_perm",
+ "check_size",
+ "check_owner",
+ "check_group",
+ "check_mtime",
+ "check_inode",
+ "realtime",
+ "check_sha256sum"
+ ],
+ "dir": "/usr/sbin",
+ "recursion_level": 256,
+ "diff_size_limit": 51200
}
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ ],
+ "nodiff": ["/etc/ssl/private.key"],
+ "ignore": [
+ "/etc/mtab",
+ "/etc/hosts.deny",
+ "/etc/mail/statistics",
+ "/etc/random-seed",
+ "/etc/random.seed",
+ "/etc/adjtime",
+ "/etc/httpd/logs",
+ "/etc/utmpx",
+ "/etc/wtmpx",
+ "/etc/cups/certs",
+ "/etc/dumpdates",
+ "/etc/svc/volatile"
+ ],
+ "ignore_sregex": [".alert$", ".log$|.swp$"],
+ "whodata": {
+ "restart_audit": "yes",
+ "startup_healthcheck": "yes"
+ },
+ "allow_remote_prefilter_cmd": "no",
+ "synchronization": {
+ "enabled": "yes",
+ "max_interval": 3600,
+ "interval": 300,
+ "response_timeout": 30,
+ "queue_size": 16384,
+ "max_eps": 10
+ },
+ "max_eps": 100,
+ "process_priority": 10,
+ "database": "disk"
+ }
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/configuration/wmodules_wmodules.json b/docker/imposter/cluster/configuration/wmodules_wmodules.json
index a1ac45e5ea..b36ce8feac 100644
--- a/docker/imposter/cluster/configuration/wmodules_wmodules.json
+++ b/docker/imposter/cluster/configuration/wmodules_wmodules.json
@@ -1,249 +1,247 @@
{
- "data": {
- "affected_items": [
- {
- "wmodules": [
- {
- "agent-upgrade": {
- "enabled": "yes",
- "max_threads": 8,
- "chunk_size": 512
- }
- },
- {
- "task-manager": {
- "enabled": "yes"
- }
- },
- {
- "cis-cat": {
- "disabled": "yes",
- "scan-on-start": "yes",
- "interval": 86400,
- "java_path": "wodles/java",
- "ciscat_path": "wodles/ciscat",
- "timeout": 1800
- }
- },
- {
- "osquery": {
- "disabled": "yes",
- "run_daemon": "yes",
- "add_labels": "yes",
- "log_path": "/var/log/osquery/test.log",
- "config_path": "/etc/osquery/test.conf"
- }
- },
- {
- "syscollector": {
- "disabled": "no",
- "scan-on-start": "yes",
- "interval": 3600,
- "network": "yes",
- "os": "yes",
- "hardware": "yes",
- "packages": "yes",
- "ports": "yes",
- "ports_all": "no",
- "processes": "yes",
- "sync_max_eps": 10
- }
- },
- {
- "sca": {
- "interval": 43200,
- "enabled": "yes",
- "scan_on_start": "yes",
- "skip_nfs": "yes",
- "policies": [
- "/var/ossec/ruleset/sca/test.yml"
- ]
- }
- },
- {
- "vulnerability-detector": {
- "enabled": "yes",
- "run_on_start": "yes",
- "interval": 300,
- "min_full_scan_interval": 21600,
- "retry_interval": 30,
- "providers": [
- {
- "name": "canonical",
- "version": "TRUSTY",
- "url": "https://test.com",
- "update_interval": 3600,
- "download_timeout": 300
- },
- {
- "name": "canonical",
- "version": "XENIAL",
- "url": "https://test.com",
- "update_interval": 3600,
- "download_timeout": 300
- },
- {
- "name": "canonical",
- "version": "BIONIC",
- "url": "https://test.com",
- "update_interval": 3600,
- "download_timeout": 300
- },
- {
- "name": "canonical",
- "version": "FOCAL",
- "url": "https://test.com",
- "update_interval": 3600,
- "download_timeout": 300
- },
- {
- "name": "debian",
- "version": "STRETCH",
- "url": "https://test.com",
- "update_interval": 3600,
- "download_timeout": 300
- },
- {
- "name": "debian",
- "version": "BUSTER",
- "url": "https://test.com",
- "update_interval": 3600,
- "download_timeout": 300
- },
- {
- "name": "redhat",
- "version": "5",
- "url": "https://test.com",
- "update_interval": 3600,
- "download_timeout": 300
- },
- {
- "name": "redhat",
- "version": "6",
- "url": "https://test.com",
- "update_interval": 3600,
- "download_timeout": 300
- },
- {
- "name": "redhat",
- "version": "7",
- "url": "https://test.com",
- "update_interval": 3600,
- "download_timeout": 300
- },
- {
- "name": "redhat",
- "version": "8",
- "url": "https://test.com",
- "update_interval": 3600,
- "download_timeout": 300
- },
- {
- "name": "jredhat",
- "update_interval": 3600,
- "download_timeout": 0
- },
- {
- "name": "alas",
- "version": "Amazon-Linux",
- "url": "https://test.com",
- "update_interval": 3600,
- "download_timeout": 300
- },
- {
- "name": "test",
- "version": "test",
- "url": "https://test.com",
- "update_interval": 3600,
- "download_timeout": 300
- },
- {
- "name": "arch",
- "update_interval": 3600,
- "download_timeout": 300
- },
- {
- "name": "nvd",
- "update_from_year": 2010,
- "update_interval": 3600,
- "download_timeout": 300
- }
- ]
- }
- },
- {
- "aws-s3": {
- "interval": 1800,
- "disabled": "no",
- "run_on_start": "yes",
- "skip_on_error": "no",
- "buckets": [
- {
- "name": "test",
- "aws_profile": "prod",
- "only_logs_after": "2020-MAY-01",
- "type": "cloudtrail",
- "remove_from_bucket": "no"
- },
- {
- "name": "test2",
- "aws_profile": "prod",
- "path": "guardduty",
- "only_logs_after": "2020-MAY-01",
- "type": "guardduty",
- "remove_from_bucket": "no"
- },
- {
- "name": "test3",
- "aws_profile": "prod",
- "path": "macie",
- "only_logs_after": "2020-MAY-01",
- "type": "custom",
- "remove_from_bucket": "no"
- },
- {
- "name": "test4",
- "aws_profile": "prod",
- "path": "vpc",
- "only_logs_after": "2020-MAY-01",
- "type": "vpcflow",
- "remove_from_bucket": "no"
- }
- ],
- "services": [
- {
- "type": "inspector",
- "aws_profile": "prod",
- "remove_log_streams": "no"
- }
- ]
- }
- },
- {
- "database": {
- "sync_agents": "yes",
- "real_time": "yes",
- "interval": 60,
- "max_queued_events": 0
- }
- },
- {
- "wazuh_download": {
- "enabled": "yes"
- }
- },
- {
- "wazuh_control": {
- "enabled": "yes"
- }
- }
- ]
+ "data": {
+ "affected_items": [
+ {
+ "wmodules": [
+ {
+ "agent-upgrade": {
+ "enabled": "yes",
+ "max_threads": 8,
+ "chunk_size": 512
}
- ],
- "total_affected_items": 1,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "Active configuration was successfully read in specified node",
- "error": 0
-}
\ No newline at end of file
+ },
+ {
+ "task-manager": {
+ "enabled": "yes"
+ }
+ },
+ {
+ "cis-cat": {
+ "disabled": "yes",
+ "scan-on-start": "yes",
+ "interval": 86400,
+ "java_path": "wodles/java",
+ "ciscat_path": "wodles/ciscat",
+ "timeout": 1800
+ }
+ },
+ {
+ "osquery": {
+ "disabled": "yes",
+ "run_daemon": "yes",
+ "add_labels": "yes",
+ "log_path": "/var/log/osquery/test.log",
+ "config_path": "/etc/osquery/test.conf"
+ }
+ },
+ {
+ "syscollector": {
+ "disabled": "no",
+ "scan-on-start": "yes",
+ "interval": 3600,
+ "network": "yes",
+ "os": "yes",
+ "hardware": "yes",
+ "packages": "yes",
+ "ports": "yes",
+ "ports_all": "no",
+ "processes": "yes",
+ "sync_max_eps": 10
+ }
+ },
+ {
+ "sca": {
+ "interval": 43200,
+ "enabled": "yes",
+ "scan_on_start": "yes",
+ "skip_nfs": "yes",
+ "policies": ["/var/ossec/ruleset/sca/test.yml"]
+ }
+ },
+ {
+ "vulnerability-detector": {
+ "enabled": "yes",
+ "run_on_start": "yes",
+ "interval": 300,
+ "min_full_scan_interval": 21600,
+ "retry_interval": 30,
+ "providers": [
+ {
+ "name": "canonical",
+ "version": "TRUSTY",
+ "url": "https://test.com",
+ "update_interval": 3600,
+ "download_timeout": 300
+ },
+ {
+ "name": "canonical",
+ "version": "XENIAL",
+ "url": "https://test.com",
+ "update_interval": 3600,
+ "download_timeout": 300
+ },
+ {
+ "name": "canonical",
+ "version": "BIONIC",
+ "url": "https://test.com",
+ "update_interval": 3600,
+ "download_timeout": 300
+ },
+ {
+ "name": "canonical",
+ "version": "FOCAL",
+ "url": "https://test.com",
+ "update_interval": 3600,
+ "download_timeout": 300
+ },
+ {
+ "name": "debian",
+ "version": "STRETCH",
+ "url": "https://test.com",
+ "update_interval": 3600,
+ "download_timeout": 300
+ },
+ {
+ "name": "debian",
+ "version": "BUSTER",
+ "url": "https://test.com",
+ "update_interval": 3600,
+ "download_timeout": 300
+ },
+ {
+ "name": "redhat",
+ "version": "5",
+ "url": "https://test.com",
+ "update_interval": 3600,
+ "download_timeout": 300
+ },
+ {
+ "name": "redhat",
+ "version": "6",
+ "url": "https://test.com",
+ "update_interval": 3600,
+ "download_timeout": 300
+ },
+ {
+ "name": "redhat",
+ "version": "7",
+ "url": "https://test.com",
+ "update_interval": 3600,
+ "download_timeout": 300
+ },
+ {
+ "name": "redhat",
+ "version": "8",
+ "url": "https://test.com",
+ "update_interval": 3600,
+ "download_timeout": 300
+ },
+ {
+ "name": "jredhat",
+ "update_interval": 3600,
+ "download_timeout": 0
+ },
+ {
+ "name": "alas",
+ "version": "Amazon-Linux",
+ "url": "https://test.com",
+ "update_interval": 3600,
+ "download_timeout": 300
+ },
+ {
+ "name": "test",
+ "version": "test",
+ "url": "https://test.com",
+ "update_interval": 3600,
+ "download_timeout": 300
+ },
+ {
+ "name": "arch",
+ "update_interval": 3600,
+ "download_timeout": 300
+ },
+ {
+ "name": "nvd",
+ "update_from_year": 2010,
+ "update_interval": 3600,
+ "download_timeout": 300
+ }
+ ]
+ }
+ },
+ {
+ "aws-s3": {
+ "interval": 1800,
+ "disabled": "no",
+ "run_on_start": "yes",
+ "skip_on_error": "no",
+ "buckets": [
+ {
+ "name": "test",
+ "aws_profile": "prod",
+ "only_logs_after": "2020-MAY-01",
+ "type": "cloudtrail",
+ "remove_from_bucket": "no"
+ },
+ {
+ "name": "test2",
+ "aws_profile": "prod",
+ "path": "guardduty",
+ "only_logs_after": "2020-MAY-01",
+ "type": "guardduty",
+ "remove_from_bucket": "no"
+ },
+ {
+ "name": "test3",
+ "aws_profile": "prod",
+ "path": "macie",
+ "only_logs_after": "2020-MAY-01",
+ "type": "custom",
+ "remove_from_bucket": "no"
+ },
+ {
+ "name": "test4",
+ "aws_profile": "prod",
+ "path": "vpc",
+ "only_logs_after": "2020-MAY-01",
+ "type": "vpcflow",
+ "remove_from_bucket": "no"
+ }
+ ],
+ "services": [
+ {
+ "type": "inspector",
+ "aws_profile": "prod",
+ "remove_log_streams": "no"
+ }
+ ]
+ }
+ },
+ {
+ "database": {
+ "sync_agents": "yes",
+ "real_time": "yes",
+ "interval": 60,
+ "max_queued_events": 0
+ }
+ },
+ {
+ "wazuh_download": {
+ "enabled": "yes"
+ }
+ },
+ {
+ "wazuh_control": {
+ "enabled": "yes"
+ }
+ }
+ ]
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Active configuration was successfully read in specified node",
+ "error": 0
+}
diff --git a/docker/imposter/cluster/error.json b/docker/imposter/cluster/error.json
index b83212e19a..e9095daff8 100644
--- a/docker/imposter/cluster/error.json
+++ b/docker/imposter/cluster/error.json
@@ -15,12 +15,10 @@
"message": "Error validating configuration: (1226): Error reading XML file 'etc/ossec.conf': (line 0).",
"remediation": "Please, fix the corrupted files"
},
- "id": [
- "worker-node"
- ]
+ "id": ["worker-node"]
}
]
},
"message": "Could not check validation in some nodes",
"error": 2
-}
\ No newline at end of file
+}
diff --git a/docker/imposter/errors/internal_server_error.json b/docker/imposter/errors/internal_server_error.json
index c6c963b851..e76239e1d6 100644
--- a/docker/imposter/errors/internal_server_error.json
+++ b/docker/imposter/errors/internal_server_error.json
@@ -1,5 +1,5 @@
{
- "statusCode": 500,
- "error": "Internal Server Error",
- "message": "An internal server error occurred."
-}
\ No newline at end of file
+ "statusCode": 500,
+ "error": "Internal Server Error",
+ "message": "An internal server error occurred."
+}
diff --git a/docker/imposter/initial_data.json b/docker/imposter/initial_data.json
index 7152eec58f..985da0369f 100644
--- a/docker/imposter/initial_data.json
+++ b/docker/imposter/initial_data.json
@@ -1,4 +1,4 @@
{
"attempt": 0,
"callRestart": false
-}
\ No newline at end of file
+}
diff --git a/docker/imposter/rules/get_rules.json b/docker/imposter/rules/get_rules.json
index 11e6bbb82b..6d14302fee 100644
--- a/docker/imposter/rules/get_rules.json
+++ b/docker/imposter/rules/get_rules.json
@@ -1,31 +1,31 @@
{
- "data": {
- "affected_items": [
- {
- "filename": "0010-rules_config.xml",
- "relative_dirname": "ruleset/rules",
- "status": "enabled"
- },
- {
- "filename": "0015-ossec_rules.xml",
- "relative_dirname": "ruleset/rules",
- "status": "enabled"
- },
- {
- "filename": "0016-wazuh_rules.xml",
- "relative_dirname": "ruleset/rules",
- "status": "enabled"
- },
- {
- "filename": "0020-syslog_rules.xml",
- "relative_dirname": "ruleset/rules",
- "status": "enabled"
- }
- ],
- "total_affected_items": 4,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "All rules files were returned",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "filename": "0010-rules_config.xml",
+ "relative_dirname": "ruleset/rules",
+ "status": "enabled"
+ },
+ {
+ "filename": "0015-ossec_rules.xml",
+ "relative_dirname": "ruleset/rules",
+ "status": "enabled"
+ },
+ {
+ "filename": "0016-wazuh_rules.xml",
+ "relative_dirname": "ruleset/rules",
+ "status": "enabled"
+ },
+ {
+ "filename": "0020-syslog_rules.xml",
+ "relative_dirname": "ruleset/rules",
+ "status": "enabled"
+ }
+ ],
+ "total_affected_items": 4,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "All rules files were returned",
+ "error": 0
+}
diff --git a/docker/imposter/sca/policy-checks.js b/docker/imposter/sca/policy-checks.js
new file mode 100644
index 0000000000..62e31ee5a4
--- /dev/null
+++ b/docker/imposter/sca/policy-checks.js
@@ -0,0 +1,24 @@
+var status =
+ context.request.queryParams.status || context.request.queryParams.result;
+
+console.log(status);
+
+switch (status) {
+ case 'failed':
+ respond().withStatusCode(200).withFile('sca/policy_checks_failed.json');
+ break;
+ case 'not applicable':
+ respond()
+ .withStatusCode(200)
+ .withFile('sca/policy_checks_not_applicable.json');
+ break;
+ case 'passed':
+ respond().withStatusCode(200).withFile('sca/policy_checks_passed.json');
+ break;
+ case '':
+ respond().withStatusCode(200).withFile('sca/policy_checks.json');
+ break;
+ default:
+ respond().withStatusCode(200).withFile('sca/policy_checks.json');
+ break;
+}
diff --git a/docker/imposter/sca/policy_checks.json b/docker/imposter/sca/policy_checks.json
new file mode 100644
index 0000000000..a3157ea165
--- /dev/null
+++ b/docker/imposter/sca/policy_checks.json
@@ -0,0 +1,97 @@
+{
+ "data": {
+ "affected_items": [
+ {
+ "description": "The cramfs filesystem type is a compressed read-only Linux filesystem embedded in small footprint systems. A cramfs image can be used without having to first decompress the image.",
+ "id": 19000,
+ "reason": "Invalid path or wrong permissions to run command 'modprobe -n -v cramfs'",
+ "command": "modprobe -n -v cramfs,lsmod",
+ "rationale": "Removing support for unneeded filesystem types reduces the local attack surface of the server. If this filesystem type is not needed, disable it.",
+ "condition": "all",
+ "title": "Ensure mounting of cramfs filesystems is disabled.",
+ "result": "not applicable",
+ "policy_id": "cis_ubuntu20-04",
+ "remediation": "1) Edit or create a file in the /etc/modprobe.d/ directory ending in .conf and add the following line: install cramfs /bin/true. 2) Run the following command to unload the cramfs module: # rmmod cramfs",
+ "compliance": [
+ {
+ "value": "1.1.1.1",
+ "key": "cis"
+ },
+ {
+ "value": "5.1",
+ "key": "cis_csc"
+ },
+ {
+ "value": "2.2.5",
+ "key": "pci_dss"
+ },
+ {
+ "value": "CC6.3",
+ "key": "tsc"
+ }
+ ],
+ "rules": [
+ {
+ "type": "command",
+ "rule": "c:modprobe -n -v cramfs -> r:^install /bin/true"
+ },
+ {
+ "type": "numeric",
+ "rule": "not c:lsmod -> r:cramfs"
+ }
+ ]
+ },
+ {
+ "remediation": "For new installations, during installation create a custom partition setup and specify a separate partition for /var. For systems that were previously installed, create a new partition and configure /etc/fstab as appropriate",
+ "rationale": "Since the /var directory may contain world-writable files and directories, there is a risk of resource exhaustion if it is not bound to a separate partition",
+ "title": "Ensure separate partition exists for /var",
+ "policy_id": "cis_debian",
+ "file": "/etc/fstab",
+ "description": "The /var directory is used by daemons and other system services to temporarily store dynamic data. Some directories created by these processes may be world-writable",
+ "id": 5003,
+ "result": "failed",
+ "condition": "all",
+ "references": "https://tldp.org/HOWTO/LVM-HOWTO/",
+ "compliance": [
+ {
+ "key": "cis",
+ "value": "1.1.6"
+ },
+ {
+ "key": "cis_csc",
+ "value": "5"
+ }
+ ]
+ },
+ {
+ "remediation": "Run the following commands to remove exim: # apt-get remove exim4; # apt-get purge exim4",
+ "rationale": "Unless POP3 and/or IMAP servers are to be provided by this system, it is recommended that the package be removed to reduce the potential attack surface",
+ "title": "Ensure IMAP and POP3 server is not enabled (POP3)",
+ "policy_id": "cis_debian",
+ "file": "/etc/inetd.conf",
+ "description": "Exim is an open source IMAP and POP3 server for Linux based systems",
+ "id": 5022,
+ "result": "passed",
+ "condition": "all",
+ "compliance": [
+ {
+ "key": "cis",
+ "value": "2.2.11"
+ },
+ {
+ "key": "cis_csc",
+ "value": "9"
+ },
+ {
+ "key": "pci_dss",
+ "value": "2.2.2"
+ }
+ ]
+ }
+ ],
+ "total_affected_items": 191,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "error": 0
+}
diff --git a/docker/imposter/sca/policy_checks_failed.json b/docker/imposter/sca/policy_checks_failed.json
new file mode 100644
index 0000000000..96aec01681
--- /dev/null
+++ b/docker/imposter/sca/policy_checks_failed.json
@@ -0,0 +1,32 @@
+{
+ "data": {
+ "affected_items": [
+ {
+ "remediation": "For new installations, during installation create a custom partition setup and specify a separate partition for /var. For systems that were previously installed, create a new partition and configure /etc/fstab as appropriate",
+ "rationale": "Since the /var directory may contain world-writable files and directories, there is a risk of resource exhaustion if it is not bound to a separate partition",
+ "title": "Ensure separate partition exists for /var",
+ "policy_id": "cis_debian",
+ "file": "/etc/fstab",
+ "description": "The /var directory is used by daemons and other system services to temporarily store dynamic data. Some directories created by these processes may be world-writable",
+ "id": 5003,
+ "result": "failed",
+ "condition": "all",
+ "references": "https://tldp.org/HOWTO/LVM-HOWTO/",
+ "compliance": [
+ {
+ "key": "cis",
+ "value": "1.1.6"
+ },
+ {
+ "key": "cis_csc",
+ "value": "5"
+ }
+ ]
+ }
+ ],
+ "total_affected_items": 191,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "error": 0
+}
diff --git a/docker/imposter/sca/policy_checks_not_applicable.json b/docker/imposter/sca/policy_checks_not_applicable.json
new file mode 100644
index 0000000000..e0d032000f
--- /dev/null
+++ b/docker/imposter/sca/policy_checks_not_applicable.json
@@ -0,0 +1,50 @@
+{
+ "data": {
+ "affected_items": [
+ {
+ "description": "The cramfs filesystem type is a compressed read-only Linux filesystem embedded in small footprint systems. A cramfs image can be used without having to first decompress the image.",
+ "id": 19000,
+ "reason": "Invalid path or wrong permissions to run command 'modprobe -n -v cramfs'",
+ "command": "modprobe -n -v cramfs,lsmod",
+ "rationale": "Removing support for unneeded filesystem types reduces the local attack surface of the server. If this filesystem type is not needed, disable it.",
+ "condition": "all",
+ "title": "Ensure mounting of cramfs filesystems is disabled.",
+ "result": "not applicable",
+ "policy_id": "cis_ubuntu20-04",
+ "remediation": "1) Edit or create a file in the /etc/modprobe.d/ directory ending in .conf and add the following line: install cramfs /bin/true. 2) Run the following command to unload the cramfs module: # rmmod cramfs",
+ "compliance": [
+ {
+ "value": "1.1.1.1",
+ "key": "cis"
+ },
+ {
+ "value": "5.1",
+ "key": "cis_csc"
+ },
+ {
+ "value": "2.2.5",
+ "key": "pci_dss"
+ },
+ {
+ "value": "CC6.3",
+ "key": "tsc"
+ }
+ ],
+ "rules": [
+ {
+ "type": "command",
+ "rule": "c:modprobe -n -v cramfs -> r:^install /bin/true"
+ },
+ {
+ "type": "numeric",
+ "rule": "not c:lsmod -> r:cramfs"
+ }
+ ]
+ }
+ ],
+ "total_affected_items": 191,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "error": 0
+}
diff --git a/docker/imposter/sca/policy_checks_passed.json b/docker/imposter/sca/policy_checks_passed.json
new file mode 100644
index 0000000000..20456a7e7f
--- /dev/null
+++ b/docker/imposter/sca/policy_checks_passed.json
@@ -0,0 +1,35 @@
+{
+ "data": {
+ "affected_items": [
+ {
+ "remediation": "Run the following commands to remove exim: # apt-get remove exim4; # apt-get purge exim4",
+ "rationale": "Unless POP3 and/or IMAP servers are to be provided by this system, it is recommended that the package be removed to reduce the potential attack surface",
+ "title": "Ensure IMAP and POP3 server is not enabled (POP3)",
+ "policy_id": "cis_debian",
+ "file": "/etc/inetd.conf",
+ "description": "Exim is an open source IMAP and POP3 server for Linux based systems",
+ "id": 5022,
+ "result": "passed",
+ "condition": "all",
+ "compliance": [
+ {
+ "key": "cis",
+ "value": "2.2.11"
+ },
+ {
+ "key": "cis_csc",
+ "value": "9"
+ },
+ {
+ "key": "pci_dss",
+ "value": "2.2.2"
+ }
+ ]
+ }
+ ],
+ "total_affected_items": 191,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "error": 0
+}
diff --git a/docker/imposter/security/login.js b/docker/imposter/security/login.js
index 86c2eb4180..5bb651462d 100755
--- a/docker/imposter/security/login.js
+++ b/docker/imposter/security/login.js
@@ -8,16 +8,16 @@ header = {
};
// The second part of the token is the payload, which contains the claims.
-// Claims are statements about an entity (typically, the user) and
-// additional data. There are three types of claims:
+// Claims are statements about an entity (typically, the user) and
+// additional data. There are three types of claims:
// registered, public, and private claims.
-nbf = Date.now()-1000;
+nbf = Date.now() - 1000;
claims = {
"iss": "wazuh",
"aud": "Wazuh API REST",
"nbf": nbf,
- "exp": nbf+3600000,
+ "exp": nbf + 3600000,
"sub": "wazuh",
"rbac_roles": [
1
@@ -36,7 +36,5 @@ resp = {
};
respond()
- .withStatusCode(200)
- .withData(JSON.stringify(resp));
-
-
+ .withStatusCode(200)
+ .withData(JSON.stringify(resp));
diff --git a/docker/imposter/security/security_policies.json b/docker/imposter/security/security_policies.json
index 2b2803a6d4..565a90284c 100644
--- a/docker/imposter/security/security_policies.json
+++ b/docker/imposter/security/security_policies.json
@@ -1,659 +1,413 @@
{
- "data": {
- "affected_items": [
- {
- "id": 1,
- "name": "agents_all_resourceless",
- "policy": {
- "actions": [
- "agent:create",
- "group:create"
- ],
- "resources": [
- "*:*:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1,
- 5
- ]
- },
- {
- "id": 2,
- "name": "agents_all_agents",
- "policy": {
- "actions": [
- "agent:read",
- "agent:delete",
- "agent:modify_group",
- "agent:reconnect",
- "agent:restart",
- "agent:upgrade"
- ],
- "resources": [
- "agent:id:*",
- "agent:group:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1,
- 5
- ]
- },
- {
- "id": 3,
- "name": "agents_all_groups",
- "policy": {
- "actions": [
- "group:read",
- "group:delete",
- "group:update_config",
- "group:modify_assignments"
- ],
- "resources": [
- "group:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1,
- 5
- ]
- },
- {
- "id": 4,
- "name": "agents_read_agents",
- "policy": {
- "actions": [
- "agent:read"
- ],
- "resources": [
- "agent:id:*",
- "agent:group:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 2,
- 4,
- 100
- ]
- },
- {
- "id": 5,
- "name": "agents_read_groups",
- "policy": {
- "actions": [
- "group:read"
- ],
- "resources": [
- "group:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 2,
- 4,
- 100
- ]
- },
- {
- "id": 6,
- "name": "agents_commands_agents",
- "policy": {
- "actions": [
- "active-response:command"
- ],
- "resources": [
- "agent:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1
- ]
- },
- {
- "id": 7,
- "name": "security_all_resourceless",
- "policy": {
- "actions": [
- "security:create",
- "security:create_user",
- "security:read_config",
- "security:update_config",
- "security:revoke",
- "security:edit_run_as"
- ],
- "resources": [
- "*:*:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1
- ]
- },
- {
- "id": 8,
- "name": "security_all_security",
- "policy": {
- "actions": [
- "security:read",
- "security:update",
- "security:delete"
- ],
- "resources": [
- "role:id:*",
- "policy:id:*",
- "user:id:*",
- "rule:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1
- ]
- },
- {
- "id": 9,
- "name": "users_all_resourceless",
- "policy": {
- "actions": [
- "security:create_user",
- "security:revoke",
- "security:edit_run_as"
- ],
- "resources": [
- "*:*:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 3
- ]
- },
- {
- "id": 10,
- "name": "users_all_users",
- "policy": {
- "actions": [
- "security:read",
- "security:update",
- "security:delete"
- ],
- "resources": [
- "user:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 3
- ]
- },
- {
- "id": 11,
- "name": "users_modify_run_as_flag",
- "policy": {
- "actions": [
- "security:edit_run_as"
- ],
- "resources": [
- "*:*:*"
- ],
- "effect": "allow"
- },
- "roles": []
- },
- {
- "id": 12,
- "name": "ciscat_read_ciscat",
- "policy": {
- "actions": [
- "ciscat:read"
- ],
- "resources": [
- "agent:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1,
- 2,
- 100
- ]
- },
- {
- "id": 13,
- "name": "decoders_read_decoders",
- "policy": {
- "actions": [
- "decoders:read"
- ],
- "resources": [
- "decoder:file:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 2,
- 100
- ]
- },
- {
- "id": 14,
- "name": "decoders_all_files",
- "policy": {
- "actions": [
- "decoders:read",
- "decoders:delete"
- ],
- "resources": [
- "decoder:file:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1
- ]
- },
- {
- "id": 15,
- "name": "decoders_all_resourceless",
- "policy": {
- "actions": [
- "decoders:update"
- ],
- "resources": [
- "*:*:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1
- ]
- },
- {
- "id": 16,
- "name": "mitre_read_mitre",
- "policy": {
- "actions": [
- "mitre:read"
- ],
- "resources": [
- "*:*:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1,
- 2,
- 100
- ]
- },
- {
- "id": 17,
- "name": "lists_read_rules",
- "policy": {
- "actions": [
- "lists:read"
- ],
- "resources": [
- "list:file:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 2,
- 100
- ]
- },
- {
- "id": 18,
- "name": "lists_all_rules",
- "policy": {
- "actions": [
- "lists:read",
- "lists:delete"
- ],
- "resources": [
- "list:file:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1
- ]
- },
- {
- "id": 19,
- "name": "lists_all_resourceless",
- "policy": {
- "actions": [
- "lists:update"
- ],
- "resources": [
- "*:*:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1
- ]
- },
- {
- "id": 20,
- "name": "rootcheck_read_rootcheck",
- "policy": {
- "actions": [
- "rootcheck:read"
- ],
- "resources": [
- "agent:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 2,
- 100
- ]
- },
- {
- "id": 21,
- "name": "rootcheck_all_rootcheck",
- "policy": {
- "actions": [
- "rootcheck:clear",
- "rootcheck:read",
- "rootcheck:run"
- ],
- "resources": [
- "agent:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1
- ]
- },
- {
- "id": 22,
- "name": "rules_read_rules",
- "policy": {
- "actions": [
- "rules:read"
- ],
- "resources": [
- "rule:file:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 2,
- 100
- ]
- },
- {
- "id": 23,
- "name": "rules_all_files",
- "policy": {
- "actions": [
- "rules:read",
- "rules:delete"
- ],
- "resources": [
- "rule:file:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1
- ]
- },
- {
- "id": 24,
- "name": "rules_all_resourceless",
- "policy": {
- "actions": [
- "rules:update"
- ],
- "resources": [
- "*:*:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1
- ]
- },
- {
- "id": 25,
- "name": "sca_read_sca",
- "policy": {
- "actions": [
- "sca:read"
- ],
- "resources": [
- "agent:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1,
- 2,
- 100
- ]
- },
- {
- "id": 26,
- "name": "syscheck_read_syscheck",
- "policy": {
- "actions": [
- "syscheck:read"
- ],
- "resources": [
- "agent:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 2,
- 100
- ]
- },
- {
- "id": 27,
- "name": "syscheck_all_syscheck",
- "policy": {
- "actions": [
- "syscheck:clear",
- "syscheck:read",
- "syscheck:run"
- ],
- "resources": [
- "agent:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1
- ]
- },
- {
- "id": 28,
- "name": "syscollector_read_syscollector",
- "policy": {
- "actions": [
- "syscollector:read"
- ],
- "resources": [
- "agent:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1,
- 2,
- 100
- ]
- },
- {
- "id": 29,
- "name": "cluster_all_resourceless",
- "policy": {
- "actions": [
- "cluster:status",
- "manager:read",
- "manager:read_api_config",
- "manager:update_config",
- "manager:restart"
- ],
- "resources": [
- "*:*:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1,
- 7
- ]
- },
- {
- "id": 30,
- "name": "cluster_all_nodes",
- "policy": {
- "actions": [
- "cluster:read_api_config",
- "cluster:read",
- "cluster:restart",
- "cluster:update_config"
- ],
- "resources": [
- "node:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1,
- 7
- ]
- },
- {
- "id": 31,
- "name": "cluster_read_resourceless",
- "policy": {
- "actions": [
- "cluster:status",
- "manager:read",
- "manager:read_api_config"
- ],
- "resources": [
- "*:*:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 2,
- 6,
- 100
- ]
- },
- {
- "id": 32,
- "name": "cluster_read_nodes",
- "policy": {
- "actions": [
- "cluster:read_api_config",
- "cluster:read",
- "cluster:read_api_config"
- ],
- "resources": [
- "node:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 2,
- 6,
- 100
- ]
- },
- {
- "id": 33,
- "name": "logtest_all_logtest",
- "policy": {
- "actions": [
- "logtest:run"
- ],
- "resources": [
- "*:*:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1,
- 100
- ]
- },
- {
- "id": 34,
- "name": "task_status_task",
- "policy": {
- "actions": [
- "task:status"
- ],
- "resources": [
- "*:*:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1
- ]
- },
- {
- "id": 35,
- "name": "vulnerability_read_vulnerability",
- "policy": {
- "actions": [
- "vulnerability:read"
- ],
- "resources": [
- "agent:id:*"
- ],
- "effect": "allow"
- },
- "roles": [
- 1,
- 2,
- 100
- ]
- },
- {
- "id": 100,
- "name": "manager_deny_read",
- "policy": {
- "actions": [
- "manager:read",
- "cluster:read"
- ],
- "resources": [
- "*:*:*",
- "node:id:*"
- ],
- "effect": "deny"
- },
- "roles": [
- 100
- ]
- }
- ],
- "total_affected_items": 36,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "All specified policies were returned",
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "affected_items": [
+ {
+ "id": 1,
+ "name": "agents_all_resourceless",
+ "policy": {
+ "actions": ["agent:create", "group:create"],
+ "resources": ["*:*:*"],
+ "effect": "allow"
+ },
+ "roles": [1, 5]
+ },
+ {
+ "id": 2,
+ "name": "agents_all_agents",
+ "policy": {
+ "actions": [
+ "agent:read",
+ "agent:delete",
+ "agent:modify_group",
+ "agent:reconnect",
+ "agent:restart",
+ "agent:upgrade"
+ ],
+ "resources": ["agent:id:*", "agent:group:*"],
+ "effect": "allow"
+ },
+ "roles": [1, 5]
+ },
+ {
+ "id": 3,
+ "name": "agents_all_groups",
+ "policy": {
+ "actions": [
+ "group:read",
+ "group:delete",
+ "group:update_config",
+ "group:modify_assignments"
+ ],
+ "resources": ["group:id:*"],
+ "effect": "allow"
+ },
+ "roles": [1, 5]
+ },
+ {
+ "id": 4,
+ "name": "agents_read_agents",
+ "policy": {
+ "actions": ["agent:read"],
+ "resources": ["agent:id:*", "agent:group:*"],
+ "effect": "allow"
+ },
+ "roles": [2, 4, 100]
+ },
+ {
+ "id": 5,
+ "name": "agents_read_groups",
+ "policy": {
+ "actions": ["group:read"],
+ "resources": ["group:id:*"],
+ "effect": "allow"
+ },
+ "roles": [2, 4, 100]
+ },
+ {
+ "id": 6,
+ "name": "agents_commands_agents",
+ "policy": {
+ "actions": ["active-response:command"],
+ "resources": ["agent:id:*"],
+ "effect": "allow"
+ },
+ "roles": [1]
+ },
+ {
+ "id": 7,
+ "name": "security_all_resourceless",
+ "policy": {
+ "actions": [
+ "security:create",
+ "security:create_user",
+ "security:read_config",
+ "security:update_config",
+ "security:revoke",
+ "security:edit_run_as"
+ ],
+ "resources": ["*:*:*"],
+ "effect": "allow"
+ },
+ "roles": [1]
+ },
+ {
+ "id": 8,
+ "name": "security_all_security",
+ "policy": {
+ "actions": ["security:read", "security:update", "security:delete"],
+ "resources": ["role:id:*", "policy:id:*", "user:id:*", "rule:id:*"],
+ "effect": "allow"
+ },
+ "roles": [1]
+ },
+ {
+ "id": 9,
+ "name": "users_all_resourceless",
+ "policy": {
+ "actions": [
+ "security:create_user",
+ "security:revoke",
+ "security:edit_run_as"
+ ],
+ "resources": ["*:*:*"],
+ "effect": "allow"
+ },
+ "roles": [3]
+ },
+ {
+ "id": 10,
+ "name": "users_all_users",
+ "policy": {
+ "actions": ["security:read", "security:update", "security:delete"],
+ "resources": ["user:id:*"],
+ "effect": "allow"
+ },
+ "roles": [3]
+ },
+ {
+ "id": 11,
+ "name": "users_modify_run_as_flag",
+ "policy": {
+ "actions": ["security:edit_run_as"],
+ "resources": ["*:*:*"],
+ "effect": "allow"
+ },
+ "roles": []
+ },
+ {
+ "id": 12,
+ "name": "ciscat_read_ciscat",
+ "policy": {
+ "actions": ["ciscat:read"],
+ "resources": ["agent:id:*"],
+ "effect": "allow"
+ },
+ "roles": [1, 2, 100]
+ },
+ {
+ "id": 13,
+ "name": "decoders_read_decoders",
+ "policy": {
+ "actions": ["decoders:read"],
+ "resources": ["decoder:file:*"],
+ "effect": "allow"
+ },
+ "roles": [2, 100]
+ },
+ {
+ "id": 14,
+ "name": "decoders_all_files",
+ "policy": {
+ "actions": ["decoders:read", "decoders:delete"],
+ "resources": ["decoder:file:*"],
+ "effect": "allow"
+ },
+ "roles": [1]
+ },
+ {
+ "id": 15,
+ "name": "decoders_all_resourceless",
+ "policy": {
+ "actions": ["decoders:update"],
+ "resources": ["*:*:*"],
+ "effect": "allow"
+ },
+ "roles": [1]
+ },
+ {
+ "id": 16,
+ "name": "mitre_read_mitre",
+ "policy": {
+ "actions": ["mitre:read"],
+ "resources": ["*:*:*"],
+ "effect": "allow"
+ },
+ "roles": [1, 2, 100]
+ },
+ {
+ "id": 17,
+ "name": "lists_read_rules",
+ "policy": {
+ "actions": ["lists:read"],
+ "resources": ["list:file:*"],
+ "effect": "allow"
+ },
+ "roles": [2, 100]
+ },
+ {
+ "id": 18,
+ "name": "lists_all_rules",
+ "policy": {
+ "actions": ["lists:read", "lists:delete"],
+ "resources": ["list:file:*"],
+ "effect": "allow"
+ },
+ "roles": [1]
+ },
+ {
+ "id": 19,
+ "name": "lists_all_resourceless",
+ "policy": {
+ "actions": ["lists:update"],
+ "resources": ["*:*:*"],
+ "effect": "allow"
+ },
+ "roles": [1]
+ },
+ {
+ "id": 20,
+ "name": "rootcheck_read_rootcheck",
+ "policy": {
+ "actions": ["rootcheck:read"],
+ "resources": ["agent:id:*"],
+ "effect": "allow"
+ },
+ "roles": [2, 100]
+ },
+ {
+ "id": 21,
+ "name": "rootcheck_all_rootcheck",
+ "policy": {
+ "actions": ["rootcheck:clear", "rootcheck:read", "rootcheck:run"],
+ "resources": ["agent:id:*"],
+ "effect": "allow"
+ },
+ "roles": [1]
+ },
+ {
+ "id": 22,
+ "name": "rules_read_rules",
+ "policy": {
+ "actions": ["rules:read"],
+ "resources": ["rule:file:*"],
+ "effect": "allow"
+ },
+ "roles": [2, 100]
+ },
+ {
+ "id": 23,
+ "name": "rules_all_files",
+ "policy": {
+ "actions": ["rules:read", "rules:delete"],
+ "resources": ["rule:file:*"],
+ "effect": "allow"
+ },
+ "roles": [1]
+ },
+ {
+ "id": 24,
+ "name": "rules_all_resourceless",
+ "policy": {
+ "actions": ["rules:update"],
+ "resources": ["*:*:*"],
+ "effect": "allow"
+ },
+ "roles": [1]
+ },
+ {
+ "id": 25,
+ "name": "sca_read_sca",
+ "policy": {
+ "actions": ["sca:read"],
+ "resources": ["agent:id:*"],
+ "effect": "allow"
+ },
+ "roles": [1, 2, 100]
+ },
+ {
+ "id": 26,
+ "name": "syscheck_read_syscheck",
+ "policy": {
+ "actions": ["syscheck:read"],
+ "resources": ["agent:id:*"],
+ "effect": "allow"
+ },
+ "roles": [2, 100]
+ },
+ {
+ "id": 27,
+ "name": "syscheck_all_syscheck",
+ "policy": {
+ "actions": ["syscheck:clear", "syscheck:read", "syscheck:run"],
+ "resources": ["agent:id:*"],
+ "effect": "allow"
+ },
+ "roles": [1]
+ },
+ {
+ "id": 28,
+ "name": "syscollector_read_syscollector",
+ "policy": {
+ "actions": ["syscollector:read"],
+ "resources": ["agent:id:*"],
+ "effect": "allow"
+ },
+ "roles": [1, 2, 100]
+ },
+ {
+ "id": 29,
+ "name": "cluster_all_resourceless",
+ "policy": {
+ "actions": [
+ "cluster:status",
+ "manager:read",
+ "manager:read_api_config",
+ "manager:update_config",
+ "manager:restart"
+ ],
+ "resources": ["*:*:*"],
+ "effect": "allow"
+ },
+ "roles": [1, 7]
+ },
+ {
+ "id": 30,
+ "name": "cluster_all_nodes",
+ "policy": {
+ "actions": [
+ "cluster:read_api_config",
+ "cluster:read",
+ "cluster:restart",
+ "cluster:update_config"
+ ],
+ "resources": ["node:id:*"],
+ "effect": "allow"
+ },
+ "roles": [1, 7]
+ },
+ {
+ "id": 31,
+ "name": "cluster_read_resourceless",
+ "policy": {
+ "actions": [
+ "cluster:status",
+ "manager:read",
+ "manager:read_api_config"
+ ],
+ "resources": ["*:*:*"],
+ "effect": "allow"
+ },
+ "roles": [2, 6, 100]
+ },
+ {
+ "id": 32,
+ "name": "cluster_read_nodes",
+ "policy": {
+ "actions": [
+ "cluster:read_api_config",
+ "cluster:read",
+ "cluster:read_api_config"
+ ],
+ "resources": ["node:id:*"],
+ "effect": "allow"
+ },
+ "roles": [2, 6, 100]
+ },
+ {
+ "id": 33,
+ "name": "logtest_all_logtest",
+ "policy": {
+ "actions": ["logtest:run"],
+ "resources": ["*:*:*"],
+ "effect": "allow"
+ },
+ "roles": [1, 100]
+ },
+ {
+ "id": 34,
+ "name": "task_status_task",
+ "policy": {
+ "actions": ["task:status"],
+ "resources": ["*:*:*"],
+ "effect": "allow"
+ },
+ "roles": [1]
+ },
+ {
+ "id": 35,
+ "name": "vulnerability_read_vulnerability",
+ "policy": {
+ "actions": ["vulnerability:read"],
+ "resources": ["agent:id:*"],
+ "effect": "allow"
+ },
+ "roles": [1, 2, 100]
+ },
+ {
+ "id": 100,
+ "name": "manager_deny_read",
+ "policy": {
+ "actions": ["manager:read", "cluster:read"],
+ "resources": ["*:*:*", "node:id:*"],
+ "effect": "deny"
+ },
+ "roles": [100]
+ }
+ ],
+ "total_affected_items": 36,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "All specified policies were returned",
+ "error": 0
+}
diff --git a/docker/imposter/security/security_roles.json b/docker/imposter/security/security_roles.json
index 777e931958..a6ea88acb3 100644
--- a/docker/imposter/security/security_roles.json
+++ b/docker/imposter/security/security_roles.json
@@ -1,122 +1,63 @@
{
- "data": {
- "affected_items": [
- {
- "id": 1,
- "name": "administrator",
- "policies": [
- 1,
- 2,
- 3,
- 6,
- 7,
- 8,
- 29,
- 30,
- 12,
- 14,
- 15,
- 18,
- 19,
- 21,
- 23,
- 24,
- 16,
- 25,
- 27,
- 28,
- 33,
- 34,
- 35
- ],
- "users": [
- 1,
- 2
- ],
- "rules": [
- 1,
- 2,
- 100
- ]
- },
- {
- "id": 2,
- "name": "readonly",
- "policies": [
- 4,
- 5,
- 12,
- 31,
- 32,
- 13,
- 17,
- 20,
- 22,
- 16,
- 25,
- 26,
- 28,
- 35
- ],
- "users": [],
- "rules": []
- },
- {
- "id": 3,
- "name": "users_admin",
- "policies": [
- 9,
- 10
- ],
- "users": [],
- "rules": []
- },
- {
- "id": 4,
- "name": "agents_readonly",
- "policies": [
- 4,
- 5
- ],
- "users": [],
- "rules": []
- },
- {
- "id": 5,
- "name": "agents_admin",
- "policies": [
- 1,
- 2,
- 3
- ],
- "users": [],
- "rules": []
- },
- {
- "id": 6,
- "name": "cluster_readonly",
- "policies": [
- 31,
- 32
- ],
- "users": [],
- "rules": []
- },
- {
- "id": 7,
- "name": "cluster_admin",
- "policies": [
- 29,
- 30
- ],
- "users": [],
- "rules": []
- }
+ "data": {
+ "affected_items": [
+ {
+ "id": 1,
+ "name": "administrator",
+ "policies": [
+ 1, 2, 3, 6, 7, 8, 29, 30, 12, 14, 15, 18, 19, 21, 23, 24, 16, 25, 27,
+ 28, 33, 34, 35
],
- "total_affected_items": 8,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "All specified roles were returned",
- "error": 0
-}
\ No newline at end of file
+ "users": [1, 2],
+ "rules": [1, 2, 100]
+ },
+ {
+ "id": 2,
+ "name": "readonly",
+ "policies": [4, 5, 12, 31, 32, 13, 17, 20, 22, 16, 25, 26, 28, 35],
+ "users": [],
+ "rules": []
+ },
+ {
+ "id": 3,
+ "name": "users_admin",
+ "policies": [9, 10],
+ "users": [],
+ "rules": []
+ },
+ {
+ "id": 4,
+ "name": "agents_readonly",
+ "policies": [4, 5],
+ "users": [],
+ "rules": []
+ },
+ {
+ "id": 5,
+ "name": "agents_admin",
+ "policies": [1, 2, 3],
+ "users": [],
+ "rules": []
+ },
+ {
+ "id": 6,
+ "name": "cluster_readonly",
+ "policies": [31, 32],
+ "users": [],
+ "rules": []
+ },
+ {
+ "id": 7,
+ "name": "cluster_admin",
+ "policies": [29, 30],
+ "users": [],
+ "rules": []
+ }
+ ],
+ "total_affected_items": 8,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "All specified roles were returned",
+ "error": 0
+}
diff --git a/docker/imposter/vulnerability/default_last_scan.json b/docker/imposter/vulnerability/default_last_scan.json
new file mode 100644
index 0000000000..45d6633b5b
--- /dev/null
+++ b/docker/imposter/vulnerability/default_last_scan.json
@@ -0,0 +1,15 @@
+{
+ "data": {
+ "affected_items": [
+ {
+ "last_full_scan": "1970-01-01T00:00:00+00:00",
+ "last_partial_scan": "1970-01-01T00:00:00+00:00"
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Last vulnerability scans of the agent were returned",
+ "error": 0
+}
diff --git a/docker/imposter/vulnerability/last_scan.json b/docker/imposter/vulnerability/last_scan.json
new file mode 100644
index 0000000000..c3f7211581
--- /dev/null
+++ b/docker/imposter/vulnerability/last_scan.json
@@ -0,0 +1,15 @@
+{
+ "data": {
+ "affected_items": [
+ {
+ "last_full_scan": "2022-12-29T17:16:58+00:00",
+ "last_partial_scan": "2022-12-29T19:02:58+00:00"
+ }
+ ],
+ "total_affected_items": 1,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "Last vulnerability scans of the agent were returned",
+ "error": 0
+}
diff --git a/docker/imposter/vulnerability/vulnerabilities.json b/docker/imposter/vulnerability/vulnerabilities.json
index 04c84a8bef..fd908de610 100644
--- a/docker/imposter/vulnerability/vulnerabilities.json
+++ b/docker/imposter/vulnerability/vulnerabilities.json
@@ -1,108 +1,108 @@
{
- "data": {
- "affected_items": [
- {
- "title": "CVE-2021-31179 affects Microsoft Office Home and Business 2016 - en-us",
- "external_references": [
- "https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2021-31179",
- "https://nvd.nist.gov/vuln/detail/CVE-2021-31179"
- ],
- "name": "Microsoft Office Home and Business 2016 - en-us",
- "cvss3_score": 7.8,
- "severity": "High",
- "updated": "2021-05-17",
- "cvss2_score": 6.8,
- "architecture": "x64",
- "version": "16.0.15225.20288",
- "published": "2021-05-11",
- "detection_time": "2022-06-24T16:09:34Z",
- "condition": "KB5001923 patch is not installed",
- "cve": "CVE-2021-31179"
- },
- {
- "title": "CVE-2020-27350 affects apt",
- "external_references": [
- "https://usn.ubuntu.com/usn/usn-4667-1",
- "https://bugs.launchpad.net/bugs/1899193",
- "https://www.debian.org/security/2020/dsa-4808",
- "https://security.netapp.com/advisory/ntap-20210108-0005/",
- "https://nvd.nist.gov/vuln/detail/CVE-2020-27350",
- "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-27350"
- ],
- "name": "apt",
- "cvss3_score": 5.7,
- "severity": "Medium",
- "updated": "2021-01-08",
- "cvss2_score": 4.6,
- "architecture": "amd64",
- "version": "1.4.9",
- "published": "2020-12-10",
- "detection_time": "2022-06-24T18:29:53Z",
- "condition": "Package less than 1.4.11",
- "cve": "CVE-2020-27350"
- },
- {
- "title": "CVE-2021-29953 affects Mozilla Firefox 53.0 (x64 en-US)",
- "external_references": [
- "https://www.mozilla.org/security/advisories/mfsa2021-20/",
- "https://bugzilla.mozilla.org/show_bug.cgi?id=1701684",
- "https://nvd.nist.gov/vuln/detail/CVE-2021-29953"
- ],
- "name": "Mozilla Firefox 53.0 (x64 en-US)",
- "cvss3_score": 6.1,
- "severity": "Medium",
- "updated": "2021-06-30",
- "cvss2_score": 4.3,
- "architecture": "x64",
- "version": "53.0",
- "published": "2021-06-24",
- "detection_time": "2022-06-24T16:09:26Z",
- "condition": "less than 88.0.1",
- "cve": "CVE-2021-29953"
- },
- {
- "title": "CVE-2021-29953 affects Mozilla Firefox 53.0 (x64 en-US)",
- "external_references": [
- "https://www.mozilla.org/security/advisories/mfsa2021-20/",
- "https://bugzilla.mozilla.org/show_bug.cgi?id=1701684",
- "https://nvd.nist.gov/vuln/detail/CVE-2021-29953"
- ],
- "name": "Mozilla Firefox 53.0 (x64 en-US)",
- "cvss3_score": 6.1,
- "severity": "Medium",
- "updated": "2021-06-30",
- "cvss2_score": 4.3,
- "architecture": "x64",
- "version": "53.0",
- "published": "2021-06-24",
- "detection_time": "2022-06-24T16:09:26Z",
- "condition": "less than 88.0.1",
- "cve": "CVE-2021-29953"
- },
- {
- "title": "CVE-2022-0809 affects Google Chrome",
- "external_references": [
- "https://chromereleases.googleblog.com/2022/03/stable-channel-update-for-desktop.html",
- "https://crbug.com/1293428",
- "https://nvd.nist.gov/vuln/detail/CVE-2022-0809"
- ],
- "name": "Google Chrome",
- "cvss3_score": 8.8,
- "severity": "High",
- "updated": "2022-04-12",
- "cvss2_score": 6.8,
- "architecture": " ",
- "version": "80.0.3987.87",
- "published": "2022-04-05",
- "detection_time": "2022-06-27T15:03:49Z",
- "condition": "less than 99.0.4844.51",
- "cve": "CVE-2022-0809"
- }
- ],
- "total_affected_items": 1378,
- "total_failed_items": 0,
- "failed_items": []
- },
- "message": "All selected vulnerabilities were returned",
- "error": 0
+ "data": {
+ "affected_items": [
+ {
+ "title": "CVE-2021-31179 affects Microsoft Office Home and Business 2016 - en-us",
+ "external_references": [
+ "https://portal.msrc.microsoft.com/en-US/security-guidance/advisory/CVE-2021-31179",
+ "https://nvd.nist.gov/vuln/detail/CVE-2021-31179"
+ ],
+ "name": "Microsoft Office Home and Business 2016 - en-us",
+ "cvss3_score": 7.8,
+ "severity": "High",
+ "updated": "2021-05-17",
+ "cvss2_score": 6.8,
+ "architecture": "x64",
+ "version": "16.0.15225.20288",
+ "published": "2021-05-11",
+ "detection_time": "2022-06-24T16:09:34Z",
+ "condition": "KB5001923 patch is not installed",
+ "cve": "CVE-2021-31179"
+ },
+ {
+ "title": "CVE-2020-27350 affects apt",
+ "external_references": [
+ "https://usn.ubuntu.com/usn/usn-4667-1",
+ "https://bugs.launchpad.net/bugs/1899193",
+ "https://www.debian.org/security/2020/dsa-4808",
+ "https://security.netapp.com/advisory/ntap-20210108-0005/",
+ "https://nvd.nist.gov/vuln/detail/CVE-2020-27350",
+ "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-27350"
+ ],
+ "name": "apt",
+ "cvss3_score": 5.7,
+ "severity": "Medium",
+ "updated": "2021-01-08",
+ "cvss2_score": 4.6,
+ "architecture": "amd64",
+ "version": "1.4.9",
+ "published": "2020-12-10",
+ "detection_time": "2022-06-24T18:29:53Z",
+ "condition": "Package less than 1.4.11",
+ "cve": "CVE-2020-27350"
+ },
+ {
+ "title": "CVE-2021-29953 affects Mozilla Firefox 53.0 (x64 en-US)",
+ "external_references": [
+ "https://www.mozilla.org/security/advisories/mfsa2021-20/",
+ "https://bugzilla.mozilla.org/show_bug.cgi?id=1701684",
+ "https://nvd.nist.gov/vuln/detail/CVE-2021-29953"
+ ],
+ "name": "Mozilla Firefox 53.0 (x64 en-US)",
+ "cvss3_score": 6.1,
+ "severity": "Medium",
+ "updated": "2021-06-30",
+ "cvss2_score": 4.3,
+ "architecture": "x64",
+ "version": "53.0",
+ "published": "2021-06-24",
+ "detection_time": "2022-06-24T16:09:26Z",
+ "condition": "less than 88.0.1",
+ "cve": "CVE-2021-29953"
+ },
+ {
+ "title": "CVE-2021-29953 affects Mozilla Firefox 53.0 (x64 en-US)",
+ "external_references": [
+ "https://www.mozilla.org/security/advisories/mfsa2021-20/",
+ "https://bugzilla.mozilla.org/show_bug.cgi?id=1701684",
+ "https://nvd.nist.gov/vuln/detail/CVE-2021-29953"
+ ],
+ "name": "Mozilla Firefox 53.0 (x64 en-US)",
+ "cvss3_score": 6.1,
+ "severity": "Medium",
+ "updated": "2021-06-30",
+ "cvss2_score": 4.3,
+ "architecture": "x64",
+ "version": "53.0",
+ "published": "2021-06-24",
+ "detection_time": "2022-06-24T16:09:26Z",
+ "condition": "less than 88.0.1",
+ "cve": "CVE-2021-29953"
+ },
+ {
+ "title": "CVE-2022-0809 affects Google Chrome",
+ "external_references": [
+ "https://chromereleases.googleblog.com/2022/03/stable-channel-update-for-desktop.html",
+ "https://crbug.com/1293428",
+ "https://nvd.nist.gov/vuln/detail/CVE-2022-0809"
+ ],
+ "name": "Google Chrome",
+ "cvss3_score": 8.8,
+ "severity": "High",
+ "updated": "2022-04-12",
+ "cvss2_score": 6.8,
+ "architecture": " ",
+ "version": "80.0.3987.87",
+ "published": "2022-04-05",
+ "detection_time": "2022-06-27T15:03:49Z",
+ "condition": "less than 99.0.4844.51",
+ "cve": "CVE-2022-0809"
+ }
+ ],
+ "total_affected_items": 1378,
+ "total_failed_items": 0,
+ "failed_items": []
+ },
+ "message": "All selected vulnerabilities were returned",
+ "error": 0
}
diff --git a/docker/imposter/vulnerability/vulnerabilities_summary.js b/docker/imposter/vulnerability/vulnerabilities_summary.js
index 5900146ecb..1832e6b797 100644
--- a/docker/imposter/vulnerability/vulnerabilities_summary.js
+++ b/docker/imposter/vulnerability/vulnerabilities_summary.js
@@ -2,39 +2,39 @@ var field = context.request.pathParams.field
switch (field) {
case 'severity':
- respond()
- .withStatusCode(200)
- .withFile('vulnerability/vulnerabilities_summary_severity.json')
+ respond()
+ .withStatusCode(200)
+ .withFile('vulnerability/vulnerabilities_summary_severity.json')
break;
case 'version':
- respond()
- .withStatusCode(200)
- .withFile('vulnerability/vulnerabilities_summary_version.json')
+ respond()
+ .withStatusCode(200)
+ .withFile('vulnerability/vulnerabilities_summary_version.json')
break;
case 'name':
- respond()
- .withStatusCode(200)
- .withFile('vulnerability/vulnerabilities_summary_name.json')
+ respond()
+ .withStatusCode(200)
+ .withFile('vulnerability/vulnerabilities_summary_name.json')
break;
case 'cve':
- respond()
- .withStatusCode(200)
- .withFile('vulnerability/vulnerabilities_summary_cve.json')
+ respond()
+ .withStatusCode(200)
+ .withFile('vulnerability/vulnerabilities_summary_cve.json')
break;
case 'cvss2_score':
- respond()
- .withStatusCode(200)
- .withFile('vulnerability/vulnerabilities_summary_cvss2_score.json')
+ respond()
+ .withStatusCode(200)
+ .withFile('vulnerability/vulnerabilities_summary_cvss2_score.json')
break;
case 'cvss3_score':
- respond()
- .withStatusCode(200)
- .withFile('vulnerability/vulnerabilities_summary_cvss3_score.json')
+ respond()
+ .withStatusCode(200)
+ .withFile('vulnerability/vulnerabilities_summary_cvss3_score.json')
break;
default:
respond()
- .withStatusCode(200)
- .withFile('agents/vulnerabilities_summary_version.json')
+ .withStatusCode(200)
+ .withFile('agents/vulnerabilities_summary_version.json')
break;
}
diff --git a/docker/imposter/vulnerability/vulnerabilities_summary_cve.json b/docker/imposter/vulnerability/vulnerabilities_summary_cve.json
index 0e2ef66029..4f158e79d2 100644
--- a/docker/imposter/vulnerability/vulnerabilities_summary_cve.json
+++ b/docker/imposter/vulnerability/vulnerabilities_summary_cve.json
@@ -1,11 +1,11 @@
{
- "data": {
- "cve": {
- "CVE-2018-0495": 7,
- "CVE-2018-12404": 7,
- "CVE-2019-11719": 7,
- "CVE-2019-11727": 7
- }
- },
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "cve": {
+ "CVE-2018-0495": 7,
+ "CVE-2018-12404": 7,
+ "CVE-2019-11719": 7,
+ "CVE-2019-11727": 7
+ }
+ },
+ "error": 0
+}
diff --git a/docker/imposter/vulnerability/vulnerabilities_summary_cvss2_score.json b/docker/imposter/vulnerability/vulnerabilities_summary_cvss2_score.json
index 2e761e9f63..c948c10b44 100644
--- a/docker/imposter/vulnerability/vulnerabilities_summary_cvss2_score.json
+++ b/docker/imposter/vulnerability/vulnerabilities_summary_cvss2_score.json
@@ -1,11 +1,11 @@
{
- "data": {
- "cvss2_score": {
- "4.3": 143,
- "5": 250,
- "6.8": 229,
- "7.5": 111
- }
- },
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "cvss2_score": {
+ "4.3": 143,
+ "5": 250,
+ "6.8": 229,
+ "7.5": 111
+ }
+ },
+ "error": 0
+}
diff --git a/docker/imposter/vulnerability/vulnerabilities_summary_cvss3_score.json b/docker/imposter/vulnerability/vulnerabilities_summary_cvss3_score.json
index 2e37c16129..e3ca750d1e 100644
--- a/docker/imposter/vulnerability/vulnerabilities_summary_cvss3_score.json
+++ b/docker/imposter/vulnerability/vulnerabilities_summary_cvss3_score.json
@@ -1,11 +1,11 @@
{
- "data": {
- "cvss3_score": {
- "7.8": 296,
- "7.5": 215,
- "5.5": 152,
- "9.8": 137
- }
- },
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "cvss3_score": {
+ "7.8": 296,
+ "7.5": 215,
+ "5.5": 152,
+ "9.8": 137
+ }
+ },
+ "error": 0
+}
diff --git a/docker/imposter/vulnerability/vulnerabilities_summary_name.json b/docker/imposter/vulnerability/vulnerabilities_summary_name.json
index 91ad55a20c..4a69ff508a 100644
--- a/docker/imposter/vulnerability/vulnerabilities_summary_name.json
+++ b/docker/imposter/vulnerability/vulnerabilities_summary_name.json
@@ -1,11 +1,11 @@
{
- "data": {
- "name":{
- "linux-image-4.9.0-9-amd64": 402,
- "vim": 53,
- "vim-common": 53,
- "vim-runtime": 53
- }
- },
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "name": {
+ "linux-image-4.9.0-9-amd64": 402,
+ "vim": 53,
+ "vim-common": 53,
+ "vim-runtime": 53
+ }
+ },
+ "error": 0
+}
diff --git a/docker/imposter/vulnerability/vulnerabilities_summary_severity.json b/docker/imposter/vulnerability/vulnerabilities_summary_severity.json
index 920c9efbed..31f64cf9ed 100644
--- a/docker/imposter/vulnerability/vulnerabilities_summary_severity.json
+++ b/docker/imposter/vulnerability/vulnerabilities_summary_severity.json
@@ -1,11 +1,11 @@
{
- "data": {
- "severity": {
- "Critical": 8,
- "Medium": 3,
- "High": 1,
- "Low": 0
- }
- },
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "severity": {
+ "Critical": 8,
+ "Medium": 3,
+ "High": 1,
+ "Low": 0
+ }
+ },
+ "error": 0
+}
diff --git a/docker/imposter/vulnerability/vulnerabilities_summary_version.json b/docker/imposter/vulnerability/vulnerabilities_summary_version.json
index 82015bf2e2..6018501fca 100644
--- a/docker/imposter/vulnerability/vulnerabilities_summary_version.json
+++ b/docker/imposter/vulnerability/vulnerabilities_summary_version.json
@@ -1,11 +1,11 @@
{
- "data": {
- "version":{
- "4.9.168-1+deb9u2": 402,
- "2:8.0.0197-4+deb9u1": 265,
- "2.24-11+deb9u4": 114,
- "1:9.10.3.dfsg.P4-12.3+deb9u5": 99
- }
- },
- "error": 0
-}
\ No newline at end of file
+ "data": {
+ "version": {
+ "4.9.168-1+deb9u2": 402,
+ "2:8.0.0197-4+deb9u1": 265,
+ "2.24-11+deb9u4": 114,
+ "1:9.10.3.dfsg.P4-12.3+deb9u5": 99
+ }
+ },
+ "error": 0
+}
diff --git a/docker/imposter/wazuh-config.yml b/docker/imposter/wazuh-config.yml
index c266b05222..1d362e6d47 100755
--- a/docker/imposter/wazuh-config.yml
+++ b/docker/imposter/wazuh-config.yml
@@ -1,6 +1,6 @@
---
plugin: openapi
-specFile: https://raw.githubusercontent.com/wazuh/wazuh/4.4/api/api/spec/spec.yaml
+specFile: https://raw.githubusercontent.com/wazuh/wazuh/master/api/api/spec/spec.yaml
system:
stores:
# this store is preloaded from file
@@ -8,7 +8,6 @@ system:
preloadFile: initial_data.json
resources:
-
# ===================================================== #
# API INFO
# ===================================================== #
@@ -144,7 +143,6 @@ resources:
- method: GET
path: /agents/summary/status
-
# ===================================================== #
# CISCAT
# ===================================================== #
@@ -183,6 +181,9 @@ resources:
# Get cluster status
- method: GET
path: /cluster/status
+ response:
+ statusCode: 200
+ staticFile: cluster/cluster_status.json
# Get local node config
- method: GET
@@ -236,6 +237,9 @@ resources:
# Get node logs
- method: GET
path: /cluster/{node_id}/logs
+ response:
+ statusCode: 200
+ scriptFile: cluster/cluster-logs.js
# Get node logs summary
- method: GET
@@ -471,6 +475,9 @@ resources:
# Get logs
- method: GET
path: /manager/logs
+ response:
+ statusCode: 200
+ scriptFile: cluster/cluster-logs.js
# Get logs summary
- method: GET
@@ -603,6 +610,9 @@ resources:
# Get policy checks
- method: GET
path: /sca/{agent_id}/checks/{policy_id}
+ response:
+ statusCode: 200
+ scriptFile: sca/policy-checks.js
# ===================================================== #
# SECURITY
@@ -615,13 +625,6 @@ resources:
statusCode: 200
scriptFile: security/login.js
- # Login (@deprecated in 4.4.0)
- - method: GET
- path: /security/user/authenticate
- response:
- statusCode: 200
- scriptFile: security/login.js
-
# Logout current user
- method: DELETE
path: /security/user/authenticate
@@ -842,6 +845,9 @@ resources:
# Get last scan datetime
- method: GET
path: /vulnerability/{agent_id}/last_scan
+ response:
+ statusCode: 200
+ staticFile: vulnerability/last_scan.json
# Get agent vulnerabilities' field summary
- method: GET
diff --git a/docker/kbn-dev/dev.sh b/docker/kbn-dev/dev.sh
index 082a79c26f..3ecd9c0be9 100755
--- a/docker/kbn-dev/dev.sh
+++ b/docker/kbn-dev/dev.sh
@@ -1,6 +1,5 @@
#!/bin/bash
-
elastic_versions=(
'7.10.2'
'7.16.0'
@@ -17,13 +16,12 @@ elastic_versions=(
'8.2.3'
'8.3.0'
'8.3.1'
- '8.3.3'
- '8.4.2'
- '8.4.3'
- '8.5.0'
+ '8.3.3'
+ '8.4.2'
+ '8.4.3'
+ '8.5.0'
)
-
usage() {
echo
echo "./dev.sh elastic_version /wazuh_app_src action "
@@ -35,19 +33,16 @@ usage() {
exit -1
}
-
-if [ $# -ne 3 ]
- then
- echo "Incorrect number of arguments " $# ", got " $@
- echo
- usage
+if [ $# -ne 3 ]; then
+ echo "Incorrect number of arguments " $# ", got " $@
+ echo
+ usage
fi
-if [[ ! " ${elastic_versions[*]} " =~ " ${1} " ]]
- then
- echo "Version ${1} not found in ${elastic_versions[*]}"
- echo
- exit -1
+if [[ ! " ${elastic_versions[*]} " =~ " ${1} " ]]; then
+ echo "Version ${1} not found in ${elastic_versions[*]}"
+ echo
+ exit -1
fi
if [[ $2 != /* ]]; then
@@ -67,18 +62,18 @@ export SRC=$2
export COMPOSE_PROJECT_NAME=es-dev-${ES_VERSION//./} # /./ removes dots: 7.10.2 => 7102
case "$3" in
- up)
- docker compose -f dev.yml -p ${COMPOSE_PROJECT_NAME} up -Vd
- ;;
- down)
- docker compose -f dev.yml -p ${COMPOSE_PROJECT_NAME} down -v --remove-orphans
- ;;
- stop)
- docker compose -f dev.yml -p ${COMPOSE_PROJECT_NAME} stop
- ;;
- *)
- echo "Action must be up | down | stop: "
- echo
- usage
- ;;
+up)
+ docker compose -f dev.yml -p ${COMPOSE_PROJECT_NAME} up -Vd
+ ;;
+down)
+ docker compose -f dev.yml -p ${COMPOSE_PROJECT_NAME} down -v --remove-orphans
+ ;;
+stop)
+ docker compose -f dev.yml -p ${COMPOSE_PROJECT_NAME} stop
+ ;;
+*)
+ echo "Action must be up | down | stop: "
+ echo
+ usage
+ ;;
esac
diff --git a/docker/osd-dev/README.md b/docker/osd-dev/README.md
index 078c0b8a0c..b4e0ed94a6 100644
--- a/docker/osd-dev/README.md
+++ b/docker/osd-dev/README.md
@@ -45,10 +45,14 @@ version.
`OpenSearch` supported versions:
- 1.2.4
- 2.3.0
+- 2.4.0
+- 2.4.1
`OpenSearch Dashboards` supported versions:
- 1.2.0
- 2.3.0
+- 2.4.0
+- 2.4.1
We must use official `Wazuh Indexer` and `Wazuh Dashboard` images for
testing!
diff --git a/docker/osd-dev/config/2.x/osd/opensearch_dashboards.yml b/docker/osd-dev/config/2.x/osd/opensearch_dashboards.yml
index 1ba75aaea5..b532686b16 100755
--- a/docker/osd-dev/config/2.x/osd/opensearch_dashboards.yml
+++ b/docker/osd-dev/config/2.x/osd/opensearch_dashboards.yml
@@ -17,3 +17,6 @@ opensearch.ssl.certificateAuthorities: ["/home/node/kbn/certs/ca.pem"]
uiSettings.overrides.defaultRoute: /app/wazuh
opensearch.username: "kibanaserver"
opensearch.password: "kibanaserver"
+opensearchDashboards.branding:
+ useExpandedHeader: false
+
diff --git a/docker/osd-dev/dev.sh b/docker/osd-dev/dev.sh
index 80102e6a18..d0ee632dbb 100755
--- a/docker/osd-dev/dev.sh
+++ b/docker/osd-dev/dev.sh
@@ -6,6 +6,10 @@ os_versions=(
'2.1.0'
'2.2.1'
'2.3.0'
+ '2.4.0'
+ '2.4.1'
+ '2.5.0'
+ '2.6.0'
)
osd_versions=(
@@ -14,6 +18,10 @@ osd_versions=(
'2.1.0'
'2.2.1'
'2.3.0'
+ '2.4.0'
+ '2.4.1'
+ '2.5.0'
+ '2.6.0'
)
usage() {
@@ -72,10 +80,10 @@ profile="standard"
export WAZUH_DASHBOARD_CONF=./config/${OSD_MAJOR}/osd/opensearch_dashboards.yml
export SEC_CONFIG_FILE=./config/${OSD_MAJOR}/os/config.yml
if [[ "$5" =~ "saml" ]]; then
- cat /etc/hosts | grep -q "idp" || exit_with_message "Add idp to /etc/hosts"
+ cat /etc/hosts | grep -q "idp" || exit_with_message "Add idp to /etc/hosts"
profile="saml"
- export WAZUH_DASHBOARD_CONF=./config/${OSD_MAJOR}/osd/opensearch_dashboards_saml.yml
+ export WAZUH_DASHBOARD_CONF=./config/${OSD_MAJOR}/osd/opensearch_dashboards_saml.yml
export SEC_CONFIG_FILE=./config/${OSD_MAJOR}/os/config-saml.yml
fi
@@ -86,6 +94,7 @@ fi
case "$4" in
up)
+ /bin/bash ../scripts/create_docker_networks.sh
docker compose --profile $profile -f dev.yml up -Vd
;;
down)
diff --git a/docker/scripts/create_docker_networks.sh b/docker/scripts/create_docker_networks.sh
new file mode 100644
index 0000000000..0f0c6e2490
--- /dev/null
+++ b/docker/scripts/create_docker_networks.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+networks=('mon' 'devel')
+
+# Function to check if the Docker network exists in the host. If not, creates it.
+# Arguments:
+# $1: Docker network name
+# Usage:
+# check_and_create_network
+check_and_create_network() {
+ if [ -z "$(docker network ls | grep $1)" ]; then
+ docker network create $1
+ fi
+}
+
+for network in ${networks[@]}; do
+ check_and_create_network ${network}
+done
\ No newline at end of file
diff --git a/kibana.json b/opensearch_dashboards.json
similarity index 61%
rename from kibana.json
rename to opensearch_dashboards.json
index 81fb35ae81..517164d819 100644
--- a/kibana.json
+++ b/opensearch_dashboards.json
@@ -1,7 +1,7 @@
{
"id": "wazuh",
- "version": "4.3.10-4311",
- "kibanaVersion": "kibana",
+ "version": "4.5.0-00",
+ "opensearchDashboardsVersion": "opensearchDashboards",
"configPath": [
"wazuh"
],
@@ -11,21 +11,19 @@
"discover",
"inspector",
"visualizations",
- "kibanaLegacy",
"uiActions",
"charts",
"savedObjects",
- "kibanaReact",
- "kibanaUtils",
- "securityOss"
+ "opensearchDashboardsReact",
+ "opensearchDashboardsUtils",
+ "opensearchDashboardsLegacy"
],
"optionalPlugins": [
"security",
- "opendistroSecurityKibana",
+ "securityDashboards",
"searchguard",
- "spaces",
"telemetry"
],
"server": true,
"ui": true
-}
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 399dc20e3d..16a409ab6f 100644
--- a/package.json
+++ b/package.json
@@ -1,14 +1,15 @@
{
"name": "wazuh",
- "version": "4.3.10",
- "revision": "4311",
- "code": "4311",
+ "version": "4.5.0",
+ "revision": "00",
+ "stage": "pre-alpha",
+ "commit": "19e41c3bf",
"pluginPlatform": {
- "version": "7.10.2"
+ "version": "2.6.0"
},
- "description": "Wazuh app",
+ "description": "Wazuh dashboard",
"keywords": [
- "kibana",
+ "opensearch_dashboards",
"wazuh",
"ossec"
],
@@ -33,7 +34,7 @@
"kbn": "node ../../scripts/kbn",
"es": "node ../../scripts/es",
"start": "plugin-helpers start",
- "build": "yarn plugin-helpers build --kibana-version=$KIBANA_VERSION",
+ "build": "yarn plugin-helpers build --opensearch-dashboards-version=$OPENSEARCH_DASHBOARDS_VERSION",
"plugin-helpers": "node ../../scripts/plugin_helpers",
"test:ui:runner": "node ../../scripts/functional_test_runner.js",
"test:server": "plugin-helpers test:server",
@@ -43,46 +44,44 @@
"prebuild": "node scripts/generate-build-version"
},
"dependencies": {
- "angular-animate": "1.7.8",
- "angular-chart.js": "1.1.1",
- "angular-material": "1.1.18",
- "axios": "^0.21.1",
- "install": "^0.10.1",
- "js2xmlparser": "^3.0.0",
+ "angular-animate": "1.8.3",
+ "angular-material": "1.2.5",
+ "axios": "^1.3.4",
+ "install": "^0.13.0",
+ "js2xmlparser": "^5.0.0",
"json2csv": "^4.1.2",
- "jwt-decode": "^2.2.0",
+ "jwt-decode": "^3.1.2",
"loglevel": "^1.7.1",
- "markdown-it-link-attributes": "^3.0.0",
+ "markdown-it-link-attributes": "^4.0.1",
"md5": "^2.3.0",
- "needle": "^2.0.1",
+ "needle": "^3.2.0",
"node-cron": "^1.1.2",
- "pdfmake": "0.1.65",
- "pug-loader": "^2.4.0",
+ "pdfmake": "0.2.7",
"querystring-browser": "1.0.4",
"react-codemirror": "^1.0.0",
"react-cookie": "^4.0.3",
"read-last-lines": "^1.7.2",
"timsort": "^0.3.0",
"typescript": "^4.4.2",
- "winston": "3.0.0"
+ "winston": "3.8.2"
},
"devDependencies": {
"@types/node-cron": "^2.0.3",
- "@typescript-eslint/eslint-plugin": "^3.10.0",
- "@typescript-eslint/parser": "^3.10.0",
- "eslint": "^7.32.0",
+ "@typescript-eslint/eslint-plugin": "^5.38.1",
+ "@typescript-eslint/parser": "^5.38.1",
+ "eslint": "^8.24.0",
"eslint-config-prettier": "^8.5.0",
- "eslint-import-resolver-typescript": "2.7.1",
+ "eslint-import-resolver-typescript": "3.5.3",
"eslint-plugin-async-await": "^0.0.0",
"eslint-plugin-cypress": "^2.12.1",
- "eslint-plugin-filenames-simple": "^0.6.0",
+ "eslint-plugin-filenames-simple": "^0.8.0",
"eslint-plugin-import": "^2.26.0",
- "eslint-plugin-prettier": "^3.1.4",
+ "eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-react": "^7.31.8",
"eslint-plugin-react-hooks": "^4.6.0",
"prettier": "^2.7.1",
"redux-mock-store": "^1.5.4",
- "tslint": "^5.11.0",
- "typescript-eslint-parser": "^18.0.0"
+ "tslint": "^6.1.3",
+ "typescript-eslint-parser": "^22.0.0"
}
}
diff --git a/public/app.js b/public/app.js
index 87207e4372..e1c8441bb6 100644
--- a/public/app.js
+++ b/public/app.js
@@ -20,9 +20,6 @@ require('./utils/dom-to-image.js');
// EUI React components wrapper
import './components';
-// angular-charts.js
-import 'angular-chart.js';
-
// pin-wz-menu.js
import { changeWazuhNavLogo } from './utils/wz-logo-menu';
@@ -127,7 +124,7 @@ app.run(function ($rootElement) {
console.error('[ERROR] - User token could not be deprecated - ', err);
})
.finally(() => {
- window.location = event.currentTarget.href;
+ window.location = event.currentTarget.href;
});
});
});
diff --git a/public/components/agents/agent-synced.tsx b/public/components/agents/agent-synced.tsx
new file mode 100644
index 0000000000..a5ac3f55cc
--- /dev/null
+++ b/public/components/agents/agent-synced.tsx
@@ -0,0 +1,22 @@
+import React from 'react';
+import { EuiHealth } from "@elastic/eui";
+import { AGENT_SYNCED_STATUS } from '../../../common/constants';
+
+interface SyncedProps {
+ synced: string;
+}
+
+export const AgentSynced = ({ synced }: SyncedProps) => {
+ const color = {
+ [AGENT_SYNCED_STATUS.SYNCED]: 'success',
+ [AGENT_SYNCED_STATUS.NOT_SYNCED]: 'subdued',
+ }[synced];
+
+ return (
+
+
+ {synced}
+
+
+ );
+}
\ No newline at end of file
diff --git a/public/components/agents/fim/inventory/registry-table.tsx b/public/components/agents/fim/inventory/registry-table.tsx
index 1ada1eda57..a03ab38ae6 100644
--- a/public/components/agents/fim/inventory/registry-table.tsx
+++ b/public/components/agents/fim/inventory/registry-table.tsx
@@ -15,12 +15,8 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiBasicTable,
- EuiOverlayMask,
- EuiOutsideClickDetector,
Direction,
} from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n/react';
import { WzRequest } from '../../../../react-services/wz-request';
import { FlyoutDetail } from './flyout';
import { filtersToObject } from '../../../wz-search-bar';
diff --git a/public/components/agents/sca/index.ts b/public/components/agents/sca/index.ts
index 0184fc57f7..90f98e1d76 100644
--- a/public/components/agents/sca/index.ts
+++ b/public/components/agents/sca/index.ts
@@ -1,2 +1,3 @@
export { MainSca } from './main';
-export { Inventory } from './inventory';
\ No newline at end of file
+export { Inventory } from './inventory';
+export * from './inventory/index'
\ No newline at end of file
diff --git a/public/components/agents/sca/inventory.tsx b/public/components/agents/sca/inventory.tsx
index e74d009176..4361b3d5a4 100644
--- a/public/components/agents/sca/inventory.tsx
+++ b/public/components/agents/sca/inventory.tsx
@@ -16,8 +16,6 @@ import {
EuiFlexGroup,
EuiPanel,
EuiPage,
- EuiBasicTable,
- EuiInMemoryTable,
EuiSpacer,
EuiText,
EuiProgress,
@@ -25,8 +23,6 @@ import {
EuiButton,
EuiButtonIcon,
EuiStat,
- EuiHealth,
- EuiDescriptionList,
EuiButtonEmpty,
EuiToolTip,
EuiCallOut,
@@ -35,10 +31,7 @@ import {
} from '@elastic/eui';
import { WzRequest } from '../../../react-services/wz-request';
import { formatUIDate } from '../../../react-services/time-service';
-import exportCsv from '../../../react-services/wz-csv';
import { getToasts } from '../../../kibana-services';
-import { WzSearchBar } from '../../../components/wz-search-bar';
-import { RuleText, ComplianceText } from './components';
import _ from 'lodash';
import {
UI_ERROR_SEVERITIES,
@@ -46,131 +39,106 @@ import {
UIErrorSeverity,
UILogLevel,
} from '../../../react-services/error-orchestrator/types';
-import { API_NAME_AGENT_STATUS, UI_LOGGER_LEVELS } from '../../../../common/constants';
+import {
+ API_NAME_AGENT_STATUS,
+ MODULE_SCA_CHECK_RESULT_LABEL,
+ UI_LOGGER_LEVELS,
+} from '../../../../common/constants';
import { getErrorOrchestrator } from '../../../react-services/common-services';
import { VisualizationBasic } from '../../common/charts/visualizations/basic';
+import { AppNavigate } from '../../../react-services/app-navigate';
+import SCAPoliciesTable from './inventory/agent-policies-table';
+import { InventoryPolicyChecksTable } from './inventory/checks-table';
+import { RuleText } from './components';
+
+type InventoryProps = {
+ agent: { [key: string]: any };
+};
-export class Inventory extends Component {
+type InventoryState = {
+ itemIdToExpandedRowMap: object;
+ showMoreInfo: boolean;
+ loading: boolean;
+ checksIsLoading: boolean;
+ redirect: boolean;
+ filters: object[];
+ pageTableChecks: { pageIndex: number; pageSize?: number };
+ policies: object[];
+ checks: object[];
+ lookingPolicy: { [key: string]: any } | boolean;
+ loadingPolicy: boolean;
+ secondTable: boolean;
+ secondTableBack: boolean;
+};
+export class Inventory extends Component {
_isMount = false;
+ agent: { [key: string]: any } = {};
+ columnsPolicies: object[];
+ lookingPolicy: { [key: string]: any } | false = false;
constructor(props) {
super(props);
- const { agent } = this.props;
this.state = {
- agent,
- items: [],
itemIdToExpandedRowMap: {},
showMoreInfo: false,
loading: false,
filters: [],
pageTableChecks: { pageIndex: 0 },
policies: [],
+ checks: [],
+ redirect: false,
+ secondTable: false,
+ secondTableBack: false,
+ checksIsLoading: false,
+ lookingPolicy: false,
+ loadingPolicy: false,
};
- this.suggestions = {};
+
this.columnsPolicies = [
{
field: 'name',
name: 'Policy',
+ sortable: true,
},
{
field: 'description',
name: 'Description',
truncateText: true,
+ sortable: true,
},
{
field: 'end_scan',
name: 'End scan',
dataType: 'date',
render: formatUIDate,
+ sortable: true,
},
{
field: 'pass',
- name: 'Pass',
+ name: MODULE_SCA_CHECK_RESULT_LABEL.passed,
width: '100px',
+ sortable: true,
},
{
field: 'fail',
- name: 'Fail',
+ name: MODULE_SCA_CHECK_RESULT_LABEL.failed,
width: '100px',
+ sortable: true,
},
{
field: 'invalid',
- name: 'Not applicable',
+ name: MODULE_SCA_CHECK_RESULT_LABEL['not applicable'],
width: '100px',
+ sortable: true,
},
{
field: 'score',
name: 'Score',
- render: (score) => {
+ render: score => {
return `${score}%`;
},
width: '100px',
},
];
- this.columnsChecks = [
- {
- field: 'id',
- name: 'ID',
- sortable: true,
- width: '100px',
- },
- {
- field: 'title',
- name: 'Title',
- sortable: true,
- truncateText: true,
- },
- {
- name: 'Target',
- truncateText: true,
- render: (item) => (
-
- {item.file ? (
-
- File: {item.file}
-
- ) : item.directory ? (
-
- Directory: {item.directory}
-
- ) : item.process ? (
-
- Process: {item.process}
-
- ) : item.command ? (
-
- Command: {item.command}
-
- ) : item.registry ? (
-
- Registry: {item.registry}
-
- ) : (
- '-'
- )}
-
- ),
- },
- {
- field: 'result',
- name: 'Result',
- truncateText: true,
- sortable: true,
- width: '150px',
- render: this.addHealthResultRender,
- },
- {
- align: 'right',
- width: '40px',
- isExpander: true,
- render: (item) => (
- this.toggleDetails(item)}
- aria-label={this.state.itemIdToExpandedRowMap[item.id] ? 'Collapse' : 'Expand'}
- iconType={this.state.itemIdToExpandedRowMap[item.id] ? 'arrowUp' : 'arrowDown'}
- />
- ),
- },
- ];
}
async componentDidMount() {
@@ -182,13 +150,19 @@ export class Inventory extends Component {
if (match && match[0]) {
this.setState({ loading: true });
const id = match[0].split('=')[1];
- const policy = await WzRequest.apiReq('GET', `/sca/${this.props.agent.id}`, {
- q: 'policy_id=' + id,
- });
- await this.loadScaPolicy(((((policy || {}).data || {}).data || {}).items || [])[0]);
+ const policy = await WzRequest.apiReq(
+ 'GET',
+ `/sca/${this.props.agent.id}`,
+ {
+ q: 'policy_id=' + id,
+ },
+ );
+ await this.loadScaPolicy(
+ ((((policy || {}).data || {}).data || {}).items || [])[0],
+ );
window.location.href = window.location.href.replace(
new RegExp('redirectPolicy=' + '[^&]*'),
- ''
+ '',
);
this.setState({ loading: false });
}
@@ -211,161 +185,38 @@ export class Inventory extends Component {
async componentDidUpdate(prevProps, prevState) {
if (!_.isEqual(this.props.agent, prevProps.agent)) {
- this.setState({ lookingPolicy: false }, async () => await this.initialize());
+ this.setState(
+ { lookingPolicy: false },
+ async () => await this.initialize(),
+ );
}
if (!_.isEqual(this.state.filters, prevState.filters)) {
this.setState({
itemIdToExpandedRowMap: {},
- pageTableChecks: { pageIndex: 0, pageSize: this.state.pageTableChecks.pageSize },
+ pageTableChecks: {
+ pageIndex: 0,
+ pageSize: this.state.pageTableChecks.pageSize,
+ },
});
}
+
+ const regex = new RegExp('redirectPolicyTable=' + '[^&]*');
+ const match = window.location.href.match(regex);
+ if (
+ match &&
+ match[0] &&
+ !this.state.secondTable &&
+ !this.state.secondTableBack
+ ) {
+ this.loadScaPolicy(match[0].split('=')[1], true);
+ this.setState({ secondTableBack: true, checksIsLoading: true });
+ }
}
componentWillUnmount() {
this._isMount = false;
}
- addHealthResultRender(result) {
- const color = (result) => {
- if (result.toLowerCase() === 'passed') {
- return 'success';
- } else if (result.toLowerCase() === 'failed') {
- return 'danger';
- } else {
- return 'subdued';
- }
- };
-
- return (
-
- {result || 'Not applicable'}
-
- );
- }
-
- /**
- * Generate and assign the suggestions for the searchbar
- * @param policy
- * @param checks
- * @returns
- */
- buildSuggestionSearchBar(policy, checks) {
- if (this.suggestions[policy]) return;
- const distinctFields = {};
- checks.forEach((item) => {
- Object.keys(item).forEach((field) => {
- if (typeof item[field] === 'string') {
- if (!distinctFields[field]) {
- distinctFields[field] = {};
- }
- if (!distinctFields[field][item[field]]) {
- distinctFields[field][item[field]] = true;
- }
- }
- });
- });
-
- /**
- * Get list of values defined in distinctFields by field
- * @param value
- * @param field
- * @returns
- */
- const getSuggestionsValues = (value, field) => {
- if (!distinctFields[field]) return [];
- return Object.keys(distinctFields[field]).filter(
- (item) => item && item.toLowerCase().includes(value.toLowerCase().trim())
- );
- };
-
- /**
- * Get list of suggestions.
- * This method validate if the suggestion item exists in the checks array fields
- * @returns List of suggestions
- */
- const getSuggestionsFields = () => {
- const defaultSuggestions = [
- {
- type: 'params',
- label: 'condition',
- description: 'Filter by check condition',
- operators: ['=', '!='],
- values: (value) => getSuggestionsValues(value, 'condition'),
- },
- {
- type: 'params',
- label: 'file',
- description: 'Filter by check file',
- operators: ['=', '!='],
- values: (value) => getSuggestionsValues(value, 'file'),
- },
- {
- type: 'params',
- label: 'title',
- description: 'Filter by check title',
- operators: ['=', '!='],
- values: (value) => getSuggestionsValues(value, 'title'),
- },
- {
- type: 'params',
- label: 'result',
- description: 'Filter by check result',
- operators: ['=', '!='],
- values: (value) => getSuggestionsValues(value, 'result'),
- },
- {
- type: 'params',
- label: 'status',
- description: 'Filter by check status',
- operators: ['=', '!='],
- values: (value) => getSuggestionsValues(value, 'status'),
- },
- {
- type: 'params',
- label: 'rationale',
- description: 'Filter by check rationale',
- operators: ['=', '!='],
- values: (value) => getSuggestionsValues(value, 'rationale'),
- },
- {
- type: 'params',
- label: 'registry',
- description: 'Filter by check registry',
- operators: ['=', '!='],
- values: (value) => getSuggestionsValues(value, 'registry'),
- },
- {
- type: 'params',
- label: 'description',
- description: 'Filter by check description',
- operators: ['=', '!='],
- values: (value) => getSuggestionsValues(value, 'description'),
- },
- {
- type: 'params',
- label: 'remediation',
- description: 'Filter by check remediation',
- operators: ['=', '!='],
- values: (value) => getSuggestionsValues(value, 'remediation'),
- },
- {
- type: 'params',
- label: 'reason',
- description: 'Filter by check reason',
- operators: ['=', '!='],
- values: (value) => getSuggestionsValues(value, 'reason'),
- },
- ];
-
- const filteresSuggestions = defaultSuggestions.filter((item) =>
- Object.keys(distinctFields).includes(item.label)
- );
- return filteresSuggestions;
- };
-
- this.suggestions[policy] = getSuggestionsFields();
- }
-
async initialize() {
try {
this._isMount && this.setState({ loading: true });
@@ -393,37 +244,46 @@ export class Inventory extends Component {
}
}
- async loadScaPolicy(policy) {
+ handleBack(ev) {
+ AppNavigate.navigateToModule(ev, 'agents', {
+ tab: 'welcome',
+ agent: this.props.agent.id,
+ });
+ ev.stopPropagation();
+ }
+
+ async loadScaPolicy(policy, secondTable?) {
this._isMount &&
this.setState({
loadingPolicy: true,
itemIdToExpandedRowMap: {},
pageTableChecks: { pageIndex: 0 },
+ secondTable: secondTable ? secondTable : false,
});
if (policy) {
try {
- const policyResponse = await WzRequest.apiReq('GET', `/sca/${this.props.agent.id}`, {
- params: {
- q: 'policy_id=' + policy.policy_id,
- },
- });
- const [policyData] = policyResponse.data.data.affected_items;
- // It queries all checks without filters, because the filters are applied in the results
- // due to the use of EuiInMemoryTable instead EuiTable components and do a request with each change of filters.
- const checksResponse = await WzRequest.apiReq(
+ const policyResponse = await WzRequest.apiReq(
'GET',
- `/sca/${this.props.agent.id}/checks/${policy.policy_id}`,
- {}
+ `/sca/${this.props.agent.id}`,
+ {
+ params: {
+ q: 'policy_id=' + policy,
+ },
+ },
);
- const checks = (
- (((checksResponse || {}).data || {}).data || {}).affected_items || []
- ).map((item) => ({ ...item, result: item.result || 'not applicable' }));
- this.buildSuggestionSearchBar(policyData.policy_id, checks);
+ const [policyData] = policyResponse.data.data.affected_items;
this._isMount &&
- this.setState({ lookingPolicy: policyData, loadingPolicy: false, items: checks });
+ this.setState({
+ lookingPolicy: policyData,
+ loadingPolicy: false,
+ checksIsLoading: false,
+ });
} catch (error) {
- this.setState({ lookingPolicy: policy, loadingPolicy: false });
-
+ this.setState({
+ lookingPolicy: policy,
+ loadingPolicy: false,
+ checksIsLoading: false,
+ });
const options: UIErrorLog = {
context: `${Inventory.name}.loadScaPolicy`,
level: UI_LOGGER_LEVELS.ERROR as UILogLevel,
@@ -437,28 +297,17 @@ export class Inventory extends Component {
getErrorOrchestrator().handleError(options);
}
} else {
- this._isMount && this.setState({ lookingPolicy: policy, loadingPolicy: false, items: [] });
+ this._isMount &&
+ this.setState({
+ lookingPolicy: policy,
+ loadingPolicy: false,
+ items: [],
+ checksIsLoading: false,
+ });
}
}
- filterPolicyChecks = () =>
- !!this.state.items &&
- this.state.items.filter((check) =>
- this.state.filters.every((filter) =>
- filter.field === 'search'
- ? Object.keys(check).some(
- (key) =>
- ['string', 'number'].includes(typeof check[key]) &&
- String(check[key]).toLowerCase().includes(filter.value.toLowerCase())
- )
- : typeof check[filter.field] === 'string' &&
- (filter.value === ''
- ? check[filter.field] === filter.value
- : check[filter.field].toLowerCase().includes(filter.value.toLowerCase()))
- )
- );
-
- toggleDetails = (item) => {
+ toggleDetails = item => {
const itemIdToExpandedRowMap = { ...this.state.itemIdToExpandedRowMap };
if (itemIdToExpandedRowMap[item.id]) {
@@ -469,9 +318,8 @@ export class Inventory extends Component {
checks += item.condition ? ` (Condition: ${item.condition})` : '';
const complianceText =
item.compliance && item.compliance.length
- ? item.compliance.map((el) => `${el.key}: ${el.value}`).join('\n')
+ ? item.compliance.map(el => `${el.key}: ${el.value}`).join('\n')
: '';
- const rulesText = item.rules.length ? item.rules.map((el) => el.rule).join('\n') : '';
const listItems = [
{
title: 'Check not applicable due to:',
@@ -502,10 +350,12 @@ export class Inventory extends Component {
description: ,
},
];
- const itemsToShow = listItems.filter((x) => {
+ const itemsToShow = listItems.filter(x => {
return x.description;
});
- itemIdToExpandedRowMap[item.id] = ;
+ itemIdToExpandedRowMap[item.id] = (
+
+ );
}
this.setState({ itemIdToExpandedRowMap });
};
@@ -517,31 +367,13 @@ export class Inventory extends Component {
toastLifeTimeMs: time,
});
};
- async downloadCsv() {
- try {
- this.showToast('success', 'Your download should begin automatically...', 3000);
- await exportCsv(
- '/sca/' + this.props.agent.id + '/checks/' + this.state.lookingPolicy.policy_id,
- [],
- this.state.lookingPolicy.policy_id
- );
- } catch (error) {
- const options: UIErrorLog = {
- context: `${Inventory.name}.downloadCsv`,
- level: UI_LOGGER_LEVELS.ERROR as UILogLevel,
- severity: UI_ERROR_SEVERITIES.BUSINESS as UIErrorSeverity,
- error: {
- error: error,
- message: error.message || error,
- title: error.name,
- },
- };
- getErrorOrchestrator().handleError(options);
- }
- }
buttonStat(text, field, value) {
- return this.setState({ filters: [{ field, value }] })}>{text} ;
+ return (
+ this.setState({ filters: [{ field, value }] })}>
+ {text}
+
+ );
}
onChangeTableChecks({ page: { index: pageIndex, size: pageSize } }) {
@@ -549,267 +381,255 @@ export class Inventory extends Component {
}
render() {
- const getPoliciesRowProps = (item, idx) => {
- return {
- 'data-test-subj': `sca-row-${idx}`,
- className: 'customRowClass',
- onClick: () => this.loadScaPolicy(item),
- };
- };
- const getChecksRowProps = (item, idx) => {
- return {
- 'data-test-subj': `sca-check-row-${idx}`,
- className: 'customRowClass',
- onClick: () => this.toggleDetails(item),
- };
- };
+ const { onClickRow } = this.props;
- const sorting = {
- sort: {
- field: 'id',
- direction: 'asc',
- },
+ const handlePoliciesTableClickRow = async policy => {
+ onClickRow
+ ? onClickRow(policy)
+ : await this.loadScaPolicy(policy.policy_id);
+ this.setState({ loading: false, redirect: true });
};
+
const buttonPopover = (
this.setState({ showMoreInfo: !this.state.showMoreInfo })}
+ iconType='iInCircle'
+ aria-label='Help'
+ onClick={() =>
+ this.setState({ showMoreInfo: !this.state.showMoreInfo })
+ }
>
);
+ const { agent } = this.props;
+
return (
- {this.state.loading && (
-
-
-
-
- )}
+ {this.state.loading ||
+ (this.state.checksIsLoading && (
+
+
+
+
+ ))}
- {this.props.agent &&
- (this.props.agent || {}).status !== API_NAME_AGENT_STATUS.NEVER_CONNECTED &&
+ {agent &&
+ (agent || {}).status !== API_NAME_AGENT_STATUS.NEVER_CONNECTED &&
!this.state.policies.length &&
!this.state.loading && (
-
- this.initialize()}>
+
+ this.initialize()}>
Refresh
-
-
- )}
+
+
+ )}
- {this.props.agent &&
- (this.props.agent || {}).status === API_NAME_AGENT_STATUS.NEVER_CONNECTED &&
+ {agent &&
+ (agent || {}).status === API_NAME_AGENT_STATUS.NEVER_CONNECTED &&
!this.state.loading && (
-
- this.initialize()}>
+
+ this.initialize()}>
Refresh
-
-
- )}
- {this.props.agent &&
- (this.props.agent || {}).os &&
+
+
+ )}
+ {agent &&
+ (agent || {}).os &&
!this.state.lookingPolicy &&
this.state.policies.length > 0 &&
- !this.state.loading && (
-
- {this.state.policies.length && (
-
- {this.state.policies.map((policy, idx) => (
-
-
-
-
-
-
- ))}
-
- )}
-
-
-
-
-
-
-
-
-
- )}
- {this.props.agent &&
- (this.props.agent || {}).os &&
- this.state.lookingPolicy &&
- !this.state.loading && (
-
-
-
-
- this.loadScaPolicy(false)}
- iconType="arrowLeft"
- aria-label="Back to policies"
- {...{ iconSize: 'l' }}
- />
-
-
-
-
- {this.state.lookingPolicy.name}
-
- this.setState({ showMoreInfo: false })}
- >
-
-
-
- Policy description: {this.state.lookingPolicy.description}
-
- Policy checksum: {this.state.lookingPolicy.hash_file}
-
-
-
-
-
-
-
-
- await this.downloadCsv()}
+ !this.state.loading &&
+ !this.state.checksIsLoading && (
+
+ {this.state.policies.length && (
+
+ {this.state.policies.map((policy: any, idx) => (
+
+
- Export formatted
-
+
+
+
-
- this.loadScaPolicy(this.state.lookingPolicy)}
- >
- Refresh
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {
- this.setState({ filters });
- }}
- />
-
-
-
-
-
- this.onChangeTableChecks(change)}
- />
-
-
-
-
- )}
+ ))}
+
+ )}
+
+
+
+
+
+
+
+
+
+ )}
+ {agent &&
+ (agent || {}).os &&
+ this.state.lookingPolicy &&
+ (!this.state.loading || !this.state.checksIsLoading) && (
+
+
+
+
+ this.handleBack(ev)
+ : () => this.loadScaPolicy(false)
+ }
+ iconType='arrowLeft'
+ aria-label='Back to policies'
+ {...{ iconSize: 'l' }}
+ />
+
+
+
+
+ {this.state.lookingPolicy.name}
+
+
+ this.setState({ showMoreInfo: false })
+ }
+ >
+
+
+
+ Policy description: {' '}
+ {this.state.lookingPolicy.description}
+
+ Policy checksum: {' '}
+ {this.state.lookingPolicy.hash_file}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
);
}
}
+
+Inventory.defaultProps = {
+ onClickRow: undefined,
+};
diff --git a/public/components/agents/sca/inventory/agent-policies-table.tsx b/public/components/agents/sca/inventory/agent-policies-table.tsx
new file mode 100644
index 0000000000..2ab8309e7e
--- /dev/null
+++ b/public/components/agents/sca/inventory/agent-policies-table.tsx
@@ -0,0 +1,33 @@
+import React from 'react';
+import { TableWzAPI } from '../../../common/tables/table-wz-api';
+
+type Props = {
+ columns: any[];
+ rowProps?: any;
+ agent: { [key in string]: any };
+ tableProps?: any;
+};
+
+export default function SCAPoliciesTable(props: Props) {
+ const { columns, rowProps, agent, tableProps } = props;
+
+ const getPoliciesRowProps = (item: any, idx: string) => {
+ return {
+ 'data-test-subj': `sca-row-${idx}`,
+ className: 'customRowClass',
+ onClick: rowProps ? () => rowProps(item) : null
+ }
+ }
+
+ return (
+ <>
+
+ >
+ );
+}
diff --git a/public/components/agents/sca/inventory/checks-table.tsx b/public/components/agents/sca/inventory/checks-table.tsx
new file mode 100644
index 0000000000..8f8641797f
--- /dev/null
+++ b/public/components/agents/sca/inventory/checks-table.tsx
@@ -0,0 +1,333 @@
+import { EuiButtonIcon, EuiDescriptionList, EuiHealth } from '@elastic/eui';
+import React, { Component } from 'react';
+import { MODULE_SCA_CHECK_RESULT_LABEL } from '../../../../../common/constants';
+import { TableWzAPI } from '../../../common/tables';
+import { IWzSuggestItem } from '../../../wz-search-bar';
+import { ComplianceText, RuleText } from '../components';
+import { getFilterValues } from './lib';
+
+type Props = {
+ agent: { [key: string]: any };
+ lookingPolicy: { [key: string]: any };
+ filters: any[];
+};
+
+type State = {
+ agent: { [key: string]: any };
+ lookingPolicy: { [key: string]: any };
+ itemIdToExpandedRowMap: {};
+ filters: any[];
+ pageTableChecks: { pageIndex: 0 };
+};
+
+export class InventoryPolicyChecksTable extends Component {
+ _isMount = false;
+ suggestions: IWzSuggestItem[] = [];
+ columnsChecks: any;
+ constructor(props) {
+ super(props);
+ const { agent, lookingPolicy, filters } = this.props;
+ this.state = {
+ agent,
+ lookingPolicy,
+ itemIdToExpandedRowMap: {},
+ filters: filters || [],
+ pageTableChecks: { pageIndex: 0 },
+ };
+ this.suggestions = [
+ {
+ type: 'params',
+ label: 'condition',
+ description: 'Filter by check condition',
+ operators: ['=', '!='],
+ values: (value) =>
+ getFilterValues(
+ 'condition',
+ value,
+ this.props.agent.id,
+ this.props.lookingPolicy.policy_id
+ ),
+ },
+ {
+ type: 'params',
+ label: 'description',
+ description: 'Filter by check description',
+ operators: ['=', '!='],
+ values: (value) =>
+ getFilterValues(
+ 'description',
+ value,
+ this.props.agent.id,
+ this.props.lookingPolicy.policy_id
+ ),
+ },
+ {
+ type: 'params',
+ label: 'file',
+ description: 'Filter by check file',
+ operators: ['=', '!='],
+ values: (value) =>
+ getFilterValues('file', value, this.props.agent.id, this.props.lookingPolicy.policy_id),
+ },
+ {
+ type: 'params',
+ label: 'registry',
+ description: 'Filter by check registry',
+ operators: ['=', '!='],
+ values: (value) =>
+ getFilterValues(
+ 'registry',
+ value,
+ this.props.agent.id,
+ this.props.lookingPolicy.policy_id
+ ),
+ },
+ {
+ type: 'params',
+ label: 'rationale',
+ description: 'Filter by check rationale',
+ operators: ['=', '!='],
+ values: (value) =>
+ getFilterValues(
+ 'rationale',
+ value,
+ this.props.agent.id,
+ this.props.lookingPolicy.policy_id
+ ),
+ },
+ {
+ type: 'params',
+ label: 'reason',
+ description: 'Filter by check reason',
+ operators: ['=', '!='],
+ values: (value) =>
+ getFilterValues('reason', value, this.props.agent.id, this.props.lookingPolicy.policy_id),
+ },
+ {
+ type: 'params',
+ label: 'remediation',
+ description: 'Filter by check remediation',
+ operators: ['=', '!='],
+ values: (value) =>
+ getFilterValues(
+ 'remediation',
+ value,
+ this.props.agent.id,
+ this.props.lookingPolicy.policy_id
+ ),
+ },
+ {
+ type: 'params',
+ label: 'result',
+ description: 'Filter by check result',
+ operators: ['=', '!='],
+ values: (value) =>
+ getFilterValues('result', value, this.props.agent.id, this.props.lookingPolicy.policy_id),
+ },
+ {
+ type: 'params',
+ label: 'title',
+ description: 'Filter by check title',
+ operators: ['=', '!='],
+ values: (value) =>
+ getFilterValues('title', value, this.props.agent.id, this.props.lookingPolicy.policy_id),
+ },
+ ];
+ this.columnsChecks = [
+ {
+ field: 'id',
+ name: 'ID',
+ sortable: true,
+ width: '100px',
+ },
+ {
+ field: 'title',
+ name: 'Title',
+ sortable: true,
+ truncateText: true,
+ },
+ {
+ name: 'Target',
+ truncateText: true,
+ render: (item) => (
+
+ {item.file ? (
+
+ File: {item.file}
+
+ ) : item.directory ? (
+
+ Directory: {item.directory}
+
+ ) : item.process ? (
+
+ Process: {item.process}
+
+ ) : item.command ? (
+
+ Command: {item.command}
+
+ ) : item.registry ? (
+
+ Registry: {item.registry}
+
+ ) : (
+ '-'
+ )}
+
+ ),
+ },
+ {
+ field: 'result',
+ name: 'Result',
+ truncateText: true,
+ sortable: true,
+ width: '150px',
+ render: this.addHealthResultRender,
+ },
+ {
+ align: 'right',
+ width: '40px',
+ isExpander: true,
+ render: (item) => (
+ this.toggleDetails(item)}
+ aria-label={this.state.itemIdToExpandedRowMap[item.id] ? 'Collapse' : 'Expand'}
+ iconType={this.state.itemIdToExpandedRowMap[item.id] ? 'arrowUp' : 'arrowDown'}
+ />
+ ),
+ },
+ ];
+ }
+
+ async componentDidMount() {}
+
+ async componentDidUpdate(prevProps) {
+ const { filters } = this.props
+ if (filters !== prevProps.filters) {
+ this.setState({ filters: filters });
+ }
+ }
+
+ componentWillUnmount() {
+ this._isMount = false;
+ }
+
+ /**
+ *
+ * @param item
+ */
+ toggleDetails = (item) => {
+ const itemIdToExpandedRowMap = { ...this.state.itemIdToExpandedRowMap };
+
+ if (itemIdToExpandedRowMap[item.id]) {
+ delete itemIdToExpandedRowMap[item.id];
+ } else {
+ let checks = '';
+ checks += (item.rules || []).length > 1 ? 'Checks' : 'Check';
+ checks += item.condition ? ` (Condition: ${item.condition})` : '';
+ const complianceText =
+ item.compliance && item.compliance.length
+ ? item.compliance.map((el) => `${el.key}: ${el.value}`).join('\n')
+ : '';
+ const listItems = [
+ {
+ title: 'Check not applicable due to:',
+ description: item.reason,
+ },
+ {
+ title: 'Rationale',
+ description: item.rationale || '-',
+ },
+ {
+ title: 'Remediation',
+ description: item.remediation || '-',
+ },
+ {
+ title: 'Description',
+ description: item.description || '-',
+ },
+ {
+ title: (item.directory || '').includes(',') ? 'Paths' : 'Path',
+ description: item.directory,
+ },
+ {
+ title: checks,
+ description: ,
+ },
+ {
+ title: 'Compliance',
+ description: ,
+ },
+ ];
+ const itemsToShow = listItems.filter((x) => {
+ return x.description;
+ });
+ itemIdToExpandedRowMap[item.id] = ;
+ }
+ this.setState({ itemIdToExpandedRowMap });
+ };
+
+ /**
+ *
+ * @param result
+ * @returns
+ */
+ addHealthResultRender(result: keyof typeof MODULE_SCA_CHECK_RESULT_LABEL) {
+ const color = (result: keyof typeof MODULE_SCA_CHECK_RESULT_LABEL) => {
+ if (result.toLowerCase() === 'passed') {
+ return 'success';
+ } else if (result.toLowerCase() === 'failed') {
+ return 'danger';
+ } else {
+ return 'subdued';
+ }
+ };
+
+ return (
+
+ {MODULE_SCA_CHECK_RESULT_LABEL[result]}
+
+ );
+ }
+
+ render() {
+ /**
+ *
+ * @param item
+ * @param idx
+ * @returns
+ */
+ const getChecksRowProps = (item, idx) => {
+ return {
+ 'data-test-subj': `sca-check-row-${idx}`,
+ className: 'customRowClass',
+ onClick: () => this.toggleDetails(item),
+ };
+ };
+
+ return (
+ <>
+ this.setState({ filters })}
+ tablePageSizeOptions={[10, 25, 50, 100]}
+ />
+ >
+ );
+ }
+}
diff --git a/public/components/agents/sca/inventory/index.ts b/public/components/agents/sca/inventory/index.ts
new file mode 100644
index 0000000000..df8e32d03f
--- /dev/null
+++ b/public/components/agents/sca/inventory/index.ts
@@ -0,0 +1,3 @@
+export * from './agent-policies-table'
+export * from './lib';
+export * from './checks-table';
diff --git a/public/components/agents/sca/inventory/lib/api-request.ts b/public/components/agents/sca/inventory/lib/api-request.ts
new file mode 100644
index 0000000000..5d7844d49f
--- /dev/null
+++ b/public/components/agents/sca/inventory/lib/api-request.ts
@@ -0,0 +1,27 @@
+import { WzRequest } from '../../../../../react-services/wz-request';
+
+export async function getFilterValues(
+ field: string,
+ value: string,
+ agentId: string,
+ policyId: string,
+ filters: { [key: string]: string } = {},
+ format = (item) => item) {
+ const filter = {
+ ...filters,
+ distinct: true,
+ select: field,
+ limit: 30,
+ };
+ if (value) {
+ filter['search'] = value;
+ }
+ const result = await WzRequest.apiReq('GET', `/sca/${agentId}/checks/${policyId}`, {
+ params: filter,
+ });
+ return (
+ result?.data?.data?.affected_items?.map((item) => {
+ return format(item[field]);
+ }) || []
+ );
+}
diff --git a/public/components/agents/sca/inventory/lib/index.ts b/public/components/agents/sca/inventory/lib/index.ts
new file mode 100644
index 0000000000..f452b74ace
--- /dev/null
+++ b/public/components/agents/sca/inventory/lib/index.ts
@@ -0,0 +1 @@
+export * from './api-request'
\ No newline at end of file
diff --git a/public/components/agents/stats/__snapshots__/table.test.tsx.snap b/public/components/agents/stats/__snapshots__/table.test.tsx.snap
index b925dcd79d..c92897168e 100644
--- a/public/components/agents/stats/__snapshots__/table.test.tsx.snap
+++ b/public/components/agents/stats/__snapshots__/table.test.tsx.snap
@@ -30,7 +30,7 @@ exports[`AgentStatTable component Renders correctly to match the snapshot 1`] =
>
-
-
-
- Location
-
-
-
+
+
+
+
+ Location
+
+
+
+
+
-
-
-
- Events
-
-
-
+
+
+
+
+ Events
+
+
+
+
+
-
-
-
- Bytes
-
-
-
+
+
+
+
+ Bytes
+
+
+
+
+
@@ -394,6 +442,7 @@ exports[`AgentStatTable component Renders correctly to match the snapshot 1`] =
{
- try {
- return text + formatUIDate(time);
- } catch (error) {
- return time !== '-' ? `${text}${time} (UTC)` : time;
- }
- }
- const syscollector = useGenericRequest('GET', `/api/syscollector/${agent.id}`, params, (result) => {return (result || {}).data || {};});
+export function InventoryMetrics({ agent }) {
+ const [params, setParams] = useState({});
+ const offsetTimestamp = (text, time) => {
+ try {
+ return text + formatUIDate(time);
+ } catch (error) {
+ return time !== '-' ? `${text}${time} (UTC)` : time;
+ }
+ };
+ const syscollector = useGenericRequest(
+ 'GET',
+ `/api/syscollector/${agent.id}`,
+ params,
+ result => {
+ return (result || {}).data || {};
+ },
+ );
if (
!syscollector.isLoading &&
- (mapValues.isEmpty(syscollector.data.hardware) || mapValues.isEmpty(syscollector.data.os))
+ (mapValues.isEmpty(syscollector.data.hardware) ||
+ mapValues.isEmpty(syscollector.data.os))
) {
return (
-
- Not enough hardware or operating system information
+
+ Not enough hardware or operating system
+ information
);
}
- return (
-
-
-
- Cores: {syscollector.isLoading ? : {syscollector.data.hardware.cpu.cores} }
-
-
- Memory: {syscollector.isLoading ? : { (syscollector.data.hardware.ram.total / 1024).toFixed(2) } MB }
-
-
- Arch: {syscollector.isLoading ? : {syscollector.data.os.architecture} }
-
-
- OS: {syscollector.isLoading ? : {syscollector.data.os.os.name} {syscollector.data.os.os.version} }
-
-
- CPU: {syscollector.isLoading ? : {syscollector.data.hardware.cpu.name} }
-
-
- Last scan: {syscollector.isLoading ? : {offsetTimestamp('',syscollector.data.os.scan.time)} }
-
-
-
- );
-
-
+ return (
+
+
+
+
+ Cores:{' '}
+ {syscollector.isLoading ? (
+
+ ) : syscollector.data.hardware.cpu?.cores ? (
+ {syscollector.data.hardware.cpu.cores}
+ ) : (
+ -
+ )}
+
+
+
+
+ Memory:{' '}
+ {syscollector.isLoading ? (
+
+ ) : syscollector.data.hardware.ram?.total ? (
+
+ {(syscollector.data.hardware.ram.total / 1024).toFixed(2)} MB
+
+ ) : (
+ -
+ )}
+
+
+
+
+ Arch:{' '}
+ {syscollector.isLoading ? (
+
+ ) : (
+ {syscollector.data.os.architecture}
+ )}
+
+
+
+
+ Operating system:{' '}
+ {syscollector.isLoading ? (
+
+ ) : (
+
+ {syscollector.data.os.os.name} {syscollector.data.os.os.version}
+
+ )}
+
+
+
+
+ CPU:{' '}
+ {syscollector.isLoading ? (
+
+ ) : syscollector.data.hardware.cpu?.name ? (
+ {syscollector.data.hardware.cpu.name}
+ ) : (
+ -
+ )}
+
+
+
+
+ Last scan:{' '}
+ {syscollector.isLoading ? (
+
+ ) : (
+
+ {offsetTimestamp('', syscollector.data.os.scan.time)}
+
+ )}
+
+
+
+
+ );
}
diff --git a/public/components/agents/syscollector/inventory.tsx b/public/components/agents/syscollector/inventory.tsx
index 7eb3c1b68b..9f1398ac22 100644
--- a/public/components/agents/syscollector/inventory.tsx
+++ b/public/components/agents/syscollector/inventory.tsx
@@ -11,7 +11,13 @@
*/
import React, { Fragment } from 'react';
-import { EuiEmptyPrompt, EuiButton, EuiFlexGroup, EuiFlexItem, EuiCallOut } from '@elastic/eui';
+import {
+ EuiEmptyPrompt,
+ EuiButton,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiCallOut,
+} from '@elastic/eui';
import { InventoryMetrics } from './components/syscollector-metrics';
import { SyscollectorTable } from './components/syscollector-table';
import { processColumns, portsColumns, packagesColumns } from './columns';
@@ -22,22 +28,28 @@ export function SyscollectorInventory({ agent }) {
if (agent && agent.status === API_NAME_AGENT_STATUS.NEVER_CONNECTED) {
return (
Agent has never connected.}
body={
- The agent has been registered but has not yet connected to the manager.
+
+ The agent has been registered but has not yet connected to the
+ manager.
+
Checking connection with the Wazuh server
}
actions={
-
+
Back
}
@@ -46,7 +58,6 @@ export function SyscollectorInventory({ agent }) {
}
let soPlatform;
-
if (((agent.os || {}).uname || '').includes('Linux')) {
soPlatform = 'linux';
} else if ((agent.os || {}).platform === 'windows') {
@@ -55,6 +66,8 @@ export function SyscollectorInventory({ agent }) {
soPlatform = 'apple';
} else if (((agent.os || {}).uname.toLowerCase() || '').includes('freebsd')) {
soPlatform = 'freebsd';
+ } else if (((agent.os || {}).uname.toLowerCase() || '').includes('sunos')) {
+ soPlatform = 'solaris';
}
const netifaceColumns = [
@@ -77,17 +90,17 @@ export function SyscollectorInventory({ agent }) {
{agent && agent.status === API_NAME_AGENT_STATUS.DISCONNECTED && (
)}
-
+
-
+
-
+
-
+
-
+
({
- label: key,
- value,
- color: this.colorsVisualizationVulnerabilitiesSummaryData[index],
- onClick: () => this.onFiltersChange(this.buildFilterQuery(field, key))
- })).sort((firstElement, secondElement) => secondElement.value - firstElement.value)
+ return Object.entries(results[field])
+ .map(([key, value], index) => ({
+ label: key,
+ value,
+ color: this.colorsVisualizationVulnerabilitiesSummaryData[index],
+ onClick: () => this.onFiltersChange(this.buildFilterQuery(field, key)),
+ }))
+ .sort(
+ (firstElement, secondElement) =>
+ secondElement.value - firstElement.value,
+ );
}
- async fetchVisualizationVulnerabilitiesSeverityData(){
+ async fetchVisualizationVulnerabilitiesSeverityData() {
const { id } = this.props.agent;
const FIELD = 'severity';
const SEVERITY_KEYS = ['Critical', 'High', 'Medium', 'Low'];
@@ -108,24 +143,27 @@ export class Inventory extends Component {
const vulnerabilityLastScan = await getLastScan(id);
const { severity } = await getAggregation(id, FIELD);
- const severityStats = SEVERITY_KEYS.map(key => ({
+ const severityStats = SEVERITY_KEYS.map(key => ({
titleColor: this.titleColors[key],
description: key,
- title: severity[key] ? severity[key] : 0
+ title: severity[key] ? severity[key] : 0,
}));
this.setState({
stats: severityStats,
isLoadingStats: false,
- vulnerabilityLastScan
+ vulnerabilityLastScan,
});
-
- return Object.keys(severity).length ? SEVERITY_KEYS.map(key => ({
- label: key,
- value: severity[key] ? severity[key] : 0,
- color: this.titleColors[key],
- onClick: () => this.onFiltersChange(this.buildFilterQuery(FIELD, key))
- })) : [];
+
+ return Object.keys(severity).length
+ ? SEVERITY_KEYS.map(key => ({
+ label: key,
+ value: severity[key] ? severity[key] : 0,
+ color: this.titleColors[key],
+ onClick: () =>
+ this.onFiltersChange(this.buildFilterQuery(FIELD, key)),
+ }))
+ : [];
}
buildFilterQuery(field = '', selectedItem = '') {
@@ -134,20 +172,20 @@ export class Inventory extends Component {
field: 'q',
value: `${field}=${selectedItem}`,
},
- ]
+ ];
}
async loadAgent() {
if (this._isMount) {
this.setState({
- isLoading: false
+ isLoading: false,
});
}
}
- onFiltersChange = (filters) => {
+ onFiltersChange = filters => {
this.setState({ filters });
- }
+ };
renderTable() {
const { filters } = this.state;
@@ -159,135 +197,152 @@ export class Inventory extends Component {
onFiltersChange={this.onFiltersChange}
/>
- )
+ );
}
loadingInventory() {
- return
-
-
-
-
-
- ;
- }
-
- // This method was created because Wazuh API returns 1970-01-01T00:00:00Z dates or undefined ones
- // when vulnerability module is not configured
- // its meant to render nothing when such date is received
- beautifyDate(date?: string) {
- return date && !['1970-01-01T00:00:00Z', '-'].includes(date) ? formatUIDate(date) : '-';
+ return (
+
+
+
+
+
+
+
+ );
}
buildTitleFilter({ description, title, titleColor }) {
const { isLoadingStats } = this.state;
return (
-
+
+ title={
+
this.onFiltersChange(this.buildFilterQuery('severity', description))}
+ onClick={() =>
+ this.onFiltersChange(
+ this.buildFilterQuery('severity', description),
+ )
+ }
>
{title}
- )}
+ }
description={description}
titleColor={titleColor}
/>
- )
+ );
}
render() {
const { isLoading, stats, vulnerabilityLastScan } = this.state;
if (isLoading) {
- return this.loadingInventory()
+ return this.loadingInventory();
}
- const last_full_scan = this.beautifyDate(vulnerabilityLastScan.last_full_scan);
- const last_partial_scan = this.beautifyDate(vulnerabilityLastScan.last_partial_scan);
-
+ const last_full_scan = beautifyDate(vulnerabilityLastScan.last_full_scan);
+ const last_partial_scan = beautifyDate(
+ vulnerabilityLastScan.last_partial_scan,
+ );
+
const table = this.renderTable();
- return
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {stats.map(stat => this.buildTitleFilter(stat))}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `No ${optionRequirement.text} results were found.`
+ }
/>
-
-
-
-
-
-
-
-
- {stats.map((stat) => this.buildTitleFilter(stat))}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- `No ${optionRequirement.text} results were found.`}
- />
-
-
-
-
-
- {table}
-
-
-
+
+
+
+
+ {table}
+
+
+ );
}
}
diff --git a/public/components/agents/vuls/inventory/detail.tsx b/public/components/agents/vuls/inventory/detail.tsx
index 4a71a2d7c0..93ae6d5469 100644
--- a/public/components/agents/vuls/inventory/detail.tsx
+++ b/public/components/agents/vuls/inventory/detail.tsx
@@ -29,14 +29,17 @@ import {
import { Discover } from '../../../common/modules/discover';
import { ModulesHelper } from '../../../common/modules/modules-helper';
import { ICustomBadges } from '../../../wz-search-bar/components';
-import { buildPhraseFilter, IIndexPattern } from '../../../../../../../src/plugins/data/common';
+import {
+ buildPhraseFilter,
+ IIndexPattern,
+} from '../../../../../../../src/plugins/data/common';
import { getIndexPattern } from '../../../overview/mitre/lib';
import moment from 'moment-timezone';
import { AppNavigate } from '../../../../react-services/app-navigate';
import { TruncateHorizontalComponents } from '../../../common/util';
import { getDataPlugin, getUiSettings } from '../../../../kibana-services';
import { FilterManager } from '../../../../../../../src/plugins/data/public/';
-import { formatUIDate } from '../../../../react-services/time-service';
+import { beautifyDate } from './lib';
export class Details extends Component {
props!: {
currentItem: {
@@ -51,22 +54,22 @@ export class Details extends Component {
};
userSvg = (
);
@@ -86,7 +89,7 @@ export class Details extends Component {
}
componentDidMount() {
- getIndexPattern().then((idxPtn) => (this.indexPattern = idxPtn));
+ getIndexPattern().then(idxPtn => (this.indexPattern = idxPtn));
}
details() {
@@ -132,47 +135,40 @@ export class Details extends Component {
name: 'Last full scan',
icon: 'clock',
link: false,
- transformValue: this.beautifyDate
+ transformValue: beautifyDate,
},
{
field: 'last_partial_scan',
name: 'Last partial scan',
icon: 'clock',
link: false,
- transformValue: this.beautifyDate
+ transformValue: beautifyDate,
},
{
field: 'published',
name: 'Published',
icon: 'clock',
link: false,
- transformValue: this.beautifyDate
+ transformValue: beautifyDate,
},
{
field: 'updated',
name: 'Updated',
icon: 'clock',
link: false,
- transformValue: this.beautifyDate
+ transformValue: beautifyDate,
},
{
field: 'external_references',
name: 'References',
icon: 'link',
link: false,
- transformValue: this.renderExternalReferences
+ transformValue: this.renderExternalReferences,
},
];
}
- // This method was created because Wazuh API returns 1970-01-01T00:00:00Z dates or undefined ones
- // when vulnerability module is not configured
- // its meant to render nothing when such date is received
- beautifyDate(date?: string) {
- return date && !['1970-01-01T00:00:00Z', '-'].includes(date) ? formatUIDate(date) : '-';
- }
-
- viewInEvents = (ev) => {
+ viewInEvents = ev => {
const { cve } = this.props.currentItem;
if (this.props.view === 'extern') {
AppNavigate.navigateToModule(ev, 'overview', {
@@ -184,8 +180,12 @@ export class Details extends Component {
AppNavigate.navigateToModule(
ev,
'overview',
- { tab: 'vuls', tabView: 'events', filters: { 'data.vulnerability.cve': cve } },
- () => this.openEventCurrentWindow()
+ {
+ tab: 'vuls',
+ tabView: 'events',
+ filters: { 'data.vulnerability.cve': cve },
+ },
+ () => this.openEventCurrentWindow(),
);
}
};
@@ -197,7 +197,7 @@ export class Details extends Component {
...buildPhraseFilter(
{ name: 'data.vulnerability.cve', type: 'text' },
cve,
- this.indexPattern
+ this.indexPattern,
),
$state: { store: 'appState' },
},
@@ -227,13 +227,16 @@ export class Details extends Component {
if (field === 'date' || field === 'mtime') {
let value_max = moment(value).add(1, 'day');
newBadge.value = `${field}>${moment(value).format(
- 'YYYY-MM-DD'
+ 'YYYY-MM-DD',
)} AND ${field}<${value_max.format('YYYY-MM-DD')}`;
} else {
- newBadge.value = `${field}=${field === 'size' ? this.props.currentItem[field] : value}`;
+ newBadge.value = `${field}=${
+ field === 'size' ? this.props.currentItem[field] : value
+ }`;
}
- !filters.some((item) => item.field === newBadge.field && item.value === newBadge.value) &&
- onFiltersChange([...filters, newBadge]);
+ !filters.some(
+ item => item.field === newBadge.field && item.value === newBadge.value,
+ ) && onFiltersChange([...filters, newBadge]);
this.props.closeFlyout();
}
@@ -248,8 +251,13 @@ export class Details extends Component {
var link = (item.link && !['events', 'extern'].includes(view)) || false;
const agentPlatform = ((this.props.agent || {}).os || {}).platform;
- if (!item.onlyLinux || (item.onlyLinux && this.props.agent && agentPlatform !== 'windows')) {
- let className = item.checksum ? 'detail-value detail-value-checksum' : 'detail-value';
+ if (
+ !item.onlyLinux ||
+ (item.onlyLinux && this.props.agent && agentPlatform !== 'windows')
+ ) {
+ let className = item.checksum
+ ? 'detail-value detail-value-checksum'
+ : 'detail-value';
className += item.field === 'perm' ? ' detail-value-perm' : '';
className += ' wz-width-100';
return (
@@ -271,18 +279,18 @@ export class Details extends Component {
{value}
{this.state.hoverAddFilter === item.field && (
{
this.addFilter(item.field, value);
}}
- iconType="magnifyWithPlus"
- aria-label="Next"
- iconSize="s"
- className="buttonAddFilter"
+ iconType='magnifyWithPlus'
+ aria-label='Next'
+ iconSize='s'
+ className='buttonAddFilter'
/>
)}
@@ -292,15 +300,20 @@ export class Details extends Component {
description={
{item.icon !== 'users' ? (
-
+
) : (
this.userSvg
)}
- {item.name}
+ {item.name}
}
- textAlign="left"
- titleSize="xs"
+ textAlign='left'
+ titleSize='xs'
/>
);
@@ -317,41 +330,55 @@ export class Details extends Component {
renderExternalReferences(references) {
return (
-
- View external references
+
+
+
+ View external references{' '}
+
+
- }>
- ({ label: link, href: link, target: '_blank' }))
- }
+ }
+ >
+ ({
+ label: link,
+ href: link,
+ target: '_blank',
+ }))}
/>
);
}
- updateTotalHits = (total) => {
+ updateTotalHits = total => {
this.setState({ totalHits: total });
};
renderDetailsPermissions(value) {
- if (((this.props.agent || {}).os || {}).platform === 'windows' && value && value !== '-') {
+ if (
+ ((this.props.agent || {}).os || {}).platform === 'windows' &&
+ value &&
+ value !== '-'
+ ) {
const components = value
.split(', ')
- .map((userNameAndPermissionsFullString) => {
- const [_, username, userPermissionsString] = userNameAndPermissionsFullString.match(
- /(\S+) \(allowed\): (\S+)/
- );
+ .map(userNameAndPermissionsFullString => {
+ const [_, username, userPermissionsString] =
+ userNameAndPermissionsFullString.match(/(\S+) \(allowed\): (\S+)/);
const permissions = userPermissionsString.split('|').sort();
return { username, permissions };
})
@@ -371,7 +398,11 @@ export class Details extends Component {
content={permissions.join(', ')}
title={`${username} permissions`}
>
-
+
{username}
@@ -380,7 +411,7 @@ export class Details extends Component {
return (
`+${count} users`}
+ labelButtonHideComponents={count => `+${count} users`}
buttonProps={{ size: 'xs' }}
componentsWidthPercentage={0.85}
/>
@@ -392,41 +423,42 @@ export class Details extends Component {
render() {
const { type, implicitFilters, view, currentItem, agent } = this.props;
const id = `${currentItem.name}-${currentItem.cve}-${currentItem.architecture}-${currentItem.version}`;
- const inspectButtonText = view === 'extern' ? 'Inspect in Dashboard' : 'Inspect in Events';
+ const inspectButtonText =
+ view === 'extern' ? 'Inspect in Dashboard' : 'Inspect in Events';
return (
+
Details
}
- paddingSize="none"
+ paddingSize='none'
initialIsOpen={true}
>
- {this.getDetails()}
+ {this.getDetails()}
{this.state.totalHits || 0} hits
}
buttonContent={
-
+
Recent events
{view !== 'events' && (
-
+
this.viewInEvents(ev)}
- type="popout"
+ className='euiButtonIcon euiButtonIcon--primary'
+ onMouseDown={ev => this.viewInEvents(ev)}
+ type='popout'
aria-label={inspectButtonText}
/>
@@ -435,10 +467,10 @@ export class Details extends Component {
}
- paddingSize="none"
+ paddingSize='none'
initialIsOpen={true}
>
-
+
this.updateTotalHits(total)}
+ updateTotalHits={total => this.updateTotalHits(total)}
/>
diff --git a/public/components/agents/vuls/inventory/lib/index.ts b/public/components/agents/vuls/inventory/lib/index.ts
index 54579ea0ab..3db5ec6559 100644
--- a/public/components/agents/vuls/inventory/lib/index.ts
+++ b/public/components/agents/vuls/inventory/lib/index.ts
@@ -1 +1,2 @@
-export * from './api-requests';
\ No newline at end of file
+export * from './api-requests';
+export * from './utils';
diff --git a/public/components/agents/vuls/inventory/lib/utils.ts b/public/components/agents/vuls/inventory/lib/utils.ts
new file mode 100644
index 0000000000..bc37df757b
--- /dev/null
+++ b/public/components/agents/vuls/inventory/lib/utils.ts
@@ -0,0 +1,10 @@
+import { formatUIDate } from '../../../../../react-services/time-service';
+
+// This method was created because Wazuh API returns 1970-01-01T00:00:00Z dates or undefined ones
+// when vulnerability module is not configured
+// its meant to render nothing when such date is received
+export function beautifyDate(date?: string) {
+ return date &&
+ (!['-'].includes(date) && !date.startsWith('1970')) ?
+ formatUIDate(date) : '-';
+}
diff --git a/public/components/common/buttons/modal-confirm.tsx b/public/components/common/buttons/modal-confirm.tsx
index aa809374ed..a92dc5d08b 100644
--- a/public/components/common/buttons/modal-confirm.tsx
+++ b/public/components/common/buttons/modal-confirm.tsx
@@ -35,12 +35,12 @@ interface WzButtonModalConfirmProps{
};
const renderModal = ({onConfirm, onCancel, modalTitle, modalConfirmText, modalCancelText, modalProps }) => ({close}) => {
- const onModalConfirm = () => {
- close();
+ const onModalConfirm = (ev) => {
+ close(ev);
onConfirm && onConfirm();
};
- const onModalCancel = () => {
- close();
+ const onModalCancel = (ev) => {
+ close(ev);
onCancel && onCancel();
};
return (
diff --git a/public/components/common/error-boundary/__snapshots__/error-boundary.test.tsx.snap b/public/components/common/error-boundary/__snapshots__/error-boundary.test.tsx.snap
index d60419fad3..9a0cb7b29a 100644
--- a/public/components/common/error-boundary/__snapshots__/error-boundary.test.tsx.snap
+++ b/public/components/common/error-boundary/__snapshots__/error-boundary.test.tsx.snap
@@ -78,27 +78,27 @@ exports[`ErrorBoundary component renders correctly to match the snapshot 1`] = `
+
+
+ Something went wrong.
+
+
-
-
- Something went wrong.
-
-
diff --git a/public/components/common/flyouts/wz-flyout.tsx b/public/components/common/flyouts/wz-flyout.tsx
index 7d84ea0d2c..69974ac599 100644
--- a/public/components/common/flyouts/wz-flyout.tsx
+++ b/public/components/common/flyouts/wz-flyout.tsx
@@ -10,24 +10,13 @@
* Find more information about this on the LICENSE file.
*/
-import React, { Component, Fragment } from 'react';
-import { EuiFlyout, EuiOverlayMask, EuiOutsideClickDetector } from '@elastic/eui';
-import { satisfyPluginPlatformVersion } from '../../../../common/semver';
+import React from 'react';
+import { EuiFlyout } from '@elastic/eui';
-export const WzFlyout = ({children, flyoutProps = {}, overlayMaskProps = {}, outsideClickDetectorProps = {}, onClose}) => (
-
- 7.10')}
- {...outsideClickDetectorProps}
- >
- 7.10') ? { outsideClickCloses: true } : {})}
- {...flyoutProps}
- >
- {children}
-
-
-
-);
+export const WzFlyout = ({ children, flyoutProps = {}, onClose }) => {
+ return (
+ {} }} {...flyoutProps} outsideClickCloses={true}>
+ {children}
+
+ )
+};
diff --git a/public/components/common/form/__snapshots__/index.test.tsx.snap b/public/components/common/form/__snapshots__/index.test.tsx.snap
new file mode 100644
index 0000000000..e310c1780b
--- /dev/null
+++ b/public/components/common/form/__snapshots__/index.test.tsx.snap
@@ -0,0 +1,450 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`[component] InputForm Renders correctly to match the snapshot with validation errors. Input: number 1`] = `
+
+`;
+
+exports[`[component] InputForm Renders correctly to match the snapshot with validation errors. Input: text 1`] = `
+
+`;
+
+exports[`[component] InputForm Renders correctly to match the snapshot with validation errors. Input: text 2`] = `
+
+`;
+
+exports[`[component] InputForm Renders correctly to match the snapshot: Input: editor 1`] = `
+
+
+
+
+ Press Enter to start editing.
+
+
+ When you're done, press Escape to stop editing.
+
+
+
+
+
+
+
+
+
+
+
+ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+
+
+
+
+
+`;
+
+exports[`[component] InputForm Renders correctly to match the snapshot: Input: filepicker 1`] = `
+
+
+
+
+
+
+
+ Select or drag the file
+
+
+
+
+
+`;
+
+exports[`[component] InputForm Renders correctly to match the snapshot: Input: number 1`] = `
+
+`;
+
+exports[`[component] InputForm Renders correctly to match the snapshot: Input: select 1`] = `
+
+`;
+
+exports[`[component] InputForm Renders correctly to match the snapshot: Input: switch 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+ Enabled
+
+
+
+`;
+
+exports[`[component] InputForm Renders correctly to match the snapshot: Input: text 1`] = `
+
+`;
+
+exports[`[component] InputForm Renders correctly to match the snapshot: Input: textarea 1`] = `
+
+
+
+`;
diff --git a/public/components/common/form/hooks.test.tsx b/public/components/common/form/hooks.test.tsx
new file mode 100644
index 0000000000..38d3f19a27
--- /dev/null
+++ b/public/components/common/form/hooks.test.tsx
@@ -0,0 +1,178 @@
+import { renderHook, act } from '@testing-library/react-hooks';
+import { useForm } from './hooks';
+
+describe('[hook] useForm', () => {
+
+ it(`[hook] useForm. Verify the initial state`, async () => {
+
+ const initialFields = {
+ text1: {
+ type: 'text',
+ initialValue: ''
+ },
+ };
+
+ const { result } = renderHook(() => useForm(initialFields));
+
+ // assert initial state
+ expect(result.current.fields.text1.changed).toBe(false);
+ expect(result.current.fields.text1.error).toBeUndefined();
+ expect(result.current.fields.text1.type).toBe('text');
+ expect(result.current.fields.text1.value).toBe('');
+ expect(result.current.fields.text1.initialValue).toBe('');
+ expect(result.current.fields.text1.onChange).toBeDefined();
+ });
+
+ it(`[hook] useForm. Verify the initial state. Multiple fields.`, async () => {
+
+ const initialFields = {
+ text1: {
+ type: 'text',
+ initialValue: ''
+ },
+ number1: {
+ type: 'number',
+ initialValue: 1
+ },
+ };
+
+ const { result } = renderHook(() => useForm(initialFields));
+
+ // assert initial state
+ expect(result.current.fields.text1.changed).toBe(false);
+ expect(result.current.fields.text1.error).toBeUndefined();
+ expect(result.current.fields.text1.type).toBe('text');
+ expect(result.current.fields.text1.value).toBe('');
+ expect(result.current.fields.text1.initialValue).toBe('');
+ expect(result.current.fields.text1.onChange).toBeDefined();
+
+ expect(result.current.fields.number1.changed).toBe(false);
+ expect(result.current.fields.number1.error).toBeUndefined();
+ expect(result.current.fields.number1.type).toBe('number');
+ expect(result.current.fields.number1.value).toBe(1);
+ expect(result.current.fields.number1.initialValue).toBe(1);
+ expect(result.current.fields.number1.onChange).toBeDefined();
+ });
+
+ it(`[hook] useForm lifecycle. Set the initial value. Change the field value. Undo changes. Change the field. Do changes.`, async () => {
+
+ const initialFieldValue = '';
+ const fieldType = 'text';
+
+ const initialFields = {
+ text1: {
+ type: fieldType,
+ initialValue: initialFieldValue
+ }
+ };
+
+ const { result } = renderHook(() => useForm(initialFields));
+
+ // assert initial state
+ expect(result.current.fields.text1.changed).toBe(false);
+ expect(result.current.fields.text1.error).toBeUndefined();
+ expect(result.current.fields.text1.type).toBe(fieldType);
+ expect(result.current.fields.text1.value).toBe(initialFieldValue);
+ expect(result.current.fields.text1.initialValue).toBe(initialFieldValue);
+ expect(result.current.fields.text1.onChange).toBeDefined();
+
+ // change the input
+ const changedValue = 't';
+ act(() => {
+ result.current.fields.text1.onChange({
+ target: {
+ value: changedValue
+ }
+ });
+ });
+
+ // assert changed state
+ expect(result.current.fields.text1.changed).toBe(true);
+ expect(result.current.fields.text1.error).toBeUndefined();
+ expect(result.current.fields.text1.type).toBe(fieldType);
+ expect(result.current.fields.text1.value).toBe(changedValue);
+ expect(result.current.fields.text1.initialValue).toBe(initialFieldValue);
+
+ // undone changes
+ act(() => {
+ result.current.undoChanges();
+ });
+
+ // assert undo changes state
+ expect(result.current.fields.text1.changed).toBe(false);
+ expect(result.current.fields.text1.error).toBeUndefined();
+ expect(result.current.fields.text1.type).toBe(fieldType);
+ expect(result.current.fields.text1.value).toBe(initialFieldValue);
+ expect(result.current.fields.text1.initialValue).toBe(initialFieldValue);
+
+ // change the input
+ const changedValue2 = 'e';
+ act(() => {
+ result.current.fields.text1.onChange({
+ target: {
+ value: changedValue2
+ }
+ });
+ });
+
+ // assert changed state
+ expect(result.current.fields.text1.changed).toBe(true);
+ expect(result.current.fields.text1.error).toBeUndefined();
+ expect(result.current.fields.text1.type).toBe(fieldType);
+ expect(result.current.fields.text1.value).toBe(changedValue2);
+ expect(result.current.fields.text1.initialValue).toBe(initialFieldValue);
+
+ // done changes
+ act(() => {
+ result.current.doChanges()
+ });
+
+ // assert do changes state
+ expect(result.current.fields.text1.changed).toBe(false);
+ expect(result.current.fields.text1.error).toBeUndefined();
+ expect(result.current.fields.text1.type).toBe(fieldType);
+ expect(result.current.fields.text1.value).toBe(changedValue2);
+ expect(result.current.fields.text1.initialValue).toBe(changedValue2);
+ });
+
+ it(`[hook] useForm lifecycle. Set the initial value. Change the field value to invalid value`, async () => {
+
+ const initialFieldValue = 'test';
+ const fieldType = 'text';
+
+ const initialFields = {
+ text1: {
+ type: fieldType,
+ initialValue: initialFieldValue,
+ validate: (value: string): string | undefined => value.length ? undefined : `Validation error: string can be empty.`
+ }
+ };
+
+ const { result } = renderHook(() => useForm(initialFields));
+
+ // assert initial state
+ expect(result.current.fields.text1.changed).toBe(false);
+ expect(result.current.fields.text1.error).toBeUndefined();
+ expect(result.current.fields.text1.type).toBe(fieldType);
+ expect(result.current.fields.text1.value).toBe(initialFieldValue);
+ expect(result.current.fields.text1.initialValue).toBe(initialFieldValue);
+ expect(result.current.fields.text1.onChange).toBeDefined();
+
+ // change the input
+ const changedValue = '';
+ act(() => {
+ result.current.fields.text1.onChange({
+ target: {
+ value: changedValue
+ }
+ });
+ });
+
+ // assert changed state
+ expect(result.current.fields.text1.changed).toBe(true);
+ expect(result.current.fields.text1.error).toBeTruthy();
+ expect(result.current.fields.text1.type).toBe(fieldType);
+ expect(result.current.fields.text1.value).toBe(changedValue);
+ expect(result.current.fields.text1.initialValue).toBe(initialFieldValue);
+ });
+});
diff --git a/public/components/common/form/hooks.tsx b/public/components/common/form/hooks.tsx
new file mode 100644
index 0000000000..f3837b4b32
--- /dev/null
+++ b/public/components/common/form/hooks.tsx
@@ -0,0 +1,91 @@
+import { useState, useRef } from 'react';
+import { isEqual } from 'lodash';
+import { EpluginSettingType } from '../../../../common/constants';
+
+function getValueFromEvent(event, type){
+ return (getValueFromEventType[type] || getValueFromEventType.default)(event);
+};
+
+const getValueFromEventType = {
+ [EpluginSettingType.switch] : (event: any) => event.target.checked,
+ [EpluginSettingType.editor]: (value: any) => value,
+ [EpluginSettingType.filepicker]: (value: any) => value,
+ default: (event: any) => event.target.value,
+};
+
+export const useForm = (fields) => {
+ const [formFields, setFormFields] = useState(Object.entries(fields).reduce((accum, [fieldKey, fieldConfiguration]) => ({
+ ...accum,
+ [fieldKey]: {
+ currentValue: fieldConfiguration.initialValue,
+ initialValue: fieldConfiguration.initialValue,
+ }
+ }), {}));
+
+ const fieldRefs = useRef({});
+
+ const enhanceFields = Object.entries(formFields).reduce((accum, [fieldKey, {currentValue: value, ...restFieldState}]) => ({
+ ...accum,
+ [fieldKey]: {
+ ...fields[fieldKey],
+ ...restFieldState,
+ type: fields[fieldKey].type,
+ value,
+ changed: !isEqual(restFieldState.initialValue, value),
+ error: fields[fieldKey]?.validate?.(value),
+ setInputRef: (reference) => {fieldRefs.current[fieldKey] = reference},
+ inputRef: fieldRefs.current[fieldKey],
+ onChange: (event) => {
+ const inputValue = getValueFromEvent(event, fields[fieldKey].type);
+ const currentValue = fields[fieldKey]?.transformChangedInputValue?.(inputValue) ?? inputValue;
+ setFormFields(state => ({
+ ...state,
+ [fieldKey]: {
+ ...state[fieldKey],
+ currentValue,
+ }
+ }))
+ },
+ }
+ }), {});
+
+ const changed = Object.fromEntries(
+ Object.entries(enhanceFields).filter(([, {changed}]) => changed).map(([fieldKey, {value}]) => ([fieldKey, fields[fieldKey]?.transformChangedOutputValue?.(value) ?? value]))
+ );
+
+ const errors = Object.fromEntries(
+ Object.entries(enhanceFields).filter(([, {error}]) => error).map(([fieldKey, {error}]) => ([fieldKey, error]))
+ );
+
+ function undoChanges(){
+ setFormFields(state => Object.fromEntries(
+ Object.entries(state).map(([fieldKey, fieldConfiguration]) => ([
+ fieldKey,
+ {
+ ...fieldConfiguration,
+ currentValue: fieldConfiguration.initialValue
+ }
+ ]))
+ ));
+ };
+
+ function doChanges(){
+ setFormFields(state => Object.fromEntries(
+ Object.entries(state).map(([fieldKey, fieldConfiguration]) => ([
+ fieldKey,
+ {
+ ...fieldConfiguration,
+ initialValue: fieldConfiguration.currentValue
+ }
+ ]))
+ ));
+ };
+
+ return {
+ fields: enhanceFields,
+ changed,
+ errors,
+ undoChanges,
+ doChanges
+ };
+};
diff --git a/public/components/common/form/index.test.tsx b/public/components/common/form/index.test.tsx
new file mode 100644
index 0000000000..17e21ee8ec
--- /dev/null
+++ b/public/components/common/form/index.test.tsx
@@ -0,0 +1,55 @@
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import { InputForm } from './index';
+import { useForm } from './hooks';
+
+jest.mock('../../../../../../node_modules/@elastic/eui/lib/services/accessibility/html_id_generator', () => ({
+ htmlIdGenerator: () => () => 'test-id',
+}));
+
+describe('[component] InputForm', () => {
+ const optionsEditor = {editor: {language: 'json'}};
+ const optionsFilepicker = {file: {type: 'image', extensions: ['.jpeg', '.jpg', '.png', '.svg']}};
+ const optionsSelect = {select: [{text: 'Label1', value: 'value1'}, {text: 'Label2', value: 'value2'}]};
+ const optionsSwitch = {switch: {values: {enabled: {label: 'Enabled', value: true}, disabled: {label: 'Disabled', value: false}}}};
+ it.each`
+ inputType | value | options
+ ${'editor'} | ${'{}'} | ${optionsEditor}
+ ${'filepicker'} | ${'{}'} | ${optionsFilepicker}
+ ${'number'} | ${4} | ${undefined}
+ ${'select'} | ${'value1'} | ${optionsSelect}
+ ${'switch'} | ${true} | ${optionsSwitch}
+ ${'text'} | ${'test'} | ${undefined}
+ ${'textarea'} | ${'test'} | ${undefined}
+ `('Renders correctly to match the snapshot: Input: $inputType', ({ inputType, value, options }) => {
+ const wrapper = render(
+ {}}
+ options={options}
+ />
+ );
+ expect(wrapper.container).toMatchSnapshot();
+ });
+
+ it.each`
+ inputType | initialValue | options | rest
+ ${'number'} | ${4} | ${{number: {min: 5}}} | ${{ validate: (value) => value > 3 ? undefined : 'Vaidation error: value is lower than 5'}}
+ ${'text'} | ${''} | ${undefined} | ${{ validate: (value) => value.length ? undefined : 'Validation error: string can not be empty' }}
+ ${'text'} | ${'test spaces'} | ${undefined} | ${{ validate: (value) => value.length ? undefined : 'Validation error: string can not contain spaces' }}
+ `('Renders correctly to match the snapshot with validation errors. Input: $inputType', async ({ inputType, initialValue, options, rest }) => {
+ const TestComponent = () => {
+ const { fields: { [inputType]: field } } = useForm({ [inputType]: { initialValue, type: inputType, options, ...rest } });
+ return (
+
+ );
+ };
+ const wrapper = render( );
+ expect(wrapper.container).toMatchSnapshot();
+ });
+});
+
diff --git a/public/components/common/form/index.tsx b/public/components/common/form/index.tsx
new file mode 100644
index 0000000000..2a6da4610e
--- /dev/null
+++ b/public/components/common/form/index.tsx
@@ -0,0 +1,67 @@
+import React from 'react';
+import { InputFormEditor } from './input_editor';
+import { InputFormNumber } from './input_number';
+import { InputFormText } from './input_text';
+import { InputFormSelect } from './input_select';
+import { InputFormSwitch } from './input_switch';
+import { InputFormFilePicker } from './input_filepicker';
+import { InputFormTextArea } from './input_text_area';
+import { EuiFlexGroup, EuiFlexItem, EuiFormRow } from '@elastic/eui';
+
+export const InputForm = ({
+ type,
+ value,
+ onChange,
+ error,
+ label,
+ header,
+ footer,
+ preInput,
+ postInput,
+...rest}) => {
+
+ const ComponentInput = Input[type];
+
+ if(!ComponentInput){
+ return null;
+ };
+
+ const isInvalid = Boolean(error);
+
+ const input = (
+
+ );
+
+ return label
+ ? (
+
+ <>
+ {typeof header === 'function' ? header({value, error}) : header}
+
+ {typeof preInput === 'function' ? preInput({value, error}) : preInput}
+
+ {input}
+
+ {typeof postInput === 'function' ? postInput({value, error}) : postInput}
+
+ {typeof footer === 'function' ? footer({value, error}) : footer}
+ >
+ )
+ : input;
+
+};
+
+const Input = {
+ switch: InputFormSwitch,
+ editor: InputFormEditor,
+ filepicker: InputFormFilePicker,
+ number: InputFormNumber,
+ select: InputFormSelect,
+ text: InputFormText,
+ textarea: InputFormTextArea,
+};
diff --git a/public/components/common/form/input_editor.tsx b/public/components/common/form/input_editor.tsx
new file mode 100644
index 0000000000..ab38c89f6d
--- /dev/null
+++ b/public/components/common/form/input_editor.tsx
@@ -0,0 +1,15 @@
+import React from 'react';
+import { EuiCodeEditor } from '@elastic/eui';
+import { IInputFormType } from './types';
+
+export const InputFormEditor = ({options, value, onChange}: IInputFormType) => {
+ return (
+
+ );
+};
diff --git a/public/components/common/form/input_filepicker.tsx b/public/components/common/form/input_filepicker.tsx
new file mode 100644
index 0000000000..5a46828a47
--- /dev/null
+++ b/public/components/common/form/input_filepicker.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+import { EuiFilePicker } from '@elastic/eui';
+import { IInputFormType } from './types';
+
+export const InputFormFilePicker = ({onChange, options, setInputRef, key, ...rest} : IInputFormType) => (
+ onChange(
+ // File was added.
+ fileList?.[0]
+ // File was removed. We set the initial value, so the useForm hook will not detect any change. */
+ || rest.initialValue)}
+ display='default'
+ fullWidth
+ aria-label='Upload a file'
+ accept={options.file.extensions.join(',')}
+ ref={setInputRef}
+ />
+);
diff --git a/public/components/common/form/input_number.tsx b/public/components/common/form/input_number.tsx
new file mode 100644
index 0000000000..f4db8e2a0b
--- /dev/null
+++ b/public/components/common/form/input_number.tsx
@@ -0,0 +1,15 @@
+import React from 'react';
+import { EuiFieldNumber } from '@elastic/eui';
+import { IInputFormType } from './types';
+
+export const InputFormNumber = ({ options, value, onChange }: IInputFormType) => {
+ const { integer, ...rest } = options?.number || {};
+ return (
+
+ );
+};
diff --git a/public/components/common/form/input_select.tsx b/public/components/common/form/input_select.tsx
new file mode 100644
index 0000000000..a8f02e99d7
--- /dev/null
+++ b/public/components/common/form/input_select.tsx
@@ -0,0 +1,13 @@
+import React from 'react';
+import { EuiSelect } from '@elastic/eui';
+import { IInputFormType } from './types';
+
+export const InputFormSelect = ({ options, value, onChange }: IInputFormType) => {
+ return (
+
+ )
+};
diff --git a/public/components/common/form/input_switch.tsx b/public/components/common/form/input_switch.tsx
new file mode 100644
index 0000000000..75a575d97f
--- /dev/null
+++ b/public/components/common/form/input_switch.tsx
@@ -0,0 +1,16 @@
+import React from 'react';
+import { EuiSwitch } from '@elastic/eui';
+import { IInputFormType } from './types';
+
+export const InputFormSwitch = ({ options, value, onChange }: IInputFormType) => {
+ const checked = Object.entries(options.switch.values)
+ .find(([, { value: statusValue }]) => value === statusValue)[0];
+
+ return (
+
+ );
+};
diff --git a/public/components/common/form/input_text.tsx b/public/components/common/form/input_text.tsx
new file mode 100644
index 0000000000..feb0d218ee
--- /dev/null
+++ b/public/components/common/form/input_text.tsx
@@ -0,0 +1,14 @@
+import React from 'react';
+import { EuiFieldText } from '@elastic/eui';
+import { IInputFormType } from "./types";
+
+export const InputFormText = ({ value, isInvalid, onChange }: IInputFormType) => {
+ return (
+
+ );
+};
diff --git a/public/components/common/form/input_text_area.tsx b/public/components/common/form/input_text_area.tsx
new file mode 100644
index 0000000000..90cbb2d2e1
--- /dev/null
+++ b/public/components/common/form/input_text_area.tsx
@@ -0,0 +1,15 @@
+import React from 'react';
+import { EuiTextArea } from '@elastic/eui';
+import { IInputFormType } from './types';
+
+export const InputFormTextArea = ({ value, isInvalid, onChange, options } : IInputFormType) => {
+ return (
+
+ );
+};
diff --git a/public/components/common/form/types.ts b/public/components/common/form/types.ts
new file mode 100644
index 0000000000..e064804790
--- /dev/null
+++ b/public/components/common/form/types.ts
@@ -0,0 +1,19 @@
+import { TPluginSettingWithKey } from "../../../../common/constants";
+
+export interface IInputFormType {
+ field: TPluginSettingWithKey
+ value: any
+ onChange: (event: any) => void
+ isInvalid?: boolean
+ options: any
+ setInputRef: (reference: any) => void
+};
+
+export interface IInputForm {
+ field: TPluginSettingWithKey
+ initialValue: any
+ onChange: (event: any) => void
+ label?: string
+ preInput?: ((options: {value: any, error: string | null}) => JSX.Element)
+ postInput?: ((options: {value: any, error: string | null}) => JSX.Element)
+};
diff --git a/public/components/common/globalBreadcrumb/globalBreadcrumb.scss b/public/components/common/globalBreadcrumb/globalBreadcrumb.scss
index e291b87de0..21a4177b19 100644
--- a/public/components/common/globalBreadcrumb/globalBreadcrumb.scss
+++ b/public/components/common/globalBreadcrumb/globalBreadcrumb.scss
@@ -1,8 +1,4 @@
-nav.euiBreadcrumbs.wz-global-breadcrumb span.euiBreadcrumb[title=""]:first-child{
- display: none;
-}
-
-.euiBreadcrumbs--truncate .wz-global-breadcrumb .euiBreadcrumb:not(.euiBreadcrumb--collapsed) span.euiToolTipAnchor{
+.euiBreadcrumbs--truncate .wz-global-breadcrumb .euiBreadcrumb:not(.euiBreadcrumb--collapsed) span.euiToolTipAnchor {
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
@@ -14,18 +10,29 @@ nav.euiBreadcrumbs.wz-global-breadcrumb span.euiBreadcrumb[title=""]:first-child
padding: 0px;
}
-.wz-global-breadcrumb-btn{
- max-width: unset!important;
+.wz-global-breadcrumb-btn {
+ max-width: unset !important;
}
@media screen and (-webkit-min-device-pixel-ratio: 0) {
- _::-webkit-full-page-media, _:future, :root , .wz-global-breadcrumb {
+
+ _::-webkit-full-page-media,
+ _:future,
+ :root,
+ .wz-global-breadcrumb {
line-height: 1.5;
}
}
@-moz-document url-prefix() {
.wz-global-breadcrumb #breadcrumbNoTitle {
- height: auto!important;
+ height: auto !important;
}
}
+
+// styles for opensearch >2.x
+
+.osdHeaderBreadcrumbs ,
+.osdHeaderBreadcrumbs--dark {
+ filter: none;
+}
diff --git a/public/components/common/globalBreadcrumb/globalBreadcrumb.tsx b/public/components/common/globalBreadcrumb/globalBreadcrumb.tsx
index c1d6dedf31..60574fa8ed 100644
--- a/public/components/common/globalBreadcrumb/globalBreadcrumb.tsx
+++ b/public/components/common/globalBreadcrumb/globalBreadcrumb.tsx
@@ -1,12 +1,12 @@
import React, { Component } from 'react';
-import { EuiBreadcrumbs, EuiToolTip } from '@elastic/eui';
+import { EuiBreadcrumbs } from '@elastic/eui';
import { connect } from 'react-redux';
import './globalBreadcrumb.scss';
import { AppNavigate } from '../../../react-services/app-navigate';
import { getAngularModule } from '../../../kibana-services';
class WzGlobalBreadcrumb extends Component {
- props: { state: { breadcrumb: [] } };
+ props: { state: { breadcrumb: [{ agent; text }] } };
constructor(props) {
super(props);
this.props = props;
@@ -15,46 +15,57 @@ class WzGlobalBreadcrumb extends Component {
async componentDidMount() {
const $injector = getAngularModule().$injector;
this.router = $injector.get('$route');
- $('#breadcrumbNoTitle').attr("title", "");
- }
- componnedDidUpdate() {
- $('#breadcrumbNoTitle').attr("title", "");
}
+
+ crumbs = () => {
+ const breadcrumbs = this.props.state.breadcrumb.map((breadcrumb) =>
+ breadcrumb.agent
+ ? {
+ className: 'euiLink euiLink--subdued osdBreadcrumbs',
+ onClick: (ev) => {
+ ev.stopPropagation();
+ AppNavigate.navigateToModule(ev, 'agents', {
+ tab: 'welcome',
+ agent: breadcrumb.agent.id,
+ });
+ this.router.reload();
+ },
+ truncate: true,
+ text: breadcrumb.agent.name,
+ }
+ : {
+ ...breadcrumb,
+ className: 'osdBreadcrumbs',
+ }
+ );
+
+ // remove frist breadcrumb if it's empty
+ if (breadcrumbs?.[0]?.text === '') {
+ breadcrumbs.shift();
+ }
+
+ return breadcrumbs;
+ };
+
render() {
return (
{!!this.props.state.breadcrumb.length && (
breadcrumb.agent ? {
- className: "euiLink euiLink--subdued ",
- onClick: (ev) => {
- ev.stopPropagation();
- AppNavigate.navigateToModule(ev, 'agents', {
- "tab": "welcome", "agent": breadcrumb.agent.id
- });
- this.router.reload();
- },
- id: "breadcrumbNoTitle",
- truncate: true,
- text: (
-
- {breadcrumb.agent.name}
-
- )
- } : breadcrumb)}
+ breadcrumbs={this.crumbs()}
aria-label="Wazuh global breadcrumbs"
/>
)}
- )
+ );
}
}
-const mapStateToProps = state => {
+const mapStateToProps = (state) => {
return {
state: state.globalBreadcrumbReducers,
};
diff --git a/public/components/common/hocs/error-boundary/__snapshots__/with-error-boundary.test.tsx.snap b/public/components/common/hocs/error-boundary/__snapshots__/with-error-boundary.test.tsx.snap
index 7627827d4b..1a84b4ea0f 100644
--- a/public/components/common/hocs/error-boundary/__snapshots__/with-error-boundary.test.tsx.snap
+++ b/public/components/common/hocs/error-boundary/__snapshots__/with-error-boundary.test.tsx.snap
@@ -83,27 +83,27 @@ exports[`withErrorBoundary hoc implementation renders correctly to match the sna
+
+
+ Something went wrong.
+
+
-
-
- Something went wrong.
-
-
diff --git a/public/components/common/hocs/withButtonOpenOnClick.tsx b/public/components/common/hocs/withButtonOpenOnClick.tsx
index bfd7a0b8b8..52ad584ceb 100644
--- a/public/components/common/hocs/withButtonOpenOnClick.tsx
+++ b/public/components/common/hocs/withButtonOpenOnClick.tsx
@@ -12,11 +12,17 @@
import React, { useState } from 'react';
-export const withButtonOpenOnClick = WrappedComponent => ({render, ...rest} : {render?:any, [x:string]: any}) => {
+export const withButtonOpenOnClick = WrappedComponent => ({render, onClick, onClose, ...rest} : {render?:any, [x:string]: any}) => {
const [isOpen, setIsOpen] = useState(false);
- const open = ev => setIsOpen(true);
- const close = ev => setIsOpen(false);
+ const open = ev => {
+ typeof onClick === 'function' && onClick(ev);
+ setIsOpen(true);
+ };
+ const close = ev => {
+ typeof onClose === 'function' && onClose(ev);
+ setIsOpen(false)
+ };
return (
<>
diff --git a/public/components/common/hocs/withUserLogged.tsx b/public/components/common/hocs/withUserLogged.tsx
index fb9ba691ef..acc6016680 100644
--- a/public/components/common/hocs/withUserLogged.tsx
+++ b/public/components/common/hocs/withUserLogged.tsx
@@ -17,8 +17,8 @@ import { getHttp } from '../../../kibana-services';
import { getAssetURL, getThemeAssetURL } from "../../../utils/assets";
export const withUserLogged = (WrappedComponent) => (props) => {
- const withUserLogged = useSelector((state)=> state.appStateReducers.withUserLogged);
- const customAppLogo = useSelector((state)=> state?.appConfig?.data?.['customization.logo.app']);
+ const withUserLogged = useSelector((state) => state.appStateReducers.withUserLogged);
+ const customAppLogo = useSelector((state) => state?.appConfig?.data?.['customization.enabled'] && state?.appConfig?.data?.['customization.logo.app']);
return withUserLogged ? : (
diff --git a/public/components/common/hooks/use-es-search.ts b/public/components/common/hooks/use-es-search.ts
index 6087e6d88e..8618cef2af 100644
--- a/public/components/common/hooks/use-es-search.ts
+++ b/public/components/common/hooks/use-es-search.ts
@@ -77,7 +77,7 @@ const useEsSearch = ({ preAppliedFilters = [], preAppliedAggs = {}, size = 10 })
const search = async (): Promise => {
if (indexPattern) {
- const esQuery = await data.query.getEsQuery(indexPattern as IndexPattern);
+ const esQuery = await data.query.getOpenSearchQuery(indexPattern as IndexPattern);
const searchSource = await data.search.searchSource.create();
const combined = [...esQuery.bool.filter, ...preAppliedFilters, ...filters];
diff --git a/public/components/common/hooks/use-kbn-loading-indicator.ts b/public/components/common/hooks/use-kbn-loading-indicator.ts
index 5514f4e041..6073f94d56 100644
--- a/public/components/common/hooks/use-kbn-loading-indicator.ts
+++ b/public/components/common/hooks/use-kbn-loading-indicator.ts
@@ -10,7 +10,7 @@
* Find more information about this on the LICENSE file.
*/
import { getHttp } from '../../../kibana-services';
-import React, { useEffect, useState } from 'react';
+import React, { useEffect, useState, useRef } from 'react';
import { BehaviorSubject } from 'rxjs';
export const useKbnLoadingIndicator = (): [
@@ -21,28 +21,27 @@ export const useKbnLoadingIndicator = (): [
const [loading, setLoading] = useState(false);
const [flag, setFlag] = useState(false);
const [visible, setVisible] = useState(0);
-
- const loadingCount$ = new BehaviorSubject(0);
-
+ const loadingCount$ = useRef(new BehaviorSubject(0))
+
useEffect(() => {
- getHttp().addLoadingCountSource(loadingCount$);
- const { unsubscribe } = getHttp()
+ getHttp().addLoadingCountSource(loadingCount$.current);
+ const subscriber = getHttp()
.getLoadingCount$()
.subscribe((count) => {
setVisible(count);
!count && setFlag(false);
});
- return unsubscribe;
+ return () => subscriber.unsubscribe();
}, []);
useEffect(() => {
if (loading && visible <= 0) {
- loadingCount$.next(loadingCount$.value + 1);
+ loadingCount$.current.next(loadingCount$.current.value + 1);
setFlag(true);
}
if (!loading && flag && visible > 0) {
- loadingCount$.next(loadingCount$.value - 1);
+ loadingCount$.current.next(loadingCount$.current.value - 1);
}
}, [visible, loading]);
return [loading, setLoading, visible > 0];
diff --git a/public/components/common/modules/discover/discover.scss b/public/components/common/modules/discover/discover.scss
index 0fcee067ec..f1e4162dd8 100644
--- a/public/components/common/modules/discover/discover.scss
+++ b/public/components/common/modules/discover/discover.scss
@@ -36,4 +36,19 @@ div.euiPanel.euiComboBoxOptionsList.euiComboBoxOptionsList {
.hover-row{
background-color: #fbfcfd;
-}
\ No newline at end of file
+}
+
+.module-discover-table .module-discover-table-details {
+ td {
+ vertical-align: text-bottom;
+
+ .wzDocViewer__value {
+ display: inline-block;
+ word-break: break-all;
+ word-wrap: break-word;
+ white-space: pre-wrap;
+ vertical-align: top;
+ padding-top: 2px;
+ }
+ }
+}
diff --git a/public/components/common/modules/discover/discover.tsx b/public/components/common/modules/discover/discover.tsx
index 5ce7937371..130d33ec82 100644
--- a/public/components/common/modules/discover/discover.tsx
+++ b/public/components/common/modules/discover/discover.tsx
@@ -48,8 +48,8 @@ import {
TimeRange,
Query,
buildPhraseFilter,
- getEsQueryConfig,
- buildEsQuery,
+ getOpenSearchQueryConfig,
+ buildOpenSearchQuery,
IFieldType,
} from '../../../../../../../src/plugins/data/common';
import { getDataPlugin, getToasts, getUiSettings } from '../../../../kibana-services';
@@ -264,20 +264,6 @@ export const Discover = compose(
this.indexPattern = {
...(await this.PluginPlatformServices.indexPatterns.get(AppState.getCurrentPattern())),
};
- const fields: IFieldType[] = [];
- Object.keys(this.indexPattern.fields).forEach((item) => {
- if (isNaN(item)) {
- fields.push(this.indexPattern.fields[item]);
- } else if (
- this.props.includeFilters &&
- this.indexPattern.fields[item].name.includes(this.props.includeFilters)
- ) {
- fields.unshift(this.indexPattern.fields[item]);
- } else {
- fields.push(this.indexPattern.fields[item]);
- }
- });
- this.indexPattern.fields = fields;
}
hideCreateCustomLabel = () => {
@@ -336,6 +322,7 @@ export const Discover = compose(
addFilterOut={(filter) => this.addFilterOut(filter)}
toggleColumn={(id) => this.addColumn(id)}
rowDetailsFields={rowDetailsFields}
+ indexPattern={this.indexPattern}
/>
);
@@ -369,8 +356,8 @@ export const Discover = compose(
: [];
const previousFilters =
(this.PluginPlatformServices && this.PluginPlatformServices.query.filterManager.getFilters()) || [];
- const elasticQuery = buildEsQuery(
- undefined,
+ const elasticQuery = buildOpenSearchQuery(
+ this.indexPattern,
query,
_.union(
previousFilters,
@@ -378,7 +365,7 @@ export const Discover = compose(
extraFilters,
this.props.shareFilterManagerWithUserAuthorized || []
),
- getEsQueryConfig(getUiSettings())
+ getOpenSearchQueryConfig(getUiSettings())
);
const { sortField, sortDirection } = this.state;
@@ -712,7 +699,7 @@ export const Discover = compose(
}
openIntelligence(e, redirectTo, itemID) {
- AppNavigate.navigateToModule(e, 'overview', { "tab": 'mitre', "tabView": "intelligence", "tabRedirect": redirectTo, "idToRedirect": itemID});
+ AppNavigate.navigateToModule(e, 'overview', { "tab": 'mitre', "tabView": "intelligence", "tabRedirect": redirectTo, "idToRedirect": itemID });
}
render() {
diff --git a/public/components/common/modules/discover/row-details.tsx b/public/components/common/modules/discover/row-details.tsx
index fdc5dc471e..c4615f1b32 100644
--- a/public/components/common/modules/discover/row-details.tsx
+++ b/public/components/common/modules/discover/row-details.tsx
@@ -10,10 +10,9 @@
* Find more information about this on the LICENSE file.
*/
-import React, { Component, Fragment } from 'react';
+import React, { Component } from 'react';
import {
EuiCodeBlock,
- EuiPanel,
EuiTitle,
EuiSpacer,
EuiIcon,
@@ -31,6 +30,9 @@ import {
EuiBadge,
EuiAccordion,
} from '@elastic/eui';
+import classNames from 'classnames';
+import { DocViewTableRowBtnCollapse } from '../../../../kibana-integrations/discover/application/components/table/table_row_btn_collapse';
+import { arrayContainsObjects, trimAngularSpan } from '../../../../kibana-integrations/discover/application/components/table/table_helper';
import './discover.scss';
import { EuiFlexItem } from '@elastic/eui';
import { WzRequest } from '../../../../react-services/wz-request';
@@ -46,7 +48,8 @@ export class RowDetails extends Component {
items: Array,
totalItems: Number
},
- hover: string
+ hover: string,
+ isCollapsed: boolean,
};
complianceEquivalences: Object
@@ -72,6 +75,7 @@ export class RowDetails extends Component {
items: [],
totalItems: 0,
},
+ isCollapsed: true,
hover: ''
}
@@ -103,7 +107,7 @@ export class RowDetails extends Component {
} else {
return 0;
};
- })
+ })
.reduce((product, [key, value]) => {
let fullPath = addDelimiter(head, key)
return isObject(value) ?
@@ -153,7 +157,9 @@ export class RowDetails extends Component {
)
}
-
+ onToggleCollapse = () => {
+ this.setState({ isCollapsed: !this.state.isCollapsed });
+ }
renderRows() {
// By default show all available fields, otherwise show the fields specified in rowDetailsFields string array
@@ -169,6 +175,7 @@ export class RowDetails extends Component {
const tmpRows = itemPaths.map((item) => {
const key = isString(field) ? item : fieldsToShow[i] + "." + item; // = agent + . + id = agent.id
const value = isString(field) ? field : this.getChildFromPath(this.props.item[fieldsToShow[i]], item);
+ const hasFieldMapping = this.props?.indexPattern?.fields?.getByName(key)?.filterable;// if the field is mapped the filter can be added and removed
const filter = {};
filter[key] = value;
const cells: any[] = [];
@@ -179,8 +186,9 @@ export class RowDetails extends Component {
{(this.state.hover === key &&
-
+
this.props.addFilter(filter)}
iconType="magnifyWithPlus"
aria-label="Filter"
@@ -189,8 +197,9 @@ export class RowDetails extends Component {
-
+
this.props.addFilterOut(filter)}
iconType="magnifyWithMinus"
aria-label="Filter"
@@ -222,13 +231,34 @@ export class RowDetails extends Component {
cells.push(keyCell);
- const formattedValue = Array.isArray(value) ? value.join(', ') : value.toString();
+ const formattedValue = Array.isArray(value) ? this.renderArrayValue(value) : value.toString();
+
+ // If the field is an array of objects, show the collapse button to show the nested fields
+ const showCollapseButton = Array.isArray(value) && arrayContainsObjects(value);
+
+ const valueClassName = classNames({
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ wzDocViewer__value: true,
+ 'truncate-by-height': showCollapseButton && this.state.isCollapsed,
+ "hover-row": this.state.hover === key
+ });
const valueCell =
- {{formattedValue}
}
+ {showCollapseButton && (
+
+ )}
+
cells.push(valueCell);
@@ -244,17 +274,28 @@ export class RowDetails extends Component {
}); //map
rows = [...rows, ...tmpRows]
}//if
- } //for
+ } //for
return rows;
}
+ // Render the row value column supporting nested fields
+ renderArrayValue = (value) => {
+ if (arrayContainsObjects(value)) {
+ const formatted = this.props?.indexPattern?.formatHit({ _index: value }, 'html')?._index;
+ return trimAngularSpan(String(formatted));
+ }
+ else {
+ return value.join(', ')
+ }
+ }
+
getTable() {
return (
-
+
{this.renderRows()}
@@ -402,7 +443,7 @@ export class RowDetails extends Component {
);
} else {
-
+
return value.toString();
}
}
@@ -414,12 +455,20 @@ export class RowDetails extends Component {
let name = "";
value.forEach(item => {
- if (item.type === 'cve')
+ if (item.type === 'cve'){
name = item.name;
- if (item.type === 'link')
- link =
{item.name}
- })
- return
{name}: {link}
+ }
+ if (item.type === 'link') {
+ link =
+ {item.name}
+ ;
+ }
+ });
+ return
{name}: {link} ;
} else {
const _value = typeof value === 'string' ? value : this.getValueAsString(value);
return (
@@ -502,9 +551,13 @@ export class RowDetails extends Component {
}
extraAction={
-
+
- View in Rules
+ View in Rules
}
paddingSize="none"
diff --git a/public/components/common/modules/events.tsx b/public/components/common/modules/events.tsx
index b012f381fb..0005eeb9d6 100644
--- a/public/components/common/modules/events.tsx
+++ b/public/components/common/modules/events.tsx
@@ -24,13 +24,12 @@ import {
} from '@elastic/eui';
import { PatternHandler } from '../../../react-services/pattern-handler';
import { enhanceDiscoverEventsCell } from './events-enhance-discover-fields';
-import { toMountPoint } from '../../../../../../src/plugins/kibana_react/public';
+import { toMountPoint } from '../../../../../../src/plugins/opensearch_dashboards_react/public';
import { withAgentSupportModule, withModuleTabLoader } from '../hocs';
import { compose } from 'redux';
import { UI_LOGGER_LEVELS } from '../../../../common/constants';
import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types';
import { getErrorOrchestrator } from '../../../react-services/common-services';
-import { satisfyPluginPlatformVersion } from '../../../../common/semver';
export const Events = compose(
withAgentSupportModule,
@@ -210,10 +209,7 @@ export const Events = compose(
try {
this.hasRefreshedKnownFields = true;
this.isRefreshing = true;
-
- if (satisfyPluginPlatformVersion('<7.11')) {
- await PatternHandler.refreshIndexPattern();
- }
+ await PatternHandler.refreshIndexPattern();
this.isRefreshing = false;
this.reloadToast();
} catch (error) {
@@ -310,45 +306,24 @@ export const Events = compose(
reloadToast = () => {
const toastLifeTimeMs = 300000;
- if (satisfyPluginPlatformVersion('<7.11')) {
- getToasts().add({
- color: 'success',
- title: 'The index pattern was refreshed successfully.',
- text: toMountPoint(
-
-
- There were some unknown fields for the current index pattern. You need to refresh
- the page to apply the changes.
-
-
- window.location.reload()} size="s">
- Reload page
-
-
-
- ),
- toastLifeTimeMs,
- });
- } else if (satisfyPluginPlatformVersion('>=7.11')) {
- getToasts().add({
- color: 'warning',
- title: 'Found unknown fields in the index pattern.',
- text: toMountPoint(
-
-
- There are some unknown fields for the current index pattern. You need to refresh the
- page to update the fields.
-
-
- window.location.reload()} size="s">
- Reload page
-
-
-
- ),
- toastLifeTimeMs,
- });
- }
+ getToasts().add({
+ color: 'success',
+ title: 'The index pattern was refreshed successfully.',
+ text: toMountPoint(
+
+
+ There were some unknown fields for the current index pattern. You need to refresh
+ the page to apply the changes.
+
+
+ window.location.reload()} size="s">
+ Reload page
+
+
+
+ ),
+ toastLifeTimeMs,
+ });
};
errorToast = (error) => {
diff --git a/public/components/common/modules/module.scss b/public/components/common/modules/module.scss
index 4587782af8..debb1fa6c1 100644
--- a/public/components/common/modules/module.scss
+++ b/public/components/common/modules/module.scss
@@ -78,8 +78,13 @@
padding-top: 105px;
}
-.wz-module.wz-module-welcome .wz-module-body{
- padding-top: 109px !important;
+.wz-module.wz-module-welcome{
+ .wz-module-agent-body{
+ padding-top: 50px !important;
+ }
+ .wz-module-body{
+ padding-top: 109px !important;
+ }
}
.wz-module.wz-module-showing-agent .wz-module-body{
@@ -111,19 +116,23 @@ discover-app-w .sidebar-container {
padding-top: 189px !important;
}
@media only screen and (max-width: 767px){
- .wz-module-header-agent h1{
- white-space: nowrap;
- text-overflow: ellipsis;
- overflow: hidden;
+ .wz-module.wz-module-welcome .wz-module-agent-body{
+ padding-top: 0px !important;
+ }
+ .wz-module-header-agent{
+ height: auto;
+ h1{
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
}
-
.wz-module-body {
margin-top: -160px;
}
.wz-module-header-agent-wrapper, .wz-module-header-nav-wrapper{
position: relative;
- padding-left: 0px;
}
.wz-module-header-nav-wrapper{
@@ -137,5 +146,18 @@ discover-app-w .sidebar-container {
.wz-module-body-agent-info > .euiFlexGroup > .euiFlexItem {
max-width: unset!important;
}
+
+ .wz-module-header-agent-title .euiFlexItem{
+ align-items: flex-start!important;
+ }
+ .wz-agent-empty-item .euiFlexItem{
+ margin-top: 0px!important;
+ margin-bottom:0px!important;
+ }
}
}
+
+.wz-section-sca-euiFlexGroup {
+ display: flex;
+ justify-content: space-between;
+}
\ No newline at end of file
diff --git a/public/components/common/modules/panel/components/module-side-panel.tsx b/public/components/common/modules/panel/components/module-side-panel.tsx
index b35045261a..7259c8bf58 100644
--- a/public/components/common/modules/panel/components/module-side-panel.tsx
+++ b/public/components/common/modules/panel/components/module-side-panel.tsx
@@ -22,8 +22,8 @@ export const ModuleSidePanel = ({ navIsDocked = false, children, ...props }) =>
onClose={() => setNavIsOpen(false)}
>
-
setNavIsOpen(!navIsOpen)}
- iconType={'cross'}
- />
{children}
diff --git a/public/components/common/tables/__snapshots__/table-default.test.tsx.snap b/public/components/common/tables/__snapshots__/table-default.test.tsx.snap
index e023d4b871..c5da18140d 100644
--- a/public/components/common/tables/__snapshots__/table-default.test.tsx.snap
+++ b/public/components/common/tables/__snapshots__/table-default.test.tsx.snap
@@ -75,6 +75,7 @@ exports[`Table Default component renders correctly to match the snapshot 1`] = `
onChange={[Function]}
pagination={
Object {
+ "hidePerPageOptions": false,
"pageIndex": 0,
"pageSize": 15,
"pageSizeOptions": Array [
@@ -186,89 +187,81 @@ exports[`Table Default component renders correctly to match the snapshot 1`] = `
ownFocus={true}
panelPaddingSize="none"
>
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+
-
- Sorting
-
-
+ Sorting
+
-
-
-
-
+
+
+
+
-
+
@@ -326,41 +319,35 @@ exports[`Table Default component renders correctly to match the snapshot 1`] = `
onClick={[Function]}
type="button"
>
-
-
-
-
- Version
-
-
-
-
-
+
+
- Click to sort in ascending order
+
+ Version
+
-
-
-
+
+
+
@@ -390,41 +377,35 @@ exports[`Table Default component renders correctly to match the snapshot 1`] = `
onClick={[Function]}
type="button"
>
-
-
-
-
- Architecture
-
-
-
-
-
+
+
- Click to sort in ascending order
+
+ Architecture
+
-
-
-
+
+
+
@@ -454,41 +435,35 @@ exports[`Table Default component renders correctly to match the snapshot 1`] = `
onClick={[Function]}
type="button"
>
-
-
-
-
- CVE
-
-
-
-
-
+
+
- Click to sort in ascending order
+
+ CVE
+
-
-
-
+
+
+
@@ -518,41 +493,35 @@ exports[`Table Default component renders correctly to match the snapshot 1`] = `
onClick={[Function]}
type="button"
>
-
-
-
-
- Name
-
-
-
-
-
+
+
- Click to sort in ascending order
+
+ Name
+
-
-
-
+
+
+
diff --git a/public/components/common/tables/__snapshots__/table-with-search-bar.test.tsx.snap b/public/components/common/tables/__snapshots__/table-with-search-bar.test.tsx.snap
index 9be43733c8..43dbaa0096 100644
--- a/public/components/common/tables/__snapshots__/table-with-search-bar.test.tsx.snap
+++ b/public/components/common/tables/__snapshots__/table-with-search-bar.test.tsx.snap
@@ -156,7 +156,6 @@ exports[`Table With Search Bar component renders correctly to match the snapshot
panelRef={[Function]}
>
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+
-
- Sorting
-
-
+ Sorting
+
-
-
-
-
+
+
+
+
-
+
@@ -552,41 +543,35 @@ exports[`Table With Search Bar component renders correctly to match the snapshot
onClick={[Function]}
type="button"
>
-
-
-
-
- Version
-
-
-
-
-
+
+
- Click to sort in ascending order
+
+ Version
+
-
-
-
+
+
+
@@ -616,41 +601,35 @@ exports[`Table With Search Bar component renders correctly to match the snapshot
onClick={[Function]}
type="button"
>
-
-
-
-
- Architecture
-
-
-
-
-
+
+
- Click to sort in ascending order
+
+ Architecture
+
-
-
-
+
+
+
@@ -680,41 +659,35 @@ exports[`Table With Search Bar component renders correctly to match the snapshot
onClick={[Function]}
type="button"
>
-
-
-
-
- CVE
-
-
-
-
-
+
+
- Click to sort in ascending order
+
+ CVE
+
-
-
-
+
+
+
@@ -744,41 +717,35 @@ exports[`Table With Search Bar component renders correctly to match the snapshot
onClick={[Function]}
type="button"
>
-
-
-
-
- Name
-
-
-
-
-
+
+
- Click to sort in ascending order
+
+ Name
+
-
-
-
+
+
+
diff --git a/public/components/common/tables/__snapshots__/table-wz-api.test.tsx.snap b/public/components/common/tables/__snapshots__/table-wz-api.test.tsx.snap
index b1ea54681a..9d8f880b48 100644
--- a/public/components/common/tables/__snapshots__/table-wz-api.test.tsx.snap
+++ b/public/components/common/tables/__snapshots__/table-wz-api.test.tsx.snap
@@ -35,13 +35,18 @@ exports[`Table WZ API component renders correctly to match the snapshot 1`] = `
}
title="Table"
>
-
+
-
-
-
-
-
+
-
-
-
-
-
-
-
+
+
+
+
-
- Sorting
-
-
+ Sorting
+
-
-
-
-
+
+
+
+
-
+
@@ -383,41 +397,35 @@ exports[`Table WZ API component renders correctly to match the snapshot 1`] = `
onClick={[Function]}
type="button"
>
-
-
-
-
- Version
-
-
-
-
-
+
+
- Click to sort in ascending order
+
+ Version
+
-
-
-
+
+
+
@@ -447,41 +455,35 @@ exports[`Table WZ API component renders correctly to match the snapshot 1`] = `
onClick={[Function]}
type="button"
>
-
-
-
-
- Architecture
-
-
-
-
-
+
+
- Click to sort in ascending order
+
+ Architecture
+
-
-
-
+
+
+
@@ -511,41 +513,35 @@ exports[`Table WZ API component renders correctly to match the snapshot 1`] = `
onClick={[Function]}
type="button"
>
-
-
-
-
- CVE
-
-
-
-
-
+
+
- Click to sort in ascending order
+
+ CVE
+
-
-
-
+
+
+
@@ -575,41 +571,35 @@ exports[`Table WZ API component renders correctly to match the snapshot 1`] = `
onClick={[Function]}
type="button"
>
-
-
-
-
- Name
-
-
-
-
-
+
+
- Click to sort in ascending order
+
+ Name
+
-
-
-
+
+
+
diff --git a/public/components/common/tables/components/__snapshots__/export-table-csv.test.tsx.snap b/public/components/common/tables/components/__snapshots__/export-table-csv.test.tsx.snap
index 5e82bb0298..a0061544cc 100644
--- a/public/components/common/tables/components/__snapshots__/export-table-csv.test.tsx.snap
+++ b/public/components/common/tables/components/__snapshots__/export-table-csv.test.tsx.snap
@@ -27,6 +27,7 @@ exports[`Export Table Csv component renders correctly to match the snapshot 1`]
{
getToasts().add({
@@ -42,7 +42,7 @@ export function ExportTableCsv({endpoint,totalItems,filters,title}){
[
...formatedFilters
],
- `vuls-${(title).toLowerCase()}`
+ `${(title).toLowerCase()}`
);
} catch (error) {
const options = {
diff --git a/public/components/common/tables/table-default.tsx b/public/components/common/tables/table-default.tsx
index 95aad1e4a4..97e3d50974 100644
--- a/public/components/common/tables/table-default.tsx
+++ b/public/components/common/tables/table-default.tsx
@@ -10,7 +10,7 @@
* Find more information about this on the LICENSE file.
*/
-import React, { useState, useEffect } from 'react';
+import React, { useState, useEffect, useRef } from 'react';
import { EuiBasicTable } from '@elastic/eui';
import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types';
import { UI_LOGGER_LEVELS } from '../../../../common/constants';
@@ -20,35 +20,37 @@ export function TableDefault({
onSearch,
tableColumns,
tablePageSizeOptions = [15, 25, 50, 100],
+ hidePerPageOptions = false,
tableInitialSortingDirection = 'asc',
tableInitialSortingField = '',
tableProps = {},
reload,
- endpoint
-})
- {
-
+ rowProps,
+ endpoint,
+}) {
const [loading, setLoading] = useState(false);
const [items, setItems] = useState([]);
const [totalItems, setTotalItems] = useState(0);
const [pagination, setPagination] = useState({
pageIndex: 0,
- pageSize: tablePageSizeOptions[0]
+ pageSize: tablePageSizeOptions[0],
});
const [sorting, setSorting] = useState({
sort: {
field: tableInitialSortingField,
direction: tableInitialSortingDirection,
- }
+ },
});
-
- function tableOnChange({ page = {}, sort = {} }){
+
+ const isMounted = useRef(false);
+
+ function tableOnChange({ page = {}, sort = {} }) {
const { index: pageIndex, size: pageSize } = page;
const { field, direction } = sort;
setPagination({
pageIndex,
- pageSize
+ pageSize,
});
setSorting({
sort: {
@@ -56,22 +58,27 @@ export function TableDefault({
direction,
},
});
- };
-
+ }
+
useEffect(() => {
- // Reset the page index when the endpoint changes.
- // This will cause that onSearch function is triggered because to changes in pagination in the another effect.
- setPagination({pageIndex: 0, pageSize: pagination.pageSize});
+ // This effect is triggered when the component is mounted because of how to the useEffect hook works.
+ // We don't want to set the pagination state because there is another effect that has this dependency
+ // and will cause the effect is triggered (redoing the onSearch function).
+ if (isMounted.current) {
+ // Reset the page index when the endpoint changes.
+ // This will cause that onSearch function is triggered because to changes in pagination in the another effect.
+ setPagination({ pageIndex: 0, pageSize: pagination.pageSize });
+ }
}, [endpoint]);
-
+
useEffect(() => {
- (async function(){
- try{
+ (async function () {
+ try {
setLoading(true);
const { items, totalItems } = await onSearch(endpoint, [], pagination, sorting);
setItems(items);
setTotalItems(totalItems);
- }catch(error){
+ } catch (error) {
setItems([]);
setTotalItems(0);
const options = {
@@ -87,21 +94,34 @@ export function TableDefault({
getErrorOrchestrator().handleError(options);
}
setLoading(false);
- })()
+ })();
}, [endpoint, pagination, sorting, reload]);
+ // It is required that this effect runs after other effects that use isMounted
+ // to avoid that these effects run when the component is mounted, only running
+ // when one of its dependencies changes.
+ useEffect(() => {
+ isMounted.current = true;
+ }, []);
+
const tablePagination = {
...pagination,
totalItemCount: totalItems,
- pageSizeOptions: tablePageSizeOptions
- }
- return
+
+ >
+ );
}
diff --git a/public/components/common/tables/table-with-search-bar.tsx b/public/components/common/tables/table-with-search-bar.tsx
index 5bfd358049..6804dcb1a8 100644
--- a/public/components/common/tables/table-with-search-bar.tsx
+++ b/public/components/common/tables/table-with-search-bar.tsx
@@ -10,8 +10,9 @@
* Find more information about this on the LICENSE file.
*/
-import React, { useState, useEffect } from 'react';
+import React, { useState, useEffect, useRef } from 'react';
import { EuiBasicTable, EuiSpacer } from '@elastic/eui';
+import _ from 'lodash';
import { WzSearchBar } from '../../wz-search-bar/';
import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types';
import { UI_LOGGER_LEVELS } from '../../../../common/constants';
@@ -48,29 +49,38 @@ export function TableWithSearchBar({
},
});
+ const isMounted = useRef(false);
+
function tableOnChange({ page = {}, sort = {} }) {
- const { index: pageIndex, size: pageSize } = page;
- const { field, direction } = sort;
- setPagination({
- pageIndex,
- pageSize,
- });
- setSorting({
- sort: {
- field,
- direction,
- },
- });
+ if (isMounted.current) {
+ const { index: pageIndex, size: pageSize } = page;
+ const { field, direction } = sort;
+ setPagination({
+ pageIndex,
+ pageSize,
+ });
+ setSorting({
+ sort: {
+ field,
+ direction,
+ },
+ });
+ }
}
useEffect(() => {
- // Reset the page index when the endpoint changes.
- // This will cause that onSearch function is triggered because to changes in pagination in the another effect.
- setPagination({pageIndex: 0, pageSize: pagination.pageSize});
- }, [endpoint]);
+ // This effect is triggered when the component is mounted because of how to the useEffect hook works.
+ // We don't want to set the pagination state because there is another effect that has this dependency
+ // and will cause the effect is triggered (redoing the onSearch function).
+ if (isMounted.current) {
+ // Reset the page index when the endpoint changes.
+ // This will cause that onSearch function is triggered because to changes in pagination in the another effect.
+ setPagination({ pageIndex: 0, pageSize: pagination.pageSize });
+ }
+ }, [endpoint, reload]);
- useEffect(() => {
- (async function () {
+ useEffect(function () {
+ (async () => {
try {
setLoading(true);
const { items, totalItems } = await onSearch(endpoint, filters, pagination, sorting);
@@ -93,12 +103,24 @@ export function TableWithSearchBar({
}
setLoading(false);
})();
- }, [filters, pagination, sorting, reload]);
+ }, [filters, pagination, sorting]);
useEffect(() => {
- setFilters(rest.filters || []);
+ // This effect is triggered when the component is mounted because of how to the useEffect hook works.
+ // We don't want to set the filters state because there is another effect that has this dependency
+ // and will cause the effect is triggered (redoing the onSearch function).
+ if (isMounted.current && !_.isEqual(rest.filters, filters)) {
+ setFilters(rest.filters || []);
+ }
}, [rest.filters]);
+ // It is required that this effect runs after other effects that use isMounted
+ // to avoid that these effects run when the component is mounted, only running
+ // when one of its dependencies changes.
+ useEffect(() => {
+ isMounted.current = true;
+ }, []);
+
const tablePagination = {
...pagination,
totalItemCount: totalItems,
diff --git a/public/components/common/tables/table-wz-api.tsx b/public/components/common/tables/table-wz-api.tsx
index 35df090b93..cb46407446 100644
--- a/public/components/common/tables/table-wz-api.tsx
+++ b/public/components/common/tables/table-wz-api.tsx
@@ -10,30 +10,61 @@
* Find more information about this on the LICENSE file.
*/
-import React, { useCallback, useState } from 'react';
+import React, { ReactNode, useCallback, useEffect, useState } from 'react';
import {
EuiTitle,
EuiLoadingSpinner,
EuiFlexGroup,
EuiFlexItem,
+ EuiText,
+ EuiButtonEmpty,
} from '@elastic/eui';
import { filtersToObject } from '../../wz-search-bar';
import { TableWithSearchBar } from './table-with-search-bar';
-import { TableDefault } from './table-default'
+import { TableDefault } from './table-default';
import { WzRequest } from '../../../react-services/wz-request';
-import { ExportTableCsv } from './components/export-table-csv';
+import { ExportTableCsv } from './components/export-table-csv';
import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types';
import { UI_LOGGER_LEVELS } from '../../../../common/constants';
import { getErrorOrchestrator } from '../../../react-services/common-services';
-export function TableWzAPI({...rest}){
+/**
+ * Search input custom filter button
+ */
+interface CustomFilterButton {
+ label: string;
+ field: string;
+ value: string;
+}
+export function TableWzAPI({
+ actionButtons,
+ ...rest
+}: {
+ actionButtons?: ReactNode | ReactNode[];
+ title?: string;
+ description?: string;
+ downloadCsv?: boolean;
+ searchTable?: boolean;
+ endpoint: string;
+ buttonOptions?: CustomFilterButton[];
+ onFiltersChange?: Function;
+ showReload?: boolean;
+ searchBarProps?: any;
+ reload?: boolean;
+}) {
const [totalItems, setTotalItems] = useState(0);
const [filters, setFilters] = useState([]);
const [isLoading, setIsLoading] = useState(false);
- const onFiltersChange = filters => typeof rest.onFiltersChange === 'function' ? rest.onFiltersChange(filters) : null;
+ const onFiltersChange = (filters) =>
+ typeof rest.onFiltersChange === 'function' ? rest.onFiltersChange(filters) : null;
+
+ /**
+ * Changing the reloadFootprint timestamp will trigger reloading the table
+ */
+ const [reloadFootprint, setReloadFootprint] = useState(rest.reload || 0);
- const onSearch = useCallback(async function(endpoint, filters, pagination, sorting){
+ const onSearch = useCallback(async function (endpoint, filters, pagination, sorting) {
try {
const { pageIndex, pageSize } = pagination;
const { field, direction } = sorting.sort;
@@ -44,12 +75,14 @@ export function TableWzAPI({...rest}){
...filtersToObject(filters),
offset: pageIndex * pageSize,
limit: pageSize,
- sort: `${direction === 'asc' ? '+' : '-'}${field}`
+ sort: `${direction === 'asc' ? '+' : '-'}${field}`,
};
const response = await WzRequest.apiReq('GET', endpoint, { params });
- const { affected_items: items, total_affected_items: totalItems } = ((response || {}).data || {}).data;
+ const { affected_items: items, total_affected_items: totalItems } = (
+ (response || {}).data || {}
+ ).data;
setIsLoading(false);
setTotalItems(totalItems);
return { items: rest.mapResponseItem ? items.map(rest.mapResponseItem) : items, totalItems };
@@ -67,42 +100,96 @@ export function TableWzAPI({...rest}){
},
};
getErrorOrchestrator().handleError(options);
- };
- },[]);
+ }
+ }, []);
+
+ const renderActionButtons = (
+ <>
+ {Array.isArray(actionButtons)
+ ? actionButtons.map((button, key) => (
+
+ {button}
+
+ ))
+ : typeof actionButtons === 'object' && (
+ {actionButtons}
+ )}
+ >
+ );
+
+ /**
+ * Generate a new reload footprint
+ */
+ const triggerReload = () => {
+ setReloadFootprint(Date.now());
+ };
+
+ useEffect(() => {
+ if (rest.reload) triggerReload();
+ }, [rest.reload]);
+
+ const ReloadButton = (
+
+ triggerReload()}
+ >
+ Refresh
+
+
+ );
const header = (
-
-
+
+
{rest.title && (
- {rest.title} {isLoading ? : ({ totalItems }) }
+
+ {rest.title}{' '}
+ {isLoading ? : ({totalItems}) }
+
)}
+ {rest.description && {rest.description} }
+
+
+
+ {/* Render optional custom action button */}
+ {renderActionButtons}
+ {/* Render optional reload button */}
+ {rest.showReload && ReloadButton}
+ {/* Render optional export to CSV button */}
+ {rest.downloadCsv && (
+
+ )}
+
- {rest.downloadCsv && }
- )
+ );
+
+ const table = rest.searchTable ? (
+
+ ) : (
+
+ );
- const table = rest.searchTable ?
- :
-
-
return (
- <>
- {header}
- {table}
- >)
+ <>
+ {header}
+ {table}
+ >
+ );
}
// Set default props
TableWzAPI.defaultProps = {
title: null,
downloadCsv: false,
- searchBar: false
-};
\ No newline at end of file
+ searchBar: false,
+};
diff --git a/public/components/common/welcome/agents-info.js b/public/components/common/welcome/agents-info.js
index 1a5a04cc26..cad892a208 100644
--- a/public/components/common/welcome/agents-info.js
+++ b/public/components/common/welcome/agents-info.js
@@ -25,6 +25,7 @@ import WzTextWithTooltipIfTruncated from '../wz-text-with-tooltip-if-truncated';
import { WzStat } from '../../wz-stat';
import { GroupTruncate } from '../util/agent-group-truncate'
import { AgentStatus } from '../../agents/agent_status';
+import { compressIPv6 } from '../../../services/ipv6-services';
export class AgentInfo extends Component {
constructor(props) {
@@ -33,7 +34,7 @@ export class AgentInfo extends Component {
this.state = {};
}
-
+
async componentDidMount() {
const managerVersion = await WzRequest.apiReq('GET', '/', {});
this.setState({
@@ -73,7 +74,7 @@ export class AgentInfo extends Component {
const osName = os_name === '- -' ? '-' : os_name;
return (
-
+
{this.getPlatformIcon(this.props.agent)}
{' '}{osName}
@@ -99,13 +100,13 @@ export class AgentInfo extends Component {
)
}
- buildStats(items) {
+ buildStats(items) {
const checkField = field => {
return field !== undefined || field ? field : '-';
};
const stats = items.map(item => {
// We add tooltipProps, so that the ClusterNode and Operating System fields occupy their space and do not exceed this, overlapping with the one on the right
- const tooltipProps = item.description === 'Cluster node' ? { anchorClassName: 'wz-width-100'} : {};
+ const tooltipProps = item.description === 'Cluster node' ? { anchorClassName: 'wz-width-100' } : {};
return (
+
) : (
{checkField(item.title)}
@@ -157,7 +158,7 @@ export class AgentInfo extends Component {
arrayStats = [
{ title: agent.id, description: 'ID', style: { minWidth: 30 } },
{ title: agent.status, description: 'Status', style: { minWidth: 130 } },
- { title: agent.ip, description: 'IP', style: { minWidth: 80 } },
+ { title: compressIPv6(agent.ip), description: 'IP address', style: { minWidth: 80 } },
{ title: agent.version, description: 'Version', style: { minWidth: 100 } },
{ title: agent.group, description: 'Groups', style: { minWidth: 150 } },
{ title: agent.name, description: 'Operating system', style: { minWidth: 150 } },
@@ -169,11 +170,9 @@ export class AgentInfo extends Component {
const stats = this.buildStats(arrayStats);
- // window.innerWidth < 1500 ? console.log("<1500") : console.log("max")
-
return (
-
+
{stats}
diff --git a/public/components/common/welcome/agents-welcome.js b/public/components/common/welcome/agents-welcome.js
index c60254d341..3ef25090e0 100644
--- a/public/components/common/welcome/agents-welcome.js
+++ b/public/components/common/welcome/agents-welcome.js
@@ -267,9 +267,17 @@ class AgentsWelcome extends Component {
-
+ {this.state.widthWindow >= 768?(
+
{this.props.agent.name}
-
+
+ ):
+ (
+
+ {this.props.agent.name}
+
+ )
+ }
@@ -308,7 +316,9 @@ class AgentsWelcome extends Component {
}
+
+
-
+
The agent has been registered but has not yet connected to the manager.
-
+
Checking connection with the Wazuh server
@@ -536,28 +550,25 @@ class AgentsWelcome extends Component {
return (
-
-
+
-
-
+
+
+
- {/* DatePicker */}
+ {/* DatePicker */}
{ }} />
diff --git a/public/components/common/welcome/components/agent-sections.ts b/public/components/common/welcome/components/agent-sections.ts
index 5e62bd7d0e..3278e60914 100644
--- a/public/components/common/welcome/components/agent-sections.ts
+++ b/public/components/common/welcome/components/agent-sections.ts
@@ -57,7 +57,7 @@ export const getAgentSections = (menuAgent) => {
github: {
id: WAZUH_MODULES_ID.GITHUB,
text: 'GitHub',
- isPin: menuAgent.github ? this.menuAgent.github : false
+ isPin: menuAgent.github ? menuAgent.github : false
},
pm: {
id: WAZUH_MODULES_ID.POLICY_MONITORING,
diff --git a/public/components/common/welcome/components/menu-agent.js b/public/components/common/welcome/components/menu-agent.js
index 866e684a93..9fc5fb6159 100644
--- a/public/components/common/welcome/components/menu-agent.js
+++ b/public/components/common/welcome/components/menu-agent.js
@@ -158,7 +158,6 @@ class WzMenuAgent extends Component {
render() {
const securityInformation = [
this.createItem(this.agentSections.securityInformation, {
- disabled: true,
icon: ,
items: this.createItems(this.securityInformationItems),
}),
@@ -166,7 +165,6 @@ class WzMenuAgent extends Component {
const auditing = [
this.createItem(this.agentSections.auditing, {
- disabled: true,
icon: ,
items: this.createItems(this.auditingItems),
}),
@@ -174,7 +172,6 @@ class WzMenuAgent extends Component {
const threatDetection = [
this.createItem(this.agentSections.threatDetection, {
- disabled: true,
icon: ,
items: this.createItems(this.threatDetectionItems),
}),
@@ -182,7 +179,6 @@ class WzMenuAgent extends Component {
const regulatoryCompliance = [
this.createItem(this.agentSections.regulatoryCompliance, {
- disabled: true,
icon: ,
items: this.createItems(this.regulatoryComplianceItems),
}),
@@ -215,7 +211,6 @@ class WzMenuAgent extends Component {
const mapStateToProps = (state) => {
return {
- state: state.rulesetReducers,
currentAgentData: state.appStateReducers.currentAgentData,
currentTab: state.appStateReducers.currentTab,
};
diff --git a/public/components/common/welcome/components/sca_scan/sca_scan.tsx b/public/components/common/welcome/components/sca_scan/sca_scan.tsx
index bebe4003e7..470db2f74f 100644
--- a/public/components/common/welcome/components/sca_scan/sca_scan.tsx
+++ b/public/components/common/welcome/components/sca_scan/sca_scan.tsx
@@ -20,13 +20,11 @@ import {
EuiText,
EuiLink,
EuiBadge,
- EuiStat,
EuiSpacer,
EuiLoadingChart,
EuiButtonIcon,
EuiToolTip,
EuiEmptyPrompt,
- EuiIcon
} from '@elastic/eui';
import moment from 'moment-timezone';
import store from '../../../../../redux/store';
@@ -36,6 +34,13 @@ import { formatUIDate } from '../../../../../react-services/time-service';
import { getAngularModule } from '../../../../../kibana-services';
import { withReduxProvider, withUserAuthorizationPrompt } from "../../../hocs";
import { compose } from 'redux';
+import SCAPoliciesTable from '../../../../agents/sca/inventory/agent-policies-table';
+import { MODULE_SCA_CHECK_RESULT_LABEL } from '../../../../../../common/constants';
+
+type Props = {
+ agent: { [key in string]: any };
+ router: any; // its angular router
+}
export const ScaScan = compose(
withReduxProvider,
@@ -49,16 +54,16 @@ export const ScaScan = compose(
{action: 'sca:read', resource: 'agent:group:*'}
]
])
-)(class ScaScan extends Component {
+)(class ScaScan extends Component {
_isMount = false;
- props!: {
- [key: string]: any
- }
+ router;
state: {
lastScan: {
[key: string]: any
},
isLoading: Boolean,
+ firstTable: Boolean,
+ policies: any[],
}
constructor(props) {
@@ -66,9 +71,12 @@ export const ScaScan = compose(
this.state = {
lastScan: {},
isLoading: true,
+ firstTable: true,
+ policies: [],
};
}
+
async componentDidMount() {
this._isMount = true;
const $injector = getAngularModule().$injector;
@@ -112,21 +120,72 @@ export const ScaScan = compose(
}
}
+ onClickRow = (policy) => {
+ window.location.href = `#/overview?tab=sca&redirectPolicyTable=${policy.policy_id}`;
+ store.dispatch(updateCurrentAgentData(this.props.agent));
+ this.router.reload();
+ }
+
renderScanDetails() {
const { isLoading, lastScan } = this.state;
if (isLoading || lastScan === undefined) return;
+
+ const columnsPolicies = [
+ {
+ field: 'name',
+ name: 'Policy',
+ width: '40%',
+ },
+ {
+ field: 'end_scan',
+ name: 'End scan',
+ dataType: 'date',
+ render: formatUIDate,
+ width: '20%',
+ },
+ {
+ field: 'pass',
+ name: MODULE_SCA_CHECK_RESULT_LABEL.passed,
+ width: '10%',
+ },
+ {
+ field: 'fail',
+ name: MODULE_SCA_CHECK_RESULT_LABEL.failed,
+ width: '10%',
+ },
+ {
+ field: 'invalid',
+ name: MODULE_SCA_CHECK_RESULT_LABEL['not applicable'],
+ width: '10%',
+ },
+ {
+ field: 'score',
+ name: 'Score',
+ width: '10%',
+ render: (score) => {
+ return `${score}%`;
+ }
+ },
+ ];
+
+ const tableProps = {
+ tablePageSizeOptions: [4],
+ hidePerPageOptions: true
+ }
+
return (
{
- window.location.href = `#/overview?tab=sca&redirectPolicy=${lastScan.policy_id}`;
+ window.location.href = `#/overview?tab=sca&redirectPolicyTable=${lastScan.policy_id}`;
store.dispatch(updateCurrentAgentData(this.props.agent));
this.router.reload();
}
}>
{lastScan.name}
+
@@ -134,63 +193,14 @@ export const ScaScan = compose(
{lastScan.policy_id}
-
-
-
- {lastScan.description}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Start time: {formatUIDate(lastScan.start_scan)}
-
-
-
-
- Duration: {this.durationScan()}
-
-
-
+
+
+
)
}
@@ -225,20 +235,30 @@ export const ScaScan = compose(
-
-
- SCA: Last scan
-
+
+
+
+ {
+ window.location.href = `#/overview?tab=sca&redirectPolicy=${lastScan.policy_id}`;
+ store.dispatch(updateCurrentAgentData(this.props.agent));
+ this.router.reload();
+ }
+ }>
+ SCA: Lastest scans
+
+
+
{
- window.location.href = `#/overview?tab=sca`;
- store.dispatch(updateCurrentAgentData(this.props.agent));
- this.router.reload();
- }
+ window.location.href = `#/overview?tab=sca`;
+ store.dispatch(updateCurrentAgentData(this.props.agent));
+ this.router.reload();
+ }
}
aria-label="Open SCA Scans" />
diff --git a/public/components/health-check/components/__snapshots__/check-result.test.tsx.snap b/public/components/health-check/components/__snapshots__/check-result.test.tsx.snap
index e3539a8c2c..1eb1fbc457 100644
--- a/public/components/health-check/components/__snapshots__/check-result.test.tsx.snap
+++ b/public/components/health-check/components/__snapshots__/check-result.test.tsx.snap
@@ -51,21 +51,21 @@ exports[`Check result component should render a Check result screen 1`] = `
{
- getDataPlugin().query.timefilter.timefilter.setTime(WAZUH_PLUGIN_PLATFORM_SETTING_TIME_FILTER)
- && checkLogger.action(`Timefilter set to ${JSON.stringify(options.defaultAppValue)}`);
- }),
+ validator: checkPluginPlatformSettings(
+ PLUGIN_PLATFORM_SETTING_NAME_TIME_FILTER,
+ JSON.stringify(WAZUH_PLUGIN_PLATFORM_SETTING_TIME_FILTER),
+ (checkLogger: CheckLogger, options: { defaultAppValue: any }) => {
+ getDataPlugin().query.timefilter.timefilter.setTime(WAZUH_PLUGIN_PLATFORM_SETTING_TIME_FILTER)
+ && checkLogger.action(`Timefilter set to ${JSON.stringify(options.defaultAppValue)}`);
+ }),
awaitFor: [],
canRetry: true,
}
};
function HealthCheckComponent() {
- const [checkErrors, setCheckErrors] = useState<{[key:string]: []}>({});
- const [checksReady, setChecksReady] = useState<{[key: string]: boolean}>({});
+ const [checkErrors, setCheckErrors] = useState<{ [key: string]: [] }>({});
+ const [checksReady, setChecksReady] = useState<{ [key: string]: boolean }>({});
const [isDebugMode, setIsDebugMode] = useState(false);
const appConfig = useAppConfig();
const checksInitiated = useRef(false);
@@ -142,35 +145,39 @@ function HealthCheckComponent() {
// Redirect to app when all checks are ready
Object.keys(checks)
.every(check => checksReady[check])
- && !isDebugMode && (() => setTimeout(redirectionPassHealthcheck, HEALTH_CHECK_REDIRECTION_TIME)
+ && !isDebugMode && (() => setTimeout(redirectionPassHealthcheck, HEALTH_CHECK_REDIRECTION_TIME)
)()
}, [checksReady]);
useEffect(() => {
// Check if Health should not redirect automatically (Debug mode)
setIsDebugMode(window.location.href.includes('debug'));
- },[]);
+ }, []);
const handleErrors = (checkID, errors, parsed) => {
const newErrors = parsed
? errors.map((error) =>
- ErrorHandler.handle(error, 'Health Check', { warning: false, silent: true })
- )
+ ErrorHandler.handle(error, 'Health Check', { warning: false, silent: true })
+ )
: errors;
- setCheckErrors((prev) => ({...prev, [checkID]: newErrors}));
+ setCheckErrors((prev) => ({ ...prev, [checkID]: newErrors }));
};
const cleanErrors = (checkID: string) => {
delete checkErrors[checkID];
- setCheckErrors({...checkErrors});
+ setCheckErrors({ ...checkErrors });
}
- const handleCheckReady = (checkID, isReady) => {
- setChecksReady(prev => ({...prev, [checkID]: isReady}));
+ const handleCheckReady = (checkID, isReady) => {
+ setChecksReady(prev => ({ ...prev, [checkID]: isReady }));
}
- const logoUrl = getHttp().basePath.prepend(appConfig.data['customization.logo.healthcheck'] ? getAssetURL(appConfig.data['customization.logo.healthcheck']) : getThemeAssetURL('logo.svg'));
+ const logoUrl = getHttp().basePath.prepend(
+ appConfig.data['customization.enabled'] && appConfig.data['customization.logo.healthcheck'] ?
+ getAssetURL(appConfig.data['customization.logo.healthcheck']) :
+ getThemeAssetURL('logo.svg')
+ );
const thereAreErrors = Object.keys(checkErrors).length > 0;
const renderChecks = () => {
@@ -188,7 +195,7 @@ function HealthCheckComponent() {
handleErrors={handleErrors}
cleanErrors={cleanErrors}
isLoading={appConfig.isLoading}
- handleCheckReady= {handleCheckReady}
+ handleCheckReady={handleCheckReady}
checksReady={checksReady}
canRetry={checks[check].canRetry}
/>
@@ -196,12 +203,35 @@ function HealthCheckComponent() {
});
};
+ const addTagsToUrl = (error) => {
+ const words = error.split(' ');
+ words.forEach((word, index) => {
+ if (word.includes('http://') || word.includes('https://')) {
+ if (words[index - 1] === 'guide:') {
+ if (word.endsWith('.') || word.endsWith(',')) {
+ words[index - 2] = `${words[index - 2]} ${words[index - 1].slice(0, -1)} ${word.slice(-1)}`;
+ } else {
+ words[index - 2] = `${words[index - 2]} ${words[index - 1].slice(0, -1)} `;
+ }
+ words.splice(index - 1, 2);
+ } else{
+ if (word.endsWith('.') || word.endsWith(',')) {
+ words[index] = `${word.slice(0, -1)} ${word.slice(-1)}`;
+ } else {
+ words[index] = `${word} `;
+ }
+ }
+ }
+ });
+ return words.join(' ');
+ };
+
const renderErrors = () => {
- return Object.keys(checkErrors).map((checkID) =>
+ return Object.keys(checkErrors).map((checkID) =>
checkErrors[checkID].map((error, index) => (
{`[${checks[checkID].label}]`} >)}
+ title={(<>{`[${checks[checkID].label}]`} >)}
color="danger"
iconType="alert"
style={{ textAlign: 'left' }}
@@ -210,7 +240,7 @@ function HealthCheckComponent() {
))
- )
+ )
};
return (
@@ -254,7 +284,7 @@ function HealthCheckComponent() {
);
}
-export const HealthCheck = compose (withErrorBoundary,withReduxProvider) (HealthCheckComponent);
+export const HealthCheck = compose(withErrorBoundary, withReduxProvider)(HealthCheckComponent);
export const HealthCheckTest = HealthCheckComponent;
diff --git a/public/components/health-check/services/check-api.service.ts b/public/components/health-check/services/check-api.service.ts
index 25a633bef2..a505d6c406 100644
--- a/public/components/health-check/services/check-api.service.ts
+++ b/public/components/health-check/services/check-api.service.ts
@@ -15,6 +15,11 @@
import { getToasts } from '../../../kibana-services';
import { ApiCheck, AppState, GenericRequest } from '../../../react-services';
import { CheckLogger } from '../types/check_logger';
+import {
+ PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING,
+ PLUGIN_APP_NAME,
+} from '../../../../common/constants';
+import { webDocumentationLink } from '../../../../common/services/web_documentation';
const trySetDefault = async (checkLogger: CheckLogger) => {
try {
@@ -33,11 +38,28 @@ const trySetDefault = async (checkLogger: CheckLogger) => {
return hosts[i].id;
}
} catch (err) {
- checkLogger.info(`Could not connect to API id [${hosts[i].id}]: ${err.message || err}`);
- errors.push(`Could not connect to API id [${hosts[i].id}]: ${err.message || err}`);
+ checkLogger.info(
+ `Could not connect to API id [${hosts[i].id}]: ${
+ err.message || err
+ }`,
+ );
+ errors.push(
+ `Could not connect to API id [${hosts[i].id}]: ${
+ err.message || err
+ }`,
+ );
}
}
if (errors.length) {
+ for (var j = 0; j < errors.length; j++) {
+ if (errors[j].includes('ERROR3099 - 405: Method Not Allowed')) {
+ return Promise.reject(
+ `No API available to connect. This may be related to a version mismatch between Wazuh Server and ${PLUGIN_APP_NAME}. Please check the versions and try again. Read more about this in our troubleshooting guide: ${webDocumentationLink(
+ PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING,
+ )}#wazuh-api-and-wazuh-app-version-mismatch-error-is-displayed.`,
+ );
+ }
+ }
return Promise.reject('No API available to connect');
}
}
@@ -48,60 +70,71 @@ const trySetDefault = async (checkLogger: CheckLogger) => {
}
};
-export const checkApiService = (appInfo: any) => async (checkLogger: CheckLogger) => {
- let apiChanged = false;
- try {
- let currentApi = JSON.parse(AppState.getCurrentAPI() || '{}');
- if(!currentApi.id){
- checkLogger.info(`No current API selected`);
- currentApi.id = await trySetDefault(checkLogger);
- apiChanged = true;
- }
-
- checkLogger.info(`Current API id [${currentApi.id}]`);
- checkLogger.info(`Checking current API id [${currentApi.id}]...`);
- const data = await ApiCheck.checkStored(currentApi.id).catch(async (err) => {
- checkLogger.info(`Current API id [${currentApi.id}] has some problem: ${err.message || err}`);
- const newApi = await trySetDefault(checkLogger);
- if (newApi.error) {
- return { error: newApi.error };
+export const checkApiService =
+ (appInfo: any) => async (checkLogger: CheckLogger) => {
+ let apiChanged = false;
+ try {
+ let currentApi = JSON.parse(AppState.getCurrentAPI() || '{}');
+ if (!currentApi.id) {
+ checkLogger.info(`No current API selected`);
+ currentApi.id = await trySetDefault(checkLogger);
+ apiChanged = true;
}
- apiChanged = true;
- checkLogger.info(`API host id [${newApi}] available`);
- return await ApiCheck.checkStored(newApi, true);
- });
- if (apiChanged) {
- const api = ((data || {}).data || {}).data || {};
- const name = (api.cluster_info || {}).manager || false;
- AppState.setCurrentAPI(JSON.stringify({ name: name, id: api.id }));
- checkLogger.info(`Set current API in cookie: id [${api.id}], name [${name}]`);
- getToasts().add({
- color: 'warning',
- title: 'Selected Wazuh API has been updated',
- text: '',
- toastLifeTimeMs: 3000,
- });
- }
- //update cluster info
- const cluster_info = (((data || {}).data || {}).data || {}).cluster_info;
- if (cluster_info) {
- AppState.setClusterInfo(cluster_info);
- checkLogger.info(`Set cluster info in cookie`);
- }
- if (data === 3099) {
- checkLogger.error('Wazuh not ready yet');
- } else if (data.data.error || data.data.data.apiIsDown) {
- const errorMessage = data.data.data.apiIsDown
- ? 'Wazuh API is down'
- : `Error connecting to the API: ${
- data.data.error && data.data.error.message ? ` ${data.data.error.message}` : ''
- }`;
- checkLogger.error(errorMessage);
+ checkLogger.info(`Current API id [${currentApi.id}]`);
+ checkLogger.info(`Checking current API id [${currentApi.id}]...`);
+ const data = await ApiCheck.checkStored(currentApi.id).catch(
+ async err => {
+ checkLogger.info(
+ `Current API id [${currentApi.id}] has some problem: ${
+ err.message || err
+ }`,
+ );
+ const newApi = await trySetDefault(checkLogger);
+ if (newApi.error) {
+ return { error: newApi.error };
+ }
+ apiChanged = true;
+ checkLogger.info(`API host id [${newApi}] available`);
+ return await ApiCheck.checkStored(newApi, true);
+ },
+ );
+
+ if (apiChanged) {
+ const api = ((data || {}).data || {}).data || {};
+ const name = (api.cluster_info || {}).manager || false;
+ AppState.setCurrentAPI(JSON.stringify({ name: name, id: api.id }));
+ checkLogger.info(
+ `Set current API in cookie: id [${api.id}], name [${name}]`,
+ );
+ getToasts().add({
+ color: 'warning',
+ title: 'Selected Wazuh API has been updated',
+ text: '',
+ toastLifeTimeMs: 3000,
+ });
+ }
+ //update cluster info
+ const cluster_info = (((data || {}).data || {}).data || {}).cluster_info;
+ if (cluster_info) {
+ AppState.setClusterInfo(cluster_info);
+ checkLogger.info(`Set cluster info in cookie`);
+ }
+ if (data === 3099) {
+ checkLogger.error('Wazuh not ready yet');
+ } else if (data.data.error || data.data.data.apiIsDown) {
+ const errorMessage = data.data.data.apiIsDown
+ ? 'Wazuh API is down'
+ : `Error connecting to the API: ${
+ data.data.error && data.data.error.message
+ ? ` ${data.data.error.message}`
+ : ''
+ }`;
+ checkLogger.error(errorMessage);
+ }
+ } catch (error) {
+ AppState.removeNavigation();
+ checkLogger.info('Removed [navigate] cookie');
+ throw error;
}
- } catch (error) {
- AppState.removeNavigation();
- checkLogger.info('Removed [navigate] cookie');
- throw error;
- }
-};
+ };
diff --git a/public/components/health-check/services/check-index-pattern/check-index-pattern-object.service.ts b/public/components/health-check/services/check-index-pattern/check-index-pattern-object.service.ts
index 607bdf14ba..2e822e4d2f 100644
--- a/public/components/health-check/services/check-index-pattern/check-index-pattern-object.service.ts
+++ b/public/components/health-check/services/check-index-pattern/check-index-pattern-object.service.ts
@@ -15,7 +15,6 @@ import { AppState, SavedObject } from '../../../../react-services';
import { getDataPlugin } from '../../../../kibana-services';
import { HEALTH_CHECK } from '../../../../../common/constants';
import { CheckLogger } from '../../types/check_logger';
-import { satisfyPluginPlatformVersion } from '../../../../../common/semver';
export const checkIndexPatternObjectService = async (appConfig, checkLogger: CheckLogger) => {
const patternId: string = AppState.getCurrentPattern();
@@ -41,11 +40,9 @@ export const checkIndexPatternObjectService = async (appConfig, checkLogger: Ch
const existDefaultIndexPattern = await SavedObject.getExistingIndexPattern(defaultPatternId);
checkLogger.info(`Index pattern id [${defaultPatternId}] exists: ${existDefaultIndexPattern ? 'yes' : 'no'}`);
if (existDefaultIndexPattern) {
- if(satisfyPluginPlatformVersion('<7.11')){
- checkLogger.info(`Refreshing index pattern fields [${defaultPatternId}]...`);
- await SavedObject.refreshIndexPattern(defaultPatternId);
- checkLogger.action(`Refreshed index pattern fields [${defaultPatternId}]`);
- };
+ checkLogger.info(`Refreshing index pattern fields [${defaultPatternId}]...`);
+ await SavedObject.refreshIndexPattern(defaultPatternId);
+ checkLogger.action(`Refreshed index pattern fields [${defaultPatternId}]`);
} else if(shouldCreateIndex) {
checkLogger.info(`Creating index pattern [${defaultPatternId}]...`);
await SavedObject.createWazuhIndexPattern(defaultPatternId);
diff --git a/public/components/health-check/services/check-index-pattern/check-index-pattern.service.ts b/public/components/health-check/services/check-index-pattern/check-index-pattern.service.ts
index 8225e3efc5..23ca42fa29 100644
--- a/public/components/health-check/services/check-index-pattern/check-index-pattern.service.ts
+++ b/public/components/health-check/services/check-index-pattern/check-index-pattern.service.ts
@@ -15,7 +15,6 @@ import { CheckLogger } from '../../types/check_logger';
import { checkFieldsService } from './check-fields.service';
import { checkIndexPatternObjectService } from './check-index-pattern-object.service';
import { checkTemplateService } from './check-template.service';
-import { satisfyPluginPlatformVersion } from '../../../../../common/semver';
export const checkIndexPatternService = (appConfig) => async (checkLogger: CheckLogger) => await checkPattern(appConfig, checkLogger);
@@ -25,9 +24,7 @@ const checkPattern = async (appConfig, checkLogger: CheckLogger) => {
};
await checkIndexPatternObjectService(appConfig, checkLogger);
await checkTemplate(appConfig, checkLogger);
- if(satisfyPluginPlatformVersion('<7.11')){
- await checkFields(appConfig, checkLogger);
- };
+ await checkFields(appConfig, checkLogger);
};
const decoratorHealthCheckRunCheckEnabled = (checkKey, fn) => {
diff --git a/public/components/health-check/services/check-pattern-support.service.ts b/public/components/health-check/services/check-pattern-support.service.ts
index 94e0e592c0..d70dab0e69 100644
--- a/public/components/health-check/services/check-pattern-support.service.ts
+++ b/public/components/health-check/services/check-pattern-support.service.ts
@@ -13,7 +13,6 @@
*/
import { SavedObject } from '../../../react-services';
import { CheckLogger } from '../types/check_logger';
-import { satisfyPluginPlatformVersion } from '../../../../common/semver';
export const checkPatternSupportService = (pattern: string, indexType : string) => async (checkLogger: CheckLogger) => {
checkLogger.info(`Checking index pattern id [${pattern}] exists...`);
@@ -21,12 +20,9 @@ export const checkPatternSupportService = (pattern: string, indexType : string)
checkLogger.info(`Exist index pattern id [${pattern}]: ${result.data ? 'yes' : 'no'}`);
if (!result.data) {
- let fields;
- if(satisfyPluginPlatformVersion('<7.11')){
- checkLogger.info(`Getting indices fields for the index pattern id [${pattern}]...`);
- fields = await SavedObject.getIndicesFields(pattern, indexType);
- checkLogger.info(`Fields for index pattern id [${pattern}] found: ${fields.length}`);
- };
+ checkLogger.info(`Getting indices fields for the index pattern id [${pattern}]...`);
+ const fields = await SavedObject.getIndicesFields(pattern, indexType);
+ checkLogger.info(`Fields for index pattern id [${pattern}] found: ${fields.length}`);
try {
checkLogger.info(`Creating saved object for the index pattern with id [${pattern}].
diff --git a/public/components/health-check/services/check-setup.service.ts b/public/components/health-check/services/check-setup.service.ts
index 73e6576276..48a674d79a 100644
--- a/public/components/health-check/services/check-setup.service.ts
+++ b/public/components/health-check/services/check-setup.service.ts
@@ -14,7 +14,7 @@
import { AppState, GenericRequest, WzRequest } from '../../../react-services';
import { CheckLogger } from '../types/check_logger';
-import { PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_UPGRADE_PLATFORM } from '../../../../common/constants';
+import { PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING, PLUGIN_APP_NAME } from '../../../../common/constants';
import { webDocumentationLink } from '../../../../common/services/web_documentation';
export const checkSetupService = appInfo => async (checkLogger: CheckLogger) => {
@@ -44,7 +44,7 @@ export const checkSetupService = appInfo => async (checkLogger: CheckLogger) =>
api.groups.version !== appSplit[0] ||
api.groups.minor !== appSplit[1]
) {
- checkLogger.error(`Wazuh API and Wazuh App version mismatch. API version: ${apiVersion}. App version: ${setupData.data.data['app-version']}. At least, major and minor should match. Check more info about upgrading Wazuh App here .`);
+ checkLogger.error(`Wazuh API and ${PLUGIN_APP_NAME} version mismatch. API version: ${apiVersion}. App version: ${setupData.data.data['app-version']}. Read more about this error in our troubleshooting guide: ${webDocumentationLink(PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING)}.`);
}
}
}
diff --git a/public/components/kbn-search-bar/kbn-search-bar.tsx b/public/components/kbn-search-bar/kbn-search-bar.tsx
index 10d3c99c5b..6f130da4fd 100644
--- a/public/components/kbn-search-bar/kbn-search-bar.tsx
+++ b/public/components/kbn-search-bar/kbn-search-bar.tsx
@@ -11,10 +11,10 @@
*/
import React from 'react';
-import { I18nProvider } from '@kbn/i18n/react';
+import { I18nProvider } from '@osd/i18n/react';
import { TimeRange, Query, Filter } from '../../../../../src/plugins/data/public';
-import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public';
+import { OpenSearchDashboardsContextProvider } from '../../../../../src/plugins/opensearch_dashboards_react/public';
import { withPluginPlatformContext, withPluginPlatformContextExtendsProps } from '../common/hocs';
import { storage } from './lib';
import { getDataPlugin, getCore } from '../../kibana-services';
@@ -45,7 +45,7 @@ const KbnSearchBar: React.FunctionComponent = (
}
return (
- = (
timeHistory={timeHistory}
/>
-
+
);
};
diff --git a/public/components/management/cluster/node-list.tsx b/public/components/management/cluster/node-list.tsx
index d383bdf948..4a5288db33 100644
--- a/public/components/management/cluster/node-list.tsx
+++ b/public/components/management/cluster/node-list.tsx
@@ -44,7 +44,7 @@ export const NodeList = withErrorBoundary (class NodeList extends Component {
},
{
field: 'ip',
- name: 'IP',
+ name: 'IP address',
sortable: true,
},
{
diff --git a/public/components/management/groups/multiple-agent-selector.tsx b/public/components/management/groups/multiple-agent-selector.tsx
index 5846df0cef..89d6cc13cb 100644
--- a/public/components/management/groups/multiple-agent-selector.tsx
+++ b/public/components/management/groups/multiple-agent-selector.tsx
@@ -396,7 +396,7 @@ export const MultipleAgentSelector = withErrorBoundary(
};
unselectElementsOfSelectByID(containerID) {
- document.getElementById(containerID).options.forEach((option) => {
+ Array.from(document.getElementById(containerID).options).forEach((option) => {
option.selected = false;
});
}
diff --git a/public/components/overview/compliance-table/compliance-table.tsx b/public/components/overview/compliance-table/compliance-table.tsx
index 00d71cdc76..7d3861e5d8 100644
--- a/public/components/overview/compliance-table/compliance-table.tsx
+++ b/public/components/overview/compliance-table/compliance-table.tsx
@@ -11,7 +11,7 @@
*/
import React, { Component } from 'react';
import { EuiPanel, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
-import { SearchBar, FilterManager } from '../../../../../../src/plugins/data/public/';
+import { FilterManager } from '../../../../../../src/plugins/data/public/';
//@ts-ignore
import { ComplianceRequirements } from './components/requirements';
@@ -29,306 +29,334 @@ import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/
import { getErrorOrchestrator } from '../../../react-services/common-services';
import { withAgentSupportModule } from '../../common/hocs';
-export const ComplianceTable = withAgentSupportModule(class ComplianceTable extends Component {
- _isMount = false;
- timefilter: {
- getTime(): any;
- setTime(time: any): void;
- _history: { history: { items: { from: string; to: string }[] } };
- };
+export const ComplianceTable = withAgentSupportModule(
+ class ComplianceTable extends Component {
+ _isMount = false;
+ timefilter: {
+ getTime(): any;
+ setTime(time: any): void;
+ _history: { history: { items: { from: string; to: string }[] } };
+ };
- PluginPlatformServices: { [key: string]: any };
- filterManager: FilterManager;
- indexPattern: any;
- state: {
- selectedRequirement: string;
- flyoutOn: boolean;
- filterParams: IFilterParams;
- complianceObject: object;
- descriptions: object;
- loadingAlerts: boolean;
- selectedRequirements: object;
- };
+ PluginPlatformServices: { [key: string]: any };
+ filterManager: FilterManager;
+ indexPattern: any;
+ state: {
+ selectedRequirement: string;
+ flyoutOn: boolean;
+ filterParams: IFilterParams;
+ complianceObject: object;
+ descriptions: object;
+ loadingAlerts: boolean;
+ selectedRequirements: object;
+ };
- props: any;
+ props: any;
- constructor(props) {
- super(props);
- this.PluginPlatformServices = getDataPlugin().query;
- this.filterManager = this.PluginPlatformServices.filterManager;
- this.timefilter = this.PluginPlatformServices.timefilter.timefilter;
- this.state = {
- selectedRequirement: '',
- flyoutOn: true,
- complianceObject: {},
- descriptions: {},
- loadingAlerts: true,
- selectedRequirements: {},
- filterParams: {
- filters: this.filterManager.getFilters() || [],
- query: { language: 'kuery', query: '' },
- time: this.timefilter.getTime(),
- },
- };
+ constructor(props) {
+ super(props);
+ this.PluginPlatformServices = getDataPlugin().query;
+ this.filterManager = this.PluginPlatformServices.filterManager;
+ this.timefilter = this.PluginPlatformServices.timefilter.timefilter;
+ this.state = {
+ selectedRequirement: '',
+ flyoutOn: true,
+ complianceObject: {},
+ descriptions: {},
+ loadingAlerts: true,
+ selectedRequirements: {},
+ filterParams: {
+ filters: this.filterManager.getFilters() || [],
+ query: { language: 'kuery', query: '' },
+ time: this.timefilter.getTime(),
+ },
+ };
- this.onChangeSelectedRequirements.bind(this);
- this.onQuerySubmit.bind(this);
- this.onFiltersUpdated.bind(this);
- }
+ this.onChangeSelectedRequirements.bind(this);
+ this.onQuerySubmit.bind(this);
+ this.onFiltersUpdated.bind(this);
+ }
- async componentDidMount() {
- this._isMount = true;
- this.filtersSubscriber = this.filterManager.getUpdates$().subscribe(() => {
- this.onFiltersUpdated(this.filterManager.getFilters());
- });
- this.indexPattern = await getIndexPattern();
- this.buildComplianceObject();
- }
+ async componentDidMount() {
+ this._isMount = true;
+ this.filtersSubscriber = this.filterManager
+ .getUpdates$()
+ .subscribe(() => {
+ this.onFiltersUpdated(this.filterManager.getFilters());
+ });
+ this.indexPattern = await getIndexPattern();
+ this.buildComplianceObject();
+ }
- componentWillUnmount() {
- this.filtersSubscriber.unsubscribe();
- }
+ componentWillUnmount() {
+ this.filtersSubscriber.unsubscribe();
+ }
- buildComplianceObject() {
- try {
- let complianceRequirements = {};
- let descriptions = {};
- let selectedRequirements = {}; // all enabled by default
- if (this.props.section === 'pci') {
- descriptions = pciRequirementsFile;
- Object.keys(pciRequirementsFile).forEach((item) => {
- const currentRequirement = item.split('.')[0];
- if (complianceRequirements[currentRequirement]) {
- complianceRequirements[currentRequirement].push(item);
- } else {
- selectedRequirements[currentRequirement] = true;
- complianceRequirements[currentRequirement] = [];
- complianceRequirements[currentRequirement].push(item);
- }
- }); //forEach
- }
- if (this.props.section === 'gdpr') {
- descriptions = gdprRequirementsFile;
- Object.keys(gdprRequirementsFile).forEach((item) => {
- const currentRequirement = item.split('_')[0];
- if (complianceRequirements[currentRequirement]) {
- complianceRequirements[currentRequirement].push(item);
- } else {
- selectedRequirements[currentRequirement] = true;
- complianceRequirements[currentRequirement] = [];
- complianceRequirements[currentRequirement].push(item);
- }
- }); //forEach
- }
+ buildComplianceObject() {
+ try {
+ let complianceRequirements = {};
+ let descriptions = {};
+ let selectedRequirements = {}; // all enabled by default
+ if (this.props.section === 'pci') {
+ descriptions = pciRequirementsFile;
+ Object.keys(pciRequirementsFile).forEach(item => {
+ const currentRequirement = item.split('.')[0];
+ if (complianceRequirements[currentRequirement]) {
+ complianceRequirements[currentRequirement].push(item);
+ } else {
+ selectedRequirements[currentRequirement] = true;
+ complianceRequirements[currentRequirement] = [];
+ complianceRequirements[currentRequirement].push(item);
+ }
+ }); //forEach
+ }
+ if (this.props.section === 'gdpr') {
+ descriptions = gdprRequirementsFile;
+ Object.keys(gdprRequirementsFile).forEach(item => {
+ const currentRequirement = item.split('_')[0];
+ if (complianceRequirements[currentRequirement]) {
+ complianceRequirements[currentRequirement].push(item);
+ } else {
+ selectedRequirements[currentRequirement] = true;
+ complianceRequirements[currentRequirement] = [];
+ complianceRequirements[currentRequirement].push(item);
+ }
+ }); //forEach
+ }
- if (this.props.section === 'hipaa') {
- descriptions = hipaaRequirementsFile;
- Object.keys(hipaaRequirementsFile).forEach((item) => {
- const currentRequirement =
- item.split('.')[0] + '.' + item.split('.')[1] + '.' + item.split('.')[2];
- if (complianceRequirements[currentRequirement]) {
- complianceRequirements[currentRequirement].push(item);
- } else {
- selectedRequirements[currentRequirement] = true;
- complianceRequirements[currentRequirement] = [];
- complianceRequirements[currentRequirement].push(item);
- }
- }); //forEach
- }
+ if (this.props.section === 'hipaa') {
+ descriptions = hipaaRequirementsFile;
+ Object.keys(hipaaRequirementsFile).forEach(item => {
+ const currentRequirement =
+ item.split('.')[0] +
+ '.' +
+ item.split('.')[1] +
+ '.' +
+ item.split('.')[2];
+ if (complianceRequirements[currentRequirement]) {
+ complianceRequirements[currentRequirement].push(item);
+ } else {
+ selectedRequirements[currentRequirement] = true;
+ complianceRequirements[currentRequirement] = [];
+ complianceRequirements[currentRequirement].push(item);
+ }
+ }); //forEach
+ }
- if (this.props.section === 'nist') {
- descriptions = nistRequirementsFile;
- Object.keys(nistRequirementsFile).forEach((item) => {
- const currentRequirement = item.split('.')[0];
- if (complianceRequirements[currentRequirement]) {
- complianceRequirements[currentRequirement].push(item);
- } else {
- selectedRequirements[currentRequirement] = true;
- complianceRequirements[currentRequirement] = [];
- complianceRequirements[currentRequirement].push(item);
- }
- }); //forEach
- }
- if (this.props.section === 'tsc') {
- descriptions = tscRequirementsFile;
- Object.keys(tscRequirementsFile).forEach((item) => {
- const currentRequirement = item.split('.')[0];
- if (complianceRequirements[currentRequirement]) {
- complianceRequirements[currentRequirement].push(item);
- } else {
- selectedRequirements[currentRequirement] = true;
- complianceRequirements[currentRequirement] = [];
- complianceRequirements[currentRequirement].push(item);
- }
- }); //forEach
- }
+ if (this.props.section === 'nist') {
+ descriptions = nistRequirementsFile;
+ Object.keys(nistRequirementsFile).forEach(item => {
+ const currentRequirement = item.split('.')[0];
+ if (complianceRequirements[currentRequirement]) {
+ complianceRequirements[currentRequirement].push(item);
+ } else {
+ selectedRequirements[currentRequirement] = true;
+ complianceRequirements[currentRequirement] = [];
+ complianceRequirements[currentRequirement].push(item);
+ }
+ }); //forEach
+ }
+ if (this.props.section === 'tsc') {
+ descriptions = tscRequirementsFile;
+ Object.keys(tscRequirementsFile).forEach(item => {
+ const currentRequirement = item.split('.')[0];
+ if (complianceRequirements[currentRequirement]) {
+ complianceRequirements[currentRequirement].push(item);
+ } else {
+ selectedRequirements[currentRequirement] = true;
+ complianceRequirements[currentRequirement] = [];
+ complianceRequirements[currentRequirement].push(item);
+ }
+ }); //forEach
+ }
- this._isMount &&
- this.setState(
- { complianceObject: complianceRequirements, selectedRequirements, descriptions },
- () => this.getRequirementsCount()
- );
- } catch (error) {
- const options = {
- context: `${ComplianceTable.name}.buildComplianceObject`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.BUSINESS,
- store: true,
- display: true,
- error: {
- error: error,
- message: error.message || error,
- title: `Compliance (${this.props.section}) data could not be fetched`,
- },
- };
- getErrorOrchestrator().handleError(options);
+ this._isMount &&
+ this.setState(
+ {
+ complianceObject: complianceRequirements,
+ selectedRequirements,
+ descriptions,
+ },
+ () => this.getRequirementsCount(),
+ );
+ } catch (error) {
+ const options = {
+ context: `${ComplianceTable.name}.buildComplianceObject`,
+ level: UI_LOGGER_LEVELS.ERROR,
+ severity: UI_ERROR_SEVERITIES.BUSINESS,
+ store: true,
+ display: true,
+ error: {
+ error: error,
+ message: error.message || error,
+ title: `Compliance (${this.props.section}) data could not be fetched`,
+ },
+ };
+ getErrorOrchestrator().handleError(options);
+ }
}
- }
- onChangeSelectedRequirements = (selectedRequirements) => {
- this.setState({ selectedRequirements });
- };
+ onChangeSelectedRequirements = selectedRequirements => {
+ this.setState({ selectedRequirements });
+ };
- onQuerySubmit = (payload: { dateRange: TimeRange; query: Query | undefined }) => {
- const { dateRange, query } = payload;
- const { filters } = this.state.filterParams;
- const filterParams: IFilterParams = { time: dateRange, filters, query };
- this.setState({ filterParams, loadingAlerts: true });
- };
+ onQuerySubmit = (payload: {
+ dateRange: TimeRange;
+ query: Query | undefined;
+ }) => {
+ const { dateRange, query } = payload;
+ const { filters } = this.state.filterParams;
+ const filterParams: IFilterParams = { time: dateRange, filters, query };
+ this.setState({ filterParams, loadingAlerts: true });
+ };
- onFiltersUpdated = (filters: []) => {
- const { time, query } = this.state.filterParams;
- const filterParams = { time, query, filters };
- this.setState({ filterParams, loadingAlerts: true });
- };
+ onFiltersUpdated = (filters: []) => {
+ const { time, query } = this.state.filterParams;
+ const filterParams = { time, query, filters };
+ this.setState({ filterParams, loadingAlerts: true });
+ };
- async componentDidUpdate(prevProps) {
- const { filterParams, loadingAlerts } = this.state;
- if (JSON.stringify(prevProps.filterParams) !== JSON.stringify(filterParams) && loadingAlerts) {
- this.getRequirementsCount();
+ async componentDidUpdate(prevProps) {
+ const { filterParams, loadingAlerts } = this.state;
+ if (
+ JSON.stringify(prevProps.filterParams) !==
+ JSON.stringify(filterParams) &&
+ loadingAlerts
+ ) {
+ this.getRequirementsCount();
+ }
}
- }
- async getRequirementsCount() {
- try {
- const { filterParams } = this.state;
- if (!this.indexPattern) {
- return;
- }
- let fieldAgg = '';
- if (this.props.section === 'pci') fieldAgg = 'rule.pci_dss';
- if (this.props.section === 'gdpr') fieldAgg = 'rule.gdpr';
- if (this.props.section === 'hipaa') fieldAgg = 'rule.hipaa';
- if (this.props.section === 'nist') fieldAgg = 'rule.nist_800_53';
- if (this.props.section === 'tsc') fieldAgg = 'rule.tsc';
- const aggs = {
- tactics: {
- terms: {
- field: fieldAgg,
- size: 100,
+ async getRequirementsCount() {
+ try {
+ const { filterParams } = this.state;
+ if (!this.indexPattern) {
+ return;
+ }
+ let fieldAgg = '';
+ if (this.props.section === 'pci') fieldAgg = 'rule.pci_dss';
+ if (this.props.section === 'gdpr') fieldAgg = 'rule.gdpr';
+ if (this.props.section === 'hipaa') fieldAgg = 'rule.hipaa';
+ if (this.props.section === 'nist') fieldAgg = 'rule.nist_800_53';
+ if (this.props.section === 'tsc') fieldAgg = 'rule.tsc';
+ const aggs = {
+ tactics: {
+ terms: {
+ field: fieldAgg,
+ size: 100,
+ },
},
- },
- };
+ };
- // TODO: use `status` and `statusText` to show errors
- // @ts-ignore
- const { data, status, statusText } = await getElasticAlerts(
- this.indexPattern,
- filterParams,
- aggs
- );
- const { buckets } = data.aggregations.tactics;
- /*if(firstTime){
+ // TODO: use `status` and `statusText` to show errors
+ // @ts-ignore
+ const { data, status, statusText } = await getElasticAlerts(
+ this.indexPattern,
+ filterParams,
+ aggs,
+ );
+
+ const buckets = data?.aggregations?.tactics?.buckets || [];
+ /*if(firstTime){
this.initTactics(buckets); // top tactics are checked on component mount
}*/
- this._isMount &&
- this.setState({ requirementsCount: buckets, loadingAlerts: false, firstTime: false });
- } catch (error) {
- const options = {
- context: `${ComplianceTable.name}.buildComplianceObject`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.BUSINESS,
- store: true,
- display: true,
- error: {
- error: error,
- message: error.message || error,
- title: `Mitre alerts could not be fetched:`,
- },
- };
- getErrorOrchestrator().handleError(options);
- this.setState({ loadingAlerts: false });
+ this._isMount &&
+ this.setState({
+ requirementsCount: buckets,
+ loadingAlerts: false,
+ firstTime: false,
+ });
+ } catch (error) {
+ const options = {
+ context: `${ComplianceTable.name}.buildComplianceObject`,
+ level: UI_LOGGER_LEVELS.ERROR,
+ severity: UI_ERROR_SEVERITIES.BUSINESS,
+ store: true,
+ display: true,
+ error: {
+ error: error,
+ message: error.message || error,
+ title: `Mitre alerts could not be fetched:`,
+ },
+ };
+ getErrorOrchestrator().handleError(options);
+ this.setState({ loadingAlerts: false });
+ }
}
- }
- onChangeFlyout = (flyoutOn) => {
- this.setState({ flyoutOn });
- };
+ onChangeFlyout = flyoutOn => {
+ this.setState({ flyoutOn });
+ };
- closeFlyout() {
- this.setState({ flyoutOn: false });
- }
+ closeFlyout() {
+ this.setState({ flyoutOn: false });
+ }
- showFlyout(requirement) {
- this.setState({
- selectedRequirement: requirement,
- flyoutOn: true,
- });
- }
+ showFlyout(requirement) {
+ this.setState({
+ selectedRequirement: requirement,
+ flyoutOn: true,
+ });
+ }
- render() {
- const { complianceObject, loadingAlerts } = this.state;
- return (
-
-
-
-
-
-
-
-
+ render() {
+ const { complianceObject, loadingAlerts } = this.state;
+ return (
+
+
+
+
+
+
+
+
-
-
-
- {!!Object.keys(complianceObject).length &&
- this.state.filterParams.time.from !== 'init' && (
-
-
-
-
-
- this.props.onSelectedTabChanged(id)}
- {...this.state}
- />
-
-
- )}
-
-
-
-
- );
- }
-})
+
+
+
+ {!!Object.keys(complianceObject).length &&
+ this.state.filterParams.time.from !== 'init' && (
+
+
+
+
+
+
+ this.props.onSelectedTabChanged(id)
+ }
+ {...this.state}
+ />
+
+
+ )}
+
+
+
+
+ );
+ }
+ },
+);
diff --git a/public/components/overview/compliance-table/components/subrequirements/subrequirements.tsx b/public/components/overview/compliance-table/components/subrequirements/subrequirements.tsx
index 43090a7510..b75770a669 100644
--- a/public/components/overview/compliance-table/components/subrequirements/subrequirements.tsx
+++ b/public/components/overview/compliance-table/components/subrequirements/subrequirements.tsx
@@ -24,15 +24,13 @@ import {
EuiPopover,
EuiText,
EuiIcon,
- EuiOverlayMask,
- EuiOutsideClickDetector,
EuiLoadingSpinner,
} from '@elastic/eui';
import { AppNavigate } from '../../../../../react-services/app-navigate';
import { AppState } from '../../../../../react-services/app-state';
import { RequirementFlyout } from '../requirement-flyout/requirement-flyout';
-import { WAZUH_ALERTS_PATTERN } from '../../../../../../common/constants';
import { getDataPlugin } from '../../../../../kibana-services';
+import { getSettingDefaultValue } from '../../../../../../common/services/settings';
export class ComplianceSubrequirements extends Component {
_isMount = false;
@@ -71,7 +69,7 @@ export class ComplianceSubrequirements extends Component {
params: { query: filter.value },
type: 'phrase',
negate: filter.negate || false,
- index: AppState.getCurrentPattern() || WAZUH_ALERTS_PATTERN,
+ index: AppState.getCurrentPattern() || getSettingDefaultValue('pattern'),
},
query: { match_phrase: matchPhrase },
$state: { store: 'appState' },
diff --git a/public/components/overview/metrics/metrics.tsx b/public/components/overview/metrics/metrics.tsx
index 2a290c5e87..ce2f26aa59 100644
--- a/public/components/overview/metrics/metrics.tsx
+++ b/public/components/overview/metrics/metrics.tsx
@@ -273,7 +273,7 @@ export const Metrics = withAllowedAgents(
},
],
office: [
- { name: "Max Rule Level", type: "custom", filter: { phrase: "office365", field: "rule.groups" }, agg: { "customAggResult": { "terms": { "field": "timestamp", "order": { "_term": "desc" }, "size": 1 }, "aggs": { "aggResult": { "terms": { "field": "rule.level" } } } } } },
+ { name: "Max Rule Level", type: "custom", filter: { phrase: "office365", field: "rule.groups" }, agg: { "customAggResult": { "terms": { "field": "rule.level", "order": { "_term": "desc" }, "size": 1 }, "aggs": { "aggResult": { "terms": { "field": "rule.level" } } } } } },
{ name: "Suspicious Downloads", type: "phrase", value: "91724", field: "rule.id", color: "danger" },
{ name: "Full Access Permissions", type: "phrase", value: "91725", field: "rule.id" },
{ name: "Phishing and Malware", type: "phrases", values: ["91556", "91575", "91700"], field: "rule.id", color: "danger" },
@@ -317,9 +317,7 @@ export const Metrics = withAllowedAgents(
async buildMetric() {
if (!this.metricsList[this.props.section] || !this._isMount) return <>>;
- const newFilters = this.filterManager.getFilters();
const searchBarQuery = this.scope.state.query;
- const newTime = this.timefilter.getTime();
const filterParams = {};
filterParams['time'] = this.timefilter.getTime();
filterParams['query'] = searchBarQuery;
diff --git a/public/components/overview/mitre/components/techniques/techniques.tsx b/public/components/overview/mitre/components/techniques/techniques.tsx
index 8234de0b73..50c4f10b28 100644
--- a/public/components/overview/mitre/components/techniques/techniques.tsx
+++ b/public/components/overview/mitre/components/techniques/techniques.tsx
@@ -9,7 +9,7 @@
*
* Find more information about this on the LICENSE file.
*/
-import React, { Component, Fragment } from 'react';
+import React, { Component } from 'react';
import {
EuiFacetButton,
EuiFlexGroup,
@@ -31,13 +31,13 @@ import { getElasticAlerts, IFilterParams } from '../../lib';
import { ITactic } from '../../';
import { withWindowSize } from '../../../../../components/common/hocs/withWindowSize';
import { WzRequest } from '../../../../../react-services/wz-request';
-import { WAZUH_ALERTS_PATTERN } from '../../../../../../common/constants';
import { AppState } from '../../../../../react-services/app-state';
import { WzFieldSearchDelay } from '../../../../common/search';
import { getDataPlugin, getToasts } from '../../../../../kibana-services';
import { UI_LOGGER_LEVELS } from '../../../../../../common/constants';
import { UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchestrator/types';
import { getErrorOrchestrator } from '../../../../../react-services/common-services';
+import { getSettingDefaultValue } from '../../../../../../common/services/settings';
const MITRE_ATTACK = 'mitre-attack';
@@ -430,7 +430,7 @@ export const Techniques = withWindowSize(
params: { query: filter.value },
type: 'phrase',
negate: filter.negate || false,
- index: AppState.getCurrentPattern() || WAZUH_ALERTS_PATTERN,
+ index: AppState.getCurrentPattern() || getSettingDefaultValue('pattern'),
},
query: { match_phrase: matchPhrase },
$state: { store: 'appState' },
diff --git a/public/components/overview/mitre/lib/elastic-helpers.ts b/public/components/overview/mitre/lib/elastic-helpers.ts
index 86b85a6b24..14b7d08451 100644
--- a/public/components/overview/mitre/lib/elastic-helpers.ts
+++ b/public/components/overview/mitre/lib/elastic-helpers.ts
@@ -12,7 +12,7 @@
import { AppState } from '../../../../react-services/app-state';
import { GenericRequest } from '../../../../react-services/generic-request';
-import { Query, TimeRange, buildRangeFilter, buildEsQuery, getEsQueryConfig, Filter } from '../../../../../../../src/plugins/data/common';
+import { Query, TimeRange, buildRangeFilter, buildOpenSearchQuery, getOpenSearchQueryConfig, Filter } from '../../../../../../../src/plugins/data/common';
import { SearchParams, SearchResponse } from 'elasticsearch';
import { WazuhConfig } from '../../../../react-services/wazuh-config';
import { getDataPlugin, getUiSettings } from '../../../../kibana-services';
@@ -85,14 +85,14 @@ export async function getElasticAlerts(indexPattern, filterParams:IFilterParams,
function buildQuery(indexPattern, filterParams:IFilterParams) {
const { filters, query, time } = filterParams;
const timeFilter = buildRangeFilter(
- {name: 'timestamp', type: 'date'},
+ {name: 'timestamp', type: 'date'},
time,
indexPattern
);
- return buildEsQuery(
- undefined,
+ return buildOpenSearchQuery(
+ indexPattern,
query,
[...filters, timeFilter],
- getEsQueryConfig(getUiSettings())
+ getOpenSearchQueryConfig(getUiSettings())
);
}
diff --git a/public/components/overview/mitre_attack_intelligence/__snapshots__/intelligence.test.tsx.snap b/public/components/overview/mitre_attack_intelligence/__snapshots__/intelligence.test.tsx.snap
index bd292e0190..ce40ecc0ea 100644
--- a/public/components/overview/mitre_attack_intelligence/__snapshots__/intelligence.test.tsx.snap
+++ b/public/components/overview/mitre_attack_intelligence/__snapshots__/intelligence.test.tsx.snap
@@ -6,7 +6,7 @@ exports[`Module Mitre Att&ck intelligence container should render permissions pr
>
+
+ You have no permissions
+
-
- You have no permissions
-
@@ -63,7 +63,7 @@ exports[`Module Mitre Att&ck intelligence container should render the component
class="euiFlexItem"
>
-
ID
-
+
Name
-
- Click to sort in descending order
-
@@ -346,11 +346,6 @@ exports[`Module Mitre Att&ck intelligence container should render the component
>
Description
-
- Click to sort in ascending order
-
diff --git a/public/components/overview/office-panel/config/drilldown-operations-config.tsx b/public/components/overview/office-panel/config/drilldown-operations-config.tsx
index a07b8a53e3..cb31f249c5 100644
--- a/public/components/overview/office-panel/config/drilldown-operations-config.tsx
+++ b/public/components/overview/office-panel/config/drilldown-operations-config.tsx
@@ -63,7 +63,7 @@ export const drilldownOperationsConfig = {
{ field: 'timestamp' },
{ field: 'rule.description', label: 'Description' },
{ field: 'data.office365.UserId', label: 'User ID' },
- { field: 'data.office365.ClientIP', label: 'Client IP' },
+ { field: 'data.office365.ClientIP', label: 'Client IP address' },
{ field: 'rule.level', label: 'Level' },
{ field: 'rule.id', label: 'Rule ID' },
]}
diff --git a/public/components/overview/office-panel/config/drilldown-rules-config.tsx b/public/components/overview/office-panel/config/drilldown-rules-config.tsx
index 294c42223d..2b60d8781f 100644
--- a/public/components/overview/office-panel/config/drilldown-rules-config.tsx
+++ b/public/components/overview/office-panel/config/drilldown-rules-config.tsx
@@ -69,7 +69,7 @@ export const drilldownRulesConfig = {
{ field: 'timestamp' },
{ field: 'rule.description', label: 'Description' },
{ field: 'data.office365.UserId', label: 'User ID' },
- { field: 'data.office365.ClientIP', label: 'Client IP' },
+ { field: 'data.office365.ClientIP', label: 'Client IP address' },
{ field: 'data.office365.Operation', label: 'Operation' },
{ field: 'rule.level', label: 'Level' },
{ field: 'rule.id', label: 'Rule ID' },
diff --git a/public/components/overview/office-panel/config/drilldown-user-config.tsx b/public/components/overview/office-panel/config/drilldown-user-config.tsx
index 696b67fbde..ff8ff10525 100644
--- a/public/components/overview/office-panel/config/drilldown-user-config.tsx
+++ b/public/components/overview/office-panel/config/drilldown-user-config.tsx
@@ -73,7 +73,7 @@ export const drilldownUserConfig = {
{ field: 'icon' },
{ field: 'timestamp' },
{ field: 'rule.description', label: 'Description' },
- { field: 'data.office365.ClientIP', label: 'Client IP' },
+ { field: 'data.office365.ClientIP', label: 'Client IP address' },
{ field: 'data.office365.Operation', label: 'Operation' },
{ field: 'rule.level', label: 'Level' },
{ field: 'rule.id', label: 'Rule ID' },
diff --git a/public/components/overview/office-panel/config/main-view-config.tsx b/public/components/overview/office-panel/config/main-view-config.tsx
index 2c0f2fd453..0122fa2f41 100644
--- a/public/components/overview/office-panel/config/main-view-config.tsx
+++ b/public/components/overview/office-panel/config/main-view-config.tsx
@@ -39,9 +39,9 @@ export const MainViewConfig = {
component: (props) => (
props.onRowClick(field, value)}
/>
diff --git a/public/components/overview/office-panel/config/module-config.tsx b/public/components/overview/office-panel/config/module-config.tsx
index 9b665ee875..78a08d6df1 100644
--- a/public/components/overview/office-panel/config/module-config.tsx
+++ b/public/components/overview/office-panel/config/module-config.tsx
@@ -38,7 +38,7 @@ export const ModuleConfig = {
'data.office365.ClientIP': {
length: () => drilldownIPConfig.rows.reduce((total, row) => total + row.columns.length, 0),
component: (props) => (
-
+
),
},
'data.office365.Operation': {
diff --git a/public/components/security/policies/create-policy.tsx b/public/components/security/policies/create-policy.tsx
index 9ffc15c692..c631283997 100644
--- a/public/components/security/policies/create-policy.tsx
+++ b/public/components/security/policies/create-policy.tsx
@@ -162,18 +162,14 @@ export const CreatePolicyFlyout = ({ closeFlyout }) => {
const createPolicy = async () => {
try {
- const result = await WzRequest.apiReq(
- 'POST',
- '/security/policies',
- {
- name: policyName,
- policy: {
- actions: addedActions.map((x) => x.action),
- resources: addedResources.map((x) => x.resource),
- effect: effectValue,
- },
- }
- );
+ const result = await WzRequest.apiReq('POST', '/security/policies', {
+ name: policyName,
+ policy: {
+ actions: addedActions.map((x) => x.action),
+ resources: addedResources.map((x) => x.resource),
+ effect: effectValue,
+ },
+ });
const resultData = (result.data || {}).data;
if (resultData.failed_items && resultData.failed_items.length) {
return;
@@ -316,6 +312,7 @@ export const CreatePolicyFlyout = ({ closeFlyout }) => {
onChangePolicyName(e)}
@@ -326,6 +323,7 @@ export const CreatePolicyFlyout = ({ closeFlyout }) => {
@@ -342,6 +340,7 @@ export const CreatePolicyFlyout = ({ closeFlyout }) => {
addAction()}
iconType="plusInCircle"
disabled={!actionValue}
@@ -367,6 +366,7 @@ export const CreatePolicyFlyout = ({ closeFlyout }) => {
{
helpText="Introduce the resource identifier. Type * for all."
>
onChangeResourceIdentifierValue(e)}
@@ -394,6 +395,7 @@ export const CreatePolicyFlyout = ({ closeFlyout }) => {
addResource()}
iconType="plusInCircle"
disabled={!resourceIdentifierValue}
@@ -414,7 +416,7 @@ export const CreatePolicyFlyout = ({ closeFlyout }) => {
>
)}
-
+
{
{
diff --git a/public/components/settings/configuration/components/bottom-bar.tsx b/public/components/settings/configuration/components/bottom-bar.tsx
index 6ea078f057..bf25996872 100644
--- a/public/components/settings/configuration/components/bottom-bar.tsx
+++ b/public/components/settings/configuration/components/bottom-bar.tsx
@@ -11,11 +11,8 @@
* Find more information about this on the LICENSE file.
*/
-import React, { } from 'react';
-import ConfigurationHandler from '../utils/configuration-handler';
-//@ts-ignore
-import { getToasts } from '../../../../kibana-services';
-import { ISetting } from '../configuration'
+import React from 'react';
+
import {
EuiBottomBar,
EuiFlexGroup,
@@ -24,50 +21,39 @@ import {
EuiButtonEmpty,
EuiButton
} from '@elastic/eui';
-import { WazuhConfig } from '../../../../react-services/wazuh-config';
-import { UI_LOGGER_LEVELS, PLUGIN_PLATFORM_NAME } from '../../../../../common/constants';
-import {
- UI_ERROR_SEVERITIES,
- UIErrorLog,
- UIErrorSeverity,
- UILogLevel,
-} from '../../../../react-services/error-orchestrator/types';
-import { getErrorOrchestrator } from '../../../../react-services/common-services';
interface IBottomBarProps {
- updatedConfig: { [setting: string]: string | number | boolean | object }
- setUpdateConfig(setting: {}): void
- setLoading(loading: boolean): void
- config: ISetting[]
+ unsavedCount: number
+ errorsCount: number
+ onCancel: () => void
+ onSave: () => void
}
-export const BottomBar: React.FunctionComponent = ({ updatedConfig, setUpdateConfig, setLoading, config }) => {
- return (!!Object.keys(updatedConfig).length
- ?
+export const BottomBar: React.FunctionComponent = ({ unsavedCount, errorsCount, onCancel, onSave }) => (
+
-
-
-
+
+
+
- : null
- );
-}
+);
-const SettingLabel = ({ updatedConfig }) => (
+const SettingLabel = ({ count, errors }) => (
- {`${Object.keys(updatedConfig).length} unsaved settings`}
+ {`${count} unsaved settings`}
+ {errors ? (
+
+ {`${errors} setting with ${errors === 1 ? 'error' : 'errors'}`}
+
+ ) : null}
);
-const CancelButton = ({ setUpdateConfig }) => (
+const CancelButton = ({ onClick }) => (
(
iconType='cross'
color="ghost"
className="mgtAdvancedSettingsForm__button"
- onClick={() => setUpdateConfig({})}>
+ onClick={onClick}>
Cancel changes
-)
+);
-const SaveButton = ({ updatedConfig, setUpdateConfig, setLoading, config }) => (
+const SaveButton = ({ onClick, isDisabled }) => (
saveSettings(updatedConfig, setUpdateConfig, setLoading, config)} >
+ onClick={onClick} >
Save changes
-)
-
-const saveSettings = async (updatedConfig: {}, setUpdateConfig: Function, setLoading: Function, config: ISetting[]) => {
- setLoading(true);
- try {
- await Promise.all(Object.keys(updatedConfig).map(async setting => await saveSetting(setting, updatedConfig, config)));
- successToast();
- setUpdateConfig({});
- } catch (error) {
- const options: UIErrorLog = {
- context: `${BottomBar.name}.saveSettings`,
- level: UI_LOGGER_LEVELS.ERROR as UILogLevel,
- severity: UI_ERROR_SEVERITIES.BUSINESS as UIErrorSeverity,
- store: true,
- error: {
- error: error,
- message: error.message || error,
- title: `Error saving the configuration: ${error.message || error}`,
- },
- };
-
- getErrorOrchestrator().handleError(options);
- } finally {
- setLoading(false);
- }
-}
-
-const saveSetting = async (setting, updatedConfig, config: ISetting[]) => {
- try {
- (config.find(item => item.setting === setting) || { value: '' }).value = updatedConfig[setting];
- const result = await ConfigurationHandler.editKey(setting, updatedConfig[setting]);
-
- // Update the app configuration frontend-cached setting in memory with the new value
- const wzConfig = new WazuhConfig();
- wzConfig.setConfig({ ...wzConfig.getConfig(), ...{ [setting]: formatValueCachedConfiguration(updatedConfig[setting]) } });
-
- // Show restart and/or reload message in toast
- const response = result.data.data;
- response.needRestart && restartToast();
- response.needReload && reloadToast();
- response.needHealtCheck && executeHealtCheck();
- } catch (error) {
- return Promise.reject(error);
- }
-}
-
-const reloadToast = () => {
- getToasts().add({
- color: 'success',
- title: 'This settings require you to reload the page to take effect.',
- text:
-
- window.location.reload()} size="s">Reload page
-
-
- })
-}
-
-const executeHealtCheck = () => {
- const toast = getToasts().add({
- color: 'warning',
- title: 'You must execute the health check for the changes to take effect',
- toastLifeTimeMs: 5000,
- text:
-
-
- {
- getToasts().remove(toast);
- window.location.href = '#/health-check';
- }} size="s">Execute health check
-
-
- });
-}
-
-const restartToast = () => {
- getToasts().add({
- color: 'warning',
- title: `You must restart ${PLUGIN_PLATFORM_NAME} for the changes to take effect`,
- });
-}
-
-const successToast = () => {
- getToasts().add({
- color: 'success',
- title: 'The configuration has been successfully updated',
- });
-}
-
-const formatValueCachedConfiguration = (value) => typeof value === 'string'
- ? isNaN(Number(value)) ? value : Number(value)
- : value;
+);
diff --git a/public/components/settings/configuration/components/categories/categories.tsx b/public/components/settings/configuration/components/categories/categories.tsx
deleted file mode 100644
index b32d8d94ea..0000000000
--- a/public/components/settings/configuration/components/categories/categories.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Wazuh app - React component building the configuration component.
- *
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-import React, { } from 'react';
-import { Category } from './components';
-import { ISetting } from '../../configuration';
-import { EuiFlexGroup } from '@elastic/eui';
-
-interface ICategoriesProps {
- config: ISetting[],
- updatedConfig: {[field:string]: string | number | boolean | []}
- setUpdatedConfig({}): void
-}
-
-export const Categories:React.FunctionComponent = ({ config, updatedConfig, setUpdatedConfig }) => {
- const categories: {[category:string]: ISetting[]} = config.reduce((acc, conf) => {
- if (!conf.category) return acc;
- return {
- ...acc,
- [conf.category]: [
- ...(acc[conf.category] || []),
- conf,
- ]
- }
- }, {})
- return (
-
- {Object.keys(categories).map((category, idx) => (
- ))}
-
- );
-}
diff --git a/public/components/settings/configuration/components/categories/components/category/category.tsx b/public/components/settings/configuration/components/categories/components/category/category.tsx
index cee948b173..ea85b8de7d 100644
--- a/public/components/settings/configuration/components/categories/components/category/category.tsx
+++ b/public/components/settings/configuration/components/categories/components/category/category.tsx
@@ -12,8 +12,6 @@
*/
import React, { } from 'react';
-import { FieldForm } from './components';
-import { ISetting } from '../../../../configuration';
import {
EuiFlexItem,
EuiPanel,
@@ -22,56 +20,194 @@ import {
EuiForm,
EuiDescribedFormGroup,
EuiTitle,
- EuiFormRow
+ EuiSpacer,
+ EuiToolTip,
+ EuiButtonIcon,
} from '@elastic/eui';
import { EuiIconTip } from '@elastic/eui';
+import { EpluginSettingType, TPluginSettingWithKey, UI_LOGGER_LEVELS } from '../../../../../../../../common/constants';
+import { webDocumentationLink } from '../../../../../../../../common/services/web_documentation';
+import classNames from 'classnames';
+import { InputForm } from '../../../../../../common/form';
+import { useDispatch } from 'react-redux';
+import { getHttp } from '../../../../../../../kibana-services';
+import { getAssetURL } from '../../../../../../../utils/assets';
+import { UI_ERROR_SEVERITIES } from '../../../../../../../react-services/error-orchestrator/types';
+import { WzRequest } from '../../../../../../../react-services';
+import { updateAppConfig } from '../../../../../../../redux/actions/appConfigActions';
+import { getErrorOrchestrator } from '../../../../../../../react-services/common-services';
+import { WzButtonModalConfirm } from '../../../../../../common/buttons';
+import { toastRequiresReloadingBrowserTab, toastRequiresRestartingPluginPlatform, toastRequiresRunningHealthcheck, toastSuccessUpdateConfiguration } from '../show-toasts';
interface ICategoryProps {
- name: string
- items: ISetting[]
- updatedConfig: { [field: string]: string | number | boolean | [] }
- setUpdatedConfig({ }): void
+ title: string
+ description?: string
+ documentationLink?: string
+ items: TPluginSettingWithKey[]
+ currentConfiguration: { [field: string]: any }
}
-export const Category: React.FunctionComponent = ({ name, items, updatedConfig, setUpdatedConfig }) => {
+export const Category: React.FunctionComponent = ({
+ title,
+ currentConfiguration,
+ description,
+ documentationLink,
+ items
+}) => {
return (
- {name}
+ {title}{
+ documentationLink &&
+
+ <>
+
+
+ >
+
+ }
+
+ {
+ description &&
+ <>
+
+
+
+ {description}
+
+
+
+
+ >
+ }
- {items.map((item, idx) => (
-
-
- {item.name}
- {isUpdated(updatedConfig, item)
- && {
+ const isUpdated = item.changed && !item.error;
+ return (
+
+
+ {item.title}
+ {item.error && (
+ }
- }
- description={item.description} >
-
-
-
-
- ))}
+ type='alert'
+ color='danger'
+ aria-label={item.key}
+ content='Invalid' />
+ )}
+ {isUpdated && (
+
+ )}
+
+ }
+ description={item.description} >
+ (
+
+
+
+ )
+ }
+ : {}
+ )}
+ />
+
+ )
+ })}
)
-}
+};
+
+const InputFormFilePickerPreInput = ({image, field}: {image: string, field: any}) => {
+ const dispatch = useDispatch();
+
+ return (
+ <>
+
+
+
+
+
+ {
+ try{
+ const response = await WzRequest.genericReq('DELETE', `/utils/configuration/files/${field.key}`);
+ dispatch(updateAppConfig(response.data.data.updatedConfiguration));
-const isUpdated = (configs, item) => typeof configs[item.setting] !== 'undefined'
\ No newline at end of file
+ // Show the toasts if necessary
+ const { requiresRunningHealthCheck, requiresReloadingBrowserTab, requiresRestartingPluginPlatform } = response.data.data;
+ requiresRunningHealthCheck && toastRequiresRunningHealthcheck();
+ requiresReloadingBrowserTab&& toastRequiresReloadingBrowserTab();
+ requiresRestartingPluginPlatform && toastRequiresRestartingPluginPlatform();
+ toastSuccessUpdateConfiguration();
+ }catch(error){
+ const options = {
+ context: `${InputFormFilePickerPreInput.name}.confirmDeleteFile`,
+ level: UI_LOGGER_LEVELS.ERROR,
+ severity: UI_ERROR_SEVERITIES.BUSINESS,
+ store: true,
+ error: {
+ error: error,
+ message: error.message || error,
+ title: error.name || error,
+ },
+ };
+ getErrorOrchestrator().handleError(options);
+ }
+ }}
+ modalProps={{ buttonColor: 'danger' }}
+ iconType="trash"
+ color="danger"
+ aria-label="Delete file"
+ />
+
+
+ >
+ );
+};
diff --git a/public/components/settings/configuration/components/categories/components/category/components/__snapshots__/field-form.test.tsx.snap b/public/components/settings/configuration/components/categories/components/category/components/__snapshots__/field-form.test.tsx.snap
deleted file mode 100644
index 55482f7924..0000000000
--- a/public/components/settings/configuration/components/categories/components/category/components/__snapshots__/field-form.test.tsx.snap
+++ /dev/null
@@ -1,67 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`FieldForm component renders correctly to match the snapshot 1`] = `
-
-
-
-
-
-
-
-
-
-`;
diff --git a/public/components/settings/configuration/components/categories/components/category/components/field-form.test.tsx b/public/components/settings/configuration/components/categories/components/category/components/field-form.test.tsx
deleted file mode 100644
index e551966749..0000000000
--- a/public/components/settings/configuration/components/categories/components/category/components/field-form.test.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Wazuh app - React test for FieldForm component.
- *
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- *
- */
-
-import React from 'react';
-import { FieldForm } from './field-form';
-import { ISetting } from '../../../../../configuration';
-import { mount } from 'enzyme';
-
-describe('FieldForm component', () => {
- it('renders correctly to match the snapshot', () => {
- const item: ISetting = {
- setting: 'string',
- value: 'boolean',
- description: 'string',
- category: 'string',
- name: 'string',
- form: { type: 'text', params: {} }
- };
- const updatedConfig = {};
- const setUpdatedConfig = jest.fn();
-
- const wrapper = mount(
-
- );
-
- expect(wrapper).toMatchSnapshot();
- });
-});
diff --git a/public/components/settings/configuration/components/categories/components/category/components/field-form.tsx b/public/components/settings/configuration/components/categories/components/category/components/field-form.tsx
deleted file mode 100644
index 54abed4317..0000000000
--- a/public/components/settings/configuration/components/categories/components/category/components/field-form.tsx
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Wazuh app - React component building the configuration component.
- *
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-import React, { useState, useEffect } from 'react';
-import { validate } from 'node-cron';
-import {
- EuiFieldText,
- EuiFieldNumber,
- EuiSwitch,
- EuiSelect,
- EuiCodeEditor,
- EuiTextColor
-} from '@elastic/eui';
-import { ISetting } from '../../../../../configuration';
-import 'brace/mode/javascript';
-import 'brace/snippets/javascript';
-import 'brace/ext/language_tools';
-import "brace/ext/searchbox";
-import {
- UI_ERROR_SEVERITIES,
- UIErrorLog, UIErrorSeverity,
- UILogLevel,
-} from '../../../../../../../../react-services/error-orchestrator/types';
-import { UI_LOGGER_LEVELS } from '../../../../../../../../../common/constants';
-import { getErrorOrchestrator } from '../../../../../../../../react-services/common-services';
-import _ from 'lodash';
-
-interface IFieldForm {
- item: ISetting
- updatedConfig: { [field: string]: string | number | boolean | [] }
- setUpdatedConfig({ }): void
-}
-export const FieldForm: React.FunctionComponent = (props) => {
- const { item } = props;
- switch (item.form.type) {
- case 'text':
- return
- case 'number':
- return
- case 'boolean':
- return
- case 'list':
- return
- case 'array':
- return
- case 'interval':
- return
- default:
- return null;
- }
-};
-
-//#region forms
-const TextForm: React.FunctionComponent = (props) => (
- onChange(e.target.value, props)} />);
-
-const NumberForm: React.FunctionComponent = (props) => (
- onChange(e.target.value, props)} />)
-const BooleanForm: React.FunctionComponent = (props) => (
- onChange(e.target.checked, props)} />);
-
-const ListForm: React.FunctionComponent = (props) => (
- onChange(e.target.value, props)} />);
-
-const IntervalForm: React.FunctionComponent = (props) => {
- const [interval, setInterval] = useState(getValue(props));
- const [invalid, setInvalid] = useState(false);
- useEffect(() => {
- if (validate(interval)) {
- setInvalid(false);
- getValue(props) !== interval && onChange(interval, props);
- } else {
- setInvalid(true);
- deleteChange(props);
- }
- }, [interval])
- return (
- <>
- setInterval(e.target.value)}
- />
- {invalid && Invalid cron schedule expressions }
- >
- );
-}
-
-const ArrayForm: React.FunctionComponent = (props) => {
- const [list, setList] = useState(JSON.stringify(getValue(props)));
-
- useEffect(() => {
- checkErrors();
- }, [list]);
-
- const checkErrors = () => {
- try {
- const parsed = JSON.parse(list);
- onChange(parsed, props);
- } catch (error) {
- const options: UIErrorLog = {
- context: `${FieldForm.name}.checkErrors`,
- level: UI_LOGGER_LEVELS.ERROR as UILogLevel,
- severity: UI_ERROR_SEVERITIES.UI as UIErrorSeverity,
- error: {
- error: error,
- message: error.message || error,
- title: error.message || error,
- },
- };
-
- getErrorOrchestrator().handleError(options);
- }
- }
- return (
-
- );
-}
-
-//#endregion
-
-//#region Helpers
-
-const getValue = ({ item, updatedConfig }: IFieldForm) => typeof updatedConfig[item.setting] !== 'undefined'
- ? updatedConfig[item.setting]
- : item.value;
-
-const onChange = (value: string | number | boolean | [], props: IFieldForm) => {
- const { updatedConfig, setUpdatedConfig, item } = props;
- if(!_.isEqual(item.value,value)){
- setUpdatedConfig({
- ...updatedConfig,
- [item.setting]: value,
- })
- }else{
- deleteChange(props);
- }
-}
-
-const deleteChange = (props: IFieldForm) => {
- const { updatedConfig, setUpdatedConfig, item } = props;
- const newConfig = { ...updatedConfig };
- delete newConfig[item.setting];
- setUpdatedConfig(newConfig);
-}
-
-//#endregion
diff --git a/public/components/settings/configuration/components/categories/components/category/components/index.ts b/public/components/settings/configuration/components/categories/components/category/components/index.ts
deleted file mode 100644
index f8dd9704e0..0000000000
--- a/public/components/settings/configuration/components/categories/components/category/components/index.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Wazuh app - React component building the configuration component.
- *
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-
-export { FieldForm } from './field-form';
\ No newline at end of file
diff --git a/public/components/settings/configuration/components/categories/components/show-toasts.tsx b/public/components/settings/configuration/components/categories/components/show-toasts.tsx
new file mode 100644
index 0000000000..b53e56e092
--- /dev/null
+++ b/public/components/settings/configuration/components/categories/components/show-toasts.tsx
@@ -0,0 +1,51 @@
+import React from 'react';
+import {
+ EuiButton,
+ EuiFlexGroup,
+ EuiFlexItem,
+} from '@elastic/eui';
+import { PLUGIN_PLATFORM_NAME } from '../../../../../../../common/constants';
+import { getToasts } from '../../../../../../kibana-services';
+
+export const toastRequiresReloadingBrowserTab = () => {
+ getToasts().add({
+ color: 'success',
+ title: 'Reload the page to apply the changes',
+ text:
+
+ window.location.reload()} size="s">Reload page
+
+
+ });
+};
+
+export const toastRequiresRunningHealthcheck = () => {
+ const toast = getToasts().add({
+ color: 'warning',
+ title: 'Run a health check to apply the changes.',
+ toastLifeTimeMs: 5000,
+ text:
+
+
+ {
+ getToasts().remove(toast);
+ window.location.href = '#/health-check';
+ }} size="s">Execute health check
+
+
+ });
+};
+
+export const toastRequiresRestartingPluginPlatform = () => {
+ getToasts().add({
+ color: 'warning',
+ title: `Restart ${PLUGIN_PLATFORM_NAME} to apply the changes`,
+ });
+};
+
+export const toastSuccessUpdateConfiguration = () => {
+ getToasts().add({
+ color: 'success',
+ title: 'The configuration has been successfully updated',
+ });
+};
\ No newline at end of file
diff --git a/public/components/settings/configuration/components/categories/index.ts b/public/components/settings/configuration/components/categories/index.ts
deleted file mode 100644
index f665665238..0000000000
--- a/public/components/settings/configuration/components/categories/index.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Wazuh app - React component building the configuration component.
- *
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-export { Categories } from './categories';
\ No newline at end of file
diff --git a/public/components/settings/configuration/components/header.tsx b/public/components/settings/configuration/components/header.tsx
index baee512ec3..7bc47fb1d3 100644
--- a/public/components/settings/configuration/components/header.tsx
+++ b/public/components/settings/configuration/components/header.tsx
@@ -11,8 +11,7 @@
* Find more information about this on the LICENSE file.
*/
-import React, { useState, useEffect, Fragment } from 'react';
-import {categoriesNames} from '../../../../../common/config-equivalences';
+import React, { useState, useEffect } from 'react';
import { AppNavigate } from '../../../../react-services/app-navigate';
import {
EuiFlexGroup,
@@ -28,7 +27,7 @@ import { PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_APP_CONFIGURATION } from '
import { getPluginDataPath } from '../../../../../common/plugin';
import { webDocumentationLink } from '../../../../../common/services/web_documentation';
-export const Header = ({query, setQuery}) => {
+export const Header = ({query, setQuery, searchBarFilters}) => {
return (
@@ -39,13 +38,12 @@ export const Header = ({query, setQuery}) => {
-
+
)
-}
-
+};
const Title = () => {
return (
@@ -68,7 +66,7 @@ const Title = () => {
)
-}
+};
const SubTitle = () => {
return (
@@ -78,16 +76,15 @@ const SubTitle = () => {
)
-}
+};
-const SearchBar = ({query, setQuery}) => {
- const [categories, setCategories] = useState([]);
+const SearchBar = ({query, setQuery, searchBarFilters}) => {
const [error, setError] = useState();
+
useEffect(() => {
- const cats = categoriesNames.map(item => ({value: item}));
- setCategories(cats);
getDefaultCategory(setQuery)
- }, [])
+ }, []);
+
const onChange = (args) => {
if(args.error){
setError(args.error);
@@ -95,28 +92,23 @@ const SearchBar = ({query, setQuery}) => {
setError(undefined);
setQuery(args);
}
- }
+ };
+
return (
-
+ <>
{!!error &&
{`${error.name}: ${error.message}`}
}
-
+ >
)
-}
+};
const getDefaultCategory = (setQuery) => {
const category:string | undefined = AppNavigate.getUrlParameter('category')
category && setQuery(`category:(${category})`)
-}
+};
diff --git a/public/components/settings/configuration/components/index.ts b/public/components/settings/configuration/components/index.ts
index 4b36cdf37d..cbc25aaeb7 100644
--- a/public/components/settings/configuration/components/index.ts
+++ b/public/components/settings/configuration/components/index.ts
@@ -11,5 +11,4 @@
* Find more information about this on the LICENSE file.
*/
export { Header } from './header';
-export { Categories } from './categories';
export { BottomBar } from './bottom-bar';
\ No newline at end of file
diff --git a/public/components/settings/configuration/configuration.tsx b/public/components/settings/configuration/configuration.tsx
index 780af7476f..d92025fc22 100644
--- a/public/components/settings/configuration/configuration.tsx
+++ b/public/components/settings/configuration/configuration.tsx
@@ -12,71 +12,282 @@
*/
import React, { useState, useEffect } from 'react';
-import { Header, Categories, BottomBar } from './components';
+import { useDispatch, useSelector } from 'react-redux';
+import { Header, BottomBar } from './components';
import { useKbnLoadingIndicator} from '../../common/hooks';
+import { useForm } from '../../common/form/hooks';
import {
+ EuiButton,
+ EuiFlexGroup,
+ EuiFlexItem,
EuiPage,
EuiPageBody,
EuiPageHeader,
EuiSpacer,
Query,
} from '@elastic/eui';
-import {
- configEquivalences,
- nameEquivalence,
- categoriesEquivalence,
- formEquivalence
-} from '../../../../common/config-equivalences';
import store from '../../../redux/store'
import { updateSelectedSettingsSection } from '../../../redux/actions/appStateActions';
-import { withUserAuthorizationPrompt, withErrorBoundary, withReduxProvider } from '../../common/hocs'
-import { WAZUH_ROLE_ADMINISTRATOR_NAME } from '../../../../common/constants';
+import { withUserAuthorizationPrompt, withErrorBoundary, withReduxProvider } from '../../common/hocs';
+import { EpluginSettingType, PLUGIN_SETTINGS, PLUGIN_SETTINGS_CATEGORIES, UI_LOGGER_LEVELS, WAZUH_ROLE_ADMINISTRATOR_NAME } from '../../../../common/constants';
import { compose } from 'redux';
+import { getPluginSettingDescription, getSettingsDefaultList, groupSettingsByCategory, getCategorySettingByTitle } from '../../../../common/services/settings';
+import { Category } from './components/categories/components';
+import { WzRequest } from '../../../react-services';
+import { UIErrorLog, UIErrorSeverity, UILogLevel, UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types';
+import { getErrorOrchestrator } from '../../../react-services/common-services';
+import { updateAppConfig } from '../../../redux/actions/appConfigActions';
+import path from 'path';
+import { toastRequiresReloadingBrowserTab, toastRequiresRestartingPluginPlatform, toastRequiresRunningHealthcheck, toastSuccessUpdateConfiguration } from './components/categories/components/show-toasts';
export type ISetting = {
- setting: string
+ key: string
value: boolean | string | number | object
description: string
category: string
name: string
readonly?: boolean
form: { type: string, params: {} }
-}
+};
+
+const pluginSettingConfigurableUI = getSettingsDefaultList()
+ .filter(categorySetting => categorySetting.isConfigurableFromUI)
+ .map(setting => ({ ...setting, category: PLUGIN_SETTINGS_CATEGORIES[setting.category].title}));
+
+const settingsCategoriesSearchBarFilters = [...new Set(pluginSettingConfigurableUI.map(({category}) => category))].sort().map(category => ({value: category}))
+
+const trasnsfromPluginSettingsToFormFields = configuration => Object.fromEntries(
+ getSettingsDefaultList()
+ .filter(pluginSetting => pluginSetting.isConfigurableFromUI)
+ .map(({
+ key,
+ type,
+ validate,
+ defaultValue: initialValue,
+ uiFormTransformChangedInputValue,
+ uiFormTransformConfigurationValueToInputValue,
+ uiFormTransformInputValueToConfigurationValue,
+ ...rest
+ }) => ([
+ key,
+ {
+ type,
+ validate: validate?.bind?.(rest),
+ transformChangedInputValue: uiFormTransformChangedInputValue?.bind?.(rest),
+ transformChangedOutputValue: uiFormTransformInputValueToConfigurationValue?.bind?.(rest),
+ initialValue: uiFormTransformConfigurationValueToInputValue ? uiFormTransformConfigurationValueToInputValue.bind(rest)(configuration?.[key] ?? initialValue) : (configuration?.[key] ?? initialValue)
+ }
+ ]))
+);
const WzConfigurationSettingsProvider = (props) => {
const [loading, setLoading ] = useKbnLoadingIndicator();
- const [config, setConfig] = useState([]);
const [query, setQuery] = useState('');
- const [updatedConfig, setUpdateConfig] = useState({});
+ const currentConfiguration = useSelector(state => state.appConfig.data);
+
+ const { fields, changed, errors, doChanges, undoChanges } = useForm(trasnsfromPluginSettingsToFormFields(currentConfiguration));
+ const dispatch = useDispatch();
+
useEffect(() => {
store.dispatch(updateSelectedSettingsSection('configuration'));
- const rawConfig = props.wazuhConfig.getConfig();
- const formatedConfig = Object.keys(rawConfig).reduce((acc, conf) => [
- ...acc,
- {
- setting: conf,
- value: rawConfig[conf],
- description: configEquivalences[conf],
- category: categoriesEquivalence[conf],
- name: nameEquivalence[conf],
- form: formEquivalence[conf],
- }
- ], []);
- setConfig(formatedConfig);
}, []);
+
+ const onChangeSearchQuery = (query) => {
+ setQuery(query);
+ };
+
+ const visibleSettings = Object.entries(fields)
+ .map(([fieldKey, fieldForm]) => ({
+ ...fieldForm,
+ key: fieldKey,
+ category: PLUGIN_SETTINGS_CATEGORIES[PLUGIN_SETTINGS[fieldKey].category].title,
+ type: PLUGIN_SETTINGS[fieldKey].type,
+ options: PLUGIN_SETTINGS[fieldKey]?.options,
+ title: PLUGIN_SETTINGS[fieldKey]?.title,
+ description: getPluginSettingDescription(PLUGIN_SETTINGS[fieldKey]),
+ }));
+
+ // https://github.com/elastic/eui/blob/aa4cfd7b7c34c2d724405a3ecffde7fe6cf3b50f/src/components/search_bar/query/query.ts#L138-L163
+ const search = Query.execute(query.query || query, visibleSettings, ['description', 'key', 'title']);
+
+ const visibleCategories = groupSettingsByCategory(search || visibleSettings)
+ // Sort categories to render them in their enum definition order
+ .sort((a, b) =>
+ (getCategorySettingByTitle(a.category)?.renderOrder || 0) -
+ (getCategorySettingByTitle(b.category)?.renderOrder || 0)
+ );
+
+ const onSave = async () => {
+ setLoading(true);
+ try {
+ const settingsToUpdate = Object.entries(changed).reduce((accum, [pluginSettingKey, currentValue]) => {
+ if(PLUGIN_SETTINGS[pluginSettingKey].isConfigurableFromFile && PLUGIN_SETTINGS[pluginSettingKey].type === EpluginSettingType.filepicker){
+ accum.fileUpload = {
+ ...accum.fileUpload,
+ [pluginSettingKey]: {
+ file: currentValue,
+ extension: path.extname(currentValue.name)
+ }
+ }
+ }else if(PLUGIN_SETTINGS[pluginSettingKey].isConfigurableFromFile){
+ accum.saveOnConfigurationFile = {
+ ...accum.saveOnConfigurationFile,
+ [pluginSettingKey]: currentValue
+ }
+ };
+ return accum;
+ }, {saveOnConfigurationFile: {}, fileUpload: {}});
+
+ const requests = [];
+
+ // Update the settings that doesn't upload a file
+ if(Object.keys(settingsToUpdate.saveOnConfigurationFile).length){
+ requests.push(WzRequest.genericReq(
+ 'PUT', '/utils/configuration',
+ settingsToUpdate.saveOnConfigurationFile
+ ));
+ };
+
+ // Update the settings that uploads a file
+ if(Object.keys(settingsToUpdate.fileUpload).length){
+ requests.push(...Object.entries(settingsToUpdate.fileUpload)
+ .map(([pluginSettingKey, {file}]) => {
+ // Create the form data
+ const formData = new FormData();
+ formData.append('file', file);
+ return WzRequest.genericReq(
+ 'PUT', `/utils/configuration/files/${pluginSettingKey}`,
+ formData,
+ {overwriteHeaders: {'content-type': 'multipart/form-data'}}
+ )
+ }));
+ };
+
+ const responses = await Promise.all(requests);
+
+ // Show the toasts if necessary
+ responses.some(({data: { data: {requiresRunningHealthCheck}}}) => requiresRunningHealthCheck) && toastRequiresRunningHealthcheck();
+ responses.some(({data: { data: {requiresReloadingBrowserTab}}}) => requiresReloadingBrowserTab) && toastRequiresReloadingBrowserTab();
+ responses.some(({data: { data: {requiresRestartingPluginPlatform}}}) => requiresRestartingPluginPlatform) && toastRequiresRestartingPluginPlatform();
+
+ // Update the app configuration frontend-cached setting in memory with the new values
+ const updatedConfiguration = {
+ ...responses.reduce((accum, {data: {data}}) => {
+ return {
+ ...accum,
+ ...(data.updatedConfiguration ? {...data.updatedConfiguration} : {}),
+ }
+ },{})
+ };
+ dispatch(updateAppConfig(updatedConfiguration));
+
+ // Remove the selected files on the file picker inputs
+ if(Object.keys(settingsToUpdate.fileUpload).length){
+ Object.keys(settingsToUpdate.fileUpload).forEach(settingKey => {
+ try{
+ fields[settingKey].inputRef.removeFiles(
+ // This method uses some methods of a DOM event.
+ // Because we want to remove the files when the configuration is saved,
+ // there is no event, so we create a object that contains the
+ // methods used to remove the files. Of this way, we can skip the errors
+ // due to missing methods.
+ // This workaround is based in @elastic/eui v29.3.2
+ // https://github.com/elastic/eui/blob/v29.3.2/src/components/form/file_picker/file_picker.tsx#L107-L108
+ {stopPropagation: () => {}, preventDefault: () => {}}
+ );
+ }catch(error){ };
+ });
+ };
+
+ // Show the success toast
+ toastSuccessUpdateConfiguration();
+
+ // Reset the form changed configuration
+ doChanges();
+ } catch (error) {
+ const options: UIErrorLog = {
+ context: `${WzConfigurationSettingsProvider.name}.onSave`,
+ level: UI_LOGGER_LEVELS.ERROR as UILogLevel,
+ severity: UI_ERROR_SEVERITIES.BUSINESS as UIErrorSeverity,
+ store: true,
+ error: {
+ error: error,
+ message: error.message || error,
+ title: `Error saving the configuration: ${error.message || error}`,
+ },
+ };
+
+ getErrorOrchestrator().handleError(options);
+ } finally {
+ setLoading(false);
+ };
+ };
+
+ const onCancel = () => {
+ const updatedSettingsUseFilePicker = Object.entries(changed).reduce((accum, [pluginSettingKey]) => {
+ if(PLUGIN_SETTINGS[pluginSettingKey].isConfigurableFromFile && PLUGIN_SETTINGS[pluginSettingKey].type === EpluginSettingType.filepicker){
+ accum.push(pluginSettingKey);
+ };
+ return accum;
+ }, []);
+
+ updatedSettingsUseFilePicker.forEach(settingKey => {
+ try{
+ fields[settingKey].inputRef.removeFiles(
+ // This method uses some methods of a DOM event.
+ // Because we want to remove the files when the configuration is saved,
+ // there is no event, so we create a object that contains the
+ // methods used to remove the files. Of this way, we can skip the errors
+ // due to missing methods.
+ // This workaround is based in @elastic/eui v29.3.2
+ // https://github.com/elastic/eui/blob/v29.3.2/src/components/form/file_picker/file_picker.tsx#L107-L108
+ {stopPropagation: () => {}, preventDefault: () => {}}
+ );
+ }catch(error){ };
+ });
+ undoChanges();
+ };
+
return (
-
+
-
+
+ {visibleCategories && visibleCategories.map(({ category, settings }) => {
+ const { description, documentationLink } = getCategorySettingByTitle(category);
+ return (
+
+ )
+ }
+ )}
+
-
+ {Object.keys(changed).length > 0 && (
+
+ )}
);
diff --git a/public/components/settings/configuration/utils/configuration-handler.js b/public/components/settings/configuration/utils/configuration-handler.js
deleted file mode 100644
index 8c15295277..0000000000
--- a/public/components/settings/configuration/utils/configuration-handler.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Wazuh app - Configuration handler service
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-
-import { WzRequest } from '../../../../react-services/wz-request';
-import { AppState } from '../../../../react-services/app-state';
-
-export default class ConfigurationHandler {
- /**
- * Set the configuration key
- */
- static async editKey(key, value) {
- try {
- if (key === 'ip.selector') {
- AppState.setPatternSelector(value);
- }
- const result = await WzRequest.genericReq('PUT', '/utils/configuration', {
- key,
- value
- });
- return result;
- } catch (error) {
- return Promise.reject(error);
- }
- }
-}
diff --git a/public/components/tools/devtools/api-requests-list.js b/public/components/tools/devtools/api-requests-list.js
index 3054dd78cf..739c18870f 100644
--- a/public/components/tools/devtools/api-requests-list.js
+++ b/public/components/tools/devtools/api-requests-list.js
@@ -221,13 +221,6 @@ export const apiRequestList =
"meta": "endpoint",
"documentationLink": "https://documentation.wazuh.com/current/user-manual/api/reference.html#get-active-configuration"
},
- {
- "name": "agents/:agent_id/group/is_sync",
- "value": "agents/:agent_id/group/is_sync",
- "score": 1,
- "meta": "endpoint",
- "documentationLink": "https://documentation.wazuh.com/current/user-manual/api/reference.html#get-sync-status-of-agent"
- },
{
"name": "agents/:agent_id/key",
"value": "agents/:agent_id/key",
diff --git a/public/components/visualize/agent-visualizations.js b/public/components/visualize/agent-visualizations.js
index 13ff661c6b..f174013cc3 100644
--- a/public/components/visualize/agent-visualizations.js
+++ b/public/components/visualize/agent-visualizations.js
@@ -44,21 +44,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-General-Alerts-summary',
- width: 60
- },
- {
- title: 'Groups summary',
- id: 'Wazuh-App-Agents-General-Groups-summary',
- width: 40
- }
- ]
- }
]
},
aws: {
@@ -112,15 +97,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-AWS-Alerts-summary'
- }
- ]
- }
]
},
fim: {
@@ -165,15 +141,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-FIM-Alerts-summary'
- }
- ]
- }
]
},
gcp: {
@@ -228,15 +195,6 @@ export const agentVisualizations = {
},
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-GCP-Alerts-summary'
- }
- ]
- }
]
},
pci: {
@@ -276,15 +234,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-PCI-Last-alerts'
- }
- ]
- }
]
},
gdpr: {
@@ -324,15 +273,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-GDPR-Last-alerts'
- }
- ]
- }
]
},
nist: {
@@ -366,15 +306,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-NIST-Last-alerts'
- }
- ]
- }
]
},
tsc: {
@@ -414,15 +345,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-TSC-Alerts-summary'
- }
- ]
- }
]
},
hipaa: {
@@ -462,15 +384,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-HIPAA-Last-alerts'
- }
- ]
- }
]
},
virustotal: {
@@ -499,15 +412,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-Virustotal-Alerts-summary'
- }
- ]
- }
]
},
osquery: {
@@ -542,15 +446,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-Osquery-Alerts-summary'
- }
- ]
- }
]
},
mitre: {
@@ -590,15 +485,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-MITRE-Alerts-summary'
- }
- ]
- }
]
},
docker: {
@@ -632,15 +518,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-Docker-Events-summary'
- }
- ]
- }
]
},
oscap: {
@@ -694,15 +571,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-OSCAP-Last-alerts'
- }
- ]
- }
]
},
ciscat: {
@@ -722,15 +590,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-app-Agents-CISCAT-alerts-summary'
- }
- ]
- }
]
},
pm: {
@@ -759,15 +618,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-PM-Alerts-summary'
- }
- ]
- }
]
},
audit: {
@@ -801,15 +651,6 @@ export const agentVisualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-Audit-Last-alerts'
- }
- ]
- }
]
},
github: {
@@ -819,12 +660,12 @@ export const agentVisualizations = {
vis: [
{
title: 'Alerts evolution by organization',
- id: 'Wazuh-App-Overview-GitHub-Alerts-Evolution-By-Organization',
+ id: 'Wazuh-App-Agents-GitHub-Alerts-Evolution-By-Organization',
width: 60
},
{
title: 'Top 5 organizations by alerts',
- id: 'Wazuh-App-Overview-GitHub-Top-5-Organizations-By-Alerts',
+ id: 'Wazuh-App-Agents-GitHub-Top-5-Organizations-By-Alerts',
width: 40
}
]
@@ -834,25 +675,16 @@ export const agentVisualizations = {
vis: [
{
title: 'Top alerts by action type and organization',
- id: 'Wazuh-App-Overview-GitHub-Alert-Action-Type-By-Organization',
+ id: 'Wazuh-App-Agents-GitHub-Alert-Action-Type-By-Organization',
width: 40
},
{
title: 'Users with more alerts',
- id: 'Wazuh-App-Overview-GitHub-Users-With-More-Alerts',
+ id: 'Wazuh-App-Agents-GitHub-Users-With-More-Alerts',
width: 60
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-GitHub-Alert-Summary',
- }
- ]
- }
]
},
};
diff --git a/public/components/visualize/visualizations.js b/public/components/visualize/visualizations.js
index f683c8488e..446c85fe8c 100644
--- a/public/components/visualize/visualizations.js
+++ b/public/components/visualize/visualizations.js
@@ -43,15 +43,6 @@ export const visualizations = {
},
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-General-Alerts-summary'
- }
- ]
- }
]
},
fim: {
@@ -100,15 +91,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-FIM-Alerts-summary'
- }
- ]
- }
]
},
office: {
@@ -122,7 +104,7 @@ export const visualizations = {
width: 40
},
{
- title: 'IP by Users',
+ title: 'IP address by Users',
id: 'Wazuh-App-Overview-Office-IPs-By-User-Barchart',
width: 30
},
@@ -162,15 +144,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-Office-Alerts-summary'
- }
- ]
- }
]
},
aws: {
@@ -224,15 +197,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-AWS-Alerts-summary'
- }
- ]
- }
]
},
gcp: {
@@ -271,21 +235,12 @@ export const visualizations = {
height: 450,
vis: [
{
- title: 'Top 5 Map by source ip',
+ title: 'Top 5 Map by source IP address',
id: 'Wazuh-App-Overview-GCP-Map-By-SourceIp',
width: 100
},
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-GCP-Alerts-summary'
- }
- ]
- }
]
},
pci: {
@@ -332,15 +287,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-PCI-DSS-Alerts-summary'
- }
- ]
- }
]
},
gdpr: {
@@ -387,15 +333,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-GDPR-Alerts-summary'
- }
- ]
- }
]
},
nist: {
@@ -414,7 +351,7 @@ export const visualizations = {
width: 50
},
{
- title: 'Requiments distribution by agent',
+ title: 'Requirements distribution by agent',
id: 'Wazuh-App-Overview-NIST-requirements-by-agents',
width: 30
}
@@ -440,15 +377,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-NIST-Alerts-summary'
- }
- ]
- }
]
},
tsc: {
@@ -495,15 +423,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-TSC-Alerts-summary'
- }
- ]
- }
]
},
hipaa: {
@@ -571,15 +490,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-HIPAA-Alerts-summary'
- }
- ]
- }
]
},
vuls: {
@@ -621,7 +531,7 @@ export const visualizations = {
},
{
height: 450,
- vis:Â [
+ vis: [
{
title: 'Top affected packages by CVEs',
id: 'Wazuh-App-Overview-vuls-packages-CVEs',
@@ -634,15 +544,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alert summary',
- id: 'Wazuh-App-Overview-vuls-Alert-summary'
- }
- ]
- }
]
},
virustotal: {
@@ -689,15 +590,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-Virustotal-Alerts-summary'
- }
- ]
- }
]
},
osquery: {
@@ -737,15 +629,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-Osquery-Alerts-summary'
- }
- ]
- }
]
},
mitre: {
@@ -785,15 +668,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-MITRE-Alerts-summary'
- }
- ]
- }
]
},
docker: {
@@ -827,15 +701,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-Docker-Events-summary'
- }
- ]
- }
]
},
oscap: {
@@ -889,15 +754,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-OSCAP-Last-alerts'
- }
- ]
- }
]
},
ciscat: {
@@ -917,15 +773,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-app-Overview-CISCAT-alerts-summary'
- }
- ]
- }
]
},
pm: {
@@ -959,15 +806,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-PM-Alerts-summary'
- }
- ]
- }
]
},
audit: {
@@ -1006,15 +844,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-Audit-Last-alerts'
- }
- ]
- }
]
},
github: {
@@ -1049,15 +878,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-GitHub-Alert-Summary',
- }
- ]
- }
]
},
};
diff --git a/public/components/visualize/wz-visualize.js b/public/components/visualize/wz-visualize.js
index 4f5554e57e..e08e43d072 100644
--- a/public/components/visualize/wz-visualize.js
+++ b/public/components/visualize/wz-visualize.js
@@ -33,13 +33,12 @@ import { Metrics } from '../overview/metrics/metrics';
import { PatternHandler } from '../../react-services/pattern-handler';
import { getToasts } from '../../kibana-services';
import { SampleDataWarning, SecurityAlerts } from './components';
-import { toMountPoint } from '../../../../../src/plugins/kibana_react/public';
+import { toMountPoint } from '../../../../../src/plugins/opensearch_dashboards_react/public';
import { withReduxProvider, withErrorBoundary } from '../common/hocs';
import { compose } from 'redux';
import { UI_LOGGER_LEVELS } from '../../../common/constants';
import { UI_ERROR_SEVERITIES } from '../../react-services/error-orchestrator/types';
import { getErrorOrchestrator } from '../../react-services/common-services';
-import { satisfyPluginPlatformVersion } from '../../../common/semver';
import { webDocumentationLink } from '../../../common/services/web_documentation';
const visHandler = new VisHandlers();
@@ -121,9 +120,7 @@ export const WzVisualize = compose(
try {
this.hasRefreshedKnownFields = true;
this.isRefreshing = true;
- if(satisfyPluginPlatformVersion('<7.11')){
- await PatternHandler.refreshIndexPattern(this.newFields);
- };
+ await PatternHandler.refreshIndexPattern(this.newFields);
this.isRefreshing = false;
this.reloadToast();
this.newFields = {};
@@ -148,50 +145,30 @@ export const WzVisualize = compose(
};
reloadToast = () => {
const toastLifeTimeMs = 300000;
- if(satisfyPluginPlatformVersion('<7.11')){
- getToasts().add({
- color: 'success',
- title: 'The index pattern was refreshed successfully.',
- text: toMountPoint(
-
- There were some unknown fields for the current index pattern.
- You need to refresh the page to apply the changes.
-
- Troubleshooting
-
-
-
- window.location.reload()} size="s">Reload page
-
- ),
- toastLifeTimeMs
- });
- }else if(satisfyPluginPlatformVersion('>=7.11')){
- getToasts().add({
- color: 'warning',
- title: 'Found unknown fields in the index pattern.',
- text: toMountPoint(
-
- There are some unknown fields for the current index pattern.
- You need to refresh the page to update the fields.
-
- Troubleshooting
-
-
-
- window.location.reload()} size="s">Reload page
-
- ),
- toastLifeTimeMs
- });
- };
+ const urlTroubleShootingDocs = webDocumentationLink(
+ 'user-manual/elasticsearch/troubleshooting.html#index-pattern-was-refreshed-toast-keeps-popping-up'
+ );
+ getToasts().add({
+ color: 'success',
+ title: 'The index pattern was refreshed successfully.',
+ text: toMountPoint(
+
+ There were some unknown fields for the current index pattern.
+ You need to refresh the page to apply the changes.
+
+ Troubleshooting
+
+
+
+ window.location.reload()} size="s">Reload page
+
+ ),
+ toastLifeTimeMs
+ });
};
render() {
const { visualizations } = this.state;
diff --git a/public/components/wz-agent-selector/wz-agent-selector.js b/public/components/wz-agent-selector/wz-agent-selector.js
index bf00fc0b0b..d95b595073 100644
--- a/public/components/wz-agent-selector/wz-agent-selector.js
+++ b/public/components/wz-agent-selector/wz-agent-selector.js
@@ -23,7 +23,7 @@ import { connect } from 'react-redux';
import { showExploreAgentModalGlobal } from '../../redux/actions/appStateActions';
import store from '../../redux/store';
import { AgentSelectionTable } from '../../controllers/overview/components/overview-actions/agents-selection-table';
-import { WAZUH_ALERTS_PATTERN } from '../../../common/constants';
+import { getSettingDefaultValue } from '../../../common/services/settings';
import { AppState } from '../../react-services/app-state';
import { getAngularModule, getDataPlugin } from '../../kibana-services';
@@ -70,7 +70,7 @@ class WzAgentSelector extends Component {
"negate": false,
"params": { "query": agentIdList[0] },
"type": "phrase",
- "index": AppState.getCurrentPattern() || WAZUH_ALERTS_PATTERN
+ "index": AppState.getCurrentPattern() || getSettingDefaultValue('pattern')
},
"query": {
"match": {
diff --git a/public/components/wz-menu/wz-menu-agent.js b/public/components/wz-menu/wz-menu-agent.js
deleted file mode 100644
index d1ca750de0..0000000000
--- a/public/components/wz-menu/wz-menu-agent.js
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Wazuh app - React component for registering agents.
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-import React, { Component, Fragment } from 'react';
-import { EuiFlexGroup, EuiFlexItem, EuiFlexGrid, EuiButtonEmpty, EuiSideNav, EuiIcon, EuiHorizontalRule, EuiPanel, EuiButton, EuiSpacer } from '@elastic/eui';
-import { WzRequest } from '../../react-services/wz-request';
-import { connect } from 'react-redux';
-import { updateCurrentAgentData } from '../../redux/actions/appStateActions';
-import { AppState } from '../../react-services/app-state';
-import { hasAgentSupportModule } from '../../react-services/wz-agents';
-import { AgentInfo } from './../common/welcome/agents-info';
-import { getAngularModule } from '../../kibana-services';
-import { WAZUH_MODULES_ID, UI_LOGGER_LEVELS } from '../../../common/constants';
-import { UI_ERROR_SEVERITIES } from '../../react-services/error-orchestrator/types';
-import { getErrorOrchestrator } from '../../react-services/common-services'
-
-class WzMenuAgent extends Component {
- constructor(props) {
- super(props);
- this.currentApi = JSON.parse(AppState.getCurrentAPI()).id;
- this.state = {
- extensions: []
- };
-
- this.agent = false;
-
- this.agentSections = {
- securityInformation: {
- id: 'securityInformation',
- text: 'Security information management'
- },
- auditing: { id: 'auditing', text: 'Auditing and Policy Monitoring' },
- threatDetection: {
- id: 'threatDetection',
- text: 'Threat detection and response'
- },
- regulatoryCompliance: {
- id: 'regulatoryCompliance',
- text: 'Regulatory Compliance'
- },
- general: { id: WAZUH_MODULES_ID.SECURITY_EVENTS, text: 'Security Events' },
- fim: { id: WAZUH_MODULES_ID.INTEGRITY_MONITORING, text: 'Integrity Monitoring' },
- aws: { id: WAZUH_MODULES_ID.AMAZON_WEB_SERVICES, text: 'Amazon AWS' },
- gcp: { id: WAZUH_MODULES_ID.GOOGLE_CLOUD_PLATFORM, text: 'Google Cloud Platform' },
- pm: { id: WAZUH_MODULES_ID.POLICY_MONITORING, text: 'Policy Monitoring' },
- sca: { id: WAZUH_MODULES_ID.SECURITY_CONFIGURATION_ASSESSMENT, text: 'Security configuration assessment' },
- audit: { id: WAZUH_MODULES_ID.AUDITING, text: 'System Auditing' },
- oscap: { id: WAZUH_MODULES_ID.OPEN_SCAP, text: 'OpenSCAP' },
- ciscat: { id: WAZUH_MODULES_ID.CIS_CAT, text: 'CIS-CAT' },
- vuls: { id: WAZUH_MODULES_ID.VULNERABILITIES, text: 'Vulnerabilities' },
- virustotal: { id: WAZUH_MODULES_ID.VIRUSTOTAL, text: 'VirusTotal' },
- osquery: { id: WAZUH_MODULES_ID.OSQUERY, text: 'Osquery' },
- docker: { id: WAZUH_MODULES_ID.DOCKER, text: 'Docker Listener' },
- mitre: { id: WAZUH_MODULES_ID.MITRE_ATTACK, text: 'MITRE ATT&CK' },
- pci: { id: WAZUH_MODULES_ID.PCI_DSS, text: 'PCI DSS' },
- gdpr: { id: WAZUH_MODULES_ID.GDPR, text: 'GDPR' },
- hipaa: { id: WAZUH_MODULES_ID.HIPAA, text: 'HIPAA' },
- nist: { id: WAZUH_MODULES_ID.NIST_800_53, text: 'NIST 800-53' },
- tsc: { id: WAZUH_MODULES_ID.TSC, text: 'TSC' },
- github: {id: WAZUH_MODULES_ID.GITHUB, text: 'GitHub'}
- };
-
- this.securityInformationItems = [
- this.agentSections.general,
- this.agentSections.fim,
- this.agentSections.gcp,
- ];
- this.auditingItems = [
- this.agentSections.pm,
- this.agentSections.audit,
- this.agentSections.oscap,
- this.agentSections.ciscat,
- this.agentSections.sca
- ];
- this.threatDetectionItems = [
- this.agentSections.vuls,
- this.agentSections.virustotal,
- this.agentSections.osquery,
- this.agentSections.docker,
- this.agentSections.mitre
- ];
- this.regulatoryComplianceItems = [
- this.agentSections.pci,
- this.agentSections.gdpr,
- this.agentSections.hipaa,
- this.agentSections.nist,
- this.agentSections.tsc
- ];
-
- }
-
- async componentDidMount() {
-
- const dataAgent = await this.getAgentData(this.props.isAgent);
- this.agent = dataAgent.data.data;
-
- const extensions = await AppState.getExtensions(this.currentApi);
- this.setState({ extensions });
- const $injector = getAngularModule().$injector;
- this.router = $injector.get('$route');
- }
-
-
- async getAgentData(agentId) {
- try {
- const result = await WzRequest.apiReq('GET', '/agents/' + agentId, {});
- return result;
- } catch (error) {
- const options = {
- context: `${WzMenuAgent.name}.getAgentData`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.BUSINESS,
- store: true,
- display: true,
- error: {
- error: error,
- message: error.message || error,
- title: error.name || error,
- },
- };
- getErrorOrchestrator().handleError(options);
- }
- }
-
-
- clickMenuItem = section => {
- this.props.closePopover();
- if (this.props.currentTab !== section) {
- if (!this.props.switchTab) {
- window.location.href = `#/agents?agent=${this.props.isAgent}&tab=${section}`;
- this.router.reload();
- } else {
- this.props.switchTab(section);
- }
- }
- };
-
- createItems = items => {
- const keyExists = key => Object.keys(this.state.extensions).includes(key);
- const keyIsTrue = key => (this.state.extensions || [])[key];
- return items.filter(item =>
- (Object.keys(this.props.currentAgentData).length ? hasAgentSupportModule(this.props.currentAgentData, item.id) : true) && Object.keys(this.state.extensions).length && (!keyExists(item.id) || keyIsTrue(item.id))
- ).map(item => this.createItem(item));
- };
-
- createItem = (item, data = {}) => {
- // NOTE: Duplicate `name` values will cause `id` collisions.
- return {
- ...data,
- id: item.id,
- name: item.text,
- isSelected: this.props.currentTab === item.id,
- onClick: () => this.clickMenuItem(item.id)
- };
- };
-
- render() {
- const securityInformation = [
- {
- name: this.agentSections.securityInformation.text,
- id: this.agentSections.securityInformation.id,
- disabled: true,
- icon: ,
- items: this.createItems(this.securityInformationItems)
- }
- ];
-
- const auditing = [
- {
- name: this.agentSections.auditing.text,
- id: this.agentSections.auditing.id,
- disabled: true,
- icon: ,
- items: this.createItems(this.auditingItems)
- }
- ];
-
- const threatDetection = [
- {
- name: this.agentSections.threatDetection.text,
- id: this.agentSections.threatDetection.id,
- disabled: true,
- icon: ,
- items: this.createItems(this.threatDetectionItems)
- }
- ];
-
- const regulatoryCompliance = [
- {
- name: this.agentSections.regulatoryCompliance.text,
- id: this.agentSections.regulatoryCompliance.id,
- disabled: true,
- icon: ,
- items: this.createItems(this.regulatoryComplianceItems)
- }
- ];
-
- return (
-
- {Object.keys(this.state.extensions).length && (
-
- {(
-
-
-
- {
- this.props.closePopover();
- window.location.href = '#/agents-preview';
- }}>
- Go to Agent welcome
-
-
-
-
-
-
-
-
-
- )}
- {this.props.isAgent && (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- this.clickMenuItem('syscollector')}
- iconType="inspect">
- Inventory data
-
-
-
- this.clickMenuItem('configuration')}
- iconType="gear" >
- Configuration
-
-
-
- )}
-
- ) || (
- )}
-
- );
- }
-}
-
-const mapStateToProps = state => {
- return {
- state: state.rulesetReducers,
- currentAgentData: state.appStateReducers.currentAgentData,
- currentTab: state.appStateReducers.currentTab
- };
-};
-
-const mapDispatchToProps = dispatch => ({
- updateCurrentAgentData: (agentData) => dispatch(updateCurrentAgentData(agentData))
-});
-
-export default connect(
- mapStateToProps,
- mapDispatchToProps
-)(WzMenuAgent);
diff --git a/public/components/wz-menu/wz-menu-management.js b/public/components/wz-menu/wz-menu-management.js
index f46eef9126..842067c691 100644
--- a/public/components/wz-menu/wz-menu-management.js
+++ b/public/components/wz-menu/wz-menu-management.js
@@ -138,7 +138,6 @@ class WzMenuManagement extends Component {
name: this.managementSections.administration.text,
id: this.managementSections.administration.id,
id: 0,
- disabled: true,
icon: ,
items: [
this.createItem(this.managementSections.rules),
@@ -154,7 +153,6 @@ class WzMenuManagement extends Component {
{
name: this.managementSections.statusReports.text,
id: this.managementSections.statusReports.id,
- disabled: true,
icon: ,
items: [
this.createItem(this.managementSections.status),
@@ -194,7 +192,7 @@ class WzMenuManagement extends Component {
const mapStateToProps = state => {
return {
- state: state.rulesetReducers,
+ state: state.managementReducers,
};
};
diff --git a/public/components/wz-menu/wz-menu-overview.js b/public/components/wz-menu/wz-menu-overview.js
index 1e90d45b41..65ce09bf04 100644
--- a/public/components/wz-menu/wz-menu-overview.js
+++ b/public/components/wz-menu/wz-menu-overview.js
@@ -331,7 +331,6 @@ class WzMenuOverview extends Component {
const mapStateToProps = state => {
return {
- state: state.rulesetReducers,
currentAgentData: state.appStateReducers.currentAgentData,
currentTab: state.appStateReducers.currentTab
};
diff --git a/public/components/wz-menu/wz-menu-settings.js b/public/components/wz-menu/wz-menu-settings.js
index dc67fc55f9..0a2a57efaa 100644
--- a/public/components/wz-menu/wz-menu-settings.js
+++ b/public/components/wz-menu/wz-menu-settings.js
@@ -124,7 +124,6 @@ class WzMenuSettings extends Component {
{
name: availableSettings.settings.text,
id: availableSettings.settings.id,
- disabled: true,
icon: ,
items: renderSettings
}
diff --git a/public/components/wz-menu/wz-menu.js b/public/components/wz-menu/wz-menu.js
index f1922c7057..634b967546 100644
--- a/public/components/wz-menu/wz-menu.js
+++ b/public/components/wz-menu/wz-menu.js
@@ -17,9 +17,7 @@ import {
EuiPopover,
EuiIcon,
EuiButtonEmpty,
- EuiText,
EuiCallOut,
- EuiPageHeader,
EuiToolTip,
EuiLoadingSpinner,
EuiFormRow,
@@ -894,7 +892,7 @@ export const WzMenu = withWindowSize(class WzMenu extends Component {
)}
- {/*this.state.hover === 'overview' */this.state.isOverviewPopoverOpen && (
+ {this.state.isOverviewPopoverOpen && (
this.setState({ menuOpened: false })}
>
@@ -904,7 +902,7 @@ export const WzMenu = withWindowSize(class WzMenu extends Component {
);
- const logotypeURL = getHttp().basePath.prepend(this.wazuhConfig.getConfig()['customization.logo.app'] ? getAssetURL(this.wazuhConfig.getConfig()['customization.logo.app']) : getThemeAssetURL('logo.svg'));
+ const logotypeURL = getHttp().basePath.prepend(this.wazuhConfig.getConfig()['customization.enabled'] && this.wazuhConfig.getConfig()['customization.logo.app'] ? getAssetURL(this.wazuhConfig.getConfig()['customization.logo.app']) : getThemeAssetURL('logo.svg'));
const mainButton = (
this.switchMenuOpened()}>
-
-
+
+
-
+
{this.state.menuOpened && (
)}
@@ -942,6 +945,10 @@ export const WzMenu = withWindowSize(class WzMenu extends Component {
const container = document.getElementsByClassName('euiBreadcrumbs');
+ const expandedHeader = document.getElementById('globalHeaderBars')
+ const wzExpandedHeader = expandedHeader.children.length === 1
+ ? 'wz-expanded-header-min'
+ : 'wz-expanded-header-max'
return ReactDOM.createPortal(
{this.state.showMenu && (
@@ -951,8 +958,8 @@ export const WzMenu = withWindowSize(class WzMenu extends Component {
{
+
+ async buildSuggestItems(inputValue: string): Promise {
return [];
}
-
- buildSuggestFields(inputValue:string):suggestItem[] {
+
+ buildSuggestFields(inputValue: string): suggestItem[] {
return [];
- };
+ }
- async buildSuggestValues(inputValue:string, value:string=''):Promise {
+ async buildSuggestValues(inputValue: string, value: string = ''): Promise {
return [];
}
- buildSuggestValue(value:string|number) {
+ buildSuggestValue(value: string | number = '') {
return {
- type: {iconType: 'kqlValue', color: 'tint0'},
- label: typeof value !== 'string' ? value.toString(): value,
+ type: { iconType: 'kqlValue', color: 'tint0' },
+ label: typeof value !== 'string' ? value.toString() : value,
};
}
@@ -40,7 +39,7 @@ export abstract class BaseHandler {
return item.label.includes(field);
}
- filterSuggestValues(item:number|string, inputValue:string) {
+ filterSuggestValues(item: number | string, inputValue: string) {
if (typeof item === 'number' && !!inputValue) {
// @ts-ignore
return item == inputValue;
@@ -51,22 +50,28 @@ export abstract class BaseHandler {
return true;
}
- onItemClick(item:suggestItem, inputValue:string, filters:object):void {}
+ onItemClick(item: suggestItem, inputValue: string, filters: object): void {}
- onInputChange(inputValue:string, currentFilters:object):{
- isInvalid: boolean, filters: object
- } { return {isInvalid:true, filters:{}} }
+ onInputChange(
+ inputValue: string,
+ currentFilters: object
+ ): {
+ isInvalid: boolean;
+ filters: object;
+ } {
+ return { isInvalid: true, filters: {} };
+ }
- onKeyPress(inputValue:string, currentFilters:object):void {}
+ onKeyPress(inputValue: string, currentFilters: object): void {}
mapSuggestFields(item): suggestItem {
const suggestItem = {
type: {
iconType: 'kqlField',
- color: 'tint4'
+ color: 'tint4',
},
label: item.label,
- }
+ };
if (item.description) {
suggestItem['description'] = item.description;
}
diff --git a/public/components/wz-search-bar/wz-search-bar.test.tsx b/public/components/wz-search-bar/wz-search-bar.test.tsx
index 85e197c0db..afc764cea2 100644
--- a/public/components/wz-search-bar/wz-search-bar.test.tsx
+++ b/public/components/wz-search-bar/wz-search-bar.test.tsx
@@ -14,14 +14,14 @@ const suggestions: IWzSuggestItem[] = [
{
type: 'q',
label: 'os.platform',
- description: 'Filter by OS platform',
+ description: 'Filter by operating system platform',
operators: ['=', '!='],
values: async (value) => getSuggestionsFilters('os.platform', value, { q: 'id!=000' }),
},
{
type: 'q',
label: 'ip',
- description: 'Filter by agent IP',
+ description: 'Filter by agent IP address',
operators: ['=', '!='],
values: async (value) => getSuggestionsFilters('ip', value, { q: 'id!=000' }),
},
diff --git a/public/controllers/agent/agents-preview.js b/public/controllers/agent/agents-preview.js
index 401c8c6833..5cc1669c65 100644
--- a/public/controllers/agent/agents-preview.js
+++ b/public/controllers/agent/agents-preview.js
@@ -77,16 +77,6 @@ export class AgentsPreviewController {
if (loc && loc.tab) {
this.submenuNavItem = loc.tab;
}
- const summaryData = await WzRequest.apiReq('GET', '/agents/summary/status', {});
- this.summary = summaryData.data.data;
- if (this.summary.total === 0) {
- if (this.addingNewAgent === undefined) {
- this.addNewAgent(true);
- }
- this.hasAgents = false;
- } else {
- this.hasAgents = true;
- }
// Watcher for URL params
this.$scope.$watch('submenuNavItem', () => {
this.$location.search('tab', this.submenuNavItem);
@@ -97,7 +87,7 @@ export class AgentsPreviewController {
});
this.registerAgentsProps = {
addNewAgent: flag => this.addNewAgent(flag),
- hasAgents: this.hasAgents,
+ hasAgents: () => this.hasAgents,
reload: () => this.$route.reload(),
getWazuhVersion: () => this.getWazuhVersion(),
getCurrentApiAddress: () => this.getCurrentApiAddress()
@@ -107,6 +97,17 @@ export class AgentsPreviewController {
const instance = new DataFactory(WzRequest.apiReq, '/agents', false, false);
//Props
this.tableAgentsProps = {
+ updateSummary: (summary) => {
+ this.summary = summary;
+ if (this.summary.total === 0) {
+ if (this.addingNewAgent === undefined) {
+ this.addNewAgent(true);
+ }
+ this.hasAgents = false;
+ } else {
+ this.hasAgents = true;
+ }
+ },
wzReq: (method, path, body) => WzRequest.apiReq(method, path, body),
addingNewAgent: () => {
this.addNewAgent(true);
diff --git a/public/controllers/agent/agents.js b/public/controllers/agent/agents.js
index b5ae910752..98deeea151 100644
--- a/public/controllers/agent/agents.js
+++ b/public/controllers/agent/agents.js
@@ -28,12 +28,13 @@ import { ErrorHandler } from '../../react-services/error-handler';
import { GroupHandler } from '../../react-services/group-handler';
import store from '../../redux/store';
import { updateGlobalBreadcrumb } from '../../redux/actions/globalBreadcrumbActions';
-import { API_NAME_AGENT_STATUS, WAZUH_ALERTS_PATTERN } from '../../../common/constants';
+import { API_NAME_AGENT_STATUS } from '../../../common/constants';
import { getDataPlugin } from '../../kibana-services';
import { hasAgentSupportModule } from '../../react-services/wz-agents';
import { UI_LOGGER_LEVELS } from '../../../common/constants';
import { UI_ERROR_SEVERITIES } from '../../react-services/error-orchestrator/types';
import { getErrorOrchestrator } from '../../react-services/common-services';
+import { getSettingDefaultValue } from '../../../common/services/settings';
export class AgentsController {
/**
@@ -306,8 +307,6 @@ export class AgentsController {
};
this.$scope.switchConfigurationTab = (configurationTab, navigate) => {
- // Check if configuration is synced
- this.checkSync();
this.$scope.navigate = navigate;
this.configurationHandler.switchConfigurationTab(configurationTab, this.$scope);
if (!this.$scope.navigate) {
@@ -510,8 +509,11 @@ export class AgentsController {
},
});
this.$scope.agent.status =
- (((((agentInfo || {}).data || {}).data || {}).affected_items || [])[0] || {}).status ||
+ agentInfo?.data?.data?.affected_items?.[0]?.status ||
this.$scope.agent.status;
+ this.$scope.isSynchronized = this.$scope.agent.status?.synced;
+
+ this.$scope.$applyAsync();
} catch (error) {
throw new Error(error);
}
@@ -617,7 +619,7 @@ export class AgentsController {
*/
addMitrefilter(id) {
const filter = `{"meta":{"index": ${
- AppState.getCurrentPattern() || WAZUH_ALERTS_PATTERN
+ AppState.getCurrentPattern() || getSettingDefaultValue('pattern')
}},"query":{"match":{"rule.mitre.id":{"query":"${id}","type":"phrase"}}}}`;
this.$rootScope.$emit('addNewKibanaFilter', {
filter: JSON.parse(filter),
@@ -738,20 +740,6 @@ export class AgentsController {
this.$scope.agent.syscheck = result;
}
- /**
- * Checks if configuration is sync
- */
- async checkSync() {
- const isSync = await WzRequest.apiReq(
- 'GET',
- `/agents/${this.$scope.agent.id}/group/is_sync`,
- {}
- );
- this.$scope.isSynchronized =
- (((((isSync || {}).data || {}).data || {}).affected_items || [])[0] || {}).synced || false;
- this.$scope.$applyAsync();
- }
-
/**
* Get the needed data for load syscollector
* @param {*} id
diff --git a/public/controllers/agent/components/agents-preview.js b/public/controllers/agent/components/agents-preview.js
index 735126e2d7..1d27b4b359 100644
--- a/public/controllers/agent/components/agents-preview.js
+++ b/public/controllers/agent/components/agents-preview.js
@@ -63,10 +63,13 @@ export const AgentsPreview = compose(
constructor(props) {
super(props);
this.state = {
- loading: false,
- showAgentsEvolutionVisualization: false,
+ loadingAgents: false,
+ loadingSummary: false,
+ showAgentsEvolutionVisualization: true,
agentTableFilters: [],
- agentStatusSummary: {}
+ agentStatusSummary: { active: '-', disconnected: '-', total: '-', pending: '-', never_connected: '-' },
+ agentConfiguration: {},
+ agentsActiveCoverage: 0,
};
this.wazuhConfig = new WazuhConfig();
this.agentStatus = UI_ORDER_AGENT_STATUS.map(agentStatus => ({
@@ -80,8 +83,8 @@ export const AgentsPreview = compose(
this._isMount = true;
this.fetchAgentStatusDetailsData();
if (this.wazuhConfig.getConfig()['wazuh.monitoring.enabled']) {
- this._isMount && this.setState({
- showAgentsEvolutionVisualization: true
+ this._isMount && this.setState({
+ showAgentsEvolutionVisualization: true
});
const tabVisualizations = new TabVisualizations();
tabVisualizations.removeAll();
@@ -106,26 +109,37 @@ export const AgentsPreview = compose(
return prev;
}, {});
};
+ async fetchSummaryStatus() {
+ this.setState({ loadingSummary: true });
+ const {data: {data: { connection: agentStatusSummary, configuration: agentConfiguration }}} = await WzRequest.apiReq('GET', '/agents/summary/status', {});
+ this.props.tableProps.updateSummary(agentStatusSummary);
+ this.setState({
+ loadingSummary: false,
+ agentStatusSummary,
+ agentConfiguration,
+ agentsActiveCoverage: ((agentStatusSummary.active / agentStatusSummary.total) * 100).toFixed(2),
+ });
+ }
+
+ async fetchAgents() {
+ this.setState({ loadingAgents: true });
+ const { data: { data: { affected_items: [lastRegisteredAgent] } } } = await WzRequest.apiReq('GET', '/agents', {
+ params: { limit: 1, sort: '-dateAdd', q: 'id!=000' },
+ });
+ const agentMostActive = await this.props.tableProps.getMostActive();
+ this.setState({
+ loadingAgents: false,
+ lastRegisteredAgent,
+ agentMostActive
+ });
+ }
async fetchAgentStatusDetailsData(){
try {
- this.setState({ loading: true });
- const {data: {data: agentStatusSummary}} = await WzRequest.apiReq('GET', '/agents/summary/status', {});
-
- const {data: {data: {affected_items: [lastRegisteredAgent]}}} = await WzRequest.apiReq('GET', '/agents', {
- params: { limit: 1, sort: '-dateAdd', q: 'id!=000' },
- });
- const agentMostActive = await this.props.tableProps.getMostActive();
-
- this.setState({
- loading: false,
- lastRegisteredAgent,
- agentStatusSummary,
- agentsActiveCoverage: ((agentStatusSummary.active/agentStatusSummary.total)*100).toFixed(2),
- agentMostActive
- });
+ this.fetchSummaryStatus();
+ this.fetchAgents();
} catch (error) {
- this.setState({loading: false});
+ this.setState({ loadingAgents: false, loadingSummary: false });
const options = {
context: `${AgentsPreview.name}.fetchAgentStatusDetailsData`,
level: UI_LOGGER_LEVELS.ERROR,
@@ -155,23 +169,28 @@ export const AgentsPreview = compose(
agentTableFilters: [{ field: 'q', value: `status=${status}` }],
});
}
+ onRenderComplete(){
+ this.setState({
+ evolutionRenderComplete: true
+ })
+ }
render() {
+ const evolutionIsReady = this.props.resultState !== 'loading';
+
return (
- {(this.state.loading && (
-
-
-
- )) || (
+ {
+ (
<>
-
+
{this.agentStatus.map(({status, label, color}) => (
this.filterAgentByStatus(status)} style={{cursor: 'pointer'}}>
@@ -210,22 +230,23 @@ export const AgentsPreview = compose(
))}
+ />
- {this.state.lastRegisteredAgent && (
this.showAgent(this.state.lastRegisteredAgent)}>
- {this.state.lastRegisteredAgent.name}
+ {this.state.lastRegisteredAgent?.name || '-'}
}
@@ -234,36 +255,33 @@ export const AgentsPreview = compose(
titleColor="primary"
/>
- )}
- {this.state.agentMostActive && (
+ {
this.showAgent(this.state.agentMostActive)}>
- {this.state.agentMostActive.name || '-'}
+ {this.state.agentMostActive?.name || '-'}
}
- className="last-agents-link"
titleSize="s"
description="Most active agent"
titleColor="primary"
/>
- )}
+ }
>
)}
- {this.state.showAgentsEvolutionVisualization && (
@@ -272,11 +290,10 @@ export const AgentsPreview = compose(
description
paddingSize="none"
betaBadgeLabel="Evolution"
- style={{ display: this.props.resultState !== 'loading' ? 'block' : 'none' }}
>
-
+
- {this.props.resultState === 'loading' && (
+ {!evolutionIsReady && (
@@ -293,7 +310,6 @@ export const AgentsPreview = compose(
- )}
diff --git a/public/controllers/agent/components/agents-preview.scss b/public/controllers/agent/components/agents-preview.scss
index d4973ceb28..e420ca4e33 100644
--- a/public/controllers/agent/components/agents-preview.scss
+++ b/public/controllers/agent/components/agents-preview.scss
@@ -32,9 +32,6 @@
padding-bottom: 12px;
}
-.p-30 {
-}
-
.loading-chart-xl {
display: block;
text-align: center;
@@ -45,6 +42,7 @@
display: flex;
align-items: baseline;
margin: 15px 0px;
+ flex-wrap: wrap;
}
.columnsSelectedCheckboxs div {
@@ -65,7 +63,7 @@
justify-content: center;
align-items: center;
background-color: rgba(255, 255, 255, 0.75);
-
+
&:hover {
opacity: 1;
}
@@ -97,3 +95,9 @@
user-select: none;
}
}
+
+.agents-status-pie {
+ .euiListGroupItem__label {
+ white-space: nowrap;
+ }
+}
diff --git a/public/controllers/agent/components/agents-table.js b/public/controllers/agent/components/agents-table.js
index 82d6c5e512..ed1ab8dd7f 100644
--- a/public/controllers/agent/components/agents-table.js
+++ b/public/controllers/agent/components/agents-table.js
@@ -23,19 +23,12 @@ import {
EuiPanel,
EuiToolTip,
EuiTitle,
- EuiHealth,
EuiSpacer,
EuiCallOut,
- EuiOverlayMask,
- EuiConfirmModal,
- EuiLoadingSpinner,
EuiCheckboxGroup,
EuiIcon,
} from '@elastic/eui';
-import { CheckUpgrade } from './checkUpgrade';
import { getToasts } from '../../../kibana-services';
-import { WzRequest } from '../../../react-services/wz-request';
-import { ActionAgents } from '../../../react-services/action-agents';
import { AppNavigate } from '../../../react-services/app-navigate';
import { GroupTruncate } from '../../../components/common/util';
import { WzSearchBar, filtersToObject } from '../../../components/wz-search-bar';
@@ -43,10 +36,12 @@ import { getAgentFilterValues } from '../../../controllers/management/components
import { WzButtonPermissions } from '../../../components/common/permissions/button';
import { formatUIDate } from '../../../react-services/time-service';
import { withErrorBoundary } from '../../../components/common/hocs';
-import { API_NAME_AGENT_STATUS, UI_LOGGER_LEVELS, UI_ORDER_AGENT_STATUS } from '../../../../common/constants';
+import { API_NAME_AGENT_STATUS, UI_LOGGER_LEVELS, UI_ORDER_AGENT_STATUS, AGENT_SYNCED_STATUS } from '../../../../common/constants';
import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types';
import { getErrorOrchestrator } from '../../../react-services/common-services';
import { AgentStatus } from '../../../components/agents/agent_status';
+import { AgentSynced } from '../../../components/agents/agent-synced';
+import { compressIPv6 } from '../../../services/ipv6-services';
export const AgentsTable = withErrorBoundary(
class AgentsTable extends Component {
@@ -77,17 +72,24 @@ export const AgentsTable = withErrorBoundary(
operators: ['=', '!='],
values: UI_ORDER_AGENT_STATUS,
},
+ {
+ type: 'q',
+ label: 'group_config_status',
+ description: 'Filter by agent synced configuration status',
+ operators: ['=', '!='],
+ values: [AGENT_SYNCED_STATUS.SYNCED, AGENT_SYNCED_STATUS.NOT_SYNCED],
+ },
{
type: 'q',
label: 'os.platform',
- description: 'Filter by OS platform',
+ description: 'Filter by operating system platform',
operators: ['=', '!='],
values: async (value) => getAgentFilterValues('os.platform', value, { q: 'id!=000' }),
},
{
type: 'q',
label: 'ip',
- description: 'Filter by agent IP',
+ description: 'Filter by agent IP address',
operators: ['=', '!='],
values: async (value) => getAgentFilterValues('ip', value, { q: 'id!=000' }),
},
@@ -165,19 +167,6 @@ export const AgentsTable = withErrorBoundary(
this.downloadCsv.bind(this);
}
- async UNSAFE_componentWillMount() {
- const managerVersion = await WzRequest.apiReq('GET', '/', {});
- const totalAgent = await WzRequest.apiReq('GET', '/agents', {});
- const agentActive = await WzRequest.apiReq('GET', '/agents/summary/status', {});
-
-
- this.setState({
- managerVersion: managerVersion.data.data.api_version,
- avaibleAgents: totalAgent.data.data.affected_items,
- agentActive: agentActive.data.data.active + agentActive.data.data.disconnected,
- });
- }
-
onTableChange = ({ page = {}, sort = {} }) => {
const { index: pageIndex, size: pageSize } = page;
const { field: sortField, direction: sortDirection } = sort;
@@ -229,8 +218,12 @@ export const AgentsTable = withErrorBoundary(
async getItems() {
try {
this._isMount && this.setState({ isLoading: true });
- const rawAgents = await this.props.wzReq('GET', '/agents', { params: this.buildFilter() });
+ const selectFieldsList = this.defaultColumns
+ .filter(field => field.field != 'actions')
+ .map(field => field.field.replace('os_', 'os.')); // "os_name" subfield should be specified as 'os.name'
+ const selectFields = [...selectFieldsList, 'os.platform', 'os.uname', 'os.version'].join(','); // Add version and uname fields to render the OS icon and version in the table
+ const rawAgents = await this.props.wzReq('GET', '/agents', { params: { ...this.buildFilter(), select: selectFields } });
const formatedAgents = (((rawAgents || {}).data || {}).data || {}).affected_items.map(
this.formatAgent.bind(this)
);
@@ -258,37 +251,6 @@ export const AgentsTable = withErrorBoundary(
}
}
- async getAllItems() {
- const { pageIndex, pageSize } = this.state;
- const filterTable = {
- offset: pageIndex * pageSize,
- limit: pageSize,
- q: this.buildQFilter(),
- sort: this.buildSortFilter(),
- };
-
- const filterAll = {
- q: this.buildQFilter(),
- sort: this.buildSortFilter(),
- };
-
- const rawAgents = await this.props.wzReq('GET', '/agents', filterTable);
-
- const agentsFiltered = await this.props.wzReq('GET', '/agents', filterAll).then(() => {
- this._isMount && this.setState({ loadingAllItem: false });
- });
-
- const formatedAgents = (((rawAgents || {}).data || {}).data || {}).items.map(
- this.formatAgent.bind(this)
- );
- this._isMount &&
- this.setState({
- agents: formatedAgents,
- avaibleAgents: agentsFiltered.data.data.items,
- totalItems: (((rawAgents || {}).data || {}).data || {}).totalItems,
- isLoading: false,
- });
- }
buildFilter() {
const { pageIndex, pageSize, filters } = this.state;
@@ -319,18 +281,15 @@ export const AgentsTable = withErrorBoundary(
}
formatAgent(agent) {
- const checkField = (field) => {
- return field !== undefined ? field : '-';
- };
const agentVersion = agent.version !== undefined ? agent.version.split(' ')[1] : '-';
const node_name = agent.node_name && agent.node_name !== 'unknown' ? agent.node_name : '-';
-
return {
id: agent.id,
name: agent.name,
- ip: agent.ip,
+ ip: compressIPv6(agent.ip),
status: agent.status,
- group: checkField(agent.group),
+ group_config_status: agent.group_config_status,
+ group: agent?.group || '-',
os_name: agent,
version: agentVersion,
node_name: node_name,
@@ -374,32 +333,26 @@ export const AgentsTable = withErrorBoundary(
}
addIconPlatformRender(agent) {
- let icon = false;
- const checkField = (field) => {
- return field !== undefined ? field : '-';
- };
- const os = (agent || {}).os;
+ let icon = '';
+ const os = agent?.os || {};
- if (((os || {}).uname || '').includes('Linux')) {
+ if ((os?.uname || '').includes('Linux')) {
icon = 'linux';
- } else if ((os || {}).platform === 'windows') {
+ } else if (os?.platform === 'windows') {
icon = 'windows';
- } else if ((os || {}).platform === 'darwin') {
+ } else if (os?.platform === 'darwin') {
icon = 'apple';
}
- const os_name =
- checkField(((agent || {}).os || {}).name) +
- ' ' +
- checkField(((agent || {}).os || {}).version);
+ const os_name = `${agent?.os?.name || ''} ${agent?.os?.version || ''}`;
return (
-
-
+ {' '}
- {os_name === '- -' ? '-' : os_name}
-
+ >{' '}
+ {os_name.trim() || '-'}
+
);
}
@@ -411,18 +364,6 @@ export const AgentsTable = withErrorBoundary(
this.props.reload();
};
- addUpgradeStatus(version, agent) {
- const { managerVersion } = this.state;
- return (
-
- );
- }
-
downloadCsv = () => {
const filters = this.buildFilter();
const formatedFilters = Object.keys(filters)
@@ -465,156 +406,6 @@ export const AgentsTable = withErrorBoundary(
});
};
- /* MULTISELECT TABLE */
- onSelectionChange = (selectedItems) => {
- const { managerVersion, pageSize } = this.state;
-
- selectedItems.forEach((item) => {
- if (managerVersion > item.version && item.version !== '.') {
- item.outdated = true;
- }
- });
-
- selectedItems.length !== pageSize
- ? this._isMount && this.setState({ allSelected: false })
- : false;
-
- this._isMount && this.setState({ selectedItems });
- };
-
- renderUpgradeButton() {
- const { selectedItems } = this.state;
-
- if (
- selectedItems.length === 0 ||
- (selectedItems.length > 0 && selectedItems.filter((item) => item.outdated).length === 0) ||
- (selectedItems.length > 0 && selectedItems.filter((item) => item.upgrading).length > 0) ||
- (selectedItems.length > 0 &&
- selectedItems.filter((item) => item.status === API_NAME_AGENT_STATUS.ACTIVE).length === 0) ||
- (selectedItems.length > 0 &&
- selectedItems.filter((item) => item.status === API_NAME_AGENT_STATUS.ACTIVE).length === 0 &&
- selectedItems.filter((item) => item.status === API_NAME_AGENT_STATUS.DISCONNECTED).length > 0) ||
- selectedItems.filter((item) => item.outdated && item.status === API_NAME_AGENT_STATUS.ACTIVE).length === 0
- ) {
- return;
- }
-
- return (
-
-
- Upgrade{' '}
- {selectedItems.filter((item) => item.outdated && item.status === API_NAME_AGENT_STATUS.ACTIVE).length}{' '}
- agents
-
-
- );
- }
-
- renderUpgradeButtonAll() {
- const { selectedItems, avaibleAgents, managerVersion } = this.state;
-
- if (
- selectedItems.length > 0 &&
- avaibleAgents.filter(
- (agent) => agent.version !== 'Wazuh ' + managerVersion && agent.status === API_NAME_AGENT_STATUS.ACTIVE
- ).length === 0
- ) {
- return;
- }
-
- return (
-
-
- Upgrade all agents
-
-
- );
- }
-
- renderRestartButton() {
- const { selectedItems } = this.state;
-
- if (
- selectedItems.length === 0 ||
- selectedItems.filter((item) => item.status === API_NAME_AGENT_STATUS.ACTIVE).length === 0
- ) {
- return;
- }
-
- return (
-
-
- Restart {selectedItems.filter((item) => item.status === API_NAME_AGENT_STATUS.ACTIVE).length} agents
-
-
- );
- }
-
- renderRestartButtonAll() {
- const { selectedItems, agentActive, avaibleAgents } = this.state;
-
- if (
- (selectedItems.length > 0 &&
- avaibleAgents.filter((item) => item.status === API_NAME_AGENT_STATUS.ACTIVE).length === 0 &&
- selectedItems.length === 0) ||
- agentActive === 0
- ) {
- return;
- }
-
- return (
-
-
- Restart all agents
-
-
- );
- }
-
- renderPurgeButton() {
- const { selectedItems } = this.state;
-
- if (selectedItems.length === 0) {
- return;
- }
-
- return (
-
- {
- this.setState({ purgeModal: true });
- }}
- >
- Delete {selectedItems.length} agents
-
-
- );
- }
-
- renderPurgeButtonAll() {
- const { selectedItems, allSelected } = this.state;
-
- if (selectedItems.length === 0 && !allSelected) {
- return;
- }
-
- return (
-
- {
- this._isMount && this.setState({ purgeModal: true });
- }}
- >
- Delete all agents
-
-
- );
- }
-
callOutRender() {
const { selectedItems, pageSize, allSelected, totalItems } = this.state;
@@ -661,218 +452,112 @@ export const AgentsTable = withErrorBoundary(
window.localStorage.setItem('columnsSelectedTableAgent', JSON.stringify(data));
}
- setUpgradingState(agentID) {
- const { agents } = this.state;
- agents.forEach((element) => {
- element.id === agentID ? (element.upgrading = true) : false;
- });
- this._isMount && this.setState({ agents });
- }
-
- changeUpgradingState = (agentID) => {
- const { agents } = this.state;
- agents.forEach((element) => {
- element.id === agentID && element.upgrading === true ? (element.upgrading = false) : false;
- });
- this._isMount && this.setState(() => ({ agents }));
- };
-
- onClickUpgrade = () => {
- const { selectedItems } = this.state;
- ActionAgents.upgradeAgents(selectedItems);
- };
-
- onClickUpgradeAll = () => {
- const { avaibleAgents, managerVersion } = this.state;
- ActionAgents.upgradeAllAgents(avaibleAgents, managerVersion);
- };
-
- onClickRestart = () => {
- const { selectedItems } = this.state;
- ActionAgents.restartAgents(selectedItems);
- this.reloadAgents();
- };
-
- onClickRestartAll = () => {
- const { avaibleAgents } = this.state;
- ActionAgents.restartAllAgents(avaibleAgents);
- this.reloadAgents();
- };
-
- onClickPurge = async () => {
- const { selectedItems } = this.state;
- const auxAgents = selectedItems
- .map((agent) => {
- return agent.id !== '000' ? agent.id : null;
- })
- .filter((agent) => agent !== null);
- try {
- const response = await WzRequest.apiReq('DELETE', `/agents`, {
- purge: true,
- ids: auxAgents,
- older_than: '1s',
- });
- response.status === 200
- ? this.showToast('success', `Selected agents were successfully deleted`, '', 5000)
- : this.showToast('warning', `Failed to delete selected agents`, '', 5000);
- } catch (error) {
- const options = {
- context: `${AgentsTable.name}.onClickPurge`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.BUSINESS,
- store: true,
- error: {
- error: error,
- message: error.message || error,
- title: `Failed to delete selected agents`,
- },
- };
- getErrorOrchestrator().handleError(options);
- }
- this.getAllItems();
- this.reloadAgents();
- this._isMount && this.setState({ purgeModal: false });
- };
-
- onClickPurgeAll = () => {
- const { avaibleAgents } = this.state;
- const auxAgents = avaibleAgents
- .map((agent) => {
- return agent.id !== '000' ? agent.id : null;
- })
- .filter((agent) => agent !== null);
- try {
- const response = WzRequest.apiReq('DELETE', `/agents`, {
- purge: true,
- ids: auxAgents,
- older_than: '1s',
- });
- response.status === 200
- ? this.showToast('success', `All agents have been successfully deleted`, '', 5000)
- : this.showToast('warning', `Failed to delete all agents`, '', 5000);
- } catch (error) {
- const options = {
- context: `${AgentsTable.name}.onClickPurgeAll`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.BUSINESS,
- store: true,
- error: {
- error: error,
- message: error.message || error,
- title: `Failed to delete all agents`,
- },
- };
- getErrorOrchestrator().handleError(options);
- }
- this.getAllItems();
- this.reloadAgents();
- this._isMount && this.setState({ purgeModal: false });
- };
+ // Columns with the property truncateText: true won't wrap the text
+ // This is added to prevent the wrap because of the table-layout: auto
+ defaultColumns = [
+ {
+ field: 'id',
+ name: 'ID',
+ sortable: true,
+ show: true,
+ },
+ {
+ field: 'name',
+ name: 'Name',
+ sortable: true,
+ show: true,
+ },
+ {
+ field: 'ip',
+ name: 'IP address',
+ sortable: true,
+ show: true,
+ },
+ {
+ field: 'group',
+ name: 'Group(s)',
+ sortable: true,
+ show: true,
+ render: (groups) => (groups !== '-' ? this.renderGroups(groups) : '-'),
+ },
+ {
+ field: 'os_name',
+ name: 'Operating system',
+ sortable: true,
+ show: true,
+ render: this.addIconPlatformRender,
+ },
+ {
+ field: 'node_name',
+ name: 'Cluster node',
+ sortable: true,
+ show: true,
+ },
+ {
+ field: 'version',
+ name: 'Version',
+ sortable: true,
+ show: true,
+ },
+ {
+ field: 'dateAdd',
+ name: 'Registration date',
+ sortable: true,
+ show: false,
+ },
+ {
+ field: 'lastKeepAlive',
+ name: 'Last keep alive',
+ sortable: true,
+ show: false,
+ },
+ {
+ field: 'status',
+ name: 'Status',
+ truncateText: true,
+ sortable: true,
+ show: true,
+ render: (status) => ,
+ },
+ {
+ field: 'group_config_status',
+ name: 'Synced',
+ sortable: true,
+ show: false,
+ render: (synced) => ,
+ },
+ {
+ align: 'right',
+ width: '5%',
+ field: 'actions',
+ name: 'Actions',
+ show: true,
+ render: (agent) => this.actionButtonsRender(agent),
+ },
+ ];
columns() {
const selectedColumns = this.getTableColumnsSelected();
- const defaultColumns = [
- {
- field: 'id',
- name: 'ID',
- sortable: true,
- width: '6%',
- },
- {
- field: 'name',
- name: 'Name',
- sortable: true,
- width: '15%',
- truncateText: true,
- },
- {
- field: 'ip',
- name: 'IP',
- width: '10%',
- truncateText: true,
- sortable: true,
- },
- {
- field: 'group',
- name: 'Group(s)',
- width: '20%',
- truncateText: true,
- sortable: true,
- render: (groups) => (groups !== '-' ? this.renderGroups(groups) : '-'),
- },
- {
- field: 'os_name',
- name: 'OS',
- sortable: true,
- width: '15%',
- truncateText: true,
- render: this.addIconPlatformRender,
- },
- {
- field: 'node_name',
- name: 'Cluster node',
- width: '10%',
- truncateText: true,
- sortable: true,
- },
- {
- field: 'version',
- name: 'Version',
- width: '5%',
- truncateText: true,
- sortable: true,
- /* render: (version, agent) => this.addUpgradeStatus(version, agent), */
- },
- {
- field: 'dateAdd',
- name: 'Registration date',
- width: '10%',
- truncateText: true,
- sortable: true,
- },
- {
- field: 'lastKeepAlive',
- name: 'Last keep alive',
- width: '10%',
- truncateText: true,
- sortable: true,
- },
- {
- field: 'status',
- name: 'Status',
- truncateText: true,
- sortable: true,
- width: '15%',
- render: (status) => ,
- },
- {
- align: 'right',
- width: '5%',
- field: 'actions',
- name: 'Actions',
- render: (agent) => this.actionButtonsRender(agent),
- },
- ];
if (selectedColumns.length != 0) {
const newSelectedColumns = [];
selectedColumns.forEach((item) => {
if (item.show) {
- const column = defaultColumns.find((column) => column.field === item.field);
+ const column = this.defaultColumns.find((column) => column.field === item.field);
newSelectedColumns.push(column);
}
});
return newSelectedColumns;
} else {
- const fieldColumns = defaultColumns.map((item) => {
+ const fieldColumns = this.defaultColumns.map((item) => {
return {
field: item.field,
name: item.name,
- show: true,
+ show: item.show,
};
});
this.setTableColumnsSelected(fieldColumns);
- return defaultColumns;
+ return fieldColumns;
}
}
@@ -972,7 +657,7 @@ export const AgentsTable = withErrorBoundary(
return {
'data-test-subj': `row-${id}`,
className: 'customRowClass',
- onClick: () => {},
+ onClick: () => { },
};
};
@@ -1001,11 +686,11 @@ export const AgentsTable = withErrorBoundary(
const pagination =
totalItems > 15
? {
- pageIndex: pageIndex,
- pageSize: pageSize,
- totalItemCount: totalItems,
- pageSizeOptions: [15, 25, 50, 100],
- }
+ pageIndex: pageIndex,
+ pageSize: pageSize,
+ totalItemCount: totalItems,
+ pageSizeOptions: [15, 25, 50, 100],
+ }
: false;
const sorting = {
sort: {
@@ -1014,15 +699,14 @@ export const AgentsTable = withErrorBoundary(
},
};
- const selection = {
- selectable: (agent) => agent.id,
- /* onSelectionChange: this.onSelectionChange */
- };
-
+ // The EuiBasicTable tableLayout is set to "auto" to improve the use of empty space in the component.
+ // Previously the tableLayout is set to "fixed" with percentage width for each column, but the use of space was not optimal.
+ // Important: If all the columns have the truncateText property set to true, the table cannot adjust properly when the viewport size is small.
return (
-
+
@@ -1047,8 +729,8 @@ export const AgentsTable = withErrorBoundary(
if (filters.length > 0) {
!auxFilters.includes(group)
? this.setState({
- filters: [...filters, { field: 'q', value: `group=${group}` }],
- })
+ filters: [...filters, { field: 'q', value: `group=${group}` }],
+ })
: false;
} else {
this.setState({
@@ -1071,56 +753,12 @@ export const AgentsTable = withErrorBoundary(
}
render() {
- const { allSelected, purgeModal, selectedItems, loadingAllItem } = this.state;
const title = this.headRender();
const filter = this.filterBarRender();
const selectColumnsRender = this.selectColumnsRender();
- const upgradeButton = this.renderUpgradeButton();
- const restartButton = this.renderRestartButton();
- const purgeButton = this.renderPurgeButton();
- const upgradeButtonAll = this.renderUpgradeButtonAll();
- const restartButtonAll = this.renderRestartButtonAll();
- const purgeButtonAll = this.renderPurgeButtonAll();
const table = this.tableRender();
const callOut = this.callOutRender();
- let renderPurgeModal, loadItems, barButtons;
- if (purgeModal) {
- renderPurgeModal = (
-
- {
- this.setState({ purgeModal: false });
- }}
- onConfirm={allSelected ? this.onClickPurgeAll : this.onClickPurge}
- cancelButtonText="No, don't do it"
- confirmButtonText="Yes, delete agents"
- defaultFocusedButton="confirm"
- buttonColor="danger"
- >
- Are you sure you want to do this?
-
-
- );
- }
-
- if (loadingAllItem) {
- barButtons = (
-
-
-
-
-
- );
- } else {
- barButtons = (
-
- {allSelected ? upgradeButtonAll : upgradeButton}
- {allSelected ? restartButtonAll : restartButton}
- {allSelected ? purgeButtonAll : purgeButton}
-
- );
- }
+ let renderPurgeModal, loadItems;
return (
@@ -1129,7 +767,6 @@ export const AgentsTable = withErrorBoundary(
{title}
{loadItems}
- {selectedItems.length > 0 && barButtons}
{callOut}
{selectColumnsRender}
{table}
diff --git a/public/controllers/agent/components/register-agent-service.test.ts b/public/controllers/agent/components/register-agent-service.test.ts
new file mode 100644
index 0000000000..e61c0bc57a
--- /dev/null
+++ b/public/controllers/agent/components/register-agent-service.test.ts
@@ -0,0 +1,312 @@
+import * as RegisterAgentService from './register-agent-service';
+import { WzRequest } from '../../../react-services/wz-request';
+import { ServerAddressOptions } from '../register-agent/steps';
+
+jest.mock('../../../react-services', () => ({
+ ...(jest.requireActual('../../../react-services') as object),
+ WzRequest: () => ({
+ apiReq: jest.fn(),
+ }),
+}));
+
+const mockedResponseClusterStatus = {
+ data: {
+ data: {
+ enabled: 'yes',
+ running: 'yes',
+ },
+ error: 0,
+ },
+};
+
+describe('Register agent service', () => {
+ beforeEach(() => jest.clearAllMocks());
+ describe('getRemoteConfiguration', () => {
+ it('should return secure connection = TRUE when have connection secure', async () => {
+ const remoteWithSecureAndNoSecure = [
+ {
+ connection: 'syslog',
+ ipv6: 'no',
+ protocol: ['UDP'],
+ port: '514',
+ 'allowed-ips': ['0.0.0.0/0'],
+ },
+ {
+ connection: 'secure',
+ ipv6: 'no',
+ protocol: ['UDP'],
+ port: '1514',
+ queue_size: '131072',
+ },
+ ];
+ const mockedResponse = {
+ data: {
+ data: {
+ affected_items: [
+ {
+ remote: remoteWithSecureAndNoSecure,
+ },
+ ],
+ },
+ },
+ };
+
+ WzRequest.apiReq = jest
+ .fn()
+ .mockResolvedValueOnce(mockedResponseClusterStatus)
+ .mockResolvedValueOnce(mockedResponse);
+ const nodeName = 'example-node';
+ const res = await RegisterAgentService.getRemoteConfiguration(
+ 'example-node',
+ );
+ expect(res.name).toBe(nodeName);
+ expect(res.haveSecureConnection).toBe(true);
+ });
+
+ it('should return secure connection = FALSE available when dont have connection secure', async () => {
+ const remoteWithSecureAndNoSecure = [
+ {
+ connection: 'syslog',
+ ipv6: 'no',
+ protocol: ['UDP', 'TCP'],
+ port: '514',
+ 'allowed-ips': ['0.0.0.0/0'],
+ },
+ ];
+ const mockedResponse = {
+ data: {
+ data: {
+ affected_items: [
+ {
+ remote: remoteWithSecureAndNoSecure,
+ },
+ ],
+ },
+ },
+ };
+ WzRequest.apiReq = jest
+ .fn()
+ .mockResolvedValueOnce(mockedResponseClusterStatus)
+ .mockResolvedValueOnce(mockedResponse);
+ const nodeName = 'example-node';
+ const res = await RegisterAgentService.getRemoteConfiguration(
+ 'example-node',
+ );
+ expect(res.name).toBe(nodeName);
+ expect(res.haveSecureConnection).toBe(false);
+ });
+
+ it('should return protocols UDP when is the only connection protocol available', async () => {
+ const remoteWithSecureAndNoSecure = [
+ {
+ connection: 'syslog',
+ ipv6: 'no',
+ protocol: ['UDP'],
+ port: '514',
+ 'allowed-ips': ['0.0.0.0/0'],
+ },
+ {
+ connection: 'secure',
+ ipv6: 'no',
+ protocol: ['UDP'],
+ port: '1514',
+ queue_size: '131072',
+ },
+ ];
+ const mockedResponse = {
+ data: {
+ data: {
+ affected_items: [
+ {
+ remote: remoteWithSecureAndNoSecure,
+ },
+ ],
+ },
+ },
+ };
+ WzRequest.apiReq = jest
+ .fn()
+ .mockResolvedValueOnce(mockedResponseClusterStatus)
+ .mockResolvedValueOnce(mockedResponse);
+ const nodeName = 'example-node';
+ const res = await RegisterAgentService.getRemoteConfiguration(
+ 'example-node',
+ );
+ expect(res.name).toBe(nodeName);
+ expect(res.isUdp).toEqual(true);
+ });
+
+ it('should return protocols TCP when is the only connection protocol available', async () => {
+ const remoteWithSecureAndNoSecure = [
+ {
+ connection: 'syslog',
+ ipv6: 'no',
+ protocol: ['TCP'],
+ port: '514',
+ 'allowed-ips': ['0.0.0.0/0'],
+ },
+ {
+ connection: 'secure',
+ ipv6: 'no',
+ protocol: ['TCP'],
+ port: '1514',
+ queue_size: '131072',
+ },
+ ];
+ const mockedResponse = {
+ data: {
+ data: {
+ affected_items: [
+ {
+ remote: remoteWithSecureAndNoSecure,
+ },
+ ],
+ },
+ },
+ };
+ WzRequest.apiReq = jest
+ .fn()
+ .mockResolvedValueOnce(mockedResponseClusterStatus)
+ .mockResolvedValueOnce(mockedResponse);
+ const nodeName = 'example-node';
+ const res = await RegisterAgentService.getRemoteConfiguration(
+ 'example-node',
+ );
+ expect(res.name).toBe(nodeName);
+ expect(res.isUdp).toEqual(false);
+ });
+
+ it('should return is not UDP when have UDP and TCP protocols available', async () => {
+ const remoteWithSecureAndNoSecure = [
+ {
+ connection: 'syslog',
+ ipv6: 'no',
+ protocol: ['TCP'],
+ port: '514',
+ 'allowed-ips': ['0.0.0.0/0'],
+ },
+ {
+ connection: 'secure',
+ ipv6: 'no',
+ protocol: ['UDP'],
+ port: '1514',
+ queue_size: '131072',
+ },
+ ];
+ const mockedResponse = {
+ data: {
+ data: {
+ affected_items: [
+ {
+ remote: remoteWithSecureAndNoSecure,
+ },
+ ],
+ },
+ },
+ };
+ WzRequest.apiReq = jest
+ .fn()
+ .mockResolvedValueOnce(mockedResponseClusterStatus)
+ .mockResolvedValueOnce(mockedResponse);
+ const nodeName = 'example-node';
+ const res = await RegisterAgentService.getRemoteConfiguration(
+ 'example-node',
+ );
+ expect(res.name).toBe(nodeName);
+ expect(res.isUdp).toEqual(false);
+ });
+ });
+
+ describe('getConnectionConfig', () => {
+ beforeAll(() => {
+ jest.clearAllMocks();
+ });
+
+ it('should return IS NOT UDP when the server address is typed manually (custom)', async () => {
+ const nodeSelected: ServerAddressOptions = {
+ label: 'node-selected',
+ value: 'node-selected',
+ nodetype: 'master',
+ };
+
+ const remoteWithSecureAndNoSecure = [
+ {
+ connection: 'syslog',
+ ipv6: 'no',
+ protocol: ['UDP'],
+ port: '514',
+ 'allowed-ips': ['0.0.0.0/0'],
+ },
+ {
+ connection: 'secure',
+ ipv6: 'no',
+ protocol: ['UDP'],
+ port: '1514',
+ queue_size: '131072',
+ },
+ ];
+ const mockedResponse = {
+ data: {
+ data: {
+ affected_items: [
+ {
+ remote: remoteWithSecureAndNoSecure,
+ },
+ ],
+ },
+ },
+ };
+ WzRequest.apiReq = jest.fn().mockResolvedValueOnce(mockedResponse);
+
+ const config = await RegisterAgentService.getConnectionConfig(
+ nodeSelected,
+ 'default-dns-address',
+ );
+ expect(config.udpProtocol).toEqual(false);
+ expect(config.serverAddress).toBe('default-dns-address');
+ });
+
+ it('should return IS NOT UDP when the server address is received like default server address dns (custom)', async () => {
+ const nodeSelected: ServerAddressOptions = {
+ label: 'node-selected',
+ value: 'node-selected',
+ nodetype: 'master',
+ };
+
+ const remoteWithSecureAndNoSecure = [
+ {
+ connection: 'syslog',
+ ipv6: 'no',
+ protocol: ['UDP'],
+ port: '514',
+ 'allowed-ips': ['0.0.0.0/0'],
+ },
+ {
+ connection: 'secure',
+ ipv6: 'no',
+ protocol: ['UDP'],
+ port: '1514',
+ queue_size: '131072',
+ },
+ ];
+ const mockedResponse = {
+ data: {
+ data: {
+ affected_items: [
+ {
+ remote: remoteWithSecureAndNoSecure,
+ },
+ ],
+ },
+ },
+ };
+ WzRequest.apiReq = jest.fn().mockResolvedValueOnce(mockedResponse);
+
+ const config = await RegisterAgentService.getConnectionConfig(
+ nodeSelected,
+ 'custom-server-address',
+ );
+ expect(config.udpProtocol).toEqual(false);
+ });
+ });
+});
diff --git a/public/controllers/agent/components/register-agent-service.ts b/public/controllers/agent/components/register-agent-service.ts
new file mode 100644
index 0000000000..c7ed1235fd
--- /dev/null
+++ b/public/controllers/agent/components/register-agent-service.ts
@@ -0,0 +1,213 @@
+import { WzRequest } from '../../../react-services/wz-request';
+import { ServerAddressOptions } from '../register-agent/steps';
+
+type Protocol = 'TCP' | 'UDP';
+
+type RemoteItem = {
+ connection: 'syslog' | 'secure';
+ ipv6: 'yes' | 'no';
+ protocol: Protocol[];
+ allowed_ips?: string[];
+ queue_size?: string;
+};
+
+type RemoteConfig = {
+ name: string;
+ isUdp: boolean | null;
+ haveSecureConnection: boolean | null;
+};
+
+/**
+ * Get the cluster status
+ */
+export const clusterStatusResponse = async (): Promise => {
+ const clusterStatus = await WzRequest.apiReq('GET', '/cluster/status', {});
+ if (
+ clusterStatus.data.data.enabled === 'yes' &&
+ clusterStatus.data.data.running === 'yes'
+ ) {
+ // Cluster mode
+ return true;
+ } else {
+ // Manager mode
+ return false;
+ }
+};
+
+/**
+ * Get the remote configuration from api
+ */
+async function getRemoteConfiguration(nodeName: string): Promise {
+ let config: RemoteConfig = {
+ name: nodeName,
+ isUdp: null,
+ haveSecureConnection: null,
+ };
+ const clusterStatus = await clusterStatusResponse();
+ let result;
+ if (clusterStatus) {
+ result = await WzRequest.apiReq(
+ 'GET',
+ `/cluster/${nodeName}/configuration/request/remote`,
+ {},
+ );
+ } else {
+ result = await WzRequest.apiReq(
+ 'GET',
+ '/manager/configuration/request/remote',
+ {},
+ );
+ }
+ const items = ((result.data || {}).data || {}).affected_items || [];
+ const remote = items[0]?.remote;
+ if (remote) {
+ const remoteFiltered = remote.filter((item: RemoteItem) => {
+ return item.connection === 'secure';
+ });
+
+ remoteFiltered.length > 0
+ ? (config.haveSecureConnection = true)
+ : (config.haveSecureConnection = false);
+
+ let protocolsAvailable: Protocol[] = [];
+ remote.forEach((item: RemoteItem) => {
+ // get all protocols available
+ item.protocol.forEach(protocol => {
+ protocolsAvailable = protocolsAvailable.concat(protocol);
+ });
+ });
+
+ config.isUdp =
+ getRemoteProtocol(protocolsAvailable) === 'UDP' ? true : false;
+ }
+ return config;
+}
+
+/**
+ * Get the remote protocol available from list of protocols
+ * @param protocols
+ */
+function getRemoteProtocol(protocols: Protocol[]) {
+ if (protocols.length === 1) {
+ return protocols[0];
+ } else {
+ return !protocols.includes('TCP') ? 'UDP' : 'TCP';
+ }
+}
+
+/**
+ * Get the remote configuration from nodes registered in the cluster and decide the protocol to setting up in deploy agent param
+ * @param nodeSelected
+ * @param defaultServerAddress
+ */
+async function getConnectionConfig(
+ nodeSelected: ServerAddressOptions,
+ defaultServerAddress?: string,
+) {
+ const nodeName = nodeSelected?.label;
+ const nodeIp = nodeSelected?.value;
+ if(!defaultServerAddress){
+ if(nodeSelected.nodetype !== 'custom'){
+ const remoteConfig = await getRemoteConfiguration(nodeName);
+ return { serverAddress: nodeIp, udpProtocol: remoteConfig.isUdp, connectionSecure: remoteConfig.haveSecureConnection };
+ }else{
+ return { serverAddress: nodeName, udpProtocol: false, connectionSecure: true };
+ }
+ } else {
+ return {
+ serverAddress: defaultServerAddress,
+ udpProtocol: false,
+ connectionSecure: true,
+ };
+ }
+}
+
+type NodeItem = {
+ name: string;
+ ip: string;
+ type: string;
+};
+
+type NodeResponse = {
+ data: {
+ data: {
+ affected_items: NodeItem[];
+ };
+ };
+};
+
+/**
+ * Get the list of the cluster nodes and parse it into a list of options
+ */
+export const getNodeIPs = async (): Promise => {
+ return await WzRequest.apiReq('GET', '/cluster/nodes', {});
+};
+
+/**
+ * Get the list of the manager and parse it into a list of options
+ */
+export const getManagerNode = async (): Promise => {
+ const managerNode = await WzRequest.apiReq('GET', '/manager/api/config', {});
+ return managerNode?.data?.data?.affected_items?.map(item => ({
+ label: item.node_name,
+ value: item.node_api_config.host,
+ nodetype: 'master',
+ })) || [];
+};
+
+/**
+ * Parse the nodes list from the API response to a format that can be used by the EuiComboBox
+ * @param nodes
+ */
+export const parseNodesInOptions = (
+ nodes: NodeResponse,
+): ServerAddressOptions[] => {
+ return nodes.data.data.affected_items.map((item: NodeItem) => ({
+ label: item.name,
+ value: item.ip,
+ nodetype: item.type,
+ }));
+};
+
+/**
+ * Get the list of the cluster nodes from API and parse it into a list of options
+ */
+export const fetchClusterNodesOptions = async (): Promise<
+ ServerAddressOptions[]
+> => {
+ const clusterStatus = await clusterStatusResponse();
+ if (clusterStatus) {
+ // Cluster mode
+ // Get the cluster nodes
+ const nodes = await getNodeIPs();
+ return parseNodesInOptions(nodes);
+ } else {
+ // Manager mode
+ // Get the manager node
+ return await getManagerNode();
+ }
+};
+
+/**
+ * Get the master node data from the list of cluster nodes
+ * @param nodeIps
+ */
+export const getMasterNode = (
+ nodeIps: ServerAddressOptions[],
+): ServerAddressOptions[] => {
+ return nodeIps.filter(nodeIp => nodeIp.nodetype === 'master');
+};
+
+/**
+ * Get the remote configuration from manager
+ * This function get the config from manager mode or cluster mode
+ */
+export const getMasterRemoteConfiguration = async () => {
+ const nodes = await fetchClusterNodesOptions();
+ const masterNode = getMasterNode(nodes);
+ return await getRemoteConfiguration(masterNode[0].label);
+}
+
+
+
+export { getConnectionConfig, getRemoteConfiguration };
diff --git a/public/controllers/agent/components/register-agent.js b/public/controllers/agent/components/register-agent.js
index 7f11c445f7..a46227d5aa 100644
--- a/public/controllers/agent/components/register-agent.js
+++ b/public/controllers/agent/components/register-agent.js
@@ -18,7 +18,6 @@ import {
EuiFlexGroup,
EuiFlexItem,
EuiPanel,
- EuiButtonGroup,
EuiComboBox,
EuiFieldText,
EuiText,
@@ -31,10 +30,11 @@ import {
EuiCallOut,
EuiSpacer,
EuiProgress,
- EuiCode,
- EuiLink,
EuiIcon,
- EuiSwitch
+ EuiSwitch,
+ EuiLink,
+ EuiFormRow,
+ EuiForm,
} from '@elastic/eui';
import { WzRequest } from '../../../react-services/wz-request';
import { withErrorBoundary } from '../../../components/common/hocs';
@@ -42,92 +42,51 @@ import { UI_LOGGER_LEVELS } from '../../../../common/constants';
import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types';
import { getErrorOrchestrator } from '../../../react-services/common-services';
import { webDocumentationLink } from '../../../../common/services/web_documentation';
-
-const architectureButtons = [
- {
- id: 'i386',
- label: 'i386',
- },
- {
- id: 'x86_64',
- label: 'x86_64',
- },
- {
- id: 'armhf',
- label: 'armhf',
- },
- {
- id: 'aarch64',
- label: 'aarch64',
- },
-];
-const architectureCentos5OrRedHat5 = [
- {
- id: 'i386',
- label: 'i386',
- },
- {
- id: 'x86_64',
- label: 'x86_64',
- },
-];
-
-const versionButtonsCentosOrRedHat = [
- {
- id: 'centos5',
- label: 'CentOS5',
- },
- {
- id: 'centos6',
- label: 'CentOS6 or higher',
- },
- {
- id: 'redhat5',
- label: 'Red Hat 5',
- },
- {
- id: 'redhat6',
- label: 'Red Hat 6 or higher',
- },
-];
-
-const osButtons = [
- {
- id: 'rpm',
- label: 'Red Hat / CentOS',
- },
- {
- id: 'deb',
- label: 'Debian / Ubuntu',
- },
- {
- id: 'win',
- label: 'Windows',
- },
- {
- id: 'macos',
- label: 'MacOS',
- },
-];
-
-const sysButtons = [
- {
- id: 'systemd',
- label: 'Systemd',
- },
- {
- id: 'sysV',
- label: 'SysV Init',
- },
-];
+import {
+ architectureButtons,
+ architectureButtonsi386,
+ architecturei386Andx86_64,
+ versionButtonsRaspbian,
+ versionButtonsSuse,
+ versionButtonsOracleLinux,
+ versionButtonFedora,
+ architectureButtonsSolaris,
+ architectureButtonsWithPPC64LE,
+ architectureButtonsAix,
+ architectureButtonsHpUx,
+ versionButtonAmazonLinux,
+ versionButtonsRedHat,
+ versionButtonsCentos,
+ architectureButtonsMacos,
+ osPrincipalButtons,
+ versionButtonsDebian,
+ versionButtonsUbuntu,
+ versionButtonsWindows,
+ versionButtonsMacOS,
+ versionButtonsOpenSuse,
+ versionButtonsSolaris,
+ versionButtonsAix,
+ versionButtonsHPUX,
+ versionButtonAlpine,
+ architectureButtonsWithPPC64LEAlpine,
+} from '../wazuh-config';
+import './register-agent.scss';
+import WzManagerAddressInput from '../register-agent/steps/wz-manager-address';
+import {
+ getMasterRemoteConfiguration
+} from './register-agent-service';
+import { PrincipalButtonGroup } from './wz-accordion';
+import RegisterAgentButtonGroup from '../register-agent/register-agent-button-group';
+import '../../../styles/common.scss';
export const RegisterAgent = withErrorBoundary(
-
class RegisterAgent extends Component {
constructor(props) {
super(props);
this.wazuhConfig = new WazuhConfig();
this.configuration = this.wazuhConfig.getConfig();
+ this.addToVersion = '-1';
+
this.state = {
status: 'incomplete',
selectedOS: '',
@@ -138,51 +97,78 @@ export const RegisterAgent = withErrorBoundary(
version: '',
wazuhVersion: '',
serverAddress: '',
+ agentName: '',
+ agentNameError: false,
+ badCharacters: [],
wazuhPassword: '',
groups: [],
selectedGroup: [],
+ defaultServerAddress: '',
udpProtocol: false,
showPassword: false,
+ showProtocol: true,
+ connectionSecure: true,
+ isAccordionOpen: false,
};
this.restartAgentCommand = {
rpm: this.systemSelector(),
+ cent: this.systemSelector(),
deb: this.systemSelector(),
- macos: 'sudo /Library/Ossec/bin/wazuh-control start',
- win: 'NET START WazuhSvc'
+ ubu: this.systemSelector(),
+ oraclelinux: this.systemSelector(),
+ macos: this.systemSelectorWazuhControlMacos(),
+ win: this.systemSelectorNet(),
};
}
+
async componentDidMount() {
try {
this.setState({ loading: true });
const wazuhVersion = await this.props.getWazuhVersion();
- let serverAddress = false;
let wazuhPassword = '';
let hidePasswordInput = false;
- serverAddress = this.configuration['enrollment.dns'] || false;
- if (!serverAddress) {
- serverAddress = await this.props.getCurrentApiAddress();
- }
+ this.getEnrollDNSConfig();
+ await this.getRemoteConfig();
let authInfo = await this.getAuthInfo();
const needsPassword = (authInfo.auth || {}).use_password === 'yes';
if (needsPassword) {
- wazuhPassword = this.configuration['enrollment.password'] || authInfo['authd.pass'] || '';
+ wazuhPassword =
+ this.configuration['enrollment.password'] ||
+ authInfo['authd.pass'] ||
+ '';
if (wazuhPassword) {
hidePasswordInput = true;
}
}
-
- const udpProtocol = await this.getRemoteInfo();
const groups = await this.getGroups();
this.setState({
- serverAddress,
needsPassword,
hidePasswordInput,
- versionButtonsCentosOrRedHat,
+ versionButtonsRedHat,
+ versionButtonsCentos,
+ versionButtonsDebian,
+ versionButtonsUbuntu,
+ versionButtonsWindows,
+ versionButtonsMacOS,
+ versionButtonsOpenSuse,
+ versionButtonsSolaris,
+ versionButtonAmazonLinux,
+ versionButtonsSuse,
+ versionButtonsAix,
+ versionButtonsHPUX,
+ versionButtonsOracleLinux,
+ versionButtonsRaspbian,
+ versionButtonFedora,
architectureButtons,
- architectureCentos5OrRedHat5,
+ architectureButtonsi386,
+ architecturei386Andx86_64,
+ architectureButtonsSolaris,
+ architectureButtonsAix,
+ architectureButtonsHpUx,
+ architectureButtonsMacos,
+ architectureButtonsWithPPC64LE,
wazuhPassword,
- udpProtocol,
wazuhVersion,
groups,
loading: false,
@@ -196,7 +182,7 @@ export const RegisterAgent = withErrorBoundary(
context: `${RegisterAgent.name}.componentDidMount`,
level: UI_LOGGER_LEVELS.ERROR,
severity: UI_ERROR_SEVERITIES.BUSINESS,
- display: false,
+ display: true,
store: false,
error: {
error: error,
@@ -208,22 +194,34 @@ export const RegisterAgent = withErrorBoundary(
}
}
- async getAuthInfo() {
- try {
- const result = await WzRequest.apiReq('GET', '/agents/000/config/auth/auth', {});
- return (result.data || {}).data || {};
- } catch (error) {
- this.setState({ gotErrorRegistrationServiceInfo: true });
- throw new Error(error);
+ getEnrollDNSConfig = () => {
+ const serverAddress = this.configuration['enrollment.dns'] || '';
+ this.setState({ defaultServerAddress: serverAddress });
+ };
+
+ getRemoteConfig = async () => {
+ const remoteConfig = await getMasterRemoteConfiguration();
+ if (remoteConfig) {
+ this.setState({
+ haveUdpProtocol: remoteConfig.isUdp,
+ haveConnectionSecure: remoteConfig.isSecure,
+ udpProtocol: remoteConfig.isUdp,
+ connectionSecure: remoteConfig.isSecure,
+ })
}
}
- async getRemoteInfo() {
+
+ async getAuthInfo() {
try {
- const result = await WzRequest.apiReq('GET', '/agents/000/config/request/remote', {});
- const remote = ((result.data || {}).data || {}).remote || {};
- return (remote[0] || {}).protocol !== 'tcp' && (remote[0] || {}).protocol[0] !== 'TCP';
+ const result = await WzRequest.apiReq(
+ 'GET',
+ '/agents/000/config/auth/auth',
+ {},
+ );
+ return (result.data || {}).data || {};
} catch (error) {
+ this.setState({ gotErrorRegistrationServiceInfo: true });
throw new Error(error);
}
}
@@ -233,19 +231,72 @@ export const RegisterAgent = withErrorBoundary(
selectedOS: os,
selectedVersion: '',
selectedArchitecture: '',
- selectedSYS: 'systemd',
+ selectedSYS: '',
});
}
systemSelector() {
- if (this.state.selectedOS === 'rpm') {
- if (this.state.selectedSYS === 'systemd') {
- return 'sudo systemctl daemon-reload\nsudo systemctl enable wazuh-agent\nsudo systemctl start wazuh-agent';
- } else return 'sudo chkconfig --add wazuh-agent\nsudo service wazuh-agent start';
- } else if (this.state.selectedOS === 'deb') {
- if (this.state.selectedSYS === 'systemd') {
- return 'sudo systemctl daemon-reload\nsudo systemctl enable wazuh-agent\nsudo systemctl start wazuh-agent';
- } else return 'sudo update-rc.d wazuh-agent defaults 95 10\nsudo service wazuh-agent start';
+ if (
+ this.state.selectedVersion === 'redhat7' ||
+ this.state.selectedVersion === 'amazonlinux2022' ||
+ this.state.selectedVersion === 'centos7' ||
+ this.state.selectedVersion === 'suse11' ||
+ this.state.selectedVersion === 'suse12' ||
+ this.state.selectedVersion === 'oraclelinux5' ||
+ this.state.selectedVersion === '22' ||
+ this.state.selectedVersion === 'amazonlinux2' ||
+ this.state.selectedVersion === 'debian8' ||
+ this.state.selectedVersion === 'debian9' ||
+ this.state.selectedVersion === 'debian10' ||
+ this.state.selectedVersion === 'busterorgreater' ||
+ this.state.selectedVersion === 'ubuntu15' ||
+ this.state.selectedVersion === 'leap15'
+ ) {
+ return 'sudo systemctl daemon-reload\nsudo systemctl enable wazuh-agent\nsudo systemctl start wazuh-agent';
+ } else if (
+ this.state.selectedVersion === 'redhat5' ||
+ this.state.selectedVersion === 'redhat6' ||
+ this.state.selectedVersion === 'centos5' ||
+ this.state.selectedVersion === 'centos6' ||
+ this.state.selectedVersion === 'oraclelinux6' ||
+ this.state.selectedVersion === 'amazonlinux1' ||
+ this.state.selectedVersion === 'debian7' ||
+ this.state.selectedVersion === 'ubuntu14'
+ ) {
+ return 'service wazuh-agent start';
+ } else return '';
+ }
+
+ systemSelectorNet() {
+ if (
+ this.state.selectedVersion === 'windowsxp' ||
+ this.state.selectedVersion === 'windowsserver2008' ||
+ this.state.selectedVersion === 'windows7'
+ ) {
+ return 'NET START WazuhSvc';
+ } else return '';
+ }
+
+ systemSelectorWazuhControlMacos() {
+ if (this.state.selectedVersion == 'sierra') {
+ return '/Library/Ossec/bin/wazuh-control start';
+ } else return '';
+ }
+
+ systemSelectorWazuhControl() {
+ if (
+ this.state.selectedVersion === 'solaris10' ||
+ this.state.selectedVersion === 'solaris11' ||
+ this.state.selectedVersion === '6.1 TL9' ||
+ this.state.selectedVersion === '3.12.12'
+ ) {
+ return '/var/ossec/bin/wazuh-control start';
+ } else return '';
+ }
+
+ systemSelectorInitD() {
+ if (this.state.selectedVersion === '11.31') {
+ return '/sbin/init.d/wazuh-agent start';
} else return '';
}
@@ -253,8 +304,37 @@ export const RegisterAgent = withErrorBoundary(
this.setState({ selectedSYS: sys });
}
- setServerAddress(event) {
- this.setState({ serverAddress: event.target.value });
+ setServerAddress(serverAddress) {
+ this.setState({ serverAddress });
+ }
+
+ setAgentName(event) {
+ const validation = /^[a-z0-9-_.]+$/i;
+ if (
+ (validation.test(event.target.value) &&
+ event.target.value.length >= 2) ||
+ event.target.value.length <= 0
+ ) {
+ this.setState({
+ agentName: event.target.value,
+ agentNameError: false,
+ badCharacters: [],
+ });
+ } else {
+ let badCharacters = event.target.value
+ .split('')
+ .map(char => char.replace(validation, ''))
+ .join('');
+ badCharacters = badCharacters
+ .split('')
+ .map(char => char.replace(/\s/, 'whitespace'));
+ const characters = [...new Set(badCharacters)];
+ this.setState({
+ agentName: event.target.value,
+ badCharacters: characters,
+ agentNameError: true,
+ });
+ }
}
setGroupName(selectedGroup) {
@@ -292,15 +372,19 @@ export const RegisterAgent = withErrorBoundary(
async getGroups() {
try {
const result = await WzRequest.apiReq('GET', '/groups', {});
- return result.data.data.affected_items.map((item) => ({ label: item.name, id: item.name }));
+ return result.data.data.affected_items.map(item => ({
+ label: item.name,
+ id: item.name,
+ }));
} catch (error) {
throw new Error(error);
}
}
optionalDeploymentVariables() {
- let deployment = `WAZUH_MANAGER='${this.state.serverAddress}' `;
-
+ let deployment =
+ this.state.serverAddress &&
+ `WAZUH_MANAGER='${this.state.serverAddress}' `;
if (this.state.selectedOS == 'win') {
deployment += `WAZUH_REGISTRATION_SERVER='${this.state.serverAddress}' `;
}
@@ -310,12 +394,12 @@ export const RegisterAgent = withErrorBoundary(
}
if (this.state.udpProtocol) {
- deployment += `WAZUH_PROTOCOL='UDP' `;
+ deployment += "WAZUH_PROTOCOL='UDP' ";
}
if (this.state.selectedGroup.length) {
deployment += `WAZUH_AGENT_GROUP='${this.state.selectedGroup
- .map((item) => item.label)
+ .map(item => item.label)
.join(',')}' `;
}
@@ -327,49 +411,317 @@ export const RegisterAgent = withErrorBoundary(
return deployment;
}
+ agentNameVariable() {
+ let agentName = `WAZUH_AGENT_NAME='${this.state.agentName}' `;
+ if (
+ this.state.selectedOS === 'macos' &&
+ this.state.selectedArchitecture &&
+ this.state.agentName !== ''
+ ) {
+ return agentName.replace(/=/g, ' ');
+ }
+ if (this.state.selectedArchitecture && this.state.agentName !== '') {
+ return agentName;
+ } else {
+ return '';
+ }
+ }
+
resolveRPMPackage() {
- switch (`${this.state.selectedVersion}-${this.state.selectedArchitecture}`) {
- case 'centos5-i386':
- return `https://packages.wazuh.com/4.x/yum5/i386/wazuh-agent-${this.state.wazuhVersion}-1.el5.i386.rpm`;
- case 'centos5-x86_64':
- return `https://packages.wazuh.com/4.x/yum5/x86_64/wazuh-agent-${this.state.wazuhVersion}-1.el5.x86_64.rpm`;
+ switch (
+ `${this.state.selectedVersion}-${this.state.selectedArchitecture}`
+ ) {
case 'redhat5-i386':
- return `https://packages.wazuh.com/4.x/yum5/i386/wazuh-agent-${this.state.wazuhVersion}-1.el5.i386.rpm`;
+ return `https://packages.wazuh.com/4.x/yum5/i386/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.el5.i386.rpm`;
case 'redhat5-x86_64':
- return `https://packages.wazuh.com/4.x/yum5/x86_64/wazuh-agent-${this.state.wazuhVersion}-1.el5.x86_64.rpm`;
- case 'centos6-i386':
- return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.i386.rpm`;
- case 'centos6-aarch64':
- return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.aarch64.rpm`;
- case 'centos6-x86_64':
- return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.x86_64.rpm`;
- case 'centos6-armhf':
- return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.armv7hl.rpm`;
+ return `https://packages.wazuh.com/4.x/yum5/x86_64/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.el5.x86_64.rpm`;
case 'redhat6-i386':
- return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.i386.rpm`;
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.i386.rpm`;
case 'redhat6-aarch64':
- return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.aarch64.rpm`;
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.aarch64.rpm`;
case 'redhat6-x86_64':
- return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.x86_64.rpm`;
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
case 'redhat6-armhf':
- return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.armv7hl.rpm`;
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.armv7hl.rpm`;
+ case 'redhat7-i386':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.i386.rpm`;
+ case 'redhat7-aarch64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.aarch64.rpm`;
+ case 'redhat7-x86_64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ case 'redhat7-armhf':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.armv7hl.rpm`;
+ case 'redhat7-powerpc':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.ppc64le.rpm`;
+ default:
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ }
+ }
+
+ resolveAlpinePackage() {
+ switch (
+ `${this.state.selectedVersion}-${this.state.selectedArchitecture}`
+ ) {
+ case '3.12.12-i386':
+ return 'https://packages.wazuh.com/key/alpine-devel%40wazuh.com-633d7457.rsa.pub && echo "https://packages.wazuh.com/4.x/alpine/v3.12/main"';
+ case '3.12.12-aarch64':
+ return 'https://packages.wazuh.com/key/alpine-devel%40wazuh.com-633d7457.rsa.pub && echo "https://packages.wazuh.com/4.x/alpine/v3.12/main"';
+ case '3.12.12-x86_64':
+ return 'https://packages.wazuh.com/key/alpine-devel%40wazuh.com-633d7457.rsa.pub && echo "https://packages.wazuh.com/4.x/alpine/v3.12/main"';
+ case '3.12.12-x86':
+ return 'https://packages.wazuh.com/key/alpine-devel%40wazuh.com-633d7457.rsa.pub && echo "https://packages.wazuh.com/4.x/alpine/v3.12/main"';
+ case '3.12.12-armhf':
+ return 'https://packages.wazuh.com/key/alpine-devel%40wazuh.com-633d7457.rsa.pub && echo "https://packages.wazuh.com/4.x/alpine/v3.12/main"';
+ case '3.12.12-powerpc':
+ return 'https://packages.wazuh.com/key/alpine-devel%40wazuh.com-633d7457.rsa.pub && echo "https://packages.wazuh.com/4.x/alpine/v3.12/main"';
+ default:
+ return 'https://packages.wazuh.com/key/alpine-devel%40wazuh.com-633d7457.rsa.pub && echo "https://packages.wazuh.com/4.x/alpine/v3.12/main"';
+ }
+ }
+
+ resolveORACLELINUXPackage() {
+ switch (
+ `${this.state.selectedVersion}-${this.state.selectedArchitecture}`
+ ) {
+ case 'oraclelinux5-i386':
+ return `https://packages.wazuh.com/4.x/yum5/i386/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.el5.i386.rpm`;
+ case 'oraclelinux5-x86_64':
+ return `https://packages.wazuh.com/4.x/yum5/x86_64/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.el5.x86_64.rpm`;
+ case 'oraclelinux6-i386':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.i386.rpm`;
+ case 'oraclelinux6-aarch64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.aarch64.rpm`;
+ case 'oraclelinux6-x86_64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ case 'oraclelinux6-armhf':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.armv7hl.rpm`;
+ default:
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ }
+ }
+
+ resolveCENTPackage() {
+ switch (
+ `${this.state.selectedVersion}-${this.state.selectedArchitecture}`
+ ) {
+ case 'centos5-i386':
+ return `https://packages.wazuh.com/4.x/yum5/i386/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.el5.i386.rpm`;
+ case 'centos5-x86_64':
+ return `https://packages.wazuh.com/4.x/yum5/x86_64/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.el5.x86_64.rpm`;
+ case 'centos6-i386':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.i386.rpm`;
+ case 'centos6-aarch64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.aarch64.rpm`;
+ case 'centos6-x86_64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ case 'centos6-armhf':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.armv7hl.rpm`;
+ case 'centos7-i386':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.i386.rpm`;
+ case 'centos7-aarch64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.aarch64.rpm`;
+ case 'centos7-x86_64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ case 'centos7-armhf':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.armv7hl.rpm`;
+ case 'centos7-powerpc':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.ppc64le.rpm`;
+ default:
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ }
+ }
+
+ resolveSUSEPackage() {
+ switch (
+ `${this.state.selectedVersion}-${this.state.selectedArchitecture}`
+ ) {
+ case 'suse11-i386':
+ return `https://packages.wazuh.com/4.x/yum5/i386/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.el5.i386.rpm`;
+ case 'suse11-x86_64':
+ return `https://packages.wazuh.com/4.x/yum5/x86_64/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.el5.x86_64.rpm`;
+ case 'suse12-i386':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.i386.rpm`;
+ case 'suse12-aarch64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.aarch64.rpm`;
+ case 'suse12-x86_64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ case 'suse12-armhf':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.armv7hl.rpm`;
+ case 'suse12-powerpc':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.ppc64le.rpm`;
default:
- return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.x86_64.rpm`;
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ }
+ }
+
+ resolveFEDORAPachage() {
+ switch (
+ `${this.state.selectedVersion}-${this.state.selectedArchitecture}`
+ ) {
+ case '22-i386':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.i386.rpm`;
+ case '22-aarch64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.aarch64.rpm`;
+ case '22-x86_64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ case '22-armhf':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.armv7hl.rpm`;
+ case '22-powerpc':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.ppc64le.rpm`;
+ default:
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ }
+ }
+
+ resolveAMAZONLPackage() {
+ switch (
+ `${this.state.selectedVersion}-${this.state.selectedArchitecture}`
+ ) {
+ case 'amazonlinux1-i386':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.i386.rpm`;
+ case 'amazonlinux1-aarch64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.aarch64.rpm`;
+ case 'amazonlinux1-x86_64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ case 'amazonlinux1-armhf':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.armv7hl.rpm`;
+ case 'amazonlinux2-i386':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.i386.rpm`;
+ case 'amazonlinux2-aarch64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.aarch64.rpm`;
+ case 'amazonlinux2-x86_64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ case 'amazonlinux2-armhf':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.armv7hl.rpm`;
+ case 'amazonlinux2022-i386':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.i386.rpm`;
+ case 'amazonlinux2022-aarch64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.aarch64.rpm`;
+ case 'amazonlinux2022-x86_64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ case 'amazonlinux2022-armhf':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.armv7hl.rpm`;
+ default:
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
}
}
resolveDEBPackage() {
switch (`${this.state.selectedArchitecture}`) {
case 'i386':
- return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_i386.deb`;
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_i386.deb`;
case 'aarch64':
- return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_arm64.deb`;
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_arm64.deb`;
case 'armhf':
- return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_armhf.deb`;
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_armhf.deb`;
case 'x86_64':
- return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_amd64.deb`;
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_amd64.deb`;
+ case 'powerpc':
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_ppc64el.deb`;
+ default:
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_amd64.deb`;
+ }
+ }
+
+ resolveRASPBIANPackage() {
+ switch (
+ `${this.state.selectedVersion}-${this.state.selectedArchitecture}`
+ ) {
+ case 'busterorgreater-i386':
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_i386.deb`;
+ case 'busterorgreater-aarch64':
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_arm64.deb`;
+ case 'busterorgreater-armhf':
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_armhf.deb`;
+ case 'busterorgreater-x86_64':
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_amd64.deb`;
+ case 'busterorgreater-powerpc':
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_ppc64el.deb`;
+ default:
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_amd64.deb`;
+ }
+ }
+
+ resolveUBUNTUPackage() {
+ switch (
+ `${this.state.selectedVersion}-${this.state.selectedArchitecture}`
+ ) {
+ case 'ubuntu14-i386':
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_i386.deb`;
+ case 'ubuntu14-aarch64':
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_arm64.deb`;
+ case 'ubuntu14-armhf':
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_armhf.deb`;
+ case 'ubuntu14-x86_64':
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_amd64.deb`;
+ case 'ubuntu15-i386':
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_i386.deb`;
+ case 'ubuntu15-aarch64':
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_arm64.deb`;
+ case 'ubuntu15-armhf':
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_armhf.deb`;
+ case 'ubuntu15-x86_64':
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_amd64.deb`;
+ default:
+ return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}${this.addToVersion}_amd64.deb`;
+ }
+ }
+
+ resolveOPENSUSEPackage() {
+ switch (
+ `${this.state.selectedVersion}-${this.state.selectedArchitecture}`
+ ) {
+ case 'leap15-i386':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.i386.rpm`;
+ case 'leap15-aarch64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.aarch64.rpm`;
+ case 'leap15-x86_64':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ case 'leap15-armhf':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.armv7hl.rpm`;
+ case 'leap15-powerpc':
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.ppc64le.rpm`;
+ default:
+ return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
+ }
+ }
+
+ resolveSOLARISPackage() {
+ switch (
+ `${this.state.selectedVersion}-${this.state.selectedArchitecture}`
+ ) {
+ case 'solaris10-i386':
+ return `https://packages.wazuh.com/4.x/solaris/i386/10/wazuh-agent_v${this.state.wazuhVersion}-sol10-i386.pkg`;
+ case 'solaris10-sparc':
+ return `https://packages.wazuh.com/4.x/solaris/sparc/10/wazuh-agent_v${this.state.wazuhVersion}-sol10-sparc.pkg`;
+ case 'solaris11-i386':
+ return `https://packages.wazuh.com/4.x/solaris/i386/11/wazuh-agent_v${this.state.wazuhVersion}-sol11-i386.p5p`;
+ case 'solaris11-sparc':
+ return `https://packages.wazuh.com/4.x/solaris/sparc/11/wazuh-agent_v${this.state.wazuhVersion}-sol11-sparc.p5p`;
+ default:
+ return `https://packages.wazuh.com/4.x/solaris/sparc/11/wazuh-agent_v${this.state.wazuhVersion}-sol11-sparc.p5p`;
+ }
+ }
+
+ resolveAIXPackage() {
+ switch (
+ `${this.state.selectedVersion}-${this.state.selectedArchitecture}`
+ ) {
+ case '6.1 TL9-powerpc':
+ return `https://packages.wazuh.com/4.x/aix/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.aix.ppc.rpm`;
+ default:
+ return `https://packages.wazuh.com/4.x/aix/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.aix.ppc.rpm`;
+ }
+ }
+
+ resolveHPPackage() {
+ switch (
+ `${this.state.selectedVersion}-${this.state.selectedArchitecture}`
+ ) {
+ case '11.31-itanium2':
+ return `https://packages.wazuh.com/4.x/hp-ux/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}-hpux-11v3-ia64.tar`;
default:
- return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_amd64.deb`;
+ return `https://packages.wazuh.com/4.x/hp-ux/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}-hpux-11v3-ia64.tar`;
}
}
@@ -377,10 +729,34 @@ export const RegisterAgent = withErrorBoundary(
switch (this.state.selectedOS) {
case 'rpm':
return this.resolveRPMPackage();
+ case 'cent':
+ return this.resolveCENTPackage();
case 'deb':
return this.resolveDEBPackage();
+ case 'ubu':
+ return this.resolveUBUNTUPackage();
+ case 'open':
+ return this.resolveOPENSUSEPackage();
+ case 'sol':
+ return this.resolveSOLARISPackage();
+ case 'aix':
+ return this.resolveAIXPackage();
+ case 'hp':
+ return this.resolveHPPackage();
+ case 'amazonlinux':
+ return this.resolveAMAZONLPackage();
+ case 'fedora':
+ return this.resolveFEDORAPachage();
+ case 'oraclelinux':
+ return this.resolveORACLELINUXPackage();
+ case 'suse':
+ return this.resolveSUSEPackage();
+ case 'raspbian':
+ return this.resolveRASPBIANPackage();
+ case 'alpine':
+ return this.resolveAlpinePackage();
default:
- return `https://packages.wazuh.com/4.x/yum5/x86_64/wazuh-agent-${this.state.wazuhVersion}-1.x86_64.rpm`;
+ return `https://packages.wazuh.com/4.x/yum/x86_64/wazuh-agent-${this.state.wazuhVersion}${this.addToVersion}.x86_64.rpm`;
}
}
@@ -396,8 +772,111 @@ export const RegisterAgent = withErrorBoundary(
? ['OS architecture']
: []),
];
+ case 'cent':
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
case 'deb':
- return [...(!this.state.selectedArchitecture ? ['OS architecture'] : [])];
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
+ case 'ubu':
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
+ case 'win':
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
+ case 'macos':
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
+ case 'open':
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
+ case 'sol':
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
+ case 'aix':
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
+ case 'hp':
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
+ case 'amazonlinux':
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
+ case 'fedora':
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
+ case 'oraclelinux':
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
+ case 'suse':
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
+ case 'raspbian':
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
+ case 'alpine':
+ return [
+ ...(!this.state.selectedVersion ? ['OS version'] : []),
+ ...(this.state.selectedVersion && !this.state.selectedArchitecture
+ ? ['OS architecture']
+ : []),
+ ];
default:
return [];
}
@@ -412,211 +891,767 @@ export const RegisterAgent = withErrorBoundary(
}
render() {
- const appVersionMajorDotMinor = this.state.wazuhVersion.split('.').slice(0, 2).join('.');
- const urlCheckConnectionDocumentation = webDocumentationLink('user-manual/agents/agent-connection.html', appVersionMajorDotMinor);
- const textAndLinkToCheckConnectionDocumentation = (
-
- To verify the connection with the Wazuh server, please follow this{' '}
-
- document.
-
-
+ const appVersionMajorDotMinor = this.state.wazuhVersion
+ .split('.')
+ .slice(0, 2)
+ .join('.');
+ const urlCheckConnectionDocumentation = webDocumentationLink(
+ 'user-manual/agents/agent-connection.html',
+ appVersionMajorDotMinor,
);
- const missingOSSelection = this.checkMissingOSSelection();
- const ipInput = (
-
-
- This is the address the agent uses to communicate with the Wazuh server. It can be an IP address or a fully qualified domain name (FQDN).
-
- this.setServerAddress(event)}
- />
-
+
+ const urlWazuhAgentEnrollment = webDocumentationLink(
+ 'user-manual/agent-enrollment/index.html',
+ appVersionMajorDotMinor,
);
+ const urlWindowsPackage = `https://packages.wazuh.com/4.x/windows/wazuh-agent-${this.state.wazuhVersion}-1.msi`;
+
+ const missingOSSelection = this.checkMissingOSSelection();
+ const agentName = (
+
+ ` "${char}"`)}
+ ${this.state.badCharacters.length <= 1 ? 'is' : 'are'}
+ not valid. Allowed characters are A-Z, a-z, ".", "-", "_"`,
+ ]}
+ >
+ this.setAgentName(event)}
+ />
+
+
+ );
const groupInput = (
<>
{!this.state.groups.length && (
<>
-
>
)}
-
- Select one or more existing groups
- {
- this.setGroupName(group);
- }}
- isDisabled={!this.state.groups.length}
- isClearable={true}
- data-test-subj="demoComboBox"
- />
-
>
);
+ const agentGroup = (
+
+ Select one or more existing groups
+ {
+ this.setGroupName(group);
+ }}
+ isDisabled={!this.state.groups.length}
+ isClearable={true}
+ data-test-subj='demoComboBox'
+ />
+
+ );
const passwordInput = (
this.setWazuhPassword(event)}
+ onChange={event => this.setWazuhPassword(event)}
/>
);
const codeBlock = {
zIndex: '100',
};
+
const customTexts = {
- rpmText: `sudo ${this.optionalDeploymentVariables()}yum install ${this.optionalPackages()}`,
- debText: `curl -so wazuh-agent-${this.state.wazuhVersion
- }.deb ${this.optionalPackages()} && sudo ${this.optionalDeploymentVariables()}dpkg -i ./wazuh-agent-${this.state.wazuhVersion
- }.deb`,
- macosText: `curl -so wazuh-agent-${this.state.wazuhVersion
- }.pkg https://packages.wazuh.com/4.x/macos/wazuh-agent-${this.state.wazuhVersion
- }-1.pkg && sudo launchctl setenv ${this.optionalDeploymentVariables()}&& sudo installer -pkg ./wazuh-agent-${this.state.wazuhVersion
- }.pkg -target /`,
- winText: `Invoke-WebRequest -Uri https://packages.wazuh.com/4.x/windows/wazuh-agent-${this.state.wazuhVersion
- }-1.msi -OutFile \${env:tmp}\\wazuh-agent-${this.state.wazuhVersion}.msi; msiexec.exe /i \${env:tmp}\\wazuh-agent-${this.state.wazuhVersion
- }.msi /q ${this.optionalDeploymentVariables()}`,
+ rpmText: `sudo ${this.optionalDeploymentVariables()}${this.agentNameVariable()}yum install -y ${this.optionalPackages()}`,
+ alpineText: `wget -O /etc/apk/keys/alpine-devel@wazuh.com-633d7457.rsa.pub ${this.optionalPackages()} >> /etc/apk/repositories && \
+apk update && \
+apk add wazuh-agent=${this.state.wazuhVersion}-r1`,
+ centText: `sudo ${this.optionalDeploymentVariables()}${this.agentNameVariable()}yum install -y ${this.optionalPackages()}`,
+ debText: `curl -so wazuh-agent.deb ${this.optionalPackages()} && sudo ${this.optionalDeploymentVariables()}${this.agentNameVariable()}dpkg -i ./wazuh-agent.deb`,
+ ubuText: `curl -so wazuh-agent.deb ${this.optionalPackages()} && sudo ${this.optionalDeploymentVariables()}${this.agentNameVariable()}dpkg -i ./wazuh-agent.deb`,
+ macosText: `curl -so wazuh-agent.pkg https://packages.wazuh.com/4.x/macos/wazuh-agent-${
+ this.state.wazuhVersion
+ }-1.pkg && sudo launchctl setenv ${this.optionalDeploymentVariables()}${this.agentNameVariable()}&& sudo installer -pkg ./wazuh-agent.pkg -target /`,
+ winText:
+ this.state.selectedVersion == 'windowsxp' ||
+ this.state.selectedVersion == 'windowsserver2008'
+ ? `msiexec.exe /i wazuh-agent-${
+ this.state.wazuhVersion
+ }-1.msi /q ${this.optionalDeploymentVariables()}${this.agentNameVariable()}`
+ : `Invoke-WebRequest -Uri https://packages.wazuh.com/4.x/windows/wazuh-agent-${
+ this.state.wazuhVersion
+ }-1.msi -OutFile \${env:tmp}\\wazuh-agent.msi; msiexec.exe /i \${env:tmp}\\wazuh-agent.msi /q ${this.optionalDeploymentVariables()}${this.agentNameVariable()}`,
+ openText: `sudo rpm --import https://packages.wazuh.com/key/GPG-KEY-WAZUH && sudo ${this.optionalDeploymentVariables()}${this.agentNameVariable()}zypper install -y ${this.optionalPackages()}`,
+ solText: `sudo curl -so ${
+ this.state.selectedVersion == 'solaris11'
+ ? 'wazuh-agent.p5p'
+ : 'wazuh-agent.pkg'
+ } ${this.optionalPackages()} && ${
+ this.state.selectedVersion == 'solaris11'
+ ? 'pkg install -g wazuh-agent.p5p wazuh-agent'
+ : 'pkgadd -d wazuh-agent.pkg'
+ }`,
+ aixText: `sudo ${this.optionalDeploymentVariables()}${this.agentNameVariable()}rpm -ivh ${this.optionalPackages()}`,
+ hpText: `cd / && sudo curl -so wazuh-agent.tar ${this.optionalPackages()} && sudo groupadd wazuh && sudo useradd -G wazuh wazuh && sudo tar -xvf wazuh-agent.tar`,
+ amazonlinuxText: `sudo ${this.optionalDeploymentVariables()}${this.agentNameVariable()}yum install -y ${this.optionalPackages()}`,
+ fedoraText: `sudo ${this.optionalDeploymentVariables()}${this.agentNameVariable()}yum install -y ${this.optionalPackages()}`,
+ oraclelinuxText: `sudo ${this.optionalDeploymentVariables()}${this.agentNameVariable()}yum install -y ${this.optionalPackages()}`,
+ suseText: `sudo ${this.optionalDeploymentVariables()}${this.agentNameVariable()}yum install -y ${this.optionalPackages()}`,
+ raspbianText: `curl -so wazuh-agent.deb ${this.optionalPackages()} && sudo ${this.optionalDeploymentVariables()}${this.agentNameVariable()}dpkg -i ./wazuh-agent.deb`,
};
const field = `${this.state.selectedOS}Text`;
const text = customTexts[field];
const language = this.getHighlightCodeLanguage(this.state.selectedOS);
+ const warningUpgrade =
+ 'If the installer finds another Wazuh agent in the system, it will upgrade it preserving the configuration.';
+ const textAndLinkToCheckConnectionDocumentation = (
+
+ To verify the connection with the Wazuh server, please follow this{' '}
+
+ document.
+
+
+ );
+
+ const warningCommand = (
+ <>
+
+ Please
+ download
+ the package from our repository and copy it to the Windows system
+ where you are going to install it. Then run the following command to
+ perform the installation:
+
+ >
+ );
+
const windowsAdvice = this.state.selectedOS === 'win' && (
<>
-
-
- You will need administrator privileges to perform this installation.
- PowerShell 3.0 or greater is required.
+
+
+
+
+ You will need administrator privileges to perform this
+ installation.
+
+
+
+ PowerShell 3.0 or greater is required.
+
- Keep in mind you need to run this command in a Windows PowerShell terminal.
+
+ Keep in mind you need to run this command in a Windows PowerShell
+ terminal.
+
>
);
- const restartAgentCommand = this.restartAgentCommand[this.state.selectedOS];
- const onTabClick = (selectedTab) => {
+ const restartAgentCommand =
+ this.restartAgentCommand[this.state.selectedOS];
+ const onTabClick = selectedTab => {
this.selectSYS(selectedTab.id);
};
- const calloutErrorRegistrationServiceInfo = this.state.gotErrorRegistrationServiceInfo ? (
+ const calloutErrorRegistrationServiceInfo = this.state
+ .gotErrorRegistrationServiceInfo ? (
) : null;
const guide = (
- {(this.state.gotErrorRegistrationServiceInfo) ? (
+ {this.state.gotErrorRegistrationServiceInfo ? (
- ) :
+ ) : this.state.selectedOS &&
+ this.state.connectionSecure === true &&
+ this.state.udpProtocol === false ? (
+
+ {this.state.agentName.length > 0 ? (
+
+ You can use this command to install and enroll the Wazuh
+ agent.
+
+ ) : (
+
+ You can use this command to install and enroll the Wazuh agent
+ in one or more hosts.
+
+ )}
+
+
+ {windowsAdvice}
+ {this.state.selectedVersion === 'windowsxp' && (
+ <>
+
+
+ >
+ )}
+ {this.state.selectedVersion === 'windowsserver2008' && (
+ <>
+
+
+ >
+ )}
+
+
+ {this.state.wazuhPassword &&
+ !this.state.showPassword &&
+ !['sol', 'hp', 'alpine'].includes(this.state.selectedOS)
+ ? this.obfuscatePassword(text)
+ : text}
+
+
+ {copy => (
+
+ )}
+
+
+ {this.state.selectedVersion == 'solaris10' ||
+ this.state.selectedVersion == 'solaris11' ? (
+ <>
+
+ Might require some extra installation{' '}
+
+ steps
+
+ .
+
+ }
+ >
+
+
+ After installing the agent, you need to enroll it in the
+ Wazuh server. Check the Wazuh agent enrollment{' '}
+
+ Wazuh agent enrollment{' '}
+
+ section to learn more.
+
+ }
+ >
+ >
+ ) : this.state.selectedVersion == '6.1 TL9' ? (
+ <>
+
+ Might require some extra installation{' '}
+
+ steps
+
+ .
+
+ }
+ >
+
+ >
+ ) : this.state.selectedVersion == '11.31' ? (
+ <>
+
+ Might require some extra installation{' '}
+
+ steps
+
+ .
+
+ }
+ >
+
+
+ After installing the agent, you need to enroll it in the
+ Wazuh server. Check the Wazuh agent enrollment{' '}
+
+ Wazuh agent enrollment{' '}
+
+ section to learn more.
+
+ }
+ >
+ >
+ ) : this.state.selectedVersion == '3.12.12' ? (
+ <>
+
+ Might require some extra installation{' '}
+
+ steps
+
+ .
+
+ }
+ >
+
+
+ After installing the agent, you need to enroll it in the
+ Wazuh server. Check the Wazuh agent enrollment{' '}
+
+ Wazuh agent enrollment{' '}
+
+ section to learn more.
+
+ }
+ >
+ >
+ ) : this.state.selectedVersion == 'debian7' ||
+ this.state.selectedVersion == 'debian8' ||
+ this.state.selectedVersion == 'debian9' ||
+ this.state.selectedVersion == 'debian10' ? (
+ <>
+
+ Might require some extra installation{' '}
+
+ steps
+
+ .
+
+ }
+ >
+
+ >
+ ) : (
+ ''
+ )}
+ {this.state.needsPassword &&
+ !['sol', 'hp', 'alpine'].includes(this.state.selectedOS) ? (
+ this.setShowPassword(active)}
+ />
+ ) : (
+ ''
+ )}
+
+
+ ) : this.state.selectedOS && this.state.connectionSecure === false ? (
+
+
+ You can use this command to install and enroll the Wazuh agent
+ in one or more hosts.
+
+
+
+
+ Warning: there's no{' '}
+
+ secure protocol configured
+ {' '}
+ and agents will not be able to communicate with the manager.
+ >
+ }
+ iconType='iInCircle'
+ />
+
+ {windowsAdvice}
+ {this.state.selectedVersion === 'windowsxp' && (
+ <>
+
+
+ >
+ )}
+ {this.state.selectedVersion === 'windowsserver2008' && (
+ <>
+
+
+ >
+ )}
+
+
+ {this.state.wazuhPassword &&
+ !this.state.showPassword &&
+ !['sol', 'hp', 'alpine'].includes(this.state.selectedOS)
+ ? this.obfuscatePassword(text)
+ : text}
+
+
+ {copy => (
+
+ )}
+
+
+ {this.state.needsPassword && (
+ this.setShowPassword(active)}
+ />
+ )}
+
+
+ ) : (
this.state.selectedOS && (
- You can use this command to install and enroll the Wazuh agent in one or more hosts.
+ You can use this command to install and enroll the Wazuh agent
+ in one or more hosts.
- If the installer finds another Wazuh agent in the system, it will upgrade it preserving the configuration.
- >
- }
- iconType="iInCircle"
+ color='warning'
+ title={warningUpgrade}
+ iconType='iInCircle'
/>
{windowsAdvice}
-
+ {this.state.selectedVersion === 'windowsxp' && (
+ <>
+
+
+ >
+ )}
+ {this.state.selectedVersion === 'windowsserver2008' && (
+ <>
+
+
+ >
+ )}
+
- {this.state.wazuhPassword && !this.state.showPassword ? this.obfuscatePassword(text) : text}
+ {this.state.wazuhPassword &&
+ !this.state.showPassword &&
+ !['sol', 'hp', 'alpine'].includes(this.state.selectedOS)
+ ? this.obfuscatePassword(text)
+ : text}
-
- {(copy) => (
-
-
Copy command
+
+ {copy => (
+
)}
{this.state.needsPassword && (
this.setShowPassword(active)}
+ onChange={active => this.setShowPassword(active)}
/>
)}
- )}
+ )
+ )}
);
- const tabs = [
+ const tabSysV = [
{
- id: 'systemd',
- name: 'Systemd',
+ id: 'sysV',
+ name: 'SysV Init',
content: (
-
+
{this.systemSelector()}
- {(copy) => (
-
-
Copy command
+ {copy => (
+
)}
-
+
{textAndLinkToCheckConnectionDocumentation}
),
},
+ ];
+
+ const tabSystemD = [
{
- id: 'sysV',
- name: 'SysV Init',
+ id: 'systemd',
+ name: 'Systemd',
content: (
-
+
{this.systemSelector()}
- {(copy) => (
-
-
Copy command
+ {copy => (
+
+ )}
+
+
+
+ {textAndLinkToCheckConnectionDocumentation}
+
+
+ ),
+ },
+ ];
+
+ const tabNet = [
+ {
+ id: 'NET',
+ name: 'NET',
+ content: (
+
+
+
+
+
+ {this.systemSelectorNet()}
+
+
+ {copy => (
+
+ )}
+
+
+
+ {textAndLinkToCheckConnectionDocumentation}
+
+
+ ),
+ },
+ ];
+
+ const tabWazuhControlMacos = [
+ {
+ id: 'Wazuh-control-macos',
+ name: 'Wazuh-control-macos',
+ content: (
+
+
+
+
+
+ {this.systemSelectorWazuhControlMacos()}
+
+
+ {copy => (
+
+ )}
+
+
+
+ {textAndLinkToCheckConnectionDocumentation}
+
+
+ ),
+ },
+ ];
+
+ const tabWazuhControl = [
+ {
+ id: 'Wazuh-control',
+ name: 'Wazuh-control',
+ content: (
+
+
+
+
+
+ {this.systemSelectorWazuhControl()}
+
+
+ {copy => (
+
+ )}
+
+
+
+ {textAndLinkToCheckConnectionDocumentation}
+
+
+ ),
+ },
+ ];
+
+ const tabInitD = [
+ {
+ id: 'Init.d',
+ name: 'Init.d',
+ content: (
+
+
+
+
+
+ {this.systemSelectorInitD()}
+
+
+ {copy => (
+
)}
-
+
{textAndLinkToCheckConnectionDocumentation}
@@ -624,141 +1659,647 @@ export const RegisterAgent = withErrorBoundary(
},
];
+ const onChangeServerAddress = async nodeSelected => {
+ this.setState({
+ serverAddress: nodeSelected,
+ udpProtocol: this.state.haveUdpProtocol,
+ connectionSecure: this.state.haveConnectionSecure
+ });
+ };
+
const steps = [
{
- title: 'Choose the Operating system',
+ title: 'Choose the operating system',
children: (
- this.selectOS(os)}
+ onChange={os => this.selectOS(os)}
/>
),
},
...(this.state.selectedOS == 'rpm'
? [
- {
- title: 'Choose the version',
- children: (
- this.setVersion(version)}
- />
- ),
- },
- ]
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
: []),
- ...(this.state.selectedOS == 'rpm' && this.state.selectedVersion == 'centos5' || this.state.selectedVersion == 'redhat5'
+ ...(this.state.selectedOS == 'oraclelinux'
? [
- {
- title: 'Choose the architecture',
- children: (
- this.setArchitecture(architecture)}
- />
- ),
- },
- ]
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
: []),
- ...(this.state.selectedOS == 'deb' ||
- (this.state.selectedOS == 'rpm' && this.state.selectedVersion == 'centos6' || this.state.selectedVersion == 'redhat6')
+ ...(this.state.selectedOS == 'raspbian'
? [
- {
- title: 'Choose the architecture',
- children: (
- this.setArchitecture(architecture)}
- />
- ),
- },
- ]
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
: []),
- {
- title: 'Wazuh server address',
- children: {ipInput} ,
- },
- ...(!(!this.state.needsPassword || this.state.hidePasswordInput)
+ ...(this.state.selectedOS == 'amazonlinux'
+ ? [
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedOS == 'cent'
? [
- {
- title: 'Wazuh password',
- children: {passwordInput} ,
- },
- ]
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedOS == 'fedora'
+ ? [
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedOS == 'deb'
+ ? [
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedOS == 'ubu'
+ ? [
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedOS == 'win'
+ ? [
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedOS == 'macos'
+ ? [
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedOS == 'suse'
+ ? [
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedOS == 'open'
+ ? [
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedOS == 'sol'
+ ? [
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedOS == 'aix'
+ ? [
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedOS == 'hp'
+ ? [
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedOS == 'alpine'
+ ? [
+ {
+ title: 'Choose the version',
+ children: (
+ this.setVersion(version)}
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedVersion == 'centos5' ||
+ this.state.selectedVersion == 'redhat5' ||
+ this.state.selectedVersion == 'oraclelinux5' ||
+ this.state.selectedVersion == 'suse11'
+ ? [
+ {
+ title: 'Choose the architecture',
+ children: (
+
+ this.setArchitecture(architecture)
+ }
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedVersion == 'leap15'
+ ? [
+ {
+ title: 'Choose the architecture',
+ children: (
+
+ this.setArchitecture(architecture)
+ }
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedVersion == '3.12.12'
+ ? [
+ {
+ title: 'Choose the architecture',
+ children: (
+
+ this.setArchitecture(architecture)
+ }
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedVersion == 'centos6' ||
+ this.state.selectedVersion == 'oraclelinux6' ||
+ this.state.selectedVersion == 'amazonlinux1' ||
+ this.state.selectedVersion == 'redhat6' ||
+ this.state.selectedVersion == 'amazonlinux2022' ||
+ this.state.selectedVersion == 'amazonlinux2' ||
+ this.state.selectedVersion == 'debian7' ||
+ this.state.selectedVersion == 'debian8' ||
+ this.state.selectedVersion == 'ubuntu14' ||
+ this.state.selectedVersion == 'ubuntu15'
+ ? [
+ {
+ title: 'Choose the architecture',
+ children: (
+
+ this.setArchitecture(architecture)
+ }
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedVersion == 'centos7' ||
+ this.state.selectedVersion == 'redhat7' ||
+ this.state.selectedVersion == 'suse12' ||
+ this.state.selectedVersion == '22' ||
+ this.state.selectedVersion == 'debian9' ||
+ this.state.selectedVersion == 'busterorgreater'
+ ? [
+ {
+ title: 'Choose the architecture',
+ children: (
+
+ this.setArchitecture(architecture)
+ }
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedVersion == 'windowsxp' ||
+ this.state.selectedVersion == 'windowsserver2008' ||
+ this.state.selectedVersion == 'windows7'
+ ? [
+ {
+ title: 'Choose the architecture',
+ children: (
+
+ this.setArchitecture(architecture)
+ }
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedVersion == 'sierra'
+ ? [
+ {
+ title: 'Choose the architecture',
+ children: (
+
+ this.setArchitecture(architecture)
+ }
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedVersion == 'solaris10' ||
+ this.state.selectedVersion == 'solaris11'
+ ? [
+ {
+ title: 'Choose the architecture',
+ children: (
+
+ this.setArchitecture(architecture)
+ }
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedVersion == '6.1 TL9'
+ ? [
+ {
+ title: 'Choose the architecture',
+ children: (
+
+ this.setArchitecture(architecture)
+ }
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(this.state.selectedVersion == '11.31'
+ ? [
+ {
+ title: 'Choose the architecture',
+ children: (
+
+ this.setArchitecture(architecture)
+ }
+ />
+ ),
+ },
+ ]
+ : []),
+ ...(!(
+ this.state.selectedOS == 'hp' ||
+ this.state.selectedOS == 'sol' ||
+ this.state.selectedOS == 'alpine'
+ )
+ ? [
+ {
+ title: 'Wazuh server address',
+ children: (
+
+
+
+ ),
+ },
+ ]
+ : []),
+ ...(!(
+ !this.state.needsPassword ||
+ this.state.hidePasswordInput ||
+ !!['solaris10', 'solaris11', '11.31', '3.12.12'].includes(
+ this.state.selectedVersion,
+ )
+ )
+ ? [
+ {
+ title: 'Wazuh password',
+ children: {passwordInput} ,
+ },
+ ]
+ : []),
+ ...(!(
+ this.state.selectedOS == 'hp' ||
+ this.state.selectedOS == 'sol' ||
+ this.state.selectedOS == 'alpine'
+ )
+ ? [
+ {
+ title: 'Assign a name and a group to the agent',
+ children: (
+
+ {agentName}
+ {groupInput}
+ {agentGroup}
+
+ ),
+ },
+ ]
: []),
- {
- title: 'Assign the agent to a group',
- children: {groupInput} ,
- },
{
title: 'Install and enroll the agent',
- children: this.state.gotErrorRegistrationServiceInfo ?
+ children: this.state.gotErrorRegistrationServiceInfo ? (
calloutErrorRegistrationServiceInfo
- : missingOSSelection.length ? (
-
- ) : (
- {guide}
- ),
+ ) : this.state.agentNameError &&
+ !['hp', 'sol', 'alpine'].includes(this.state.selectedOS) ? (
+
+ ) : missingOSSelection.length ? (
+
+ ) : (
+ {guide}
+ ),
},
- ...(this.state.selectedOS == 'rpm' || this.state.selectedOS == 'deb'
+ ...(this.state.selectedOS == 'rpm' ||
+ this.state.selectedOS == 'cent' ||
+ this.state.selectedOS == 'suse' ||
+ this.state.selectedOS == 'fedora' ||
+ this.state.selectedOS == 'oraclelinux' ||
+ this.state.selectedOS == 'amazonlinux' ||
+ this.state.selectedOS == 'deb' ||
+ this.state.selectedOS == 'raspbian' ||
+ this.state.selectedOS == 'ubu' ||
+ this.state.selectedOS == 'win' ||
+ this.state.selectedOS == 'macos' ||
+ this.state.selectedOS == 'open' ||
+ this.state.selectedOS == 'sol' ||
+ this.state.selectedOS == 'aix' ||
+ this.state.selectedOS == 'hp' ||
+ this.state.selectedOS == 'alpine' ||
+ this.state.selectedOS == ''
? [
- {
- title: 'Start the agent',
- children: this.state.gotErrorRegistrationServiceInfo ?
- calloutErrorRegistrationServiceInfo
- : missingOSSelection.length ? (
+ {
+ title: 'Start the agent',
+ children: this.state.gotErrorRegistrationServiceInfo ? (
+ calloutErrorRegistrationServiceInfo
+ ) : this.state.agentNameError &&
+ !['hp', 'sol', 'alpine'].includes(this.state.selectedOS) ? (
+
+ ) : missingOSSelection.length ? (
) : (
),
- },
- ]
+ },
+ ]
: []),
-
...(!missingOSSelection.length &&
- this.state.selectedOS !== 'rpm' &&
- this.state.selectedOS !== 'deb' &&
- restartAgentCommand
+ this.state.selectedOS !== 'rpm' &&
+ this.state.selectedOS !== 'deb' &&
+ this.state.selectedOS !== 'cent' &&
+ this.state.selectedOS !== 'ubu' &&
+ this.state.selectedOS !== 'win' &&
+ this.state.selectedOS !== 'macos' &&
+ this.state.selectedOS !== 'open' &&
+ this.state.selectedOS !== 'sol' &&
+ this.state.selectedOS !== 'aix' &&
+ this.state.selectedOS !== 'hp' &&
+ this.state.selectedOS !== 'amazonlinux' &&
+ this.state.selectedOS !== 'fedora' &&
+ this.state.selectedOS !== 'oraclelinux' &&
+ this.state.selectedOS !== 'suse' &&
+ this.state.selectedOS !== 'raspbian' &&
+ this.state.selectedOS !== 'alpine' &&
+ restartAgentCommand
? [
- {
- title: 'Start the agent',
- children: this.state.gotErrorRegistrationServiceInfo ?
- calloutErrorRegistrationServiceInfo
- : (
-
+ {
+ title: 'Start the agent',
+ children: this.state.gotErrorRegistrationServiceInfo ? (
+ calloutErrorRegistrationServiceInfo
+ ) : (
+
-
+
{restartAgentCommand}
- {(copy) => (
-
-
Copy command
+ {copy => (
+
)}
@@ -766,13 +2307,14 @@ export const RegisterAgent = withErrorBoundary(
),
- },
- ]
+ },
+ ]
: []),
];
+
return (
-
+
@@ -784,31 +2326,31 @@ export const RegisterAgent = withErrorBoundary(
- {this.props.hasAgents && (
+ {this.props.hasAgents() && (
this.props.addNewAgent(false)}
- iconType="cross"
+ iconType='cross'
>
Close
)}
- {!this.props.hasAgents && (
+ {!this.props.hasAgents() && (
this.props.reload()}
- iconType="refresh"
+ iconType='refresh'
>
Refresh
)}
-
+
{this.state.loading && (
<>
-
+
>
@@ -826,5 +2368,5 @@ export const RegisterAgent = withErrorBoundary(
);
}
- }
-);
\ No newline at end of file
+ },
+);
diff --git a/public/controllers/agent/components/register-agent.scss b/public/controllers/agent/components/register-agent.scss
new file mode 100644
index 0000000000..e19973cad7
--- /dev/null
+++ b/public/controllers/agent/components/register-agent.scss
@@ -0,0 +1,14 @@
+.registerAgent{
+ min-height: calc(100vh - 100px);
+ background: #fafbfd;
+ .euiButtonGroup__buttons {
+ display: grid;
+ grid-template-columns: repeat(5, 1fr);
+ grid-gap: 10px;
+ padding: 0 3px;
+ box-shadow: none;
+ }
+ .euiButtonGroup--medium .euiButtonGroupButton:not(:first-child), .euiButtonGroup--small .euiButtonGroupButton:not(:first-child) {
+ margin-left: 0 !important;
+ }
+}
\ No newline at end of file
diff --git a/public/controllers/agent/components/register-agent.test.js b/public/controllers/agent/components/register-agent.test.js
new file mode 100644
index 0000000000..9d8b76ff23
--- /dev/null
+++ b/public/controllers/agent/components/register-agent.test.js
@@ -0,0 +1,33 @@
+import React from 'react';
+import { render, waitFor } from '@testing-library/react';
+import { RegisterAgent } from '../components/register-agent'
+
+// mocked getErrorOrchestrator
+const mockedGetErrorOrchestrator = {
+ handleError: jest.fn(),
+ };
+
+ jest.mock('../../../react-services/common-services', () => {
+ return {
+ getErrorOrchestrator: () => mockedGetErrorOrchestrator,
+ };
+ });
+
+describe('RegisterAgent', () => {
+ it('mount - RegisterAgent', async() => {
+ const getWazuhVersion = jest.fn();
+ const getCurrentApiAddress = jest.fn();
+ const addNewAgent = jest.fn();
+ const reload = jest.fn();
+
+ const props = {
+ hasAgents: true,
+ getWazuhVersion,
+ getCurrentApiAddress,
+ addNewAgent,
+ reload,
+ };
+ const { debug } = render(
);
+ debug()
+ });
+});
diff --git a/public/controllers/agent/components/wz-accordion.tsx b/public/controllers/agent/components/wz-accordion.tsx
new file mode 100644
index 0000000000..f2e72ed167
--- /dev/null
+++ b/public/controllers/agent/components/wz-accordion.tsx
@@ -0,0 +1,57 @@
+import React, { useState } from 'react';
+import {
+ EuiPanel,
+ EuiSpacer,
+ EuiAccordion,
+ EuiButtonGroup,
+ htmlIdGenerator,
+} from '@elastic/eui';
+import { osButtons } from '../wazuh-config';
+
+export const PrincipalButtonGroup = ({
+ legend,
+ options,
+ idSelected,
+ onChange,
+}) => {
+ return (
+ <>
+
+
+
+
+
+ >
+ );
+};
+
+export const WzAccordion = ({ children }) => {
+ const [isAccordionOpen, setIsAccordionOpen] = useState(false);
+ const rightArrowAccordionId = htmlIdGenerator('wz-accordion')();
+ return (
+
setIsAccordionOpen(isOpen)}
+ className={'action-btn-td'}
+ >
+
+
+ {children}
+
+
+ );
+};
diff --git a/public/controllers/agent/register-agent/__snapshots__/register-agent-button-group.test.tsx.snap b/public/controllers/agent/register-agent/__snapshots__/register-agent-button-group.test.tsx.snap
new file mode 100644
index 0000000000..2d214a76d1
--- /dev/null
+++ b/public/controllers/agent/register-agent/__snapshots__/register-agent-button-group.test.tsx.snap
@@ -0,0 +1,138 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`RegisterAgentButtonGroup should render correctly 1`] = `
+Object {
+ "asFragment": [Function],
+ "baseElement":
+
+
+
+ Test legend
+
+
+
+
+
+
+ test
+
+
+
+
+
+
+ ,
+ "container":
+
+
+ Test legend
+
+
+
+
+
+
+ test
+
+
+
+
+
+
,
+ "debug": [Function],
+ "findAllByAltText": [Function],
+ "findAllByDisplayValue": [Function],
+ "findAllByLabelText": [Function],
+ "findAllByPlaceholderText": [Function],
+ "findAllByRole": [Function],
+ "findAllByTestId": [Function],
+ "findAllByText": [Function],
+ "findAllByTitle": [Function],
+ "findByAltText": [Function],
+ "findByDisplayValue": [Function],
+ "findByLabelText": [Function],
+ "findByPlaceholderText": [Function],
+ "findByRole": [Function],
+ "findByTestId": [Function],
+ "findByText": [Function],
+ "findByTitle": [Function],
+ "getAllByAltText": [Function],
+ "getAllByDisplayValue": [Function],
+ "getAllByLabelText": [Function],
+ "getAllByPlaceholderText": [Function],
+ "getAllByRole": [Function],
+ "getAllByTestId": [Function],
+ "getAllByText": [Function],
+ "getAllByTitle": [Function],
+ "getByAltText": [Function],
+ "getByDisplayValue": [Function],
+ "getByLabelText": [Function],
+ "getByPlaceholderText": [Function],
+ "getByRole": [Function],
+ "getByTestId": [Function],
+ "getByText": [Function],
+ "getByTitle": [Function],
+ "queryAllByAltText": [Function],
+ "queryAllByDisplayValue": [Function],
+ "queryAllByLabelText": [Function],
+ "queryAllByPlaceholderText": [Function],
+ "queryAllByRole": [Function],
+ "queryAllByTestId": [Function],
+ "queryAllByText": [Function],
+ "queryAllByTitle": [Function],
+ "queryByAltText": [Function],
+ "queryByDisplayValue": [Function],
+ "queryByLabelText": [Function],
+ "queryByPlaceholderText": [Function],
+ "queryByRole": [Function],
+ "queryByTestId": [Function],
+ "queryByText": [Function],
+ "queryByTitle": [Function],
+ "rerender": [Function],
+ "unmount": [Function],
+}
+`;
diff --git a/public/controllers/agent/register-agent/register-agent-button-group.test.tsx b/public/controllers/agent/register-agent/register-agent-button-group.test.tsx
new file mode 100644
index 0000000000..88c8582390
--- /dev/null
+++ b/public/controllers/agent/register-agent/register-agent-button-group.test.tsx
@@ -0,0 +1,111 @@
+import React from 'react';
+import '@testing-library/jest-dom';
+import { render } from '@testing-library/react';
+import RegisterAgentButtonGroup from './register-agent-button-group';
+
+jest.mock(
+ '../../../../../../node_modules/@elastic/eui/lib/services/accessibility/html_id_generator',
+ () => ({
+ htmlIdGenerator: () => () => 'htmlId',
+ })
+);
+
+
+describe('RegisterAgentButtonGroup', () => {
+ it('should render correctly', () => {
+ const buttonsOpts = [{ id: 'test', label: 'test' }];
+ const wrapper = render(
+
{}}
+ />,
+ );
+ expect(wrapper).toMatchSnapshot();
+ });
+
+ it('should render the label text', () => {
+ const buttonsOpts = [{ id: 'test', label: 'test' }];
+ const { getByText } = render(
+ {}}
+ />,
+ );
+ expect(getByText('Test legend')).toBeInTheDocument();
+ });
+
+ it('should auto select button when the group have only one button in options list', () => {
+ const mockedOnChange = jest.fn();
+ const buttonsOpts = [{ id: 'test', label: 'test' }];
+ render(
+ ,
+ );
+ expect(mockedOnChange).toBeCalledWith(buttonsOpts[0].id);
+ });
+
+ it('should auto select button when the group have an option with the default property in true', () => {
+ const mockedOnChange = jest.fn();
+ const buttonsOpts = [
+ { id: 'test', label: 'test' },
+ { id: 'auto-selected', label: 'test2', default: true },
+ ];
+ render(
+ ,
+ );
+ expect(mockedOnChange).toBeCalledWith(buttonsOpts[1].id);
+ });
+
+ it('should auto select the first button when the group have more than one option with the default property in true', () => {
+ const mockedOnChange = jest.fn();
+ const buttonsOpts = [
+ { id: 'test', label: 'test' },
+ { id: 'auto-selected', label: 'test2', default: true },
+ { id: 'auto-selected2', label: 'test3', default: true },
+ ];
+ render(
+ ,
+ );
+ expect(mockedOnChange).toBeCalledWith(buttonsOpts[1].id);
+ });
+
+ it('should render the correct number of buttons defined in the options received', () => {
+ const mockedOnChange = jest.fn();
+ const buttonsOpts = [
+ { id: 'test', label: 'test' },
+ { id: 'test2', label: 'test2' },
+ { id: 'test3', label: 'test3' },
+ ];
+ const { getByText, getByRole } = render(
+ ,
+ );
+
+ buttonsOpts.forEach((button) => {
+ expect(getByText(button.label)).toBeInTheDocument();
+ })
+ });
+
+});
diff --git a/public/controllers/agent/register-agent/register-agent-button-group.tsx b/public/controllers/agent/register-agent/register-agent-button-group.tsx
new file mode 100644
index 0000000000..bf7b40546e
--- /dev/null
+++ b/public/controllers/agent/register-agent/register-agent-button-group.tsx
@@ -0,0 +1,54 @@
+import { EuiButtonGroup } from '@elastic/eui';
+import React, { useEffect } from 'react';
+
+interface RegisterAgentButtonGroupProps {
+ legend: string;
+ options: Array<{id: string, label: string, default?: boolean}>;
+ idSelected: string;
+ onChange: (value: string) => void;
+}
+
+export default function RegisterAgentButtonGroup({
+ legend,
+ options,
+ idSelected,
+ onChange,
+}: RegisterAgentButtonGroupProps) {
+
+ useEffect(() => {
+ setDefaultOptions();
+ }, []);
+
+ useEffect(() => {
+ setDefaultOptions();
+ }, [options, idSelected])
+
+ /**
+ * Set default option
+ * Autoselect option when there is only one option
+ * Autoselect option when an option have default property in true
+ */
+ const setDefaultOptions = () => {
+ if(!idSelected){ // prevent autoselect every time the options change
+ if (options.length === 1) {
+ idSelected = options[0].id;
+ onChange(options[0].id);
+ }else if(options.filter(item => item.default).length > 0){
+ const defaultOption = options.filter(item => item.default)[0].id
+ idSelected = defaultOption;
+ onChange(defaultOption);
+ }
+ }
+ };
+
+ return (
+
+ );
+}
diff --git a/public/controllers/agent/register-agent/steps/__snapshots__/server-address.test.tsx.snap b/public/controllers/agent/register-agent/steps/__snapshots__/server-address.test.tsx.snap
new file mode 100644
index 0000000000..d41e54d637
--- /dev/null
+++ b/public/controllers/agent/register-agent/steps/__snapshots__/server-address.test.tsx.snap
@@ -0,0 +1,84 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Server Address Combobox should match snapshot 1`] = `
+
+
+
+ This is the address the agent uses to communicate with the Wazuh server. It can be an IP address or a fully qualified domain name (FQDN).
+
+
+
+
+`;
diff --git a/public/controllers/agent/register-agent/steps/index.ts b/public/controllers/agent/register-agent/steps/index.ts
new file mode 100644
index 0000000000..5732aed9ae
--- /dev/null
+++ b/public/controllers/agent/register-agent/steps/index.ts
@@ -0,0 +1 @@
+export * from './server-address';
\ No newline at end of file
diff --git a/public/controllers/agent/register-agent/steps/server-address.test.tsx b/public/controllers/agent/register-agent/steps/server-address.test.tsx
new file mode 100644
index 0000000000..ce3e8c513e
--- /dev/null
+++ b/public/controllers/agent/register-agent/steps/server-address.test.tsx
@@ -0,0 +1,221 @@
+import React from 'react';
+import { render, fireEvent } from '@testing-library/react';
+import '@testing-library/jest-dom';
+import { act } from 'react-dom/test-utils';
+import ServerAddress from './server-address';
+import * as registerAgentsUtils from '../../components/register-agent-service';
+
+jest.mock('../../../../kibana-services', () => ({
+ ...(jest.requireActual('../../../../kibana-services') as object),
+ getHttp: jest.fn().mockReturnValue({
+ basePath: {
+ get: () => {
+ return 'http://localhost:5601';
+ },
+ prepend: url => {
+ return `http://localhost:5601${url}`;
+ },
+ },
+ }),
+ getCookies: jest.fn().mockReturnValue({
+ set: (name, value, options) => {
+ return true;
+ },
+ get: () => {
+ return '{}';
+ },
+ remove: () => {
+ return;
+ },
+ }),
+}));
+
+const mockedNodesIps = [
+ {
+ name: 'master-node',
+ type: 'master',
+ version: '4.x',
+ ip: 'wazuh-master',
+ },
+ {
+ name: 'worker1',
+ type: 'worker',
+ version: '4.x',
+ ip: '172.26.0.7',
+ },
+ {
+ name: 'worker2',
+ type: 'worker',
+ version: '4.x',
+ ip: '172.26.0.6',
+ },
+];
+
+const mockedClusterNodes = {
+ data: {
+ data: {
+ affected_items: mockedNodesIps,
+ total_affected_items: mockedNodesIps.length,
+ total_failed_items: 0,
+ failed_items: [],
+ },
+ message: 'All selected nodes information was returned',
+ error: 0,
+ },
+};
+
+const promiseFetchOptions = Promise.resolve(
+ registerAgentsUtils.parseNodesInOptions(mockedClusterNodes),
+);
+const mockedFetchOptions = () => promiseFetchOptions;
+
+describe('Server Address Combobox', () => {
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('should render correctly', () => {
+ const { container } = render(
+ {}}
+ fetchOptions={() =>
+ Promise.resolve(
+ registerAgentsUtils.parseNodesInOptions(mockedClusterNodes),
+ )
+ }
+ />,
+ );
+ expect(container).toBeInTheDocument();
+ });
+
+ it('should match snapshot', () => {
+ const { container } = render(
+ {}} fetchOptions={mockedFetchOptions} />,
+ );
+ expect(container).toMatchSnapshot();
+ });
+
+ it('should set default combobox value and disable input when defaultValue is defined', async () => {
+ const onChangeMocked = jest.fn();
+ const { container, getByText, getByRole } = render(
+ ,
+ );
+
+ await act(async () => {
+ await promiseFetchOptions;
+ expect(onChangeMocked).toBeCalledTimes(1);
+ expect(onChangeMocked).toBeCalledWith([
+ { label: 'default-dns', value: 'default-dns', nodetype: 'custom' },
+ ]);
+ expect(getByText('default-dns')).toBeInTheDocument();
+ expect(getByRole('textbox')).toHaveAttribute('disabled');
+ expect(container).toBeInTheDocument();
+ });
+ });
+
+ it('should set node type master like default value when combobox is initiliazed and not have defaultValue', async () => {
+ const { container, getByText } = render(
+ {}} fetchOptions={mockedFetchOptions} />,
+ );
+
+ await act(async () => {
+ await promiseFetchOptions; // waiting for the combobox items are loaded
+ expect(getByText('master-node')).toBeInTheDocument();
+ expect(container).toBeInTheDocument();
+ });
+ });
+
+ it('should render the correct number of options', async () => {
+ const { getByRole, findByText } = render(
+ {}} fetchOptions={mockedFetchOptions} />,
+ );
+
+ await act(async () => {
+ await promiseFetchOptions; // waiting for the combobox items are loaded
+ fireEvent.click(getByRole('button', { name: 'Clear input' }));
+ await findByText(`${mockedNodesIps[0].name}:${mockedNodesIps[0].ip}`);
+ await findByText(`${mockedNodesIps[1].name}:${mockedNodesIps[1].ip}`);
+ await findByText(`${mockedNodesIps[2].name}:${mockedNodesIps[2].ip}`);
+ });
+ });
+
+ it('should allow only single selection', async () => {
+ const onChangeMocked = jest.fn();
+ const { getByRole, getByText, findByText } = render(
+ ,
+ );
+ await act(async () => {
+ await promiseFetchOptions; // waiting for the combobox items are loaded
+ fireEvent.click(getByRole('button', { name: 'Clear input' }));
+ const serverAddresInput = getByRole('textbox');
+ fireEvent.change(serverAddresInput, { target: { value: 'first-typed' } });
+ fireEvent.keyDown(serverAddresInput, { key: 'Enter', code: 'Enter' });
+ fireEvent.change(serverAddresInput, { target: { value: 'last-typed' } });
+ fireEvent.keyDown(serverAddresInput, { key: 'Enter', code: 'Enter' });
+ expect(onChangeMocked).toHaveBeenLastCalledWith([
+ { label: 'last-typed', value: 'last-typed', nodetype: 'custom' },
+ ]);
+ expect(getByText('last-typed')).toBeInTheDocument();
+ });
+ });
+
+ it('should return EMPTY parsed Node IPs when options are not selected', async () => {
+ const onChangeMocked = jest.fn();
+ const { getByRole, container } = render(
+ ,
+ );
+ await act(async () => {
+ await promiseFetchOptions; // waiting for the combobox items are loaded
+ fireEvent.click(getByRole('button', { name: 'Clear input' }));
+ expect(onChangeMocked).toBeCalledTimes(2);
+ expect(onChangeMocked).toBeCalledWith([]);
+ expect(container).toBeInTheDocument();
+ });
+ });
+
+ it('should allow create customs options when user type and trigger enter key', async () => {
+ const onChangeMocked = jest.fn();
+
+ const { getByRole } = render(
+ ,
+ );
+ await act(async () => {
+ await promiseFetchOptions; // waiting for the combobox items are loaded
+ fireEvent.change(getByRole('textbox'), {
+ target: { value: 'custom-ip-dns' },
+ });
+ fireEvent.keyDown(getByRole('textbox'), { key: 'Enter', code: 'Enter' });
+ expect(onChangeMocked).toBeCalledTimes(2);
+ expect(onChangeMocked).toHaveBeenNthCalledWith(2, [
+ { label: 'custom-ip-dns', value: 'custom-ip-dns', nodetype: 'custom' },
+ ]);
+ });
+ });
+
+ it('should show "node.name:node.ip" in the combobox options', async () => {
+ const { getByRole, getByText } = render(
+ {}} fetchOptions={mockedFetchOptions} />,
+ );
+ await act(async () => {
+ await promiseFetchOptions; // waiting for the combobox items are loaded
+ fireEvent.click(getByRole('button', { name: 'Clear input' }));
+ });
+
+ mockedNodesIps.forEach(nodeItem => {
+ expect(getByText(`${nodeItem.name}:${nodeItem.ip}`)).toBeInTheDocument();
+ });
+ });
+});
diff --git a/public/controllers/agent/register-agent/steps/server-address.tsx b/public/controllers/agent/register-agent/steps/server-address.tsx
new file mode 100644
index 0000000000..8c23073f36
--- /dev/null
+++ b/public/controllers/agent/register-agent/steps/server-address.tsx
@@ -0,0 +1,170 @@
+import {
+ EuiComboBox,
+ EuiComboBoxOptionOption,
+ EuiHighlight,
+ EuiText,
+} from '@elastic/eui';
+import React, { useEffect, useState } from 'react';
+import { UI_LOGGER_LEVELS } from '../../../../../common/constants';
+import { getErrorOrchestrator } from '../../../../react-services/common-services';
+import { UI_ERROR_SEVERITIES } from '../../../../react-services/error-orchestrator/types';
+import { getMasterNode } from '../../components/register-agent-service';
+
+type Props = {
+ onChange: (value: EuiComboBoxOptionOption[]) => void;
+ fetchOptions: () => Promise[]>;
+ defaultValue?: string;
+};
+
+export type ServerAddressOptions = EuiComboBoxOptionOption & {
+ nodetype?: string;
+};
+
+const ServerAddress = (props: Props) => {
+ const { onChange, fetchOptions, defaultValue } = props;
+ const [nodeIPs, setNodeIPs] = useState([]);
+ const [selectedNodeIPs, setSelectedNodeIPs] = useState<
+ ServerAddressOptions[]
+ >([]);
+ const [isLoading, setIsLoading] = useState(false);
+ const [isDisabled, setIsDisabled] = useState(false);
+
+ useEffect(() => {
+ initialize();
+ }, []);
+
+ /**
+ * Fetches the node IPs (options) and sets the state
+ */
+ const initialize = async () => {
+ if (!fetchOptions) {
+ throw new Error('fetchOptions is required');
+ }
+ try {
+ setIsLoading(true);
+ await setDefaultValue();
+ setIsLoading(false);
+ } catch (error) {
+ setIsLoading(false);
+ const options = {
+ context: `${ServerAddress.name}.initialize`,
+ level: UI_LOGGER_LEVELS.ERROR,
+ severity: UI_ERROR_SEVERITIES.BUSINESS,
+ display: true,
+ store: false,
+ error: {
+ error: error,
+ message: error.message || error,
+ title: error.name || error,
+ },
+ };
+ getErrorOrchestrator().handleError(options);
+ }
+ };
+
+ /**
+ * Sets the default value of server address
+ */
+ const setDefaultValue = async () => {
+ if (defaultValue) {
+ const defaultNode = [{ label: defaultValue, value: defaultValue, nodetype: 'custom' }];
+ handleOnChange(defaultNode);
+ setIsDisabled(true);
+ } else {
+ setIsDisabled(false);
+ const nodeIps = await fetchOptions();
+ setNodeIPs(nodeIps);
+ const defaultNode = getMasterNode(nodeIps);
+ if (defaultNode.length > 0) {
+ handleOnChange(defaultNode);
+ }
+ }
+ };
+
+ /**
+ * Handles the change of the selected node IP
+ * @param value
+ */
+ const handleOnChange = (value: EuiComboBoxOptionOption[]) => {
+ setSelectedNodeIPs(value);
+ onChange(value);
+ };
+
+ /**
+ * Handle the render of the custom options in the combobox list
+ * @param option
+ * @param searchValue
+ * @param contentClassName
+ */
+ const handleRenderOption = (
+ option: EuiComboBoxOptionOption,
+ inputValue: string,
+ contentClassName: string,
+ ) => {
+ const { label, value } = option;
+ return (
+
+ {`${label}:${value}`}
+
+ );
+ };
+
+ /**
+ * Handle the interaction when the user enter a option that is not in the list
+ * Creating new options in the list and selecting it
+ * @param inputValue
+ * @param options
+ */
+ const handleOnCreateOption = (
+ inputValue: string,
+ options: ServerAddressOptions[] = [],
+ ) => {
+ if (!inputValue) {
+ return;
+ }
+
+ const normalizedSearchValue = inputValue.trim().toLowerCase();
+ if (!normalizedSearchValue) {
+ return;
+ }
+
+ const newOption = {
+ value: inputValue,
+ label: inputValue,
+ nodetype: 'custom',
+ };
+ // Create the option if it doesn't exist.
+ if (
+ options.findIndex(
+ (option: ServerAddressOptions) =>
+ option.label.trim().toLowerCase() === normalizedSearchValue,
+ ) === -1
+ ) {
+ setNodeIPs([...nodeIPs, newOption]);
+ }
+ // Select the option.
+ handleOnChange([newOption]);
+ };
+
+ return (
+
+
+ This is the address the agent uses to communicate with the Wazuh server. It can be an IP address or a fully qualified domain name (FQDN).
+
+ handleOnCreateOption(sv, fo)}
+ />
+
+ );
+};
+
+export default ServerAddress;
diff --git a/public/controllers/agent/register-agent/steps/wz-manager-address.tsx b/public/controllers/agent/register-agent/steps/wz-manager-address.tsx
new file mode 100644
index 0000000000..0c46c70676
--- /dev/null
+++ b/public/controllers/agent/register-agent/steps/wz-manager-address.tsx
@@ -0,0 +1,46 @@
+import React, { memo, useCallback, useEffect, useState } from 'react';
+import { EuiText, EuiFieldText } from '@elastic/eui';
+
+type Props = {
+ onChange: (value: string) => void;
+ defaultValue?: string;
+};
+
+const WzManagerAddressInput = (props: Props) => {
+ const { onChange, defaultValue } = props;
+ const [value, setValue] = useState('');
+
+ useEffect(() => {
+ if(defaultValue){
+ setValue(defaultValue);
+ onChange(defaultValue);
+ }else{
+ setValue('');
+ onChange('');
+ }
+ },[])
+ /**
+ * Handles the change of the selected node IP
+ * @param value
+ */
+ const handleOnChange = (event: React.ChangeEvent) => {
+ const { value } = event.target;
+ onChange(value);
+ setValue(value);
+ };
+ return (
+
+
+ This is the address the agent uses to communicate with the Wazuh server.
+ It can be an IP address or a fully qualified domain name (FQDN).
+
+
+
+ );
+};
+
+export default WzManagerAddressInput;
diff --git a/public/controllers/agent/wazuh-config/index.ts b/public/controllers/agent/wazuh-config/index.ts
new file mode 100644
index 0000000000..e555fb5517
--- /dev/null
+++ b/public/controllers/agent/wazuh-config/index.ts
@@ -0,0 +1,416 @@
+const architectureButtons = [
+ {
+ id: 'i386',
+ label: 'i386',
+ },
+ {
+ id: 'x86_64',
+ label: 'x86_64',
+ default: true
+ },
+ {
+ id: 'armhf',
+ label: 'armhf',
+ },
+ {
+ id: 'aarch64',
+ label: 'aarch64',
+ },
+];
+
+const architectureButtonsWithPPC64LE = [
+ {
+ id: 'i386',
+ label: 'i386',
+ },
+ {
+ id: 'x86_64',
+ label: 'x86_64',
+ default: true
+ },
+ {
+ id: 'armhf',
+ label: 'armhf',
+ },
+ {
+ id: 'aarch64',
+ label: 'aarch64',
+ },
+ {
+ id: 'powerpc',
+ label: 'PowerPC',
+ },
+];
+
+const architectureButtonsWithPPC64LEAlpine = [
+ {
+ id: 'i386',
+ label: 'i386',
+ },
+ {
+ id: 'x86',
+ label: 'x86',
+ },
+ {
+ id: 'x86_64',
+ label: 'x86_64',
+ default: true
+ },
+ {
+ id: 'armhf',
+ label: 'armhf',
+ },
+ {
+ id: 'aarch64',
+ label: 'aarch64',
+ },
+ {
+ id: 'powerpc',
+ label: 'PowerPC',
+ },
+];
+
+const architectureButtonsi386 = [
+ {
+ id: 'i386/x86_64',
+ label: 'i386/x86_64',
+ },
+];
+
+const architecturei386Andx86_64 = [
+ {
+ id: 'i386',
+ label: 'i386',
+ },
+ {
+ id: 'x86_64',
+ label: 'x86_64',
+ default: true
+ },
+];
+
+const architectureButtonsSolaris = [
+ {
+ id: 'i386',
+ label: 'i386',
+ default: true
+ },
+ {
+ id: 'sparc',
+ label: 'SPARC',
+ },
+];
+
+const architectureButtonsMacos = [
+ {
+ id: 'intel/applesilicon',
+ label: 'Intel/Apple Silicon',
+ },
+];
+
+const architectureButtonsAix = [
+ {
+ id: 'powerpc',
+ label: 'PowerPC',
+ },
+];
+
+const architectureButtonsHpUx = [
+ {
+ id: 'itanium2',
+ label: 'Itanium2',
+ },
+];
+
+const versionButtonAmazonLinux = [
+ {
+ id: 'amazonlinux1',
+ label: 'Amazon Linux 1',
+ },
+ {
+ id: 'amazonlinux2',
+ label: 'Amazon Linux 2',
+ },
+ {
+ id: 'amazonlinux2022',
+ label: 'Amazon Linux 2022',
+ default: true
+ },
+];
+
+const versionButtonsRedHat = [
+ {
+ id: 'redhat5',
+ label: 'Red Hat 5',
+ },
+ {
+ id: 'redhat6',
+ label: 'Red Hat 6',
+ },
+ {
+ id: 'redhat7',
+ label: 'Red Hat 7 +',
+ default: true
+ },
+];
+
+const versionButtonsCentos = [
+ {
+ id: 'centos5',
+ label: 'CentOS 5',
+ },
+ {
+ id: 'centos6',
+ label: 'CentOS 6',
+ },
+ {
+ id: 'centos7',
+ label: 'CentOS 7 +',
+ default: true
+ },
+];
+
+const versionButtonsDebian = [
+ {
+ id: 'debian7',
+ label: 'Debian 7',
+ },
+ {
+ id: 'debian8',
+ label: 'Debian 8',
+ },
+ {
+ id: 'debian9',
+ label: 'Debian 9 +',
+ default: true
+ },
+];
+
+const versionButtonFedora = [
+ {
+ id: '22',
+ label: 'Fedora 22 +',
+ },
+];
+
+const versionButtonsUbuntu = [
+ {
+ id: 'ubuntu14',
+ label: 'Ubuntu 14',
+ },
+ {
+ id: 'ubuntu15',
+ label: 'Ubuntu 15 +',
+ default: true
+ },
+];
+
+const versionButtonsWindows = [
+ {
+ id: 'windowsxp',
+ label: 'Windows XP',
+ },
+ {
+ id: 'windowsserver2008',
+ label: 'Windows Server 2008',
+ },
+ {
+ id: 'windows7',
+ label: 'Windows 7 +',
+ default: true
+ },
+];
+
+const versionButtonsSuse = [
+ {
+ id: 'suse11',
+ label: 'SUSE 11',
+ },
+ {
+ id: 'suse12',
+ label: 'SUSE 12',
+ default: true
+ },
+];
+
+const versionButtonsMacOS = [
+ {
+ id: 'sierra',
+ label: 'macOS Sierra +',
+ },
+];
+
+const versionButtonsOpenSuse = [
+ {
+ id: 'leap15',
+ label: 'openSUSE Leap 15 +',
+ },
+];
+
+const versionButtonsSolaris = [
+ {
+ id: 'solaris10',
+ label: 'Solaris 10',
+ },
+ {
+ id: 'solaris11',
+ label: 'Solaris 11',
+ default: true
+ },
+];
+
+const versionButtonsAix = [
+ {
+ id: '6.1 TL9',
+ label: 'AIX 6.1 TL9 +',
+ },
+];
+
+const versionButtonsHPUX = [
+ {
+ id: '11.31',
+ label: 'HP-UX 11.31 +',
+ },
+];
+
+const versionButtonsOracleLinux = [
+ {
+ id: 'oraclelinux5',
+ label: 'Oracle Linux 5',
+ },
+ {
+ id: 'oraclelinux6',
+ label: 'Oracle Linux 6 +',
+ default: true
+ },
+];
+
+const versionButtonsRaspbian = [
+ {
+ id: 'busterorgreater',
+ label: 'Raspbian Buster or greater',
+ },
+];
+
+const versionButtonAlpine = [
+ {
+ id: '3.12.12',
+ label: '3.12.12 +',
+ },
+];
+
+/**
+ * Order the OS Buttons Alphabetically by label
+ * @param a
+ * @param b
+ * @returns
+ */
+const orderOSAlphabetically = (a, b) => {
+ if (a.label.toUpperCase() < b.label.toUpperCase()) {
+ return -1;
+ }
+ if (a.label.toUpperCase() > b.label.toUpperCase()) {
+ return 1;
+ }
+ return 0;
+};
+
+const osPrincipalButtons = [
+ {
+ id: 'rpm',
+ label: 'Red Hat Enterprise Linux',
+ },
+ {
+ id: 'cent',
+ label: 'CentOS',
+ },
+ {
+ id: 'ubu',
+ label: 'Ubuntu',
+ },
+ {
+ id: 'win',
+ label: 'Windows',
+ },
+ {
+ id: 'macos',
+ label: 'macOS',
+ },
+];
+
+const osButtons = [
+ {
+ id: 'deb',
+ label: 'Debian',
+ },
+ {
+ id: 'open',
+ label: 'openSUSE',
+ },
+ {
+ id: 'sol',
+ label: 'Solaris',
+ },
+ {
+ id: 'aix',
+ label: 'AIX',
+ },
+ {
+ id: 'hp',
+ label: 'HP-UX',
+ },
+ {
+ id: 'amazonlinux',
+ label: 'Amazon Linux',
+ },
+ {
+ id: 'fedora',
+ label: 'Fedora',
+ },
+ {
+ id: 'oraclelinux',
+ label: 'Oracle Linux',
+ },
+ {
+ id: 'suse',
+ label: 'SUSE',
+ },
+ {
+ id: 'raspbian',
+ label: 'Raspbian OS',
+ },
+ {
+ id: 'alpine',
+ label: 'Alpine',
+ },
+].sort(orderOSAlphabetically);
+
+export {
+ architectureButtons,
+ architecturei386Andx86_64,
+ versionButtonsRaspbian,
+ versionButtonsSuse,
+ architectureButtonsWithPPC64LE,
+ versionButtonsOracleLinux,
+ versionButtonFedora,
+ versionButtonsRedHat,
+ versionButtonsCentos,
+ versionButtonAlpine,
+ architectureButtonsMacos,
+ osButtons,
+ osPrincipalButtons,
+ versionButtonsDebian,
+ versionButtonsUbuntu,
+ versionButtonAmazonLinux,
+ versionButtonsWindows,
+ versionButtonsMacOS,
+ versionButtonsOpenSuse,
+ versionButtonsSolaris,
+ versionButtonsAix,
+ versionButtonsHPUX,
+ architectureButtonsi386,
+ architectureButtonsSolaris,
+ architectureButtonsAix,
+ architectureButtonsHpUx,
+ architectureButtonsWithPPC64LEAlpine,
+};
diff --git a/public/controllers/management/components/management/cdblists/components/cdblists-table.tsx b/public/controllers/management/components/management/cdblists/components/cdblists-table.tsx
new file mode 100644
index 0000000000..db27928072
--- /dev/null
+++ b/public/controllers/management/components/management/cdblists/components/cdblists-table.tsx
@@ -0,0 +1,191 @@
+/*
+ * Wazuh app - Agent vulnerabilities table component
+ * Copyright (C) 2015-2022 Wazuh, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Find more information about this on the LICENSE file.
+ */
+
+import React, { useState } from 'react';
+import { TableWzAPI } from '../../../../../../components/common/tables';
+import { getToasts } from '../../../../../../kibana-services';
+import { resourceDictionary, ResourcesConstants, ResourcesHandler } from '../../common/resources-handler';
+import { getErrorOrchestrator } from '../../../../../../react-services/common-services';
+import { UI_ERROR_SEVERITIES } from '../../../../../../react-services/error-orchestrator/types';
+import { UI_LOGGER_LEVELS } from '../../../../../../../common/constants';
+
+import { SECTION_CDBLIST_SECTION, SECTION_CDBLIST_KEY } from '../../common/constants';
+import CDBListsColumns from './columns';
+
+import { withUserPermissions } from '../../../../../../components/common/hocs/withUserPermissions';
+import { WzUserPermissions } from '../../../../../../react-services/wz-user-permissions';
+import { compose } from 'redux';
+import {
+ ManageFiles,
+ AddNewFileButton,
+ AddNewCdbListButton,
+ UploadFilesButton,
+} from '../../common/actions-buttons'
+
+function CDBListsTable(props) {
+ const [filters, setFilters] = useState([]);
+ const [showingFiles, setShowingFiles] = useState(false);
+ const [tableFootprint, setTableFootprint] = useState(0);
+
+ const resourcesHandler = new ResourcesHandler(ResourcesConstants.LISTS);
+
+ const updateFilters = (filters) => {
+ setFilters(filters);
+ }
+
+ const toggleShowFiles = () => {
+ setShowingFiles(!showingFiles);
+ }
+
+
+ const getColumns = () => {
+ const cdblistsColumns = new CDBListsColumns({
+ removeItems: removeItems,
+ state: {
+ section: SECTION_CDBLIST_KEY,
+ defaultItems: []
+ }, ...props
+ }).columns;
+ const columns = cdblistsColumns[SECTION_CDBLIST_KEY];
+ return columns;
+ }
+
+ /**
+ * Columns and Rows properties
+ */
+ const getRowProps = (item) => {
+ const { id, name } = item;
+
+ const getRequiredPermissions = (item) => {
+ const { permissionResource } = resourceDictionary[SECTION_CDBLIST_KEY];
+ return [
+ {
+ action: `${SECTION_CDBLIST_KEY}:read`,
+ resource: permissionResource(item.name),
+ },
+ ];
+ };
+
+ return {
+ 'data-test-subj': `row-${id || name}`,
+ className: 'customRowClass',
+ onClick: !WzUserPermissions.checkMissingUserPermissions(
+ getRequiredPermissions(item),
+ props.userPermissions
+ )
+ ? async (ev) => {
+ const result = await resourcesHandler.getFileContent(item.filename);
+ const file = {
+ name: item.filename,
+ content: result,
+ path: item.relative_dirname,
+ };
+ updateListContent(file);
+ }
+ : undefined,
+ };
+ };
+
+ /**
+ * Remove files method
+ */
+ const removeItems = async (items) => {
+ try {
+ const results = items.map(async (item, i) => {
+ await resourcesHandler.deleteFile(item.filename || item.name);
+ });
+
+ Promise.all(results).then((completed) => {
+ setTableFootprint(Date.now());
+ getToasts().add({
+ color: 'success',
+ title: 'Success',
+ text: 'Deleted successfully',
+ toastLifeTimeMs: 3000,
+ });
+ });
+ } catch (error) {
+ const options = {
+ context: `${WzRulesetTable.name}.removeItems`,
+ level: UI_LOGGER_LEVELS.ERROR,
+ severity: UI_ERROR_SEVERITIES.BUSINESS,
+ error: {
+ error: error,
+ message: `Error deleting item: ${error.message || error}`,
+ title: error.name || error,
+ },
+ };
+ getErrorOrchestrator().handleError(options);
+ }
+ }
+
+ const { updateRestartClusterManager, updateListContent } = props;
+ const columns = getColumns();
+
+ /**
+ * Build table custom action buttons dynamically based on showing files state
+ */
+ const actionButtons = [
+ ,
+ ,
+ ,
+ { updateRestartClusterManager && updateRestartClusterManager() }}
+ />,
+ ];
+
+
+
+ return (
+
+ );
+
+}
+
+
+export default compose(
+ withUserPermissions
+)(CDBListsTable);
\ No newline at end of file
diff --git a/public/controllers/management/components/management/cdblists/components/columns.tsx b/public/controllers/management/components/management/cdblists/components/columns.tsx
new file mode 100644
index 0000000000..7afa10ea9d
--- /dev/null
+++ b/public/controllers/management/components/management/cdblists/components/columns.tsx
@@ -0,0 +1,185 @@
+import React from 'react';
+import { EuiToolTip, EuiButtonIcon, EuiBadge } from '@elastic/eui';
+import { resourceDictionary, ResourcesHandler, ResourcesConstants } from '../../common/resources-handler';
+import exportCsv from '../../../../../../react-services/wz-csv';
+import { WzButtonPermissions } from '../../../../../../components/common/permissions/button';
+import { WzButtonPermissionsModalConfirm } from '../../../../../../components/common/buttons';
+import { getErrorOrchestrator } from '../../../../../../react-services/common-services';
+import { UIErrorLog } from '../../../../../../react-services/error-orchestrator/types';
+import { getErrorOptions } from '../../common/error-helper';
+import { Columns } from '../../common/interfaces';
+
+export default class CDBListsColumns {
+
+ columns: Columns = { lists: [] };
+
+ constructor(props) {
+ this.props = props;
+ this._buildColumns();
+ }
+
+ _buildColumns() {
+ this.columns = {
+ lists: [
+ {
+ field: 'filename',
+ name: 'Name',
+ align: 'left',
+ sortable: true
+ },
+ {
+ field: 'relative_dirname',
+ name: 'Path',
+ align: 'left',
+ sortable: true
+ },
+ {
+ name: 'Actions',
+ align: 'left',
+ render: (item) => (
+
+ {
+ try {
+ ev.stopPropagation();
+ await exportCsv(`/lists?path=${item.relative_dirname}/${item.filename}`,
+ [{ _isCDBList: true, name: 'path', value: `${item.relative_dirname}/${item.filename}` }],
+ item.filename
+ )
+ } catch (error) {
+ const options: UIErrorLog = getErrorOptions(
+ error,
+ 'Lists.exportFile'
+ );
+ getErrorOrchestrator().handleError(options);
+ }
+ }}
+ color="primary"
+ />
+
+ )
+ }
+ ]
+ };
+
+ const getReadButtonPermissions = (item) => {
+ const { permissionResource } = resourceDictionary[ResourcesConstants.LISTS];
+ return [
+ {
+ action: `${ResourcesConstants.LISTS}:read`,
+ resource: permissionResource(item.filename),
+ },
+ ];
+ };
+
+ const getEditButtonPermissions = (item) => {
+ const { permissionResource } = resourceDictionary[ResourcesConstants.LISTS];
+ return [
+ {
+ action: `${ResourcesConstants.LISTS}:read`,
+ resource: permissionResource(item.filename),
+ },
+ { action: `${ResourcesConstants.LISTS}:update`, resource: permissionResource(item.filename) },
+ ];
+ };
+
+ const getDeleteButtonPermissions = (item) => {
+ const { permissionResource } = resourceDictionary[ResourcesConstants.LISTS];
+ return [
+ {
+ action: `${ResourcesConstants.LISTS}:delete`,
+ resource: permissionResource(item.filename),
+ },
+ ];
+ };
+
+ // @ts-ignore
+ this.columns.lists[2] =
+ {
+ name: 'Actions',
+ align: 'left',
+ render: item => {
+ const defaultItems = this.props.state.defaultItems;
+ return (
+
+ {
+ try {
+ ev.stopPropagation();
+ const resourcesHandler = new ResourcesHandler(ResourcesConstants.LISTS);
+ const result = await resourcesHandler.getFileContent(item.filename);
+ const file = { name: item.filename, content: result, path: item.relative_dirname };
+ this.props.updateListContent(file);
+ } catch (error) {
+ const options: UIErrorLog = getErrorOptions(
+ error,
+ 'Lists.editFileContent'
+ );
+ getErrorOrchestrator().handleError(options);
+ }
+ }}
+ color="primary"
+ />
+ {
+ try {
+ this.props.removeItems([item])
+ } catch (error) {
+ const options: UIErrorLog = getErrorOptions(
+ error,
+ 'Lists.deleteFile'
+ );
+ getErrorOrchestrator().handleError(options);
+ }
+ }}
+ onClose={async (ev) => ev.stopPropagation()}
+ onClick={(ev) => ev.stopPropagation()}
+ color="danger"
+ modalTitle={'Are you sure?'}
+ modalProps={{
+ buttonColor: 'danger',
+ onClick: (ev) => ev.stopPropagation()
+ }}
+ />
+ {
+ try {
+ ev.stopPropagation();
+ await exportCsv(`/lists`,
+ [{ _isCDBList: true, name: 'filename', value: `${item.filename}` }],
+ item.filename
+ )
+ } catch (error) {
+ const options: UIErrorLog = getErrorOptions(
+ error,
+ 'Lists.exportFile'
+ );
+ getErrorOrchestrator().handleError(options);
+ }
+ }}
+ color="primary"
+ />
+
+ )
+ }
+ }
+ };
+}
diff --git a/public/controllers/management/components/management/cdblists/main-cdblists.tsx b/public/controllers/management/components/management/cdblists/main-cdblists.tsx
new file mode 100644
index 0000000000..1071e38602
--- /dev/null
+++ b/public/controllers/management/components/management/cdblists/main-cdblists.tsx
@@ -0,0 +1,40 @@
+/*
+ * Wazuh app - React component for main CDB List view.
+ * Copyright (C) 2015-2022 Wazuh, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Find more information about this on the LICENSE file.
+ */
+import React, { useState } from 'react';
+// Redux
+import WzReduxProvider from '../../../../../redux/wz-redux-provider';
+import WzCDBListsOverview from './views/cdblists-overview';
+import WzListEditor from './views/list-editor';
+
+export default function WzCDBList({ clusterStatus }) {
+ const [listContent, setListContent] = useState(false);
+
+ return (
+
+ {
+ (listContent && (
+ { setListContent(false) }}
+ updateListContent={(listContent) => { setListContent(listContent) }}
+ />
+ )) || (
+ { setListContent(listContent) }}
+ />
+ )
+ }
+
+ );
+}
diff --git a/public/controllers/management/components/management/cdblists/views/cdblists-overview.tsx b/public/controllers/management/components/management/cdblists/views/cdblists-overview.tsx
new file mode 100644
index 0000000000..eb836acea4
--- /dev/null
+++ b/public/controllers/management/components/management/cdblists/views/cdblists-overview.tsx
@@ -0,0 +1,69 @@
+import React, { useState } from 'react';
+
+// Eui components
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiPanel,
+ EuiPage,
+ EuiSpacer
+} from '@elastic/eui';
+
+// Wazuh components
+import { withUserAuthorizationPrompt, withGlobalBreadcrumb } from '../../../../../../components/common/hocs';
+import { compose } from 'redux';
+import { resourceDictionary } from '../../common/resources-handler';
+import { SECTION_CDBLIST_NAME, SECTION_CDBLIST_KEY } from '../../common/constants';
+import CDBListsTable from '../components/cdblists-table';
+import '../../common/layout-overview.scss';
+import WzRestartClusterManagerCallout from '../../../../../../components/common/restart-cluster-manager-callout';
+
+
+function WzCDBListsOverview(props) {
+
+ const [showWarningRestart, setShowWarningRestart] = useState(false);
+
+ const updateRestartManagers = (showWarningRestart) => {
+ setShowWarningRestart(showWarningRestart);
+ }
+
+ const { clusterStatus } = props;
+ return
+
+ {showWarningRestart && (
+ <>
+
+ updateRestartManagers(false)}
+ onRestartedError={() => updateRestartManagers(true)}
+ />
+
+ >
+ )}
+
+
+
+ updateRestartManagers(showWarningRestart)}
+ />
+
+
+
+ ;
+}
+
+
+export default compose(
+ withGlobalBreadcrumb(props => {
+ return [
+ { text: '' },
+ { text: 'Management', href: '#/manager' },
+ { text: SECTION_CDBLIST_NAME}
+ ];
+ }),
+ withUserAuthorizationPrompt((props) => [
+ { action: `${SECTION_CDBLIST_KEY}:read`, resource: resourceDictionary[SECTION_CDBLIST_KEY].permissionResource('*') }
+ ])
+)(WzCDBListsOverview);
diff --git a/public/controllers/management/components/management/ruleset/list-editor.js b/public/controllers/management/components/management/cdblists/views/list-editor.tsx
similarity index 89%
rename from public/controllers/management/components/management/ruleset/list-editor.js
rename to public/controllers/management/components/management/cdblists/views/list-editor.tsx
index b91b4e6997..88ba63855d 100644
--- a/public/controllers/management/components/management/ruleset/list-editor.js
+++ b/public/controllers/management/components/management/cdblists/views/list-editor.tsx
@@ -18,10 +18,8 @@ import {
EuiTitle,
EuiToolTip,
EuiButtonIcon,
- EuiButton,
EuiText,
EuiButtonEmpty,
- EuiPopover,
EuiFieldText,
EuiSpacer,
EuiPanel,
@@ -29,21 +27,20 @@ import {
import { connect } from 'react-redux';
-import { cleanInfo, updateListContent } from '../../../../../redux/actions/rulesetActions';
+import { resourceDictionary, ResourcesHandler, ResourcesConstants } from '../../common/resources-handler';
-import { resourceDictionary, RulesetHandler, RulesetResources } from './utils/ruleset-handler';
+import { getToasts } from '../../../../../../kibana-services';
-import { getToasts } from '../../../../../kibana-services';
+import exportCsv from '../../../../../../react-services/wz-csv';
-import exportCsv from '../../../../../react-services/wz-csv';
+import { updateWazuhNotReadyYet } from '../../../../../../redux/actions/appStateActions';
+import WzRestartClusterManagerCallout from '../../../../../../components/common/restart-cluster-manager-callout';
+import { WzButtonPermissions } from '../../../../../../components/common/permissions/button';
-import { updateWazuhNotReadyYet } from '../../../../../redux/actions/appStateActions';
-import WzRestartClusterManagerCallout from '../../../../../components/common/restart-cluster-manager-callout';
-import { WzButtonPermissions } from '../../../../../components/common/permissions/button';
+import { UI_ERROR_SEVERITIES } from '../../../../../../react-services/error-orchestrator/types';
+import { UI_LOGGER_LEVELS } from '../../../../../../../common/constants';
+import { getErrorOrchestrator } from '../../../../../../react-services/common-services';
-import { UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchestrator/types';
-import { UI_LOGGER_LEVELS } from '../../../../../../common/constants';
-import { getErrorOrchestrator } from '../../../../../react-services/common-services';
class WzListEditor extends Component {
constructor(props) {
super(props);
@@ -60,12 +57,11 @@ class WzListEditor extends Component {
};
this.items = {};
- this.rulesetHandler = new RulesetHandler(RulesetResources.LISTS);
+ this.resourcesHandler = new ResourcesHandler(ResourcesConstants.LISTS);
}
componentDidMount() {
- const { listInfo } = this.props.state;
- const { content } = listInfo;
+ const { listContent: { content } } = this.props;
const obj = this.contentToObject(content);
this.items = { ...obj };
const items = this.contentToArray(obj);
@@ -136,7 +132,7 @@ class WzListEditor extends Component {
return;
}
this.setState({ isSaving: true });
- await this.rulesetHandler.updateFile(name, raw, overwrite);
+ await this.resourcesHandler.updateFile(name, raw, overwrite);
if (!addingNew) {
const file = { name: name, content: raw, path: path };
this.props.updateListContent(file);
@@ -211,8 +207,8 @@ class WzListEditor extends Component {
getUpdatePermissions = (name) => {
return [
{
- action: `${RulesetResources.LISTS}:update`,
- resource: resourceDictionary[RulesetResources.LISTS].permissionResource(name),
+ action: `${ResourcesConstants.LISTS}:update`,
+ resource: resourceDictionary[ResourcesConstants.LISTS].permissionResource(name),
},
];
};
@@ -220,8 +216,8 @@ class WzListEditor extends Component {
getDeletePermissions = (name) => {
return [
{
- action: `${RulesetResources.LISTS}:delete`,
- resource: resourceDictionary[RulesetResources.LISTS].permissionResource(name),
+ action: `${ResourcesConstants.LISTS}:delete`,
+ resource: resourceDictionary[ResourcesConstants.LISTS].permissionResource(name),
},
];
};
@@ -292,7 +288,7 @@ class WzListEditor extends Component {
color="primary"
iconSize="l"
iconType="arrowLeft"
- onClick={() => this.props.cleanInfo()}
+ onClick={() => this.props.clearContent()}
/>
{name}
@@ -420,7 +416,7 @@ class WzListEditor extends Component {
color="primary"
iconSize="l"
iconType="arrowLeft"
- onClick={() => this.props.cleanInfo()}
+ onClick={() => this.props.clearContent()}
/>
{name}
@@ -525,13 +521,10 @@ class WzListEditor extends Component {
];
}
- //isDisabled={nameForSaving.length <= 4}
render() {
- const { listInfo, isLoading, error } = this.props.state;
- const { name, path } = listInfo;
+ const { listContent: { name, path }, isLoading } = this.props;
const message = isLoading ? false : 'No results...';
- const columns = this.columns;
const addingNew = name === false || !name;
const listName = this.state.newListName || name;
@@ -635,19 +628,11 @@ class WzListEditor extends Component {
}
}
-const mapStateToProps = (state) => {
- return {
- state: state.rulesetReducers,
- };
-};
-
const mapDispatchToProps = (dispatch) => {
return {
- cleanInfo: () => dispatch(cleanInfo()),
- updateListContent: (content) => dispatch(updateListContent(content)),
updateWazuhNotReadyYet: (wazuhNotReadyYet) =>
dispatch(updateWazuhNotReadyYet(wazuhNotReadyYet)),
};
};
-export default connect(mapStateToProps, mapDispatchToProps)(WzListEditor);
+export default connect(null, mapDispatchToProps)(WzListEditor);
diff --git a/public/controllers/management/components/management/common/actions-buttons.tsx b/public/controllers/management/components/management/common/actions-buttons.tsx
new file mode 100644
index 0000000000..8222516a6a
--- /dev/null
+++ b/public/controllers/management/components/management/common/actions-buttons.tsx
@@ -0,0 +1,187 @@
+/*
+ * Wazuh app - React component for tables custom action buttons.
+ * Copyright (C) 2015-2022 Wazuh, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Find more information about this on the LICENSE file.
+ */
+import React from 'react';
+// Eui components
+
+import { UploadFiles } from '../../upload-files';
+import { resourceDictionary, ResourcesHandler } from './resources-handler';
+import { WzButtonPermissions } from '../../../../../components/common/permissions/button';
+
+import { UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchestrator/types';
+import { UI_LOGGER_LEVELS } from '../../../../../../common/constants';
+import { getErrorOrchestrator } from '../../../../../react-services/common-services';
+import { SECTION_CDBLIST_SECTION } from './constants';
+
+/**
+ * Uploads the files
+ * @param {Array} files
+ * @param {String} path
+ */
+async function uploadFiles(files, resource, overwrite) {
+ try {
+ let errors = false;
+ let results: any[] = [];
+ const resourcesHandler = new ResourcesHandler(resource);
+ for (let idx in files) {
+ const { file, content } = files[idx];
+ try {
+ await resourcesHandler.updateFile(file, content, overwrite);
+ results.push({
+ index: idx,
+ uploaded: true,
+ file: file,
+ error: 0,
+ });
+ } catch (error) {
+ errors = true;
+ results.push({
+ index: idx,
+ uploaded: false,
+ file: file,
+ error: error,
+ });
+ }
+ }
+ if (errors) throw results;
+ return results;
+ } catch (error) {
+ throw error;
+ }
+}
+
+const getReadPermissionsFiles = (section) => {
+ const { permissionResource } = resourceDictionary[section];
+ return [
+ {
+ action: `${section}:read`,
+ resource: permissionResource('*'),
+ },
+ ];
+};
+
+const getUpdatePermissionsFiles = (section) => {
+ const { permissionResource } = resourceDictionary[section];
+ return [
+ {
+ action: `${section}:update`,
+ resource: permissionResource('*'),
+ },
+ {
+ action: `${section}:read`,
+ resource: permissionResource('*'),
+ },
+ ];
+};
+
+// Add new rule button
+export const AddNewFileButton = ({ section, updateAddingFile }) => (
+ <>{
+ section !== SECTION_CDBLIST_SECTION &&
+
+ updateAddingFile({
+ name: '',
+ content: '',
+ path: `etc/${section}`,
+ })
+ }
+ >
+ {`Add new ${section} file`}
+
+ }>
+)
+
+//Add new CDB list button
+export const AddNewCdbListButton = (({ section, updateListContent }) => {
+ return <>
+
+ updateListContent({
+ name: false,
+ content: '',
+ path: 'etc/lists',
+ })
+ }
+ >
+ {`Add new ${section} file`}
+
+ >
+});
+
+// Manage files
+export const ManageFiles = (({ section, showingFiles, ...props }) => {
+
+ /**
+ * Toggle between files and rules or decoders
+ */
+ const toggleFiles = async () => {
+ try {
+ props.toggleShowFiles(!showingFiles);
+ } catch (error) {
+ const options = {
+ context: 'ActionButtons.toggleFiles',
+ level: UI_LOGGER_LEVELS.ERROR,
+ severity: UI_ERROR_SEVERITIES.BUSINESS,
+ store: false,
+ error: {
+ error: error,
+ message: `Error toggling to files: ${error.message || error}`,
+ title: error.name || error,
+ },
+ };
+ getErrorOrchestrator().handleError(options);
+ }
+ }
+ return (
+ <>
+ {section !== SECTION_CDBLIST_SECTION &&
+ await toggleFiles()}
+ >
+ {showingFiles ? `Manage ${section}` : `Manage ${section} files`}
+ }
+ >
+ )
+});
+
+const uploadFile = async (files, resource, overwrite) => {
+ try {
+ const result = await uploadFiles(files, resource, overwrite);
+ return result;
+ } catch (error) {
+ return error;
+ }
+};
+
+export const UploadFilesButton = (({ clusterStatus, section, showingFiles, onSuccess, ...props }) => {
+
+ return (
+ {
+ onSuccess && onSuccess(true)
+ }}
+ />
+ )
+});
diff --git a/public/controllers/management/components/management/ruleset/utils/colors.js b/public/controllers/management/components/management/common/colors.ts
similarity index 100%
rename from public/controllers/management/components/management/ruleset/utils/colors.js
rename to public/controllers/management/components/management/common/colors.ts
diff --git a/public/controllers/management/components/management/common/constants.ts b/public/controllers/management/components/management/common/constants.ts
new file mode 100644
index 0000000000..4ad8214e6f
--- /dev/null
+++ b/public/controllers/management/components/management/common/constants.ts
@@ -0,0 +1,11 @@
+export const SECTION_RULES_NAME = 'Rules';
+export const SECTION_RULES_KEY = 'rules';
+export const SECTION_RULES_SECTION = 'rules';
+
+export const SECTION_DECODERS_NAME = 'Decoders';
+export const SECTION_DECODERS_KEY = 'decoders';
+export const SECTION_DECODERS_SECTION = 'decoders';
+
+export const SECTION_CDBLIST_NAME = 'CDB lists';
+export const SECTION_CDBLIST_KEY = 'lists';
+export const SECTION_CDBLIST_SECTION = 'lists';
diff --git a/public/controllers/management/components/management/common/error-helper.ts b/public/controllers/management/components/management/common/error-helper.ts
new file mode 100644
index 0000000000..813b792303
--- /dev/null
+++ b/public/controllers/management/components/management/common/error-helper.ts
@@ -0,0 +1,21 @@
+import { UIErrorLog, UILogLevel, UIErrorSeverity, UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchestrator/types';
+import { UI_LOGGER_LEVELS } from '../../../../../../common/constants';
+/**
+ * Build and return a new error options object, based on the actual error
+ * and the context
+ * @param error raised error
+ * @param context context of the error
+ * @returns a dictionary with the error details for the ErrorOrchestator
+ */
+ export function getErrorOptions(error: unknown, context: string): UIErrorLog {
+ return {
+ context: context,
+ level: UI_LOGGER_LEVELS.ERROR as UILogLevel,
+ severity: UI_ERROR_SEVERITIES.BUSINESS as UIErrorSeverity,
+ error: {
+ error: error,
+ message: error?.message || error,
+ title: error?.name,
+ },
+ };
+ }
\ No newline at end of file
diff --git a/public/controllers/management/components/management/ruleset/ruleset-editor.js b/public/controllers/management/components/management/common/file-editor.tsx
similarity index 88%
rename from public/controllers/management/components/management/ruleset/ruleset-editor.js
rename to public/controllers/management/components/management/common/file-editor.tsx
index 73046b2d84..17b3f0de05 100644
--- a/public/controllers/management/components/management/ruleset/ruleset-editor.js
+++ b/public/controllers/management/components/management/common/file-editor.tsx
@@ -12,10 +12,6 @@
import React, { Component, Fragment } from 'react';
import { connect } from 'react-redux';
-import {
- cleanInfo,
- updateFileContent
-} from '../../../../../redux/actions/rulesetActions';
import 'brace/theme/textmate';
// Eui components
@@ -34,8 +30,8 @@ import {
EuiPanel,
} from '@elastic/eui';
-import { resourceDictionary, RulesetHandler, RulesetResources } from './utils/ruleset-handler';
-import validateConfigAfterSent from './utils/valid-configuration';
+import { resourceDictionary, ResourcesHandler } from './resources-handler';
+import validateConfigAfterSent from './valid-configuration';
import { getToasts } from '../../../../../kibana-services';
import { updateWazuhNotReadyYet } from '../../../../../redux/actions/appStateActions';
@@ -47,14 +43,13 @@ import 'brace/mode/xml';
import 'brace/snippets/xml';
import 'brace/ext/language_tools';
import "brace/ext/searchbox";
-import { showFlyoutLogtest } from '../../../../../redux/actions/appStateActions';
import _ from 'lodash';
import { UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchestrator/types';
import { UI_LOGGER_LEVELS } from '../../../../../../common/constants';
import { getErrorOrchestrator } from '../../../../../react-services/common-services';
-class WzRulesetEditor extends Component {
+class WzFileEditor extends Component {
_isMounted = false;
constructor(props) {
super(props);
@@ -68,9 +63,9 @@ class WzRulesetEditor extends Component {
enableSnippets: true,
enableLiveAutocompletion: false,
};
- this.rulesetHandler = new RulesetHandler(this.props.state.section);
- const { fileContent, addingRulesetFile } = this.props.state;
- const { name, content, path } = fileContent ? fileContent : addingRulesetFile;
+ this.resourcesHandler = new ResourcesHandler(this.props.section);
+ const { fileContent, addingFile } = this.props;
+ const { name, content, path } = fileContent ? fileContent : addingFile;
this.state = {
isSaving: false,
@@ -89,13 +84,19 @@ class WzRulesetEditor extends Component {
componentWillUnmount() {
// When the component is going to be unmounted its info is clear
this._isMounted = false;
- this.props.cleanInfo();
+ this.props.cleanEditState();
}
componentDidMount() {
this._isMounted = true;
}
+ /**
+ * Check if the file content has changed and is not empty
+ */
+ contentHasChanged() {
+ return !!this.state.content.trim() && (this.state.content.trim() !== this.state.initContent.trim());
+ }
/**
* Save the new content
@@ -106,7 +107,7 @@ class WzRulesetEditor extends Component {
if (!this._isMounted) {
return;
}else if(/\s/.test(name)) {
- this.showToast('warning', 'Warning', `The ${this.props.state.section} name must not contain spaces.`, 3000);
+ this.showToast('warning', 'Warning', `The ${this.props.section} name must not contain spaces.`, 3000);
return;
}
try {
@@ -114,12 +115,12 @@ class WzRulesetEditor extends Component {
this.setState({ isSaving: true, error: false });
- await this.rulesetHandler.updateFile(name, content, overwrite);
+ await this.resourcesHandler.updateFile(name, content, overwrite);
try {
await validateConfigAfterSent();
} catch (error) {
const options = {
- context: `${WzRulesetEditor.name}.save`,
+ context: `${WzFileEditor.name}.save`,
level: UI_LOGGER_LEVELS.ERROR,
severity: UI_ERROR_SEVERITIES.BUSINESS,
error: {
@@ -134,13 +135,13 @@ class WzRulesetEditor extends Component {
let toastMessage;
- if (this.props.state.addingRulesetFile != false) {
+ if (this.props.addingFile != false) {
//remove current invalid file if the file is new.
- await this.rulesetHandler.deleteFile(name);
+ await this.resourcesHandler.deleteFile(name);
toastMessage = 'The new file was deleted.';
} else {
//restore file to previous version
- await this.rulesetHandler.updateFile(name, this.state.initContent, overwrite);
+ await this.resourcesHandler.updateFile(name, this.state.initContent, overwrite);
toastMessage = 'The content file was restored to previous state.';
}
@@ -156,14 +157,20 @@ class WzRulesetEditor extends Component {
});
} catch (error) {
+ let errorMessage;
+ if (error instanceof Error) {
+ errorMessage = error.details
+ ? error.details
+ : String(error);
+ }
this.setState({ error, isSaving: false });
const options = {
- context: `${WzRulesetEditor.name}.save`,
+ context: `${WzFileEditor.name}.save`,
level: UI_LOGGER_LEVELS.ERROR,
severity: UI_ERROR_SEVERITIES.BUSINESS,
error: {
error: error,
- message: errorMessage,
+ message: errorMessage || error,
title: error.name || error,
},
};
@@ -196,15 +203,15 @@ class WzRulesetEditor extends Component {
};
render() {
- const { section, addingRulesetFile, fileContent } = this.props.state;
+ const { section, addingFile, fileContent } = this.props;
const { wazuhNotReadyYet } = this.props;
const { name, content, path, showWarningRestart } = this.state;
const isRules = path.includes('rules') ? 'Ruleset Test' : 'Decoders Test';
- const isEditable = addingRulesetFile
+ const isEditable = addingFile
? true
: path !== 'ruleset/rules' && path !== 'ruleset/decoders';
- let nameForSaving = addingRulesetFile ? this.state.inputValue : name;
+ let nameForSaving = addingFile ? this.state.inputValue : name;
nameForSaving = nameForSaving.endsWith('.xml') ? nameForSaving : `${nameForSaving}.xml`;
const overwrite = fileContent ? true : false;
@@ -212,7 +219,6 @@ class WzRulesetEditor extends Component {
const onClickOpenLogtest = () => {
this.props.logtestProps.openCloseFlyout();
- this.props.showFlyoutLogtest(true);
};
const buildLogtestButton = () => {
@@ -243,7 +249,7 @@ class WzRulesetEditor extends Component {
fill
iconType={isEditable && xmlError ? 'alert' : 'save'}
isLoading={this.state.isSaving}
- isDisabled={nameForSaving.length <= 4 || !!(isEditable && xmlError)}
+ isDisabled={nameForSaving.length <= 4 || !!(isEditable && xmlError) || !this.contentHasChanged()}
onClick={() => this.save(nameForSaving, overwrite)}
>
{isEditable && xmlError ? 'XML format error' : 'Save'}
@@ -262,7 +268,7 @@ class WzRulesetEditor extends Component {
title="Unsubmitted changes"
onConfirm={() => {
closeModal;
- this.props.cleanInfo();
+ this.props.cleanEditState();
}}
onCancel={closeModal}
cancelButtonText="No, don't do it"
@@ -300,7 +306,7 @@ class WzRulesetEditor extends Component {
) {
showModal();
} else {
- this.props.cleanInfo();
+ this.props.cleanEditState();
}
}}
/>
@@ -332,7 +338,7 @@ class WzRulesetEditor extends Component {
) {
showModal();
} else {
- this.props.cleanInfo();
+ this.props.cleanEditState();
}
}}
/>
@@ -408,7 +414,6 @@ class WzRulesetEditor extends Component {
const mapStateToProps = state => {
return {
- state: state.rulesetReducers,
wazuhNotReadyYet: state.appStateReducers.wazuhNotReadyYet,
showFlyout: state.appStateReducers.showFlyoutLogtest,
};
@@ -416,14 +421,11 @@ const mapStateToProps = state => {
const mapDispatchToProps = dispatch => {
return {
- cleanInfo: () => dispatch(cleanInfo()),
- updateFileContent: content => dispatch(updateFileContent(content)),
updateWazuhNotReadyYet: wazuhNotReadyYet => dispatch(updateWazuhNotReadyYet(wazuhNotReadyYet)),
- showFlyoutLogtest: showFlyout => dispatch(showFlyoutLogtest(showFlyout)),
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
-)(WzRulesetEditor);
+)(WzFileEditor);
diff --git a/public/controllers/management/components/management/common/flyout-detail.scss b/public/controllers/management/components/management/common/flyout-detail.scss
new file mode 100644
index 0000000000..197d3e62c4
--- /dev/null
+++ b/public/controllers/management/components/management/common/flyout-detail.scss
@@ -0,0 +1,17 @@
+.wz-decoders-flyout,
+.wz-ruleset-flyout {
+ .flyout-header {
+ padding-right: 42px;
+ }
+
+ .euiAccordion__button {
+ margin-top: 8px;
+ }
+
+ .euiFlyoutBody__overflow {
+ padding-top: 3px;
+ }
+ .euiAccordion__children-isLoading {
+ line-height: inherit;
+ }
+}
\ No newline at end of file
diff --git a/public/controllers/management/components/management/common/interfaces.ts b/public/controllers/management/components/management/common/interfaces.ts
new file mode 100644
index 0000000000..13b79041a9
--- /dev/null
+++ b/public/controllers/management/components/management/common/interfaces.ts
@@ -0,0 +1,15 @@
+export interface ColumnProps {
+ field?: string;
+ name?: string;
+ align?: string;
+ sortable?: boolean;
+ width?: string;
+ render?: Function | undefined
+}
+
+export interface Columns {
+ decoders?: Array;
+ rules?: Array;
+ lists?: Array;
+ files?: Array;
+}
\ No newline at end of file
diff --git a/public/controllers/management/components/management/ruleset/ruleset-overview.scss b/public/controllers/management/components/management/common/layout-overview.scss
similarity index 100%
rename from public/controllers/management/components/management/ruleset/ruleset-overview.scss
rename to public/controllers/management/components/management/common/layout-overview.scss
diff --git a/public/controllers/management/components/management/ruleset/utils/ruleset-handler.ts b/public/controllers/management/components/management/common/resources-handler.ts
similarity index 84%
rename from public/controllers/management/components/management/ruleset/utils/ruleset-handler.ts
rename to public/controllers/management/components/management/common/resources-handler.ts
index bff3abb517..293db983b8 100644
--- a/public/controllers/management/components/management/ruleset/utils/ruleset-handler.ts
+++ b/public/controllers/management/components/management/common/resources-handler.ts
@@ -1,31 +1,36 @@
-import { WzRequest } from '../../../../../../react-services';
+import { WzRequest } from '../../../../../react-services';
+import {
+ SECTION_DECODERS_SECTION,
+ SECTION_RULES_SECTION,
+ SECTION_CDBLIST_SECTION
+} from './constants';
type DECODERS = 'decoders';
type LISTS = 'lists';
type RULES = 'rules';
export type Resource = DECODERS | LISTS | RULES;
-export const RulesetResources = {
- DECODERS: 'decoders',
- LISTS: 'lists',
- RULES: 'rules',
+export const ResourcesConstants = {
+ DECODERS: SECTION_DECODERS_SECTION,
+ LISTS: SECTION_CDBLIST_SECTION,
+ RULES: SECTION_RULES_SECTION,
};
export const resourceDictionary = {
- [RulesetResources.DECODERS]: {
+ [ResourcesConstants.DECODERS]: {
resourcePath: '/decoders',
permissionResource: (value) => `decoder:file:${value}`
},
- [RulesetResources.LISTS]: {
+ [ResourcesConstants.LISTS]: {
resourcePath: '/lists',
permissionResource: (value) => `list:file:${value}`
},
- [RulesetResources.RULES]: {
+ [ResourcesConstants.RULES]: {
resourcePath: '/rules',
permissionResource: (value) => `rule:file:${value}`
},
};
-export class RulesetHandler {
+export class ResourcesHandler {
resource: Resource;
constructor(_resource: Resource) {
this.resource = _resource;
diff --git a/public/controllers/management/components/management/ruleset/utils/valid-configuration.js b/public/controllers/management/components/management/common/valid-configuration.ts
similarity index 95%
rename from public/controllers/management/components/management/ruleset/utils/valid-configuration.js
rename to public/controllers/management/components/management/common/valid-configuration.ts
index 41019120ed..9ffe4376da 100644
--- a/public/controllers/management/components/management/ruleset/utils/valid-configuration.js
+++ b/public/controllers/management/components/management/common/valid-configuration.ts
@@ -10,7 +10,7 @@
* Find more information about this on the LICENSE file.
*/
-import { WzRequest } from '../../../../../../react-services/wz-request';
+import { WzRequest } from '../../../../../react-services/wz-request';
const validateConfigAfterSent = async (node = false) => {
try {
diff --git a/public/controllers/management/components/management/configuration/alerts/__snapshots__/alerts-configurations.test.tsx.snap b/public/controllers/management/components/management/configuration/alerts/__snapshots__/alerts-configurations.test.tsx.snap
index eb5dab7a8c..3f023d84b1 100644
--- a/public/controllers/management/components/management/configuration/alerts/__snapshots__/alerts-configurations.test.tsx.snap
+++ b/public/controllers/management/components/management/configuration/alerts/__snapshots__/alerts-configurations.test.tsx.snap
@@ -12,22 +12,15 @@ exports[`WzConfigurationAlerts component mount OK renders correctly to match the
"replaceReducer": [Function],
"subscribe": [Function],
},
- "subscription": Subscription {
+ "subscription": Object {
+ "addNestedSub": [Function],
+ "getListeners": [Function],
"handleChangeWrapper": [Function],
- "listeners": Object {
- "notify": [Function],
- },
+ "isSubscribed": [Function],
+ "notifyNestedSubs": [Function],
"onStateChange": [Function],
- "parentSub": undefined,
- "store": Object {
- "clearActions": [Function],
- "dispatch": [Function],
- "getActions": [Function],
- "getState": [Function],
- "replaceReducer": [Function],
- "subscribe": [Function],
- },
- "unsubscribe": null,
+ "trySubscribe": [Function],
+ "tryUnsubscribe": [Function],
},
}
}
diff --git a/public/controllers/management/components/management/configuration/configuration-no-agent.js b/public/controllers/management/components/management/configuration/configuration-no-agent.js
index a0287a8bd9..4e10f9aded 100644
--- a/public/controllers/management/components/management/configuration/configuration-no-agent.js
+++ b/public/controllers/management/components/management/configuration/configuration-no-agent.js
@@ -26,7 +26,11 @@ export const WzAgentNeverConnectedPrompt = () => (
The agent has been registered but has not yet connected to the manager.
-
+
Checking connection with the Wazuh server
@@ -36,4 +40,4 @@ export const WzAgentNeverConnectedPrompt = () => (
Back
}
- />)
\ No newline at end of file
+ />)
diff --git a/public/controllers/management/components/management/configuration/configuration-settings.js b/public/controllers/management/components/management/configuration/configuration-settings.js
index b89a6e710d..459e3e8f58 100644
--- a/public/controllers/management/components/management/configuration/configuration-settings.js
+++ b/public/controllers/management/components/management/configuration/configuration-settings.js
@@ -133,7 +133,7 @@ export default [
{
name: 'Inventory data',
description:
- 'Gather relevant information about system OS, hardware, networking and packages',
+ 'Gather relevant information about system operating system, hardware, networking and packages',
goto: 'inventory'
},
{
diff --git a/public/controllers/management/components/management/configuration/global-configuration/global-configuration-remote.js b/public/controllers/management/components/management/configuration/global-configuration/global-configuration-remote.js
index a284e2b7ad..2c0a2bddae 100644
--- a/public/controllers/management/components/management/configuration/global-configuration/global-configuration-remote.js
+++ b/public/controllers/management/components/management/configuration/global-configuration/global-configuration-remote.js
@@ -62,17 +62,17 @@ class WzConfigurationGlobalConfigurationRemote extends Component {
{ field: 'ipv6', name: 'IPv6', render: renderValueOrNoValue },
{
field: 'allowed-ips',
- name: 'Allowed IPs',
+ name: 'Allowed IP addresses',
render: item => renderAllowedDeniedIPs(item, 'allowed')
},
{
field: 'denied-ips',
- name: 'Denied Ips',
+ name: 'Denied IP addresses',
render: item => renderAllowedDeniedIPs(item, 'denied')
},
{
field: 'local_ip',
- name: 'Local IP',
+ name: 'Local IP address',
render: renderValueOrDefault('All interfaces')
},
{
diff --git a/public/controllers/management/components/management/configuration/integrations/integrations.js b/public/controllers/management/components/management/configuration/integrations/integrations.js
index 371971a6df..f76db6110a 100644
--- a/public/controllers/management/components/management/configuration/integrations/integrations.js
+++ b/public/controllers/management/components/management/configuration/integrations/integrations.js
@@ -57,7 +57,7 @@ const integrationsSettings = [
{ field: 'group', label: 'Filter alerts by these rule groupst' },
{
field: 'event_location',
- label: 'Filter alerts by location (agent, IP or file)'
+ label: 'Filter alerts by location (agent, IP address or file)'
},
{ field: 'alert_format', label: 'Used format to write alerts' }
];
diff --git a/public/controllers/management/components/management/configuration/log-collection/log-collection-commands.js b/public/controllers/management/components/management/configuration/log-collection/log-collection-commands.js
index 9321204bfb..1cbede8688 100644
--- a/public/controllers/management/components/management/configuration/log-collection/log-collection-commands.js
+++ b/public/controllers/management/components/management/configuration/log-collection/log-collection-commands.js
@@ -15,15 +15,12 @@ import React, { Component, Fragment } from 'react';
import WzNoConfig from '../util-components/no-config';
import WzConfigurationSettingsTabSelector from '../util-components/configuration-settings-tab-selector';
import WzConfigurationListSelector from '../util-components/configuration-settings-list-selector';
-import {
- isString,
- renderValueOrDefault,
- renderValueOrNoValue
-} from '../utils/utils';
+import { isString, renderValueOrDefault, renderValueOrNoValue } from '../utils/utils';
import { settingsListBuilder } from '../utils/builders';
import helpLinks from './help-links';
+import { LOGCOLLECTOR_LOCALFILE_PROP, LOCALFILE_COMMANDS_PROP } from './types';
-const renderTargetField = item => item ? item.join(', ') : 'agent';
+const renderTargetField = (item) => (item ? item.join(', ') : 'agent');
const mainSettings = [
{ field: 'logformat', label: 'Log format' },
@@ -32,54 +29,40 @@ const mainSettings = [
{
field: 'frequency',
label: 'Interval between command executions',
- render: renderValueOrNoValue
+ render: renderValueOrNoValue,
},
{
field: 'target',
label: 'Redirect output to this socket',
- render: renderTargetField
- }
+ render: renderTargetField,
+ },
];
-
class WzConfigurationLogCollectionCommands extends Component {
constructor(props) {
super(props);
}
render() {
const { currentConfig } = this.props;
- const items =
- currentConfig['logcollector-localfile'] &&
- currentConfig['logcollector-localfile']['localfile-commands']
- ? settingsListBuilder(
- currentConfig['logcollector-localfile']['localfile-commands'],
- [
- 'file',
- 'alias',
- 'commnad',
- (item) => `${item.logformat}${item.target ? ` - ${item.target.join(', ')}` : ''}`
- ]
- )
- : [];
+ const items = currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]?.[LOCALFILE_COMMANDS_PROP]
+ ? settingsListBuilder(currentConfig[LOGCOLLECTOR_LOCALFILE_PROP][LOCALFILE_COMMANDS_PROP], [
+ 'file',
+ 'alias',
+ 'commnad',
+ (item) => `${item.logformat}${item.target ? ` - ${item.target.join(', ')}` : ''}`,
+ ])
+ : [];
return (
- {currentConfig['logcollector-localfile'] &&
- isString(currentConfig['logcollector-localfile']) && (
-
- )}
- {currentConfig['logcollector-localfile'] &&
- !isString(currentConfig['logcollector-localfile']) &&
- !(currentConfig['logcollector-localfile']['localfile-commands'] || [])
- .length ? (
+ {isString(currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]) && (
+
+ )}
+ {!isString(currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]) &&
+ !currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]?.[LOCALFILE_COMMANDS_PROP]?.length ? (
) : null}
- {currentConfig['logcollector-localfile'] &&
- !isString(currentConfig['logcollector-localfile']) &&
- currentConfig['logcollector-localfile']['localfile-commands'] &&
- currentConfig['logcollector-localfile']['localfile-commands'].length ? (
+ {!isString(currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]) &&
+ currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]?.[LOCALFILE_COMMANDS_PROP]?.length ? (
-
+
) : null}
@@ -98,8 +78,4 @@ class WzConfigurationLogCollectionCommands extends Component {
}
}
-WzConfigurationLogCollectionCommands.propTypes = {
- // currentConfig: PropTypes.object.isRequired
-};
-
export default WzConfigurationLogCollectionCommands;
diff --git a/public/controllers/management/components/management/configuration/log-collection/log-collection-logs.js b/public/controllers/management/components/management/configuration/log-collection/log-collection-logs.js
index c927354291..66015f8f58 100644
--- a/public/controllers/management/components/management/configuration/log-collection/log-collection-logs.js
+++ b/public/controllers/management/components/management/configuration/log-collection/log-collection-logs.js
@@ -15,16 +15,21 @@ import React, { Component, Fragment } from 'react';
import WzNoConfig from '../util-components/no-config';
import WzConfigurationSettingsTabSelector from '../util-components/configuration-settings-tab-selector';
import WzConfigurationListSelector from '../util-components/configuration-settings-list-selector';
-import {
- isString,
- renderValueOrDefault,
- renderValueOrNoValue
-} from '../utils/utils';
+import { isString, renderValueOrNoValue } from '../utils/utils';
import { settingsListBuilder } from '../utils/builders';
import helpLinks from './help-links';
+import { LOGCOLLECTOR_LOCALFILE_PROP, LOCALFILE_LOGS_PROP } from './types';
-const renderTargetField = item => item ? item.join(', ') : 'agent';
+const renderTargetField = (item) => (item ? item.join(', ') : 'agent');
+const renderArrayObjectField = arrayObjectField => {
+ const stringToRender = arrayObjectField
+ ? arrayObjectField
+ .map(({ value, type }) => value?.concat(type ? ` (${type})` : ''))
+ .join(', ')
+ : '-';
+ return stringToRender;
+};
const mainSettings = [
{ field: 'logformat', label: 'Log format' },
@@ -32,41 +37,47 @@ const mainSettings = [
{
field: 'only-future-events',
label: 'Only receive logs occured after start',
- when: 'agent'
+ when: 'agent',
},
{
field: 'reconnect_time',
- label:
- 'Time in seconds to try to reconnect with Windows Event Channel when it has fallen',
- when: 'agent'
+ label: 'Time in seconds to try to reconnect with Windows Event Channel when it has fallen',
+ when: 'agent',
},
{
field: 'query',
label: 'Filter logs using this XPATH query',
render: renderValueOrNoValue,
- when: 'agent'
+ when: 'agent',
},
{
field: 'labels',
label: 'Only receive logs occured after start',
render: renderValueOrNoValue,
- when: 'agent'
+ when: 'agent',
},
{
field: 'target',
label: 'Redirect output to this socket',
- render: renderTargetField
- }
+ render: renderTargetField,
+ },
+ {
+ field: 'ignore',
+ label: 'If the expression matches, the log will be ignored',
+ render: renderArrayObjectField,
+ },
+ {
+ field: 'restrict',
+ label: 'The log will only be processed if the expression matches',
+ render: renderArrayObjectField,
+ },
];
-
-const getMainSettingsAgentOrManager = agent =>
+const getMainSettingsAgentOrManager = (agent) =>
agent && agent.id === '000'
- ? mainSettings.filter(setting => setting.when !== 'agent')
- : mainSettings.filter(setting =>
- setting.when === 'agent'
- ? agent && agent.os && agent.os.platform === 'windows'
- : true
+ ? mainSettings.filter((setting) => setting.when !== 'agent')
+ : mainSettings.filter((setting) =>
+ setting.when === 'agent' ? agent && agent.os && agent.os.platform === 'windows' : true
);
class WzConfigurationLogCollectionLogs extends Component {
constructor(props) {
@@ -74,38 +85,25 @@ class WzConfigurationLogCollectionLogs extends Component {
}
render() {
const { currentConfig, agent } = this.props;
- const items =
- currentConfig['logcollector-localfile'] &&
- currentConfig['logcollector-localfile']['localfile-logs']
- ? settingsListBuilder(
- currentConfig['logcollector-localfile']['localfile-logs'],
- [
- 'file',
- 'alias',
- 'commnad',
- (item) => `${item.logformat}${item.target ? ` - ${item.target.join(', ')}` : ''}`
- ]
- )
- : [];
+ const items = currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]?.[LOCALFILE_LOGS_PROP]
+ ? settingsListBuilder(currentConfig[LOGCOLLECTOR_LOCALFILE_PROP][LOCALFILE_LOGS_PROP], [
+ 'file',
+ 'alias',
+ 'commnad',
+ (item) => `${item.logformat}${item.target ? ` - ${item.target.join(', ')}` : ''}`,
+ ])
+ : [];
return (
- {currentConfig['logcollector-localfile'] &&
- isString(currentConfig['logcollector-localfile']) && (
-
- )}
- {currentConfig['logcollector-localfile'] &&
- !isString(currentConfig['logcollector-localfile']) &&
- !(currentConfig['logcollector-localfile']['localfile-logs'] || [])
- .length ? (
+ {isString(currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]) && (
+
+ )}
+ {!isString(currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]) &&
+ !currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]?.[LOCALFILE_LOGS_PROP]?.length ? (
) : null}
- {currentConfig['logcollector-localfile'] &&
- !isString(currentConfig['logcollector-localfile']) &&
- currentConfig['logcollector-localfile']['localfile-logs'] &&
- currentConfig['logcollector-localfile']['localfile-logs'].length ? (
+ {!isString(currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]) &&
+ currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]?.[LOCALFILE_LOGS_PROP]?.length ? (
- {currentConfig['logcollector-socket'] &&
- isString(currentConfig['logcollector-socket']) && (
-
- )}
- {currentConfig['logcollector-socket'] &&
- !isString(currentConfig['logcollector-socket']) &&
- !currentConfig['logcollector-socket'].target ? (
+ {isString(currentConfig?.[LOGCOLLECTOR_SOCKET_PROP]) && (
+
+ )}
+ {!isString(currentConfig?.[LOGCOLLECTOR_SOCKET_PROP]) &&
+ !currentConfig?.[LOGCOLLECTOR_SOCKET_PROP]?.target?.length ? (
) : null}
- {currentConfig['logcollector-socket'] &&
- !isString(currentConfig['logcollector-socket']) &&
- currentConfig['logcollector-socket'].target &&
- currentConfig['logcollector-socket'].target.length ? (
+ {!isString(currentConfig?.[LOGCOLLECTOR_SOCKET_PROP]) &&
+ currentConfig?.[LOGCOLLECTOR_SOCKET_PROP]?.target?.length ? (
-
+
) : null}
@@ -95,8 +83,4 @@ class WzConfigurationLogCollectionSockets extends Component {
}
}
-WzConfigurationLogCollectionSockets.propTypes = {
- // currentConfig: PropTypes.object.isRequired
-};
-
export default WzConfigurationLogCollectionSockets;
diff --git a/public/controllers/management/components/management/configuration/log-collection/log-collection-windowsevents.js b/public/controllers/management/components/management/configuration/log-collection/log-collection-windowsevents.js
new file mode 100644
index 0000000000..13391dbe21
--- /dev/null
+++ b/public/controllers/management/components/management/configuration/log-collection/log-collection-windowsevents.js
@@ -0,0 +1,116 @@
+/*
+ * Wazuh app - React component for show configuration of log collection - commands tab.
+ * Copyright (C) 2015-2022 Wazuh, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Find more information about this on the LICENSE file.
+ */
+
+import React, { Component, Fragment } from 'react';
+
+import WzNoConfig from '../util-components/no-config';
+import WzConfigurationSettingsTabSelector from '../util-components/configuration-settings-tab-selector';
+import WzConfigurationListSelector from '../util-components/configuration-settings-list-selector';
+import { renderValueOrNoValue, isString } from '../utils/utils';
+import { settingsListBuilder } from '../utils/builders';
+import helpLinks from './help-links';
+import { LOGCOLLECTOR_LOCALFILE_PROP, LOCALFILE_WINDOWSEVENT_PROP } from './types';
+
+/**
+ * Return input label based on logformat value
+ *
+ * @param {*} value => field value
+ * @param {*} item => settings item
+ * @param {*} config => all log data
+ * @returns string => value to show in Channel label
+ */
+const channelLabel = (value, item, config) => {
+ return config.logformat === 'eventlog'
+ ? 'Log'
+ : config.logformat === 'eventchannel'
+ ? 'Channel'
+ : 'Channel';
+};
+
+/**
+ *
+ * @param {*} data => all log data
+ * @returns string => value to show in query input
+ */
+const queryValue = (data) => {
+ return typeof data === 'undefined' ? '-' : typeof data === 'object' ? data.value : data;
+};
+
+/**
+ * Returns targets array parsed in one string
+ * @param {*} item
+ * @returns string => target
+ */
+const renderTargetField = (item) => (item ? item.join(', ') : 'agent');
+/**
+ * Return panels title
+ * @param {*} item => log data
+ * @returns
+ */
+const panelsLabel = (item) =>
+ !item.channel
+ ? `${item.logformat} - ${renderTargetField(item.target)}`
+ : `${item.channel} (${item.logformat})`;
+
+const mainSettings = [
+ { field: 'logformat', label: 'Log format' },
+ { field: 'channel', label: 'Channel', render: renderValueOrNoValue, renderLabel: channelLabel },
+ { field: 'query', label: 'Query', render: queryValue },
+ {
+ field: 'only-future-events',
+ label: 'Only future events',
+ render: renderValueOrNoValue,
+ },
+ {
+ field: 'reconnect_time',
+ label: 'Reconnect Time',
+ render: renderValueOrNoValue,
+ },
+];
+
+class WzConfigurationLogCollectionWindowsEvents extends Component {
+ constructor(props) {
+ super(props);
+ }
+ render() {
+ const { currentConfig } = this.props;
+ const items = currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]?.[LOCALFILE_WINDOWSEVENT_PROP]
+ ? settingsListBuilder(
+ currentConfig[LOGCOLLECTOR_LOCALFILE_PROP][LOCALFILE_WINDOWSEVENT_PROP],
+ panelsLabel
+ )
+ : [];
+ return (
+
+ {isString(currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]) && (
+
+ )}
+ {!currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]?.[LOCALFILE_WINDOWSEVENT_PROP]?.length ? (
+
+ ) : null}
+ {currentConfig?.[LOGCOLLECTOR_LOCALFILE_PROP]?.[LOCALFILE_WINDOWSEVENT_PROP]?.length ? (
+
+
+
+ ) : null}
+
+ );
+ }
+}
+
+export default WzConfigurationLogCollectionWindowsEvents;
diff --git a/public/controllers/management/components/management/configuration/log-collection/log-collection.js b/public/controllers/management/components/management/configuration/log-collection/log-collection.js
index b5bb872082..10d6af0d2a 100644
--- a/public/controllers/management/components/management/configuration/log-collection/log-collection.js
+++ b/public/controllers/management/components/management/configuration/log-collection/log-collection.js
@@ -17,9 +17,15 @@ import WzTabSelector, {
} from '../util-components/tab-selector';
import WzConfigurationLogCollectionLogs from './log-collection-logs';
import WzConfigurationLogCollectionCommands from './log-collection-commands';
+import WzConfigurationLogCollectionWindowsEvents from './log-collection-windowsevents'
import WzConfigurationLogCollectionSockets from './log-collection-sockets';
import withWzConfig from '../util-hocs/wz-config';
import { isString } from '../utils/utils';
+import {
+ LOCALFILE_COMMANDS_PROP,
+ LOCALFILE_LOGS_PROP,
+ LOCALFILE_WINDOWSEVENT_PROP,
+ LOGCOLLECTOR_LOCALFILE_PROP } from './types'
class WzConfigurationLogCollection extends Component {
constructor(props) {
@@ -28,36 +34,45 @@ class WzConfigurationLogCollection extends Component {
render() {
let { currentConfig, agent } = this.props;
currentConfig =
- currentConfig['logcollector-localfile'] &&
- !isString(currentConfig['logcollector-localfile'])
+ currentConfig[LOGCOLLECTOR_LOCALFILE_PROP] &&
+ !isString(currentConfig[LOGCOLLECTOR_LOCALFILE_PROP])
? {
...currentConfig,
- 'logcollector-localfile': {
- ...currentConfig['logcollector-localfile'],
- 'localfile-logs': currentConfig[
- 'logcollector-localfile'
- ].localfile.filter(item => typeof item.file !== 'undefined'), // TODO: it needs to be defined to support localfile as `eventchannel`. These doesn't have file property.
- 'localfile-commands': currentConfig[
- 'logcollector-localfile'
- ].localfile.filter(item => typeof item.file === 'undefined')
+ [LOGCOLLECTOR_LOCALFILE_PROP]: {
+ ...currentConfig[LOGCOLLECTOR_LOCALFILE_PROP],
+ [LOCALFILE_LOGS_PROP]: currentConfig[LOGCOLLECTOR_LOCALFILE_PROP].localfile.filter(item => typeof item.file !== 'undefined'), // TODO: it needs to be defined to support localfile as `eventchannel`. These doesn't have file property.
+ [LOCALFILE_WINDOWSEVENT_PROP]: currentConfig[LOGCOLLECTOR_LOCALFILE_PROP].localfile.filter(item => item.logformat === 'eventchannel' || item.logformat === 'eventlog'),
+ [LOCALFILE_COMMANDS_PROP]: currentConfig[LOGCOLLECTOR_LOCALFILE_PROP].localfile.filter(item => item.logformat === 'command' || item.logformat === 'full_command')
}
}
: currentConfig;
return (
-
-
-
-
-
-
+ { currentConfig[LOGCOLLECTOR_LOCALFILE_PROP][LOCALFILE_LOGS_PROP].length > 0 &&
+
+
+
+ }
+ { currentConfig[LOGCOLLECTOR_LOCALFILE_PROP][LOCALFILE_WINDOWSEVENT_PROP].length > 0 &&
+
+
+
+ }
+ { currentConfig[LOGCOLLECTOR_LOCALFILE_PROP][LOCALFILE_COMMANDS_PROP].length > 0 &&
+
+
+
+ }
({
+ getAngularModule: jest.fn(),
+ getUiSettings: () => ({
+ get: (uiSetting: string) => {
+ if (uiSetting === 'theme:darkMode') {
+ return false;
+ }
+ },
+ }),
+}));
+
+const mockStore = configureMockStore();
+const store = mockStore({
+ configurationReducers: { clusterNodeSelected: false },
+});
+
+// mocked getErrorOrchestrator
+const mockedGetErrorOrchestrator = {
+ handleError: jest.fn(),
+};
+
+jest.mock('../../../../../../react-services/common-services', () => {
+ return {
+ getErrorOrchestrator: () => mockedGetErrorOrchestrator,
+ };
+});
+
+// mocked hoc withWzConfig
+jest.mock('../util-hocs/wz-config', () => () => (Component) => (props) => );
+
+// Linux Agent mocked data
+const linuxCurrentConfigMocked = {
+ 'logcollector-localfile': {
+ localfile: [
+ {
+ file: '/var/ossec/logs/active-responses.log',
+ logformat: 'syslog',
+ ignore_binaries: 'no',
+ 'only-future-events': 'yes',
+ target: ['agent'],
+ },
+ {
+ file: '/var/log/dpkg.log',
+ logformat: 'syslog',
+ ignore_binaries: 'no',
+ 'only-future-events': 'yes',
+ target: ['agent'],
+ },
+ {
+ logformat: 'command',
+ command: 'df -P',
+ alias: 'df -P',
+ ignore_binaries: 'no',
+ target: ['agent'],
+ frequency: 360,
+ },
+ {
+ logformat: 'full_command',
+ command:
+ "netstat -tulpn | sed 's/\\\\([[:alnum:]]\\\\+\\\\)\\\\ \\\\+[[:digit:]]\\\\+\\\\ \\\\+[[:digit:]]\\\\+\\\\ \\\\+\\\\(.*\\\\):\\\\([[:digit:]]*\\\\)\\\\ \\\\+\\\\([0-9\\\\.\\\\:\\\\*]\\\\+\\\\).\\\\+\\\\ \\\\([[:digit:]]*\\\\/[[:alnum:]\\\\-]*\\\\).*/\\\\1 \\\\2 == \\\\3 == \\\\4 \\\\5/' | sort -k 4 -g | sed 's/ == \\\\(.*\\\\) ==/:\\\\1/' | sed 1,2d",
+ alias: 'netstat listening ports',
+ ignore_binaries: 'no',
+ target: ['agent'],
+ frequency: 360,
+ },
+ {
+ logformat: 'full_command',
+ command: 'last -n 20',
+ alias: 'last -n 20',
+ ignore_binaries: 'no',
+ target: ['agent'],
+ frequency: 360,
+ },
+ ],
+ },
+ 'logcollector-socket': {},
+};
+
+const linuxAgentMocked = {
+ os: {
+ arch: 'x86_64',
+ codename: 'Bionic Beaver',
+ major: '18',
+ minor: '04',
+ name: 'Ubuntu',
+ platform: 'ubuntu',
+ uname:
+ 'Linux |wazuh_agent_ubuntu_sources_cmake-v4.3.4-rc1 |5.10.104-linuxkit |#1 SMP Thu Mar 17 17:08:06 UTC 2022 |x86_64',
+ version: '18.04.6 LTS',
+ },
+ group: ['default'],
+ status: 'active',
+ lastKeepAlive: '2022-06-24T14:59:11Z',
+ node_name: 'master-node',
+ manager: 'wazuh-manager-master-v4.3.4-rc1-7.10.2',
+ mergedSum: '4a8724b20dee0124ff9656783c490c4e',
+ dateAdd: '2022-06-23T15:28:03Z',
+ registerIP: 'any',
+ name: 'wazuh_agent_ubuntu_sources_cmake-v4.3.4-rc1',
+ version: 'Wazuh v4.3.4',
+ id: '001',
+ ip: '172.18.0.5',
+ configSum: 'ab73af41699f13fdd81903b5f23d8d00',
+ agentPlatform: 'linux',
+};
+
+// Window Agent mocked data
+const windowAgentMocked = {
+ os: {
+ build: '19043',
+ major: '10',
+ minor: '0',
+ name: 'Microsoft Windows 10 Pro',
+ platform: 'windows',
+ uname: 'Microsoft Windows 10 Pro',
+ version: '10.0.19043',
+ },
+ manager: 'wazuh-manager-master-v4.3.4-rc1-7.10.2',
+ dateAdd: '2022-06-24T14:47:58Z',
+ ip: '192.168.0.98',
+ lastKeepAlive: '2022-06-24T16:09:20Z',
+ name: 'W10-4.3',
+ status: 'active',
+ version: 'Wazuh v4.3.0',
+ mergedSum: '4a8724b20dee0124ff9656783c490c4e',
+ group: ['default'],
+ id: '002',
+ configSum: 'ab73af41699f13fdd81903b5f23d8d00',
+ registerIP: 'any',
+ node_name: 'master-node',
+ agentPlatform: 'windows',
+};
+
+const windowsCurrentConfigMocked = {
+ 'logcollector-localfile': {
+ localfile: [
+ {
+ channel: 'Application',
+ logformat: 'eventchannel',
+ ignore_binaries: 'no',
+ 'only-future-events': 'yes',
+ target: ['agent'],
+ reconnect_time: 5,
+ },
+ {
+ channel: 'Security',
+ logformat: 'eventchannel',
+ query: {
+ value:
+ 'Event/System[EventID != 5145 and EventID != 5156 and EventID != 5447 and\\n EventID != 4656 and EventID != 4658 and EventID != 4663 and EventID != 4660 and\\n EventID != 4670 and EventID != 4690 and EventID != 4703 and EventID != 4907 and\\n EventID != 5152 and EventID != 5157]',
+ },
+ ignore_binaries: 'no',
+ 'only-future-events': 'yes',
+ target: ['agent'],
+ reconnect_time: 5,
+ },
+ {
+ channel: 'System',
+ logformat: 'eventchannel',
+ ignore_binaries: 'no',
+ 'only-future-events': 'yes',
+ target: ['agent'],
+ reconnect_time: 5,
+ },
+ {
+ file: 'active-response\\\\active-responses.log',
+ logformat: 'syslog',
+ ignore_binaries: 'no',
+ 'only-future-events': 'yes',
+ target: ['agent'],
+ },
+ ],
+ },
+ 'logcollector-socket': {},
+};
+
+describe('Log Collection Section', () => {
+ describe('Linux Agent', () => {
+ it('should render correct tabs when receive a linux agent', async () => {
+ const { getByRole } = render(
+
+
+
+ );
+
+ expect(getByRole('tab', { name: 'Logs' })).toBeInTheDocument();
+ expect(getByRole('tab', { name: 'Commands' })).toBeInTheDocument();
+ expect(() => getByRole('tab', { name: 'Windows Events' })).toThrow();
+ expect(getByRole('tab', { name: 'Sockets' })).toBeInTheDocument();
+ });
+
+ it('should shows the correct panel sidebar items when "Commands" tab is selected depends on received config', () => {
+ const { getByText, getByRole } = render(
+
+
+
+ );
+
+ fireEvent.click(getByText('Commands'));
+ getByRole('heading', { name: /command monitoring/i });
+ // buttons on left sidebar, showing alias
+ const localFilesWithAlias = linuxCurrentConfigMocked[
+ 'logcollector-localfile'
+ ].localfile.filter((item) => item.alias);
+ localFilesWithAlias.forEach((item) => {
+ getByRole('button', { name: new RegExp(item.alias || '', 'i') });
+ });
+ });
+
+ it('should shows the correct "Commands" data for each command selected', () => {
+ const { getByText, getByRole, getByTestId } = render(
+
+
+
+ );
+
+ fireEvent.click(getByText('Commands'));
+ getByRole('heading', { name: /command monitoring/i });
+ // check all sidebar buttons functionality and inputs showed
+ const localFilesWithAlias = linuxCurrentConfigMocked[
+ 'logcollector-localfile'
+ ].localfile.filter((item) => item.alias);
+ localFilesWithAlias.forEach((item) => {
+ const commandItem = getByRole('button', { name: new RegExp(item.alias || '', 'i') });
+ fireEvent.click(commandItem);
+ getByText(/log format/i);
+ expect(getByTestId('log-format')).toHaveValue(item.logformat);
+ getByText(/run this command/i);
+ expect(getByTestId('run-this-command')).toHaveValue(item.command);
+ getByText(/command alias/i);
+ expect(getByTestId('command-alias')).toHaveValue(item.alias);
+ getByText(/interval between command executions/i);
+ expect(getByTestId('interval-between-command-executions')).toHaveValue(
+ `${item.frequency?.toString()}`
+ );
+ getByText(/redirect output to this socket/i);
+ expect(getByTestId('redirect-output-to-this-socket')).toHaveValue(`${item.target.pop()}`);
+ });
+ });
+ });
+
+ describe('Windows Agent', () => {
+ it('should render correct tabs when receive a window agent', async () => {
+ const { getByRole } = render(
+
+
+
+ );
+
+ expect(getByRole('tab', { name: 'Logs' })).toBeInTheDocument();
+ expect(() => getByRole('tab', { name: 'Commands' })).toThrow();
+ expect(getByRole('tab', { name: 'Windows Events' })).toBeInTheDocument();
+ expect(getByRole('tab', { name: 'Sockets' })).toBeInTheDocument();
+ });
+
+ it('should shows the correct panel sidebar items when "Windows Events" tab is selected depends on received config', () => {
+ const { getByText, getByRole } = render(
+
+
+
+ );
+
+ fireEvent.click(getByText('Windows Events'));
+ getByRole('heading', { name: /windows events logs/i });
+ // buttons on left sidebar, showing alias
+ const localFilesWithChannel = windowsCurrentConfigMocked[
+ 'logcollector-localfile'
+ ].localfile.filter((item) => item.logformat === 'eventchannel');
+ localFilesWithChannel.forEach((item) => {
+ const eventBtn = getByRole('button', { name: new RegExp(`${item.channel}`, 'i') });
+ fireEvent.click(eventBtn);
+ });
+ });
+
+ it('should shows the correct "Windows Events" data for each command selected', () => {
+ const { getByText, getByRole, getByTestId } = render(
+
+
+
+ );
+
+ fireEvent.click(getByText('Windows Events'));
+ getByRole('heading', { name: /windows events logs/i });
+ // check all sidebar buttons functionality and inputs showed
+ const localFilesWithChannel = windowsCurrentConfigMocked[
+ 'logcollector-localfile'
+ ].localfile.filter((item) => item.logformat === 'eventchannel');
+ localFilesWithChannel.forEach((item) => {
+ const eventBtn = getByRole('button', { name: new RegExp(`${item.channel}`, 'i') });
+ fireEvent.click(eventBtn);
+ getByText(/log format/i);
+ expect(getByTestId('log-format')).toHaveValue(item.logformat);
+ getByText('Channel');
+ expect(getByTestId('channel')).toHaveValue(item.channel);
+ getByText(/query/i);
+ expect(getByTestId('query')).toHaveValue(item.query?.value);
+ getByText(/only future events/i);
+ expect(getByTestId('only-future-events')).toHaveValue(item['only-future-events']);
+ getByText(/reconnect time/i);
+ expect(getByTestId('reconnect-time')).toHaveValue(item.reconnect_time?.toString());
+ });
+ });
+ });
+});
diff --git a/public/controllers/management/components/management/configuration/log-collection/types.js b/public/controllers/management/components/management/configuration/log-collection/types.js
new file mode 100644
index 0000000000..27e32f111c
--- /dev/null
+++ b/public/controllers/management/components/management/configuration/log-collection/types.js
@@ -0,0 +1,7 @@
+
+export const LOGCOLLECTOR_LOCALFILE_PROP = 'logcollector-localfile';
+export const LOGCOLLECTOR_SOCKET_PROP = 'logcollector-socket';
+
+export const LOCALFILE_LOGS_PROP = 'localfile-logs';
+export const LOCALFILE_WINDOWSEVENT_PROP = 'localfile-windowsevent';
+export const LOCALFILE_COMMANDS_PROP = 'localfile-commands';
\ No newline at end of file
diff --git a/public/controllers/management/components/management/configuration/office365/__snapshots__/office365.test.tsx.snap b/public/controllers/management/components/management/configuration/office365/__snapshots__/office365.test.tsx.snap
index 48beb24a36..7bc2775a55 100644
--- a/public/controllers/management/components/management/configuration/office365/__snapshots__/office365.test.tsx.snap
+++ b/public/controllers/management/components/management/configuration/office365/__snapshots__/office365.test.tsx.snap
@@ -12,22 +12,15 @@ exports[`WzConfigurationOffice365 component renders correctly to match the snaps
"replaceReducer": [Function],
"subscribe": [Function],
},
- "subscription": Subscription {
+ "subscription": Object {
+ "addNestedSub": [Function],
+ "getListeners": [Function],
"handleChangeWrapper": [Function],
- "listeners": Object {
- "notify": [Function],
- },
+ "isSubscribed": [Function],
+ "notifyNestedSubs": [Function],
"onStateChange": [Function],
- "parentSub": undefined,
- "store": Object {
- "clearActions": [Function],
- "dispatch": [Function],
- "getActions": [Function],
- "getState": [Function],
- "replaceReducer": [Function],
- "subscribe": [Function],
- },
- "unsubscribe": null,
+ "trySubscribe": [Function],
+ "tryUnsubscribe": [Function],
},
}
}
diff --git a/public/controllers/management/components/management/configuration/office365/components/SubscriptionTab/__snapshots__/SubscriptionTab.test.tsx.snap b/public/controllers/management/components/management/configuration/office365/components/SubscriptionTab/__snapshots__/SubscriptionTab.test.tsx.snap
index 804317ace8..f8a679939c 100644
--- a/public/controllers/management/components/management/configuration/office365/components/SubscriptionTab/__snapshots__/SubscriptionTab.test.tsx.snap
+++ b/public/controllers/management/components/management/configuration/office365/components/SubscriptionTab/__snapshots__/SubscriptionTab.test.tsx.snap
@@ -60,11 +60,11 @@ exports[`SubscriptionTab component renders correctly to match the snapshot 1`] =
helpLinks={
Array [
Object {
- "href": "https://documentation.wazuh.com/4.3/office365/index.html",
+ "href": "https://documentation.wazuh.com/4.5/office365/index.html",
"text": "Using Wazuh to monitor Office 365",
},
Object {
- "href": "https://documentation.wazuh.com/4.3/user-manual/reference/ossec-conf/office365-module.html",
+ "href": "https://documentation.wazuh.com/4.5/user-manual/reference/ossec-conf/office365-module.html",
"text": "Configuration options for the module",
},
]
@@ -76,11 +76,11 @@ exports[`SubscriptionTab component renders correctly to match the snapshot 1`] =
help={
Array [
Object {
- "href": "https://documentation.wazuh.com/4.3/office365/index.html",
+ "href": "https://documentation.wazuh.com/4.5/office365/index.html",
"text": "Using Wazuh to monitor Office 365",
},
Object {
- "href": "https://documentation.wazuh.com/4.3/user-manual/reference/ossec-conf/office365-module.html",
+ "href": "https://documentation.wazuh.com/4.5/user-manual/reference/ossec-conf/office365-module.html",
"text": "Configuration options for the module",
},
]
@@ -238,11 +238,11 @@ exports[`SubscriptionTab component renders correctly to match the snapshot 1`] =
links={
Array [
Object {
- "href": "https://documentation.wazuh.com/4.3/office365/index.html",
+ "href": "https://documentation.wazuh.com/4.5/office365/index.html",
"text": "Using Wazuh to monitor Office 365",
},
Object {
- "href": "https://documentation.wazuh.com/4.3/user-manual/reference/ossec-conf/office365-module.html",
+ "href": "https://documentation.wazuh.com/4.5/user-manual/reference/ossec-conf/office365-module.html",
"text": "Configuration options for the module",
},
]
@@ -262,84 +262,76 @@ exports[`SubscriptionTab component renders correctly to match the snapshot 1`] =
hasArrow={true}
id="show-help"
isOpen={false}
- ownFocus={false}
+ ownFocus={true}
panelPaddingSize="m"
>
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+ viewBox="0 0 16 16"
+ width={16}
+ xmlns="http://www.w3.org/2000/svg"
+ />
+
+
+
+
+
+
+
-
+
@@ -484,18 +476,34 @@ exports[`SubscriptionTab component renders correctly to match the snapshot 1`] =
}
}
>
-
-
-
- Name
-
-
-
+
+
+
+
+ Name
+
+
+
+
+
diff --git a/public/controllers/management/components/management/configuration/office365/components/api-auth-tab/__snapshots__/api-auth-tab.test.tsx.snap b/public/controllers/management/components/management/configuration/office365/components/api-auth-tab/__snapshots__/api-auth-tab.test.tsx.snap
index 68ce1357fe..ff206b16db 100644
--- a/public/controllers/management/components/management/configuration/office365/components/api-auth-tab/__snapshots__/api-auth-tab.test.tsx.snap
+++ b/public/controllers/management/components/management/configuration/office365/components/api-auth-tab/__snapshots__/api-auth-tab.test.tsx.snap
@@ -70,11 +70,11 @@ exports[`ApiAuthTab component renders correctly to match the snapshot 1`] = `
helpLinks={
Array [
Object {
- "href": "https://documentation.wazuh.com/4.3/office365/index.html",
+ "href": "https://documentation.wazuh.com/4.5/office365/index.html",
"text": "Using Wazuh to monitor Office 365",
},
Object {
- "href": "https://documentation.wazuh.com/4.3/user-manual/reference/ossec-conf/office365-module.html",
+ "href": "https://documentation.wazuh.com/4.5/user-manual/reference/ossec-conf/office365-module.html",
"text": "Configuration options for the module",
},
]
@@ -86,11 +86,11 @@ exports[`ApiAuthTab component renders correctly to match the snapshot 1`] = `
help={
Array [
Object {
- "href": "https://documentation.wazuh.com/4.3/office365/index.html",
+ "href": "https://documentation.wazuh.com/4.5/office365/index.html",
"text": "Using Wazuh to monitor Office 365",
},
Object {
- "href": "https://documentation.wazuh.com/4.3/user-manual/reference/ossec-conf/office365-module.html",
+ "href": "https://documentation.wazuh.com/4.5/user-manual/reference/ossec-conf/office365-module.html",
"text": "Configuration options for the module",
},
]
@@ -248,11 +248,11 @@ exports[`ApiAuthTab component renders correctly to match the snapshot 1`] = `
links={
Array [
Object {
- "href": "https://documentation.wazuh.com/4.3/office365/index.html",
+ "href": "https://documentation.wazuh.com/4.5/office365/index.html",
"text": "Using Wazuh to monitor Office 365",
},
Object {
- "href": "https://documentation.wazuh.com/4.3/user-manual/reference/ossec-conf/office365-module.html",
+ "href": "https://documentation.wazuh.com/4.5/user-manual/reference/ossec-conf/office365-module.html",
"text": "Configuration options for the module",
},
]
@@ -272,84 +272,76 @@ exports[`ApiAuthTab component renders correctly to match the snapshot 1`] = `
hasArrow={true}
id="show-help"
isOpen={false}
- ownFocus={false}
+ ownFocus={true}
panelPaddingSize="m"
>
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+ viewBox="0 0 16 16"
+ width={16}
+ xmlns="http://www.w3.org/2000/svg"
+ />
+
+
+
+
+
+
+
-
+
@@ -471,7 +463,7 @@ exports[`ApiAuthTab component renders correctly to match the snapshot 1`] = `
}
>
@@ -549,6 +541,7 @@ exports[`GeneralTab component renders correctly to match the snapshot 1`] = `
}
>
@@ -565,6 +558,7 @@ exports[`GeneralTab component renders correctly to match the snapshot 1`] = `
@@ -643,6 +638,7 @@ exports[`GeneralTab component renders correctly to match the snapshot 1`] = `
@@ -721,6 +718,7 @@ exports[`GeneralTab component renders correctly to match the snapshot 1`] = `
@@ -799,6 +798,7 @@ exports[`GeneralTab component renders correctly to match the snapshot 1`] = `
+
-
- {label}
-
+ {label}
{Array.isArray(value) ? (
@@ -71,7 +65,11 @@ class WzConfigurationSetting extends Component {
))}
) : (
-
+
)}
@@ -83,8 +81,7 @@ class WzConfigurationSetting extends Component {
WzConfigurationSetting.propTypes = {
keyItem: PropTypes.string.isRequired,
- label: PropTypes.string.isRequired
- // value: PropTypes.string
+ label: PropTypes.string.isRequired,
};
export default WzConfigurationSetting;
diff --git a/public/controllers/management/components/management/configuration/util-components/configuration-settings-group.js b/public/controllers/management/components/management/configuration/util-components/configuration-settings-group.js
index 9e74209e71..f7fafdeb9f 100644
--- a/public/controllers/management/components/management/configuration/util-components/configuration-settings-group.js
+++ b/public/controllers/management/components/management/configuration/util-components/configuration-settings-group.js
@@ -62,7 +62,11 @@ class WzSettingsGroup extends Component {
{
* @param {any} defaultValue
* @returns {function}
*/
-export const renderValueOrDefault = defaultValue => value =>
- typeof value !== 'undefined' ? value : defaultValue;
+export const renderValueOrDefault = defaultValue => value => {
+ if (typeof value !== 'undefined') {
+ if (isArray(value)) {
+ return value.join(', ');
+ }
+ return value;
+ }
+ return defaultValue;
+};
/**
* Return value if isn't falsy or '-'
diff --git a/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/public/controllers/management/components/management/configuration/utils/wz-fetch.js
index e13bd3d9f3..60f506df39 100644
--- a/public/controllers/management/components/management/configuration/utils/wz-fetch.js
+++ b/public/controllers/management/components/management/configuration/utils/wz-fetch.js
@@ -14,6 +14,7 @@ import { WzRequest } from '../../../../../../react-services/wz-request';
import { replaceIllegalXML } from './xml';
import { getToasts } from '../../../../../../kibana-services';
import { delayAsPromise } from '../../../../../../../common/utils';
+import { AGENT_SYNCED_STATUS } from '../../../../../../../common/constants';
/**
* Get configuration for an agent/manager of request sections
@@ -480,9 +481,9 @@ export const validateAfterSent = async (node = false) => {
export const agentIsSynchronized = async agent => {
const isSync = await WzRequest.apiReq(
'GET',
- `/agents/${agent.id}/group/is_sync`, {}
+ `/agents?q=id=${agent.id}&select=group_config_status`, {}
);
- return (((((isSync || {}).data || {}).data || {}).affected_items || [])[0] || {}).synced || false;
+ return isSync?.data?.data?.affected_items?.[0]?.group_config_status == AGENT_SYNCED_STATUS.SYNCED;
}
/**
@@ -499,7 +500,7 @@ export const clusterNodes = async () => {
/**
- * Check the current security platform that is installed (xpack, opendistro, searchguard...)
+ * Check the current security platform that is installed (OpenSearch Dashboards Security)
*/
export const checkCurrentSecurityPlatform = async () => {
try {
diff --git a/public/controllers/management/components/management/decoders/__snapshots__/main-decoders.test.tsx.snap b/public/controllers/management/components/management/decoders/__snapshots__/main-decoders.test.tsx.snap
new file mode 100644
index 0000000000..ab4c46c446
--- /dev/null
+++ b/public/controllers/management/components/management/decoders/__snapshots__/main-decoders.test.tsx.snap
@@ -0,0 +1,81 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Ruleset component renders correctly to match the snapshot 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+ Loading ...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/public/controllers/management/components/management/decoders/components/columns.tsx b/public/controllers/management/components/management/decoders/components/columns.tsx
new file mode 100644
index 0000000000..9e3e160425
--- /dev/null
+++ b/public/controllers/management/components/management/decoders/components/columns.tsx
@@ -0,0 +1,205 @@
+import React from 'react';
+import { resourceDictionary, ResourcesHandler, ResourcesConstants } from '../../common/resources-handler';
+import { WzButtonPermissions } from '../../../../../../components/common/permissions/button';
+import { WzButtonPermissionsModalConfirm } from '../../../../../../components/common/buttons';
+import { getErrorOrchestrator } from '../../../../../../react-services/common-services';
+import { UIErrorLog } from '../../../../../../react-services/error-orchestrator/types';
+import { getErrorOptions } from '../../common/error-helper';
+import { Columns } from '../../common/interfaces';
+
+
+export default class DecodersColumns {
+
+ columns: Columns = {};
+
+ constructor(props) {
+ this.props = props;
+ this._buildColumns();
+ }
+
+ _buildColumns() {
+ this.columns = {
+ decoders: [
+ {
+ field: 'name',
+ name: 'Name',
+ align: 'left',
+ sortable: true
+ },
+ {
+ field: 'details.program_name',
+ name: 'Program name',
+ align: 'left',
+ sortable: false
+ },
+ {
+ field: 'details.order',
+ name: 'Order',
+ align: 'left',
+ sortable: false
+ },
+ {
+ field: 'filename',
+ name: 'File',
+ align: 'left',
+ sortable: true,
+ render: (value, item) => {
+ return (
+ {
+ try {
+ ev.stopPropagation();
+ const resourcesHandler = new ResourcesHandler(ResourcesConstants.DECODERS);
+ const result = await resourcesHandler.getFileContent(value);
+ const file = { name: value, content: result, path: item.relative_dirname };
+ this.props.updateFileContent(file);
+ } catch (error) {
+ const options: UIErrorLog = getErrorOptions(
+ error,
+ 'Decoders.readFileContent'
+ );
+ getErrorOrchestrator().handleError(options);
+ }
+ }}>
+ {value}
+
+ );
+ }
+ },
+ {
+ field: 'relative_dirname',
+ name: 'Path',
+ align: 'left',
+ sortable: true
+ }
+ ],
+ files: [
+ {
+ field: 'filename',
+ name: 'File',
+ align: 'left',
+ sortable: true
+ },
+ {
+ name: 'Actions',
+ align: 'left',
+ render: item => {
+ if (item.relative_dirname.startsWith('ruleset/')) {
+ return (
+ {
+ try {
+ ev.stopPropagation();
+ const resourcesHandler = new ResourcesHandler(ResourcesConstants.DECODERS);
+ const result = await resourcesHandler.getFileContent(item.filename);
+ const file = { name: item.filename, content: result, path: item.relative_dirname };
+ this.props.updateFileContent(file);
+ } catch (error) {
+ const options: UIErrorLog = getErrorOptions(
+ error,
+ 'Decoders.readFileContent'
+ );
+ getErrorOrchestrator().handleError(options);
+ }
+ }}
+ color="primary"
+ />
+ );
+ } else {
+ return (
+
+ {
+ try {
+ ev.stopPropagation();
+ const resourcesHandler = new ResourcesHandler(ResourcesConstants.DECODERS);
+ const result = await resourcesHandler.getFileContent(item.filename);
+ const file = { name: item.filename, content: result, path: item.relative_dirname };
+ this.props.updateFileContent(file);
+ } catch (error) {
+ const options: UIErrorLog = getErrorOptions(
+ error,
+ 'Files.editFileContent'
+ );
+ getErrorOrchestrator().handleError(options);
+ }
+ }}
+ color="primary"
+ />
+ {
+ try {
+ this.props.removeItems([item]);
+ } catch (error) {
+ const options: UIErrorLog = getErrorOptions(
+ error,
+ 'Files.deleteFile'
+ );
+ getErrorOrchestrator().handleError(options);
+ }
+ }}
+ color="danger"
+ modalTitle={'Are you sure?'}
+ modalProps={{
+ buttonColor: 'danger',
+ }}
+ />
+
+ );
+ }
+ }
+ }
+ ]
+ };
+
+ const getReadButtonPermissions = (item) => {
+ const { permissionResource } = resourceDictionary[ResourcesConstants.DECODERS];
+ return [
+ {
+ action: `${ResourcesConstants.DECODERS}:read`,
+ resource: permissionResource(item.filename),
+ },
+ ];
+ };
+
+ const getEditButtonPermissions = (item) => {
+ const { permissionResource } = resourceDictionary[ResourcesConstants.DECODERS];
+ return [
+ {
+ action: `${ResourcesConstants.DECODERS}:read`,
+ resource: permissionResource(item.filename),
+ },
+ { action: `${ResourcesConstants.DECODERS}:update`, resource: permissionResource(item.filename) },
+ ];
+ };
+
+ const getDeleteButtonPermissions = (item) => {
+ const { permissionResource } = resourceDictionary[ResourcesConstants.DECODERS];
+ return [
+ {
+ action: `${ResourcesConstants.DECODERS}:delete`,
+ resource: permissionResource(item.filename),
+ },
+ ];
+ };
+
+ }
+}
diff --git a/public/controllers/management/components/management/decoders/components/decoders-suggestions.ts b/public/controllers/management/components/management/decoders/components/decoders-suggestions.ts
new file mode 100644
index 0000000000..fbd4ed6999
--- /dev/null
+++ b/public/controllers/management/components/management/decoders/components/decoders-suggestions.ts
@@ -0,0 +1,44 @@
+import { WzRequest } from '../../../../../../react-services/wz-request';
+
+const decodersItems = [
+ {
+ type: 'params',
+ label: 'filename',
+ description: 'Filters the decoders by file name.',
+ values: async value => {
+ const filter = { limit: 30 };
+ if (value) {
+ filter['search'] = value;
+ }
+ const result = await WzRequest.apiReq('GET', '/decoders/files', filter);
+ return (((result || {}).data || {}).data || {}).affected_items.map((item) => { return item.filename });
+ },
+ },
+ {
+ type: 'params',
+ label: 'relative_dirname',
+ description: 'Path of the decoders files.',
+ values: async () => {
+ const result = await WzRequest.apiReq('GET', '/manager/configuration', {
+ params: {
+ section: 'ruleset',
+ field: 'decoder_dir'
+ }
+ });
+ return (((result || {}).data || {}).data || {}).affected_items[0].ruleset.decoder_dir;
+ }
+ },
+ {
+ type: 'params',
+ label: 'status',
+ description: 'Filters the decoders by status.',
+ values: ['enabled', 'disabled']
+ }
+];
+
+const apiSuggestsItems = {
+ items: decodersItems,
+ files: [],
+};
+
+export default apiSuggestsItems;
\ No newline at end of file
diff --git a/public/controllers/management/components/management/decoders/components/decoders-table.tsx b/public/controllers/management/components/management/decoders/components/decoders-table.tsx
new file mode 100644
index 0000000000..19e2357c64
--- /dev/null
+++ b/public/controllers/management/components/management/decoders/components/decoders-table.tsx
@@ -0,0 +1,279 @@
+/*
+ * Wazuh app - Agent vulnerabilities table component
+ * Copyright (C) 2015-2022 Wazuh, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Find more information about this on the LICENSE file.
+ */
+
+import React, { useState, useCallback } from 'react';
+import { TableWzAPI } from '../../../../../../components/common/tables';
+import { getToasts } from '../../../../../../kibana-services';
+import { resourceDictionary, ResourcesConstants, ResourcesHandler } from '../../common/resources-handler';
+import { getErrorOrchestrator } from '../../../../../../react-services/common-services';
+import { UI_ERROR_SEVERITIES } from '../../../../../../react-services/error-orchestrator/types';
+import { UI_LOGGER_LEVELS } from '../../../../../../../common/constants';
+
+import DecodersColumns from './columns';
+import { FlyoutDetail } from './flyout-detail';
+import { withUserPermissions } from '../../../../../../components/common/hocs/withUserPermissions';
+import { WzUserPermissions } from '../../../../../../react-services/wz-user-permissions';
+import { compose } from 'redux';
+import { SECTION_DECODERS_SECTION, SECTION_DECODERS_KEY } from '../../common/constants';
+import {
+ ManageFiles,
+ AddNewFileButton,
+ UploadFilesButton,
+} from '../../common/actions-buttons'
+
+import apiSuggestsItems from './decoders-suggestions';
+
+/***************************************
+ * Render tables
+ */
+const FilesTable = ({
+ actionButtons,
+ buttonOptions,
+ columns,
+ searchBarSuggestions,
+ filters,
+ updateFilters,
+ reload
+}) =>
+
+const DecodersFlyoutTable = ({
+ actionButtons,
+ buttonOptions,
+ columns,
+ searchBarSuggestions,
+ getRowProps,
+ filters,
+ updateFilters,
+ isFlyoutVisible,
+ currentItem,
+ closeFlyout,
+ cleanFilters,
+ ...props
+}) => <>
+
+ {isFlyoutVisible && (
+
+ )}
+ >
+
+/***************************************
+ * Main component
+ */
+export default compose(
+ withUserPermissions
+)(function DecodersTable({ setShowingFiles, showingFiles, ...props }) {
+ const [filters, setFilters] = useState([]);
+ const [isFlyoutVisible, setIsFlyoutVisible] = useState(false);
+ const [currentItem, setCurrentItem] = useState(null);
+ const [tableFootprint, setTableFootprint] = useState(0);
+
+ const resourcesHandler = new ResourcesHandler(ResourcesConstants.DECODERS);
+
+ // Table custom filter options
+ const buttonOptions = [{ label: "Custom decoders", field: "relative_dirname", value: "etc/decoders" },];
+
+ const updateFilters = (filters) => {
+ setFilters(filters);
+ }
+
+ const cleanFilters = () => {
+ setFilters([]);
+ }
+
+ const toggleShowFiles = () => {
+ setFilters([]);
+ setShowingFiles(!showingFiles);
+ }
+
+ const closeFlyout = () => {
+ setIsFlyoutVisible(false);
+ setCurrentItem(null);
+ }
+
+ /**
+ * Columns and Rows properties
+ */
+ const getColumns = () => {
+ const decodersColumns = new DecodersColumns({
+ removeItems: removeItems,
+ state: {
+ section: SECTION_DECODERS_KEY
+ }, ...props
+ }).columns;
+ const columns = decodersColumns[showingFiles ? 'files' : SECTION_DECODERS_KEY];
+ return columns;
+ }
+
+ const getRowProps = (item) => {
+ const getRequiredPermissions = (item) => {
+ const { permissionResource } = resourceDictionary[SECTION_DECODERS_KEY];
+ return [
+ {
+ action: `${SECTION_DECODERS_KEY}:read`,
+ resource: permissionResource(item.name),
+ },
+ ];
+ };
+
+ return {
+ 'data-test-subj': `row-${item.name}-${item.details?.order}`,
+ className: 'customRowClass',
+ onClick: !WzUserPermissions.checkMissingUserPermissions(
+ getRequiredPermissions(item),
+ props.userPermissions
+ )
+ ? () => {
+ setCurrentItem(item)
+ setIsFlyoutVisible(true);
+ }
+ : undefined,
+ };
+ };
+
+ /**
+ * Remove files method
+ */
+ const removeItems = async (items) => {
+ try {
+ const results = items.map(async (item, i) => {
+ await resourcesHandler.deleteFile(item.filename || item.name);
+ });
+
+ Promise.all(results).then((completed) => {
+ setTableFootprint(Date.now());
+ getToasts().add({
+ color: 'success',
+ title: 'Success',
+ text: 'Deleted successfully',
+ toastLifeTimeMs: 3000,
+ });
+ });
+ } catch (error) {
+ const options = {
+ context: `${WzRulesetTable.name}.removeItems`,
+ level: UI_LOGGER_LEVELS.ERROR,
+ severity: UI_ERROR_SEVERITIES.BUSINESS,
+ error: {
+ error: error,
+ message: `Error deleting item: ${error.message || error}`,
+ title: error.name || error,
+ },
+ };
+ getErrorOrchestrator().handleError(options);
+ }
+ }
+
+ const { updateRestartClusterManager, updateFileContent } = props;
+ const columns = getColumns();
+
+ /**
+ * Build table custom action buttons dynamically based on showing files state
+ */
+ const buildActionButtons = useCallback(() => {
+ const buttons = [
+ ,
+ ,
+ ];
+ if (showingFiles)
+ buttons.push( { updateRestartClusterManager && updateRestartClusterManager() }}
+ />);
+ return buttons;
+ }, [showingFiles]);
+
+ const actionButtons = buildActionButtons();
+
+ return (
+
+ {showingFiles ? (
+
+ ) : (
+
+ )}
+
+ );
+});
diff --git a/public/controllers/management/components/management/decoders/components/flyout-detail.tsx b/public/controllers/management/components/management/decoders/components/flyout-detail.tsx
new file mode 100644
index 0000000000..2295403cfc
--- /dev/null
+++ b/public/controllers/management/components/management/decoders/components/flyout-detail.tsx
@@ -0,0 +1,36 @@
+/*
+ * Wazuh app - Agent vulnerabilities components
+ * Copyright (C) 2015-2022 Wazuh, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Find more information about this on the LICENSE file.
+ */
+
+import React from 'react';
+import {
+ WzFlyout,
+} from '../../../../../../components/common/flyouts';
+import WzDecoderInfo from '../views/decoder-info';
+import '../../common/flyout-detail.scss'
+
+export const FlyoutDetail = ({ item, title, closeFlyout, filters, ...rest }) => {
+ return (
+ closeFlyout()}
+ flyoutProps={{
+ size: "l",
+ 'aria-labelledby': title,
+ maxWidth: "70%",
+ className: "wz-inventory wzApp wz-decoders-flyout",
+ }}
+ >
+ {item && <>
+
+ >}
+
+ );
+}
diff --git a/public/controllers/management/components/management/decoders/main-decoders.test.tsx b/public/controllers/management/components/management/decoders/main-decoders.test.tsx
new file mode 100644
index 0000000000..3b45076ae8
--- /dev/null
+++ b/public/controllers/management/components/management/decoders/main-decoders.test.tsx
@@ -0,0 +1,42 @@
+/*
+ * Wazuh app - React test for Ruleset component.
+ *
+ * Copyright (C) 2015-2022 Wazuh, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Find more information about this on the LICENSE file.
+ *
+ */
+
+import React from 'react';
+import { mount } from 'enzyme';
+import WzRuleset from '../ruleset/main-ruleset';
+
+jest.mock('../../../../../kibana-services', () => ({
+ getAngularModule: jest.fn(),
+ getHttp: () => ({
+ basePath: {
+ prepend: (str) => str,
+ },
+ }),
+ getUiSettings: () => ({
+ get: (setting: string): any => {
+ if(setting === 'theme:darkMode'){
+ return false
+ }
+ }
+ })
+}));
+
+describe('Ruleset component', () => {
+ it('renders correctly to match the snapshot', () => {
+ const logtestProps = '';
+ const clusterStatus = '';
+ const wrapper = mount( );
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/public/controllers/management/components/management/decoders/main-decoders.tsx b/public/controllers/management/components/management/decoders/main-decoders.tsx
new file mode 100644
index 0000000000..7948d2f959
--- /dev/null
+++ b/public/controllers/management/components/management/decoders/main-decoders.tsx
@@ -0,0 +1,55 @@
+/*
+ * Wazuh app - React component for main Decoders view.
+ * Copyright (C) 2015-2022 Wazuh, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Find more information about this on the LICENSE file.
+ */
+import React, { useState } from 'react';
+// Redux
+import WzReduxProvider from '../../../../../redux/wz-redux-provider';
+import WzDecodersOverview from './views/decoders-overview';
+import WzFileEditor from '../common/file-editor';
+import { SECTION_DECODERS_SECTION } from '../common/constants';
+
+export default function WzDecoder({ clusterStatus, logtestProps }) {
+
+ const [fileContent, setFileContent] = useState(false);
+ const [addingFile, setAddingFile] = useState(false);
+ const [showingFiles, setShowingFiles] = useState(false);
+
+ const cleanEditState = () => {
+ setFileContent(false);
+ setAddingFile(false);
+ }
+
+ return (
+
+ {
+ ((fileContent || addingFile) && (
+ { setFileContent(fileContent) }}
+ cleanEditState={() => cleanEditState()}
+ />
+ )) || (
+ { setFileContent(fileContent) }}
+ updateAddingFile={(addingFile) => { setAddingFile(addingFile) }}
+ setShowingFiles={() => { setShowingFiles(!showingFiles) }}
+ showingFiles={showingFiles}
+ />
+ )
+ }
+
+ );
+}
diff --git a/public/controllers/management/components/management/decoders/views/decoder-info.tsx b/public/controllers/management/components/management/decoders/views/decoder-info.tsx
new file mode 100644
index 0000000000..5e9446c259
--- /dev/null
+++ b/public/controllers/management/components/management/decoders/views/decoder-info.tsx
@@ -0,0 +1,347 @@
+import React, { Component } from 'react';
+import _ from 'lodash';
+// Eui components
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiFlyoutHeader,
+ EuiFlyoutBody,
+ EuiTitle,
+ EuiToolTip,
+ EuiSpacer,
+ EuiLink,
+ EuiAccordion,
+ EuiFlexGrid,
+} from '@elastic/eui';
+
+import { ResourcesHandler, ResourcesConstants } from '../../common/resources-handler';
+import { colors } from '../../common/colors';
+import { TableWzAPI } from '../../../../../../components/common/tables';
+import { UI_ERROR_SEVERITIES } from '../../../../../../react-services/error-orchestrator/types';
+import { UI_LOGGER_LEVELS } from '../../../../../../../common/constants';
+import { getErrorOrchestrator } from '../../../../../../react-services/common-services';
+
+export default class WzDecoderInfo extends Component {
+ constructor(props) {
+ super(props);
+ this.onClickRow = this.onClickRow.bind(this);
+ this.state = {
+ currentInfo: {}
+ };
+
+ this.resourcesHandler = new ResourcesHandler(ResourcesConstants.DECODERS);
+
+ const handleFileClick = async (value, item) => {
+ try {
+ const result = await this.resourcesHandler.getFileContent(value);
+ const file = { name: value, content: result, path: item.relative_dirname };
+ this.props.updateFileContent(file);
+ } catch (error) {
+ const options = {
+ context: `${WzDecoderInfo.name}.handleFileClick`,
+ level: UI_LOGGER_LEVELS.ERROR,
+ severity: UI_ERROR_SEVERITIES.BUSINESS,
+ error: {
+ error: error,
+ message: `Error updating file content: ${error.message || error}`,
+ title: error.name || error,
+ },
+ };
+ getErrorOrchestrator().handleError(options);
+ }
+ };
+
+ this.columns = [
+ {
+ field: 'name',
+ name: 'Name',
+ align: 'left',
+ sortable: true,
+ },
+ {
+ field: 'details.program_name',
+ name: 'Program name',
+ align: 'left',
+ sortable: true,
+ },
+ {
+ field: 'details.order',
+ name: 'Order',
+ align: 'left',
+ sortable: true,
+ },
+ {
+ field: 'filename',
+ name: 'File',
+ align: 'left',
+ sortable: true,
+ render: (value, item) => {
+ return (
+
+ handleFileClick(value, item)}>{value}
+
+ );
+ },
+ },
+ {
+ field: 'relative_dirname',
+ name: 'Path',
+ align: 'left',
+ sortable: true,
+ },
+ ];
+ }
+
+ async componentDidMount() {
+ document.body.scrollTop = 0; // For Safari
+ document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera
+
+ this.setState({
+ currentId: this.props.item
+ });
+ }
+
+ /**
+ * Clean the existing filters and sets the new ones and back to the previous section
+ */
+ setNewFiltersAndBack(filters) {
+ this.props.cleanFilters();
+ this.props.onFiltersChange(filters);
+ this.props.closeFlyout();
+ }
+
+ /**
+ * Render the basic information in a list
+ * @param {Number} position
+ * @param {String} file
+ * @param {String} path
+ */
+ renderInfo(position, file, path) {
+ return (
+
+
+ Position
+ {position}
+
+
+ File
+
+
+
+ this.setNewFiltersAndBack([{ field: 'filename', value: file }])
+ }
+ >
+ {file}
+
+
+
+
+
+ Path
+
+
+
+ this.setNewFiltersAndBack([{ field: 'relative_dirname', value: path }])
+ }
+ >
+ {path}
+
+
+
+
+
+
+ );
+ }
+
+ /**
+ * Render a list with the details
+ * @param {Array} details
+ */
+ renderDetails(details) {
+ const detailsToRender = [];
+ const capitalize = (str) => str[0].toUpperCase() + str.slice(1);
+
+ Object.keys(details).forEach((key) => {
+ let content = details[key];
+ if (key === 'order') {
+ content = this.colorOrder(content);
+ } else if (typeof details[key] === 'object') {
+ content = (
+
+ {Object.keys(details[key]).map((k) => (
+
+ {k}:
+ {details[key][k]}
+
+
+ ))}
+
+ );
+ } else {
+ content = {details[key]} ;
+ }
+ detailsToRender.push(
+
+ {capitalize(key)}
+ {content}
+
+ );
+ });
+
+ return {detailsToRender} ;
+ }
+
+ /**
+ * This set a color to a given order
+ * @param {String} order
+ */
+ colorOrder(order) {
+ order = order.toString();
+ let valuesArray = order.split(',');
+ const result = [];
+ for (let i = 0, len = valuesArray.length; i < len; i++) {
+ const coloredString = (
+
+ {valuesArray[i].startsWith(' ') ? valuesArray[i] : ` ${valuesArray[i]}`}
+
+ );
+ result.push(coloredString);
+ }
+ return result;
+ }
+
+ /**
+ * This set a color to a given regex
+ * @param {String} regex
+ */
+ colorRegex(regex) {
+ regex = regex.toString();
+ const starts = (
+
+ {regex.split('(')[0]}
+
+ );
+ let valuesArray = regex.match(/\(((?!<\/span>).)*?\)(?!<\/span>)/gim);
+ const result = [starts];
+ for (let i = 0, len = valuesArray.length; i < len; i++) {
+ const coloredString = (
+
+ {valuesArray[i]}
+
+ );
+ result.push(coloredString);
+ }
+ return result;
+ }
+
+/**
+ * Update decoder details with the selected detail row
+ * @param decoder
+ */
+ onClickRow(decoder) {
+ return {
+ onClick: () => {
+ this.setState({ currentDecoder: decoder });
+ },
+ };
+ };
+
+ render() {
+ const currentDecoder =
+ this.state && this.state.currentDecoder ? this.state.currentDecoder : this.props.item;
+ const { position, details, filename, name, relative_dirname } = currentDecoder;
+
+ return (
+ <>
+
+ {/* Decoder description name */}
+
+
+
+
+ {name}
+
+
+
+
+
+
+ {/* Cards */}
+
+ {/* General info */}
+
+
+ Information
+
+ }
+ paddingSize="none"
+ initialIsOpen={true}
+ >
+
+ {this.renderInfo(position, filename, relative_dirname)}
+
+
+
+
+
+
+
+ Details
+
+ }
+ paddingSize="none"
+ initialIsOpen={true}
+ >
+ {this.renderDetails(details)}
+
+
+
+ {/* Table */}
+
+
+
+ Related decoders
+
+ }
+ paddingSize="none"
+ initialIsOpen={true}
+ >
+
+
+
+ {currentDecoder?.filename &&
+
+ }
+
+
+
+
+
+
+
+ >
+ );
+ }
+}
diff --git a/public/controllers/management/components/management/decoders/views/decoders-overview.tsx b/public/controllers/management/components/management/decoders/views/decoders-overview.tsx
new file mode 100644
index 0000000000..f47d4498dd
--- /dev/null
+++ b/public/controllers/management/components/management/decoders/views/decoders-overview.tsx
@@ -0,0 +1,71 @@
+import React, { useState } from 'react';
+import { connect } from 'react-redux';
+
+// Eui components
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiPanel,
+ EuiPage,
+ EuiSpacer
+} from '@elastic/eui';
+
+// Wazuh components
+import { withUserAuthorizationPrompt, withGlobalBreadcrumb } from '../../../../../../components/common/hocs';
+import { compose } from 'redux';
+import { resourceDictionary } from '../../common/resources-handler';
+import { SECTION_DECODERS_NAME, SECTION_DECODERS_KEY } from '../../common/constants';
+import '../../common/layout-overview.scss';
+import DecodersTable from '../components/decoders-table';
+import WzRestartClusterManagerCallout from '../../../../../../components/common/restart-cluster-manager-callout';
+
+
+function WzDecodersOverview(props) {
+
+ const [showWarningRestart, setShowWarningRestart] = useState(false);
+
+ const updateRestartManagers = (showWarningRestart) => {
+ setShowWarningRestart(showWarningRestart);
+ }
+
+
+ const { clusterStatus } = props;
+ return
+
+ {showWarningRestart && (
+ <>
+
+ updateRestartManagers(false)}
+ onRestartedError={() => updateRestartManagers(true)}
+ />
+
+ >
+ )}
+
+
+
+ updateRestartManagers(showWarningRestart)}
+ />
+
+
+
+ ;
+
+}
+
+export default compose(
+ withGlobalBreadcrumb(props => {
+ return [
+ { text: '' },
+ { text: 'Management', href: '#/manager' },
+ { text: SECTION_DECODERS_NAME}
+ ];
+ }),
+ withUserAuthorizationPrompt((props) => [
+ { action: `${SECTION_DECODERS_KEY}:read`, resource: resourceDictionary[SECTION_DECODERS_KEY].permissionResource('*') }
+ ])
+)(WzDecodersOverview);
diff --git a/public/controllers/management/components/management/groups/__snapshots__/groups-main.test.tsx.snap b/public/controllers/management/components/management/groups/__snapshots__/groups-main.test.tsx.snap
index 3ae64fbacd..8e263c9825 100644
--- a/public/controllers/management/components/management/groups/__snapshots__/groups-main.test.tsx.snap
+++ b/public/controllers/management/components/management/groups/__snapshots__/groups-main.test.tsx.snap
@@ -12,22 +12,15 @@ exports[`Group main component renders correctly to match the snapshot 1`] = `
"replaceReducer": [Function],
"subscribe": [Function],
},
- "subscription": Subscription {
+ "subscription": Object {
+ "addNestedSub": [Function],
+ "getListeners": [Function],
"handleChangeWrapper": [Function],
- "listeners": Object {
- "notify": [Function],
- },
+ "isSubscribed": [Function],
+ "notifyNestedSubs": [Function],
"onStateChange": [Function],
- "parentSub": undefined,
- "store": Object {
- "clearActions": [Function],
- "dispatch": [Function],
- "getActions": [Function],
- "getState": [Function],
- "replaceReducer": [Function],
- "subscribe": [Function],
- },
- "unsubscribe": null,
+ "trySubscribe": [Function],
+ "tryUnsubscribe": [Function],
},
}
}
diff --git a/public/controllers/management/components/management/groups/group-agents-table.js b/public/controllers/management/components/management/groups/group-agents-table.js
index a4598a35d4..534726d6aa 100644
--- a/public/controllers/management/components/management/groups/group-agents-table.js
+++ b/public/controllers/management/components/management/groups/group-agents-table.js
@@ -52,7 +52,7 @@ class WzGroupAgentsTable extends Component {
{
type: 'q',
label: 'os.platform',
- description: 'Filter by OS platform',
+ description: 'Filter by operating system platform',
operators: ['=', '!='],
values: async (value) =>
getAgentFilterValues('os.platform', value, {
@@ -62,7 +62,7 @@ class WzGroupAgentsTable extends Component {
{
type: 'q',
label: 'ip',
- description: 'Filter by agent IP',
+ description: 'Filter by agent IP address',
operators: ['=', '!='],
values: async (value) =>
getAgentFilterValues('ip', value, { q: `group=${this.props.state.itemDetail.name}` }),
@@ -153,7 +153,7 @@ class WzGroupAgentsTable extends Component {
},
{
field: 'ip',
- name: 'Ip',
+ name: 'IP address',
align: 'left',
sortable: true,
},
@@ -165,13 +165,13 @@ class WzGroupAgentsTable extends Component {
},
{
field: 'os.name',
- name: 'Os name',
+ name: 'Operating system name',
align: 'left',
sortable: true,
},
{
field: 'os.version',
- name: 'Os version',
+ name: 'Operating system version',
align: 'left',
sortable: true,
},
diff --git a/public/controllers/management/components/management/groups/utils/columns-main.js b/public/controllers/management/components/management/groups/utils/columns-main.js
index bd30750e5d..a4143218df 100644
--- a/public/controllers/management/components/management/groups/utils/columns-main.js
+++ b/public/controllers/management/components/management/groups/utils/columns-main.js
@@ -19,7 +19,8 @@ export default class GroupsColums {
{
field: 'count',
name: 'Agents',
- align: 'left'
+ align: 'left',
+ sortable: true
},
{
field: 'configSum',
diff --git a/public/controllers/management/components/management/management-main.js b/public/controllers/management/components/management/management-main.js
index 74fbd84978..d940694b7b 100644
--- a/public/controllers/management/components/management/management-main.js
+++ b/public/controllers/management/components/management/management-main.js
@@ -13,8 +13,10 @@ import React, { Component, Fragment } from 'react';
// Redux
import store from '../../../../redux/store';
-import { updateRulesetSection } from '../../../../redux/actions/rulesetActions';
+import { updateManagementSection } from '../../../../redux/actions/managementActions';
import WzRuleset from './ruleset/main-ruleset';
+import WzCDBLists from './cdblists/main-cdblists';
+import WzDecoders from './decoders/main-decoders';
import WzGroups from './groups/groups-main';
import WzStatus from './status/status-main';
import WzLogs from './mg-logs/logs';
@@ -24,6 +26,11 @@ import WzStatistics from './statistics/statistics-main';
import { connect } from 'react-redux';
import { clusterReq } from './configuration/utils/wz-fetch';
import { updateClusterStatus } from '../../../../redux/actions/appStateActions';
+import {
+ SECTION_CDBLIST_SECTION,
+ SECTION_DECODERS_SECTION,
+ SECTION_RULES_SECTION
+} from './common/constants';
class WzManagementMain extends Component {
constructor(props) {
@@ -32,11 +39,11 @@ class WzManagementMain extends Component {
this.store = store;
}
UNSAFE_componentWillMount() {
- this.props.updateRulesetSection(this.props.section);
+ this.props.updateManagementSection(this.props.section);
}
componentWillUnmount() {
- store.dispatch(updateRulesetSection(''));
+ store.dispatch(updateManagementSection(''));
}
componentDidMount() {
@@ -68,7 +75,6 @@ class WzManagementMain extends Component {
render() {
const { section } = this.props;
- const ruleset = ['ruleset', 'rules', 'decoders', 'lists'];
return (
{(section === 'groups' && ) ||
@@ -77,7 +83,15 @@ class WzManagementMain extends Component {
(section === 'statistics' && ) ||
(section === 'logs' && ) ||
(section === 'configuration' && ) ||
- (ruleset.includes(section) && (
+ (section === SECTION_DECODERS_SECTION && ) ||
+ (section === SECTION_CDBLIST_SECTION && ) ||
+ (['ruleset', SECTION_RULES_SECTION].includes(section) && (
{
return {
- updateRulesetSection: (section) => dispatch(updateRulesetSection(section)),
+ updateManagementSection: (section) => dispatch(updateManagementSection(section)),
updateClusterStatus: (clusterStatus) => dispatch(updateClusterStatus(clusterStatus)),
};
};
diff --git a/public/controllers/management/components/management/mg-logs/logs.js b/public/controllers/management/components/management/mg-logs/logs.js
index ef74a55476..7d54ee991b 100644
--- a/public/controllers/management/components/management/mg-logs/logs.js
+++ b/public/controllers/management/components/management/mg-logs/logs.js
@@ -413,6 +413,7 @@ export default compose(
iconType="importAction"
onClick={this.exportFormatted}
isLoading={this.state.generatingCsv}
+ isDisabled={!this.state.logsList}
>
Export formatted
diff --git a/public/controllers/management/components/management/ruleset/__snapshots__/main-ruleset.test.tsx.snap b/public/controllers/management/components/management/ruleset/__snapshots__/main-ruleset.test.tsx.snap
index c380a859b2..ab4c46c446 100644
--- a/public/controllers/management/components/management/ruleset/__snapshots__/main-ruleset.test.tsx.snap
+++ b/public/controllers/management/components/management/ruleset/__snapshots__/main-ruleset.test.tsx.snap
@@ -9,113 +9,72 @@ exports[`Ruleset component renders correctly to match the snapshot 1`] = `
-
-
-
+
-
-
-
-
-
-
- Loading ...
-
-
-
-
-
-
+
+
-
+ Loading ...
+
+
+
+
+
+
+
+
+
-
+
diff --git a/public/controllers/management/components/management/ruleset/actions-buttons.js b/public/controllers/management/components/management/ruleset/actions-buttons.js
deleted file mode 100644
index 515496f6b9..0000000000
--- a/public/controllers/management/components/management/ruleset/actions-buttons.js
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Wazuh app - React component for registering agents.
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-import React, { Component, Fragment } from 'react';
-// Eui components
-import { EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
-import { getToasts } from '../../../../../kibana-services';
-
-import {
- toggleShowFiles,
- updateLoadingStatus,
- updteAddingRulesetFile,
- updateListContent,
- updateIsProcessing,
- updatePageIndex,
-} from '../../../../../redux/actions/rulesetActions';
-
-import exportCsv from '../../../../../react-services/wz-csv';
-import { UploadFiles } from '../../upload-files';
-import columns from './utils/columns';
-import { resourceDictionary, RulesetHandler, RulesetResources } from './utils/ruleset-handler';
-import { WzButtonPermissions } from '../../../../../components/common/permissions/button';
-
-import { connect } from 'react-redux';
-
-import { UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchestrator/types';
-import { UI_LOGGER_LEVELS } from '../../../../../../common/constants';
-import { getErrorOrchestrator } from '../../../../../react-services/common-services';
-
-class WzRulesetActionButtons extends Component {
- constructor(props) {
- super(props);
-
- this.state = { generatingCsv: false };
- this.exportCsv = exportCsv;
-
- this.columns = columns;
- this.refreshTimeoutId = null;
- }
-
- showToast(title, text, color) {
- getToasts().add({
- title,
- text,
- color,
- toastLifeTimeMs: 3000,
- });
- }
- /**
- * Generates a CSV
- */
- async generateCsv() {
- try {
- this.setState({ generatingCsv: true });
- const { section, filters } = this.props.state; //TODO get filters from the search bar from the REDUX store
- const mapFilters = filters.map((filter) => ({
- name: filter.field,
- value: filter.value,
- })); // adapt to shape used in /api/csv file: server/controllers/wazuh-api.js
- await this.exportCsv(
- `/${section}${this.props.state.showingFiles ? '/files' : ''}`,
- mapFilters,
- section
- );
- } catch (error) {
- const options = {
- context: `${WzRulesetActionButtons.name}.generateCsv`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.BUSINESS,
- error: {
- error: error,
- message: `Error generating CSV: ${error.message || error}`,
- title: error.name || error,
- },
- };
- getErrorOrchestrator().handleError(options);
-
- this.setState({ generatingCsv: false });
- }
- this.setState({ generatingCsv: false });
- }
-
- /**
- * Uploads the files
- * @param {Array} files
- * @param {String} path
- */
- async uploadFiles(files, resource, overwrite) {
- try {
- let errors = false;
- let results = [];
- const rulesetHandler = new RulesetHandler(resource);
- for (let idx in files) {
- const { file, content } = files[idx];
- try {
- await rulesetHandler.updateFile(file, content, overwrite);
- results.push({
- index: idx,
- uploaded: true,
- file: file,
- error: 0,
- });
- } catch (error) {
- errors = true;
- results.push({
- index: idx,
- uploaded: false,
- file: file,
- error: error,
- });
- }
- }
- if (errors) throw results;
- return results;
- } catch (error) {
- throw error;
- }
- }
-
- /**
- * Toggle between files and rules or decoders
- */
- async toggleFiles() {
- try {
- this.props.updateLoadingStatus(true);
- const { showingFiles } = this.props.state;
- this.props.toggleShowFiles(!showingFiles);
- this.props.updateIsProcessing(true);
- this.props.updatePageIndex(0);
- this.props.updateLoadingStatus(false);
- } catch (error) {
- const options = {
- context: `${WzRulesetActionButtons.name}.toggleFiles`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.BUSINESS,
- store: false,
- error: {
- error: error,
- message: `Error generating CSV: ${error.message || error}`,
- title: error.name || error,
- },
- };
- getErrorOrchestrator().handleError(options);
- }
- }
-
- /**
- * Refresh the items
- */
- async refresh() {
- try {
- this.props.updateIsProcessing(true);
- // this.onRefreshLoading();
- } catch (error) {
- throw error;
- }
- }
-
- onRefreshLoading() {
- clearInterval(this.refreshTimeoutId);
-
- this.props.updateLoadingStatus(true);
- // this.refreshTimeoutId = setInterval(() => {
- // if(!this.props.state.isProcessing) {
- // clearInterval(this.refreshTimeoutId);
- // }
- // }, 100);
- }
-
- render() {
- const { section, showingFiles } = this.props.state;
-
- const getReadPermissionsFiles = () => {
- const { permissionResource } = resourceDictionary[section];
- return [
- {
- action: `${section}:read`,
- resource: permissionResource('*'),
- },
- ];
- };
-
- const getUpdatePermissionsFiles = () => {
- const { permissionResource } = resourceDictionary[section];
- return [
- {
- action: `${section}:update`,
- resource: permissionResource('*'),
- },
- {
- action: `${section}:read`,
- resource: permissionResource('*'),
- },
- ];
- };
-
- // Export button
- const exportButton = (
- await this.generateCsv()}
- isLoading={this.state.generatingCsv}
- >
- Export formatted
-
- );
-
- // Add new rule button
- const addNewRuleButton = (
-
- this.props.updteAddingRulesetFile({
- name: '',
- content: '',
- path: `etc/${section}`,
- })
- }
- >
- {`Add new ${section} file`}
-
- );
-
- //Add new CDB list button
- const addNewCdbListButton = (
-
- this.props.updateListContent({
- name: false,
- content: '',
- path: 'etc/lists',
- })
- }
- >
- {`Add new ${section} file`}
-
- );
-
- // Manage files
- const manageFiles = (
- await this.toggleFiles()}
- >
- {showingFiles ? `Manage ${section}` : `Manage ${section} files`}
-
- );
-
- // Refresh
- const refresh = (
- await this.refresh()}>
- Refresh
-
- );
-
- const uploadFile = async (files, resource, overwrite) => {
- try {
- const result = await this.uploadFiles(files, resource, overwrite);
- await this.refresh();
- return result
- } catch (error) {
- return error
- }
- };
-
- return (
-
- {section !== 'lists' && {manageFiles} }
- {section !== 'lists' && {addNewRuleButton} }
- {section === 'lists' && {addNewCdbListButton} }
- {(section === 'lists' || showingFiles) && (
-
- this.props.updateRestartClusterManager(true)}
- />
-
- )}
- {exportButton}
- {refresh}
-
- );
- }
-}
-
-const mapStateToProps = (state) => {
- return {
- state: state.rulesetReducers,
- };
-};
-
-const mapDispatchToProps = (dispatch) => {
- return {
- toggleShowFiles: (status) => dispatch(toggleShowFiles(status)),
- updateLoadingStatus: (status) => dispatch(updateLoadingStatus(status)),
- updteAddingRulesetFile: (content) => dispatch(updteAddingRulesetFile(content)),
- updateListContent: (content) => dispatch(updateListContent(content)),
- updateIsProcessing: (isProcessing) => dispatch(updateIsProcessing(isProcessing)),
- updatePageIndex: (pageIndex) => dispatch(updatePageIndex(pageIndex)),
- };
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(WzRulesetActionButtons);
diff --git a/public/controllers/management/components/management/ruleset/components/columns.tsx b/public/controllers/management/components/management/ruleset/components/columns.tsx
new file mode 100644
index 0000000000..ba57e1760f
--- /dev/null
+++ b/public/controllers/management/components/management/ruleset/components/columns.tsx
@@ -0,0 +1,281 @@
+import React from 'react';
+import { EuiToolTip, EuiBadge } from '@elastic/eui';
+import { resourceDictionary, ResourcesHandler, ResourcesConstants } from '../../common/resources-handler';
+import { WzButtonPermissions } from '../../../../../../components/common/permissions/button';
+import { WzButtonPermissionsModalConfirm } from '../../../../../../components/common/buttons';
+import { getErrorOrchestrator } from '../../../../../../react-services/common-services';
+import { UIErrorLog } from '../../../../../../react-services/error-orchestrator/types';
+import { getErrorOptions } from '../../common/error-helper';
+import { Columns } from '../../common/interfaces';
+
+
+export default class RulesetColumns {
+
+ columns: Columns = {};
+
+ constructor(props) {
+ this.props = props;
+ this._buildColumns();
+ }
+
+ _buildColumns() {
+ this.columns = {
+ rules: [
+ {
+ field: 'id',
+ name: 'ID',
+ align: 'left',
+ sortable: true,
+ width: '5%'
+ },
+ {
+ field: 'description',
+ name: 'Description',
+ align: 'left',
+ sortable: true,
+ width: '30%',
+ render: (value, item) => {
+ if (value === undefined) return '';
+ const regex = /\$(.*?)\)/g;
+ let result = value.match(regex);
+ let haveTooltip = false;
+ let toolTipDescription = false;
+ if (result !== null) {
+ haveTooltip = true;
+ toolTipDescription = value;
+ for (const oldValue of result) {
+ let newValue = oldValue.replace('$(', ``);
+ newValue = newValue.replace(')', ' ');
+ value = value.replace(oldValue, newValue);
+ }
+ }
+ return (
+
+ {haveTooltip === false ?
+ :
+
+
+
+ }
+
+ );
+ }
+ },
+ {
+ field: 'groups',
+ name: 'Groups',
+ align: 'left',
+ sortable: false,
+ width: '10%'
+ },
+ {
+ name: 'Regulatory compliance',
+ render: this.buildComplianceBadges
+ },
+ {
+ field: 'level',
+ name: 'Level',
+ align: 'left',
+ sortable: true,
+ width: '5%'
+ },
+ {
+ field: 'filename',
+ name: 'File',
+ align: 'left',
+ sortable: true,
+ width: '15%',
+ render: (value, item) => {
+ return (
+ {
+ try{
+ ev.stopPropagation();
+ const resourcesHandler = new ResourcesHandler(ResourcesConstants.RULES);
+ const result = await resourcesHandler.getFileContent(value);
+ const file = { name: value, content: result, path: item.relative_dirname };
+ this.props.updateFileContent(file);
+ }catch(error){
+ const options: UIErrorLog = getErrorOptions(
+ error,
+ 'Rules.readFileContent'
+ );
+ getErrorOrchestrator().handleError(options);
+ }
+ }}>
+ {value}
+
+ );
+ }
+ },
+ {
+ field: 'relative_dirname',
+ name: 'Path',
+ align: 'left',
+ sortable: true,
+ width: '10%'
+ }
+ ],
+ files: [
+ {
+ field: 'filename',
+ name: 'File',
+ align: 'left',
+ sortable: true
+ },
+ {
+ name: 'Actions',
+ align: 'left',
+ render: item => {
+ if (item.relative_dirname.startsWith('ruleset/')) {
+ return (
+ {
+ try{
+ ev.stopPropagation();
+ const resourcesHandler = new ResourcesHandler(this.props.state.section);
+ const result = await resourcesHandler.getFileContent(item.filename);
+ const file = { name: item.filename, content: result, path: item.relative_dirname };
+ this.props.updateFileContent(file);
+ }catch(error){
+ const options: UIErrorLog = getErrorOptions(
+ error,
+ 'Files.readFileContent'
+ );
+ getErrorOrchestrator().handleError(options);
+ }
+ }}
+ color="primary"
+ />
+ );
+ } else {
+ return (
+
+ {
+ try {
+ ev.stopPropagation();
+ const resourcesHandler = new ResourcesHandler(ResourcesConstants.RULES);
+ const result = await resourcesHandler.getFileContent(item.filename);
+ const file = { name: item.filename, content: result, path: item.relative_dirname };
+ this.props.updateFileContent(file);
+ } catch (error) {
+ const options: UIErrorLog = getErrorOptions(
+ error,
+ 'Files.editFileContent'
+ );
+ getErrorOrchestrator().handleError(options);
+ }
+ }}
+ color="primary"
+ />
+ {
+ try {
+ this.props.removeItems([item]);
+ } catch (error) {
+ const options: UIErrorLog = getErrorOptions(
+ error,
+ 'Files.deleteFile'
+ );
+ getErrorOrchestrator().handleError(options);
+ }
+ }}
+ color="danger"
+ modalTitle={'Are you sure?'}
+ modalProps={{
+ buttonColor: 'danger',
+ }}
+ />
+
+ );
+ }
+ }
+ }
+ ]
+ };
+
+ const getReadButtonPermissions = (item) => {
+ const { permissionResource } = resourceDictionary[ResourcesConstants.RULES];
+ return [
+ {
+ action: `${ResourcesConstants.RULES}:read`,
+ resource: permissionResource(item.filename),
+ },
+ ];
+ };
+
+ const getEditButtonPermissions = (item) => {
+ const { permissionResource } = resourceDictionary[ResourcesConstants.RULES];
+ return [
+ {
+ action: `${ResourcesConstants.RULES}:read`,
+ resource: permissionResource(item.filename),
+ },
+ { action: `${ResourcesConstants.RULES}:update`, resource: permissionResource(item.filename) },
+ ];
+ };
+
+ const getDeleteButtonPermissions = (item) => {
+ const { permissionResource } = resourceDictionary[ResourcesConstants.RULES];
+ return [
+ {
+ action: `${ResourcesConstants.RULES}:delete`,
+ resource: permissionResource(item.filename),
+ },
+ ];
+ };
+ }
+
+ buildComplianceBadges(item) {
+ const badgeList = [];
+ const fields = ['pci_dss', 'gpg13', 'hipaa', 'gdpr', 'nist_800_53', 'tsc', 'mitre'];
+ const buildBadge = field => {
+
+ return (
+
+ ev.stopPropagation()}
+ onClickAriaLabel={field.toUpperCase()}
+ style={{ margin: '1px 2px' }}
+ >
+ {field.toUpperCase()}
+
+
+ );
+ };
+ try {
+ for (const field of fields) {
+ if (item[field].length) {
+ badgeList.push(buildBadge(field));
+ }
+ }
+ } catch (error) { }
+
+ return {badgeList}
;
+ }
+}
diff --git a/public/controllers/management/components/management/ruleset/components/flyout-detail.tsx b/public/controllers/management/components/management/ruleset/components/flyout-detail.tsx
new file mode 100644
index 0000000000..d378b68733
--- /dev/null
+++ b/public/controllers/management/components/management/ruleset/components/flyout-detail.tsx
@@ -0,0 +1,38 @@
+/*
+ * Wazuh app - Rules components
+ * Copyright (C) 2015-2022 Wazuh, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Find more information about this on the LICENSE file.
+ */
+
+import React from 'react';
+import {
+ WzFlyout,
+} from '../../../../../../components/common/flyouts';
+import WzRuleInfo from '../views/rule-info';
+import '../../common/flyout-detail.scss'
+
+export const FlyoutDetail = ({ isLoading, item, title, closeFlyout, filters, ...rest }) => {
+
+
+ return (
+ closeFlyout()}
+ flyoutProps={{
+ size: "l",
+ 'aria-labelledby': title,
+ maxWidth: "70%",
+ className: "wz-inventory wzApp wz-ruleset-flyout",
+ }}
+ >
+ {item && !isLoading && <>
+
+ >}
+
+ );
+}
diff --git a/public/controllers/management/components/management/ruleset/components/ruleset-suggestions.ts b/public/controllers/management/components/management/ruleset/components/ruleset-suggestions.ts
new file mode 100644
index 0000000000..84e4115185
--- /dev/null
+++ b/public/controllers/management/components/management/ruleset/components/ruleset-suggestions.ts
@@ -0,0 +1,141 @@
+import { WzRequest } from '../../../../../../react-services/wz-request';
+
+const rulesItems = [
+ {
+ type: 'params',
+ label: 'status',
+ description: 'Filters the rules by status.',
+ values: ['enabled', 'disabled']
+ },
+ {
+ type: 'params',
+ label: 'group',
+ description: 'Filters the rules by group',
+ values: async value => {
+ const filter = { limit: 30 };
+ if (value) {
+ filter['search'] = value;
+ }
+ const result = await WzRequest.apiReq('GET', '/rules/groups', filter);
+ return result?.data?.data?.affected_items;
+ },
+ },
+ {
+ type: 'params',
+ label: 'level',
+ description: 'Filters the rules by level',
+ values: [...Array(16).keys()]
+ },
+ {
+ type: 'params',
+ label: 'filename',
+ description: 'Filters the rules by file name.',
+ values: async value => {
+ const filter = { limit: 30 };
+ if (value) {
+ filter['search'] = value;
+ }
+ const result = await WzRequest.apiReq('GET', '/rules/files', filter);
+ return result?.data?.data?.affected_items?.map((item) => { return item.filename });
+ },
+ },
+ {
+ type: 'params',
+ label: 'relative_dirname',
+ description: 'Path of the rules files',
+ values: async () => {
+ const result = await WzRequest.apiReq('GET', '/manager/configuration', {
+ params: {
+ section: 'ruleset',
+ field: 'rule_dir'
+ }
+ });
+ return result?.data?.data?.affected_items?.[0].ruleset.rule_dir;
+ }
+ },
+ {
+ type: 'params',
+ label: 'hipaa',
+ description: 'Filters the rules by HIPAA requirement',
+ values: async () => {
+ const result = await WzRequest.apiReq('GET', '/rules/requirement/hipaa', {});
+ return result?.data?.data?.affected_items;
+ }
+ },
+ {
+ type: 'params',
+ label: 'gdpr',
+ description: 'Filters the rules by GDPR requirement',
+ values: async () => {
+ const result = await WzRequest.apiReq('GET', '/rules/requirement/gdpr', {});
+ return result?.data?.data?.affected_items;
+ }
+ },
+ {
+ type: 'params',
+ label: 'nist-800-53',
+ description: 'Filters the rules by NIST requirement',
+ values: async () => {
+ const result = await WzRequest.apiReq('GET', '/rules/requirement/nist-800-53', {});
+ return result?.data?.data?.affected_items;
+ }
+ },
+ {
+ type: 'params',
+ label: 'gpg13',
+ description: 'Filters the rules by GPG requirement',
+ values: async () => {
+ const result = await WzRequest.apiReq('GET', '/rules/requirement/gpg13', {});
+ return result?.data?.data?.affected_items;
+ }
+ },
+ {
+ type: 'params',
+ label: 'pci_dss',
+ description: 'Filters the rules by PCI DSS requirement',
+ values: async () => {
+ const result = await WzRequest.apiReq('GET', '/rules/requirement/pci_dss', {});
+ return result?.data?.data?.affected_items;
+ }
+ },
+ {
+ type: 'params',
+ label: 'tsc',
+ description: 'Filters the rules by TSC requirement',
+ values: async () => {
+ const result = await WzRequest.apiReq('GET', '/rules/requirement/tsc', {});
+ return result?.data?.data?.affected_items;
+ }
+ },
+ {
+ type: 'params',
+ label: 'mitre',
+ description: 'Filters the rules by MITRE requirement',
+ values: async () => {
+ const result = await WzRequest.apiReq('GET', '/rules/requirement/mitre', {});
+ return result?.data?.data?.affected_items;
+ }
+ }
+];
+const rulesFiles = [
+ {
+ type: 'params',
+ label: 'filename',
+ description: 'Filters the rules by file name.',
+ values: async value => {
+ const filter = { limit: 30 };
+ if (value) {
+ filter['search'] = value;
+ }
+ const result = await WzRequest.apiReq('GET', '/rules/files', filter);
+ return result?.data?.data?.affected_items?.map((item) => { return item.filename });
+ },
+ },
+];
+
+const apiSuggestsItems = {
+ items: rulesItems,
+ files: rulesFiles,
+};
+
+export default apiSuggestsItems;
diff --git a/public/controllers/management/components/management/ruleset/components/ruleset-table.tsx b/public/controllers/management/components/management/ruleset/components/ruleset-table.tsx
new file mode 100644
index 0000000000..ee5ff82bcd
--- /dev/null
+++ b/public/controllers/management/components/management/ruleset/components/ruleset-table.tsx
@@ -0,0 +1,295 @@
+/*
+ * Wazuh app - Agent ruleset table component
+ * Copyright (C) 2015-2022 Wazuh, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Find more information about this on the LICENSE file.
+ */
+
+import React, { useEffect, useState, useCallback } from 'react';
+import { getToasts } from '../../../../../../kibana-services';
+import { resourceDictionary, ResourcesConstants, ResourcesHandler } from '../../common/resources-handler';
+import { getErrorOrchestrator } from '../../../../../../react-services/common-services';
+import { UI_ERROR_SEVERITIES } from '../../../../../../react-services/error-orchestrator/types';
+import { UI_LOGGER_LEVELS } from '../../../../../../../common/constants';
+
+import { TableWzAPI } from '../../../../../../components/common/tables';
+import { SECTION_RULES_SECTION, SECTION_RULES_KEY } from '../../common/constants';
+import RulesetColumns from './columns';
+import { FlyoutDetail } from './flyout-detail';
+import { withUserPermissions } from '../../../../../../components/common/hocs/withUserPermissions';
+import { WzUserPermissions } from '../../../../../../react-services/wz-user-permissions';
+import { compose } from 'redux';
+import {
+ ManageFiles,
+ AddNewFileButton,
+ UploadFilesButton,
+} from '../../common/actions-buttons'
+
+import apiSuggestsItems from './ruleset-suggestions';
+
+/***************************************
+ * Render tables
+ */
+const FilesTable = ({
+ actionButtons,
+ buttonOptions,
+ columns,
+ searchBarSuggestions,
+ filters,
+ updateFilters,
+ reload
+}) =>
+
+const RulesFlyoutTable = ({
+ actionButtons,
+ buttonOptions,
+ columns,
+ searchBarSuggestions,
+ filters,
+ updateFilters,
+ getRowProps,
+ isFlyoutVisible,
+ currentItem,
+ closeFlyout,
+ cleanFilters,
+ ...props
+}) => <>
+
+ {isFlyoutVisible && (
+
+ )}
+ >
+
+/***************************************
+ * Main component
+ */
+function RulesetTable({ setShowingFiles, showingFiles, ...props }) {
+ const [filters, setFilters] = useState([]);
+ const [isFlyoutVisible, setIsFlyoutVisible] = useState(false);
+ const [currentItem, setCurrentItem] = useState(null);
+
+ const [tableFootprint, setTableFootprint] = useState(0);
+
+ const resourcesHandler = new ResourcesHandler(ResourcesConstants.RULES);
+
+ useEffect(() => {
+ const regex = new RegExp('redirectRule=' + '[^&]*');
+ const match = window.location.href.match(regex);
+ if (match && match[0]) {
+ setCurrentItem(parseInt(match[0].split('=')[1]))
+ setIsFlyoutVisible(true)
+ }
+ }, [])
+
+ // Table custom filter options
+ const buttonOptions = [{ label: "Custom rules", field: "relative_dirname", value: "etc/rules" },];
+
+ const updateFilters = (filters) => {
+ setFilters(filters);
+ }
+
+ const cleanFilters = () => {
+ setFilters([]);
+ }
+
+ const toggleShowFiles = () => {
+ setFilters([]);
+ setShowingFiles(!showingFiles);
+ }
+
+ const closeFlyout = () => {
+ setIsFlyoutVisible(false);
+ }
+
+
+ /**
+ * Remove files method
+ */
+ const removeItems = async (items) => {
+ try {
+ const results = items.map(async (item, i) => {
+ await resourcesHandler.deleteFile(item.filename || item.name);
+ });
+
+ Promise.all(results).then((completed) => {
+ setTableFootprint(Date.now());
+ getToasts().add({
+ color: 'success',
+ title: 'Success',
+ text: 'Deleted successfully',
+ toastLifeTimeMs: 3000,
+ });
+ });
+ } catch (error) {
+ const options = {
+ context: `${WzRulesetTable.name}.removeItems`,
+ level: UI_LOGGER_LEVELS.ERROR,
+ severity: UI_ERROR_SEVERITIES.BUSINESS,
+ error: {
+ error: error,
+ message: `Error deleting item: ${error.message || error}`,
+ title: error.name || error,
+ },
+ };
+ getErrorOrchestrator().handleError(options);
+ }
+ }
+
+ /**
+ * Columns and Rows properties
+ */
+ const getColumns = () => {
+ const rulesetColumns = new RulesetColumns({
+ removeItems: removeItems,
+ state: {
+ section: SECTION_RULES_KEY
+ }, ...props
+ }).columns;
+ const columns = rulesetColumns[showingFiles ? 'files' : SECTION_RULES_KEY];
+ return columns;
+ }
+
+ const getRowProps = (item) => {
+ const { id, name } = item;
+
+ const getRequiredPermissions = (item) => {
+ const { permissionResource } = resourceDictionary[SECTION_RULES_KEY];
+ return [
+ {
+ action: `${SECTION_RULES_KEY}:read`,
+ resource: permissionResource(item.name),
+ },
+ ];
+ };
+
+ return {
+ 'data-test-subj': `row-${id || name}`,
+ className: 'customRowClass',
+ onClick: !WzUserPermissions.checkMissingUserPermissions(
+ getRequiredPermissions(item),
+ props.userPermissions
+ )
+ ? (item) => {
+ setCurrentItem(id)
+ setIsFlyoutVisible(true);
+ }
+ : undefined,
+ };
+ };
+
+ const { updateRestartClusterManager, updateFileContent } = props;
+ const columns = getColumns();
+
+ /**
+ * Build table custom action buttons dynamically based on showing files state
+ */
+ const buildActionButtons = useCallback(() => {
+ const buttons = [
+ ,
+ ,
+ ];
+ if (showingFiles)
+ buttons.push( { updateRestartClusterManager && updateRestartClusterManager() }}
+ />);
+ return buttons;
+ }, [showingFiles]);
+
+ const actionButtons = buildActionButtons();
+
+ return (
+
+ {showingFiles ? (
+
+ ) : (
+
+ )}
+
+ );
+
+}
+
+
+export default compose(
+ withUserPermissions
+)(RulesetTable);
\ No newline at end of file
diff --git a/public/controllers/management/components/management/ruleset/decoder-info.js b/public/controllers/management/components/management/ruleset/decoder-info.js
deleted file mode 100644
index 6756f7222d..0000000000
--- a/public/controllers/management/components/management/ruleset/decoder-info.js
+++ /dev/null
@@ -1,393 +0,0 @@
-import React, { Component, Fragment } from 'react';
-// Eui components
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiPanel,
- EuiPage,
- EuiButtonIcon,
- EuiTitle,
- EuiToolTip,
- EuiText,
- EuiSpacer,
- EuiInMemoryTable,
- EuiLink,
- EuiAccordion,
- EuiFlexGrid,
-} from '@elastic/eui';
-
-import { connect } from 'react-redux';
-
-import { RulesetHandler, RulesetResources } from './utils/ruleset-handler';
-import { colors } from './utils/colors';
-
-import {
- updateFileContent,
- cleanFileContent,
- cleanInfo,
- updateFilters,
- cleanFilters,
-} from '../../../../../redux/actions/rulesetActions';
-
-import { UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchestrator/types';
-import { UI_LOGGER_LEVELS } from '../../../../../../common/constants';
-import { getErrorOrchestrator } from '../../../../../react-services/common-services';
-
-class WzDecoderInfo extends Component {
- constructor(props) {
- super(props);
-
- this.rulesetHandler = new RulesetHandler(RulesetResources.DECODERS);
-
- const handleFileClick = async (value, item) => {
- try {
- const result = await this.rulesetHandler.getFileContent(value);
- const file = { name: value, content: result, path: item.relative_dirname };
- this.props.updateFileContent(file);
- } catch (error) {
- const options = {
- context: `${WzDecoderInfo.name}.handleFileClick`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.BUSINESS,
- error: {
- error: error,
- message: `Error updating file content: ${error.message || error}`,
- title: error.name || error,
- },
- };
- getErrorOrchestrator().handleError(options);
- }
- };
-
- this.columns = [
- {
- field: 'name',
- name: 'Name',
- align: 'left',
- sortable: true,
- },
- {
- field: 'details.program_name',
- name: 'Program name',
- align: 'left',
- sortable: true,
- },
- {
- field: 'details.order',
- name: 'Order',
- align: 'left',
- sortable: true,
- },
- {
- field: 'filename',
- name: 'File',
- align: 'left',
- sortable: true,
- render: (value, item) => {
- return (
-
- handleFileClick(value, item)}>{value}
-
- );
- },
- },
- {
- field: 'relative_dirname',
- name: 'Path',
- align: 'left',
- sortable: true,
- },
- ];
- }
-
- /**
- * Clean the existing filters and sets the new ones and back to the previous section
- */
- setNewFiltersAndBack(filters) {
- this.props.cleanFilters();
- this.props.updateFilters(filters);
- this.props.cleanInfo();
- }
-
- /**
- * Render the basic information in a list
- * @param {Number} position
- * @param {String} file
- * @param {String} path
- */
- renderInfo(position, file, path) {
- return (
-
-
- Position
- {position}
-
-
- File
-
-
-
- this.setNewFiltersAndBack([{ field: 'filename', value: file }])
- }
- >
- {file}
-
-
-
-
-
- Path
-
-
-
- this.setNewFiltersAndBack([{ field: 'relative_dirname', value: path }])
- }
- >
- {path}
-
-
-
-
-
-
- );
- }
-
- /**
- * Render a list with the details
- * @param {Array} details
- */
- renderDetails(details) {
- const detailsToRender = [];
- const capitalize = (str) => str[0].toUpperCase() + str.slice(1);
-
- Object.keys(details).forEach((key) => {
- let content = details[key];
- if (key === 'order') {
- content = this.colorOrder(content);
- } else if (typeof details[key] === 'object') {
- content = (
-
- {Object.keys(details[key]).map((k) => (
-
- {k}:
- {details[key][k]}
-
-
- ))}
-
- );
- } else {
- content = {details[key]} ;
- }
- detailsToRender.push(
-
- {capitalize(key)}
- {content}
-
- );
- });
-
- return {detailsToRender} ;
- }
-
- /**
- * This set a color to a given order
- * @param {String} order
- */
- colorOrder(order) {
- order = order.toString();
- let valuesArray = order.split(',');
- const result = [];
- for (let i = 0, len = valuesArray.length; i < len; i++) {
- const coloredString = (
-
- {valuesArray[i].startsWith(' ') ? valuesArray[i] : ` ${valuesArray[i]}`}
-
- );
- result.push(coloredString);
- }
- return result;
- }
-
- /**
- * This set a color to a given regex
- * @param {String} regex
- */
- colorRegex(regex) {
- regex = regex.toString();
- const starts = (
-
- {regex.split('(')[0]}
-
- );
- let valuesArray = regex.match(/\(((?!<\/span>).)*?\)(?!<\/span>)/gim);
- const result = [starts];
- for (let i = 0, len = valuesArray.length; i < len; i++) {
- const coloredString = (
-
- {valuesArray[i]}
-
- );
- result.push(coloredString);
- }
- return result;
- }
-
- /**
- * Changes between decoders
- * @param {Number} name
- */
- changeBetweenDecoders(name) {
- this.setState({ currentDecoder: name });
- }
-
- render() {
- const { decoderInfo, isLoading } = this.props.state;
- const currentDecoder =
- this.state && this.state.currentDecoder ? this.state.currentDecoder : decoderInfo.current;
- const decoders = decoderInfo.affected_items;
- const currentDecoderArr = decoders.filter((r) => {
- return r.name === currentDecoder;
- });
- const currentDecoderInfo = currentDecoderArr[0];
- const { position, details, filename, name, relative_dirname } = currentDecoderInfo;
- const columns = this.columns;
-
- const onClickRow = (item) => {
- return {
- onClick: () => {
- this.changeBetweenDecoders(item.name);
- },
- };
- };
-
- return (
-
-
-
- {/* Decoder description name */}
-
-
-
-
-
- {
- window.location.href = window.location.href.replace(
- new RegExp('redirectRule=' + '[^&]*'),
- ''
- );
- this.props.cleanInfo();
- }}
- />
-
- {name}
-
-
-
-
- {/* Cards */}
-
-
- {/* General info */}
-
-
- Information
-
- }
- paddingSize="none"
- initialIsOpen={true}
- >
-
- {this.renderInfo(position, filename, relative_dirname)}
-
-
-
-
-
-
-
- Details
-
- }
- paddingSize="none"
- initialIsOpen={true}
- >
- {this.renderDetails(details)}
-
-
-
- {/* Table */}
-
-
-
- Related decoders
-
- }
- paddingSize="none"
- initialIsOpen={true}
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
- }
-}
-
-const mapStateToProps = (state) => {
- return {
- state: state.rulesetReducers,
- };
-};
-
-const mapDispatchToProps = (dispatch) => {
- return {
- updateFileContent: (content) => dispatch(updateFileContent(content)),
- cleanFileContent: () => dispatch(cleanFileContent()),
- updateFilters: (filters) => dispatch(updateFilters(filters)),
- cleanFilters: () => dispatch(cleanFilters()),
- cleanInfo: () => dispatch(cleanInfo()),
- };
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(WzDecoderInfo);
diff --git a/public/controllers/management/components/management/ruleset/main-ruleset.js b/public/controllers/management/components/management/ruleset/main-ruleset.js
deleted file mode 100644
index 35a7ad3211..0000000000
--- a/public/controllers/management/components/management/ruleset/main-ruleset.js
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Wazuh app - React component for registering agents.
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-import React, { Component } from 'react';
-// Redux
-import store from '../../../../../redux/store';
-import WzReduxProvider from '../../../../../redux/wz-redux-provider';
-//Wazuh ruleset tables(rules, decoder, lists)
-import WzRulesetOverview from './ruleset-overview';
-//Information about rule or decoder
-import WzRuleInfo from './rule-info';
-import WzDecoderInfo from './decoder-info';
-import WzRulesetEditor from './ruleset-editor';
-import WzListEditor from './list-editor';
-
-export default class WzRuleset extends Component {
- _isMount = false;
- constructor(props) {
- super(props);
- this.state = {}; //Init state empty to avoid fails when try to read any parameter and this.state is not defined yet
- this.store = store;
- }
-
- UNSAFE_componentWillMount() {
- this._isMount = true;
- this.store.subscribe(() => {
- const state = this.store.getState().rulesetReducers;
- if (this._isMount) {
- this.setState(state);
- this.setState({ selectedTabId: state.section });
- }
- });
- }
-
- componentWillUnmount() {
- this._isMount = false;
- // When the component is going to be unmounted the ruleset state is reset
- const { ruleInfo, decoderInfo, listInfo, fileContent, addingRulesetFile } = this.state;
- if (
- !window.location.href.includes('rules?tab=rules') &&
- (!ruleInfo && !decoderInfo && !listInfo && !fileContent, !addingRulesetFile)
- ) {
- this.store.dispatch({ type: 'RESET' });
- }
- }
-
- render() {
- const { ruleInfo, decoderInfo, listInfo, fileContent, addingRulesetFile } = this.state;
-
- return (
-
- {(ruleInfo && ) ||
- (decoderInfo && ) ||
- (listInfo && ) ||
- ((fileContent || addingRulesetFile) && (
-
- )) || }
-
- );
- }
-}
diff --git a/public/controllers/management/components/management/ruleset/main-ruleset.tsx b/public/controllers/management/components/management/ruleset/main-ruleset.tsx
new file mode 100644
index 0000000000..5b95c11e3b
--- /dev/null
+++ b/public/controllers/management/components/management/ruleset/main-ruleset.tsx
@@ -0,0 +1,55 @@
+/*
+ * Wazuh app - React component for main Rules view.
+ * Copyright (C) 2015-2022 Wazuh, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Find more information about this on the LICENSE file.
+ */
+import React, { useState } from 'react';
+import WzReduxProvider from '../../../../../redux/wz-redux-provider';
+import WzRulesetOverview from './views/ruleset-overview';
+import WzFileEditor from '../common/file-editor';
+import { SECTION_RULES_SECTION } from '../common/constants';
+
+
+export default function WzRuleset({ clusterStatus, logtestProps }) {
+
+ const [fileContent, setFileContent] = useState(false);
+ const [addingFile, setAddingFile] = useState(false);
+ const [showingFiles, setShowingFiles] = useState(false);
+
+ const cleanEditState = () => {
+ setFileContent(false);
+ setAddingFile(false);
+ }
+
+ return (
+
+ {
+ ((fileContent || addingFile) && (
+ { setFileContent(fileContent) }}
+ cleanEditState={() => cleanEditState()}
+ />
+ )) || (
+ { setFileContent(fileContent) }}
+ updateAddingFile={(addingFile) => { setAddingFile(addingFile) }}
+ setShowingFiles={() => { setShowingFiles(!showingFiles) }}
+ showingFiles={showingFiles}
+ />
+ )
+ }
+
+ );
+}
diff --git a/public/controllers/management/components/management/ruleset/ruleset-filter-bar.js b/public/controllers/management/components/management/ruleset/ruleset-filter-bar.js
deleted file mode 100644
index a7ca6ad053..0000000000
--- a/public/controllers/management/components/management/ruleset/ruleset-filter-bar.js
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Wazuh app - React component for registering agents.
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-import React, { Component } from 'react';
-
-import { EuiComboBox, EuiFormRow } from '@elastic/eui';
-import { connect } from 'react-redux';
-
-import {
- updateLoadingStatus,
- updateFilters,
- updateError
-} from '../../../../../redux/actions/rulesetActions';
-
-import { RulesetHandler, RulesetResources } from './utils/ruleset-handler';
-import { UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchestrator/types';
-import { UI_LOGGER_LEVELS } from '../../../../../../common/constants';
-import { getErrorOrchestrator } from '../../../../../react-services/common-services';
-
-class WzRulesetFilterBar extends Component {
- constructor(props) {
- super(props);
-
- this.state = {
- isInvalid: false,
- selectedOptions: []
- };
-
- this.rulesetHandler = new RulesetHandler(this.props.state.section);
- this.availableOptions = {
- rules: [
- 'nist-800-53',
- 'hipaa',
- 'gdpr',
- 'pci',
- 'gpg13',
- 'tsc',
- 'group',
- 'level',
- 'path',
- 'file'
- ],
- decoders: ['path', 'file'],
- lists: []
- };
- this.notValidMessage = false;
- }
-
- componentDidMount() {
- this.buildSelectedOptions(this.props.state.filters); // If there are any filter in the redux store it will be restored when the component was mounted
- }
-
- isValid = value => {
- const { section, showingFiles } = this.props.state;
- if (section === 'lists' || showingFiles) return true; //There are not filters for lists
- const lowerValue = value.toLowerCase();
- const availableOptions = this.availableOptions[
- this.props.state.section
- ].toString();
- this.notValidMessage = false;
- const options = this.availableOptions[this.props.state.section];
- const valueSplit = lowerValue.split(':');
- const oneTwoDots = valueSplit.length - 1 === 1; // Has : once
- const moreTwoDots = valueSplit.length - 1 > 1; // Has : several times
- const notAvailable = !options.includes(valueSplit[0]); // Not include in the available options
- if (moreTwoDots || (oneTwoDots && notAvailable)) {
- if (oneTwoDots) {
- this.notValidMessage = `${
- valueSplit[0]
- } is a not valid filter, the available filters are: ${availableOptions}`;
- } else {
- this.notValidMessage = 'Only allow ":" once';
- }
- return false;
- }
- return true;
- };
-
- /**
- * Set a valid array of objects for the options in the combo box [{label: value}, {label: value}]
- */
- async buildSelectedOptions(filters) {
- try {
- const selectedOptions = [];
- Object.keys(filters).forEach(key => {
- const value = filters[key];
- const option = key === 'search' ? value : `${key}:${value}`;
- const newOption = {
- label: option
- };
- selectedOptions.push(newOption);
- });
- this.setState({ selectedOptions });
- //const result = await this.wzReq.apiReq('GET', this.paths[section], {})
- if (Object.keys(filters).length) await this.fetchItems(filters);
- } catch (error) {
- const options = {
- context: `${WzRulesetFilterBar.name}.buildSelectedOptions`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.UI,
- error: {
- error: error,
- message: error.message || error,
- title: `Error building selected options: ${error.message || error}`,
- },
- };
- getErrorOrchestrator().handleError(options);
- }
- }
-
- /**
- * Fetch items (rules, decoders)
- * @param {Object} filters
- */
- async fetchItems(filters) {
- try {
- const { section } = this.props.state;
- let fetcher = this.rulesetHandler.getResource;
- if (section === RulesetResources.LISTS) fetcher = this.rulesetHandler.getFiles; // If the sections is lists the fetcher changes
- this.props.updateLoadingStatus(true);
- const result = await fetcher(filters);
- this.props.updateLoadingStatus(false);
- } catch (error) {
- this.props.updateError(error);
- throw error;
- }
- }
-
- /**
- * When any element is removed from the this.state.selectedOptions is removed too from this.props.state.filters
- * @param {Array} selectedOptions
- */
- async cleanCurrentOption(selectedOptions) {
- try {
- const remainingKeys = [];
- const currentOptions = { ...this.props.state.filters };
- selectedOptions.forEach(option => {
- const value = option.label;
- const valueSplit = value.split(':');
- const isSearch = valueSplit.length === 1;
- const keyToRemove = isSearch ? 'search' : valueSplit[0];
- remainingKeys.push(keyToRemove);
- });
- const currentOptiosnKeys = Object.keys(currentOptions);
- const keysToRemove = currentOptiosnKeys.filter(option => {
- return !remainingKeys.includes(option);
- });
- keysToRemove.forEach(key => delete currentOptions[key]);
- this.props.updateFilters(currentOptions);
- await this.fetchItems(currentOptions);
- } catch (error) {
- const options = {
- context: `${WzRulesetFilterBar.name}.cleanCurrentOption`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.UI,
- error: {
- error: error,
- message: `Error cleaning current options: ${error.message || error}`,
- title: error.name || error,
- },
- };
- getErrorOrchestrator().handleError(options);
- }
- }
-
- onCreateOption = searchValue => {
- const isList = this.props.state.section === 'lists';
- const lowerValue = searchValue.toLowerCase();
- const currentOptions = { ...this.props.state.filters };
- const creatingSplit = lowerValue.split(':');
- let key = 'search';
- let value;
- if (!isList) {
- if (creatingSplit.length > 1) {
- key = creatingSplit[0];
- value = creatingSplit[1];
- } else {
- value = creatingSplit[0];
- }
- if (!this.isValid(lowerValue) || !value) return false; // Return false to explicitly reject the user's input.
- } else {
- value = lowerValue;
- }
- currentOptions[key] = value;
- this.props.updateFilters(currentOptions);
- this.buildSelectedOptions(currentOptions);
- };
-
- // When writting in the filter bar
- onSearchChange = searchValue => {
- if (!searchValue) {
- this.setState({
- isInvalid: false
- });
-
- return;
- }
-
- this.setState({
- isInvalid: !this.isValid(searchValue)
- });
- };
-
- onChange = selectedOptions => {
- this.setState({
- selectedOptions,
- isInvalid: false
- });
- this.cleanCurrentOption(selectedOptions);
- };
-
- render() {
- const { section, showingFiles } = this.props.state;
- const { selectedOptions, isInvalid } = this.state;
- const options = !Object.keys(this.props.state.filters).length
- ? []
- : selectedOptions;
- const filters = !showingFiles
- ? `Filter ${section}...`
- : `Search ${section} files...`;
-
- return (
-
-
-
- );
- }
-}
-
-const mapStateToProps = state => {
- return {
- state: state.rulesetReducers
- };
-};
-
-const mapDispatchToProps = dispatch => {
- return {
- updateLoadingStatus: status => dispatch(updateLoadingStatus(status)),
- updateFilters: filters => dispatch(updateFilters(filters)),
- updateError: error => dispatch(updateError(error))
- };
-};
-
-export default connect(
- mapStateToProps,
- mapDispatchToProps
-)(WzRulesetFilterBar);
diff --git a/public/controllers/management/components/management/ruleset/ruleset-overview.js b/public/controllers/management/components/management/ruleset/ruleset-overview.js
deleted file mode 100644
index d6d31a2924..0000000000
--- a/public/controllers/management/components/management/ruleset/ruleset-overview.js
+++ /dev/null
@@ -1,117 +0,0 @@
-import React, { Component } from 'react';
-// Eui components
-import {
- EuiFlexGroup,
- EuiFlexItem,
- EuiPanel,
- EuiPage,
- EuiText,
- EuiTitle,
- EuiLoadingSpinner,
- EuiSpacer
-} from '@elastic/eui';
-
-import { connect } from 'react-redux';
-
-// Wazuh components
-import WzRulesetTable from './ruleset-table';
-import WzRulesetSearchBar from './ruleset-search-bar';
-import WzRulesetActionButtons from './actions-buttons';
-import './ruleset-overview.scss';
-import { withUserAuthorizationPrompt, withGlobalBreadcrumb } from '../../../../../components/common/hocs';
-import WzRestartClusterManagerCallout from '../../../../../components/common/restart-cluster-manager-callout';
-import { compose } from 'redux';
-import { resourceDictionary } from './utils/ruleset-handler';
-
-class WzRulesetOverview extends Component {
- sectionNames = {
- rules: 'Rules',
- decoders: 'Decoders',
- lists: 'CDB lists'
- };
-
- constructor(props) {
- super(props);
- this.state = {
- totalItems: 0,
- showWarningRestart: false
- }
- }
-
- updateRestartManagers(showWarningRestart){
- this.setState({ showWarningRestart });
- }
-
- render() {
- const { section } = this.props.state;
- const { totalItems } = this.state;
-
- return (
-
-
-
-
-
- {this.sectionNames[section]} {totalItems === false ? : ({totalItems}) }
-
-
-
- this.updateRestartManagers(showWarningRestart)}/>
-
-
-
-
- {`From here you can manage your ${section}.`}
-
-
-
- {this.state.showWarningRestart && (
- <>
-
- this.updateRestartManagers(false)}
- onRestartedError={() => this.updateRestartManagers(true)}
- />
-
- >
- )}
-
-
-
- this.setState({ totalItems })}
- />
-
-
-
-
- );
- }
-}
-
-const mapStateToProps = state => {
- return {
- state: state.rulesetReducers
- };
-};
-
-export default compose(
- connect(
- mapStateToProps
- ),
- withGlobalBreadcrumb(props => {
- const sectionNames = {
- rules: 'Rules',
- decoders: 'Decoders',
- lists: 'CDB lists'
- }
- return [
- { text: '' },
- { text: 'Management', href: '#/manager' },
- { text: sectionNames[props.state.section] }
- ];
- }),
- withUserAuthorizationPrompt((props) => [{action: `${props.state.section}:read`, resource: resourceDictionary[props.state.section].permissionResource('*')}])
-)(WzRulesetOverview);
diff --git a/public/controllers/management/components/management/ruleset/ruleset-popover-filters.tsx b/public/controllers/management/components/management/ruleset/ruleset-popover-filters.tsx
deleted file mode 100644
index 945b03eac3..0000000000
--- a/public/controllers/management/components/management/ruleset/ruleset-popover-filters.tsx
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Wazuh app - React component for show filter list.
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-import {
- EuiFlexItem,
- EuiPopover,
- EuiButton,
- EuiButtonEmpty
-} from '@elastic/eui';
-
-class WzPopoverFilters extends Component {
- filters: {
- rules: { label: string; value: string; }[];
- decoders: { label: string; value: string; }[];
- };
-
- constructor(props) {
- super(props);
- this.state = {
- isPopoverOpen: false
- }
- this.filters = {
- rules: [
- { label: 'File', value: 'file' }, { label: 'Path', value: 'path' }, { label: 'Level', value: 'level' },
- { label: 'Group', value: 'group' }, { label: 'PCI control', value: 'pci' }, { label: 'GDPR', value: 'gdpr' }, { label: 'HIPAA', value: 'hipaa' }, { label: 'NIST-800-53', value: 'nist-800-53' }, { label: 'TSC', value: 'tsc' }
- ],
- decoders: [
- { label: 'File', value: 'file' }, { label: 'Path', value: 'path' }
- ]
- };
- }
-
- onButtonClick() {
- this.setState({
- isPopoverOpen: !this.state['isPopoverOpen'],
- });
- }
-
- closePopover() {
- this.setState({
- isPopoverOpen: false,
- });
- }
-
- render() {
- const { section } = this.props['state'];
- const button = (
- this.onButtonClick()}
- iconType="logstashFilter"
- aria-label="Filter">
- Filters
-
- );
-
- return (
-
-
- {this.filters[section].map((filter, idx) => (
-
- null}>
- {filter.label}
-
-
- ))}
-
-
- );
- }
-
-}
-
-const mapStateToProps = (state) => {
- return {
- state: state.rulesetReducers,
- };
-};
-
-const mapDispatchToProps = (dispatch) => {
- return {
- };
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(WzPopoverFilters);
diff --git a/public/controllers/management/components/management/ruleset/ruleset-search-bar.js b/public/controllers/management/components/management/ruleset/ruleset-search-bar.js
deleted file mode 100644
index 8331cefee1..0000000000
--- a/public/controllers/management/components/management/ruleset/ruleset-search-bar.js
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Wazuh app - React component for registering agents.
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-import React, { Component } from 'react';
-import { connect } from 'react-redux';
-
-import {
- updateFilters,
- updateIsProcessing
-} from '../../../../../redux/actions/rulesetActions';
-import { WzRequest } from '../../../../../react-services/wz-request';
-import { WzSearchBar } from '../../../../../components/wz-search-bar';
-
-class WzRulesetSearchBar extends Component {
- constructor(props) {
- super(props);
- }
-
- rulesItems = [
- {
- type: 'params',
- label: 'status',
- description: 'Filters the rules by status.',
- values: ['enabled', 'disabled']
- },
- {
- type: 'params',
- label: 'group',
- description: 'Filters the rules by group',
- values: async value => {
- const filter = { limit: 30 };
- if (value) {
- filter['search'] = value;
- }
- const wzReq = (...args) => WzRequest.apiReq(...args);
- const result = await wzReq('GET', '/rules/groups', filter);
- return (((result || {}).data || {}).data || {}).affected_items;
- },
- },
- {
- type: 'params',
- label: 'level',
- description: 'Filters the rules by level',
- values: [...Array(16).keys()]
- },
- {
- type: 'params',
- label: 'filename',
- description: 'Filters the rules by file name.',
- values: async value => {
- const filter = { limit: 30 };
- if (value) {
- filter['search'] = value;
- }
- const wzReq = (...args) => WzRequest.apiReq(...args);
- const result = await wzReq('GET', '/rules/files', filter);
- return (((result || {}).data || {}).data || {}).affected_items.map((item) => {return item.filename});
- },
- },
- {
- type: 'params',
- label: 'relative_dirname',
- description: 'Path of the rules files',
- values: async value => {
- const wzReq = (...args) => WzRequest.apiReq(...args);
- const result = await wzReq('GET', '/manager/configuration', {params: {
- section: 'ruleset',
- field: 'rule_dir'
- }});
- return (((result || {}).data || {}).data || {}).affected_items[0].ruleset.rule_dir;
- }
- },
- {
- type: 'params',
- label: 'hipaa',
- description: 'Filters the rules by HIPAA requirement',
- values: async () => {
- const wzReq = (...args) => WzRequest.apiReq(...args);
- const result = await wzReq('GET', '/rules/requirement/hipaa', {});
- return (((result || {}).data || {}).data || {}).affected_items;
- }
- },
- {
- type: 'params',
- label: 'gdpr',
- description: 'Filters the rules by GDPR requirement',
- values: async () => {
- const wzReq = (...args) => WzRequest.apiReq(...args);
- const result = await wzReq('GET', '/rules/requirement/gdpr', {});
- return (((result || {}).data || {}).data || {}).affected_items;
- }
- },
- {
- type: 'params',
- label: 'nist-800-53',
- description: 'Filters the rules by NIST requirement',
- values: async () => {
- const wzReq = (...args) => WzRequest.apiReq(...args);
- const result = await wzReq('GET', '/rules/requirement/nist-800-53', {});
- return (((result || {}).data || {}).data || {}).affected_items;
- }
- },
- {
- type: 'params',
- label: 'gpg13',
- description: 'Filters the rules by GPG requirement',
- values: async () => {
- const wzReq = (...args) => WzRequest.apiReq(...args);
- const result = await wzReq('GET', '/rules/requirement/gpg13', {});
- return (((result || {}).data || {}).data || {}).affected_items;
- }
- },
- {
- type: 'params',
- label: 'pci_dss',
- description: 'Filters the rules by PCI DSS requirement',
- values: async () => {
- const wzReq = (...args) => WzRequest.apiReq(...args);
- const result = await wzReq('GET', '/rules/requirement/pci_dss', {});
- return (((result || {}).data || {}).data || {}).affected_items;
- }
- },
- {
- type: 'params',
- label: 'tsc',
- description: 'Filters the rules by TSC requirement',
- values: async () => {
- const wzReq = (...args) => WzRequest.apiReq(...args);
- const result = await wzReq('GET', '/rules/requirement/tsc', {});
- return (((result || {}).data || {}).data || {}).affected_items;
- }
- },
- {
- type: 'params',
- label: 'mitre',
- description: 'Filters the rules by MITRE requirement',
- values: async () => {
- const result = await WzRequest.apiReq('GET', '/rules/requirement/mitre', {});
- return (((result || {}).data || {}).data || {}).affected_items;
- }
- }
- ];
- rulesFiles = [
- {
- type: 'params',
- label: 'filename',
- description: 'Filters the rules by file name.',
- values: async value => {
- const filter = { limit: 30 };
- if (value) {
- filter['search'] = value;
- }
- const wzReq = (...args) => WzRequest.apiReq(...args);
- const result = await wzReq('GET', '/rules/files', filter);
- return (((result || {}).data || {}).data || {}).affected_items.map((item) => {return item.filename});
- },
- },
- ];
-
- decodersItems = [
- {
- type: 'params',
- label: 'filename',
- description: 'Filters the decoders by file name.',
- values: async value => {
- const filter = { limit: 30 };
- if (value) {
- filter['search'] = value;
- }
- const wzReq = (...args) => WzRequest.apiReq(...args);
- const result = await wzReq('GET', '/decoders/files', filter);
- return (((result || {}).data || {}).data || {}).affected_items.map((item) => {return item.filename});
- },
- },
- {
- type: 'params',
- label: 'relative_dirname',
- description: 'Path of the decoders files.',
- values: async () => {
- const wzReq = (...args) => WzRequest.apiReq(...args);
- const result = await wzReq('GET', '/manager/configuration', {params: {
- section: 'ruleset',
- field: 'decoder_dir'
- }});
- return (((result || {}).data || {}).data || {}).affected_items[0].ruleset.decoder_dir;
- }
- },
- {
- type: 'params',
- label: 'status',
- description: 'Filters the decoders by status.',
- values: ['enabled', 'disabled']
- }
- ];
-
- apiSuggestsItems = {
- items: {
- rules: this.rulesItems,
- decoders: this.decodersItems,
- list: []
- },
- files: {
- rule: this.rulesFiles,
- decoders: [],
- list: []
- }
- };
-
- buttonOptions = {
- rules: [{label: "Custom rules", field:"relative_dirname", value:"etc/rules"}, ],
- decoders: [{label: "Custom decoders", field:"relative_dirname", value:"etc/decoders"}, ],
- list: []
- };
-
- render() {
- const { section, showingFiles, filters } = this.props.state;
- const type = showingFiles ? 'files' : 'items';
- const suggestions = this.apiSuggestsItems[type][section] || [];
- const buttonOptions = this.buttonOptions[section];
- return (
-
- );
- }
-}
-
-const mapStateToProps = state => {
- return {
- state: state.rulesetReducers
- };
-};
-
-const mapDispatchToProps = dispatch => {
- return {
- updateFilters: filters => dispatch(updateFilters(filters)),
- updateIsProcessing: state => dispatch(updateIsProcessing(state))
- };
-};
-
-export default connect(
- mapStateToProps,
- mapDispatchToProps
-)(WzRulesetSearchBar);
diff --git a/public/controllers/management/components/management/ruleset/ruleset-table.js b/public/controllers/management/components/management/ruleset/ruleset-table.js
deleted file mode 100644
index d88583b605..0000000000
--- a/public/controllers/management/components/management/ruleset/ruleset-table.js
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Wazuh app - React component for registering agents.
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-import React, { Component } from 'react';
-import { EuiBasicTable, EuiCallOut, EuiOverlayMask, EuiConfirmModal } from '@elastic/eui';
-
-import { connect } from 'react-redux';
-import { RulesetHandler, RulesetResources, resourceDictionary } from './utils/ruleset-handler';
-import { getToasts } from '../../../../../kibana-services';
-
-import {
- updateIsProcessing,
- updateShowModal,
- updateDefaultItems,
- updateListContent,
- updateFileContent,
- updateListItemsForRemove,
- updateRuleInfo,
- updateDecoderInfo,
-} from '../../../../../redux/actions/rulesetActions';
-
-import RulesetColums from './utils/columns';
-import { WzRequest } from '../../../../../react-services/wz-request';
-import { filtersToObject } from '../../../../../components/wz-search-bar';
-import { withUserPermissions } from '../../../../../components/common/hocs/withUserPermissions';
-import { WzUserPermissions } from '../../../../../react-services/wz-user-permissions';
-import { compose } from 'redux';
-import { UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchestrator/types';
-import { UI_LOGGER_LEVELS } from '../../../../../../common/constants';
-import { getErrorOrchestrator } from '../../../../../react-services/common-services';
-class WzRulesetTable extends Component {
- _isMounted = false;
- constructor(props) {
- super(props);
- this.wzReq = (...args) => WzRequest.apiReq(...args);
- this.state = {
- items: [],
- pageSize: 15,
- pageIndex: 0,
- totalItems: 0,
- isLoading: false,
- isRedirect: false,
- };
- this.paths = {
- rules: '/rules',
- decoders: '/decoders',
- lists: '/lists/files',
- };
- this.extraSectionPrefixResource = {
- rules: 'rule:file',
- decoders: 'decoder:file',
- lists: 'list:file',
- };
- this.rulesetHandler = new RulesetHandler(this.props.state.section);
- }
-
- async componentDidMount() {
- this._isMounted = true;
- this.props.updateIsProcessing(true);
- if (this.props.state.section === RulesetResources.RULES) {
- const regex = new RegExp('redirectRule=' + '[^&]*');
- const match = window.location.href.match(regex);
- if (match && match[0]) {
- this._isMounted && this.setState({ isRedirect: true });
- const id = match[0].split('=')[1];
- try {
- const result = await this.rulesetHandler.getResource({
- params: {
- rule_ids: id,
- },
- });
- const items = result.data.affected_items || [];
- if (items.length) {
- const info = await this.rulesetHandler.getResource({
- params: {
- filename: items[0].filename,
- },
- });
- if (info.data) {
- Object.assign(info.data, { current: parseInt(id) });
- }
- this.props.updateRuleInfo(info.data);
- }
- } catch (error) {
- const options = {
- context: `${WzRulesetTable.name}.componentDidMount`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.BUSINESS,
- error: {
- error: error,
- message: `Error getting resources: ${error.message || error}`,
- title: error.name || error,
- },
- };
- getErrorOrchestrator().handleError(options);
- }
- this._isMounted && this.setState({ isRedirect: false });
- }
- }
- }
-
- async componentDidUpdate(prevProps) {
- const { isProcessing, section, showingFiles, filters } = this.props.state;
-
- const processingChange =
- prevProps.state.isProcessing !== isProcessing ||
- (prevProps.state.isProcessing && isProcessing);
- const sectionChanged = prevProps.state.section !== section;
- const showingFilesChanged = prevProps.state.showingFiles !== showingFiles;
- const filtersChanged = prevProps.state.filters !== filters;
-
- try {
- if (
- (this._isMounted && processingChange && isProcessing) ||
- sectionChanged ||
- filtersChanged
- ) {
- if (sectionChanged || showingFilesChanged || filtersChanged) {
- this._isMounted &&
- (await this.setState({
- pageSize: this.state.pageSize,
- pageIndex: 0,
- sortDirection: null,
- sortField: null,
- }));
- }
- this._isMounted && this.setState({ isLoading: true });
- this.props.updateIsProcessing(false);
- await this.getItems();
- }
- } catch (error) {
- const options = {
- context: `${WzRulesetTable.name}.componentDidUpdate`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.BUSINESS,
- error: {
- error: error,
- message: `Error getting items: ${error.message || error}`,
- title: error.name || error,
- },
- };
- getErrorOrchestrator().handleError(options);
- }
- }
-
- componentWillUnmount() {
- this._isMounted = false;
- }
-
- async getItems() {
- const { section, showingFiles } = this.props.state;
-
- this._isMounted &&
- this.setState({
- items: [],
- });
- this.props.updateTotalItems(false);
-
- const rawItems = await this.wzReq(
- 'GET',
- `${this.paths[this.props.request]}${showingFiles ? '/files' : ''}`,
- { params: this.buildFilter() }
- ).catch((error) => {
- throw new Error(`Error when get the items of ${section}`);
- });
-
- const { affected_items = [], total_affected_items = 0 } =
- ((rawItems || {}).data || {}).data || {};
- this.props.updateTotalItems(total_affected_items);
- this._isMounted &&
- this.setState({
- items: affected_items,
- totalItems: total_affected_items,
- isLoading: false,
- });
- }
-
- async setDefaultItems() {
- try {
- const requestDefaultItems = await this.wzReq('GET', '/manager/configuration', {
- wait_for_complete: false,
- section: 'ruleset',
- field: 'list',
- });
-
- const defaultItems = ((requestDefaultItems || {}).data || {}).data;
- this.props.updateDefaultItems(defaultItems);
- } catch (error) {
- throw error;
- }
- }
-
- buildFilter() {
- const { pageSize, pageIndex } = this.state;
- const { filters } = this.props.state;
- const filter = {
- offset: pageIndex * pageSize,
- limit: pageSize,
- ...this.buildSortFilter(),
- ...filtersToObject(filters),
- };
-
- return filter;
- }
-
- buildSortFilter() {
- const { sortDirection, sortField } = this.state;
- const sortFilter = {};
- if (sortField) {
- const direction = sortDirection === 'asc' ? '+' : '-';
- sortFilter['sort'] = direction + sortField;
- }
-
- return sortFilter;
- }
-
- onTableChange = ({ page = {}, sort = {} }) => {
- const { index: pageIndex, size: pageSize } = page;
- const { field: sortField, direction: sortDirection } = sort;
- this.setState({ pageSize, pageIndex, sortDirection, sortField });
- this.props.updateIsProcessing(true);
- };
-
- getColumns() {
- const { section, showingFiles } = this.props.state;
- const rulesetColums = new RulesetColums(this.props).columns;
- const columns = showingFiles ? rulesetColums.files : rulesetColums[section];
- return columns;
- }
-
- render() {
- const { error } = this.props.state;
- const {
- items,
- pageSize,
- totalItems,
- pageIndex,
- sortField,
- sortDirection,
- isLoading,
- isRedirect,
- } = this.state;
- const columns = this.getColumns();
- const message = isLoading ? null : 'No results...';
- const pagination = {
- pageIndex: pageIndex,
- pageSize: pageSize,
- totalItemCount: totalItems,
- pageSizeOptions: [10, 15, 25, 50, 100],
- };
- const sorting = !!sortField
- ? {
- sort: {
- field: sortField,
- direction: sortDirection,
- },
- }
- : {};
-
- if (!error) {
- const itemList = this.props.state.itemList;
-
- const getRowProps = (item) => {
- const { id, name } = item;
-
- const getRequiredPermissions = (item) => {
- const { section } = this.props.state;
- const { permissionResource } = resourceDictionary[section];
- return [
- {
- action: `${section}:read`,
- resource: permissionResource(item.name),
- },
- ];
- };
-
- const updateInfo = async () => {
- if (this.isLoading) return;
- this.setState({ isLoading: true });
- const { section } = this.props.state;
- section === RulesetResources.RULES && (window.location.href = `${window.location.href}&redirectRule=${id}`);
- try {
- if (section === RulesetResources.LISTS) {
- const result = await this.rulesetHandler.getFileContent(item.filename);
- const file = {
- name: item.filename,
- content: result,
- path: item.relative_dirname,
- };
- this.props.updateListContent(file);
- } else {
- const result = await this.rulesetHandler.getResource({
- params: {
- filename: item.filename,
- },
- });
- if (result.data) {
- Object.assign(result.data, { current: id || name });
- }
- if (section === RulesetResources.RULES) this.props.updateRuleInfo(result.data);
- if (section === RulesetResources.DECODERS) this.props.updateDecoderInfo(result.data);
- }
- } catch (error) {
- const options = {
- context: `${WzRulesetTable.name}.updateInfo`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.BUSINESS,
- error: {
- error: error,
- message: `Error updating info: ${error.message || error}`,
- title: error.name || error,
- },
- };
- getErrorOrchestrator().handleError(options);
- this.setState({ isLoading: false });
- }
- this.setState({ isLoading: false });
- };
-
- return {
- 'data-test-subj': `row-${id || name}`,
- className: 'customRowClass',
- onClick: !WzUserPermissions.checkMissingUserPermissions(
- getRequiredPermissions(item),
- this.props.userPermissions
- )
- ? updateInfo
- : undefined,
- };
- };
-
- return (
-
-
- {this.props.state.showModal ? (
-
- this.props.updateShowModal(false)}
- onConfirm={() => {
- this.removeItems(itemList);
- this.props.updateShowModal(false);
- }}
- cancelButtonText="No, don't do it"
- confirmButtonText="Yes, do it"
- defaultFocusedButton="cancel"
- buttonColor="danger"
- >
- These items will be removed
-
- {itemList.map(function (item, i) {
- return
{item.filename ? item.filename : item.name} ;
- })}
-
-
-
- ) : null}
-
- );
- } else {
- return ;
- }
- }
-
- showToast = (color, title, text, time) => {
- getToasts().add({
- color: color,
- title: title,
- text: text,
- toastLifeTimeMs: time,
- });
- };
-
- async removeItems(items) {
- try {
- this.setState({ isLoading: true });
- const results = items.map(async (item, i) => {
- await this.rulesetHandler.deleteFile(item.filename || item.name);
- });
-
- Promise.all(results).then((completed) => {
- this.props.updateIsProcessing(true);
- this.showToast('success', 'Success', 'Deleted successfully', 3000);
- });
- } catch (error) {
- const options = {
- context: `${WzRulesetTable.name}.removeItems`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.BUSINESS,
- error: {
- error: error,
- message: `Error deleting item: ${error.message || error}`,
- title: error.name || error,
- },
- };
- getErrorOrchestrator().handleError(options);
- }
- }
-}
-
-const mapStateToProps = (state) => {
- return {
- state: state.rulesetReducers,
- };
-};
-
-const mapDispatchToProps = (dispatch) => {
- return {
- updateDefaultItems: (defaultItems) => dispatch(updateDefaultItems(defaultItems)), //TODO: Research to remove
- updateIsProcessing: (isProcessing) => dispatch(updateIsProcessing(isProcessing)),
- updateShowModal: (showModal) => dispatch(updateShowModal(showModal)),
- updateFileContent: (fileContent) => dispatch(updateFileContent(fileContent)),
- updateListContent: (listInfo) => dispatch(updateListContent(listInfo)),
- updateListItemsForRemove: (itemList) => dispatch(updateListItemsForRemove(itemList)),
- updateRuleInfo: (rule) => dispatch(updateRuleInfo(rule)),
- updateDecoderInfo: (rule) => dispatch(updateDecoderInfo(rule)),
- };
-};
-
-export default compose(
- connect(mapStateToProps, mapDispatchToProps),
- withUserPermissions
-)(WzRulesetTable);
diff --git a/public/controllers/management/components/management/ruleset/section-selector.js b/public/controllers/management/components/management/ruleset/section-selector.js
deleted file mode 100644
index 7333ff0d7b..0000000000
--- a/public/controllers/management/components/management/ruleset/section-selector.js
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Wazuh app - React component for registering agents.
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-import React, { Component } from 'react';
-import { EuiSelect } from '@elastic/eui';
-
-import { connect } from 'react-redux';
-import {
- updateRulesetSection,
- updateLoadingStatus,
- toggleShowFiles,
- cleanFilters,
- updateError,
- updateIsProcessing
-} from '../../../../redux/actions/rulesetActions';
-
-import { WzRequest } from '../../../../react-services/wz-request';
-import { UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchestrator/types';
-import { UI_LOGGER_LEVELS } from '../../../../../../common/constants';
-import { getErrorOrchestrator } from '../../../../../react-services/common-services';
-
-class WzSectionSelector extends Component {
- constructor(props) {
- super(props);
-
- this.sections = [
- { value: 'rules', text: 'Rules' },
- { value: 'decoders', text: 'Decoders' },
- { value: 'lists', text: 'CDB lists' }
- ];
-
- this.paths = {
- rules: '/rules',
- decoders: '/decoders',
- lists: '/lists/files'
- };
-
- this.wzReq = WzRequest;
- }
-
- /**
- * Fetch the data for a section: rules, decoders, lists...
- * @param {String} newSection
- */
- async fetchData(newSection) {
- try {
- const currentSection = this.props.state.section;
- if (
- Object.keys(this.props.state.filters).length &&
- newSection === currentSection
- )
- return; // If there's any filter and the section is de same doesn't fetch again
- this.props.changeSection(newSection);
- this.props.updateLoadingStatus(true);
- const result = await this.wzReq.apiReq('GET', this.paths[newSection], {});
- const items = result.data.data.items;
-
- this.props.toggleShowFiles(false);
- this.props.changeSection(newSection);
- this.props.updateLoadingStatus(false);
- } catch (error) {
- this.props.updateError(error);
- throw error;
- }
- }
-
- onChange = async e => {
- try {
- const section = e.target.value;
- this.props.cleanFilters();
- this.props.updateIsProcessing(true);
- this.fetchData(section);
- }catch (error){
- const options = {
- context: `${WzSectionSelector.name}.onChange`,
- level: UI_LOGGER_LEVELS.ERROR,
- severity: UI_ERROR_SEVERITIES.BUSINESS,
- error: {
- error: error,
- message: error.message || error,
- title: `Error fetching data: ${error.message || error}`,
- },
- };
- getErrorOrchestrator().handleError(options);
- }
- };
-
- render() {
- return (
-
- );
- }
-}
-
-const mapStateToProps = state => {
- return {
- state: state.rulesetReducers
- };
-};
-
-const mapDispatchToProps = dispatch => {
- return {
- changeSection: section => dispatch(updateRulesetSection(section)),
- updateLoadingStatus: status => dispatch(updateLoadingStatus(status)),
- toggleShowFiles: status => dispatch(toggleShowFiles(status)),
- cleanFilters: () => dispatch(cleanFilters()),
- updateError: error => dispatch(updateError(error)),
- updateIsProcessing: isProcessing =>
- dispatch(updateIsProcessing(isProcessing))
- };
-};
-
-export default connect(
- mapStateToProps,
- mapDispatchToProps
-)(WzSectionSelector);
diff --git a/public/controllers/management/components/management/ruleset/utils/columns.tsx b/public/controllers/management/components/management/ruleset/utils/columns.tsx
deleted file mode 100644
index 1a3160b636..0000000000
--- a/public/controllers/management/components/management/ruleset/utils/columns.tsx
+++ /dev/null
@@ -1,481 +0,0 @@
-import React from 'react';
-import { EuiToolTip, EuiButtonIcon, EuiLink, EuiBadge } from '@elastic/eui';
-import { resourceDictionary, RulesetHandler, RulesetResources } from './ruleset-handler';
-import exportCsv from '../../../../../../react-services/wz-csv';
-import { WzButtonPermissions } from '../../../../../../components/common/permissions/button';
-import { getErrorOrchestrator } from '../../../../../../react-services/common-services';
-import { UIErrorLog, UILogLevel, UIErrorSeverity, UI_ERROR_SEVERITIES } from '../../../../../../react-services/error-orchestrator/types';
-import { UI_LOGGER_LEVELS } from '../../../../../../../common/constants';
-
-export default class RulesetColumns {
- constructor(tableProps) {
- this.tableProps = tableProps;
-
- this.buildColumns = () => {
- this.columns = {
- rules: [
- {
- field: 'id',
- name: 'ID',
- align: 'left',
- sortable: true,
- width: '5%'
- },
- {
- field: 'description',
- name: 'Description',
- align: 'left',
- sortable: true,
- width: '30%',
- render: (value, item) => {
- if(value === undefined) return '';
- const regex = /\$(.*?)\)/g;
- let result = value.match(regex);
- let haveTooltip = false;
- let toolTipDescription = false;
- if(result !== null) {
- haveTooltip = true;
- toolTipDescription = value;
- for (const oldValue of result) {
- let newValue = oldValue.replace('$(',``);
- newValue = newValue.replace(')', ' ');
- value = value.replace(oldValue, newValue);
- }
- }
- return (
-
- {haveTooltip === false ?
- :
-
-
-
- }
-
- );
- }
- },
- {
- field: 'groups',
- name: 'Groups',
- align: 'left',
- sortable: false,
- width: '10%'
- },
- {
- name: 'Regulatory compliance',
- render: this.buildComplianceBadges
- },
- {
- field: 'level',
- name: 'Level',
- align: 'left',
- sortable: true,
- width: '5%'
- },
- {
- field: 'filename',
- name: 'File',
- align: 'left',
- sortable: true,
- width: '15%',
- render: (value, item) => {
- return (
- {
- try{
- ev.stopPropagation();
- const rulesetHandler = new RulesetHandler(RulesetResources.RULES);
- const result = await rulesetHandler.getFileContent(value);
- const file = { name: value, content: result, path: item.relative_dirname };
- this.tableProps.updateFileContent(file);
- }catch(error){
- const options: UIErrorLog = this.getErrorOptions(
- error,
- 'Rules.readFileContent'
- );
- getErrorOrchestrator().handleError(options);
- }
- }}>
- {value}
-
- );
- }
- },
- {
- field: 'relative_dirname',
- name: 'Path',
- align: 'left',
- sortable: true,
- width: '10%'
- }
- ],
- decoders: [
- {
- field: 'name',
- name: 'Name',
- align: 'left',
- sortable: true
- },
- {
- field: 'details.program_name',
- name: 'Program name',
- align: 'left',
- sortable: false
- },
- {
- field: 'details.order',
- name: 'Order',
- align: 'left',
- sortable: false
- },
- {
- field: 'filename',
- name: 'File',
- align: 'left',
- sortable: true,
- render: (value, item) => {
- return (
- {
- try{
- ev.stopPropagation();
- const rulesetHandler = new RulesetHandler(RulesetResources.DECODERS);
- const result = await rulesetHandler.getFileContent(value);
- const file = { name: value, content: result, path: item.relative_dirname };
- this.tableProps.updateFileContent(file);
- }catch(error){
- const options: UIErrorLog = this.getErrorOptions(
- error,
- 'Decoders.readFileContent'
- );
- getErrorOrchestrator().handleError(options);
- }
- }}>
- {value}
-
- );
- }
- },
- {
- field: 'relative_dirname',
- name: 'Path',
- align: 'left',
- sortable: true
- }
- ],
- lists: [
- {
- field: 'filename',
- name: 'Name',
- align: 'left',
- sortable: true
- },
- {
- field: 'relative_dirname',
- name: 'Path',
- align: 'left',
- sortable: true
- },
- {
- name: 'Actions',
- align: 'left',
- render: (item) => (
-
- {
- try{
- ev.stopPropagation();
- await exportCsv(`/lists?path=${item.relative_dirname}/${item.filename}`, [{_isCDBList: true, name: 'path', value: `${item.relative_dirname}/${item.filename}`}], item.filename)
- }catch(error){
- const options: UIErrorLog = this.getErrorOptions(
- error,
- 'Lists.exportFile'
- );
- getErrorOrchestrator().handleError(options);
- }
- }}
- color="primary"
- />
-
- )
- }
- ],
- files: [
- {
- field: 'filename',
- name: 'File',
- align: 'left',
- sortable: true
- },
- {
- name: 'Actions',
- align: 'left',
- render: item => {
- if (item.relative_dirname.startsWith('ruleset/')) {
- return (
- {
- try{
- ev.stopPropagation();
- const rulesetHandler = new RulesetHandler(this.tableProps.state.section);
- const result = await rulesetHandler.getFileContent(item.filename);
- const file = { name: item.filename, content: result, path: item.relative_dirname };
- this.tableProps.updateFileContent(file);
- }catch(error){
- const options: UIErrorLog = this.getErrorOptions(
- error,
- 'Files.readFileContent'
- );
- getErrorOrchestrator().handleError(options);
- }
- }}
- color="primary"
- />
- );
- } else {
- return (
-
- {
- try{
- ev.stopPropagation();
- const rulesetHandler = new RulesetHandler(this.tableProps.state.section);
- const result = await rulesetHandler.getFileContent(item.filename);
- const file = { name: item.filename, content: result, path: item.relative_dirname };
- this.tableProps.updateFileContent(file);
- }catch(error){
- const options: UIErrorLog = this.getErrorOptions(
- error,
- 'Files.editFileContent'
- );
- getErrorOrchestrator().handleError(options);
- }
- }}
- color="primary"
- />
- {
- try{
- ev.stopPropagation();
- this.tableProps.updateListItemsForRemove([item]);
- this.tableProps.updateShowModal(true);
- }catch(error){
- const options: UIErrorLog = this.getErrorOptions(
- error,
- 'Files.deleteFile'
- );
- getErrorOrchestrator().handleError(options);
- }
- }}
- color="danger"
- />
-
- );
- }
- }
- }
- ]
- };
-
- const getReadButtonPermissions = (item) => {
- const { section } = this.tableProps.state;
- const { permissionResource } = resourceDictionary[section];
- return [
- {
- action: `${section}:read`,
- resource: permissionResource(item.filename),
- },
- ];
- };
-
- const getEditButtonPermissions = (item) => {
- const { section } = this.tableProps.state;
- const { permissionResource } = resourceDictionary[section];
- return [
- {
- action: `${section}:read`,
- resource: permissionResource(item.filename),
- },
- { action: `${section}:update`, resource: permissionResource(item.filename) },
- ];
- };
-
- const getDeleteButtonPermissions = (item) => {
- const { section } = this.tableProps.state;
- const { permissionResource } = resourceDictionary[section];
- return [
- {
- action: `${section}:delete`,
- resource: permissionResource(item.filename),
- },
- ];
- };
-
- this.columns.lists[2] =
- {
- name: 'Actions',
- align: 'left',
- render: item => {
- const defaultItems = this.tableProps.state.defaultItems;
- return (
-
- {
- try{
- ev.stopPropagation();
- const rulesetHandler = new RulesetHandler(this.tableProps.state.section);
- const result = await rulesetHandler.getFileContent(item.filename);
- const file = { name: item.filename, content: result, path: item.relative_dirname };
- this.tableProps.updateListContent(file);
- }catch(error){
- const options: UIErrorLog = this.getErrorOptions(
- error,
- 'Lists.editFileContent'
- );
- getErrorOrchestrator().handleError(options);
- }
- }}
- color="primary"
- />
- {
- try{
- ev.stopPropagation();
- this.tableProps.updateListItemsForRemove([item]);
- this.tableProps.updateShowModal(true);
- }catch(error){
- const options: UIErrorLog = this.getErrorOptions(
- error,
- 'Lists.deleteFile'
- );
- getErrorOrchestrator().handleError(options);
- }
- }}
- color="danger"
- isDisabled={defaultItems.indexOf(`${item.relative_dirname}`) !== -1}
- />
- {
- try{
- ev.stopPropagation();
- await exportCsv(`/lists`, [{_isCDBList: true, name: 'filename', value: `${item.filename}`}], item.filename)
- }catch(error){
- const options: UIErrorLog = this.getErrorOptions(
- error,
- 'Lists.exportFile'
- );
- getErrorOrchestrator().handleError(options);
- }
- }}
- color="primary"
- />
-
- )
- }
- }
- };
-
-
- this.buildColumns();
- }
-
- /**
- * Build and return a new error options object, based on the actual error
- * and the context
- * @param error raised error
- * @param context context of the error
- * @returns a dictionary with the error details for the ErrorOrchestator
- */
- private getErrorOptions(error: unknown, context: string): UIErrorLog {
- return {
- context: context,
- level: UI_LOGGER_LEVELS.ERROR as UILogLevel,
- severity: UI_ERROR_SEVERITIES.BUSINESS as UIErrorSeverity,
- error: {
- error: error,
- message: error.message || error,
- title: error.name,
- },
- };
- }
-
- buildComplianceBadges(item) {
- const badgeList = [];
- const fields = ['pci_dss', 'gpg13', 'hipaa', 'gdpr', 'nist_800_53', 'tsc', 'mitre'];
- const buildBadge = field => {
- const idGenerator = () => {
- return (
- '_' +
- Math.random()
- .toString(36)
- .substr(2, 9)
- );
- };
-
- return (
-
- ev.stopPropagation()}
- onClickAriaLabel={field.toUpperCase()}
- style={{ margin: '1px 2px' }}
- >
- {field.toUpperCase()}
-
-
- );
- };
- try {
- for (const field of fields) {
- if (item[field].length) {
- badgeList.push(buildBadge(field));
- }
- }
- } catch (error) {}
-
- return {badgeList}
;
- }
-}
diff --git a/public/controllers/management/components/management/ruleset/rule-info.js b/public/controllers/management/components/management/ruleset/views/rule-info.tsx
similarity index 73%
rename from public/controllers/management/components/management/ruleset/rule-info.js
rename to public/controllers/management/components/management/ruleset/views/rule-info.tsx
index 355ffd164a..9c98a1354e 100644
--- a/public/controllers/management/components/management/ruleset/rule-info.js
+++ b/public/controllers/management/components/management/ruleset/views/rule-info.tsx
@@ -1,16 +1,14 @@
-import React, { Component, Fragment } from 'react';
+import React, { Component } from 'react';
// Eui components
import {
EuiFlexGroup,
EuiFlexItem,
- EuiPanel,
- EuiPage,
- EuiButtonIcon,
+ EuiFlyoutHeader,
+ EuiFlyoutBody,
EuiTitle,
EuiToolTip,
EuiBadge,
EuiSpacer,
- EuiInMemoryTable,
EuiLink,
EuiAccordion,
EuiFlexGrid,
@@ -18,25 +16,16 @@ import {
EuiLoadingSpinner,
} from '@elastic/eui';
-import { connect } from 'react-redux';
-import { WzRequest } from '../../../../../react-services/wz-request';
+import { WzRequest } from '../../../../../../react-services/wz-request';
-import { RulesetHandler, RulesetResources } from './utils/ruleset-handler';
+import { ResourcesHandler, ResourcesConstants } from '../../common/resources-handler';
+import WzTextWithTooltipTruncated from '../../../../../../components/common/wz-text-with-tooltip-if-truncated';
+import { UI_ERROR_SEVERITIES } from '../../../../../../react-services/error-orchestrator/types';
+import { UI_LOGGER_LEVELS } from '../../../../../../../common/constants';
+import { TableWzAPI } from '../../../../../../components/common/tables';
+import { getErrorOrchestrator } from '../../../../../../react-services/common-services';
-import {
- updateFileContent,
- cleanFileContent,
- cleanInfo,
- updateFilters,
- cleanFilters,
-} from '../../../../../redux/actions/rulesetActions';
-
-import WzTextWithTooltipTruncated from '../../../../../components/common/wz-text-with-tooltip-if-truncated';
-import { UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchestrator/types';
-import { UI_LOGGER_LEVELS } from '../../../../../../common/constants';
-import { getErrorOrchestrator } from '../../../../../react-services/common-services';
-
-class WzRuleInfo extends Component {
+export default class WzRuleInfo extends Component {
constructor(props) {
super(props);
this.complianceEquivalences = {
@@ -56,13 +45,15 @@ class WzRuleInfo extends Component {
mitreTechniques: [],
mitreRuleId: '',
mitreIds: [],
+ currentRuleInfo: {},
+ isLoading: true
};
- this.rulesetHandler = new RulesetHandler(RulesetResources.RULES);
+ this.resourcesHandler = new ResourcesHandler(ResourcesConstants.RULES);
- const handleFileClick = async (event, {filename, relative_dirname}) => {
+ const handleFileClick = async (event, { filename, relative_dirname }) => {
event.stopPropagation();
try {
- const result = await this.rulesetHandler.getFileContent(filename);
+ const result = await this.resourcesHandler.getFileContent(filename);
const file = {
name: filename,
content: result,
@@ -151,11 +142,67 @@ class WzRuleInfo extends Component {
];
}
- componentDidMount() {
+ async componentDidMount() {
document.body.scrollTop = 0; // For Safari
document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera
+
+ this.setState({
+ currentRuleId: this.props.item,
+ isLoading: true,
+ mitreLoading: true,
+ });
+ }
+
+ async componentDidUpdate(prevProps, prevState) {
+ if (prevState.currentRuleId !== this.state.currentRuleId)
+ await this.loadRule()
}
+ async loadRule() {
+ const { currentRuleId, mitreRuleId } = this.state;
+ try {
+ let mitreState = {};
+ const result = await this.resourcesHandler.getResource({
+ params: {
+ rule_ids: currentRuleId,
+ },
+ });
+ const currentRule = result?.data?.affected_items?.length ? result.data.affected_items[0] : {};
+
+ const compliance = this.buildCompliance(currentRule);
+ if (compliance?.mitre?.length && currentRuleId !== mitreRuleId) {
+ mitreState = this.addMitreInformation(compliance.mitre, currentRuleId);
+ } else if (currentRuleId !== mitreRuleId) {
+ mitreState = {
+ mitreLoading: false,
+ mitreRuleId: currentRuleId,
+ mitreIds: [],
+ mitreTactics: [],
+ mitreTechniques: [],
+ }
+ }
+
+ this.setState({
+ currentRuleInfo: currentRule,
+ compliance: compliance,
+ isLoading: false,
+ ...mitreState
+ });
+ } catch (error) {
+ const options = {
+ context: `${WzRuleInfo.name}.handleFileClick`,
+ level: UI_LOGGER_LEVELS.ERROR,
+ severity: UI_ERROR_SEVERITIES.BUSINESS,
+ error: {
+ error: error,
+ message: `Error updating file content: ${error.message || error}`,
+ title: error.name || error,
+ },
+ };
+ getErrorOrchestrator().handleError(options);
+ }
+
+ }
/**
* Build an object with the compliance info about a rule
* @param {Object} ruleInfo
@@ -173,12 +220,9 @@ class WzRuleInfo extends Component {
const badgeList = [];
const fields = ['pci_dss', 'gpg13', 'hipaa', 'gdpr', 'nist_800_53', 'tsc', 'mitre'];
const buildBadge = (field) => {
- const idGenerator = () => {
- return '_' + Math.random().toString(36).substr(2, 9);
- };
return (
-
+
ev.stopPropagation()}
@@ -218,10 +262,13 @@ class WzRuleInfo extends Component {
* Clean the existing filters and sets the new ones and back to the previous section
*/
setNewFiltersAndBack(filters) {
- window.location.href = window.location.href.replace(new RegExp('redirectRule=' + '[^&]*'), '');
+ window.history.pushState("",
+ window.document.title,
+ window.location.href.replace(new RegExp('&redirectRule=' + '[^&]*'), '')
+ );
this.props.cleanFilters();
- this.props.updateFilters(filters);
- this.props.cleanInfo();
+ this.props.onFiltersChange(filters);
+ this.props.closeFlyout();
}
/**
@@ -231,7 +278,7 @@ class WzRuleInfo extends Component {
* @param {String} file
* @param {String} path
*/
- renderInfo(id, level, file, path, groups) {
+ renderInfo(id = '', level = '', file = '', path = '', groups = []) {
return (
@@ -301,13 +348,20 @@ class WzRuleInfo extends Component {
let name = '';
value.forEach((item) => {
- if (item.type === 'cve') name = item.name;
- if (item.type === 'link')
+ if (item.type === 'cve'){
+ name = item.name;
+ }
+ if (item.type === 'link'){
link = (
-
+
{item.name}
);
+ }
});
return (
@@ -340,16 +394,16 @@ class WzRuleInfo extends Component {
* Render a list with the details
* @param {Array} details
*/
- renderDetails(details) {
+ renderDetails(details = {}) {
const detailsToRender = [];
- const capitalize = (str) => str[0].toUpperCase() + str.slice(1);
+
// Exclude group key of details
Object.keys(details)
.filter((key) => key !== 'group')
.forEach((key) => {
detailsToRender.push(
- {capitalize(key)}
+ {key}
{details[key] === '' ? 'true' : this.getFormattedDetails(details[key])}
);
@@ -404,8 +458,9 @@ class WzRuleInfo extends Component {
}
async addMitreInformation(compliance, currentRuleId) {
+ let newMitreState = {};
try {
- this.setState({ mitreLoading: true, mitreRuleId: currentRuleId });
+ Object.assign(newMitreState, { mitreRuleId: currentRuleId });
const mitreName = [];
const mitreIds = [];
const mitreTactics = await Promise.all(
@@ -425,8 +480,7 @@ class WzRuleInfo extends Component {
if (mitreTactics.length) {
let removeDuplicates = (arr) => arr.filter((v, i) => arr.indexOf(v) === i);
const uniqueTactics = removeDuplicates(mitreTactics.flat());
- this.setState({
- mitreLoading: false,
+ Object.assign(newMitreState, {
mitreRuleId: currentRuleId,
mitreIds,
mitreTactics: uniqueTactics,
@@ -434,7 +488,7 @@ class WzRuleInfo extends Component {
});
}
} catch (error) {
- this.setState({ mitreLoading: false });
+ Object.assign(newMitreState, { mitreLoading: false });
const options = {
context: `${WzRuleInfo.name}.addMitreInformation`,
level: UI_LOGGER_LEVELS.ERROR,
@@ -447,6 +501,7 @@ class WzRuleInfo extends Component {
};
getErrorOrchestrator().handleError(options);
}
+ return newMitreState;
}
/**
@@ -458,17 +513,9 @@ class WzRuleInfo extends Component {
this.state && this.state.currentRuleId
? this.state.currentRuleId
: this.props.state.ruleInfo.current;
- if (compliance.mitre && compliance.mitre.length && currentRuleId !== this.state.mitreRuleId) {
- this.addMitreInformation(compliance.mitre, currentRuleId);
- } else if (currentRuleId !== this.state.mitreRuleId) {
- this.setState({
- mitreLoading: false,
- mitreRuleId: currentRuleId,
- mitreIds: [],
- mitreTactics: [],
- mitreTechniques: [],
- });
- }
+
+
+
const listCompliance = [];
if (compliance.mitre) delete compliance.mitre;
const keys = Object.keys(compliance);
@@ -543,11 +590,16 @@ class WzRuleInfo extends Component {
* @param {Number} ruleId
*/
changeBetweenRules(ruleId) {
+ // Prevent reloading the same rule
+ if (this.state.currentRuleId == ruleId) {
+ return;
+ }
+
window.location.href = window.location.href.replace(
new RegExp('redirectRule=' + '[^&]*'),
`redirectRule=${ruleId}`
);
- this.setState({ currentRuleId: ruleId });
+ this.setState({ currentRuleId: ruleId, isLoading: true });
}
/**
@@ -568,72 +620,50 @@ class WzRuleInfo extends Component {
return value;
}
- render() {
- const { ruleInfo, isLoading } = this.props.state;
- const currentRuleId =
- this.state && this.state.currentRuleId ? this.state.currentRuleId : ruleInfo.current;
- const rules = ruleInfo.affected_items;
- const currentRuleArr = rules.filter((r) => {
- return r.id === currentRuleId;
- });
- const currentRuleInfo = currentRuleArr[0];
- const { description, details, filename, relative_dirname, level, id, groups } = currentRuleInfo;
- const compliance = this.buildCompliance(currentRuleInfo);
- const columns = this.columns;
-
- const onClickRow = (item) => {
- return {
- onClick: () => {
- this.changeBetweenRules(item.id);
- },
- };
+ onClickRow = (item) => {
+ return {
+ onClick: () => {
+ this.changeBetweenRules(item.id);
+ },
};
+ };
+
+ render() {
+ const { description, details, filename, relative_dirname, level, id, groups } = this.state.currentRuleInfo;
+ const compliance = this.buildCompliance(this.state.currentRuleInfo);
return (
-
-
-
- {/* Rule description name */}
-
-
-
-
-
- {
- window.location.href = window.location.href.replace(
- new RegExp('redirectRule=' + '[^&]*'),
- ''
- );
- this.props.cleanInfo();
- }}
- />
-
- {
+ <>
+
+
+
+
+
+ {
+ description && (
- }
-
-
-
-
-
- View alerts of this Rule
+ />)
+ }
+
+
+
+
+
+ View alerts of this Rule
-
-
- {/* Cards */}
-
+
+
+
+
+
+
+ {/* Cards */}
{/* General info */}
@@ -646,10 +676,12 @@ class WzRuleInfo extends Component {
}
paddingSize="none"
initialIsOpen={true}
+ isLoading={this.state.isLoading}
+ isLoadingMessage={''}
>
-
+
{this.renderInfo(id, level, filename, relative_dirname, groups)}
-
+
@@ -665,13 +697,15 @@ class WzRuleInfo extends Component {
}
paddingSize="none"
initialIsOpen={true}
+ isLoading={this.state.isLoading}
+ isLoadingMessage={''}
>
- {this.renderDetails(details)}
+ {this.renderDetails(details)}
{/* Compliance */}
- {Object.keys(compliance).length > 0 && (
+ {compliance && Object.keys(compliance).length > 0 && (
-
+
{this.renderCompliance(compliance)}
-
+
@@ -701,50 +737,33 @@ class WzRuleInfo extends Component {
Related rules
}
+ isLoading={this.state.isLoading}
+ isLoadingMessage={''}
paddingSize="none"
initialIsOpen={true}
>
-
+
-
+ {this.state.currentRuleInfo?.filename &&
+
+ }
-
+
-
-
-
-
+
+
+
+ >
);
}
}
-
-const mapStateToProps = (state) => {
- return {
- state: state.rulesetReducers,
- };
-};
-
-const mapDispatchToProps = (dispatch) => {
- return {
- updateFileContent: (content) => dispatch(updateFileContent(content)),
- cleanFileContent: () => dispatch(cleanFileContent()),
- updateFilters: (filters) => dispatch(updateFilters(filters)),
- cleanFilters: () => dispatch(cleanFilters()),
- cleanInfo: () => dispatch(cleanInfo()),
- };
-};
-
-export default connect(mapStateToProps, mapDispatchToProps)(WzRuleInfo);
diff --git a/public/controllers/management/components/management/ruleset/views/ruleset-overview.tsx b/public/controllers/management/components/management/ruleset/views/ruleset-overview.tsx
new file mode 100644
index 0000000000..62908569d2
--- /dev/null
+++ b/public/controllers/management/components/management/ruleset/views/ruleset-overview.tsx
@@ -0,0 +1,69 @@
+import React, { useState } from 'react';
+
+// Eui components
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiPanel,
+ EuiPage,
+ EuiSpacer
+} from '@elastic/eui';
+
+// Wazuh components
+import { withUserAuthorizationPrompt, withGlobalBreadcrumb } from '../../../../../../components/common/hocs';
+import { compose } from 'redux';
+import { resourceDictionary } from '../../common/resources-handler';
+import { SECTION_RULES_NAME, SECTION_RULES_KEY } from '../../common/constants';
+import RulesetTable from '../components/ruleset-table';
+import '../../common/layout-overview.scss';
+import WzRestartClusterManagerCallout from '../../../../../../components/common/restart-cluster-manager-callout';
+
+
+function WzRulesetOverview(props) {
+
+ const [showWarningRestart, setShowWarningRestart] = useState(false);
+
+ const updateRestartManagers = (showWarningRestart) => {
+ setShowWarningRestart(showWarningRestart);
+ }
+
+
+ const { clusterStatus } = props;
+ return
+
+ {showWarningRestart && (
+ <>
+
+ updateRestartManagers(false)}
+ onRestartedError={() => updateRestartManagers(true)}
+ />
+
+ >
+ )}
+
+
+
+ updateRestartManagers(showWarningRestart)}
+ />
+
+
+
+ ;
+}
+
+export default compose(
+ withGlobalBreadcrumb(props => {
+ return [
+ { text: '' },
+ { text: 'Management', href: '#/manager' },
+ { text: SECTION_RULES_NAME}
+ ];
+ }),
+ withUserAuthorizationPrompt((props) => [
+ { action: `${SECTION_RULES_KEY}:read`, resource: resourceDictionary[SECTION_RULES_KEY].permissionResource('*') }
+ ])
+)(WzRulesetOverview);
diff --git a/public/controllers/management/components/management/status/__snapshots__/status-main.test.tsx.snap b/public/controllers/management/components/management/status/__snapshots__/status-main.test.tsx.snap
index 32ba949fba..076b2ebc55 100644
--- a/public/controllers/management/components/management/status/__snapshots__/status-main.test.tsx.snap
+++ b/public/controllers/management/components/management/status/__snapshots__/status-main.test.tsx.snap
@@ -6,11 +6,11 @@ exports[`Status component renders correctly to match the snapshot 1`] = `
@@ -54,6 +54,7 @@ exports[`Status component renders correctly to match the snapshot 1`] = `
>
diff --git a/public/controllers/management/components/management/status/actions-buttons-main.js b/public/controllers/management/components/management/status/actions-buttons-main.js
index ce95c92052..9ba6b42efc 100644
--- a/public/controllers/management/components/management/status/actions-buttons-main.js
+++ b/public/controllers/management/components/management/status/actions-buttons-main.js
@@ -132,7 +132,7 @@ class WzStatusActionButtons extends Component {
this.props.updateLoadingStatus(true);
this.props.updateSelectedNode(node);
- const [agentsCount, agentsCountByManagerNodes] = (await Promise.all([
+ const [{connection: agentsCount}, agentsCountByManagerNodes] = (await Promise.all([
this.statusHandler.agentsSummary(),
this.statusHandler.clusterAgentsCount()
])).map(response => response?.data?.data);
diff --git a/public/controllers/management/components/management/status/status-agent-info.js b/public/controllers/management/components/management/status/status-agent-info.js
index b3d8f12100..903573c846 100644
--- a/public/controllers/management/components/management/status/status-agent-info.js
+++ b/public/controllers/management/components/management/status/status-agent-info.js
@@ -80,7 +80,7 @@ export class WzStatusAgentInfo extends Component {
{agentStatusLabelByAgentStatus(agentInfo.status)}
- IP Address
+ IP address
{agentInfo.ip}
diff --git a/public/controllers/management/components/management/status/status-overview.js b/public/controllers/management/components/management/status/status-overview.js
index a2f20feb3d..6818945806 100644
--- a/public/controllers/management/components/management/status/status-overview.js
+++ b/public/controllers/management/components/management/status/status-overview.js
@@ -94,7 +94,7 @@ export class WzStatusOverview extends Component {
this.props.updateLoadingStatus(true);
- const [agentsCount, clusterStatus, managerInfo, agentsCountByManagerNodes] = (await Promise.all([
+ const [{connection: agentsCount, configuration}, clusterStatus, managerInfo, agentsCountByManagerNodes] = (await Promise.all([
this.statusHandler.agentsSummary(),
this.statusHandler.clusterStatus(),
this.statusHandler.managerInfo(),
@@ -104,6 +104,7 @@ export class WzStatusOverview extends Component {
this.props.updateStats({
agentsCountByManagerNodes: agentsCountByManagerNodes.nodes,
agentsCount,
+ agentsSynced: configuration.total ? ((configuration.synced / configuration.total) * 100).toFixed(2) : 0,
agentsCoverage: agentsCount.total ? ((agentsCount.active / agentsCount.total) * 100).toFixed(2) : 0,
});
diff --git a/public/controllers/management/components/management/status/status-stats.js b/public/controllers/management/components/management/status/status-stats.js
index ddfe719192..1ac67027e1 100644
--- a/public/controllers/management/components/management/status/status-stats.js
+++ b/public/controllers/management/components/management/status/status-stats.js
@@ -44,8 +44,16 @@ export class WzStatusStats extends Component {
this._isMounted = false;
}
- render() {
+ getTitle(status) {
const { stats } = this.props.state;
+ const metric = {
+ [status]: stats?.agentsCount?.[status],
+ coverage: `${stats?.agentsCoverage}%`,
+ };
+ return metric[status];
+ }
+
+ render() {
return (
@@ -54,7 +62,7 @@ export class WzStatusStats extends Component {
{this.agentStatus.map(({color, description, status}) => (
{
const file = this.state.files[item].name;
return file.substr(file.length - 4) !== '.xml';
@@ -230,7 +233,7 @@ export class UploadFiles extends Component {
))}
@@ -239,11 +242,6 @@ export class UploadFiles extends Component {
);
}
- /**
- * Format Bytes size to largest unit
- */
- formatBytes(a, b = 2) { if (0 === a) return "0 Bytes"; const c = 0 > b ? 0 : b, d = Math.floor(Math.log(a) / Math.log(1024)); return parseFloat((a / Math.pow(1024, d)).toFixed(c)) + " " + ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"][d] }
-
/**
* Renders the errors when trying to upload files
*/
diff --git a/public/controllers/management/management.js b/public/controllers/management/management.js
index 3629b75f10..59c9dab970 100644
--- a/public/controllers/management/management.js
+++ b/public/controllers/management/management.js
@@ -16,9 +16,9 @@ import { WzRequest } from '../../react-services/wz-request';
import { ErrorHandler } from '../../react-services/error-handler';
import { ShareAgent } from '../../factories/share-agent';
import {
- RulesetHandler,
- RulesetResources,
-} from './components/management/ruleset/utils/ruleset-handler';
+ ResourcesHandler,
+ ResourcesConstants
+} from './components/management/common/resources-handler';
import { UI_ERROR_SEVERITIES } from '../../react-services/error-orchestrator/types';
import { UI_LOGGER_LEVELS } from '../../../common/constants';
@@ -47,7 +47,7 @@ export class ManagementController {
this.currentGroup = false;
this.logtestOpened = false;
this.uploadOpened = false;
- this.rulesetTab = RulesetResources.RULES;
+ this.rulesetTab = ResourcesConstants.RULES;
this.$scope.$on('setCurrentGroup', (ev, params) => {
this.currentGroup = (params || {}).currentGroup || false;
@@ -490,12 +490,12 @@ export class ManagementController {
try {
this.errors = false;
this.results = [];
- const rulesetHandler = new RulesetHandler(resource);
+ const resourcesHandler = new ResourcesHandler(resource);
for (let idx in files) {
const { file, content } = files[idx];
try {
- await rulesetHandler.updateFile(file, content, true); // True does not overwrite the file
+ await resourcesHandler.updateFile(file, content, true); // True does not overwrite the file
this.results.push({
index: idx,
uploaded: true,
diff --git a/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap b/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap
index ac13fef1bc..9ea86c2c29 100644
--- a/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap
+++ b/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap
@@ -6,7 +6,7 @@ exports[`Stats component renders correctly to match the snapshot 1`] = `
getAgentFilterValues('os.platform', value, { q: 'id!=000'})},
- { type: 'q', label: 'ip', description: 'Filter by agent IP', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('ip', value, { q: 'id!=000'})},
+ { type: 'q', label: 'os.platform', description: 'Filter by operating system platform', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('os.platform', value, { q: 'id!=000'})},
+ { type: 'q', label: 'ip', description: 'Filter by agent IP address', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('ip', value, { q: 'id!=000'})},
{ type: 'q', label: 'name', description: 'Filter by agent name', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('name', value, { q: 'id!=000'})},
{ type: 'q', label: 'id', description: 'Filter by agent id', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('id', value, { q: 'id!=000'})},
{ type: 'q', label: 'group', description: 'Filter by agent group', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('group', value, { q: 'id!=000'})},
diff --git a/public/controllers/overview/components/overview-actions/overview-actions.js b/public/controllers/overview/components/overview-actions/overview-actions.js
index 4bd84ffb22..6d7d04f1e6 100644
--- a/public/controllers/overview/components/overview-actions/overview-actions.js
+++ b/public/controllers/overview/components/overview-actions/overview-actions.js
@@ -27,9 +27,9 @@ import {
import { WzButton } from '../../../../components/common/buttons';
import './agents-selector.scss';
import { AgentSelectionTable } from './agents-selection-table';
-import { WAZUH_ALERTS_PATTERN } from '../../../../../common/constants';
import { AppState } from '../../../../react-services/app-state';
import { getDataPlugin } from '../../../../kibana-services';
+import { getSettingDefaultValue } from '../../../../../common/services/settings';
class OverviewActions extends Component {
constructor(props) {
@@ -110,7 +110,7 @@ class OverviewActions extends Component {
negate: false,
params: { query: agentIdList[0] },
type: 'phrase',
- index: AppState.getCurrentPattern() || WAZUH_ALERTS_PATTERN,
+ index: AppState.getCurrentPattern() || getSettingDefaultValue('pattern'),
},
query: {
match: {
diff --git a/public/controllers/overview/components/select-agent.js b/public/controllers/overview/components/select-agent.js
index cccabf316a..3dfafb9af6 100644
--- a/public/controllers/overview/components/select-agent.js
+++ b/public/controllers/overview/components/select-agent.js
@@ -170,7 +170,7 @@ export const SelectAgent = withErrorBoundary (class SelectAgent extends Componen
},
{
field: 'ip',
- name: 'IP',
+ name: 'IP address',
truncateText: true,
sortable: true
},
diff --git a/public/controllers/overview/overview.js b/public/controllers/overview/overview.js
index abd4dc235e..5404d50e83 100644
--- a/public/controllers/overview/overview.js
+++ b/public/controllers/overview/overview.js
@@ -22,10 +22,11 @@ import { updateCurrentTab, updateCurrentAgentData } from '../../redux/actions/ap
import { VisFactoryHandler } from '../../react-services/vis-factory-handler';
import { RawVisualizations } from '../../factories/raw-visualizations';
import store from '../../redux/store';
-import { UI_LOGGER_LEVELS, WAZUH_ALERTS_PATTERN } from '../../../common/constants';
+import { UI_LOGGER_LEVELS } from '../../../common/constants';
import { getDataPlugin } from '../../kibana-services';
import { UI_ERROR_SEVERITIES } from '../../react-services/error-orchestrator/types';
import { getErrorOrchestrator } from '../../react-services/common-services';
+import { getSettingDefaultValue } from '../../../common/services/settings';
export class OverviewController {
/**
@@ -329,7 +330,7 @@ export class OverviewController {
*/
async getSummary() {
try {
- const {data: { data }} = await WzRequest.apiReq('GET', '/agents/summary/status', {});
+ const {data: { data: {connection: data} }} = await WzRequest.apiReq('GET', '/agents/summary/status', {});
this.agentsCount = data;
this.welcomeCardsProps.agentsCountTotal = data.total;
this.agentsCoverity = data.total ? (data.active / data.total) * 100 : 0;
@@ -358,7 +359,7 @@ export class OverviewController {
* @param {*} id
*/
addMitrefilter(id) {
- const filter = `{"meta":{ "index": ${AppState.getCurrentPattern() || WAZUH_ALERTS_PATTERN}},"query":{"match":{"rule.mitre.id":{"query":"${id}","type":"phrase"}}}}`;
+ const filter = `{"meta":{ "index": ${AppState.getCurrentPattern() || getSettingDefaultValue('pattern')}},"query":{"match":{"rule.mitre.id":{"query":"${id}","type":"phrase"}}}}`;
this.$rootScope.$emit('addNewKibanaFilter', { filter: JSON.parse(filter) });
}
diff --git a/public/controllers/settings/settings.js b/public/controllers/settings/settings.js
index 403cca6e67..f30a9fb442 100644
--- a/public/controllers/settings/settings.js
+++ b/public/controllers/settings/settings.js
@@ -22,7 +22,7 @@ import { formatUIDate } from '../../react-services/time-service';
import store from '../../redux/store';
import { updateGlobalBreadcrumb } from '../../redux/actions/globalBreadcrumbActions';
import { updateSelectedSettingsSection } from '../../redux/actions/appStateActions';
-import { UI_LOGGER_LEVELS, PLUGIN_PLATFORM_NAME } from '../../../common/constants';
+import { UI_LOGGER_LEVELS, PLUGIN_APP_NAME } from '../../../common/constants';
import { UI_ERROR_SEVERITIES } from '../../react-services/error-orchestrator/types';
import { getErrorOrchestrator } from '../../react-services/common-services';
import { getAssetURL } from '../../utils/assets';
@@ -38,7 +38,7 @@ export class SettingsController {
*/
constructor($scope, $window, $location, errorHandler) {
this.pluginPlatformVersion = (pluginPlatform || {}).version || false;
- this.pluginPlatformName = PLUGIN_PLATFORM_NAME;
+ this.pluginAppName = PLUGIN_APP_NAME;
this.$scope = $scope;
this.$window = $window;
this.$location = $location;
@@ -452,7 +452,7 @@ export class SettingsController {
{
date: new Date(),
level: 'error',
- message: 'Error when loading Wazuh app logs'
+ message: 'Error when loading logs'
}
];
}
@@ -539,7 +539,7 @@ export class SettingsController {
};
}
throw {
- message: `Some of the API entries are not reachable. You can still use the Wazuh APP but please, review your hosts configuration.`,
+ message: `Some of the API entries are not reachable. You can still use the ${PLUGIN_APP_NAME} but please, review your hosts configuration.`,
type: 'warning',
closedEnabled: true
};
diff --git a/public/factories/wazuh-security.js b/public/factories/wazuh-security.js
index ca97b70dfc..9d61ca5e41 100644
--- a/public/factories/wazuh-security.js
+++ b/public/factories/wazuh-security.js
@@ -11,9 +11,8 @@
* Find more information about this on the LICENSE file.
*/
-import { WzSecurityXpack } from '../react-services/wz-security-xpack';
-import { WzSecurityOpendistro } from '../react-services/wz-security-opendistro';
-import { WAZUH_SECURITY_PLUGIN_XPACK_SECURITY, WAZUH_SECURITY_PLUGIN_OPEN_DISTRO_FOR_ELASTICSEARCH } from '../../common/constants';
+import { WzSecurityOpenSearchDashboardsSecurity } from '../react-services/wz-security-opensearch-dashboards-security';
+import { WAZUH_SECURITY_PLUGIN_OPENSEARCH_DASHBOARDS_SECURITY } from '../../common/constants';
import store from '../redux/store';
@@ -26,10 +25,8 @@ export class WazuhSecurity {
return WazuhSecurity.instance;
}
const platform = store.getState().appStateReducers.currentPlatform;
- if(platform === WAZUH_SECURITY_PLUGIN_XPACK_SECURITY){
- this.security = WzSecurityXpack;
- }else if(platform === WAZUH_SECURITY_PLUGIN_OPEN_DISTRO_FOR_ELASTICSEARCH){
- this.security = WzSecurityOpendistro;
+ if(platform === WAZUH_SECURITY_PLUGIN_OPENSEARCH_DASHBOARDS_SECURITY){
+ this.security = WzSecurityOpenSearchDashboardsSecurity;
}else{
this.security = false;
}
diff --git a/public/get_inner_angular.ts b/public/get_inner_angular.ts
index c59956ff8e..a01cf5a7f0 100644
--- a/public/get_inner_angular.ts
+++ b/public/get_inner_angular.ts
@@ -23,9 +23,9 @@
import angular from 'angular';
// required for `ngSanitize` angular module
import 'angular-sanitize';
-import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular';
-import { CoreStart, PluginInitializerContext } from 'kibana/public';
-import { Storage } from '../../../src/plugins/kibana_utils/public';
+import { i18nDirective, i18nFilter, I18nProvider } from '@osd/i18n/angular';
+import { CoreStart, PluginInitializerContext } from 'opensearch_dashboards/public';
+import { Storage } from '../../../src/plugins/opensearch_dashboards_utils/public';
import { NavigationPublicPluginStart as NavigationStart } from '../../../src/plugins/navigation/public';
import {
initAngularBootstrap,
@@ -36,7 +36,7 @@ import {
watchMultiDecorator,
createTopNavDirective,
createTopNavHelper,
-} from '../../../src/plugins/kibana_legacy/public';
+} from '../../../src/plugins/opensearch_dashboards_legacy/public';
import { AppPluginStartDependencies } from './types';
import { getScopedHistory, setDiscoverModule } from './kibana-services';
import { createDiscoverLegacyDirective } from './kibana-integrations/discover/application/components/create_discover_legacy_directive';
@@ -87,7 +87,6 @@ export function initializeInnerAngularModule(name = 'app/wazuh', navigation: Nav
'ngRoute',
'react',
'ngMaterial',
- 'chart.js',
'ui.bootstrap',
'app/discover',
])
diff --git a/public/index.ts b/public/index.ts
index 704a3620b9..1cff187921 100644
--- a/public/index.ts
+++ b/public/index.ts
@@ -1,4 +1,4 @@
-import { PluginInitializer, PluginInitializerContext } from 'kibana/public';
+import { PluginInitializer, PluginInitializerContext } from 'opensearch_dashboards/public';
import { WazuhPlugin } from './plugin';
import { WazuhSetup, WazuhSetupPlugins, WazuhStart, WazuhStartPlugins } from './types';
diff --git a/public/kibana-integrations/discover/application/angular/directives/histogram.tsx b/public/kibana-integrations/discover/application/angular/directives/histogram.tsx
index ffa15feae1..00e697a298 100644
--- a/public/kibana-integrations/discover/application/angular/directives/histogram.tsx
+++ b/public/kibana-integrations/discover/application/angular/directives/histogram.tsx
@@ -42,8 +42,8 @@ import {
Theme,
} from '@elastic/charts';
-import { i18n } from '@kbn/i18n';
-import { IUiSettingsClient } from 'kibana/public';
+import { i18n } from '@osd/i18n';
+import { IUiSettingsClient } from 'opensearch_dashboards/public';
import { EuiChartThemeType } from '@elastic/eui/dist/eui_charts_theme';
import { Subscription, combineLatest } from 'rxjs';
import { getServices } from '../../../kibana_services';
@@ -220,7 +220,7 @@ export class DiscoverHistogram extends Component
\s+
diff --git a/public/kibana-integrations/discover/application/angular/doc_table/doc_table.ts b/public/kibana-integrations/discover/application/angular/doc_table/doc_table.ts
index 94bd8e83a1..fec5ab9a22 100644
--- a/public/kibana-integrations/discover/application/angular/doc_table/doc_table.ts
+++ b/public/kibana-integrations/discover/application/angular/doc_table/doc_table.ts
@@ -18,7 +18,7 @@
*/
import html from './doc_table.html';
-import { dispatchRenderComplete } from '../../../../../../../../src/plugins/kibana_utils/public';
+import { dispatchRenderComplete } from '../../../../../../../../src/plugins/opensearch_dashboards_utils/public';
import { SAMPLE_SIZE_SETTING } from '../../../common';
// @ts-ignore
import { getLimitedSearchResultsMessage } from './doc_table_strings';
diff --git a/public/kibana-integrations/discover/application/angular/doc_table/doc_table_strings.js b/public/kibana-integrations/discover/application/angular/doc_table/doc_table_strings.js
index f1d65207c7..f637bcc735 100644
--- a/public/kibana-integrations/discover/application/angular/doc_table/doc_table_strings.js
+++ b/public/kibana-integrations/discover/application/angular/doc_table/doc_table_strings.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
/**
* A message letting the user know the results that have been retrieved is limited
diff --git a/public/kibana-integrations/discover/application/angular/helpers/point_series.ts b/public/kibana-integrations/discover/application/angular/helpers/point_series.ts
index 4c280bf43e..4751723b70 100644
--- a/public/kibana-integrations/discover/application/angular/helpers/point_series.ts
+++ b/public/kibana-integrations/discover/application/angular/helpers/point_series.ts
@@ -40,8 +40,8 @@ export interface Table {
interface HistogramParams {
date: true;
interval: Duration;
- intervalESValue: number;
- intervalESUnit: Unit;
+ intervalOpenSearchValue: number;
+ intervalOpenSearchUnit: Unit;
format: string;
bounds: {
min: Moment;
@@ -61,8 +61,8 @@ export interface Dimensions {
interface Ordered {
date: true;
interval: Duration;
- intervalESUnit: string;
- intervalESValue: number;
+ intervalOpenSearchUnit: string;
+ intervalOpenSearchValue: number;
min: Moment;
max: Moment;
}
@@ -88,12 +88,12 @@ export const buildPointSeriesData = (table: Table, dimensions: Dimensions) => {
chart.xAxisFormat = x.format;
chart.xAxisLabel = table.columns[x.accessor].name;
- const { intervalESUnit, intervalESValue, interval, bounds } = x.params;
+ const { intervalOpenSearchUnit, intervalOpenSearchValue, interval, bounds } = x.params;
chart.ordered = {
date: true,
interval,
- intervalESUnit,
- intervalESValue,
+ intervalOpenSearchUnit,
+ intervalOpenSearchValue,
min: bounds.min,
max: bounds.max,
};
diff --git a/public/kibana-integrations/discover/application/components/context_error_message/context_error_message.tsx b/public/kibana-integrations/discover/application/components/context_error_message/context_error_message.tsx
index f73496c2ee..8b4769b2f8 100644
--- a/public/kibana-integrations/discover/application/components/context_error_message/context_error_message.tsx
+++ b/public/kibana-integrations/discover/application/components/context_error_message/context_error_message.tsx
@@ -18,7 +18,7 @@
*/
import React from 'react';
import { EuiCallOut, EuiText } from '@elastic/eui';
-import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
+import { FormattedMessage, I18nProvider } from '@osd/i18n/react';
// @ts-ignore
import { FAILURE_REASONS, LOADING_STATUS } from '../../angular/context/query';
diff --git a/public/kibana-integrations/discover/application/components/discover_legacy.tsx b/public/kibana-integrations/discover/application/components/discover_legacy.tsx
index d8a12118c2..53efccde48 100644
--- a/public/kibana-integrations/discover/application/components/discover_legacy.tsx
+++ b/public/kibana-integrations/discover/application/components/discover_legacy.tsx
@@ -19,9 +19,9 @@
import React, { useState, useCallback, useEffect } from 'react';
import classNames from 'classnames';
import { EuiButtonEmpty, EuiButtonIcon } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
-import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
-import { IUiSettingsClient, MountPoint } from 'kibana/public';
+import { i18n } from '@osd/i18n';
+import { FormattedMessage, I18nProvider } from '@osd/i18n/react';
+import { IUiSettingsClient, MountPoint } from 'opensearch_dashboards/public';
import { HitsCounter } from './hits_counter';
import { TimechartHeader } from './timechart_header';
import { DiscoverSidebar } from './sidebar';
@@ -87,7 +87,7 @@ export interface DiscoverLegacyProps {
updateQuery: (payload: { dateRange: TimeRange; query?: Query }, isUpdate?: boolean) => void;
updateSavedQueryId: (savedQueryId?: string) => void;
vis?: Vis;
- showMain?: Boolean;
+ showMain?: Boolean;
}
export function DiscoverLegacy({
diff --git a/public/kibana-integrations/discover/application/components/doc/doc.tsx b/public/kibana-integrations/discover/application/components/doc/doc.tsx
index 2623b5a270..19fc597a5e 100644
--- a/public/kibana-integrations/discover/application/components/doc/doc.tsx
+++ b/public/kibana-integrations/discover/application/components/doc/doc.tsx
@@ -17,7 +17,7 @@
* under the License.
*/
import React from 'react';
-import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
+import { FormattedMessage, I18nProvider } from '@osd/i18n/react';
import { EuiCallOut, EuiLink, EuiLoadingSpinner, EuiPageContent } from '@elastic/eui';
import { IndexPatternsContract } from 'src/plugins/data/public';
import { ElasticRequestState, useEsDocSearch } from './use_es_doc_search';
diff --git a/public/kibana-integrations/discover/application/components/doc_viewer/doc_viewer_render_error.tsx b/public/kibana-integrations/discover/application/components/doc_viewer/doc_viewer_render_error.tsx
index 2ebdc8c6f8..c0d4884752 100644
--- a/public/kibana-integrations/discover/application/components/doc_viewer/doc_viewer_render_error.tsx
+++ b/public/kibana-integrations/discover/application/components/doc_viewer/doc_viewer_render_error.tsx
@@ -18,7 +18,7 @@
*/
import React from 'react';
import { EuiCallOut, EuiCodeBlock } from '@elastic/eui';
-import { formatMsg, formatStack } from '../../../../../../../../src/plugins/kibana_legacy/public';
+import { formatMsg, formatStack } from '../../../../../../../../src/plugins/opensearch_dashboards_legacy/public';
interface Props {
error: Error | string;
diff --git a/public/kibana-integrations/discover/application/components/doc_viewer/doc_viewer_tab.tsx b/public/kibana-integrations/discover/application/components/doc_viewer/doc_viewer_tab.tsx
index 2dfee3487a..9337eee40f 100644
--- a/public/kibana-integrations/discover/application/components/doc_viewer/doc_viewer_tab.tsx
+++ b/public/kibana-integrations/discover/application/components/doc_viewer/doc_viewer_tab.tsx
@@ -17,7 +17,7 @@
* under the License.
*/
import React from 'react';
-import { I18nProvider } from '@kbn/i18n/react';
+import { I18nProvider } from '@osd/i18n/react';
import { DocViewRenderTab } from './doc_viewer_render_tab';
import { DocViewerError } from './doc_viewer_render_error';
import { DocViewRenderFn, DocViewRenderProps } from '../../doc_views/doc_views_types';
diff --git a/public/kibana-integrations/discover/application/components/field_name/field_name.tsx b/public/kibana-integrations/discover/application/components/field_name/field_name.tsx
index 3b4146295b..1edddf60d5 100644
--- a/public/kibana-integrations/discover/application/components/field_name/field_name.tsx
+++ b/public/kibana-integrations/discover/application/components/field_name/field_name.tsx
@@ -19,7 +19,7 @@
import React from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui';
-import { FieldIcon, FieldIconProps } from '../../../../../../../../src/plugins/kibana_react/public';
+import { FieldIcon, FieldIconProps } from '../../../../../../../../src/plugins/opensearch_dashboards_react/public';
import { shortenDottedString } from '../../helpers';
import { getFieldTypeName } from './field_type_name';
diff --git a/public/kibana-integrations/discover/application/components/field_name/field_type_name.ts b/public/kibana-integrations/discover/application/components/field_name/field_type_name.ts
index a67c20fc4f..a18c5a6299 100644
--- a/public/kibana-integrations/discover/application/components/field_name/field_type_name.ts
+++ b/public/kibana-integrations/discover/application/components/field_name/field_type_name.ts
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
export function getFieldTypeName(type: string) {
switch (type) {
diff --git a/public/kibana-integrations/discover/application/components/help_menu/help_menu_util.js b/public/kibana-integrations/discover/application/components/help_menu/help_menu_util.js
index 03ab44966f..41df593a25 100644
--- a/public/kibana-integrations/discover/application/components/help_menu/help_menu_util.js
+++ b/public/kibana-integrations/discover/application/components/help_menu/help_menu_util.js
@@ -17,7 +17,7 @@
* under the License.
*/
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
import { getServices } from '../../../kibana_services';
const { docLinks } = getServices();
diff --git a/public/kibana-integrations/discover/application/components/hits_counter/hits_counter.tsx b/public/kibana-integrations/discover/application/components/hits_counter/hits_counter.tsx
index 1d2cd12877..b266c25b75 100644
--- a/public/kibana-integrations/discover/application/components/hits_counter/hits_counter.tsx
+++ b/public/kibana-integrations/discover/application/components/hits_counter/hits_counter.tsx
@@ -18,8 +18,8 @@
*/
import React from 'react';
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
-import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
-import { i18n } from '@kbn/i18n';
+import { FormattedMessage, I18nProvider } from '@osd/i18n/react';
+import { i18n } from '@osd/i18n';
import { formatNumWithCommas } from '../../helpers';
export interface HitsCounterProps {
diff --git a/public/kibana-integrations/discover/application/components/json_code_block/json_code_block.tsx b/public/kibana-integrations/discover/application/components/json_code_block/json_code_block.tsx
index 9297ab0dfc..87b8ba139e 100644
--- a/public/kibana-integrations/discover/application/components/json_code_block/json_code_block.tsx
+++ b/public/kibana-integrations/discover/application/components/json_code_block/json_code_block.tsx
@@ -18,7 +18,7 @@
*/
import React from 'react';
import { EuiCodeBlock } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
import { DocViewRenderProps } from '../../doc_views/doc_views_types';
export function JsonCodeBlock({ hit }: DocViewRenderProps) {
diff --git a/public/kibana-integrations/discover/application/components/loading_spinner/loading_spinner.tsx b/public/kibana-integrations/discover/application/components/loading_spinner/loading_spinner.tsx
index 4e1754638d..d5795bab55 100644
--- a/public/kibana-integrations/discover/application/components/loading_spinner/loading_spinner.tsx
+++ b/public/kibana-integrations/discover/application/components/loading_spinner/loading_spinner.tsx
@@ -18,7 +18,7 @@
*/
import React from 'react';
import { EuiLoadingSpinner, EuiTitle, EuiSpacer } from '@elastic/eui';
-import { FormattedMessage } from '@kbn/i18n/react';
+import { FormattedMessage } from '@osd/i18n/react';
export function LoadingSpinner() {
return (
diff --git a/public/kibana-integrations/discover/application/components/sidebar/change_indexpattern.tsx b/public/kibana-integrations/discover/application/components/sidebar/change_indexpattern.tsx
index 4a539b618f..60bb13a437 100644
--- a/public/kibana-integrations/discover/application/components/sidebar/change_indexpattern.tsx
+++ b/public/kibana-integrations/discover/application/components/sidebar/change_indexpattern.tsx
@@ -17,7 +17,7 @@
* under the License.
*/
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
import React, { useState } from 'react';
import {
EuiButtonEmpty,
diff --git a/public/kibana-integrations/discover/application/components/sidebar/discover_field.tsx b/public/kibana-integrations/discover/application/components/sidebar/discover_field.tsx
index 8e36a096a8..309f074399 100644
--- a/public/kibana-integrations/discover/application/components/sidebar/discover_field.tsx
+++ b/public/kibana-integrations/discover/application/components/sidebar/discover_field.tsx
@@ -18,9 +18,9 @@
*/
import React, { useState } from 'react';
import { EuiPopover, EuiPopoverTitle, EuiButtonIcon, EuiToolTip } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
import { DiscoverFieldDetails } from './discover_field_details';
-import { FieldIcon, FieldButton } from '../../../../../../../../src/plugins/kibana_react/public';
+import { FieldIcon, FieldButton } from '../../../../../../../../src/plugins/opensearch_dashboards_react/public';
import { FieldDetails } from './types';
import { IndexPatternField, IndexPattern } from '../../../../../../../../src/plugins/data/public';
import { shortenDottedString } from '../../helpers';
diff --git a/public/kibana-integrations/discover/application/components/sidebar/discover_field_bucket.tsx b/public/kibana-integrations/discover/application/components/sidebar/discover_field_bucket.tsx
index 18539cde0f..70cc730aa2 100644
--- a/public/kibana-integrations/discover/application/components/sidebar/discover_field_bucket.tsx
+++ b/public/kibana-integrations/discover/application/components/sidebar/discover_field_bucket.tsx
@@ -18,7 +18,7 @@
*/
import React from 'react';
import { EuiText, EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
import { StringFieldProgressBar } from './string_progress_bar';
import { Bucket } from './types';
import { IndexPatternField } from '../../../../../../../../src/plugins/data/public';
diff --git a/public/kibana-integrations/discover/application/components/sidebar/discover_field_details.tsx b/public/kibana-integrations/discover/application/components/sidebar/discover_field_details.tsx
index 7d4aa5e227..dc43205c3a 100644
--- a/public/kibana-integrations/discover/application/components/sidebar/discover_field_details.tsx
+++ b/public/kibana-integrations/discover/application/components/sidebar/discover_field_details.tsx
@@ -18,7 +18,7 @@
*/
import React, { useState, useEffect } from 'react';
import { EuiLink, EuiIconTip, EuiText, EuiPopoverFooter, EuiButton, EuiSpacer } from '@elastic/eui';
-import { FormattedMessage } from '@kbn/i18n/react';
+import { FormattedMessage } from '@osd/i18n/react';
import { DiscoverFieldBucket } from './discover_field_bucket';
import { getWarnings } from './lib/get_warnings';
import {
diff --git a/public/kibana-integrations/discover/application/components/sidebar/discover_field_search.tsx b/public/kibana-integrations/discover/application/components/sidebar/discover_field_search.tsx
index 99dad418c0..07ef36dc3a 100644
--- a/public/kibana-integrations/discover/application/components/sidebar/discover_field_search.tsx
+++ b/public/kibana-integrations/discover/application/components/sidebar/discover_field_search.tsx
@@ -17,7 +17,7 @@
* under the License.
*/
import React, { OptionHTMLAttributes, ReactNode, useState } from 'react';
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
import {
EuiFacetButton,
EuiFieldSearch,
@@ -35,7 +35,7 @@ import {
EuiButtonGroup,
EuiOutsideClickDetector,
} from '@elastic/eui';
-import { FormattedMessage } from '@kbn/i18n/react';
+import { FormattedMessage } from '@osd/i18n/react';
export interface State {
searchable: string;
diff --git a/public/kibana-integrations/discover/application/components/sidebar/discover_index_pattern.tsx b/public/kibana-integrations/discover/application/components/sidebar/discover_index_pattern.tsx
index 3acdcb1e92..f4200c3ad1 100644
--- a/public/kibana-integrations/discover/application/components/sidebar/discover_index_pattern.tsx
+++ b/public/kibana-integrations/discover/application/components/sidebar/discover_index_pattern.tsx
@@ -17,9 +17,9 @@
* under the License.
*/
import React, { useState, useEffect } from 'react';
-import { SavedObject } from 'kibana/public';
+import { SavedObject } from 'opensearch_dashboards/public';
import { IIndexPattern, IndexPatternAttributes } from 'src/plugins/data/public';
-import { I18nProvider } from '@kbn/i18n/react';
+import { I18nProvider } from '@osd/i18n/react';
import { IndexPatternRef } from './types';
import { ChangeIndexPattern } from './change_indexpattern';
diff --git a/public/kibana-integrations/discover/application/components/sidebar/discover_index_pattern_title.tsx b/public/kibana-integrations/discover/application/components/sidebar/discover_index_pattern_title.tsx
index b57b6887e9..c4e9258bd0 100644
--- a/public/kibana-integrations/discover/application/components/sidebar/discover_index_pattern_title.tsx
+++ b/public/kibana-integrations/discover/application/components/sidebar/discover_index_pattern_title.tsx
@@ -19,8 +19,8 @@
import React from 'react';
import { EuiToolTip, EuiFlexItem, EuiFlexGroup, EuiTitle, EuiButtonEmpty } from '@elastic/eui';
-import { FormattedMessage } from '@kbn/i18n/react';
-import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@osd/i18n/react';
+import { i18n } from '@osd/i18n';
export interface DiscoverIndexPatternTitleProps {
/**
* determines whether the change link is displayed
diff --git a/public/kibana-integrations/discover/application/components/sidebar/discover_sidebar.tsx b/public/kibana-integrations/discover/application/components/sidebar/discover_sidebar.tsx
index 1359256522..715ee623db 100644
--- a/public/kibana-integrations/discover/application/components/sidebar/discover_sidebar.tsx
+++ b/public/kibana-integrations/discover/application/components/sidebar/discover_sidebar.tsx
@@ -18,10 +18,10 @@
*/
import './discover_sidebar.scss';
import React, { useCallback, useEffect, useState, useMemo } from 'react';
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
import { EuiButtonIcon, EuiTitle, EuiSpacer } from '@elastic/eui';
import { sortBy } from 'lodash';
-import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
+import { FormattedMessage, I18nProvider } from '@osd/i18n/react';
import { DiscoverField } from './discover_field';
import { DiscoverIndexPattern } from './discover_index_pattern';
import { DiscoverFieldSearch } from './discover_field_search';
diff --git a/public/kibana-integrations/discover/application/components/sidebar/lib/field_calculator.js b/public/kibana-integrations/discover/application/components/sidebar/lib/field_calculator.js
index 0ee279ac5b..80a8a4e846 100644
--- a/public/kibana-integrations/discover/application/components/sidebar/lib/field_calculator.js
+++ b/public/kibana-integrations/discover/application/components/sidebar/lib/field_calculator.js
@@ -18,7 +18,7 @@
*/
import _ from 'lodash';
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
function getFieldValues(hits, field, indexPattern) {
const name = field.name;
diff --git a/public/kibana-integrations/discover/application/components/sidebar/lib/get_field_type_name.ts b/public/kibana-integrations/discover/application/components/sidebar/lib/get_field_type_name.ts
index a67c20fc4f..a18c5a6299 100644
--- a/public/kibana-integrations/discover/application/components/sidebar/lib/get_field_type_name.ts
+++ b/public/kibana-integrations/discover/application/components/sidebar/lib/get_field_type_name.ts
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
export function getFieldTypeName(type: string) {
switch (type) {
diff --git a/public/kibana-integrations/discover/application/components/sidebar/lib/get_warnings.ts b/public/kibana-integrations/discover/application/components/sidebar/lib/get_warnings.ts
index fa2336f784..8bcba037d5 100644
--- a/public/kibana-integrations/discover/application/components/sidebar/lib/get_warnings.ts
+++ b/public/kibana-integrations/discover/application/components/sidebar/lib/get_warnings.ts
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
import { IndexPatternField } from '../../../../../../../../../src/plugins/data/public';
export function getWarnings(field: IndexPatternField) {
diff --git a/public/kibana-integrations/discover/application/components/sidebar/lib/visualize_trigger_utils.ts b/public/kibana-integrations/discover/application/components/sidebar/lib/visualize_trigger_utils.ts
index 677539a4f2..ad9ce92e9a 100644
--- a/public/kibana-integrations/discover/application/components/sidebar/lib/visualize_trigger_utils.ts
+++ b/public/kibana-integrations/discover/application/components/sidebar/lib/visualize_trigger_utils.ts
@@ -23,16 +23,16 @@ import {
visualizeGeoFieldTrigger,
} from '../../../../../../../../../src/plugins/ui_actions/public';
import { getUiActions } from '../../../../kibana_services';
-import { IndexPatternField, KBN_FIELD_TYPES } from '../../../../../../../../../src/plugins/data/public';
+import { IndexPatternField, OSD_FIELD_TYPES } from '../../../../../../../../../src/plugins/data/public';
function getTriggerConstant(type: string) {
- return type === KBN_FIELD_TYPES.GEO_POINT || type === KBN_FIELD_TYPES.GEO_SHAPE
+ return type === OSD_FIELD_TYPES.GEO_POINT || type === OSD_FIELD_TYPES.GEO_SHAPE
? VISUALIZE_GEO_FIELD_TRIGGER
: VISUALIZE_FIELD_TRIGGER;
}
function getTrigger(type: string) {
- return type === KBN_FIELD_TYPES.GEO_POINT || type === KBN_FIELD_TYPES.GEO_SHAPE
+ return type === OSD_FIELD_TYPES.GEO_POINT || type === OSD_FIELD_TYPES.GEO_SHAPE
? visualizeGeoFieldTrigger
: visualizeFieldTrigger;
}
diff --git a/public/kibana-integrations/discover/application/components/skip_bottom_button/skip_bottom_button.tsx b/public/kibana-integrations/discover/application/components/skip_bottom_button/skip_bottom_button.tsx
index d5bc5bb64f..bcc36eecd4 100644
--- a/public/kibana-integrations/discover/application/components/skip_bottom_button/skip_bottom_button.tsx
+++ b/public/kibana-integrations/discover/application/components/skip_bottom_button/skip_bottom_button.tsx
@@ -18,7 +18,7 @@
*/
import React from 'react';
import { EuiSkipLink } from '@elastic/eui';
-import { FormattedMessage, I18nProvider } from '@kbn/i18n/react';
+import { FormattedMessage, I18nProvider } from '@osd/i18n/react';
export interface SkipBottomButtonProps {
/**
diff --git a/public/kibana-integrations/discover/application/components/table/table_row_btn_collapse.tsx b/public/kibana-integrations/discover/application/components/table/table_row_btn_collapse.tsx
index bb5ea4bd20..f6b52fed05 100644
--- a/public/kibana-integrations/discover/application/components/table/table_row_btn_collapse.tsx
+++ b/public/kibana-integrations/discover/application/components/table/table_row_btn_collapse.tsx
@@ -17,7 +17,7 @@
* under the License.
*/
import React from 'react';
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
export interface Props {
diff --git a/public/kibana-integrations/discover/application/components/table/table_row_btn_filter_add.tsx b/public/kibana-integrations/discover/application/components/table/table_row_btn_filter_add.tsx
index bd842eb5c6..3b623c096b 100644
--- a/public/kibana-integrations/discover/application/components/table/table_row_btn_filter_add.tsx
+++ b/public/kibana-integrations/discover/application/components/table/table_row_btn_filter_add.tsx
@@ -17,9 +17,9 @@
* under the License.
*/
import React from 'react';
-import { FormattedMessage } from '@kbn/i18n/react';
+import { FormattedMessage } from '@osd/i18n/react';
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
export interface Props {
onClick: () => void;
@@ -47,7 +47,7 @@ export function DocViewTableRowBtnFilterAdd({ onClick, disabled = false }: Props
})}
className="kbnDocViewer__actionButton"
data-test-subj="addInclusiveFilterButton"
- disabled={disabled}
+ isDisabled={disabled}
onClick={onClick}
iconType={'magnifyWithPlus'}
iconSize={'s'}
diff --git a/public/kibana-integrations/discover/application/components/table/table_row_btn_filter_exists.tsx b/public/kibana-integrations/discover/application/components/table/table_row_btn_filter_exists.tsx
index dab22c103b..fa351bac60 100644
--- a/public/kibana-integrations/discover/application/components/table/table_row_btn_filter_exists.tsx
+++ b/public/kibana-integrations/discover/application/components/table/table_row_btn_filter_exists.tsx
@@ -17,9 +17,9 @@
* under the License.
*/
import React from 'react';
-import { FormattedMessage } from '@kbn/i18n/react';
+import { FormattedMessage } from '@osd/i18n/react';
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
export interface Props {
onClick: () => void;
@@ -60,7 +60,7 @@ export function DocViewTableRowBtnFilterExists({
onClick={onClick}
className="kbnDocViewer__actionButton"
data-test-subj="addExistsFilterButton"
- disabled={disabled}
+ isDisabled={disabled}
iconType={'indexOpen'}
iconSize={'s'}
/>
diff --git a/public/kibana-integrations/discover/application/components/table/table_row_btn_filter_remove.tsx b/public/kibana-integrations/discover/application/components/table/table_row_btn_filter_remove.tsx
index bbef54cb4e..79787754ae 100644
--- a/public/kibana-integrations/discover/application/components/table/table_row_btn_filter_remove.tsx
+++ b/public/kibana-integrations/discover/application/components/table/table_row_btn_filter_remove.tsx
@@ -17,9 +17,9 @@
* under the License.
*/
import React from 'react';
-import { FormattedMessage } from '@kbn/i18n/react';
+import { FormattedMessage } from '@osd/i18n/react';
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
export interface Props {
onClick: () => void;
@@ -47,7 +47,7 @@ export function DocViewTableRowBtnFilterRemove({ onClick, disabled = false }: Pr
})}
className="kbnDocViewer__actionButton"
data-test-subj="removeInclusiveFilterButton"
- disabled={disabled}
+ isDisabled={disabled}
onClick={onClick}
iconType={'magnifyWithMinus'}
iconSize={'s'}
diff --git a/public/kibana-integrations/discover/application/components/table/table_row_btn_toggle_column.tsx b/public/kibana-integrations/discover/application/components/table/table_row_btn_toggle_column.tsx
index 3e5a057929..926e7d1a01 100644
--- a/public/kibana-integrations/discover/application/components/table/table_row_btn_toggle_column.tsx
+++ b/public/kibana-integrations/discover/application/components/table/table_row_btn_toggle_column.tsx
@@ -17,9 +17,9 @@
* under the License.
*/
import React from 'react';
-import { FormattedMessage } from '@kbn/i18n/react';
+import { FormattedMessage } from '@osd/i18n/react';
import { EuiToolTip, EuiButtonIcon } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
export interface Props {
active: boolean;
@@ -36,7 +36,7 @@ export function DocViewTableRowBtnToggleColumn({ onClick, active, disabled = fal
})}
className="kbnDocViewer__actionButton"
data-test-subj="toggleColumnButton"
- disabled
+ isDisabled={disabled}
iconType={'tableOfContents'}
iconSize={'s'}
/>
diff --git a/public/kibana-integrations/discover/application/components/table/table_row_icon_no_mapping.tsx b/public/kibana-integrations/discover/application/components/table/table_row_icon_no_mapping.tsx
index 3094d366ce..4d2f433697 100644
--- a/public/kibana-integrations/discover/application/components/table/table_row_icon_no_mapping.tsx
+++ b/public/kibana-integrations/discover/application/components/table/table_row_icon_no_mapping.tsx
@@ -18,7 +18,7 @@
*/
import React from 'react';
import { EuiIconTip } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
export function DocViewTableRowIconNoMapping() {
const ariaLabel = i18n.translate('discover.docViews.table.noCachedMappingForThisFieldAriaLabel', {
diff --git a/public/kibana-integrations/discover/application/components/table/table_row_icon_underscore.tsx b/public/kibana-integrations/discover/application/components/table/table_row_icon_underscore.tsx
index 791ab18de5..09d759bb5e 100644
--- a/public/kibana-integrations/discover/application/components/table/table_row_icon_underscore.tsx
+++ b/public/kibana-integrations/discover/application/components/table/table_row_icon_underscore.tsx
@@ -18,7 +18,7 @@
*/
import React from 'react';
import { EuiIconTip } from '@elastic/eui';
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
export function DocViewTableRowIconUnderscore() {
const ariaLabel = i18n.translate(
diff --git a/public/kibana-integrations/discover/application/components/timechart_header/timechart_header.tsx b/public/kibana-integrations/discover/application/components/timechart_header/timechart_header.tsx
index 1451106827..da0b041b3e 100644
--- a/public/kibana-integrations/discover/application/components/timechart_header/timechart_header.tsx
+++ b/public/kibana-integrations/discover/application/components/timechart_header/timechart_header.tsx
@@ -25,8 +25,8 @@ import {
EuiSelect,
EuiIconTip,
} from '@elastic/eui';
-import { I18nProvider } from '@kbn/i18n/react';
-import { i18n } from '@kbn/i18n';
+import { I18nProvider } from '@osd/i18n/react';
+import { i18n } from '@osd/i18n';
import moment from 'moment';
export interface TimechartHeaderProps {
diff --git a/public/kibana-integrations/discover/application/components/top_nav/open_search_panel.js b/public/kibana-integrations/discover/application/components/top_nav/open_search_panel.js
index 3908b13360..7f00ed59f9 100644
--- a/public/kibana-integrations/discover/application/components/top_nav/open_search_panel.js
+++ b/public/kibana-integrations/discover/application/components/top_nav/open_search_panel.js
@@ -20,8 +20,8 @@
import React from 'react';
import PropTypes from 'prop-types';
import rison from 'rison-node';
-import { i18n } from '@kbn/i18n';
-import { FormattedMessage } from '@kbn/i18n/react';
+import { i18n } from '@osd/i18n';
+import { FormattedMessage } from '@osd/i18n/react';
import {
EuiButton,
EuiFlexGroup,
diff --git a/public/kibana-integrations/discover/application/helpers/breadcrumbs.ts b/public/kibana-integrations/discover/application/helpers/breadcrumbs.ts
index 17492b02f7..0f262a0f3a 100644
--- a/public/kibana-integrations/discover/application/helpers/breadcrumbs.ts
+++ b/public/kibana-integrations/discover/application/helpers/breadcrumbs.ts
@@ -17,7 +17,7 @@
* under the License.
*/
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
export function getRootBreadcrumbs() {
return [
diff --git a/public/kibana-integrations/discover/application/helpers/validate_time_range.ts b/public/kibana-integrations/discover/application/helpers/validate_time_range.ts
index 411147f827..ce4d9133cf 100644
--- a/public/kibana-integrations/discover/application/helpers/validate_time_range.ts
+++ b/public/kibana-integrations/discover/application/helpers/validate_time_range.ts
@@ -17,8 +17,8 @@
* under the License.
*/
import dateMath from '@elastic/datemath';
-import { i18n } from '@kbn/i18n';
-import { ToastsStart } from 'kibana/public';
+import { i18n } from '@osd/i18n';
+import { ToastsStart } from 'opensearch_dashboards/public';
/**
* Validates a given time filter range, provided by URL or UI
diff --git a/public/kibana-integrations/discover/build_services.ts b/public/kibana-integrations/discover/build_services.ts
index 1ef9711c49..9d7d4dd86b 100644
--- a/public/kibana-integrations/discover/build_services.ts
+++ b/public/kibana-integrations/discover/build_services.ts
@@ -26,7 +26,7 @@ import {
ToastsStart,
IUiSettingsClient,
PluginInitializerContext,
-} from 'kibana/public';
+} from 'opensearch_dashboards/public';
import {
FilterManager,
TimefilterContract,
@@ -37,11 +37,11 @@ import { Start as InspectorPublicPluginStart } from '../../../../../src/plugins/
import { SharePluginStart } from 'src/plugins/share/public';
import { ChartsPluginStart } from 'src/plugins/charts/public';
import { VisualizationsStart } from 'src/plugins/visualizations/public';
-import { SavedObjectKibanaServices } from 'src/plugins/saved_objects/public';
+import { SavedObjectOpenSearchDashboardsServices } from 'src/plugins/saved_objects/public';
//import { createSavedSearchesLoader, SavedSearch } from './saved_searches';
import { getHistory } from './kibana_services';
-import { KibanaLegacyStart } from '../../../../../src/plugins/kibana_legacy/public';
+import { OpenSearchDashboardsLegacyStart } from '../../../../../src/plugins/opensearch_dashboards_legacy/public';
import { UrlForwardingStart } from '../../../../../src/plugins/url_forwarding/public';
import { NavigationPublicPluginStart } from '../../../../../src/plugins/navigation/public';
import { getDataPlugin, getNavigationPlugin, getVisualizationsPlugin } from '../../kibana-services';
@@ -62,7 +62,7 @@ export interface DiscoverServices {
metadata: { branch: string };
navigation: NavigationPublicPluginStart;
share?: SharePluginStart;
- kibanaLegacy: KibanaLegacyStart;
+ kibanaLegacy: OpenSearchDashboardsLegacyStart;
urlForwarding: UrlForwardingStart;
timefilter: TimefilterContract;
toastNotifications: ToastsStart;
@@ -79,7 +79,7 @@ export async function buildServices(
context: PluginInitializerContext,
getEmbeddableInjector: any
): Promise {
-/* const services: SavedObjectKibanaServices = {
+/* const services: SavedObjectOpenSearchDashboardsServices = {
savedObjectsClient: core.savedObjects.client,
indexPatterns: plugins.data.indexPatterns,
search: plugins.data.search,
diff --git a/public/kibana-integrations/discover/kibana_services.ts b/public/kibana-integrations/discover/kibana_services.ts
index f80027969e..bc1a514baa 100644
--- a/public/kibana-integrations/discover/kibana_services.ts
+++ b/public/kibana-integrations/discover/kibana_services.ts
@@ -19,13 +19,13 @@
import _ from 'lodash';
import { createHashHistory } from 'history';
-import { ScopedHistory, AppMountParameters } from 'kibana/public';
+import { ScopedHistory, AppMountParameters } from 'opensearch_dashboards/public';
import { UiActionsStart } from 'src/plugins/ui_actions/public';
import { DiscoverServices } from './build_services';
-import { createGetterSetter } from '../../../../../src/plugins/kibana_utils/public';
+import { createGetterSetter } from '../../../../../src/plugins/opensearch_dashboards_utils/public';
import { search } from '../../../../../src/plugins/data/public';
import { DocViewsRegistry } from './application/doc_views/doc_views_registry';
-import { i18n } from '@kbn/i18n';
+import { i18n } from '@osd/i18n';
import type { estypes } from '@elastic/elasticsearch';
import type { ISearchSource } from 'src/plugins/data/public';
import type { RequestStatistics } from 'src/plugins/inspector/common';
@@ -97,8 +97,8 @@ export const [getScopedHistory, setScopedHistory] = createGetterSetter {
- const services = await buildServices(
+ const services = await buildServices(
getCore(),
getPlugins(),
{ env: { packageInfo: { branch: "7.10" } } },
@@ -239,7 +239,7 @@ function discoverController(
data.query,
appStateContainer,
{
- filters: esFilters.FilterStateStore.APP_STATE,
+ filters: opensearchFilters.FilterStateStore.APP_STATE,
query: true,
}
);
@@ -302,14 +302,14 @@ function discoverController(
next: () => {
//Patch empty fields
const filters = filterManager.getAppFilters();
- if(filters.filter(item=> item.meta.params && item.meta.params.query === '').length){
+ if (filters.filter(item => item.meta.params && item.meta.params.query === '').length) {
getToasts().add({
color: 'warning',
title: 'Invalid field value',
text: 'The filter field contains invalid value',
toastLifeTimeMs: 10000,
});
- filterManager.setFilters(filters.filter(item=>item.meta.params.query));
+ filterManager.setFilters(filters.filter(item => item.meta.params.query));
}
//end of patch empty fields
$scope.state.filters = filters;
@@ -501,8 +501,8 @@ function discoverController(
savedSearch: savedSearch,
indexPatternList: $route.current.locals.ip.list,
config: config,
- fixedScroll: $scope.tabView === 'discover'? createFixedScroll($scope, $timeout) : () => {},
- setHeaderActionMenu: () => {} //getHeaderActionMenuMounter(),
+ fixedScroll: $scope.tabView === 'discover' ? createFixedScroll($scope, $timeout) : () => { },
+ setHeaderActionMenu: () => { } //getHeaderActionMenuMounter(),
};
const shouldSearchOnPageLoad = () => {
@@ -547,7 +547,7 @@ function discoverController(
negate: true,
params: { query: '000' },
type: 'phrase',
- index: AppState.getCurrentPattern() || WAZUH_ALERTS_PATTERN
+ index: AppState.getCurrentPattern() || getSettingDefaultValue('pattern')
},
query: { match_phrase: { 'agent.id': '000' } },
$state: { store: 'appState' }
@@ -712,13 +712,13 @@ function discoverController(
// Wazuh filters are not ready yet
if (!filtersAreReady()) return;
if (!_.isEqual(query, appStateContainer.getState().query) || isUpdate === false) {
- /// Wazuh 7.7.x
- let q = { ...query };
- if (query && typeof query === 'object') {
- q.timestamp = new Date().getTime().toString();
- }
- ///
- setAppState({ query: q });
+ /// Wazuh 7.7.x
+ let q = { ...query };
+ if (query && typeof query === 'object') {
+ q.timestamp = new Date().getTime().toString();
+ }
+ ///
+ setAppState({ query: q });
// WAZUH query from search bar
discoverPendingUpdates.removeAll();
discoverPendingUpdates.addItem($scope.state.query, filterManager.filters);
@@ -747,7 +747,7 @@ function discoverController(
const bounds = agg.params.timeRange ? timefilter.calculateBounds(agg.params.timeRange) : null;
agg.buckets.setBounds(bounds);
- const { esUnit, esValue } = agg.buckets.getInterval();
+ const { opensearchUnit, opensearchValue } = agg.buckets.getInterval();
return {
x: {
accessor: 0,
@@ -755,9 +755,9 @@ function discoverController(
format: agg.toSerializedFieldFormat(),
params: {
date: true,
- interval: moment.duration(esValue, esUnit),
- intervalESValue: esValue,
- intervalESUnit: esUnit,
+ interval: moment.duration(opensearchValue, opensearchUnit),
+ intervalOpenSearchValue: opensearchValue,
+ intervalOpenSearchUnit: opensearchUnit,
format: agg.buckets.getScaledDateFormat(),
bounds: agg.buckets.getBounds(),
},
@@ -923,7 +923,7 @@ function discoverController(
$scope.filterQuery = function (field, values, operation) {
// Commented due to https://github.com/elastic/kibana/issues/22426
//$scope.indexPattern.popularizeField(field, 1);
- const newFilters = esFilters.generateFilters(
+ const newFilters = opensearchFilters.generateFilters(
filterManager,
field,
values,
@@ -1076,7 +1076,7 @@ function discoverController(
if ($scope.fetchStatus !== fetchStatuses.UNINITIALIZED) {
setTimeout(() => {
modulesHelper.hideCloseButtons();
- }, 100);
+ }, 100);
}
});
diff --git a/public/kibana-integrations/kibana-vis.js b/public/kibana-integrations/kibana-vis.js
index 27e2adc156..825806795b 100644
--- a/public/kibana-integrations/kibana-vis.js
+++ b/public/kibana-integrations/kibana-vis.js
@@ -410,6 +410,7 @@ class KibanaVis extends Component {
this.$rootScope.rendered = 'false';
}
}
+ if (typeof this.props.onRenderComplete === 'function') this.props.onRenderComplete();
};
showDateRangePicker = () => {
diff --git a/public/kibana-integrations/visualizations/saved_object_loader.ts b/public/kibana-integrations/visualizations/saved_object_loader.ts
index fc5240fc6c..8e0190411d 100644
--- a/public/kibana-integrations/visualizations/saved_object_loader.ts
+++ b/public/kibana-integrations/visualizations/saved_object_loader.ts
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { ChromeStart, SavedObjectsClientContract, SavedObjectsFindOptions } from 'kibana/public';
+import { ChromeStart, SavedObjectsClientContract, SavedObjectsFindOptions } from 'opensearch_dashboards/public';
import { SavedObject } from '../../../../src/plugins/saved_objects/public/types';
import { StringsTools } from '../../utils/strings-tools';
@@ -80,7 +80,7 @@ export class SavedObjectLoader {
// just assign the defaults and be done
_.assign(instance, instance.defaults);
return instance.hydrateIndexPattern().then(() => {
- return afterESResp.call(instance); // eslint-disable-line
+ return afterOpenSearchResp.call(instance); // eslint-disable-line
});
}
return this.processFunc()
@@ -92,8 +92,8 @@ export class SavedObjectLoader {
found: raw._version ? true : false
};
})
- .then(instance.applyESResp)
- .catch(instance.applyEsResp);
+ .then(instance.applyOpenSearchResp)
+ .catch(instance.applyOpenSearchResp);
})
.then(() => instance);
});
diff --git a/public/kibana-integrations/visualizations/saved_visualizations.ts b/public/kibana-integrations/visualizations/saved_visualizations.ts
index 2b1a8ebd6a..614e79419a 100644
--- a/public/kibana-integrations/visualizations/saved_visualizations.ts
+++ b/public/kibana-integrations/visualizations/saved_visualizations.ts
@@ -17,17 +17,17 @@
* under the License.
*/
import { SavedObjectLoader } from './saved_object_loader';
-import { SavedObjectKibanaServices } from '../../../../src/plugins/saved_objects/public';
+import { SavedObjectOpenSearchDashboardsServices } from '../../../../../src/plugins/saved_objects/public';
import { findListItems } from './find_list_items';
import { createSavedVisClass } from './_saved_vis';
-import { TypesStart } from '../../../../src/plugins/visualizations/public/vis_types';
+import { TypesStart } from '../../../../../src/plugins/visualizations/public/vis_types';
import { getVisualizationsPlugin } from '../kibana-services';
-export interface SavedObjectKibanaServicesWithVisualizations extends SavedObjectKibanaServices {
+export interface SavedObjectOpenSearchDashboardsServicesWithVisualizations extends SavedObjectOpenSearchDashboardsServices {
visualizationTypes: TypesStart;
}
export type SavedVisualizationsLoader = ReturnType;
-export function createSavedVisLoader(services: SavedObjectKibanaServicesWithVisualizations) {
+export function createSavedVisLoader(services: SavedObjectOpenSearchDashboardsServicesWithVisualizations) {
const { savedObjectsClient, visualizationTypes } = services;
class SavedObjectLoaderVisualize extends SavedObjectLoader {
diff --git a/public/kibana-services.ts b/public/kibana-services.ts
index 899d0b9829..9f9998beca 100644
--- a/public/kibana-services.ts
+++ b/public/kibana-services.ts
@@ -7,8 +7,8 @@ import {
SavedObjectsStart,
ScopedHistory,
ToastsStart,
-} from 'kibana/public';
-import { createGetterSetter } from '../../../src/plugins/kibana_utils/common';
+} from 'opensearch_dashboards/public';
+import { createGetterSetter } from '../../../src/plugins/opensearch_dashboards_utils/common';
import { DataPublicPluginStart } from '../../../src/plugins/data/public';
import { VisualizationsStart } from '../../../src/plugins/visualizations/public';
import { NavigationPublicPluginStart } from '../../../src/plugins/navigation/public';
diff --git a/public/package.test.ts b/public/package.test.ts
new file mode 100644
index 0000000000..0ee26aa170
--- /dev/null
+++ b/public/package.test.ts
@@ -0,0 +1,50 @@
+import packageValue from '../package.json';
+
+const isNaN = (currentValue: string) => Number.isNaN(Number(currentValue));
+
+describe('package.json version', () => {
+ it('should have a version', () => {
+ expect(packageValue.version).toBeDefined();
+ });
+ it("Wazuh's revision should be to follow the major.minor.patch.pattern.", () => {
+ const versionSplit = packageValue.version.split('.');
+
+ const versionIsNaN = versionSplit.every(isNaN);
+
+ expect(versionSplit.length).toBe(3);
+ expect(versionIsNaN).toBeFalsy();
+ });
+});
+
+describe('package.json revison', () => {
+ it('should have a revison', () => {
+ expect(packageValue.revision).toBeDefined();
+ });
+ it('the revision should be a 2 digit number.', () => {
+ const revision = packageValue.revision;
+
+ const revisionIsNaN = isNaN(revision);
+
+ expect(revision.length).toBe(2);
+ expect(revisionIsNaN).toBeFalsy();
+ });
+});
+
+describe('package.json stage', () => {
+ it('should have a stage', () => {
+ expect(packageValue.stage).toBeDefined();
+ });
+ it('the state should be one of the defined.', () => {
+ const stateDefined = [
+ 'pre-alpha',
+ 'alpha',
+ 'beta',
+ 'release-candidate',
+ 'stable',
+ ];
+
+ const stage = packageValue.stage;
+
+ expect(stateDefined).toContain(stage);
+ });
+});
diff --git a/public/panels/elastic-with-sample-data/amazon-aws.ndjson b/public/panels/elastic-with-sample-data/amazon-aws.ndjson
new file mode 100644
index 0000000000..60978088ce
--- /dev/null
+++ b/public/panels/elastic-with-sample-data/amazon-aws.ndjson
@@ -0,0 +1,3 @@
+{"attributes":{"fieldAttrs":"{}","fieldFormatMap":"{}","fields":"[]","name":"wazuh-alerts-4.x-dashboards","runtimeFieldMap":"{}","sourceFilters":"[]","timeFieldName":"timestamp","title":"wazuh-alerts-4.x-dashboards","typeMeta":"{}"},"coreMigrationVersion":"8.6.0","created_at":"2023-02-01T14:22:22.164Z","id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","migrationVersion":{"index-pattern":"8.0.0"},"references":[],"type":"index-pattern","updated_at":"2023-02-01T14:22:22.164Z","version":"WzEwNDksMV0="}
+{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"optionsJSON":"{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}","panelsJSON":"[{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":31,\"h\":15,\"i\":\"5177564c-7c79-4412-9c03-99dca92b90d5\"},\"panelIndex\":\"5177564c-7c79-4412-9c03-99dca92b90d5\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-bca83102-e00c-4277-b280-a91ef087536e\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"left\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"curveType\":\"CURVE_MONOTONE_X\",\"fillOpacity\":1,\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"area_stacked\",\"layers\":[{\"layerId\":\"bca83102-e00c-4277-b280-a91ef087536e\",\"accessors\":[\"80ac5cd7-4cfb-4c07-ad75-3cedb6212f18\"],\"position\":\"top\",\"seriesType\":\"area_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"4d2f8c1f-5ce3-449b-b0d7-f1d1989ba49e\",\"splitAccessor\":\"0e534aac-0aaf-4458-8d88-e2575fb2ebb9\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"bca83102-e00c-4277-b280-a91ef087536e\":{\"columns\":{\"0e534aac-0aaf-4458-8d88-e2575fb2ebb9\":{\"label\":\"Top 3 values of data.aws.source\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.aws.source\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"80ac5cd7-4cfb-4c07-ad75-3cedb6212f18\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]}},\"4d2f8c1f-5ce3-449b-b0d7-f1d1989ba49e\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"80ac5cd7-4cfb-4c07-ad75-3cedb6212f18\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"filter\":{\"query\":\"rule.groups : \\\"amazon\\\" \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"0e534aac-0aaf-4458-8d88-e2575fb2ebb9\",\"4d2f8c1f-5ce3-449b-b0d7-f1d1989ba49e\",\"80ac5cd7-4cfb-4c07-ad75-3cedb6212f18\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Events by source over time\"},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":31,\"y\":0,\"w\":17,\"h\":15,\"i\":\"692e518d-0688-414b-92e8-6b2bf1b960dd\"},\"panelIndex\":\"692e518d-0688-414b-92e8-6b2bf1b960dd\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsPie\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-ecb05aff-bc9d-4ba1-b817-bf4016e0c5ef\"}],\"state\":{\"visualization\":{\"shape\":\"donut\",\"layers\":[{\"layerId\":\"ecb05aff-bc9d-4ba1-b817-bf4016e0c5ef\",\"primaryGroups\":[\"e81edf81-ce10-496b-8ca9-eb38d5ff2ccb\"],\"metrics\":[\"4a2c1031-e343-427d-b141-b47ccc7a570a\"],\"numberDisplay\":\"hidden\",\"categoryDisplay\":\"hide\",\"legendDisplay\":\"show\",\"nestedLegend\":false,\"layerType\":\"data\",\"emptySizeRatio\":0.7}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"ecb05aff-bc9d-4ba1-b817-bf4016e0c5ef\":{\"columns\":{\"e81edf81-ce10-496b-8ca9-eb38d5ff2ccb\":{\"label\":\"Top 5 values of data.aws.source\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.aws.source\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"4a2c1031-e343-427d-b141-b47ccc7a570a\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]}},\"4a2c1031-e343-427d-b141-b47ccc7a570a\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}}},\"columnOrder\":[\"e81edf81-ce10-496b-8ca9-eb38d5ff2ccb\",\"4a2c1031-e343-427d-b141-b47ccc7a570a\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Sources\"},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":15,\"w\":48,\"h\":15,\"i\":\"25e0d536-4163-46e6-abd5-5cd45cd9f30a\"},\"panelIndex\":\"25e0d536-4163-46e6-abd5-5cd45cd9f30a\",\"embeddableConfig\":{\"attributes\":{\"title\":\"e\",\"description\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-c23cdcb3-1e5c-46f0-9ef2-827d9b867cb2\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"8882fc10-f772-4a02-af1f-049b59a04dfd\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"1835ff08-affb-403c-991e-8e642c7a5456\"},{\"isTransposed\":false,\"columnId\":\"6dce6ade-b342-4645-9ff2-228f319d69f7\"},{\"isTransposed\":false,\"columnId\":\"f8266242-342d-4046-8bb5-90efe4839a60\",\"hidden\":true},{\"columnId\":\"06b78908-beb7-4a01-a9b0-b7f9775318d9\",\"isTransposed\":false},{\"columnId\":\"ea992e31-8ea1-4548-8182-da51c911cf21\",\"isTransposed\":false},{\"columnId\":\"a8c6efd9-93b3-4636-96ea-43b359962134\",\"isTransposed\":false,\"oneClickFilter\":true}],\"layerId\":\"c23cdcb3-1e5c-46f0-9ef2-827d9b867cb2\",\"layerType\":\"data\",\"headerRowHeight\":\"custom\",\"headerRowHeightLines\":2,\"rowHeight\":\"custom\",\"rowHeightLines\":2,\"paging\":{\"size\":10,\"enabled\":true}},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"c23cdcb3-1e5c-46f0-9ef2-827d9b867cb2\":{\"columns\":{\"8882fc10-f772-4a02-af1f-049b59a04dfd\":{\"label\":\"agent.name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"agent.name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f8266242-342d-4046-8bb5-90efe4839a60\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"1835ff08-affb-403c-991e-8e642c7a5456\":{\"label\":\"data.aws.source\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.aws.source\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f8266242-342d-4046-8bb5-90efe4839a60\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"6dce6ade-b342-4645-9ff2-228f319d69f7\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"f8266242-342d-4046-8bb5-90efe4839a60\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}},\"06b78908-beb7-4a01-a9b0-b7f9775318d9\":{\"label\":\"rule.description\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.description\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f8266242-342d-4046-8bb5-90efe4839a60\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"ea992e31-8ea1-4548-8182-da51c911cf21\":{\"label\":\"rule.level\",\"dataType\":\"number\",\"operationType\":\"range\",\"sourceField\":\"rule.level\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"includeEmptyRows\":true,\"type\":\"histogram\",\"ranges\":[{\"from\":0,\"to\":1000,\"label\":\"\"}],\"maxBars\":\"auto\"}},\"a8c6efd9-93b3-4636-96ea-43b359962134\":{\"label\":\"rule.id\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.id\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f8266242-342d-4046-8bb5-90efe4839a60\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true}},\"columnOrder\":[\"6dce6ade-b342-4645-9ff2-228f319d69f7\",\"8882fc10-f772-4a02-af1f-049b59a04dfd\",\"1835ff08-affb-403c-991e-8e642c7a5456\",\"06b78908-beb7-4a01-a9b0-b7f9775318d9\",\"ea992e31-8ea1-4548-8182-da51c911cf21\",\"a8c6efd9-93b3-4636-96ea-43b359962134\",\"f8266242-342d-4046-8bb5-90efe4839a60\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Events\"}]","timeRestore":false,"title":"Amazon AWS","version":1},"coreMigrationVersion":"8.6.0","created_at":"2023-02-10T14:05:12.784Z","id":"ff5626e0-a63f-11ed-8b0e-91d62e747cc9","migrationVersion":{"dashboard":"8.6.0"},"references":[{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"5177564c-7c79-4412-9c03-99dca92b90d5:indexpattern-datasource-layer-bca83102-e00c-4277-b280-a91ef087536e","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"692e518d-0688-414b-92e8-6b2bf1b960dd:indexpattern-datasource-layer-ecb05aff-bc9d-4ba1-b817-bf4016e0c5ef","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"25e0d536-4163-46e6-abd5-5cd45cd9f30a:indexpattern-datasource-layer-c23cdcb3-1e5c-46f0-9ef2-827d9b867cb2","type":"index-pattern"}],"type":"dashboard","updated_at":"2023-02-10T14:05:12.784Z","version":"WzM5OTg0LDNd"}
+{"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":2,"missingRefCount":0,"missingReferences":[]}
\ No newline at end of file
diff --git a/public/panels/elastic-with-sample-data/docker-listener.ndjson b/public/panels/elastic-with-sample-data/docker-listener.ndjson
new file mode 100644
index 0000000000..56f802305f
--- /dev/null
+++ b/public/panels/elastic-with-sample-data/docker-listener.ndjson
@@ -0,0 +1,3 @@
+{"attributes":{"fieldAttrs":"{}","fieldFormatMap":"{}","fields":"[]","name":"wazuh-alerts-4.x-dashboards","runtimeFieldMap":"{}","sourceFilters":"[]","timeFieldName":"timestamp","title":"wazuh-alerts-4.x-dashboards","typeMeta":"{}"},"coreMigrationVersion":"8.6.0","created_at":"2023-02-01T14:22:22.164Z","id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","migrationVersion":{"index-pattern":"8.0.0"},"references":[],"type":"index-pattern","updated_at":"2023-02-01T14:22:22.164Z","version":"WzEwNDksMV0="}
+{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"optionsJSON":"{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}","panelsJSON":"[{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":14,\"h\":12,\"i\":\"9c90478b-ef8d-4f0a-89ea-7cac2fb2b631\"},\"panelIndex\":\"9c90478b-ef8d-4f0a-89ea-7cac2fb2b631\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsPie\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-b9d91550-4d81-4724-926b-368cbac70c5c\"}],\"state\":{\"visualization\":{\"shape\":\"donut\",\"layers\":[{\"layerId\":\"b9d91550-4d81-4724-926b-368cbac70c5c\",\"primaryGroups\":[\"393155df-15ed-400b-bef4-be554873a6c6\"],\"metrics\":[\"bc0afca3-aed2-4b22-970c-c91ac3e2bc02\"],\"numberDisplay\":\"percent\",\"categoryDisplay\":\"hide\",\"legendDisplay\":\"show\",\"nestedLegend\":false,\"layerType\":\"data\",\"emptySizeRatio\":0.7}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"b9d91550-4d81-4724-926b-368cbac70c5c\":{\"columns\":{\"393155df-15ed-400b-bef4-be554873a6c6\":{\"label\":\"Top 5 values of data.docker.Action\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.docker.Action\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"bc0afca3-aed2-4b22-970c-c91ac3e2bc02\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false}},\"bc0afca3-aed2-4b22-970c-c91ac3e2bc02\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}}},\"columnOrder\":[\"393155df-15ed-400b-bef4-be554873a6c6\",\"bc0afca3-aed2-4b22-970c-c91ac3e2bc02\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Top 5 events\"},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":14,\"y\":0,\"w\":34,\"h\":12,\"i\":\"ec92f542-1336-4a92-90e6-548fa7a78db6\"},\"panelIndex\":\"ec92f542-1336-4a92-90e6-548fa7a78db6\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-45315f08-c693-4bdc-aa72-8546f280b2b2\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"45315f08-c693-4bdc-aa72-8546f280b2b2\",\"accessors\":[\"69651d63-8697-41d8-b639-5d77e806c90a\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"93ae869a-82d8-4825-9391-568728d510a7\",\"splitAccessor\":\"588460de-4d21-471e-922f-0b59d3ec977f\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"45315f08-c693-4bdc-aa72-8546f280b2b2\":{\"columns\":{\"93ae869a-82d8-4825-9391-568728d510a7\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"69651d63-8697-41d8-b639-5d77e806c90a\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"588460de-4d21-471e-922f-0b59d3ec977f\":{\"label\":\"Top 3 values of data.docker.Type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.docker.Type\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"69651d63-8697-41d8-b639-5d77e806c90a\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false}}},\"columnOrder\":[\"588460de-4d21-471e-922f-0b59d3ec977f\",\"93ae869a-82d8-4825-9391-568728d510a7\",\"69651d63-8697-41d8-b639-5d77e806c90a\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Events by source over time\"},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":12,\"w\":48,\"h\":37,\"i\":\"cac9a63e-4892-4879-bd94-210fd3b5b3d0\"},\"panelIndex\":\"cac9a63e-4892-4879-bd94-210fd3b5b3d0\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-c51272e9-4ceb-4095-a2a2-7d27d957fc4e\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"1cedf71d-5da2-423a-8108-0d28190dc1f2\",\"isTransposed\":false},{\"columnId\":\"09e332ce-350b-499a-8df5-9b15ed375c20\",\"isTransposed\":false,\"oneClickFilter\":true},{\"columnId\":\"e323b79e-be8f-458d-80b9-100d79e6fc3c\",\"isTransposed\":false,\"hidden\":true},{\"columnId\":\"655b8229-82ac-4302-a97c-a5b1778f22f9\",\"isTransposed\":false},{\"columnId\":\"c47bc042-54fd-4134-9cec-05f36c5c95e0\",\"isTransposed\":false},{\"columnId\":\"1bef96c9-5098-47db-9d76-2eba9c1cfd33\",\"isTransposed\":false},{\"columnId\":\"a61f2679-de38-4a5d-b105-dab5d341a400\",\"isTransposed\":false},{\"columnId\":\"f7109d3b-68d4-418c-b4c4-fe451858d375\",\"isTransposed\":false},{\"columnId\":\"28c7593f-f805-4cbd-afed-94dfdbde7d29\",\"isTransposed\":false,\"oneClickFilter\":true}],\"layerId\":\"c51272e9-4ceb-4095-a2a2-7d27d957fc4e\",\"layerType\":\"data\",\"headerRowHeight\":\"custom\",\"headerRowHeightLines\":2,\"rowHeight\":\"custom\",\"rowHeightLines\":2,\"paging\":{\"size\":10,\"enabled\":true}},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"c51272e9-4ceb-4095-a2a2-7d27d957fc4e\":{\"columns\":{\"1cedf71d-5da2-423a-8108-0d28190dc1f2\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"09e332ce-350b-499a-8df5-9b15ed375c20\":{\"label\":\"agent.name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"agent.name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e323b79e-be8f-458d-80b9-100d79e6fc3c\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"e323b79e-be8f-458d-80b9-100d79e6fc3c\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}},\"655b8229-82ac-4302-a97c-a5b1778f22f9\":{\"label\":\"data.docker.Type\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.docker.Type\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e323b79e-be8f-458d-80b9-100d79e6fc3c\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"c47bc042-54fd-4134-9cec-05f36c5c95e0\":{\"label\":\"data.docker.Action\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.docker.Action\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e323b79e-be8f-458d-80b9-100d79e6fc3c\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"1bef96c9-5098-47db-9d76-2eba9c1cfd33\":{\"label\":\"data.docker.Actor.ID\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.docker.Actor.ID\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e323b79e-be8f-458d-80b9-100d79e6fc3c\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"a61f2679-de38-4a5d-b105-dab5d341a400\":{\"label\":\"rule.description\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.description\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e323b79e-be8f-458d-80b9-100d79e6fc3c\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"f7109d3b-68d4-418c-b4c4-fe451858d375\":{\"label\":\"rule.level\",\"dataType\":\"number\",\"operationType\":\"range\",\"sourceField\":\"rule.level\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"includeEmptyRows\":true,\"type\":\"histogram\",\"ranges\":[{\"from\":0,\"to\":1000,\"label\":\"\"}],\"maxBars\":\"auto\"}},\"28c7593f-f805-4cbd-afed-94dfdbde7d29\":{\"label\":\"rule.id\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.id\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"e323b79e-be8f-458d-80b9-100d79e6fc3c\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true}},\"columnOrder\":[\"1cedf71d-5da2-423a-8108-0d28190dc1f2\",\"09e332ce-350b-499a-8df5-9b15ed375c20\",\"655b8229-82ac-4302-a97c-a5b1778f22f9\",\"1bef96c9-5098-47db-9d76-2eba9c1cfd33\",\"c47bc042-54fd-4134-9cec-05f36c5c95e0\",\"a61f2679-de38-4a5d-b105-dab5d341a400\",\"f7109d3b-68d4-418c-b4c4-fe451858d375\",\"28c7593f-f805-4cbd-afed-94dfdbde7d29\",\"e323b79e-be8f-458d-80b9-100d79e6fc3c\"],\"sampling\":1,\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Events\"}]","timeRestore":false,"title":"Docker Listener","version":1},"coreMigrationVersion":"8.6.0","created_at":"2023-02-10T17:25:20.820Z","id":"8359c240-a7cf-11ed-8b0e-91d62e747cc9","migrationVersion":{"dashboard":"8.6.0"},"references":[{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"9c90478b-ef8d-4f0a-89ea-7cac2fb2b631:indexpattern-datasource-layer-b9d91550-4d81-4724-926b-368cbac70c5c","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"ec92f542-1336-4a92-90e6-548fa7a78db6:indexpattern-datasource-layer-45315f08-c693-4bdc-aa72-8546f280b2b2","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"cac9a63e-4892-4879-bd94-210fd3b5b3d0:indexpattern-datasource-layer-c51272e9-4ceb-4095-a2a2-7d27d957fc4e","type":"index-pattern"}],"type":"dashboard","updated_at":"2023-02-10T17:25:20.820Z","version":"WzQxODQxLDNd"}
+{"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":2,"missingRefCount":0,"missingReferences":[]}
\ No newline at end of file
diff --git a/public/panels/elastic-with-sample-data/incident-response.ndjson b/public/panels/elastic-with-sample-data/incident-response.ndjson
new file mode 100644
index 0000000000..a5804ad9f0
--- /dev/null
+++ b/public/panels/elastic-with-sample-data/incident-response.ndjson
@@ -0,0 +1,3 @@
+{"attributes":{"fieldAttrs":"{}","fieldFormatMap":"{}","fields":"[]","name":"wazuh-alerts-4.x-dashboards","runtimeFieldMap":"{}","sourceFilters":"[]","timeFieldName":"timestamp","title":"wazuh-alerts-4.x-dashboards","typeMeta":"{}"},"coreMigrationVersion":"8.6.0","created_at":"2023-02-01T14:22:22.164Z","id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","migrationVersion":{"index-pattern":"8.0.0"},"references":[],"type":"index-pattern","updated_at":"2023-02-01T14:22:22.164Z","version":"WzEwNDksMV0="}
+{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"optionsJSON":"{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}","panelsJSON":"[{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":15,\"h\":13,\"i\":\"caf3fb07-a3b0-4f51-b000-926f4b26ee4f\"},\"panelIndex\":\"caf3fb07-a3b0-4f51-b000-926f4b26ee4f\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsPie\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-3ef3cbb5-abf3-4697-9e38-f4cf60bcdd5d\"}],\"state\":{\"visualization\":{\"shape\":\"donut\",\"layers\":[{\"layerId\":\"3ef3cbb5-abf3-4697-9e38-f4cf60bcdd5d\",\"primaryGroups\":[\"ccea2153-9f5c-4f65-9346-1feceb3783eb\"],\"metrics\":[\"06ae1d26-0a3a-4f59-b5bd-8cb93b640f86\"],\"numberDisplay\":\"hidden\",\"categoryDisplay\":\"hide\",\"legendDisplay\":\"show\",\"nestedLegend\":false,\"layerType\":\"data\",\"emptySizeRatio\":0.7,\"legendSize\":\"large\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"3ef3cbb5-abf3-4697-9e38-f4cf60bcdd5d\":{\"columns\":{\"06ae1d26-0a3a-4f59-b5bd-8cb93b640f86\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"filter\":{\"query\":\"\",\"language\":\"kuery\"}},\"ccea2153-9f5c-4f65-9346-1feceb3783eb\":{\"label\":\"Top 5 values of rule.groups\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.groups\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"06ae1d26-0a3a-4f59-b5bd-8cb93b640f86\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false}}},\"columnOrder\":[\"ccea2153-9f5c-4f65-9346-1feceb3783eb\",\"06ae1d26-0a3a-4f59-b5bd-8cb93b640f86\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Alert groups\"},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":15,\"y\":0,\"w\":33,\"h\":13,\"i\":\"115417e6-11a1-4a55-8055-220b69dad98e\"},\"panelIndex\":\"115417e6-11a1-4a55-8055-220b69dad98e\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-54e72470-df75-47d1-a7a6-3d2f807a39d1\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":false,\"position\":\"right\",\"showSingleSeries\":false},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"54e72470-df75-47d1-a7a6-3d2f807a39d1\",\"accessors\":[\"db53a2e0-d936-4f7c-86bb-fc4e20810e64\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"f518cf1a-0d1d-44c7-97a0-12c5cd840e14\",\"splitAccessor\":\"a195fccb-9268-453a-b824-54f1e3f72d12\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"54e72470-df75-47d1-a7a6-3d2f807a39d1\":{\"columns\":{\"a195fccb-9268-453a-b824-54f1e3f72d12\":{\"label\":\"Top 5 values of rule.groups\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.groups\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"db53a2e0-d936-4f7c-86bb-fc4e20810e64\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false}},\"f518cf1a-0d1d-44c7-97a0-12c5cd840e14\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"db53a2e0-d936-4f7c-86bb-fc4e20810e64\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"filter\":{\"query\":\"rule.groups : \\\"audit\\\" \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"a195fccb-9268-453a-b824-54f1e3f72d12\",\"f518cf1a-0d1d-44c7-97a0-12c5cd840e14\",\"db53a2e0-d936-4f7c-86bb-fc4e20810e64\"],\"sampling\":1,\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Events\"},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":13,\"w\":48,\"h\":13,\"i\":\"edc2487b-0a85-4975-b841-457471ee5cd0\"},\"panelIndex\":\"edc2487b-0a85-4975-b841-457471ee5cd0\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-f001be29-b6cc-4c99-8aae-5941a7f9a8ee\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"5f8c9137-f9b6-4074-ba6c-9fa777b6afdf\"},{\"columnId\":\"4a2c3535-ba05-42d2-8dbb-5218d3309ea6\",\"isTransposed\":false},{\"isTransposed\":false,\"columnId\":\"72a21fae-312d-4cbb-8a94-fa24d4b29933\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"884cc56d-feb1-40dd-89a9-e006ec72dd85\"},{\"columnId\":\"6bb85b4f-0834-416d-8ade-49d83caac7ee\",\"isTransposed\":false,\"oneClickFilter\":false},{\"isTransposed\":false,\"columnId\":\"b3369c71-8edb-4569-89df-883f23ea2785\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"233f059c-ccd6-4a64-a6be-4961a3c4d500\",\"hidden\":true,\"colorMode\":\"none\"}],\"layerId\":\"f001be29-b6cc-4c99-8aae-5941a7f9a8ee\",\"layerType\":\"data\",\"headerRowHeight\":\"custom\",\"headerRowHeightLines\":2,\"rowHeight\":\"custom\",\"rowHeightLines\":2,\"paging\":{\"size\":10,\"enabled\":true}},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"f001be29-b6cc-4c99-8aae-5941a7f9a8ee\":{\"columns\":{\"5f8c9137-f9b6-4074-ba6c-9fa777b6afdf\":{\"label\":\"rule.groups\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.groups\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"233f059c-ccd6-4a64-a6be-4961a3c4d500\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"4a2c3535-ba05-42d2-8dbb-5218d3309ea6\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"72a21fae-312d-4cbb-8a94-fa24d4b29933\":{\"label\":\"agent.name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"agent.name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"233f059c-ccd6-4a64-a6be-4961a3c4d500\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"884cc56d-feb1-40dd-89a9-e006ec72dd85\":{\"label\":\"rule.description\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.description\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"233f059c-ccd6-4a64-a6be-4961a3c4d500\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"6bb85b4f-0834-416d-8ade-49d83caac7ee\":{\"label\":\"rule.level\",\"dataType\":\"number\",\"operationType\":\"range\",\"sourceField\":\"rule.level\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"includeEmptyRows\":true,\"type\":\"histogram\",\"ranges\":[{\"from\":0,\"to\":1000,\"label\":\"\"}],\"maxBars\":\"auto\"}},\"b3369c71-8edb-4569-89df-883f23ea2785\":{\"label\":\"rule.id\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.id\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"233f059c-ccd6-4a64-a6be-4961a3c4d500\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"233f059c-ccd6-4a64-a6be-4961a3c4d500\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"4a2c3535-ba05-42d2-8dbb-5218d3309ea6\",\"72a21fae-312d-4cbb-8a94-fa24d4b29933\",\"5f8c9137-f9b6-4074-ba6c-9fa777b6afdf\",\"884cc56d-feb1-40dd-89a9-e006ec72dd85\",\"6bb85b4f-0834-416d-8ade-49d83caac7ee\",\"b3369c71-8edb-4569-89df-883f23ea2785\",\"233f059c-ccd6-4a64-a6be-4961a3c4d500\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":true},\"title\":\"Security alerts\"}]","timeRestore":false,"title":"Incident response","version":1},"coreMigrationVersion":"8.6.0","created_at":"2023-02-10T14:08:55.451Z","id":"e30257a0-a641-11ed-8b0e-91d62e747cc9","migrationVersion":{"dashboard":"8.6.0"},"references":[{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"caf3fb07-a3b0-4f51-b000-926f4b26ee4f:indexpattern-datasource-layer-3ef3cbb5-abf3-4697-9e38-f4cf60bcdd5d","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"115417e6-11a1-4a55-8055-220b69dad98e:indexpattern-datasource-layer-54e72470-df75-47d1-a7a6-3d2f807a39d1","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"edc2487b-0a85-4975-b841-457471ee5cd0:indexpattern-datasource-layer-f001be29-b6cc-4c99-8aae-5941a7f9a8ee","type":"index-pattern"}],"type":"dashboard","updated_at":"2023-02-10T14:08:55.451Z","version":"WzQwMTQxLDNd"}
+{"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":2,"missingRefCount":0,"missingReferences":[]}
\ No newline at end of file
diff --git a/public/panels/elastic-with-sample-data/malware-detection.ndjson b/public/panels/elastic-with-sample-data/malware-detection.ndjson
new file mode 100644
index 0000000000..ecd13894f5
--- /dev/null
+++ b/public/panels/elastic-with-sample-data/malware-detection.ndjson
@@ -0,0 +1,3 @@
+{"attributes":{"fieldAttrs":"{}","fieldFormatMap":"{}","fields":"[]","name":"wazuh-alerts-4.x-dashboards","runtimeFieldMap":"{}","sourceFilters":"[]","timeFieldName":"timestamp","title":"wazuh-alerts-4.x-dashboards","typeMeta":"{}"},"coreMigrationVersion":"8.6.0","created_at":"2023-02-01T14:22:22.164Z","id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","migrationVersion":{"index-pattern":"8.0.0"},"references":[],"type":"index-pattern","updated_at":"2023-02-01T14:22:22.164Z","version":"WzEwNDksMV0="}
+{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"optionsJSON":"{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}","panelsJSON":"[{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":18,\"h\":13,\"i\":\"847a1b06-c15d-41a2-9a08-73b056e959fb\"},\"panelIndex\":\"847a1b06-c15d-41a2-9a08-73b056e959fb\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-0c3e7889-e551-4507-bb13-1a4ff7d96f96\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"curveType\":\"LINEAR\",\"fillOpacity\":1,\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"area_stacked\",\"layers\":[{\"layerId\":\"0c3e7889-e551-4507-bb13-1a4ff7d96f96\",\"accessors\":[\"9b7ab5ea-5a4d-4fc1-a493-861ed613bfdb\"],\"position\":\"top\",\"seriesType\":\"area_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"f4e6f4ad-fca2-4012-9dc4-a34df1d4a5ec\",\"yConfig\":[{\"forAccessor\":\"9b7ab5ea-5a4d-4fc1-a493-861ed613bfdb\",\"color\":\"#40d4e0\"}]}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"0c3e7889-e551-4507-bb13-1a4ff7d96f96\":{\"columns\":{\"f4e6f4ad-fca2-4012-9dc4-a34df1d4a5ec\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"9b7ab5ea-5a4d-4fc1-a493-861ed613bfdb\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"filter\":{\"query\":\"rule.groups : \\\"rootcheck\\\" \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"f4e6f4ad-fca2-4012-9dc4-a34df1d4a5ec\",\"9b7ab5ea-5a4d-4fc1-a493-861ed613bfdb\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Emotet malware activity\"},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":18,\"y\":0,\"w\":30,\"h\":13,\"i\":\"cc5ad74e-c871-4ac3-9487-328adc286921\"},\"panelIndex\":\"cc5ad74e-c871-4ac3-9487-328adc286921\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-5ccb00b3-1675-4c9f-a542-927c5930e66e\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"line\",\"layers\":[{\"layerId\":\"5ccb00b3-1675-4c9f-a542-927c5930e66e\",\"accessors\":[\"f001735e-ca2b-455d-a50a-b7f44b005f0b\"],\"position\":\"top\",\"seriesType\":\"line\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"b662da8a-50ee-4dae-a2bb-25861753d95c\",\"splitAccessor\":\"52edc505-8c8a-4965-a3f3-46ca861738af\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"5ccb00b3-1675-4c9f-a542-927c5930e66e\":{\"columns\":{\"52edc505-8c8a-4965-a3f3-46ca861738af\":{\"label\":\"Top 5 values of data.title\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.title\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f001735e-ca2b-455d-a50a-b7f44b005f0b\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]}},\"b662da8a-50ee-4dae-a2bb-25861753d95c\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"f001735e-ca2b-455d-a50a-b7f44b005f0b\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"filter\":{\"query\":\"rule.groups : \\\"rootcheck\\\" \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true}}},\"columnOrder\":[\"52edc505-8c8a-4965-a3f3-46ca861738af\",\"b662da8a-50ee-4dae-a2bb-25861753d95c\",\"f001735e-ca2b-455d-a50a-b7f44b005f0b\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Rootkits activity over time\"},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":13,\"w\":48,\"h\":21,\"i\":\"e3873842-502a-4ba4-a3ab-d5bcdc9d908c\"},\"panelIndex\":\"e3873842-502a-4ba4-a3ab-d5bcdc9d908c\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-777017d9-58d0-4f3f-8461-64af784d41a4\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"56e30fec-0d21-4af5-9751-7630c08713e8\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"94ca03f4-c063-4be7-b4c1-007c8a6d271a\"},{\"isTransposed\":false,\"columnId\":\"1169cee0-a32f-48d2-8e12-2919736d710a\"},{\"isTransposed\":false,\"columnId\":\"23107287-fb86-49ea-bdea-79d55b5e7ea4\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"125edb0b-de81-41b8-9612-1d87188e2b12\"},{\"isTransposed\":false,\"columnId\":\"a1caa30b-78e1-493d-bb05-f29242d47609\",\"hidden\":true},{\"columnId\":\"694278f2-f767-4450-90f5-4a95905e989f\",\"isTransposed\":false},{\"columnId\":\"1073b1b6-aa33-4e11-841b-0b6459a56603\",\"isTransposed\":false}],\"layerId\":\"777017d9-58d0-4f3f-8461-64af784d41a4\",\"layerType\":\"data\",\"headerRowHeight\":\"custom\",\"headerRowHeightLines\":2,\"rowHeight\":\"custom\",\"rowHeightLines\":2,\"paging\":{\"size\":10,\"enabled\":true}},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"777017d9-58d0-4f3f-8461-64af784d41a4\":{\"columns\":{\"56e30fec-0d21-4af5-9751-7630c08713e8\":{\"label\":\"agent.name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"agent.name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"a1caa30b-78e1-493d-bb05-f29242d47609\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"94ca03f4-c063-4be7-b4c1-007c8a6d271a\":{\"label\":\"rule.mitre.technique\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.mitre.technique\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"a1caa30b-78e1-493d-bb05-f29242d47609\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"1169cee0-a32f-48d2-8e12-2919736d710a\":{\"label\":\"rule.mitre.tactic\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.mitre.tactic\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"a1caa30b-78e1-493d-bb05-f29242d47609\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"23107287-fb86-49ea-bdea-79d55b5e7ea4\":{\"label\":\"rule.id\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.id\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"a1caa30b-78e1-493d-bb05-f29242d47609\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"125edb0b-de81-41b8-9612-1d87188e2b12\":{\"label\":\"rule.description\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.description\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"a1caa30b-78e1-493d-bb05-f29242d47609\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"a1caa30b-78e1-493d-bb05-f29242d47609\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"filter\":{\"query\":\"rule.groups : \\\"rootcheck\\\" \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"694278f2-f767-4450-90f5-4a95905e989f\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"1073b1b6-aa33-4e11-841b-0b6459a56603\":{\"label\":\"rule.level\",\"dataType\":\"number\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.level\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"a1caa30b-78e1-493d-bb05-f29242d47609\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true}},\"columnOrder\":[\"694278f2-f767-4450-90f5-4a95905e989f\",\"56e30fec-0d21-4af5-9751-7630c08713e8\",\"94ca03f4-c063-4be7-b4c1-007c8a6d271a\",\"1169cee0-a32f-48d2-8e12-2919736d710a\",\"1073b1b6-aa33-4e11-841b-0b6459a56603\",\"23107287-fb86-49ea-bdea-79d55b5e7ea4\",\"125edb0b-de81-41b8-9612-1d87188e2b12\",\"a1caa30b-78e1-493d-bb05-f29242d47609\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Security alerts\"}]","timeRestore":false,"title":"Malware Detection","version":1},"coreMigrationVersion":"8.6.0","created_at":"2023-02-10T14:10:08.648Z","id":"f9bb41b0-a3cf-11ed-9187-5147a2b9eedf","migrationVersion":{"dashboard":"8.6.0"},"references":[{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"847a1b06-c15d-41a2-9a08-73b056e959fb:indexpattern-datasource-layer-0c3e7889-e551-4507-bb13-1a4ff7d96f96","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"cc5ad74e-c871-4ac3-9487-328adc286921:indexpattern-datasource-layer-5ccb00b3-1675-4c9f-a542-927c5930e66e","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"e3873842-502a-4ba4-a3ab-d5bcdc9d908c:indexpattern-datasource-layer-777017d9-58d0-4f3f-8461-64af784d41a4","type":"index-pattern"}],"type":"dashboard","updated_at":"2023-02-10T14:10:08.648Z","version":"WzQwMTkzLDNd"}
+{"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":2,"missingRefCount":0,"missingReferences":[]}
\ No newline at end of file
diff --git a/public/panels/elastic-with-sample-data/pci-dss.ndjson b/public/panels/elastic-with-sample-data/pci-dss.ndjson
new file mode 100644
index 0000000000..1e48a939f6
--- /dev/null
+++ b/public/panels/elastic-with-sample-data/pci-dss.ndjson
@@ -0,0 +1,3 @@
+{"attributes":{"fieldAttrs":"{}","fieldFormatMap":"{}","fields":"[]","name":"wazuh-alerts-4.x-dashboards","runtimeFieldMap":"{}","sourceFilters":"[]","timeFieldName":"timestamp","title":"wazuh-alerts-4.x-dashboards","typeMeta":"{}"},"coreMigrationVersion":"8.6.0","created_at":"2023-02-01T14:22:22.164Z","id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","migrationVersion":{"index-pattern":"8.0.0"},"references":[],"type":"index-pattern","updated_at":"2023-02-01T14:22:22.164Z","version":"WzEwNDksMV0="}
+{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"optionsJSON":"{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}","panelsJSON":"[{\"version\":\"8.6.0\",\"type\":\"visualization\",\"gridData\":{\"x\":0,\"y\":0,\"w\":29,\"h\":15,\"i\":\"976e6302-500a-427c-bd29-75cee9034fe6\"},\"panelIndex\":\"976e6302-500a-427c-bd29-75cee9034fe6\",\"embeddableConfig\":{\"savedVis\":{\"id\":\"\",\"title\":\"PCI DSS requirements\",\"description\":\"\",\"type\":\"line\",\"params\":{\"type\":\"line\",\"grid\":{\"categoryLines\":false,\"valueAxis\":\"\"},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"filter\":true,\"truncate\":100},\"title\":{},\"style\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":true,\"truncate\":100},\"title\":{\"text\":\"\"},\"style\":{}}],\"seriesParams\":[{\"show\":true,\"type\":\"line\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"drawLinesBetweenPoints\":true,\"lineWidth\":0,\"showCircles\":true,\"circlesRadius\":10,\"interpolate\":\"linear\",\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"detailedTooltip\":true,\"palette\":{\"type\":\"palette\",\"name\":\"default\"},\"addLegend\":true,\"legendPosition\":\"right\",\"fittingFunction\":\"linear\",\"times\":[],\"addTimeMarker\":false,\"truncateLegend\":true,\"maxLegendLines\":1,\"radiusRatio\":9,\"thresholdLine\":{\"show\":false,\"value\":10,\"width\":1,\"style\":\"full\",\"color\":\"#E7664C\"},\"labels\":{}},\"uiState\":{},\"data\":{\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"params\":{\"emptyAsNull\":false},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"params\":{\"field\":\"timestamp\",\"timeRange\":{\"from\":\"now-10w\",\"to\":\"now\"},\"useNormalizedEsInterval\":true,\"extendToTimeRange\":false,\"scaleMetricValues\":false,\"interval\":\"auto\",\"used_interval\":\"1d\",\"drop_partials\":false,\"min_doc_count\":1,\"extended_bounds\":{}},\"schema\":\"segment\"},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"rule.pci_dss\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":5,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"includeIsRegex\":true,\"excludeIsRegex\":true},\"schema\":\"group\"}],\"searchSource\":{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}}},\"enhancements\":{}}},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":29,\"y\":0,\"w\":19,\"h\":15,\"i\":\"d299d776-0b4f-4955-b7d6-5717119dba59\"},\"panelIndex\":\"d299d776-0b4f-4955-b7d6-5717119dba59\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-c85ec231-a4fc-495d-b8d6-1aad7dc1e489\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"c85ec231-a4fc-495d-b8d6-1aad7dc1e489\",\"accessors\":[\"0ca7b7c5-03fd-401d-bd44-201d8ca00b25\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"e17436ee-06c3-4b4e-acda-f8d379648407\",\"splitAccessor\":\"852bf376-24f0-4b54-8568-0964c3289eb4\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"c85ec231-a4fc-495d-b8d6-1aad7dc1e489\":{\"columns\":{\"e17436ee-06c3-4b4e-acda-f8d379648407\":{\"label\":\"Requirements\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.pci_dss\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"0ca7b7c5-03fd-401d-bd44-201d8ca00b25\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"0ca7b7c5-03fd-401d-bd44-201d8ca00b25\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"852bf376-24f0-4b54-8568-0964c3289eb4\":{\"label\":\"Top 5 values of agent.name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"agent.name\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"0ca7b7c5-03fd-401d-bd44-201d8ca00b25\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false}}},\"columnOrder\":[\"e17436ee-06c3-4b4e-acda-f8d379648407\",\"852bf376-24f0-4b54-8568-0964c3289eb4\",\"0ca7b7c5-03fd-401d-bd44-201d8ca00b25\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Requirements by agent\"},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":15,\"w\":48,\"h\":17,\"i\":\"f3674cc2-b4c6-44e1-baa9-6dcb9b932a01\"},\"panelIndex\":\"f3674cc2-b4c6-44e1-baa9-6dcb9b932a01\",\"embeddableConfig\":{\"attributes\":{\"title\":\"PCI DSS\",\"description\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-951964d6-a0d3-4593-911f-b598f1bdd7a6\"}],\"state\":{\"visualization\":{\"layerId\":\"951964d6-a0d3-4593-911f-b598f1bdd7a6\",\"layerType\":\"data\",\"columns\":[{\"isTransposed\":false,\"columnId\":\"27ae8c68-e64e-4824-9422-df1611b74c58\"},{\"isTransposed\":false,\"columnId\":\"30508bd4-917e-4614-9922-c445af8e8a8f\"},{\"isTransposed\":false,\"columnId\":\"7044d45a-dce5-4fbe-8af4-64a9b1e14840\"},{\"isTransposed\":false,\"columnId\":\"49885e99-2da3-4165-9b20-9d78ccaca4bd\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"df70835d-3cfb-4ead-a942-d60c00330c30\"},{\"columnId\":\"f7cf15d8-617e-4a52-bdc2-6b94a9c722ad\",\"isTransposed\":false,\"hidden\":true},{\"columnId\":\"f96a237b-410c-475c-863e-60acde29fc71\",\"isTransposed\":false,\"oneClickFilter\":true}],\"paging\":{\"size\":10,\"enabled\":true}},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"951964d6-a0d3-4593-911f-b598f1bdd7a6\":{\"columns\":{\"27ae8c68-e64e-4824-9422-df1611b74c58\":{\"label\":\"rule.description\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.description\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f7cf15d8-617e-4a52-bdc2-6b94a9c722ad\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"30508bd4-917e-4614-9922-c445af8e8a8f\":{\"label\":\"rule.level\",\"dataType\":\"number\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.level\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f7cf15d8-617e-4a52-bdc2-6b94a9c722ad\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"7044d45a-dce5-4fbe-8af4-64a9b1e14840\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"49885e99-2da3-4165-9b20-9d78ccaca4bd\":{\"label\":\"agent.name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"agent.name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f7cf15d8-617e-4a52-bdc2-6b94a9c722ad\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"df70835d-3cfb-4ead-a942-d60c00330c30\":{\"label\":\"rule.pci_dss\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.pci_dss\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f7cf15d8-617e-4a52-bdc2-6b94a9c722ad\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"f7cf15d8-617e-4a52-bdc2-6b94a9c722ad\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}},\"f96a237b-410c-475c-863e-60acde29fc71\":{\"label\":\"rule.id\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.id\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"f7cf15d8-617e-4a52-bdc2-6b94a9c722ad\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true}},\"columnOrder\":[\"7044d45a-dce5-4fbe-8af4-64a9b1e14840\",\"49885e99-2da3-4165-9b20-9d78ccaca4bd\",\"df70835d-3cfb-4ead-a942-d60c00330c30\",\"27ae8c68-e64e-4824-9422-df1611b74c58\",\"30508bd4-917e-4614-9922-c445af8e8a8f\",\"f96a237b-410c-475c-863e-60acde29fc71\",\"f7cf15d8-617e-4a52-bdc2-6b94a9c722ad\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Recent events\"}]","timeRestore":false,"title":"PCI DSS","version":1},"coreMigrationVersion":"8.6.0","created_at":"2023-02-10T17:26:37.119Z","id":"ad09bc40-a634-11ed-8b0e-91d62e747cc9","migrationVersion":{"dashboard":"8.6.0"},"references":[{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"976e6302-500a-427c-bd29-75cee9034fe6:kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"d299d776-0b4f-4955-b7d6-5717119dba59:indexpattern-datasource-layer-c85ec231-a4fc-495d-b8d6-1aad7dc1e489","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"f3674cc2-b4c6-44e1-baa9-6dcb9b932a01:indexpattern-datasource-layer-951964d6-a0d3-4593-911f-b598f1bdd7a6","type":"index-pattern"}],"type":"dashboard","updated_at":"2023-02-10T17:26:37.119Z","version":"WzQxOTk2LDNd"}
+{"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":2,"missingRefCount":0,"missingReferences":[]}
\ No newline at end of file
diff --git a/public/panels/elastic-with-sample-data/security-events.ndjson b/public/panels/elastic-with-sample-data/security-events.ndjson
new file mode 100644
index 0000000000..3ea7f39d27
--- /dev/null
+++ b/public/panels/elastic-with-sample-data/security-events.ndjson
@@ -0,0 +1,3 @@
+{"attributes":{"fieldAttrs":"{}","fieldFormatMap":"{}","fields":"[]","name":"wazuh-alerts-4.x-dashboards","runtimeFieldMap":"{}","sourceFilters":"[]","timeFieldName":"timestamp","title":"wazuh-alerts-4.x-dashboards","typeMeta":"{}"},"coreMigrationVersion":"8.6.0","created_at":"2023-02-01T14:22:22.164Z","id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","migrationVersion":{"index-pattern":"8.0.0"},"references":[],"type":"index-pattern","updated_at":"2023-02-01T14:22:22.164Z","version":"WzEwNDksMV0="}
+{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"optionsJSON":"{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}","panelsJSON":"[{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":8,\"y\":0,\"w\":8,\"h\":5,\"i\":\"c90b5ced-c476-4336-8248-5f5eee09b7d3\"},\"panelIndex\":\"c90b5ced-c476-4336-8248-5f5eee09b7d3\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-f7d51ed1-e2c7-4eff-a2f0-426523a27b79\"}],\"state\":{\"visualization\":{\"layerId\":\"f7d51ed1-e2c7-4eff-a2f0-426523a27b79\",\"accessor\":\"bba216ab-0609-4fc7-9f00-3f95df7bd9e5\",\"layerType\":\"data\",\"textAlign\":\"center\",\"colorMode\":\"Labels\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":3,\"name\":\"custom\",\"reverse\":false,\"rangeType\":\"number\",\"rangeMin\":null,\"rangeMax\":null,\"progression\":\"fixed\",\"stops\":[{\"color\":\"#1E75B6\",\"stop\":300}],\"colorStops\":[{\"color\":\"#1E75B6\",\"stop\":null}],\"continuity\":\"all\",\"maxSteps\":5}},\"size\":\"xxl\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"f7d51ed1-e2c7-4eff-a2f0-426523a27b79\":{\"columns\":{\"bba216ab-0609-4fc7-9f00-3f95df7bd9e5\":{\"label\":\"Total\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"bba216ab-0609-4fc7-9f00-3f95df7bd9e5\"],\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{}}},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":16,\"y\":0,\"w\":8,\"h\":5,\"i\":\"dc864252-a518-4187-80ca-b581ad14f1cb\"},\"panelIndex\":\"dc864252-a518-4187-80ca-b581ad14f1cb\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-a63a4df1-6335-4d1e-a8fb-44d550e0513b\"},{\"type\":\"index-pattern\",\"name\":\"4cd727d8-200d-4869-b702-ff540bd3ff56\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\"}],\"state\":{\"visualization\":{\"layerId\":\"a63a4df1-6335-4d1e-a8fb-44d550e0513b\",\"accessor\":\"65d5d9ac-208b-4393-b498-12f4351445bd\",\"layerType\":\"data\",\"colorMode\":\"Labels\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":3,\"name\":\"custom\",\"reverse\":false,\"rangeType\":\"number\",\"rangeMin\":null,\"rangeMax\":null,\"progression\":\"fixed\",\"stops\":[{\"color\":\"#e57488\",\"stop\":8}],\"colorStops\":[{\"color\":\"#e57488\",\"stop\":null}],\"continuity\":\"all\",\"maxSteps\":5}},\"textAlign\":\"center\",\"size\":\"xxl\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[{\"meta\":{\"index\":\"4cd727d8-200d-4869-b702-ff540bd3ff56\",\"alias\":\"rule.level >= 12\",\"type\":\"custom\",\"key\":\"query\",\"value\":\"{\\\"bool\\\":{\\\"must\\\":[],\\\"filter\\\":[{\\\"bool\\\":{\\\"should\\\":[{\\\"range\\\":{\\\"rule.level\\\":{\\\"gte\\\":\\\"12\\\"}}}],\\\"minimum_should_match\\\":1}}],\\\"should\\\":[],\\\"must_not\\\":[]}}\",\"disabled\":false,\"negate\":false},\"query\":{\"bool\":{\"must\":[],\"filter\":[{\"bool\":{\"should\":[{\"range\":{\"rule.level\":{\"gte\":\"12\"}}}],\"minimum_should_match\":1}}],\"should\":[],\"must_not\":[]}},\"$state\":{\"store\":\"appState\"}}],\"datasourceStates\":{\"formBased\":{\"layers\":{\"a63a4df1-6335-4d1e-a8fb-44d550e0513b\":{\"columns\":{\"65d5d9ac-208b-4393-b498-12f4351445bd\":{\"label\":\"Level 12 or above alerts\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"filter\":{\"query\":\"rule.level >= 12\",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"65d5d9ac-208b-4393-b498-12f4351445bd\"],\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{}}},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":24,\"y\":0,\"w\":8,\"h\":5,\"i\":\"4bab10c4-2a6d-4f8f-8094-323581c98950\"},\"panelIndex\":\"4bab10c4-2a6d-4f8f-8094-323581c98950\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-28318134-b7bd-4faa-b21e-b0a6665b526f\"},{\"type\":\"index-pattern\",\"name\":\"1b7728c2-28d0-40f9-81ed-74e77231242c\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\"}],\"state\":{\"visualization\":{\"layerId\":\"28318134-b7bd-4faa-b21e-b0a6665b526f\",\"accessor\":\"e1a6a50b-cffe-4c92-b756-bad658aee97d\",\"layerType\":\"data\",\"textAlign\":\"center\",\"colorMode\":\"Labels\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":3,\"name\":\"custom\",\"reverse\":false,\"rangeType\":\"number\",\"rangeMin\":null,\"rangeMax\":null,\"progression\":\"fixed\",\"stops\":[{\"color\":\"#d4458d\",\"stop\":4}],\"colorStops\":[{\"color\":\"#d4458d\",\"stop\":null}],\"continuity\":\"all\",\"maxSteps\":5}},\"size\":\"xxl\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[{\"meta\":{\"index\":\"1b7728c2-28d0-40f9-81ed-74e77231242c\",\"alias\":\"rule.groups : \\\"authentication_failed\\\" or \\\"win_authentication_failed\\\" or \\\"authentication_failures\\\"\",\"type\":\"custom\",\"key\":\"query\",\"value\":\"{\\\"bool\\\":{\\\"must\\\":[],\\\"filter\\\":[{\\\"bool\\\":{\\\"should\\\":[{\\\"bool\\\":{\\\"should\\\":[{\\\"term\\\":{\\\"rule.groups\\\":\\\"authentication_failed\\\"}}],\\\"minimum_should_match\\\":1}},{\\\"multi_match\\\":{\\\"type\\\":\\\"phrase\\\",\\\"query\\\":\\\"win_authentication_failed\\\",\\\"lenient\\\":true}},{\\\"multi_match\\\":{\\\"type\\\":\\\"phrase\\\",\\\"query\\\":\\\"authentication_failures\\\",\\\"lenient\\\":true}}],\\\"minimum_should_match\\\":1}}],\\\"should\\\":[],\\\"must_not\\\":[]}}\",\"disabled\":false,\"negate\":false},\"query\":{\"bool\":{\"must\":[],\"filter\":[{\"bool\":{\"should\":[{\"bool\":{\"should\":[{\"term\":{\"rule.groups\":\"authentication_failed\"}}],\"minimum_should_match\":1}},{\"multi_match\":{\"type\":\"phrase\",\"query\":\"win_authentication_failed\",\"lenient\":true}},{\"multi_match\":{\"type\":\"phrase\",\"query\":\"authentication_failures\",\"lenient\":true}}],\"minimum_should_match\":1}}],\"should\":[],\"must_not\":[]}},\"$state\":{\"store\":\"appState\"}}],\"datasourceStates\":{\"formBased\":{\"layers\":{\"28318134-b7bd-4faa-b21e-b0a6665b526f\":{\"columns\":{\"e1a6a50b-cffe-4c92-b756-bad658aee97d\":{\"label\":\"Athentication failure\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"rule.groups\",\"isBucketed\":false,\"filter\":{\"query\":\"rule.groups : \\\"authentication_failed\\\" or \\\"win_authentication_failed\\\" or \\\"authentication_failures\\\"\",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"e1a6a50b-cffe-4c92-b756-bad658aee97d\"],\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{}}},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":32,\"y\":0,\"w\":8,\"h\":5,\"i\":\"3cc5e7d4-2f44-438e-8529-6dfae4e29b16\"},\"panelIndex\":\"3cc5e7d4-2f44-438e-8529-6dfae4e29b16\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-67c3da39-aad2-4ff4-812f-15cf135b2d12\"},{\"type\":\"index-pattern\",\"name\":\"933a08d4-fd4c-4829-938c-df17bc87af15\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\"}],\"state\":{\"visualization\":{\"layerId\":\"67c3da39-aad2-4ff4-812f-15cf135b2d12\",\"accessor\":\"ea00d671-3e3a-434a-8813-1dfa3a023112\",\"layerType\":\"data\",\"textAlign\":\"center\",\"colorMode\":\"Labels\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":3,\"name\":\"custom\",\"reverse\":false,\"rangeType\":\"number\",\"rangeMin\":null,\"rangeMax\":null,\"progression\":\"fixed\",\"stops\":[{\"color\":\"#1a938a\",\"stop\":2}],\"colorStops\":[{\"color\":\"#1a938a\",\"stop\":null}],\"continuity\":\"all\",\"maxSteps\":5}},\"size\":\"xxl\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[{\"meta\":{\"index\":\"933a08d4-fd4c-4829-938c-df17bc87af15\",\"type\":\"exists\",\"key\":\"rule.groups\",\"value\":\"exists\",\"disabled\":false,\"negate\":false,\"alias\":null},\"query\":{\"exists\":{\"field\":\"rule.groups\"}},\"$state\":{\"store\":\"appState\"}}],\"datasourceStates\":{\"formBased\":{\"layers\":{\"67c3da39-aad2-4ff4-812f-15cf135b2d12\":{\"columns\":{\"ea00d671-3e3a-434a-8813-1dfa3a023112\":{\"label\":\"Authentication success\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"rule.groups\",\"isBucketed\":false,\"filter\":{\"query\":\"rule.groups: \\\"authentication_success\\\" \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"ea00d671-3e3a-434a-8813-1dfa3a023112\"],\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{}}},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":5,\"w\":32,\"h\":14,\"i\":\"fc1f8b94-2637-4f4d-a998-f6a59c6b9e7e\"},\"panelIndex\":\"fc1f8b94-2637-4f4d-a998-f6a59c6b9e7e\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-e8600050-5477-49a7-a28e-ce9a47ded5f5\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"e8600050-5477-49a7-a28e-ce9a47ded5f5\",\"accessors\":[\"8d76d731-1e09-4706-b3d9-48108dd7dd32\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"splitAccessor\":\"3f2d0dea-171c-41ed-9452-29106c10a968\",\"xAccessor\":\"c5296771-93c8-48cb-bf57-cad19d8c829e\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"e8600050-5477-49a7-a28e-ce9a47ded5f5\":{\"columns\":{\"8d76d731-1e09-4706-b3d9-48108dd7dd32\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"c5296771-93c8-48cb-bf57-cad19d8c829e\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":false,\"dropPartials\":false}},\"3f2d0dea-171c-41ed-9452-29106c10a968\":{\"label\":\"Top 5 values of agent.name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"agent.name\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"8d76d731-1e09-4706-b3d9-48108dd7dd32\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false}}},\"columnOrder\":[\"3f2d0dea-171c-41ed-9452-29106c10a968\",\"c5296771-93c8-48cb-bf57-cad19d8c829e\",\"8d76d731-1e09-4706-b3d9-48108dd7dd32\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Alerts evolution - Top 5 agents\"},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":32,\"y\":5,\"w\":16,\"h\":14,\"i\":\"e35f33d0-784d-471a-842e-576523d0ca80\"},\"panelIndex\":\"e35f33d0-784d-471a-842e-576523d0ca80\",\"embeddableConfig\":{\"attributes\":{\"title\":\"Top Mitre\",\"description\":\"\",\"visualizationType\":\"lnsPie\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-d2ef6c07-620f-431e-85f2-77175187e0fe\"}],\"state\":{\"visualization\":{\"shape\":\"pie\",\"layers\":[{\"layerId\":\"d2ef6c07-620f-431e-85f2-77175187e0fe\",\"primaryGroups\":[\"a676e778-cad9-431e-b520-3e87b3a0afb2\"],\"metrics\":[\"c2640e02-f544-4f25-a0a4-aaec8e9e2f47\"],\"numberDisplay\":\"percent\",\"categoryDisplay\":\"hide\",\"legendDisplay\":\"show\",\"nestedLegend\":false,\"layerType\":\"data\",\"emptySizeRatio\":0.3,\"legendSize\":\"xlarge\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"d2ef6c07-620f-431e-85f2-77175187e0fe\":{\"columns\":{\"a676e778-cad9-431e-b520-3e87b3a0afb2\":{\"label\":\"Top 5 values of rule.mitre.tactic\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.mitre.tactic\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"c2640e02-f544-4f25-a0a4-aaec8e9e2f47\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false}},\"c2640e02-f544-4f25-a0a4-aaec8e9e2f47\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}}},\"columnOrder\":[\"a676e778-cad9-431e-b520-3e87b3a0afb2\",\"c2640e02-f544-4f25-a0a4-aaec8e9e2f47\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Top Mitre ATT&K tactics\"},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":19,\"w\":48,\"h\":15,\"i\":\"ee6f5f4c-2a18-4733-a593-23c1f2a24376\"},\"panelIndex\":\"ee6f5f4c-2a18-4733-a593-23c1f2a24376\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-f001be29-b6cc-4c99-8aae-5941a7f9a8ee\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"72a21fae-312d-4cbb-8a94-fa24d4b29933\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"884cc56d-feb1-40dd-89a9-e006ec72dd85\"},{\"isTransposed\":false,\"columnId\":\"5333b889-bfc5-4e1a-a4e3-54828d1dd91b\"},{\"isTransposed\":false,\"columnId\":\"b3369c71-8edb-4569-89df-883f23ea2785\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"233f059c-ccd6-4a64-a6be-4961a3c4d500\",\"hidden\":true,\"colorMode\":\"none\"},{\"columnId\":\"6bb85b4f-0834-416d-8ade-49d83caac7ee\",\"isTransposed\":false,\"oneClickFilter\":false},{\"columnId\":\"4a2c3535-ba05-42d2-8dbb-5218d3309ea6\",\"isTransposed\":false},{\"columnId\":\"c74264a6-eb65-4232-9444-a503723c6fdf\",\"isTransposed\":false,\"oneClickFilter\":true}],\"layerId\":\"f001be29-b6cc-4c99-8aae-5941a7f9a8ee\",\"layerType\":\"data\",\"headerRowHeight\":\"custom\",\"headerRowHeightLines\":2,\"rowHeight\":\"custom\",\"rowHeightLines\":2,\"paging\":{\"size\":10,\"enabled\":true}},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"f001be29-b6cc-4c99-8aae-5941a7f9a8ee\":{\"columns\":{\"72a21fae-312d-4cbb-8a94-fa24d4b29933\":{\"label\":\"agent.name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"agent.name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"233f059c-ccd6-4a64-a6be-4961a3c4d500\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"884cc56d-feb1-40dd-89a9-e006ec72dd85\":{\"label\":\"rule.description\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.description\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"233f059c-ccd6-4a64-a6be-4961a3c4d500\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"5333b889-bfc5-4e1a-a4e3-54828d1dd91b\":{\"label\":\"rule.mitre.tactic\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.mitre.tactic\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"233f059c-ccd6-4a64-a6be-4961a3c4d500\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"b3369c71-8edb-4569-89df-883f23ea2785\":{\"label\":\"rule.id\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.id\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"233f059c-ccd6-4a64-a6be-4961a3c4d500\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"233f059c-ccd6-4a64-a6be-4961a3c4d500\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true},\"6bb85b4f-0834-416d-8ade-49d83caac7ee\":{\"label\":\"rule.level\",\"dataType\":\"number\",\"operationType\":\"range\",\"sourceField\":\"rule.level\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"includeEmptyRows\":true,\"type\":\"histogram\",\"ranges\":[{\"from\":0,\"to\":1000,\"label\":\"\"}],\"maxBars\":\"auto\"}},\"4a2c3535-ba05-42d2-8dbb-5218d3309ea6\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"c74264a6-eb65-4232-9444-a503723c6fdf\":{\"label\":\"rule.mitre.id\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.mitre.id\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"233f059c-ccd6-4a64-a6be-4961a3c4d500\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true}},\"columnOrder\":[\"4a2c3535-ba05-42d2-8dbb-5218d3309ea6\",\"72a21fae-312d-4cbb-8a94-fa24d4b29933\",\"c74264a6-eb65-4232-9444-a503723c6fdf\",\"5333b889-bfc5-4e1a-a4e3-54828d1dd91b\",\"884cc56d-feb1-40dd-89a9-e006ec72dd85\",\"6bb85b4f-0834-416d-8ade-49d83caac7ee\",\"b3369c71-8edb-4569-89df-883f23ea2785\",\"233f059c-ccd6-4a64-a6be-4961a3c4d500\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Security alerts\"}]","timeRestore":false,"title":"wazuh-security-events","version":1},"coreMigrationVersion":"8.6.0","created_at":"2023-02-10T17:27:35.461Z","id":"1002c610-a23f-11ed-9c45-1d7f2cbf4bd8","migrationVersion":{"dashboard":"8.6.0"},"references":[{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"c90b5ced-c476-4336-8248-5f5eee09b7d3:indexpattern-datasource-layer-f7d51ed1-e2c7-4eff-a2f0-426523a27b79","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"dc864252-a518-4187-80ca-b581ad14f1cb:indexpattern-datasource-layer-a63a4df1-6335-4d1e-a8fb-44d550e0513b","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"dc864252-a518-4187-80ca-b581ad14f1cb:4cd727d8-200d-4869-b702-ff540bd3ff56","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"4bab10c4-2a6d-4f8f-8094-323581c98950:indexpattern-datasource-layer-28318134-b7bd-4faa-b21e-b0a6665b526f","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"4bab10c4-2a6d-4f8f-8094-323581c98950:1b7728c2-28d0-40f9-81ed-74e77231242c","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"3cc5e7d4-2f44-438e-8529-6dfae4e29b16:indexpattern-datasource-layer-67c3da39-aad2-4ff4-812f-15cf135b2d12","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"3cc5e7d4-2f44-438e-8529-6dfae4e29b16:933a08d4-fd4c-4829-938c-df17bc87af15","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"fc1f8b94-2637-4f4d-a998-f6a59c6b9e7e:indexpattern-datasource-layer-e8600050-5477-49a7-a28e-ce9a47ded5f5","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"e35f33d0-784d-471a-842e-576523d0ca80:indexpattern-datasource-layer-d2ef6c07-620f-431e-85f2-77175187e0fe","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"ee6f5f4c-2a18-4733-a593-23c1f2a24376:indexpattern-datasource-layer-f001be29-b6cc-4c99-8aae-5941a7f9a8ee","type":"index-pattern"}],"type":"dashboard","updated_at":"2023-02-10T17:27:35.461Z","version":"WzQyMDc5LDNd"}
+{"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":2,"missingRefCount":0,"missingReferences":[]}
\ No newline at end of file
diff --git a/public/panels/elastic-with-sample-data/vulnerabilities.ndjson b/public/panels/elastic-with-sample-data/vulnerabilities.ndjson
new file mode 100644
index 0000000000..cbc4dfbbe7
--- /dev/null
+++ b/public/panels/elastic-with-sample-data/vulnerabilities.ndjson
@@ -0,0 +1,3 @@
+{"attributes":{"fieldAttrs":"{}","fieldFormatMap":"{}","fields":"[]","name":"wazuh-alerts-4.x-dashboards","runtimeFieldMap":"{}","sourceFilters":"[]","timeFieldName":"timestamp","title":"wazuh-alerts-4.x-dashboards","typeMeta":"{}"},"coreMigrationVersion":"8.6.0","created_at":"2023-02-01T14:22:22.164Z","id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","migrationVersion":{"index-pattern":"8.0.0"},"references":[],"type":"index-pattern","updated_at":"2023-02-01T14:22:22.164Z","version":"WzEwNDksMV0="}
+{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"optionsJSON":"{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}","panelsJSON":"[{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":7,\"y\":0,\"w\":8,\"h\":5,\"i\":\"9931cceb-51f1-4e47-bd26-491e7a624592\"},\"panelIndex\":\"9931cceb-51f1-4e47-bd26-491e7a624592\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-1dc5f9b1-9f0c-458b-98e6-e92708af5b9d\"},{\"type\":\"index-pattern\",\"name\":\"b9624937-542e-4ac9-9f09-ae532ade3311\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\"}],\"state\":{\"visualization\":{\"layerId\":\"1dc5f9b1-9f0c-458b-98e6-e92708af5b9d\",\"accessor\":\"df19010a-26e5-446d-9d74-56fe2495e38b\",\"layerType\":\"data\",\"textAlign\":\"center\",\"size\":\"xxl\",\"colorMode\":\"Labels\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":3,\"name\":\"custom\",\"reverse\":false,\"rangeType\":\"number\",\"rangeMin\":null,\"rangeMax\":null,\"progression\":\"fixed\",\"stops\":[{\"color\":\"#db5871\",\"stop\":2}],\"colorStops\":[{\"color\":\"#db5871\",\"stop\":null}],\"continuity\":\"all\",\"maxSteps\":5}}},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[{\"meta\":{\"index\":\"b9624937-542e-4ac9-9f09-ae532ade3311\",\"type\":\"exists\",\"key\":\"data.vulnerability.severity\",\"value\":\"exists\",\"disabled\":false,\"negate\":false,\"alias\":null},\"query\":{\"exists\":{\"field\":\"data.vulnerability.severity\"}},\"$state\":{\"store\":\"appState\"}}],\"datasourceStates\":{\"formBased\":{\"layers\":{\"1dc5f9b1-9f0c-458b-98e6-e92708af5b9d\":{\"columns\":{\"df19010a-26e5-446d-9d74-56fe2495e38b\":{\"label\":\"Critical Severity Alerts\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"data.vulnerability.severity\",\"isBucketed\":false,\"filter\":{\"query\":\"data.vulnerability.severity : \\\"Critical\\\" \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"df19010a-26e5-446d-9d74-56fe2495e38b\"],\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{}}},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":15,\"y\":0,\"w\":8,\"h\":5,\"i\":\"a0b05cdd-c4b5-46b0-af2e-32253bd965e6\"},\"panelIndex\":\"a0b05cdd-c4b5-46b0-af2e-32253bd965e6\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-fd6049b6-e52c-449e-9775-ded5ac1eac15\"}],\"state\":{\"visualization\":{\"layerId\":\"fd6049b6-e52c-449e-9775-ded5ac1eac15\",\"accessor\":\"2ce8bbeb-74d7-4e28-b616-6edd33c1f981\",\"layerType\":\"data\",\"textAlign\":\"center\",\"size\":\"xxl\",\"colorMode\":\"Labels\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":3,\"name\":\"custom\",\"reverse\":false,\"rangeType\":\"number\",\"rangeMin\":null,\"rangeMax\":null,\"progression\":\"fixed\",\"stops\":[{\"color\":\"#0c5da3\",\"stop\":2}],\"colorStops\":[{\"color\":\"#0c5da3\",\"stop\":null}],\"continuity\":\"all\",\"maxSteps\":5}}},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"fd6049b6-e52c-449e-9775-ded5ac1eac15\":{\"columns\":{\"2ce8bbeb-74d7-4e28-b616-6edd33c1f981\":{\"label\":\"Hight Severity Alerts\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"data.vulnerability.severity\",\"isBucketed\":false,\"filter\":{\"query\":\"data.vulnerability.severity : \\\"High\\\" \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"2ce8bbeb-74d7-4e28-b616-6edd33c1f981\"],\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{}}},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":23,\"y\":0,\"w\":9,\"h\":5,\"i\":\"b22f2aba-370b-40f2-8f30-c7175fd21d84\"},\"panelIndex\":\"b22f2aba-370b-40f2-8f30-c7175fd21d84\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-a8774fa0-5ae6-4746-94bd-cd21a0210641\"}],\"state\":{\"visualization\":{\"layerId\":\"a8774fa0-5ae6-4746-94bd-cd21a0210641\",\"accessor\":\"b7764bb5-540b-4183-a8c5-e9e856e48949\",\"layerType\":\"data\",\"colorMode\":\"Labels\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":3,\"name\":\"custom\",\"reverse\":false,\"rangeType\":\"number\",\"rangeMin\":null,\"rangeMax\":null,\"progression\":\"fixed\",\"stops\":[{\"color\":\"#007d73\",\"stop\":2}],\"colorStops\":[{\"color\":\"#007d73\",\"stop\":null}],\"continuity\":\"all\",\"maxSteps\":5}},\"textAlign\":\"center\",\"size\":\"xxl\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"a8774fa0-5ae6-4746-94bd-cd21a0210641\":{\"columns\":{\"b7764bb5-540b-4183-a8c5-e9e856e48949\":{\"label\":\"Medium Severity Alerts\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"data.vulnerability.severity\",\"isBucketed\":false,\"filter\":{\"query\":\"data.vulnerability.severity : \\\"Medium\\\" \",\"language\":\"kuery\"},\"reducedTimeRange\":\"\",\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"b7764bb5-540b-4183-a8c5-e9e856e48949\"],\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{}}},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":32,\"y\":0,\"w\":9,\"h\":5,\"i\":\"dad9436c-6a56-47cc-a52a-065c86d64c7f\"},\"panelIndex\":\"dad9436c-6a56-47cc-a52a-065c86d64c7f\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsLegacyMetric\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-a397e361-0b6a-4d18-b957-2afce890f6c3\"},{\"type\":\"index-pattern\",\"name\":\"a532bc3a-2caf-4353-9a37-17d4fb373b0d\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\"}],\"state\":{\"visualization\":{\"layerId\":\"a397e361-0b6a-4d18-b957-2afce890f6c3\",\"accessor\":\"c0f27509-4ce0-4eca-94c5-e1eddfc176e9\",\"layerType\":\"data\",\"colorMode\":\"Labels\",\"palette\":{\"name\":\"custom\",\"type\":\"palette\",\"params\":{\"steps\":3,\"name\":\"custom\",\"reverse\":false,\"rangeType\":\"number\",\"rangeMin\":null,\"rangeMax\":null,\"progression\":\"fixed\",\"stops\":[{\"color\":\"#222222\",\"stop\":2}],\"colorStops\":[{\"color\":\"#222222\",\"stop\":null}],\"continuity\":\"all\",\"maxSteps\":5}},\"textAlign\":\"center\",\"size\":\"xxl\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[{\"meta\":{\"index\":\"a532bc3a-2caf-4353-9a37-17d4fb373b0d\",\"alias\":\"data.vulnerability.severity : \\\"Low\\\" \",\"type\":\"custom\",\"key\":\"query\",\"value\":\"{\\\"bool\\\":{\\\"must\\\":[],\\\"filter\\\":[{\\\"bool\\\":{\\\"should\\\":[{\\\"term\\\":{\\\"data.vulnerability.severity\\\":\\\"Low\\\"}}],\\\"minimum_should_match\\\":1}}],\\\"should\\\":[],\\\"must_not\\\":[]}}\",\"disabled\":false,\"negate\":false},\"query\":{\"bool\":{\"must\":[],\"filter\":[{\"bool\":{\"should\":[{\"term\":{\"data.vulnerability.severity\":\"Low\"}}],\"minimum_should_match\":1}}],\"should\":[],\"must_not\":[]}},\"$state\":{\"store\":\"appState\"}}],\"datasourceStates\":{\"formBased\":{\"layers\":{\"a397e361-0b6a-4d18-b957-2afce890f6c3\":{\"columns\":{\"c0f27509-4ce0-4eca-94c5-e1eddfc176e9\":{\"label\":\"Low Severity Alerts\",\"dataType\":\"number\",\"operationType\":\"unique_count\",\"scale\":\"ratio\",\"sourceField\":\"data.vulnerability.severity\",\"isBucketed\":false,\"filter\":{\"query\":\"data.vulnerability.severity : \\\"Low\\\" \",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"c0f27509-4ce0-4eca-94c5-e1eddfc176e9\"],\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{}}},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":5,\"w\":25,\"h\":14,\"i\":\"8fe06d85-091b-47aa-a809-aae9150a3314\"},\"panelIndex\":\"8fe06d85-091b-47aa-a809-aae9150a3314\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-47832b00-8a1a-4d99-8631-89379474c236\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"curveType\":\"CURVE_MONOTONE_X\",\"fillOpacity\":1,\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"area_stacked\",\"layers\":[{\"layerId\":\"47832b00-8a1a-4d99-8631-89379474c236\",\"accessors\":[\"32448531-8094-4131-89c9-38ed77a620ec\"],\"position\":\"top\",\"seriesType\":\"area_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"yConfig\":[{\"forAccessor\":\"32448531-8094-4131-89c9-38ed77a620ec\",\"axisMode\":\"auto\"}],\"xAccessor\":\"f20c7be6-a511-4b95-be88-6de506dbf1d8\",\"splitAccessor\":\"526e79e6-d985-4fc0-b5f3-ec87f5d24b83\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"47832b00-8a1a-4d99-8631-89379474c236\":{\"columns\":{\"526e79e6-d985-4fc0-b5f3-ec87f5d24b83\":{\"label\":\"Top 5 values of data.vulnerability.severity\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.vulnerability.severity\",\"isBucketed\":true,\"params\":{\"size\":5,\"orderBy\":{\"type\":\"column\",\"columnId\":\"32448531-8094-4131-89c9-38ed77a620ec\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false}},\"f20c7be6-a511-4b95-be88-6de506dbf1d8\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"3h\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"32448531-8094-4131-89c9-38ed77a620ec\":{\"label\":\"Count\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"filter\":{\"query\":\"\",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"526e79e6-d985-4fc0-b5f3-ec87f5d24b83\",\"f20c7be6-a511-4b95-be88-6de506dbf1d8\",\"32448531-8094-4131-89c9-38ed77a620ec\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Alert severity\"},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":25,\"y\":5,\"w\":23,\"h\":14,\"i\":\"680cfedf-a868-4de2-8173-897f4df7f6d7\"},\"panelIndex\":\"680cfedf-a868-4de2-8173-897f4df7f6d7\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsHeatmap\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-6f9a4ce5-1395-4bc6-9dd6-0a8c130e9d8a\"}],\"state\":{\"visualization\":{\"shape\":\"heatmap\",\"layerId\":\"6f9a4ce5-1395-4bc6-9dd6-0a8c130e9d8a\",\"layerType\":\"data\",\"legend\":{\"isVisible\":true,\"position\":\"right\",\"type\":\"heatmap_legend\"},\"gridConfig\":{\"type\":\"heatmap_grid\",\"isCellLabelVisible\":false,\"isYAxisLabelVisible\":true,\"isXAxisLabelVisible\":true,\"isYAxisTitleVisible\":false,\"isXAxisTitleVisible\":true,\"yTitle\":\"\"},\"valueAccessor\":\"4e7e0e20-a869-417a-b9ba-fac0c17e10ed\",\"yAccessor\":\"6fcc771b-b4e8-4684-80da-49b7b897dc24\",\"xAccessor\":\"e8d69708-c954-444b-a94f-9eb1befd3197\",\"palette\":{\"type\":\"palette\",\"name\":\"positive\",\"params\":{\"name\":\"positive\",\"continuity\":\"above\",\"reverse\":false,\"stops\":[{\"color\":\"#d6e9e4\",\"stop\":0},{\"color\":\"#aed3ca\",\"stop\":20},{\"color\":\"#85bdb1\",\"stop\":40},{\"color\":\"#5aa898\",\"stop\":60},{\"color\":\"#209280\",\"stop\":80}],\"rangeMin\":0,\"rangeMax\":null},\"accessor\":\"4e7e0e20-a869-417a-b9ba-fac0c17e10ed\"}},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"6f9a4ce5-1395-4bc6-9dd6-0a8c130e9d8a\":{\"columns\":{\"4e7e0e20-a869-417a-b9ba-fac0c17e10ed\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true},\"customLabel\":false},\"6fcc771b-b4e8-4684-80da-49b7b897dc24\":{\"label\":\"Top 3 values of data.vulnerability.severity\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.vulnerability.severity\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"4e7e0e20-a869-417a-b9ba-fac0c17e10ed\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":false},\"e8d69708-c954-444b-a94f-9eb1befd3197\":{\"label\":\"agent.name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"agent.name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"4e7e0e20-a869-417a-b9ba-fac0c17e10ed\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true}},\"columnOrder\":[\"6fcc771b-b4e8-4684-80da-49b7b897dc24\",\"e8d69708-c954-444b-a94f-9eb1befd3197\",\"4e7e0e20-a869-417a-b9ba-fac0c17e10ed\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Vulnerabilities heat map\"},{\"version\":\"8.6.0\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":19,\"w\":48,\"h\":14,\"i\":\"5a8626af-2bc4-4317-ad7f-20622c16db0a\"},\"panelIndex\":\"5a8626af-2bc4-4317-ad7f-20622c16db0a\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"f410770f-a2da-47db-8a47-20b2ddbdcf5e\",\"name\":\"indexpattern-datasource-layer-d94ddf3d-d285-450e-aba4-46057df55fb7\"}],\"state\":{\"visualization\":{\"columns\":[{\"isTransposed\":false,\"columnId\":\"542028d8-117e-4ee0-ba25-3ff4475940aa\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"e26de584-b46b-474e-bcd4-11bd37ff8e2e\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"1007fe8b-8a98-4b60-b8ef-93cd49227cd4\"},{\"isTransposed\":false,\"columnId\":\"ec84289b-cb43-4fae-9b94-7b17b696e4e0\"},{\"isTransposed\":false,\"columnId\":\"89ac7aeb-dfe3-449c-a109-6686a3610a4b\",\"oneClickFilter\":true},{\"isTransposed\":false,\"columnId\":\"5a0e5d4b-1345-4f59-ba8b-662451bf949b\",\"hidden\":true},{\"columnId\":\"4732efcd-d7cd-4a02-8b03-c498b3bb637c\",\"isTransposed\":false},{\"columnId\":\"056be5db-ea40-4979-9985-8f0c73a8dcef\",\"isTransposed\":false}],\"layerId\":\"d94ddf3d-d285-450e-aba4-46057df55fb7\",\"layerType\":\"data\",\"paging\":{\"size\":10,\"enabled\":true}},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"d94ddf3d-d285-450e-aba4-46057df55fb7\":{\"columns\":{\"542028d8-117e-4ee0-ba25-3ff4475940aa\":{\"label\":\"agent.name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"agent.name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"5a0e5d4b-1345-4f59-ba8b-662451bf949b\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"e26de584-b46b-474e-bcd4-11bd37ff8e2e\":{\"label\":\"data.vulnerability.cve\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.vulnerability.cve\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"5a0e5d4b-1345-4f59-ba8b-662451bf949b\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"1007fe8b-8a98-4b60-b8ef-93cd49227cd4\":{\"label\":\"data.vulnerability.package.name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.vulnerability.package.name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"5a0e5d4b-1345-4f59-ba8b-662451bf949b\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"ec84289b-cb43-4fae-9b94-7b17b696e4e0\":{\"label\":\"data.vulnerability.severity\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.vulnerability.package.version\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"5a0e5d4b-1345-4f59-ba8b-662451bf949b\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"89ac7aeb-dfe3-449c-a109-6686a3610a4b\":{\"label\":\"rule.id\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"rule.id\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"5a0e5d4b-1345-4f59-ba8b-662451bf949b\"},\"orderDirection\":\"desc\",\"otherBucket\":false,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true},\"5a0e5d4b-1345-4f59-ba8b-662451bf949b\":{\"label\":\"Count of records\",\"dataType\":\"number\",\"operationType\":\"count\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"___records___\",\"params\":{\"emptyAsNull\":true}},\"4732efcd-d7cd-4a02-8b03-c498b3bb637c\":{\"label\":\"timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"056be5db-ea40-4979-9985-8f0c73a8dcef\":{\"label\":\"data.vulnerability.package.version\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"data.vulnerability.package.version\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"5a0e5d4b-1345-4f59-ba8b-662451bf949b\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false},\"customLabel\":true}},\"columnOrder\":[\"4732efcd-d7cd-4a02-8b03-c498b3bb637c\",\"542028d8-117e-4ee0-ba25-3ff4475940aa\",\"e26de584-b46b-474e-bcd4-11bd37ff8e2e\",\"1007fe8b-8a98-4b60-b8ef-93cd49227cd4\",\"056be5db-ea40-4979-9985-8f0c73a8dcef\",\"ec84289b-cb43-4fae-9b94-7b17b696e4e0\",\"89ac7aeb-dfe3-449c-a109-6686a3610a4b\",\"5a0e5d4b-1345-4f59-ba8b-662451bf949b\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Events\"}]","timeRestore":false,"title":"Vulnerabilities","version":1},"coreMigrationVersion":"8.6.0","created_at":"2023-02-24T13:45:51.222Z","id":"21ad34e0-a3de-11ed-9187-5147a2b9eedf","migrationVersion":{"dashboard":"8.6.0"},"references":[{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"9931cceb-51f1-4e47-bd26-491e7a624592:indexpattern-datasource-layer-1dc5f9b1-9f0c-458b-98e6-e92708af5b9d","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"9931cceb-51f1-4e47-bd26-491e7a624592:b9624937-542e-4ac9-9f09-ae532ade3311","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"a0b05cdd-c4b5-46b0-af2e-32253bd965e6:indexpattern-datasource-layer-fd6049b6-e52c-449e-9775-ded5ac1eac15","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"b22f2aba-370b-40f2-8f30-c7175fd21d84:indexpattern-datasource-layer-a8774fa0-5ae6-4746-94bd-cd21a0210641","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"dad9436c-6a56-47cc-a52a-065c86d64c7f:indexpattern-datasource-layer-a397e361-0b6a-4d18-b957-2afce890f6c3","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"dad9436c-6a56-47cc-a52a-065c86d64c7f:a532bc3a-2caf-4353-9a37-17d4fb373b0d","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"8fe06d85-091b-47aa-a809-aae9150a3314:indexpattern-datasource-layer-47832b00-8a1a-4d99-8631-89379474c236","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"680cfedf-a868-4de2-8173-897f4df7f6d7:indexpattern-datasource-layer-6f9a4ce5-1395-4bc6-9dd6-0a8c130e9d8a","type":"index-pattern"},{"id":"f410770f-a2da-47db-8a47-20b2ddbdcf5e","name":"5a8626af-2bc4-4317-ad7f-20622c16db0a:indexpattern-datasource-layer-d94ddf3d-d285-450e-aba4-46057df55fb7","type":"index-pattern"}],"type":"dashboard","updated_at":"2023-02-24T13:45:51.222Z","version":"WzQ1MzQwLDRd"}
+{"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":2,"missingRefCount":0,"missingReferences":[]}
\ No newline at end of file
diff --git a/public/panels/splunk-with-sample-data/amazon-aws b/public/panels/splunk-with-sample-data/amazon-aws
new file mode 100644
index 0000000000..1f37baa828
--- /dev/null
+++ b/public/panels/splunk-with-sample-data/amazon-aws
@@ -0,0 +1,136 @@
+{
+ "visualizations": {
+ "viz_lTJLU7ar": {
+ "type": "splunk.area",
+ "options": {
+ "stackMode": "stacked",
+ "xAxisTitleText": "timestamp",
+ "yAxisTitleText": "count",
+ "legendDisplay": "left"
+ },
+ "dataSources": {
+ "primary": "ds_BHh1kZmb"
+ },
+ "title": "Events by source over time"
+ },
+ "viz_l5qazB46": {
+ "type": "splunk.pie",
+ "options": {
+ "showDonutHole": true
+ },
+ "dataSources": {
+ "primary": "ds_Y2J0psR4"
+ },
+ "title": "Sources"
+ },
+ "viz_1JzeNwnq": {
+ "type": "splunk.table",
+ "title": "Events",
+ "dataSources": {
+ "primary": "ds_K2y81pak"
+ }
+ }
+ },
+ "dataSources": {
+ "ds_BHh1kZmb": {
+ "type": "ds.search",
+ "options": {
+ "queryParameters": {
+ "earliest": "$global_time.earliest$",
+ "latest": "$global_time.latest$"
+ },
+ "query": "index=\"wazuh-alerts\" \"data.aws.source\"=\"*\" | timechart count by \"data.aws.source\""
+ },
+ "name": "Search_1"
+ },
+ "ds_Y2J0psR4": {
+ "type": "ds.search",
+ "options": {
+ "queryParameters": {
+ "earliest": "$global_time.earliest$",
+ "latest": "$global_time.latest$"
+ },
+ "query": "index=\"wazuh-alerts\" \"data.aws.source\"=\"*\" | chart count by \"data.aws.source\""
+ },
+ "name": "Search_2"
+ },
+ "ds_K2y81pak": {
+ "type": "ds.search",
+ "options": {
+ "queryParameters": {
+ "earliest": "$global_time.earliest$",
+ "latest": "$global_time.latest$"
+ },
+ "query": "index=\"wazuh-alerts\" \"agent.name\"=\"*\", \"data.aws.source\"=\"*\", \"rule.description\"=\"*\", \"rule.level\"=\"*\", \"rule.id\"=\"*\" | table _time, agent.name, data.aws.source, rule.description, rule.level, rule.id"
+ },
+ "name": "Search_3"
+ }
+ },
+ "defaults": {
+ "dataSources": {
+ "ds.search": {
+ "options": {
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ }
+ }
+ }
+ },
+ "inputs": {
+ "input_global_trp": {
+ "type": "input.timerange",
+ "options": {
+ "token": "global_time",
+ "defaultValue": "-60m@m,now",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "title": "Global Time Range"
+ }
+ },
+ "layout": {
+ "type": "grid",
+ "options": {},
+ "structure": [
+ {
+ "item": "viz_lTJLU7ar",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 0,
+ "w": 795,
+ "h": 334
+ }
+ },
+ {
+ "item": "viz_1JzeNwnq",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 334,
+ "w": 1200,
+ "h": 358
+ }
+ },
+ {
+ "item": "viz_l5qazB46",
+ "type": "block",
+ "position": {
+ "x": 795,
+ "y": 0,
+ "w": 405,
+ "h": 334
+ }
+ }
+ ],
+ "globalInputs": [
+ "input_global_trp"
+ ]
+ },
+ "description": "",
+ "title": "Amazon AWS"
+}
diff --git a/public/panels/splunk-with-sample-data/docker-listener b/public/panels/splunk-with-sample-data/docker-listener
new file mode 100644
index 0000000000..3a48133a49
--- /dev/null
+++ b/public/panels/splunk-with-sample-data/docker-listener
@@ -0,0 +1,130 @@
+{
+ "visualizations": {
+ "viz_OcJb59wC": {
+ "type": "splunk.pie",
+ "options": {
+ "showDonutHole": true
+ },
+ "dataSources": {
+ "primary": "ds_5TEzCbIf"
+ },
+ "title": "Top 5 events"
+ },
+ "viz_bQPbbrvw": {
+ "type": "splunk.column",
+ "title": "Events by source over time",
+ "dataSources": {
+ "primary": "ds_l6nQN96B"
+ },
+ "options": {
+ "xAxisTitleText": "timestamp",
+ "yAxisTitleText": "count"
+ }
+ },
+ "viz_7GGKwL33": {
+ "type": "splunk.table",
+ "dataSources": {
+ "primary": "ds_gW45zmr5"
+ },
+ "title": "Events"
+ }
+ },
+ "dataSources": {
+ "ds_5TEzCbIf": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" | top limit=5 data.docker.Action | chart count by data.docker.Action",
+ "queryParameters": {
+ "earliest": "$global_time.earliest$",
+ "latest": "$global_time.latest$"
+ }
+ },
+ "name": "Search_1"
+ },
+ "ds_l6nQN96B": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" | timechart count by data.docker.Type useother=false usenull=false\n",
+ "queryParameters": {
+ "earliest": "$global_time.earliest$",
+ "latest": "$global_time.latest$"
+ }
+ },
+ "name": "Search_2"
+ },
+ "ds_gW45zmr5": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"agent.name\"=\"*\", \"data.docker.Type\"=\"*\", \"data.docker.Actor.ID\"=\"*\", \"data.docker.Action\"=\"*\", \"rule.description\"=\"*\", \"rule.level\"=\"*\", \"rule.id\"=\"*\" | table _time, agent.name, data.docker.Type, data.docker.Actor.ID, data.docker.Action, rule.description, rule.level, rule.id",
+ "queryParameters": {
+ "earliest": "$global_time.earliest$",
+ "latest": "$global_time.latest$"
+ }
+ },
+ "name": "Search_3"
+ }
+ },
+ "defaults": {
+ "dataSources": {
+ "ds.search": {
+ "options": {
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ }
+ }
+ }
+ },
+ "inputs": {
+ "input_global_trp": {
+ "type": "input.timerange",
+ "options": {
+ "token": "global_time",
+ "defaultValue": "-24h@h,now"
+ },
+ "title": "Global Time Range"
+ }
+ },
+ "layout": {
+ "type": "grid",
+ "options": {},
+ "structure": [
+ {
+ "item": "viz_OcJb59wC",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 0,
+ "w": 415,
+ "h": 316
+ }
+ },
+ {
+ "item": "viz_7GGKwL33",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 316,
+ "w": 1200,
+ "h": 378
+ }
+ },
+ {
+ "item": "viz_bQPbbrvw",
+ "type": "block",
+ "position": {
+ "x": 415,
+ "y": 0,
+ "w": 785,
+ "h": 316
+ }
+ }
+ ],
+ "globalInputs": [
+ "input_global_trp"
+ ]
+ },
+ "description": "",
+ "title": "Docker Listener"
+}
diff --git a/public/panels/splunk-with-sample-data/incident-response b/public/panels/splunk-with-sample-data/incident-response
new file mode 100644
index 0000000000..c6aa2d60ee
--- /dev/null
+++ b/public/panels/splunk-with-sample-data/incident-response
@@ -0,0 +1,135 @@
+{
+ "visualizations": {
+ "viz_bRMOrrNo": {
+ "type": "splunk.pie",
+ "options": {
+ "showDonutHole": true
+ },
+ "dataSources": {
+ "primary": "ds_T5OG9qjO"
+ },
+ "title": "Alert groups"
+ },
+ "viz_iOvmhhgU": {
+ "type": "splunk.table",
+ "options": {},
+ "dataSources": {
+ "primary": "ds_tnYl87gQ"
+ }
+ },
+ "viz_P0bNNVfw": {
+ "type": "splunk.column",
+ "options": {
+ "stackMode": "stacked",
+ "xAxisTitleText": "timestamp",
+ "yAxisTitleText": "count"
+ },
+ "dataSources": {
+ "primary": "ds_GccX6Lrj"
+ },
+ "title": "Events"
+ }
+ },
+ "dataSources": {
+ "ds_T5OG9qjO": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"rule.groups{}\"=\"*\" | top limit=5 \"rule.groups{}\" | chart count by \"rule.groups{}\" useother=false usenull=false",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_1"
+ },
+ "ds_tnYl87gQ": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"agent.name\"=\"*\", \"rule.groups{}\"=\"*\", \"rule.description\"=\"*\", \"rule.level\"=\"*\", \"rule.id\"=\"*\" | table _time, agent.name, rule.groups{}, rule.description, rule.level, rule.id",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_2"
+ },
+ "ds_GccX6Lrj": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"rule.groups{}\"=\"audit\" | timechart count by \"rule.groups{}\"",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_3"
+ }
+ },
+ "defaults": {
+ "dataSources": {
+ "ds.search": {
+ "options": {
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ }
+ }
+ }
+ },
+ "inputs": {
+ "input_global_trp": {
+ "type": "input.timerange",
+ "options": {
+ "token": "global_time",
+ "defaultValue": "-60m@m,now",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "title": "Global Time Range"
+ }
+ },
+ "layout": {
+ "type": "grid",
+ "options": {},
+ "structure": [
+ {
+ "item": "viz_bRMOrrNo",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 0,
+ "w": 388,
+ "h": 292
+ }
+ },
+ {
+ "item": "viz_iOvmhhgU",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 292,
+ "w": 1200,
+ "h": 399
+ }
+ },
+ {
+ "item": "viz_P0bNNVfw",
+ "type": "block",
+ "position": {
+ "x": 388,
+ "y": 0,
+ "w": 812,
+ "h": 292
+ }
+ }
+ ],
+ "globalInputs": [
+ "input_global_trp"
+ ]
+ },
+ "description": "",
+ "title": "Incident-response"
+}
diff --git a/public/panels/splunk-with-sample-data/integrity-monitoring b/public/panels/splunk-with-sample-data/integrity-monitoring
new file mode 100644
index 0000000000..01c4db0cd8
--- /dev/null
+++ b/public/panels/splunk-with-sample-data/integrity-monitoring
@@ -0,0 +1,115 @@
+{
+ "visualizations": {
+ "viz_ybUZnzEr": {
+ "type": "splunk.area",
+ "dataSources": {
+ "primary": "ds_fkydr4kz"
+ },
+ "title": "Alerts by action over time",
+ "showProgressBar": false,
+ "showLastUpdated": false,
+ "options": {
+ "stackMode": "stacked"
+ }
+ },
+ "viz_HEgUBWpZ": {
+ "type": "splunk.table",
+ "dataSources": {
+ "primary": "ds_2tZ06PqM"
+ },
+ "title": "Recent events"
+ }
+ },
+ "dataSources": {
+ "ds_fkydr4kz": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" | timechart count by syscheck.event useother=false usenull=false",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_1"
+ },
+ "ds_2tZ06PqM": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"syscheck.event\"=\"*\", \"syscheck.path\"=\"*\", \"rule.level\"=\"*\", \"rule.id\"=\"*\" | table _time, syscheck.event, syscheck.path, rule.level, rule.id\n",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_2"
+ },
+ "ds_a4NPP8kb_ds_2tZ06PqM": {
+ "type": "ds.search",
+ "options": {
+ "query": "wazuh-alerts-4.x-sample | table _time, syscheck.event, syscheck.path, rule.level, rule.id\n",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_2 copy 1"
+ }
+ },
+ "defaults": {
+ "dataSources": {
+ "ds.search": {
+ "options": {
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ }
+ }
+ }
+ },
+ "inputs": {
+ "input_global_trp": {
+ "type": "input.timerange",
+ "options": {
+ "token": "global_time",
+ "defaultValue": "-60m@m,now",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "title": "Global Time Range"
+ }
+ },
+ "layout": {
+ "type": "grid",
+ "options": {},
+ "structure": [
+ {
+ "item": "viz_ybUZnzEr",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 0,
+ "w": 1200,
+ "h": 300
+ }
+ },
+ {
+ "item": "viz_HEgUBWpZ",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 300,
+ "w": 1200,
+ "h": 400
+ }
+ }
+ ],
+ "globalInputs": [
+ "input_global_trp"
+ ]
+ },
+ "description": "",
+ "title": "Integrity-monitoring"
+}
\ No newline at end of file
diff --git a/public/panels/splunk-with-sample-data/log-data-analysis b/public/panels/splunk-with-sample-data/log-data-analysis
new file mode 100644
index 0000000000..8bccc32306
--- /dev/null
+++ b/public/panels/splunk-with-sample-data/log-data-analysis
@@ -0,0 +1,102 @@
+{
+ "visualizations": {
+ "viz_XbK1b9yA": {
+ "type": "splunk.column",
+ "options": {
+ "yAxisTitleText": "count"
+ },
+ "dataSources": {
+ "primary": "ds_r5yaY2un"
+ },
+ "title": "Attack tactics by agent"
+ },
+ "viz_Jl6VyaTG": {
+ "type": "splunk.table",
+ "options": {},
+ "dataSources": {
+ "primary": "ds_0VMCtG7V"
+ }
+ }
+ },
+ "dataSources": {
+ "ds_r5yaY2un": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"rule.mitre.tactic{}\"=\"*\" | chart count by \"agent.name\", \"rule.mitre.tactic{}\"",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_1"
+ },
+ "ds_0VMCtG7V": {
+ "type": "ds.search",
+ "options": {
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ },
+ "query": "index=\"wazuh-alerts\" \"rule.mitre.technique{}\"=\"*\", \"rule.mitre.tactic{}\"=\"*\", \"rule.level\"=\"*\", \"rule.id\"=\"*\", \"rule.description\"=\"*\" | table _time, rule.mitre.technique{}, rule.mitre.tactic{}, rule.level, rule.id, rule.description"
+ },
+ "name": "Search_2"
+ }
+ },
+ "defaults": {
+ "dataSources": {
+ "ds.search": {
+ "options": {
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ }
+ }
+ }
+ },
+ "inputs": {
+ "input_global_trp": {
+ "type": "input.timerange",
+ "options": {
+ "token": "global_time",
+ "defaultValue": "-60m@m,now",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "title": "Global Time Range"
+ }
+ },
+ "layout": {
+ "type": "grid",
+ "options": {},
+ "structure": [
+ {
+ "item": "viz_XbK1b9yA",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 0,
+ "w": 634,
+ "h": 351
+ }
+ },
+ {
+ "item": "viz_Jl6VyaTG",
+ "type": "block",
+ "position": {
+ "x": 634,
+ "y": 0,
+ "w": 566,
+ "h": 351
+ }
+ }
+ ],
+ "globalInputs": [
+ "input_global_trp"
+ ]
+ },
+ "description": "",
+ "title": "Log-data-analysis"
+}
diff --git a/public/panels/splunk-with-sample-data/malware-detection b/public/panels/splunk-with-sample-data/malware-detection
new file mode 100644
index 0000000000..e413477a2c
--- /dev/null
+++ b/public/panels/splunk-with-sample-data/malware-detection
@@ -0,0 +1,136 @@
+{
+ "visualizations": {
+ "viz_Q5GQT6h2": {
+ "type": "splunk.area",
+ "dataSources": {
+ "primary": "ds_N3cdEic4"
+ },
+ "options": {
+ "stackMode": "stacked",
+ "xAxisTitleText": "timestamp",
+ "yAxisTitleText": "count"
+ },
+ "title": "Emotet malware activity"
+ },
+ "viz_U8vFKyUp": {
+ "type": "splunk.table",
+ "dataSources": {
+ "primary": "ds_f5AJxLS5"
+ },
+ "title": "Security alerts"
+ },
+ "viz_uLQLGVbg": {
+ "type": "splunk.line",
+ "options": {
+ "xAxisTitleText": "timestamp",
+ "yAxisTitleText": "count"
+ },
+ "dataSources": {
+ "primary": "ds_IcWLWjPn"
+ },
+ "title": "Rootkits activity over time"
+ }
+ },
+ "dataSources": {
+ "ds_N3cdEic4": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"rule.groups{}\"=\"rootcheck\" | timechart count by \"rule.groups{}\"",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_1"
+ },
+ "ds_f5AJxLS5": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"rule.mitre.technique{}\"=\"*\", \"rule.mitre.tactic{}\"=\"*\", \"rule.level\"=\"*\", \"rule.id\"=\"*\", \"rule.description\"=\"*\" | table _time, agent.name, rule.mitre.technique{}, rule.mitre.tactic{}, rule.level, rule.id, rule.description\n",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_2"
+ },
+ "ds_IcWLWjPn": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" | timechart count by data.title useother=false usenull=false\n",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_3"
+ }
+ },
+ "defaults": {
+ "dataSources": {
+ "ds.search": {
+ "options": {
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ }
+ }
+ }
+ },
+ "inputs": {
+ "input_global_trp": {
+ "type": "input.timerange",
+ "options": {
+ "token": "global_time",
+ "defaultValue": "-60m@m,now",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "title": "Global Time Range"
+ }
+ },
+ "layout": {
+ "type": "grid",
+ "options": {},
+ "structure": [
+ {
+ "item": "viz_Q5GQT6h2",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 0,
+ "w": 458,
+ "h": 293
+ }
+ },
+ {
+ "item": "viz_U8vFKyUp",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 293,
+ "w": 1200,
+ "h": 381
+ }
+ },
+ {
+ "item": "viz_uLQLGVbg",
+ "type": "block",
+ "position": {
+ "x": 458,
+ "y": 0,
+ "w": 742,
+ "h": 293
+ }
+ }
+ ],
+ "globalInputs": [
+ "input_global_trp"
+ ]
+ },
+ "description": "",
+ "title": "Malware-detection"
+}
\ No newline at end of file
diff --git a/public/panels/splunk-with-sample-data/pci-dss b/public/panels/splunk-with-sample-data/pci-dss
new file mode 100644
index 0000000000..692d4863c2
--- /dev/null
+++ b/public/panels/splunk-with-sample-data/pci-dss
@@ -0,0 +1,137 @@
+{
+ "visualizations": {
+ "viz_9NIbkgTo": {
+ "type": "splunk.bubble",
+ "options": {
+ "backgroundColor": "#ffffff",
+ "xAxisTitleText": "timestamp",
+ "yAxisTitleText": "count"
+ },
+ "dataSources": {
+ "primary": "ds_g3vSgFS7"
+ },
+ "title": "PCI DSS requirements"
+ },
+ "viz_Z6CAbCjJ": {
+ "type": "splunk.column",
+ "options": {
+ "stackMode": "stacked",
+ "yAxisTitleText": "count",
+ "xAxisTitleText": "requirements"
+ },
+ "dataSources": {
+ "primary": "ds_lljKZIBi"
+ },
+ "title": "Requirements by agent"
+ },
+ "viz_AtTGNj0f": {
+ "type": "splunk.table",
+ "dataSources": {
+ "primary": "ds_9ABDZ4aq"
+ },
+ "title": "Recent events"
+ }
+ },
+ "dataSources": {
+ "ds_g3vSgFS7": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"rule.pci_dss{}\"=\"*\" | timechart count by \"rule.pci_dss{}\"\n",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_1"
+ },
+ "ds_lljKZIBi": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"agent.name\"=\"*\" | chart count by \"rule.pci_dss{}\", \"agent.name\"",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_2"
+ },
+ "ds_9ABDZ4aq": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"agent.name\"=\"*\", \"rule.pci_dss{}\"=\"*\", \"rule.description\"=\"*\", \"rule.level\"=\"*\", \"rule.id\"=\"*\" | table _time, agent.name, rule.pci_dss{}, rule.description, rule.level, rule.id",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_3"
+ }
+ },
+ "defaults": {
+ "dataSources": {
+ "ds.search": {
+ "options": {
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ }
+ }
+ }
+ },
+ "inputs": {
+ "input_global_trp": {
+ "type": "input.timerange",
+ "options": {
+ "token": "global_time",
+ "defaultValue": "-60m@m,now",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "title": "Global Time Range"
+ }
+ },
+ "layout": {
+ "type": "grid",
+ "options": {},
+ "structure": [
+ {
+ "item": "viz_9NIbkgTo",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 0,
+ "w": 629,
+ "h": 400
+ }
+ },
+ {
+ "item": "viz_AtTGNj0f",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 400,
+ "w": 1200,
+ "h": 291
+ }
+ },
+ {
+ "item": "viz_Z6CAbCjJ",
+ "type": "block",
+ "position": {
+ "x": 629,
+ "y": 0,
+ "w": 571,
+ "h": 400
+ }
+ }
+ ],
+ "globalInputs": [
+ "input_global_trp"
+ ]
+ },
+ "description": "",
+ "title": "PCI-DSS"
+}
diff --git a/public/panels/splunk-with-sample-data/policy-monitoring b/public/panels/splunk-with-sample-data/policy-monitoring
new file mode 100644
index 0000000000..2c6e13b43a
--- /dev/null
+++ b/public/panels/splunk-with-sample-data/policy-monitoring
@@ -0,0 +1,297 @@
+{
+ "visualizations": {
+ "viz_oAPKLE0R": {
+ "type": "splunk.column",
+ "options": {
+ "xAxisTitleText": "timestamp",
+ "yAxisTitleText": "Count",
+ "stackMode": "stacked"
+ },
+ "dataSources": {
+ "primary": "ds_TdanKF0I"
+ },
+ "showProgressBar": false,
+ "showLastUpdated": false,
+ "title": "Alerts evolution - Top 5 agents",
+ "description": ""
+ },
+ "viz_Y07WmZ1b": {
+ "type": "splunk.table",
+ "dataSources": {
+ "primary": "ds_ut2DiVW9"
+ },
+ "title": "Security alerts",
+ "description": ""
+ },
+ "viz_DI7fpctI": {
+ "type": "splunk.pie",
+ "dataSources": {
+ "primary": "ds_EmDJmxMO"
+ },
+ "showProgressBar": false,
+ "showLastUpdated": false,
+ "title": "Top Mitre ATT&K tactics"
+ },
+ "viz_qYCIuSjF": {
+ "type": "splunk.singlevalueradial",
+ "options": {
+ "majorColor": "#0258a1",
+ "trendColor": "#000000"
+ },
+ "dataSources": {
+ "primary": "ds_d9cN1Qn9"
+ },
+ "title": "Total"
+ },
+ "viz_aTlMnG7A": {
+ "type": "splunk.singlevalueradial",
+ "options": {
+ "majorColor": "#db566f"
+ },
+ "dataSources": {
+ "primary": "ds_ZPT4uVoe"
+ },
+ "title": "Level 12 or above alerts"
+ },
+ "viz_R8LMR6U6": {
+ "type": "splunk.singlevalueradial",
+ "options": {
+ "backgroundColor": "#ffffff",
+ "majorColor": "#bf0561"
+ },
+ "dataSources": {
+ "primary": "ds_d8m0U7Ph"
+ },
+ "title": "Authentication failure"
+ },
+ "viz_nDMI4ZGW": {
+ "type": "splunk.singlevalueradial",
+ "options": {
+ "majorColor": "#007d73"
+ },
+ "dataSources": {
+ "primary": "ds_7FDRhb5m"
+ },
+ "title": "Authentication success"
+ }
+ },
+ "dataSources": {
+ "ds_TdanKF0I": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" | timechart count by agent.name\n\n",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_1"
+ },
+ "ds_ut2DiVW9": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"rule.mitre.id{}\"=\"*\" | table _time, agent.name, rule.mitre.id{}, rule.mitre.tactic{}, rule.description, rule.level, rule.id\n",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_2"
+ },
+ "ds_EmDJmxMO": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" | top limit=5 agent.name | chart count by agent.name\n",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_3"
+ },
+ "ds_5QIbKzqF": {
+ "type": "ds.search",
+ "options": {
+ "query": "wazuh-alerts-4.x-sample | chart count by rule.groups",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_4"
+ },
+ "ds_d9cN1Qn9": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" | stats count",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_5"
+ },
+ "ds_ZPT4uVoe": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" rule.level>=12 | stats count",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_6"
+ },
+ "ds_d8m0U7Ph": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"rule.groups{}\"=\"authentication_failed\" OR \"rule.groups{}\"=\"win_authentication_failed\" OR \"rule.groups{}\"=\"authentication_failures\" | stats count",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_7"
+ },
+ "ds_7FDRhb5m": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"rule.groups{}\"=authentication_success | stats count",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_8"
+ },
+ "ds_UIfFJptm": {
+ "type": "ds.search",
+ "options": {
+ "query": "wazuh-alerts-4.x-sample | stats count",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_9"
+ },
+ "ds_z3i8WcOf": {
+ "type": "ds.search",
+ "options": {
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ },
+ "query": "wazuh-alerts-4.x-sample rule.groups=\"authentication_failures\" | stats count by rule.groups"
+ },
+ "name": "Search_10"
+ }
+ },
+ "defaults": {
+ "dataSources": {
+ "ds.search": {
+ "options": {
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ }
+ }
+ }
+ },
+ "inputs": {
+ "input_global_trp": {
+ "type": "input.timerange",
+ "options": {
+ "token": "global_time",
+ "defaultValue": "-60m@m,now",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "title": "Global Time Range"
+ }
+ },
+ "layout": {
+ "type": "grid",
+ "options": {},
+ "structure": [
+ {
+ "item": "viz_qYCIuSjF",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 0,
+ "w": 291,
+ "h": 137
+ }
+ },
+ {
+ "item": "viz_oAPKLE0R",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 137,
+ "w": 731,
+ "h": 326
+ }
+ },
+ {
+ "item": "viz_Y07WmZ1b",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 463,
+ "w": 1200,
+ "h": 400
+ }
+ },
+ {
+ "item": "viz_aTlMnG7A",
+ "type": "block",
+ "position": {
+ "x": 291,
+ "y": 0,
+ "w": 286,
+ "h": 137
+ }
+ },
+ {
+ "item": "viz_R8LMR6U6",
+ "type": "block",
+ "position": {
+ "x": 577,
+ "y": 0,
+ "w": 301,
+ "h": 137
+ }
+ },
+ {
+ "item": "viz_DI7fpctI",
+ "type": "block",
+ "position": {
+ "x": 731,
+ "y": 137,
+ "w": 469,
+ "h": 326
+ }
+ },
+ {
+ "item": "viz_nDMI4ZGW",
+ "type": "block",
+ "position": {
+ "x": 878,
+ "y": 0,
+ "w": 322,
+ "h": 137
+ }
+ }
+ ],
+ "globalInputs": [
+ "input_global_trp"
+ ]
+ },
+ "description": "",
+ "title": "Policy-monitoring"
+}
diff --git a/public/panels/splunk-with-sample-data/vulnerabilities b/public/panels/splunk-with-sample-data/vulnerabilities
new file mode 100644
index 0000000000..97cf05e5e5
--- /dev/null
+++ b/public/panels/splunk-with-sample-data/vulnerabilities
@@ -0,0 +1,261 @@
+{
+ "visualizations": {
+ "viz_XlLyYDmC": {
+ "type": "splunk.area",
+ "dataSources": {
+ "primary": "ds_DljIxEDR"
+ },
+ "options": {
+ "stackMode": "stacked",
+ "xAxisTitleText": "timestamp",
+ "yAxisTitleText": "count"
+ },
+ "title": "Alert severity"
+ },
+ "viz_qzFw5Wx7": {
+ "type": "splunk.table",
+ "options": {},
+ "dataSources": {
+ "primary": "ds_Irx4cEkl"
+ }
+ },
+ "viz_3V3AvVY4": {
+ "type": "splunk.singlevalueradial",
+ "dataSources": {
+ "primary": "ds_oyvgAG73"
+ },
+ "title": "Critical Severity Alerts",
+ "options": {
+ "majorColor": "#db566f"
+ }
+ },
+ "viz_cmEIbZ9q": {
+ "type": "splunk.singlevalueradial",
+ "dataSources": {
+ "primary": "ds_TVyYlSRA"
+ },
+ "title": "Hight Severity Alerts",
+ "options": {
+ "majorColor": "#0258a1"
+ }
+ },
+ "viz_4QSVuglC": {
+ "type": "splunk.singlevalueradial",
+ "dataSources": {
+ "primary": "ds_D0hAYmXA"
+ },
+ "title": "Medium Severity Alerts",
+ "options": {
+ "majorColor": "#007d73"
+ }
+ },
+ "viz_VI9ZdnSO": {
+ "type": "splunk.singlevalueradial",
+ "dataSources": {
+ "primary": "ds_1KrtDz29"
+ },
+ "title": "Low Severity Alerts",
+ "options": {
+ "majorColor": "#232323"
+ }
+ }
+ },
+ "dataSources": {
+ "ds_DljIxEDR": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" | timechart count by data.vulnerability.severity useother=false usenull=false",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_1"
+ },
+ "ds_31leL1fM": {
+ "type": "ds.search",
+ "options": {
+ "query": "wazuh-alerts-4.x-sample | timechart count by data.vulnerability.severity",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_2"
+ },
+ "ds_jymjmvtF": {
+ "type": "ds.search",
+ "options": {
+ "query": "wazuh-alerts-4.x-sample | timechart count by data.vulnerability.severity",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_3"
+ },
+ "ds_jEwqnxee": {
+ "type": "ds.search",
+ "options": {
+ "query": "wazuh-alerts-4.x-sample | timechart count by data.vulnerability.severity",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_4"
+ },
+ "ds_Irx4cEkl": {
+ "type": "ds.search",
+ "options": {
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ },
+ "query": "index=\"wazuh-alerts\" \"agent.name\"=\"*\", \"data.vulnerability.cve\"=\"*\", \"data.vulnerability.package.name\"=\"*\", \"data.vulnerability.package.version\"=\"*\", \"data.vulnerability.severity\"=\"*\", \"rule.id\"=\"*\" | table _time, agent.name, data.vulnerability.cve, data.vulnerability.package.name, data.vulnerability.package.version, data.vulnerability.severity, rule.id\n\n"
+ },
+ "name": "Search_5"
+ },
+ "ds_oyvgAG73": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"data.vulnerability.severity\"=\"Critical\" | stats count by \"data.vulnerability.severity\"",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_6"
+ },
+ "ds_TVyYlSRA": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"data.vulnerability.severity\"=\"High\" | stats count by \"data.vulnerability.severity\"",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_7"
+ },
+ "ds_D0hAYmXA": {
+ "type": "ds.search",
+ "options": {
+ "query": "index-\"wazuh-alerts\" \"data.vulnerability.severity\"=\"Medium\" | stats count by \"data.vulnerability.severity\"",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_8"
+ },
+ "ds_1KrtDz29": {
+ "type": "ds.search",
+ "options": {
+ "query": "index=\"wazuh-alerts\" \"data.vulnerability.severity\"=\"Low\" | stats count by \"data.vulnerability.severity\"",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "name": "Search_9"
+ }
+ },
+ "defaults": {
+ "dataSources": {
+ "ds.search": {
+ "options": {
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ }
+ }
+ }
+ },
+ "inputs": {
+ "input_global_trp": {
+ "type": "input.timerange",
+ "options": {
+ "token": "global_time",
+ "defaultValue": "-60m@m,now",
+ "queryParameters": {
+ "latest": "$global_time.latest$",
+ "earliest": "$global_time.earliest$"
+ }
+ },
+ "title": "Global Time Range"
+ }
+ },
+ "layout": {
+ "type": "grid",
+ "options": {},
+ "structure": [
+ {
+ "item": "viz_3V3AvVY4",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 0,
+ "w": 279,
+ "h": 131
+ }
+ },
+ {
+ "item": "viz_XlLyYDmC",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 131,
+ "w": 1200,
+ "h": 284
+ }
+ },
+ {
+ "item": "viz_qzFw5Wx7",
+ "type": "block",
+ "position": {
+ "x": 0,
+ "y": 415,
+ "w": 1200,
+ "h": 251
+ }
+ },
+ {
+ "item": "viz_cmEIbZ9q",
+ "type": "block",
+ "position": {
+ "x": 279,
+ "y": 0,
+ "w": 293,
+ "h": 131
+ }
+ },
+ {
+ "item": "viz_4QSVuglC",
+ "type": "block",
+ "position": {
+ "x": 572,
+ "y": 0,
+ "w": 309,
+ "h": 131
+ }
+ },
+ {
+ "item": "viz_VI9ZdnSO",
+ "type": "block",
+ "position": {
+ "x": 881,
+ "y": 0,
+ "w": 319,
+ "h": 131
+ }
+ }
+ ],
+ "globalInputs": [
+ "input_global_trp"
+ ]
+ },
+ "description": "",
+ "title": "Vulnerabilities"
+}
diff --git a/public/plugin.ts b/public/plugin.ts
index 07a3dad2a6..c414c07aa9 100644
--- a/public/plugin.ts
+++ b/public/plugin.ts
@@ -1,5 +1,5 @@
import { BehaviorSubject } from 'rxjs';
-import { AppMountParameters, CoreSetup, CoreStart, AppUpdater, Plugin, PluginInitializerContext } from 'kibana/public';
+import { AppMountParameters, CoreSetup, CoreStart, AppUpdater, Plugin, PluginInitializerContext } from 'opensearch_dashboards/public';
import {
setDataPlugin,
setHttp,
@@ -28,85 +28,112 @@ import { AppState } from './react-services/app-state';
import { setErrorOrchestrator } from './react-services/common-services';
import { ErrorOrchestratorService } from './react-services/error-orchestrator/error-orchestrator.service';
import { getThemeAssetURL, getAssetURL } from './utils/assets';
-import { WzRequest } from './react-services/wz-request';
+import store from './redux/store';
+import { updateAppConfig } from './redux/actions/appConfigActions';
+import { initializeInterceptor, unregisterInterceptor } from './services/request-handler';
+
+const SIDEBAR_LOGO = 'customization.logo.sidebar';
const innerAngularName = 'app/wazuh';
+
export class WazuhPlugin implements Plugin {
- constructor(private readonly initializerContext: PluginInitializerContext) {}
+ constructor(private readonly initializerContext: PluginInitializerContext) { }
public initializeInnerAngular?: () => void;
private innerAngularInitialized: boolean = false;
private stateUpdater = new BehaviorSubject(() => ({}));
private hideTelemetryBanner?: () => void;
- public setup(core: CoreSetup, plugins: WazuhSetupPlugins): WazuhSetup {
+ public async setup(core: CoreSetup, plugins: WazuhSetupPlugins): WazuhSetup {
const UI_THEME = core.uiSettings.get('theme:darkMode') ? 'dark' : 'light';
- core.application.register({
- id: `wazuh`,
- title: 'Wazuh',
- icon: core.http.basePath.prepend(getThemeAssetURL('icon.svg', UI_THEME)),
- mount: async (params: AppMountParameters) => {
- try {
- if (!this.initializeInnerAngular) {
- throw Error('Wazuh plugin method initializeInnerAngular is undefined');
- }
- // hide the telemetry banner.
- // Set the flag in the telemetry saved object as the notice was seen and dismissed
- this.hideTelemetryBanner && await this.hideTelemetryBanner();
- setScopedHistory(params.history);
- // Load application bundle
- const { renderApp } = await import('./application');
- // Get start services as specified in kibana.json
- const [coreStart, depsStart] = await core.getStartServices();
- setErrorOrchestrator(ErrorOrchestratorService);
- setHttp(core.http);
- setCookies(new Cookies());
- if(!AppState.checkCookies() || params.history.parentHistory.action === 'PUSH') {
- window.location.reload();
- }
- await this.initializeInnerAngular();
- //Check is user has Wazuh disabled
- const response = await WzRequest.genericReq(
- 'GET',
- `/api/check-wazuh`,
- )
-
- params.element.classList.add('dscAppWrapper', 'wz-app');
- const unmount = await renderApp(innerAngularName, params.element);
- //Update if user has Wazuh disabled
- this.stateUpdater.next(() => {
- if (response.data.isWazuhDisabled) {
- unmount();
+
+ // Get custom logos configuration to start up the app with the correct logos
+ let logosInitialState = {};
+ try {
+ logosInitialState = await core.http.get(`/api/logos`);
+ }
+ catch (error) {
+ console.error('plugin.ts: Error getting logos configuration', error);
+ }
+
+ //Check if user has wazuh disabled and avoid registering the application if not
+ let response = { isWazuhDisabled: 1 };
+ try {
+ response = await core.http.get('/api/check-wazuh');
+ }
+ catch (error) {
+ console.error('plugin.ts: Error checking if Wazuh is enabled', error);
+ }
+
+ if (!response.isWazuhDisabled) {
+ core.application.register({
+ id: `wazuh`,
+ title: 'Wazuh',
+ icon: core.http.basePath.prepend(
+ logosInitialState?.logos?.[SIDEBAR_LOGO] ?
+ getAssetURL(logosInitialState?.logos?.[SIDEBAR_LOGO]) :
+ getThemeAssetURL('icon.svg', UI_THEME)),
+ mount: async (params: AppMountParameters) => {
+ try {
+ initializeInterceptor(core);
+ if (!this.initializeInnerAngular) {
+ throw Error('Wazuh plugin method initializeInnerAngular is undefined');
+ }
+
+ // Update redux app state logos with the custom logos
+ if (logosInitialState?.logos) {
+ store.dispatch(updateAppConfig(logosInitialState.logos));
}
- return {
- status: response.data.isWazuhDisabled,
- category: {
- id: 'wazuh',
- label: 'Wazuh',
- order: 0,
- euiIconType: core.http.basePath.prepend(response.data.logoSidebar ? getAssetURL(response.data.logoSidebar) : getThemeAssetURL('icon.svg', UI_THEME)),
- }}
- })
- return () => {
- unmount();
- };
- }catch(error){
- console.debug(error);
- }
- },
- category: {
- id: 'wazuh',
- label: 'Wazuh',
- order: 0,
- euiIconType: core.http.basePath.prepend(getThemeAssetURL('icon.svg', UI_THEME)),
- },
- updater$: this.stateUpdater
- });
+ // hide the telemetry banner.
+ // Set the flag in the telemetry saved object as the notice was seen and dismissed
+ this.hideTelemetryBanner && await this.hideTelemetryBanner();
+ setScopedHistory(params.history);
+ // Load application bundle
+ const { renderApp } = await import('./application');
+ // Get start services as specified in kibana.json
+ const [coreStart, depsStart] = await core.getStartServices();
+ setErrorOrchestrator(ErrorOrchestratorService);
+ setHttp(core.http);
+ setCookies(new Cookies());
+ if (!AppState.checkCookies() || params.history.parentHistory.action === 'PUSH') {
+ window.location.reload();
+ }
+ await this.initializeInnerAngular();
+ params.element.classList.add('dscAppWrapper', 'wz-app');
+ const unmount = await renderApp(innerAngularName, params.element);
+ this.stateUpdater.next(() => {
+ return {
+ status: response.isWazuhDisabled,
+ category: {
+ id: 'wazuh',
+ label: 'Wazuh',
+ order: 0,
+ euiIconType: core.http.basePath.prepend(logosInitialState?.logos?.[SIDEBAR_LOGO] ? getAssetURL(logosInitialState?.logos?.[SIDEBAR_LOGO]) : getThemeAssetURL('icon.svg', UI_THEME)),
+ }
+ }
+ })
+ return () => {
+ unmount();
+ unregisterInterceptor();
+ };
+ } catch (error) {
+ console.debug(error);
+ }
+ },
+ category: {
+ id: 'wazuh',
+ label: 'Wazuh',
+ order: 0,
+ euiIconType: core.http.basePath.prepend(logosInitialState?.logos?.[SIDEBAR_LOGO] ? getAssetURL(logosInitialState?.logos?.[SIDEBAR_LOGO]) : getThemeAssetURL('icon.svg', UI_THEME)),
+ },
+ updater$: this.stateUpdater
+ });
+ }
return {};
}
public start(core: CoreStart, plugins: AppPluginStartDependencies): WazuhStart {
// hide security alert
- if(plugins.securityOss) {
+ if (plugins.securityOss) {
plugins.securityOss.insecureCluster.hideAlert(true);
};
- if(plugins?.telemetry?.telemetryNotifications?.setOptedInNoticeSeen) {
+ if (plugins?.telemetry?.telemetryNotifications?.setOptedInNoticeSeen) {
// assign to a method to hide the telemetry banner used when the app is mounted
this.hideTelemetryBanner = () => plugins.telemetry.telemetryNotifications.setOptedInNoticeSeen();
};
@@ -143,4 +170,4 @@ export class WazuhPlugin implements Plugin indexPattern?.attributes?.fields ? JSON.parse(indexPattern.attributes.fields) : []);
- }else if(satisfyPluginPlatformVersion('>=7.11')){
- indexPatternsFields = await Promise.all(indexPatterns.map(async indexPattern => {
- try{
- const {data: {fields}} = await GenericRequest.request(
- 'GET',
- `/api/index_patterns/_fields_for_wildcard?pattern=${indexPattern.attributes.title}`,
- {}
- );
- return fields;
- }catch(error){
- return [];
- }
- }));
- }
- return indexPatterns.map((indexPattern, idx) => ({...indexPattern, _fields: indexPatternsFields[idx]}));
+ return indexPatterns.map((indexPattern) => ({...indexPattern, _fields: indexPattern?.attributes?.fields ? JSON.parse(indexPattern.attributes.fields) : []}));
}
/**
@@ -96,10 +78,7 @@ export class SavedObject {
static async existsOrCreateIndexPattern(patternID) {
const result = await SavedObject.existsIndexPattern(patternID);
if (!result.data) {
- let fields = '';
- if (satisfyPluginPlatformVersion('<7.11')) {
- fields = await SavedObject.getIndicesFields(patternID, WAZUH_INDEX_TYPE_ALERTS);
- }
+ const fields = await SavedObject.getIndicesFields(patternID, WAZUH_INDEX_TYPE_ALERTS);
await this.createSavedObject(
'index-pattern',
patternID,
@@ -156,21 +135,7 @@ export class SavedObject {
null,
true
);
- let indexPatternFields;
- if(satisfyPluginPlatformVersion('<7.11')){
- indexPatternFields = indexPatternData?.data?.attributes?.fields ? JSON.parse(indexPatternData.data.attributes.fields) : [];
- }else if(satisfyPluginPlatformVersion('>=7.11')){
- try{
- const {data: {fields}} = await GenericRequest.request(
- 'GET',
- `/api/index_patterns/_fields_for_wildcard?pattern=${indexPatternData.data.attributes.title}`,
- {}
- );
- indexPatternFields = fields;
- } catch (error) {
- indexPatternFields = [];
- }
- }
+ const indexPatternFields = indexPatternData?.data?.attributes?.fields ? JSON.parse(indexPatternData.data.attributes.fields) : [];
return { ...indexPatternData.data, ...{ _fields: indexPatternFields } };
} catch (error) {
if (error && error.response && error.response.status == 404) return false;
@@ -190,7 +155,7 @@ export class SavedObject {
params
);
- if (satisfyPluginPlatformVersion('<7.11') && type === 'index-pattern') {
+ if (type === 'index-pattern') {
await this.refreshFieldsOfIndexPattern(id, params.attributes.title, fields);
}
@@ -270,9 +235,7 @@ export class SavedObject {
*/
static async createWazuhIndexPattern(pattern) {
try {
- const fields = satisfyPluginPlatformVersion('<7.11')
- ? await SavedObject.getIndicesFields(pattern, WAZUH_INDEX_TYPE_ALERTS)
- : '';
+ const fields = await SavedObject.getIndicesFields(pattern, WAZUH_INDEX_TYPE_ALERTS);
await this.createSavedObject(
'index-pattern',
pattern,
diff --git a/public/react-services/wz-agents.ts b/public/react-services/wz-agents.ts
index abb2e3a3b2..5c0a5a4c83 100644
--- a/public/react-services/wz-agents.ts
+++ b/public/react-services/wz-agents.ts
@@ -9,7 +9,7 @@
*
* Find more information about this on the LICENSE file.
*/
-import { ErrorToastOptions } from 'kibana/public';
+import { ErrorToastOptions } from 'opensearch_dashboards/public';
import { WAZUH_AGENTS_OS_TYPE } from '../../common/constants';
import { getToasts } from '../kibana-services';
import { UnsupportedComponents } from '../utils/components-os-support';
diff --git a/public/react-services/wz-api-check.js b/public/react-services/wz-api-check.js
index cbf4bf1316..38cc0f957f 100644
--- a/public/react-services/wz-api-check.js
+++ b/public/react-services/wz-api-check.js
@@ -10,11 +10,11 @@
* Find more information about this on the LICENSE file.
*/
import { WazuhConfig } from './wazuh-config';
-import axios from 'axios';
import { AppState } from './app-state';
import { WzMisc } from '../factories/misc';
import { getHttp } from '../kibana-services';
import { PLUGIN_PLATFORM_REQUEST_HEADERS } from '../../common/constants';
+import { request } from '../services/request-handler';
export class ApiCheck {
static async checkStored(data, idChanged = false) {
@@ -40,7 +40,7 @@ export class ApiCheck {
AppState.setPatternSelector(configuration['ip.selector']);
}
- const response = await axios(options);
+ const response = await request(options);
if (response.error) {
return Promise.reject(response);
@@ -79,7 +79,7 @@ export class ApiCheck {
timeout: timeout || 20000
};
- const response = await axios(options);
+ const response = await request(options);
if (response.error) {
return Promise.reject(response);
diff --git a/public/react-services/wz-request.ts b/public/react-services/wz-request.ts
index 39819ddd21..e9087a273f 100644
--- a/public/react-services/wz-request.ts
+++ b/public/react-services/wz-request.ts
@@ -9,16 +9,16 @@
*
* Find more information about this on the LICENSE file.
*/
-import axios from 'axios';
import { AppState } from './app-state';
import { ApiCheck } from './wz-api-check';
import { WzAuthentication } from './wz-authentication';
import { WzMisc } from '../factories/misc';
import { WazuhConfig } from './wazuh-config';
-import { OdfeUtils } from '../utils';
import IApiResponse from './interfaces/api-response.interface';
import { getHttp } from '../kibana-services';
import { PLUGIN_PLATFORM_REQUEST_HEADERS } from '../../common/constants';
+import { request } from '../services/request-handler';
+
export class WzRequest {
static wazuhConfig: any;
@@ -32,13 +32,15 @@ export class WzRequest {
method,
path,
payload: any = null,
- extraOptions: { shouldRetry?: boolean, checkCurrentApiIsUp?: boolean } = {
+ extraOptions: { shouldRetry?: boolean, checkCurrentApiIsUp?: boolean, overwriteHeaders?: any } = {
shouldRetry: true,
- checkCurrentApiIsUp: true
+ checkCurrentApiIsUp: true,
+ overwriteHeaders: {}
}
) {
const shouldRetry = typeof extraOptions.shouldRetry === 'boolean' ? extraOptions.shouldRetry : true;
- const checkCurrentApiIsUp = typeof extraOptions.checkCurrentApiIsUp === 'boolean' ? extraOptions.checkCurrentApiIsUp : true;
+ const checkCurrentApiIsUp = typeof extraOptions.checkCurrentApiIsUp === 'boolean' ? extraOptions.checkCurrentApiIsUp : true;
+ const overwriteHeaders = typeof extraOptions.overwriteHeaders === 'object' ? extraOptions.overwriteHeaders : {};
try {
if (!method || !path) {
throw new Error('Missing parameters');
@@ -50,13 +52,13 @@ export class WzRequest {
const url = getHttp().basePath.prepend(path);
const options = {
method: method,
- headers: { ...PLUGIN_PLATFORM_REQUEST_HEADERS, 'content-type': 'application/json' },
+ headers: { ...PLUGIN_PLATFORM_REQUEST_HEADERS, 'content-type': 'application/json', ...overwriteHeaders },
url: url,
data: payload,
timeout: timeout,
};
- const data = await axios(options);
+ const data = await request(options);
if (data['error']) {
throw new Error(data['error']);
@@ -64,7 +66,6 @@ export class WzRequest {
return Promise.resolve(data);
} catch (error) {
- OdfeUtils.checkOdfeSessionExpired(error);
//if the requests fails, we need to check if the API is down
if(checkCurrentApiIsUp){
const currentApi = JSON.parse(AppState.getCurrentAPI() || '{}');
@@ -119,7 +120,7 @@ export class WzRequest {
try {
if (!method || !path || !body) {
throw new Error('Missing parameters');
- }
+ }
const id = JSON.parse(AppState.getCurrentAPI()).id;
const requestData = { method, path, body, id };
const response = await this.genericReq('POST', '/api/request', requestData, options);
diff --git a/public/react-services/wz-security-opendistro.js b/public/react-services/wz-security-opensearch-dashboards-security.js
similarity index 95%
rename from public/react-services/wz-security-opendistro.js
rename to public/react-services/wz-security-opensearch-dashboards-security.js
index 839c1dc900..33fa04a5ed 100644
--- a/public/react-services/wz-security-opendistro.js
+++ b/public/react-services/wz-security-opensearch-dashboards-security.js
@@ -13,7 +13,7 @@
import { GenericRequest } from "./generic-request";
import { WzRequest } from './wz-request';
-export class WzSecurityOpendistro {
+export class WzSecurityOpenSearchDashboardsSecurity {
static async getUsers() {
try {
const users = await GenericRequest.request(
diff --git a/public/react-services/wz-security-opendistro.test.js b/public/react-services/wz-security-opensearch-dashboards-security.test.js
similarity index 87%
rename from public/react-services/wz-security-opendistro.test.js
rename to public/react-services/wz-security-opensearch-dashboards-security.test.js
index 4bff8bc02c..035722bc27 100644
--- a/public/react-services/wz-security-opendistro.test.js
+++ b/public/react-services/wz-security-opensearch-dashboards-security.test.js
@@ -11,7 +11,7 @@
* Find more information about this on the LICENSE file.
*/
-import { WzSecurityOpendistro } from './wz-security-opendistro';
+import { WzSecurityOpenSearchDashboardsSecurity } from './wz-security-opensearch-dashboards-security';
jest.mock('./generic-request', () => ({
GenericRequest: {
@@ -37,7 +37,7 @@ jest.mock('./generic-request', () => ({
}));
describe('Wazuh Internal Users', () => {
it('Should return the ODFE internal users', async () => {
- const users = await WzSecurityOpendistro.getUsers();
+ const users = await WzSecurityOpenSearchDashboardsSecurity.getUsers();
const expected_result = [
{ username: 'wazuh', email: 'wazuh@email.com', full_name: 'wazuh surname', roles: [] },
];
diff --git a/public/react-services/wz-security-xpack.js b/public/react-services/wz-security-xpack.js
deleted file mode 100644
index 97f53446cf..0000000000
--- a/public/react-services/wz-security-xpack.js
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Wazuh app - Generic request
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-
-import { GenericRequest } from "./generic-request";
-import { WzRequest } from './wz-request';
-
-export class WzSecurityXpack {
- static async getUsers() {
- try {
- const users = await GenericRequest.request(
- "GET",
- `/internal/security/users`,
- {}
- );
- return users.data;
- } catch (error) {
- throw error;
- }
- }
-
- static async createUser(username, params) {
- try {
- const response = await GenericRequest.request(
- "POST",
- `/internal/security/users/${username}`,
- { ...params }
- );
- return response.data;
- } catch (error) {
- throw error;
- }
- }
-
- static async editUser(username, params) {
- try {
- const response = await GenericRequest.request(
- "POST",
- `/internal/security/users/${username}`,
- { ...params }
- );
- return response.data;
- } catch (error) {
- throw error;
- }
- }
-
- static async deleteUser(username) {
- try {
- const response = await GenericRequest.request(
- "DELETE",
- `/internal/security/users/${username}`
- );
- return response.data;
- } catch (error) {
- throw error;
- }
- }
-
- static async createPolicy(params) {
- try {
- const response = await WzRequest.apiReq(
- "POST",
- '/security/policies',
- { ...params }
- );
- return response.data;
- } catch (error) {
- throw error;
- }
- }
-}
diff --git a/public/react-services/wz-security-xpack.test.js b/public/react-services/wz-security-xpack.test.js
deleted file mode 100644
index fc2eafc2e5..0000000000
--- a/public/react-services/wz-security-xpack.test.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Wazuh app
- *
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-
-import { WzSecurityXpack } from './wz-security-xpack';
-
-jest.mock('./generic-request', () => ({
- GenericRequest: {
- request: (method, path) => {
- return {
- data: {
- username: 'wazuh_system',
- roles: ['kibana_system', 'wazuh'],
- full_name: 'wazuh',
- email: '',
- metadata: {},
- enabled: true,
- },
- };
- },
- },
-}));
-jest.mock('./wz-request', () => ({
- WzRequest: {
- apiReq: (method, path, params) => {
- return {
- data: {
- id: 3,
- name: 'agents_all_groups',
- policy: {
- actions: [
- 'group:read',
- 'group:delete',
- 'group:update_config',
- 'group:modify_assignments',
- ],
- resources: ['group:id:*'],
- effect: 'allow',
- },
- roles: [1, 5],
- },
- };
- },
- },
-}));
-describe('Wazuh Internal Users with X-Pack', () => {
- it('Should create a X-Pack policy', async () => {
- const users = await WzSecurityXpack.createPolicy();
- const expected_result = {
- id: 3,
- name: 'agents_all_groups',
- policy: {
- actions: ['group:read', 'group:delete', 'group:update_config', 'group:modify_assignments'],
- resources: ['group:id:*'],
- effect: 'allow',
- },
- roles: [1, 5],
- };
- expect(users).toEqual(expected_result);
- });
- it('Should create,edit and delete a X-Pack user and also gets all the X-pack internal users', async () => {
- const createUser = await WzSecurityXpack.createUser();
- const users = await WzSecurityXpack.getUsers();
- const editUser = await WzSecurityXpack.editUser();
- const deleteUser = await WzSecurityXpack.deleteUser();
- const expected_result = {
- username: 'wazuh_system',
- roles: ['kibana_system', 'wazuh'],
- full_name: 'wazuh',
- email: '',
- metadata: {},
- enabled: true,
- };
- expect(createUser).toEqual(expected_result);
- expect(editUser).toEqual(expected_result);
- expect(deleteUser).toEqual(expected_result);
- expect(users).toEqual(expected_result);
- });
-});
diff --git a/public/react-services/wz-user-permissions.ts b/public/react-services/wz-user-permissions.ts
index 1b720620ba..523ad0777d 100644
--- a/public/react-services/wz-user-permissions.ts
+++ b/public/react-services/wz-user-permissions.ts
@@ -21,7 +21,7 @@ export class WzUserPermissions{
const missingOrPermissions = WzUserPermissions.checkMissingUserPermissions(permission, userPermissions);
return Array.isArray(missingOrPermissions) ? missingOrPermissions.length === permission.length : missingOrPermissions;
}
-
+
const isGenericResource = (permission.resource.match(':\\*') || []).index === permission.resource.length - 2
const actionName = typeof permission === 'string' ? permission : permission.action;
@@ -48,8 +48,8 @@ export class WzUserPermissions{
const simplePermission = (resource: string) => {
return (
![actionResource, actionResourceAll].includes(resource) &&
- (resource.match(actionResource.replace('*', '\\*')) ||
- resource.match(actionResourceAll.replace('*', '\*')))
+ (resource.match(actionResource.replace(/\*/g, '.+')) ||
+ resource.match(actionResourceAll.replace(/\*/g, '.+')))
);
};
@@ -102,10 +102,10 @@ export class WzUserPermissions{
return userPermissions[actionName][actionResource]
? notAllowInWazuhPermissions(actionResource)
: Object.keys(userPermissions[actionName]).some((resource) => {
- return resource.match(actionResourceAll.replace('*', '\\*')) !== null;
+ return resource.match(actionResourceAll.replace(/\*/g, '.+')) !== null;
})
? Object.keys(userPermissions[actionName]).some((resource) => {
- if (resource.match(actionResourceAll.replace('*', '\\*'))) {
+ if (resource.match(actionResourceAll.replace(/\*/g, '.+'))) {
return notAllowInWazuhPermissions(resource);
}
})
diff --git a/public/redux/actions/rulesetActions.js b/public/redux/actions/rulesetActions.js
deleted file mode 100644
index 168f74a21c..0000000000
--- a/public/redux/actions/rulesetActions.js
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Wazuh app - React component for registering agents.
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-
-/**
- * Update the ruleset section
- * @param {String} section
- */
-export const updateRulesetSection = section => {
- return {
- type: 'UPDATE_RULESET_SECTION',
- section
- };
-};
-
-/**
- * Update the files content
- * @param {String} content
- */
-export const updateFileContent = content => {
- return {
- type: 'UPDATE_FILE_CONTENT',
- content: content
- };
-};
-
-/**
- * Toggle the modal confirm of the ruleset table
- * @param {Boolean} showModal
- */
-export const updateShowModal = showModal => {
- return {
- type: 'UPDATE_SHOW_MODAL',
- showModal: showModal
- };
-};
-
-/**
- * Update the list of items to remove
- * @param {Array} itemList
- */
-export const updateListItemsForRemove = itemList => {
- return {
- type: 'UPDATE_LIST_ITEMS_FOR_REMOVE',
- itemList: itemList
- };
-};
-
-export const updateSortField = sortField => {
- return {
- type: 'UPDATE_SORT_FIELD',
- sortField: sortField
- };
-};
-
-export const updateSortDirection = sortDirection => {
- return {
- type: 'UPDATE_SORT_DIRECTION',
- sortDirection: sortDirection
- };
-};
-
-export const updateDefaultItems = defaultItems => {
- return {
- type: 'UPDATE_DEFAULT_ITEMS',
- defaultItems: defaultItems
- };
-};
-
-/**
- * Update the lists content
- * @param {String} content
- */
-export const updateListContent = content => {
- return {
- type: 'UPDATE_LIST_CONTENT',
- content: content
- };
-};
-
-/**
- * Update the loading status
- * @param {Boolean} loading
- */
-export const updateLoadingStatus = loading => {
- return {
- type: 'UPDATE_LOADING_STATUS',
- status: loading
- };
-};
-
-/**
- * Reset the ruleset store
- */
-export const resetRuleset = () => {
- return {
- type: 'RESET'
- };
-};
-
-/**
- * Toggle show files
- * @param {Boolean} status
- */
-export const toggleShowFiles = status => {
- return {
- type: 'TOGGLE_SHOW_FILES',
- status: status
- };
-};
-
-/**
- * Update the rule info
- * @param {String} info
- */
-export const updateRuleInfo = info => {
- return {
- type: 'UPDATE_RULE_INFO',
- info: info
- };
-};
-
-/**
- * Update the decoder info
- * @param {String} info
- */
-export const updateDecoderInfo = info => {
- return {
- type: 'UPDATE_DECODER_INFO',
- info: info
- };
-};
-
-/**
- * Toggle the updating of the table
- * @param {Boolean} isProcessing
- */
-export const updateIsProcessing = isProcessing => {
- return {
- type: 'UPDATE_IS_PROCESSING',
- isProcessing: isProcessing
- };
-};
-
-/**
- * Set the page index value of the table
- * @param {Number} pageIndex
- */
-export const updatePageIndex = pageIndex => {
- return {
- type: 'UPDATE_PAGE_INDEX',
- pageIndex: pageIndex
- };
-};
-
-/**
- * Update the filters
- * @param {string} filters
- */
-export const updateFilters = filters => {
- return {
- type: 'UPDATE_RULE_FILTERS',
- filters: filters
- };
-};
-
-export const cleanFilters = () => {
- return {
- type: 'CLEAN_FILTERS'
- };
-};
-
-export const cleanInfo = () => {
- return {
- type: 'CLEAN_INFO'
- };
-};
-
-export const cleanFileContent = () => {
- return {
- type: 'CLEAN_CONTENT'
- };
-};
-
-export const updteAddingRulesetFile = content => {
- return {
- type: 'UPDATE_ADDING_RULESET_FILE',
- content: content
- };
-};
-
-export const updateError = error => {
- return {
- type: 'UPDATE_ERROR',
- error: error
- };
-};
diff --git a/public/redux/reducers/appConfigReducers.ts b/public/redux/reducers/appConfigReducers.ts
index 4157abf4ef..5f3d43fd92 100644
--- a/public/redux/reducers/appConfigReducers.ts
+++ b/public/redux/reducers/appConfigReducers.ts
@@ -11,14 +11,14 @@
*/
import { Reducer } from 'redux';
-import { WAZUH_DEFAULT_APP_CONFIG } from '../../../common/constants';
+import { getSettingsDefault } from '../../../common/services/settings';
import { AppConfigState, ResolverAction } from '../types';
const initialState: AppConfigState = {
isLoading: false,
isReady: false,
hasError: false,
- data: WAZUH_DEFAULT_APP_CONFIG,
+ data: getSettingsDefault(),
};
const appConfigReducer: Reducer = (
diff --git a/public/redux/reducers/rootReducers.js b/public/redux/reducers/rootReducers.js
index c85271cf46..34be93893a 100644
--- a/public/redux/reducers/rootReducers.js
+++ b/public/redux/reducers/rootReducers.js
@@ -11,7 +11,6 @@
*/
import { combineReducers } from 'redux';
-import rulesetReducers from './rulesetReducers';
import groupsReducers from './groupsReducers';
import statusReducers from './statusReducers';
import reportingReducers from './reportingReducers';
@@ -25,7 +24,6 @@ import toolsReducers from './toolsReducers';
import appConfig from './appConfigReducers';
export default combineReducers({
- rulesetReducers,
groupsReducers,
statusReducers,
reportingReducers,
diff --git a/public/redux/reducers/rulesetReducers.js b/public/redux/reducers/rulesetReducers.js
deleted file mode 100644
index 560b38fe3f..0000000000
--- a/public/redux/reducers/rulesetReducers.js
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Wazuh app - React component for registering agents.
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-
-const initialState = {
- addingRulesetFile: false,
- decoderInfo: false,
- error: false,
- fileContent: false,
- filters: [],
- isLoading: false,
- isProcessing: false,
- itemList: [],
- items: [],
- listInfo: false,
- pageIndex: 0,
- ruleInfo: false,
- section: '',
- showingFiles: false,
- showModal: false,
- sortDirection: 'asc',
- sortField: 'id',
- defaultItems: []
-};
-
-const rulesetReducers = (state = initialState, action) => {
- switch (action.type) {
- case 'CLEAN_CONTENT':
- return Object.assign({}, state, { fileContent: false, error: false });
- case 'CLEAN_FILTERS':
- return Object.assign({}, state, { filters: [] });
- case 'CLEAN_INFO':
- return Object.assign({}, state, {
- decoderInfo: false,
- ruleInfo: false,
- listInfo: false,
- fileContent: false,
- addingRulesetFile: false,
- error: false
- });
- case 'RESET':
- return initialState;
- case 'TOGGLE_SHOW_FILES':
- return Object.assign({}, state, {
- showingFiles: action.status,
- error: false
- });
- case 'UPDATE_ADDING_RULESET_FILE':
- return Object.assign({}, state, {
- addingRulesetFile: action.content,
- error: false
- });
- case 'UPDATE_DECODER_INFO':
- return Object.assign({}, state, {
- decoderInfo: action.info,
- ruleInfo: false,
- listInfo: false,
- error: false
- });
- case 'UPDATE_DEFAULT_ITEMS':
- return Object.assign({}, state, {
- defaultItems: action.defaultItems,
- error: false
- });
- case 'UPDATE_ERROR':
- return Object.assign({}, state, { error: action.error });
- case 'UPDATE_FILE_CONTENT':
- return Object.assign({}, state, {
- fileContent: action.content,
- decoderInfo: false,
- ruleInfo: false,
- listInfo: false,
- error: false
- });
- case 'UPDATE_RULE_FILTERS':
- return Object.assign({}, state, {
- filters: action.filters,
- isProcessing: true,
- error: false
- });
- case 'UPDATE_IS_PROCESSING':
- return Object.assign({}, state, {
- isProcessing: action.isProcessing,
- ruleInfo: false,
- listInfo: false,
- error: false
- });
- case 'UPDATE_ITEMS':
- return Object.assign({}, state, { items: action.items, error: false });
- case 'REMOVE_ITEMS':
- return Object.assign({}, state, { items: [], error: false });
- case 'UPDATE_LIST_CONTENT':
- return Object.assign({}, state, {
- fileContent: false,
- decoderInfo: false,
- ruleInfo: false,
- listInfo: action.content,
- error: false
- });
- case 'UPDATE_LIST_ITEMS_FOR_REMOVE':
- return Object.assign({}, state, {
- itemList: action.itemList,
- error: false
- });
- case 'UPDATE_LOADING_STATUS':
- return Object.assign({}, state, {
- isLoading: action.status,
- error: false
- });
- case 'UPDATE_PAGE_INDEX':
- return Object.assign({}, state, {
- pageIndex: action.pageIndex,
- ruleInfo: false,
- listInfo: false,
- error: false
- });
- case 'UPDATE_RULE_INFO':
- return Object.assign({}, state, {
- ruleInfo: action.info,
- decoderInfo: false,
- listInfo: false,
- error: false
- });
- case 'UPDATE_RULESET_SECTION':
- return Object.assign({}, state, {
- section: action.section,
- showingFiles: false,
- error: false
- });
- case 'UPDATE_SHOW_MODAL':
- return Object.assign({}, state, {
- showModal: action.showModal,
- error: false
- });
- case 'UPDATE_SORT_DIRECTION':
- return Object.assign({}, state, {
- sortDirection: action.sortDirection,
- error: false
- });
- case 'UPDATE_SORT_FIELD':
- return Object.assign({}, state, {
- sortField: action.sortField,
- error: false
- });
- default:
- return state;
- }
-};
-
-export default rulesetReducers;
diff --git a/public/services/ipv6-services.test.js b/public/services/ipv6-services.test.js
new file mode 100644
index 0000000000..9887751b65
--- /dev/null
+++ b/public/services/ipv6-services.test.js
@@ -0,0 +1,21 @@
+import { compressIPv6 } from "./ipv6-services";
+
+describe('[settings] Input validation', () => {
+ it.each`
+ value | expectedValidation
+ ${'192.168.100.1'} | ${'192.168.100.1'}
+ ${'FE80:1234:2223:A000:2202:B3FF:FE1E:8329'} | ${'FE80:1234:2223:A000:2202:B3FF:FE1E:8329'}
+ ${'FE80:0034:0223:A000:0002:B3FF:0000:8329'} | ${'FE80:34:223:A000:2:B3FF:0:8329'}
+ ${'FE80:1234:2223:0000:0000:B3FF:FE1E:8329'} | ${'FE80:1234:2223::B3FF:FE1E:8329'}
+ ${'FE80:0000:0000:A000:0000:0000:0000:8329'} | ${'FE80:0:0:A000::8329'}
+ ${'FE80:0000:0000:0000:2202:00FF:0E1E:8329'} | ${'FE80::2202:FF:E1E:8329'}
+ ${'0000:0000:0000:0000:2202:00FF:0E1E:8329'} | ${'::2202:FF:E1E:8329'}
+ ${'2202:00FF:0E1E:8329:2202:0000:0000:0000'} | ${'2202:FF:E1E:8329:2202::'}
+ ${'0000:0000:0000:0000:0000:0000:0000:0000'} | ${'::'}
+ ${undefined} | ${undefined}
+ ${234} | ${234}
+ `('$value | $expectedValidation', ({ value, expectedValidation }) => {
+ expect(
+ compressIPv6(value)).toBe(expectedValidation);
+ });
+});
diff --git a/public/services/ipv6-services.ts b/public/services/ipv6-services.ts
new file mode 100644
index 0000000000..ac7fe331c2
--- /dev/null
+++ b/public/services/ipv6-services.ts
@@ -0,0 +1,21 @@
+export function compressIPv6 (ip: string) {
+ if (typeof (ip) !== 'string') {
+ return ip;
+ }
+ if (ip?.split(':').length !== 8) {
+ return ip;
+ }
+
+ let output = ip.split(':').map(terms => terms.replace(/\b0+/g, '') || '0').join(':');
+ const zeros = Array.from(output.matchAll(/\b:?(?:0+:?){2,}/g));
+ if (zeros.length > 0) {
+ let max = '';
+ zeros.forEach(item => {
+ if (item[0].replace(/:/g, '').length > max.replace(/:/g, '').length) {
+ max = item[0];
+ }
+ });
+ output = output.replace(max, '::');
+ }
+ return output;
+}
diff --git a/public/services/request-handler.js b/public/services/request-handler.js
new file mode 100644
index 0000000000..119668839c
--- /dev/null
+++ b/public/services/request-handler.js
@@ -0,0 +1,57 @@
+import axios from 'axios';
+import { HTTP_STATUS_CODES } from '../../common/constants';
+
+let allow = true;
+export let unregisterInterceptor = () => { };
+const source = axios.CancelToken.source();
+
+const disableRequests = () => {
+ allow = false;
+ source.cancel('Requests cancelled');
+ return;
+}
+
+export const initializeInterceptor = (core) => {
+ unregisterInterceptor = core.http.intercept({
+ responseError: (httpErrorResponse, controller) => {
+ if (
+ httpErrorResponse.response?.status === HTTP_STATUS_CODES.UNAUTHORIZED
+ ) {
+ disableRequests();
+ }
+ },
+ request: (current, controller) => {
+ if (
+ !allow
+ ) {
+ throw new Error("Disable request");
+ };
+ },
+ });
+}
+
+export const request = async (options = {}) => {
+ if (!allow) {
+ return Promise.reject('Requests are disabled');
+ };
+ if (!options.method || !options.url) {
+ return Promise.reject("Missing parameters");
+ };
+ options = {
+ ...options, cancelToken: source.token
+ };
+
+ if (allow) {
+ try {
+ const requestData = await axios(options);
+ return Promise.resolve(requestData);
+ }
+ catch (e) {
+ if (e.response?.data?.message === 'Unauthorized' || e.response?.data?.message === 'Authentication required') {
+ disableRequests();
+ window.location.reload();
+ }
+ return Promise.reject(e);
+ }
+ }
+}
diff --git a/public/services/resolves/get-config.js b/public/services/resolves/get-config.js
index ba4aa543c1..63f055e951 100644
--- a/public/services/resolves/get-config.js
+++ b/public/services/resolves/get-config.js
@@ -10,10 +10,10 @@
* Find more information about this on the LICENSE file.
*/
-import { WAZUH_DEFAULT_APP_CONFIG } from '../../../common/constants';
+import { getSettingsDefault } from '../../../common/services/settings';
export async function getWzConfig($q, genericReq, wazuhConfig) {
- const defaultConfig = { ...WAZUH_DEFAULT_APP_CONFIG };
+ const defaultConfig = getSettingsDefault();
try {
const config = await genericReq.request('GET', '/utils/configuration', {});
diff --git a/public/services/resolves/settings-wizard.js b/public/services/resolves/settings-wizard.js
index 48949bb406..35c454a307 100644
--- a/public/services/resolves/settings-wizard.js
+++ b/public/services/resolves/settings-wizard.js
@@ -169,10 +169,10 @@ export function settingsWizard(
if (data.data.length > 0) {
// Try to set some API entry as default
const defaultApi = await tryToSetDefault(data.data);
- setUpCredentials('Wazuh App: Default API has been updated.', defaultApi);
+ setUpCredentials('Default Wazuh API has been updated.', defaultApi);
$location.path('health-check');
} else {
- setUpCredentials('Wazuh App: Please set up Wazuh API credentials.');
+ setUpCredentials('Please set up Wazuh API credentials.');
}
deferred.resolve();
})
@@ -198,15 +198,15 @@ export function settingsWizard(
if (data.data.length > 0) {
// Try to set some as default
const defaultApi = await tryToSetDefault(data.data);
- setUpCredentials('Wazuh App: Default API has been updated.', defaultApi);
+ setUpCredentials('Default Wazuh API has been updated.', defaultApi);
$location.path('health-check');
} else {
- setUpCredentials('Wazuh App: Please set up Wazuh API credentials.', false);
+ setUpCredentials('Please set up Wazuh API credentials.', false);
}
}
})
.catch((error) => {
- setUpCredentials('Wazuh App: Please set up Wazuh API credentials.');
+ setUpCredentials('Please set up Wazuh API credentials.');
});
}
}
diff --git a/public/styles/7.9.0/index.dark.scss b/public/styles/7.9.0/index.dark.scss
deleted file mode 100644
index 74be7f9042..0000000000
--- a/public/styles/7.9.0/index.dark.scss
+++ /dev/null
@@ -1,2803 +0,0 @@
-.invisible {
- visibility: hidden; }
-
-.echChartStatus {
- visibility: hidden;
- pointer-events: none;
- z-index: -100000;
- width: 0;
- height: 0;
- position: absolute; }
-
-.echChart {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- height: 100%;
- position: relative; }
- .echChart--column {
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column; }
-
-.echContainer {
- -webkit-box-flex: 1;
- -webkit-flex: 1;
- -ms-flex: 1;
- flex: 1;
- position: relative; }
-
-.echChartPointerContainer {
- position: absolute;
- top: 0;
- bottom: 0;
- right: 0;
- left: 0;
- -webkit-box-sizing: border-box;
- box-sizing: border-box;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none; }
-
-.echChartResizer {
- z-index: -10000000;
- position: absolute;
- bottom: 0;
- top: 0;
- left: 0;
- right: 0;
- -webkit-box-sizing: border-box;
- box-sizing: border-box; }
-
-#echAnnotationContainerPortal {
- position: absolute;
- pointer-events: none; }
-
-.echAnnotation {
- pointer-events: none;
- position: absolute;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- font-size: 12px;
- font-weight: 700; }
-
-.echAnnotation--hidden,
-.echAnnotation__tooltip--hidden {
- opacity: 0; }
-
-.echAnnotation__tooltip {
- -webkit-box-shadow: 0 12px 24px 0 rgba(0, 0, 0, 0.1), 0 6px 12px 0 rgba(0, 0, 0, 0.1), 0 4px 4px 0 rgba(0, 0, 0, 0.1), 0 2px 2px 0 rgba(0, 0, 0, 0.1);
- box-shadow: 0 12px 24px 0 rgba(0, 0, 0, 0.1), 0 6px 12px 0 rgba(0, 0, 0, 0.1), 0 4px 4px 0 rgba(0, 0, 0, 0.1), 0 2px 2px 0 rgba(0, 0, 0, 0.1);
- border-radius: 4px;
- background-color: black;
- color: #FFF;
- z-index: 9000;
- max-width: 256px;
- overflow-wrap: break-word;
- font-size: 14px;
- font-size: 0.875rem;
- line-height: 1.5;
- padding: 12px;
- font-size: 12px;
- font-size: 0.75rem;
- line-height: 1.5;
- position: absolute;
- padding: 0;
- -webkit-transition: opacity 250ms;
- transition: opacity 250ms;
- pointer-events: none;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none; }
-
-.echAnnotation__header {
- font-weight: 700;
- border-bottom: solid 1px #333333;
- padding-bottom: 4px;
- margin-bottom: 4px;
- padding: 4px 8px; }
-
-.echAnnotation__details {
- padding: 4px 8px; }
-
-#echTooltipContainerPortal {
- position: absolute;
- pointer-events: none;
- z-index: 10000000; }
-
-.echTooltip {
- position: absolute;
- -webkit-box-shadow: 0 12px 24px 0 rgba(0, 0, 0, 0.1), 0 6px 12px 0 rgba(0, 0, 0, 0.1), 0 4px 4px 0 rgba(0, 0, 0, 0.1), 0 2px 2px 0 rgba(0, 0, 0, 0.1);
- box-shadow: 0 12px 24px 0 rgba(0, 0, 0, 0.1), 0 6px 12px 0 rgba(0, 0, 0, 0.1), 0 4px 4px 0 rgba(0, 0, 0, 0.1), 0 2px 2px 0 rgba(0, 0, 0, 0.1);
- border-radius: 4px;
- background-color: black;
- color: #FFF;
- z-index: 9000;
- max-width: 256px;
- overflow-wrap: break-word;
- font-size: 14px;
- font-size: 0.875rem;
- line-height: 1.5;
- padding: 12px;
- font-size: 12px;
- font-size: 0.75rem;
- line-height: 1.5;
- padding: 0;
- -webkit-transition: opacity 250ms;
- transition: opacity 250ms;
- pointer-events: none;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- margin-bottom: 4px; }
- .echTooltip__list {
- padding: 4px; }
- .echTooltip__header {
- font-weight: 700;
- border-bottom: solid 1px #333333;
- padding-bottom: 4px;
- margin-bottom: 4px;
- margin-bottom: 0;
- padding: 4px 8px; }
- .echTooltip__item {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- padding: 3px;
- -webkit-box-sizing: border-box;
- box-sizing: border-box;
- border-left: 4px solid transparent;
- min-width: 1px; }
- .echTooltip__label {
- overflow-wrap: break-word;
- word-wrap: break-word;
- min-width: 1px;
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 auto;
- -ms-flex: 1 1 auto;
- flex: 1 1 auto; }
- .echTooltip__value {
- font-weight: 700;
- text-align: right;
- -webkit-font-feature-settings: 'tnum';
- font-feature-settings: 'tnum';
- margin-left: 8px; }
- .echTooltip__rowHighlighted {
- background-color: rgba(255, 255, 255, 0.1); }
- .echTooltip--hidden {
- opacity: 0; }
-
-.echIcon {
- -webkit-flex-shrink: 0;
- -ms-flex-negative: 0;
- flex-shrink: 0;
- display: inline-block;
- vertical-align: middle;
- fill: currentColor; }
- .echIcon svg {
- -webkit-transform: translate(0, 0);
- transform: translate(0, 0); }
- .echIcon:focus {
- opacity: 1;
- background: #232635; }
-
-.echLegend--top .echLegendList, .echLegend--bottom .echLegendList {
- display: grid;
- grid-column-gap: 24px;
- grid-row-gap: 8px;
- margin-top: 8px;
- margin-bottom: 8px; }
- @media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {
- .echLegend--top .echLegendList, .echLegend--bottom .echLegendList {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: horizontal;
- -webkit-box-direction: normal;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-flex-wrap: wrap;
- -ms-flex-wrap: wrap;
- flex-wrap: wrap; } }
-
-.echLegend--left .echLegendList, .echLegend--right .echLegendList {
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column; }
-
-.echLegend--top, .echLegend--left {
- -webkit-box-ordinal-group: 1;
- -webkit-order: 0;
- -ms-flex-order: 0;
- order: 0; }
-
-.echLegend--bottom, .echLegend--right {
- -webkit-box-ordinal-group: 2;
- -webkit-order: 1;
- -ms-flex-order: 1;
- order: 1; }
-
-.echLegend--debug {
- background: red; }
-
-.echLegend .echLegendListContainer {
- scrollbar-width: thin;
- height: 100%;
- overflow-y: auto;
- -webkit-mask-image: linear-gradient(to bottom, rgba(255, 0, 0, 0.1) 0%, red 7.5px, red calc(100% - 7.5px), rgba(255, 0, 0, 0.1) 100%);
- mask-image: linear-gradient(to bottom, rgba(255, 0, 0, 0.1) 0%, red 7.5px, red calc(100% - 7.5px), rgba(255, 0, 0, 0.1) 100%);
- width: 100%;
- overflow-y: auto;
- overflow-x: hidden; }
- .echLegend .echLegendListContainer::-webkit-scrollbar {
- width: 16px;
- height: 16px; }
- .echLegend .echLegendListContainer::-webkit-scrollbar-thumb {
- background-color: rgba(152, 162, 179, 0.5);
- border: 6px solid transparent;
- background-clip: content-box; }
- .echLegend .echLegendListContainer::-webkit-scrollbar-corner, .echLegend .echLegendListContainer::-webkit-scrollbar-track {
- background-color: transparent; }
-
-.echLegendItem {
- color: #DFE5EF;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-wrap: nowrap;
- -ms-flex-wrap: nowrap;
- flex-wrap: nowrap;
- -webkit-box-pack: justify;
- -webkit-justify-content: space-between;
- -ms-flex-pack: justify;
- justify-content: space-between;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- -webkit-box-align: center;
- -webkit-align-items: center;
- -ms-flex-align: center;
- align-items: center;
- width: 100%; }
- .echLegendItem:not(.echLegendItem--hidden) .echLegendItem__color--changable {
- cursor: pointer; }
- .echLegendItem__color {
- margin-right: 4px; }
- .echLegendItem__visibility {
- margin-right: 4px; }
- .echLegendItem__visibility:hover {
- cursor: pointer; }
- .echLegendItem__label {
- font-size: 12px;
- font-size: 0.75rem;
- line-height: 1.5;
- max-width: 100%;
- overflow: hidden !important;
- text-overflow: ellipsis !important;
- white-space: nowrap !important;
- word-wrap: normal !important;
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 auto;
- -ms-flex: 1 1 auto;
- flex: 1 1 auto; }
- .echLegendItem__label--clickable:hover {
- cursor: pointer;
- text-decoration: underline; }
- .echLegendItem__extra {
- font-size: 12px;
- font-size: 0.75rem;
- line-height: 1.5;
- text-align: right;
- margin-left: 4px;
- -webkit-font-feature-settings: 'tnum';
- font-feature-settings: 'tnum'; }
- .echLegendItem__extra--hidden {
- display: none; }
- .echLegendItem--right, .echLegendItem--left {
- padding-top: 4px;
- padding-bottom: 4px; }
- @media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {
- .echLegendItem {
- padding-top: 4px;
- padding-bottom: 4px; }
- .echLegendItem--bottom, .echLegendItem--top {
- width: 200px;
- margin-right: 24px; } }
- .echLegendItem--hidden {
- color: #98A2B3; }
-
-.echReactiveChart_unavailable {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-align: center;
- -webkit-align-items: center;
- -ms-flex-align: center;
- align-items: center;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
- width: 100%;
- height: 100%;
- font-size: 12px;
- font-size: 0.75rem;
- line-height: 1.5;
- color: #98A2B3; }
-
-.echHighlighter {
- position: absolute;
- z-index: 1000;
- pointer-events: none;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- width: 100%;
- height: 100%; }
-
-.echHighlighterOverlay__fill {
- fill: rgba(255, 255, 255, 0.2); }
-
-.echHighlighterOverlay__stroke {
- stroke: rgba(255, 255, 255, 0.2); }
-
-.echHighlighter__mask {
- fill: rgba(29, 30, 36, 0.5); }
-
-.echCrosshair,
-.echCrosshair__band,
-.echCrosshair__line {
- position: absolute;
- pointer-events: none; }
-
-.echCrosshair__line {
- z-index: 8000; }
-
-.echBrushTool {
- position: absolute;
- top: 0;
- left: 0;
- margin: 0;
- padding: 0;
- -webkit-box-sizing: border-box;
- box-sizing: border-box;
- overflow: hidden;
- pointer-events: none; }
-
-.echCanvasRenderer {
- position: absolute;
- top: 0;
- left: 0;
- padding: 0;
- margin: 0;
- border: 0;
- background: transparent; }
-
-.echAnnotation {
- font-size: 12px;
- font-weight: 700; }
-
-input.ng-invalid.ng-dirty, input.ng-invalid.ng-touched,
-textarea.ng-invalid.ng-dirty,
-textarea.ng-invalid.ng-touched,
-select.ng-invalid.ng-dirty,
-select.ng-invalid.ng-touched {
- border-color: #F66 !important; }
-
-input[type='radio'][disabled],
-fieldset[disabled] input[type='radio'],
-input[type='checkbox'][disabled],
-fieldset[disabled]
-input[type='checkbox'],
-.radio[disabled],
-fieldset[disabled]
-.radio,
-.radio-inline[disabled],
-fieldset[disabled]
-.radio-inline,
-.checkbox[disabled],
-fieldset[disabled]
-.checkbox,
-.checkbox-inline[disabled],
-fieldset[disabled]
-.checkbox-inline {
- cursor: default;
- opacity: 0.8; }
-
-.checkbox label {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-align: center;
- -webkit-align-items: center;
- -ms-flex-align: center;
- align-items: center;
- padding-left: 0 !important; }
- .checkbox label input[type='checkbox'] {
- float: none;
- margin: 0 4px;
- position: static; }
-
-.chrHeaderWrapper:not(.headerWrapper) .content {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: horizontal;
- -webkit-box-direction: normal;
- -webkit-flex-flow: row nowrap;
- -ms-flex-flow: row nowrap;
- flex-flow: row nowrap;
- width: 100%;
- height: 100%;
- overflow: hidden; }
-
-.application > *,
-.app-container > * {
- position: relative; }
-
-.application > config,
-.app-container > config {
- z-index: 1; }
-
-.application > navbar,
-.app-container > navbar {
- padding-bottom: 8px; }
-
-.application .globalQueryBar,
-.app-container .globalQueryBar {
- padding: 0px 8px 8px 8px; }
-
-.application > nav,
-.application > navbar,
-.app-container > nav,
-.app-container > navbar {
- z-index: 2 !important; }
-
-.application {
- position: relative;
- z-index: 0;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-flex: 1;
- -webkit-flex-grow: 1;
- -ms-flex-positive: 1;
- flex-grow: 1;
- -webkit-flex-shrink: 0;
- -ms-flex-negative: 0;
- flex-shrink: 0;
- -webkit-flex-basis: auto;
- -ms-flex-preferred-size: auto;
- flex-basis: auto;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column; }
- .application > * {
- -webkit-flex-shrink: 0;
- -ms-flex-negative: 0;
- flex-shrink: 0; }
-
-[fixed-scroll] {
- overflow-x: auto;
- padding-bottom: 0; }
- [fixed-scroll] + .fixed-scroll-scroller {
- position: fixed;
- bottom: 0;
- overflow-x: auto;
- overflow-y: hidden; }
-
-.page-row {
- padding: 0 16px;
- margin: 16px 0; }
-
-.page-row-text {
- color: #98A2B3;
- font-size: 14px; }
-
-:focus:not([class^='eui']):not(.kbn-resetFocusState) {
- -webkit-animation: 350ms cubic-bezier(0.694, 0.0482, 0.335, 1) 1 normal forwards focusRingAnimate !important;
- animation: 350ms cubic-bezier(0.694, 0.0482, 0.335, 1) 1 normal forwards focusRingAnimate !important; }
-
-.euiComboBox input:not([class^='eui']):focus {
- -webkit-animation: none !important;
- animation: none !important; }
-
-.euiBody--collapsibleNavIsDocked .euiBottomBar {
- margin-left: 320px; }
-
-.fullWidth {
- width: 100% !important; }
-
-.small {
- font-size: 0.9em !important; }
-
-.smaller {
- font-size: 0.8em !important; }
-
-.smallest {
- font-size: 0.7em !important; }
-
-.text-monospace {
- font-family: "Roboto Mono", Consolas, Menlo, Courier, monospace; }
-
-.application .ace-tm {
- background-color: #25262E;
- color: #DFE5EF; }
- .application .ace-tm .ace_scrollbar {
- scrollbar-width: thin; }
- .application .ace-tm .ace_scrollbar::-webkit-scrollbar {
- width: 16px;
- height: 16px; }
- .application .ace-tm .ace_scrollbar::-webkit-scrollbar-thumb {
- background-color: rgba(152, 162, 179, 0.5);
- border: 6px solid transparent;
- background-clip: content-box; }
- .application .ace-tm .ace_scrollbar::-webkit-scrollbar-corner, .application .ace-tm .ace_scrollbar::-webkit-scrollbar-track {
- background-color: transparent; }
- .application .ace-tm .ace_gutter-active-line,
- .application .ace-tm .ace_marker-layer .ace_active-line {
- background-color: rgba(52, 55, 65, 0.7); }
- .application .ace-tm .ace_snippet-marker {
- width: 100%;
- background-color: #343741;
- border: none; }
- .application .ace-tm .ace_indent-guide {
- background: linear-gradient(to left, #535966 0%, #535966 1px, transparent 1px, transparent 100%); }
- .application .ace-tm .ace_search {
- z-index: 1001; }
- .application .ace-tm .ace_layer.ace_marker-layer {
- overflow: visible; }
- .application .ace-tm .ace_warning {
- color: #F66; }
- .application .ace-tm .ace_method {
- color: #ec7bb3; }
- .application .ace-tm .ace_url,
- .application .ace-tm .ace_start_triple_quote,
- .application .ace-tm .ace_end_triple_quote {
- color: #25b2aa; }
- .application .ace-tm .ace_multi_string {
- color: #4db867;
- font-style: italic; }
- .application .ace-tm .ace_gutter {
- background-color: #1D1E24;
- color: #98A2B3;
- border-left: 1px solid #343741; }
- .application .ace-tm .ace_print-margin {
- width: 1px;
- background: #343741; }
- .application .ace-tm .ace_fold {
- background-color: #6B72E6; }
- .application .ace-tm .ace_cursor {
- color: #FFF; }
- .application .ace-tm .ace_invisible {
- color: #343741; }
- .application .ace-tm .ace_storage,
- .application .ace-tm .ace_keyword {
- color: #5eaac6; }
- .application .ace-tm .ace_constant {
- color: #d28f8f; }
- .application .ace-tm .ace_constant.ace_buildin {
- color: #a097f6; }
- .application .ace-tm .ace_constant.ace_language {
- color: #9698f6; }
- .application .ace-tm .ace_constant.ace_library {
- color: #4db867; }
- .application .ace-tm .ace_invalid {
- background-color: #4d1f1f;
- color: #ff8585; }
- .application .ace-tm .ace_support.ace_function {
- color: #9ba4b6; }
- .application .ace-tm .ace_support.ace_constant {
- color: #4db867; }
- .application .ace-tm .ace_support.ace_type,
- .application .ace-tm .ace_support.ace_class {
- color: #949ce6; }
- .application .ace-tm .ace_keyword.ace_operator {
- color: #98A2B3; }
- .application .ace-tm .ace_string {
- color: #4db867; }
- .application .ace-tm .ace_comment {
- color: #83ac97; }
- .application .ace-tm .ace_comment.ace_doc {
- color: #5eaac6; }
- .application .ace-tm .ace_comment.ace_doc.ace_tag {
- color: #9da1a9; }
- .application .ace-tm .ace_constant.ace_numeric {
- color: #5eaac6; }
- .application .ace-tm .ace_variable {
- color: #5eaac6; }
- .application .ace-tm .ace_xml-pe {
- color: #98A2B3; }
- .application .ace-tm .ace_entity.ace_name.ace_function {
- color: #9a9ada; }
- .application .ace-tm .ace_heading {
- color: #9a97ff; }
- .application .ace-tm .ace_list {
- color: #dd85c9; }
- .application .ace-tm .ace_meta.ace_tag {
- color: #959ed0; }
- .application .ace-tm .ace_string.ace_regex {
- color: #ff7575; }
- .application .ace-tm .ace_marker-layer .ace_selection {
- background: #08334a; }
- .application .ace-tm.ace_multiselect .ace_selection.ace_start {
- -webkit-box-shadow: 0 0 3px 0px #1D1E24;
- box-shadow: 0 0 3px 0px #1D1E24; }
- .application .ace-tm .ace_marker-layer .ace_step {
- background: #332918; }
- .application .ace-tm .ace_marker-layer .ace_stack {
- background: #192d2a; }
- .application .ace-tm .ace_marker-layer .ace_bracket {
- margin: -1px 0 0 -1px;
- border: 1px solid #343741; }
- .application .ace-tm .ace_marker-layer .ace_selected-word {
- background: #25262E;
- border: 1px solid #343741; }
-
-.control-group, navbar {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-flex: 0;
- -webkit-flex: 0 0 auto;
- -ms-flex: 0 0 auto;
- flex: 0 0 auto;
- -webkit-box-orient: horizontal;
- -webkit-box-direction: normal;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-flex-wrap: wrap;
- -ms-flex-wrap: wrap;
- flex-wrap: wrap;
- -webkit-box-align: stretch;
- -webkit-align-items: stretch;
- -ms-flex-align: stretch;
- align-items: stretch;
- padding: 4px 16px; }
- .control-group > *, navbar > * {
- padding-right: 16px;
- -webkit-box-flex: 0;
- -webkit-flex: 0 0 auto;
- -ms-flex: 0 0 auto;
- flex: 0 0 auto; }
- .control-group > *:last-child, navbar > *:last-child {
- padding-right: 0; }
- .control-group .inline-form .input-group, navbar .inline-form .input-group {
- margin-bottom: 0;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex; }
- .control-group .inline-form .input-group > *, navbar .inline-form .input-group > * {
- border-radius: 0; }
- .control-group .inline-form .input-group > :first-child, navbar .inline-form .input-group > :first-child {
- border-bottom-left-radius: 4px;
- border-top-left-radius: 4px; }
- .control-group .inline-form .input-group > :last-child, navbar .inline-form .input-group > :last-child {
- border-bottom-right-radius: 4px;
- border-top-right-radius: 4px; }
- .control-group .inline-form, navbar .inline-form {
- -webkit-box-flex: 0;
- -webkit-flex: 0 0 auto;
- -ms-flex: 0 0 auto;
- flex: 0 0 auto;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- display: flex; }
- .control-group .inline-form > *, navbar .inline-form > * {
- -webkit-flex-shrink: 0;
- -ms-flex-negative: 0;
- flex-shrink: 0; }
- .control-group .inline-form > .typeahead, navbar .inline-form > .typeahead {
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 auto;
- -ms-flex: 1 1 auto;
- flex: 1 1 auto;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column; }
- .control-group .inline-form > .typeahead > *, navbar .inline-form > .typeahead > * {
- -webkit-flex-shrink: 0;
- -ms-flex-negative: 0;
- flex-shrink: 0; }
- .control-group .inline-form > .typeahead > .input-group, navbar .inline-form > .typeahead > .input-group {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-flex: 1;
- -webkit-flex: 1 0 auto;
- -ms-flex: 1 0 auto;
- flex: 1 0 auto; }
- .control-group .inline-form > .typeahead > .input-group > *, navbar .inline-form > .typeahead > .input-group > * {
- float: none;
- height: auto;
- width: auto;
- -webkit-box-flex: 0;
- -webkit-flex: 0 0 auto;
- -ms-flex: 0 0 auto;
- flex: 0 0 auto; }
- .control-group .inline-form > .typeahead > .input-group input[type="text"], navbar .inline-form > .typeahead > .input-group input[type="text"] {
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 100%;
- -ms-flex: 1 1 100%;
- flex: 1 1 100%; }
- .control-group > .fill, navbar > .fill {
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 1%;
- -ms-flex: 1 1 1%;
- flex: 1 1 1%; }
-
-.hintbox {
- padding: 8px 12px;
- border-radius: 4px;
- margin-bottom: 8px;
- background-color: #343741;
- line-height: 1.5; }
- .hintbox a {
- color: #1BA9F5 !important; }
- .hintbox a:hover {
- color: #098dd4 !important; }
- .hintbox pre {
- background-color: #1D1E24; }
- .hintbox ul, .hintbox ol {
- padding-left: 24px; }
- .hintbox > * {
- margin: 0; }
- .hintbox > * + * {
- margin-top: 8px; }
- .hintbox .table-bordered {
- border: 1px solid #343741; }
- .hintbox .table-bordered > thead > tr > th,
- .hintbox .table-bordered > thead > tr > td,
- .hintbox .table-bordered > tbody > tr > th,
- .hintbox .table-bordered > tbody > tr > td,
- .hintbox .table-bordered > tfoot > tr > th,
- .hintbox .table-bordered > tfoot > tr > td {
- border: 1px solid #343741; }
- .hintbox .table-bordered > thead > tr > th,
- .hintbox .table-bordered > thead > tr > td {
- border-bottom-width: 2px; }
-
-.hintbox-label,
-.hintbox-label[ng-click] {
- cursor: help; }
-
-i.input-error {
- position: absolute;
- margin-left: -24px;
- color: #F66;
- margin-top: 8px;
- z-index: 5; }
-
-select {
- color: #DFE5EF;
- background-color: #1D1E24; }
-
-.form-control {
- display: block;
- width: 100%;
- height: 32px;
- padding: 4px 12px;
- font-size: 14px;
- font-size: 0.875rem;
- line-height: 1.5;
- border: 1px solid #343741;
- background-color: #16171c;
- color: #DFE5EF;
- border-radius: 4px;
- cursor: pointer; }
- .form-control:not([type='range']) {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none; }
- .form-control:focus {
- border-color: #1BA9F5;
- outline: none;
- -webkit-box-shadow: none;
- box-shadow: none; }
-
-select.form-control {
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath fill='rgb%28223, 229, 239%29' d='M13.0688508,5.15725038 L8.38423975,9.76827428 C8.17054415,9.97861308 7.82999214,9.97914095 7.61576025,9.76827428 L2.93114915,5.15725038 C2.7181359,4.94758321 2.37277319,4.94758321 2.15975994,5.15725038 C1.94674669,5.36691756 1.94674669,5.70685522 2.15975994,5.9165224 L6.84437104,10.5275463 C7.48517424,11.1582836 8.51644979,11.1566851 9.15562896,10.5275463 L13.8402401,5.9165224 C14.0532533,5.70685522 14.0532533,5.36691756 13.8402401,5.15725038 C13.6272268,4.94758321 13.2818641,4.94758321 13.0688508,5.15725038 Z'/%3E%3C/svg%3E");
- background-size: 16px;
- background-repeat: no-repeat;
- background-position: calc(100% - 8px);
- padding-right: 32px; }
- select.form-control::-ms-expand {
- display: none; }
- select.form-control:focus::-ms-value {
- color: #DFE5EF;
- background: transparent; }
-
-.kuiFormSection {
- margin-bottom: 16px; }
-
-.kuiFormLabel {
- font-size: 12px;
- font-weight: 600;
- color: #DFE5EF;
- display: block;
- margin-bottom: 5px; }
- .kuiFormLabel[for] {
- cursor: pointer; }
-
-.kuiInputNote {
- margin: 4px 0 8px; }
-
-.kuiInputNote--danger {
- color: #F66; }
-
-.kuiInputNote--warning {
- color: #FFCE7A; }
-
-.list-group-menu.select-mode a {
- outline: none;
- color: #1898dd; }
-
-.list-group-menu .list-group-menu-item {
- list-style: none;
- color: #1898dd; }
- .list-group-menu .list-group-menu-item.active {
- font-weight: bold;
- background-color: #343741; }
- .list-group-menu .list-group-menu-item:hover {
- background-color: #031119; }
- .list-group-menu .list-group-menu-item li {
- list-style: none;
- color: #1898dd; }
-
-navbar {
- max-height: 340px;
- margin-bottom: 0;
- padding: 0 8px 4px;
- color: #98A2B3;
- background-color: #343741;
- border: none;
- z-index: 1000; }
- navbar > * {
- padding-right: 8px; }
- navbar .navbar-text {
- margin-top: 4px;
- margin-bottom: 4px; }
- navbar > .name {
- max-width: 100%;
- overflow: hidden !important;
- text-overflow: ellipsis !important;
- white-space: nowrap !important;
- word-wrap: normal !important;
- -webkit-align-self: center;
- -ms-flex-item-align: center;
- align-self: center;
- font-size: 20px; }
- navbar button {
- color: #98A2B3;
- background-color: transparent; }
- navbar button:hover, navbar button:focus {
- color: #98A2B3;
- background-color: transparent; }
- navbar button:active, navbar button.active {
- color: #D4DAE5;
- background-color: transparent;
- -webkit-box-shadow: none;
- box-shadow: none; }
- navbar button:active:focus, navbar button.active:focus {
- outline: none; }
- navbar button[disabled] {
- color: #535966;
- background-color: transparent; }
- navbar .inline-form .input-group button {
- color: #1D1E24;
- background-color: #98A2B3;
- border: none; }
- @media only screen and (min-width: 992px) and (max-width: 1199px) {
- navbar > .name {
- max-width: 500px; } }
- @media only screen and (min-width: 1200px) {
- navbar > .name {
- max-width: 500px; } }
- @media only screen and (max-width: 574px) {
- navbar > .fill {
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 992px;
- -ms-flex: 1 1 992px;
- flex: 1 1 992px; } }
- @media only screen and (min-width: 575px) and (max-width: 767px) {
- navbar > .fill {
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 992px;
- -ms-flex: 1 1 992px;
- flex: 1 1 992px; } }
- @media only screen and (min-width: 768px) and (max-width: 991px) {
- navbar > .fill {
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 992px;
- -ms-flex: 1 1 992px;
- flex: 1 1 992px; } }
- @media only screen and (max-width: 574px) {
- navbar > .name {
- max-width: 100%; } }
- @media only screen and (min-width: 575px) and (max-width: 767px) {
- navbar > .name {
- max-width: 100%; } }
-
-.config {
- border-bottom: 1px solid transparent; }
- .config .container-fluid {
- background-color: #1a1b20;
- padding: 8px; }
-
-paginate {
- display: block; }
- paginate paginate-controls {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-align: center;
- -webkit-align-items: center;
- -ms-flex-align: center;
- align-items: center;
- padding: 4px 4px 8px;
- text-align: center; }
- paginate paginate-controls .pagination-other-pages {
- -webkit-box-flex: 1;
- -webkit-flex: 1 0 auto;
- -ms-flex: 1 0 auto;
- flex: 1 0 auto;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center; }
- paginate paginate-controls .pagination-other-pages-list {
- -webkit-box-flex: 0;
- -webkit-flex: 0 0 auto;
- -ms-flex: 0 0 auto;
- flex: 0 0 auto;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
- padding: 0;
- margin: 0;
- list-style: none; }
- paginate paginate-controls .pagination-other-pages-list > li {
- -webkit-box-flex: 0;
- -webkit-flex: 0 0 auto;
- -ms-flex: 0 0 auto;
- flex: 0 0 auto;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none; }
- paginate paginate-controls .pagination-other-pages-list > li a {
- text-decoration: none;
- background-color: #25262E;
- margin-left: 2px;
- padding: 8px 12px; }
- paginate paginate-controls .pagination-other-pages-list > li a:hover {
- text-decoration: underline; }
- paginate paginate-controls .pagination-other-pages-list > li.active a {
- text-decoration: none !important;
- font-weight: 700;
- color: #98A2B3;
- cursor: default; }
- paginate paginate-controls .pagination-size {
- -webkit-box-flex: 0;
- -webkit-flex: 0 0 auto;
- -ms-flex: 0 0 auto;
- flex: 0 0 auto; }
- paginate paginate-controls .pagination-size input[type=number] {
- width: 3em; }
-
-.spinner.ng-hide {
- visibility: hidden;
- display: block !important;
- opacity: 0;
- -webkit-transition-delay: 0.25s;
- transition-delay: 0.25s; }
-
-/**
-* Style ES document _source in table view key: value
-* Use alpha so this will stand out against non-white backgrounds, e.g. the highlighted
-* row in the Context Log.
-*/
-.table .table {
- background-color: #1D1E24; }
-
-kbn-table dl.source, .kbn-table dl.source, tbody[kbn-rows] dl.source {
- margin-bottom: 0;
- line-height: 2em;
- word-break: break-word; }
- kbn-table dl.source dt, kbn-table dl.source dd, .kbn-table dl.source dt, .kbn-table dl.source dd, tbody[kbn-rows] dl.source dt, tbody[kbn-rows] dl.source dd {
- display: inline; }
- kbn-table dl.source dt, .kbn-table dl.source dt, tbody[kbn-rows] dl.source dt {
- background-color: rgba(22, 135, 196, 0.1);
- color: #DFE5EF;
- padding: 2px 4px;
- margin-right: 4px;
- word-break: normal;
- border-radius: 4px; }
-
-kbn-table .table .table, .kbn-table .table .table, tbody[kbn-rows] .table .table {
- margin-bottom: 0; }
- kbn-table .table .table tr:first-child > td, .kbn-table .table .table tr:first-child > td, tbody[kbn-rows] .table .table tr:first-child > td {
- border-top: none; }
- kbn-table .table .table td.field-name, .kbn-table .table .table td.field-name, tbody[kbn-rows] .table .table td.field-name {
- font-weight: 700; }
-
-table th i.fa-sort {
- color: #343741; }
-
-table th button.fa-sort-asc,
-table th button.fa-sort-down,
-table th i.fa-sort-asc,
-table th i.fa-sort-down {
- color: #1BA9F5; }
-
-table th button.fa-sort-desc,
-table th button.fa-sort-up,
-table th i.fa-sort-desc,
-table th i.fa-sort-up {
- color: #1BA9F5; }
-
-.truncate-by-height {
- overflow: hidden; }
-
-/*!
- * ui-select
- * http://github.com/angular-ui/ui-select
- * Version: 0.19.5 - 2016-10-24T23:13:59.551Z
- * License: MIT
- */
-/* Style when highlighting a search. */
-.ui-select-highlight {
- font-weight: bold; }
-
-.ui-select-offscreen {
- clip: rect(0 0 0 0) !important;
- width: 1px !important;
- height: 1px !important;
- border: 0 !important;
- margin: 0 !important;
- padding: 0 !important;
- overflow: hidden !important;
- position: absolute !important;
- outline: 0 !important;
- left: 0px !important;
- top: 0px !important; }
-
-.ui-select-choices-row:hover {
- background-color: #25262E; }
-
-/* Select2 theme */
-/* Mark invalid Select2 */
-.ng-dirty.ng-invalid > a.select2-choice {
- border-color: #F66; }
-
-.select2-result-single {
- padding-left: 0; }
-
-.select2-locked > .select2-search-choice-close {
- display: none; }
-
-.select-locked > .ui-select-match-close {
- display: none; }
-
-body > .select2-container.open {
- z-index: 9999;
- /* The z-index Select2 applies to the select2-drop */ }
-
-/* Handle up direction Select2 */
-.ui-select-container[theme='select2'].direction-up .ui-select-match,
-.ui-select-container.select2.direction-up .ui-select-match {
- border-radius: 4px;
- /* FIXME hardcoded value :-/ */
- border-top-left-radius: 0;
- border-top-right-radius: 0; }
-
-.ui-select-container[theme='select2'].direction-up .ui-select-dropdown,
-.ui-select-container.select2.direction-up .ui-select-dropdown {
- border-radius: 4px;
- /* FIXME hardcoded value :-/ */
- border-bottom-left-radius: 0;
- border-bottom-right-radius: 0;
- border-top-width: 1px;
- /* FIXME hardcoded value :-/ */
- border-top-style: solid;
- -webkit-box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25);
- box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25);
- margin-top: -4px;
- /* FIXME hardcoded value :-/ */ }
-
-.ui-select-container[theme='select2'].direction-up .ui-select-dropdown .select2-search,
-.ui-select-container.select2.direction-up .ui-select-dropdown .select2-search {
- margin-top: 4px;
- /* FIXME hardcoded value :-/ */ }
-
-.ui-select-container[theme='select2'].direction-up.select2-dropdown-open .ui-select-match,
-.ui-select-container.select2.direction-up.select2-dropdown-open .ui-select-match {
- border-bottom-color: #1BA9F5; }
-
-.ui-select-container[theme='select2'] .ui-select-dropdown .ui-select-search-hidden,
-.ui-select-container[theme='select2'] .ui-select-dropdown .ui-select-search-hidden input {
- opacity: 0;
- height: 0;
- min-height: 0;
- padding: 0;
- margin: 0;
- border: 0; }
-
-/* Bootstrap theme */
-/* Helper class to show styles when focus */
-.btn-default-focus {
- color: #DFE5EF;
- background-color: #1D1E24;
- border-color: #1BA9F5;
- text-decoration: none;
- outline: none;
- -webkit-box-shadow: none;
- box-shadow: none; }
-
-.ui-select-bootstrap .ui-select-toggle {
- display: block;
- width: 100%;
- height: 32px;
- padding: 4px 12px;
- font-size: 14px;
- font-size: 0.875rem;
- line-height: 1.5;
- border: 1px solid #343741;
- background-color: #16171c;
- color: #DFE5EF;
- border-radius: 4px;
- cursor: pointer;
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath fill='rgb%28223, 229, 239%29' d='M13.0688508,5.15725038 L8.38423975,9.76827428 C8.17054415,9.97861308 7.82999214,9.97914095 7.61576025,9.76827428 L2.93114915,5.15725038 C2.7181359,4.94758321 2.37277319,4.94758321 2.15975994,5.15725038 C1.94674669,5.36691756 1.94674669,5.70685522 2.15975994,5.9165224 L6.84437104,10.5275463 C7.48517424,11.1582836 8.51644979,11.1566851 9.15562896,10.5275463 L13.8402401,5.9165224 C14.0532533,5.70685522 14.0532533,5.36691756 13.8402401,5.15725038 C13.6272268,4.94758321 13.2818641,4.94758321 13.0688508,5.15725038 Z'/%3E%3C/svg%3E");
- background-size: 16px;
- background-repeat: no-repeat;
- background-position: calc(100% - 8px);
- padding-right: 32px; }
- .ui-select-bootstrap .ui-select-toggle:not([type='range']) {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none; }
- .ui-select-bootstrap .ui-select-toggle:focus {
- border-color: #1BA9F5;
- outline: none;
- -webkit-box-shadow: none;
- box-shadow: none; }
- .ui-select-bootstrap .ui-select-toggle::-ms-expand {
- display: none; }
- .ui-select-bootstrap .ui-select-toggle:focus::-ms-value {
- color: #DFE5EF;
- background: transparent; }
-
-.ui-select-bootstrap .ui-select-toggle > .caret {
- display: none; }
-
-/* Fix Bootstrap dropdown position when inside a input-group */
-.input-group > .ui-select-bootstrap.dropdown {
- /* Instead of relative */
- position: static; }
-
-.input-group > .ui-select-bootstrap > input.ui-select-search.form-control {
- border-radius: 4px;
- /* FIXME hardcoded value :-/ */
- border-top-right-radius: 0;
- border-bottom-right-radius: 0; }
-
-.input-group > .ui-select-bootstrap > input.ui-select-search.form-control.direction-up {
- border-radius: 4px !important;
- /* FIXME hardcoded value :-/ */
- border-top-right-radius: 0 !important;
- border-bottom-right-radius: 0 !important; }
-
-.ui-select-bootstrap .ui-select-search-hidden {
- opacity: 0;
- height: 0;
- min-height: 0;
- padding: 0;
- margin: 0;
- border: 0; }
-
-.ui-select-bootstrap > .ui-select-match > .btn {
- display: block;
- width: 100%;
- height: 32px;
- padding: 4px 12px;
- font-size: 14px;
- font-size: 0.875rem;
- line-height: 1.5;
- border: 1px solid #343741;
- background-color: #16171c;
- color: #DFE5EF;
- border-radius: 4px;
- cursor: pointer;
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath fill='rgb%28223, 229, 239%29' d='M13.0688508,5.15725038 L8.38423975,9.76827428 C8.17054415,9.97861308 7.82999214,9.97914095 7.61576025,9.76827428 L2.93114915,5.15725038 C2.7181359,4.94758321 2.37277319,4.94758321 2.15975994,5.15725038 C1.94674669,5.36691756 1.94674669,5.70685522 2.15975994,5.9165224 L6.84437104,10.5275463 C7.48517424,11.1582836 8.51644979,11.1566851 9.15562896,10.5275463 L13.8402401,5.9165224 C14.0532533,5.70685522 14.0532533,5.36691756 13.8402401,5.15725038 C13.6272268,4.94758321 13.2818641,4.94758321 13.0688508,5.15725038 Z'/%3E%3C/svg%3E");
- background-size: 16px;
- background-repeat: no-repeat;
- background-position: calc(100% - 8px);
- padding-right: 32px;
- text-align: left !important; }
- .ui-select-bootstrap > .ui-select-match > .btn:not([type='range']) {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none; }
- .ui-select-bootstrap > .ui-select-match > .btn:focus {
- border-color: #1BA9F5;
- outline: none;
- -webkit-box-shadow: none;
- box-shadow: none; }
- .ui-select-bootstrap > .ui-select-match > .btn::-ms-expand {
- display: none; }
- .ui-select-bootstrap > .ui-select-match > .btn:focus::-ms-value {
- color: #DFE5EF;
- background: transparent; }
- .ui-select-bootstrap > .ui-select-match > .btn .ui-select-placeholder {
- color: #535966; }
- .ui-select-bootstrap > .ui-select-match > .btn:focus, .ui-select-bootstrap > .ui-select-match > .btn:active {
- background-color: #1D1E24;
- color: #DFE5EF;
- outline: none; }
-
-.ui-select-bootstrap > .ui-select-match > .caret {
- display: none; }
-
-/* See Scrollable Menu with Bootstrap 3 http://stackoverflow.com/questions/19227496 */
-.ui-select-bootstrap > .ui-select-choices,
-.ui-select-bootstrap > .ui-select-no-choice {
- width: 100%;
- height: auto;
- max-height: 224px;
- overflow-x: hidden; }
-
-body > .ui-select-bootstrap.open {
- z-index: 2000; }
-
-.ui-select-multiple.ui-select-bootstrap {
- height: auto;
- padding: 3px 5px 2px;
- border: 1px solid #343741;
- background-color: #16171c; }
- .ui-select-multiple.ui-select-bootstrap.kuiInputError {
- border-color: #F66; }
-
-.ui-select-multiple.ui-select-bootstrap input.ui-select-search {
- background-color: transparent !important;
- /* To prevent double background when disabled */
- border: none;
- outline: none;
- height: 1.666666em;
- margin-bottom: 3px; }
-
-.ui-select-multiple.ui-select-bootstrap .ui-select-match .close {
- font-size: 1.6em;
- line-height: 0.75; }
-
-.ui-select-multiple.ui-select-bootstrap .ui-select-match-item {
- outline: 0;
- margin: 0 3px 3px 0; }
-
-.ui-select-multiple .ui-select-match-item {
- position: relative; }
-
-.ui-select-multiple .ui-select-match-item.dropping .ui-select-match-close {
- pointer-events: none; }
-
-.ui-select-multiple:hover .ui-select-match-item.dropping-before:before {
- content: '';
- position: absolute;
- top: 0;
- right: 100%;
- height: 100%;
- margin-right: 2px;
- border-left: 1px solid #1BA9F5; }
-
-.ui-select-multiple:hover .ui-select-match-item.dropping-after:after {
- content: '';
- position: absolute;
- top: 0;
- left: 100%;
- height: 100%;
- margin-left: 2px;
- border-right: 1px solid #1BA9F5; }
-
-.ui-select-bootstrap .ui-select-choices-row > span {
- font-size: 14px;
- font-size: 0.875rem;
- line-height: 1.5;
- max-width: 100%;
- overflow: hidden !important;
- text-overflow: ellipsis !important;
- white-space: nowrap !important;
- word-wrap: normal !important;
- font-weight: inherit;
- cursor: pointer;
- display: block;
- padding: 4px 16px;
- clear: both;
- color: #DFE5EF;
- white-space: nowrap; }
- .ui-select-bootstrap .ui-select-choices-row > span:hover, .ui-select-bootstrap .ui-select-choices-row > span:focus {
- text-decoration: none;
- color: #DFE5EF;
- background-color: #232635; }
-
-.ui-select-bootstrap .ui-select-choices-row.active > span {
- color: #DFE5EF;
- text-decoration: none;
- outline: 0;
- background-color: #232635; }
-
-.ui-select-bootstrap .ui-select-choices-row.disabled > span,
-.ui-select-bootstrap .ui-select-choices-row.active.disabled > span {
- color: #434548;
- cursor: not-allowed;
- background-color: transparent; }
-
-/* fix hide/show angular animation */
-.ui-select-match.ng-hide-add,
-.ui-select-search.ng-hide-add {
- display: none !important; }
-
-/* Mark invalid Bootstrap */
-.ui-select-bootstrap.ng-dirty.ng-invalid > button.btn.ui-select-match {
- border-color: #F66; }
-
-/* Handle up direction Bootstrap */
-.ui-select-container[theme='bootstrap'].direction-up .ui-select-dropdown {
- -webkit-box-shadow: 0 6px 12px -1px rgba(0, 0, 0, 0.2), 0 4px 4px -1px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.2);
- box-shadow: 0 6px 12px -1px rgba(0, 0, 0, 0.2), 0 4px 4px -1px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.2); }
-
-.ui-select-bootstrap .ui-select-match-text {
- width: 100%;
- padding-right: 1em; }
-
-.ui-select-bootstrap .ui-select-match-text span {
- display: inline-block;
- width: 100%;
- overflow: hidden; }
-
-.ui-select-bootstrap .ui-select-toggle > a.btn {
- position: absolute;
- height: 10px;
- right: 10px;
- margin-top: -2px; }
-
-/* Spinner */
-.ui-select-refreshing {
- position: absolute;
- right: 0;
- padding: 8px 27px;
- top: 1px;
- display: inline-block;
- font-family: 'Glyphicons Halflings';
- font-style: normal;
- font-weight: normal;
- line-height: 1;
- -webkit-font-smoothing: antialiased; }
-
-@-webkit-keyframes ui-select-spin {
- 0% {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg); }
- 100% {
- -webkit-transform: rotate(359deg);
- transform: rotate(359deg); } }
-
-@keyframes ui-select-spin {
- 0% {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg); }
- 100% {
- -webkit-transform: rotate(359deg);
- transform: rotate(359deg); } }
-
-.ui-select-spin {
- -webkit-animation: ui-select-spin 2s infinite linear;
- animation: ui-select-spin 2s infinite linear; }
-
-.ui-select-refreshing.ng-animate {
- -webkit-animation: none 0s; }
-
-/**
- * 1. Fix appearance of ui-select in the Filtering UI.
- */
-.btn-default .ui-select-placeholder {
- color: #535966;
- /* 1 */ }
-
-.uiSelectMatch--ellipsis {
- max-width: 100%;
- overflow: hidden !important;
- text-overflow: ellipsis !important;
- white-space: nowrap !important;
- word-wrap: normal !important; }
-
-.ui-select-choices-group-label {
- color: #DFE5EF;
- font-size: 12px;
- font-size: 0.75rem;
- line-height: 1.5rem;
- font-weight: 700;
- max-width: 100%;
- overflow: hidden !important;
- text-overflow: ellipsis !important;
- white-space: nowrap !important;
- word-wrap: normal !important;
- padding: 4px; }
-
-.kbnUiAceKeyboardHint {
- position: absolute;
- top: 0;
- bottom: 0;
- right: 0;
- left: 0;
- background: rgba(29, 30, 36, 0.7);
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
- -webkit-box-align: center;
- -webkit-align-items: center;
- -ms-flex-align: center;
- align-items: center;
- text-align: center;
- opacity: 0; }
- .kbnUiAceKeyboardHint:focus {
- opacity: 1;
- border: 2px solid #1BA9F5;
- z-index: 1000; }
- .kbnUiAceKeyboardHint.kbnUiAceKeyboardHint-isInactive {
- display: none; }
-
-.input-datetime-format {
- font-size: 12px;
- color: #535966;
- padding: 4px 16px; }
-
-saved-object-finder .list-sort-button,
-paginated-selectable-list .list-sort-button {
- border-top-left-radius: 0 !important;
- border-top-right-radius: 0 !important;
- border: none;
- padding: 8px 16px;
- font-weight: 400;
- background-color: #25262E; }
-
-saved-object-finder ul.li-striped li,
-paginated-selectable-list ul.li-striped li {
- border: none; }
-
-saved-object-finder ul.li-striped li:nth-child(even),
-paginated-selectable-list ul.li-striped li:nth-child(even) {
- background-color: #25262E; }
-
-saved-object-finder ul.li-striped li:nth-child(odd),
-paginated-selectable-list ul.li-striped li:nth-child(odd) {
- background-color: #1D1E24; }
-
-saved-object-finder ul.li-striped .paginate-heading,
-paginated-selectable-list ul.li-striped .paginate-heading {
- font-weight: 400;
- color: #D4DAE5; }
-
-saved-object-finder ul.li-striped .list-group-item,
-paginated-selectable-list ul.li-striped .list-group-item {
- padding: 8px 16px; }
- saved-object-finder ul.li-striped .list-group-item ul,
- paginated-selectable-list ul.li-striped .list-group-item ul {
- padding: 0;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: horizontal;
- -webkit-box-direction: normal;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row; }
- saved-object-finder ul.li-striped .list-group-item ul .finder-type,
- paginated-selectable-list ul.li-striped .list-group-item ul .finder-type {
- margin-right: 8px; }
- saved-object-finder ul.li-striped .list-group-item a,
- paginated-selectable-list ul.li-striped .list-group-item a {
- display: block;
- color: #1BA9F5 !important; }
- saved-object-finder ul.li-striped .list-group-item a i,
- paginated-selectable-list ul.li-striped .list-group-item a i {
- color: #1898dd !important;
- margin-right: 8px; }
- saved-object-finder ul.li-striped .list-group-item:first-child,
- paginated-selectable-list ul.li-striped .list-group-item:first-child {
- border-top-left-radius: 0 !important;
- border-top-right-radius: 0 !important; }
- saved-object-finder ul.li-striped .list-group-item.list-group-no-results p,
- paginated-selectable-list ul.li-striped .list-group-item.list-group-no-results p {
- margin-bottom: 0 !important; }
-
-saved-object-finder paginate paginate-controls,
-paginated-selectable-list paginate paginate-controls {
- margin: 16px; }
-
-.kbnError--url-overflow-app {
- padding: 24px; }
-
-/**
- * 1. override the z-index: 1 applied to all non-eui elements that are in :focus via kui
- * - see packages/kbn-ui-framework/src/global_styling/reset/_reset.scss
- */
-.dshExitFullScreenButton {
- -webkit-box-shadow: 0 12px 24px 0 rgba(0, 0, 0, 0.1), 0 6px 12px 0 rgba(0, 0, 0, 0.1), 0 4px 4px 0 rgba(0, 0, 0, 0.1), 0 2px 2px 0 rgba(0, 0, 0, 0.1);
- box-shadow: 0 12px 24px 0 rgba(0, 0, 0, 0.1), 0 6px 12px 0 rgba(0, 0, 0, 0.1), 0 4px 4px 0 rgba(0, 0, 0, 0.1), 0 2px 2px 0 rgba(0, 0, 0, 0.1);
- left: 8px;
- bottom: 8px;
- position: fixed;
- display: block;
- padding: 4px 8px;
- border: none;
- background: none;
- z-index: 5;
- background: #FFF;
- border-radius: 4px;
- text-align: left; }
- .dshExitFullScreenButton:hover {
- background: #FFF; }
- .dshExitFullScreenButton:hover .dshExitFullScreenButton__icon {
- color: #1D1E24; }
-
-.dshExitFullScreenButton__text {
- line-height: 1.2;
- color: #535966; }
-
-.dshExitFullScreenButton__icon {
- color: #535966; }
-
-.kbnFieldFormatEditor__samples audio {
- max-width: 100%; }
-
-.testScript__searchBar .globalQueryBar {
- padding: 16px 0 0; }
-
-style-compile {
- display: none; }
-
-.mgtSideBarNav {
- width: 192px; }
-
-@media only screen and (max-width: 574px) {
- .mgtSideBarNav {
- width: auto;
- margin-bottom: 16px; } }
-
-@media only screen and (min-width: 575px) and (max-width: 767px) {
- .mgtSideBarNav {
- width: auto;
- margin-bottom: 16px; } }
-
-/**
-* Style ES document _source in table view key: value
-* Use alpha so this will stand out against non-white backgrounds, e.g. the highlighted
-* row in the Context Log.
-*/
-discover-app {
- -webkit-box-flex: 1;
- -webkit-flex-grow: 1;
- -ms-flex-positive: 1;
- flex-grow: 1; }
-
-.dscHistogram {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- height: 200px;
- padding: 8px; }
-
-.dscWrapper {
- padding-right: 8px;
- padding-left: 32px;
- z-index: 1; }
-
-.dscWrapper__content {
- -webkit-box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.3), 0 1px 5px -2px rgba(0, 0, 0, 0.3);
- box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.3), 0 1px 5px -2px rgba(0, 0, 0, 0.3);
- background-color: #1D1E24;
- border: 1px solid #343741;
- border-radius: 4px;
- -webkit-box-flex: 1;
- -webkit-flex-grow: 1;
- -ms-flex-positive: 1;
- flex-grow: 1; }
- .dscWrapper__content.dscWrapper__content--flexGrowZero {
- -webkit-box-flex: 0;
- -webkit-flex-grow: 0;
- -ms-flex-positive: 0;
- flex-grow: 0; }
- .dscWrapper__content.dscWrapper__content--isClickable {
- display: block;
- width: 100%;
- text-align: left;
- -webkit-transition: all 150ms cubic-bezier(0.694, 0.0482, 0.335, 1);
- transition: all 150ms cubic-bezier(0.694, 0.0482, 0.335, 1); }
- .dscWrapper__content.dscWrapper__content--isClickable:hover, .dscWrapper__content.dscWrapper__content--isClickable:focus {
- -webkit-box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.15), 0 2px 2px -1px rgba(0, 0, 0, 0.3);
- box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.15), 0 2px 2px -1px rgba(0, 0, 0, 0.3);
- -webkit-transform: translateY(-2px);
- transform: translateY(-2px);
- cursor: pointer; }
- .dscWrapper__content.dscWrapper__content--shadow {
- -webkit-box-shadow: 0 6px 12px -1px rgba(0, 0, 0, 0.2), 0 4px 4px -1px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.2);
- box-shadow: 0 6px 12px -1px rgba(0, 0, 0, 0.2), 0 4px 4px -1px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.2);
- border-bottom-color: #343741; }
- .dscWrapper__content.dscWrapper__content--shadow.dscWrapper__content--isClickable:hover, .dscWrapper__content.dscWrapper__content--shadow.dscWrapper__content--isClickable:focus {
- -webkit-box-shadow: 0 12px 24px 0 rgba(0, 0, 0, 0.2), 0 6px 12px 0 rgba(0, 0, 0, 0.2), 0 4px 4px 0 rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.2);
- box-shadow: 0 12px 24px 0 rgba(0, 0, 0, 0.2), 0 6px 12px 0 rgba(0, 0, 0, 0.2), 0 4px 4px 0 rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.2); }
-
-.dscWrapper__content {
- padding-top: 4px;
- background-color: #1D1E24; }
- .dscWrapper__content .kbn-table {
- margin-bottom: 0; }
-
-.dscTimechart {
- display: block;
- position: relative; }
- .dscTimechart .series > rect {
- fill-opacity: 0.5;
- stroke-width: 1; }
-
-.dscResultCount {
- text-align: center;
- padding-top: 4px;
- padding-left: 12px; }
- .dscResultCount .dscResultHits {
- padding-left: 4px; }
- .dscResultCount > .kuiLink {
- padding-left: 12px; }
-
-.dscTimechart__header {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
- min-height: 40px;
- padding: 4px 0; }
-
-.dscOverlay {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 20;
- padding-top: 12px;
- opacity: 0.75;
- text-align: center;
- background-color: transparent; }
-
-.dscTable {
- overflow: auto; }
- .dscTable .kbnDocTable__row {
- font-family: "Roboto Mono", Consolas, Menlo, Courier, monospace;
- font-size: 12px; }
-
-.dscTable__footer {
- background-color: #343741;
- padding: 5px 10px;
- text-align: center; }
-
-.dscResults h3 {
- margin: -20px 0 10px 0;
- text-align: center; }
-
-.dscResults__interval {
- display: inline-block;
- width: auto; }
-
-.dscSkipButton {
- position: absolute;
- left: -10000px;
- top: 4px;
- width: 1px;
- height: 1px;
- overflow: hidden; }
- .dscSkipButton:focus {
- left: initial;
- right: 16px;
- width: auto;
- height: auto; }
-
-.tab-discover {
- overflow: hidden; }
-
-.discoverFetchError {
- max-width: 1000px; }
-
-.dscSidebar__container {
- padding-left: 0 !important;
- padding-right: 0 !important;
- background-color: transparent;
- border-right-color: transparent;
- border-bottom-color: transparent; }
-
-.dscIndexPattern__container {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-align: center;
- -webkit-align-items: center;
- -ms-flex-align: center;
- align-items: center;
- height: 48px;
- margin-top: -8px; }
-
-.dscIndexPattern__triggerButton {
- color: #DFE5EF;
- font-size: 16px;
- font-size: 1rem;
- line-height: 1.5rem;
- font-weight: 600;
- letter-spacing: -0.02em;
- line-height: 40px; }
-
-.dscFieldList {
- list-style: none;
- margin-bottom: 0; }
-
-.dscFieldList--selected,
-.dscFieldList--unpopular,
-.dscFieldList--popular {
- padding-left: 8px;
- padding-right: 8px; }
-
-.dscFieldListHeader {
- padding: 8px 8px 0 8px;
- background-color: #343741; }
-
-.dscFieldList--popular {
- background-color: #343741; }
-
-.dscFieldChooser {
- padding-left: 8px !important;
- padding-right: 8px !important; }
-
-.dscFieldChooser__toggle {
- color: #535966;
- margin-left: 8px !important; }
-
-.dscSidebarItem {
- border-top: 1px solid transparent;
- position: relative;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-align: center;
- -webkit-align-items: center;
- -ms-flex-align: center;
- align-items: center;
- -webkit-box-pack: justify;
- -webkit-justify-content: space-between;
- -ms-flex-pack: justify;
- justify-content: space-between;
- padding: 0 2px;
- cursor: pointer;
- font-size: 12px;
- border-top: solid 1px transparent;
- border-bottom: solid 1px transparent;
- line-height: normal; }
- .dscSidebarItem:hover .dscSidebarItem__action, .dscSidebarItem:focus .dscSidebarItem__action {
- opacity: 1; }
-
-.dscSidebarItem--active {
- border-top: 1px solid #343741;
- background: #23242c;
- color: #FFF; }
- .dscSidebarItem--active .euiText {
- font-weight: bold; }
-
-.dscSidebarField {
- padding: 4px 0;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-align: start;
- -webkit-align-items: flex-start;
- -ms-flex-align: start;
- align-items: flex-start;
- max-width: 100%;
- margin: 0;
- width: 100%;
- border: none;
- border-radius: 0;
- text-align: left; }
-
-.dscSidebarField__name {
- margin-left: 8px;
- -webkit-box-flex: 1;
- -webkit-flex-grow: 1;
- -ms-flex-positive: 1;
- flex-grow: 1; }
-
-.dscSidebarField__fieldIcon {
- margin-top: 2px;
- margin-right: 2px; }
-
-/**
- * 1. Only visually hide the action, so that it's still accessible to screen readers.
- * 2. When tabbed to, this element needs to be visible for keyboard accessibility.
- */
-.dscSidebarItem__action {
- opacity: 0;
- /* 1 */
- -webkit-transition: none;
- transition: none;
- font-size: 12px;
- padding: 2px 6px !important;
- height: 22px !important;
- min-width: auto !important; }
- .dscSidebarItem__action:focus {
- opacity: 1;
- /* 2 */ }
- .dscSidebarItem__action .euiButton__content {
- padding: 0 4px; }
-
-/*
- Fixes EUI known issue https://github.com/elastic/eui/issues/1749
-*/
-.dscProgressBarTooltip__anchor {
- display: block; }
-
-.dscFieldSearch {
- padding: 8px; }
-
-.dscFieldSearch__toggleButton {
- width: calc(100% - 8px);
- color: #1BA9F5;
- padding-left: 4px;
- margin-left: 4px; }
-
-.dscFieldSearch__filterWrapper {
- -webkit-box-flex: 0;
- -webkit-flex-grow: 0;
- -ms-flex-positive: 0;
- flex-grow: 0; }
-
-.dscFieldSearch__formWrapper {
- padding: 12px; }
-
-.dscFieldDetails {
- padding: 8px;
- background-color: #25262E;
- color: #DFE5EF;
- margin-bottom: 8px; }
-
-.dscNoResults {
- max-width: 1000px; }
-
-.dscHistogram__header--partial {
- font-weight: 400;
- min-width: 192px; }
-
-/**
- * 1. The local nav contains tooltips which should pop over the filter bar.
- * 2. The filter and local nav components should always appear above the dashboard grid items.
- * 3. The filter and local nav components should always appear above the discover content.
- * 4. The sidebar collapser button should appear above the main Discover content but below the top elements.
- * 5. Dragged panels in dashboard should always appear above other panels.
- */
-/* 1 */
-/* 1 */
-/* 2 */
-/* 5 */
-/* 3 */
-/* 4 */
-.collapsible-sidebar {
- position: relative;
- z-index: 2; }
- .collapsible-sidebar .kbnCollapsibleSidebar__collapseButton {
- position: absolute;
- top: 0;
- right: -21px;
- cursor: pointer;
- z-index: -1; }
- .collapsible-sidebar.closed {
- width: 0 !important;
- border-right-width: 0;
- border-left-width: 0; }
- .collapsible-sidebar.closed > * {
- visibility: hidden; }
- .collapsible-sidebar.closed .kbnCollapsibleSidebar__collapseButton {
- visibility: visible; }
- .collapsible-sidebar.closed .kbnCollapsibleSidebar__collapseButton .chevron-cont:before {
- content: "\F138"; }
-
-@media only screen and (max-width: 574px) {
- .collapsible-sidebar.closed {
- display: none; }
- .collapsible-sidebar .kbnCollapsibleSidebar__collapseButton {
- display: none; } }
-
-@media only screen and (min-width: 575px) and (max-width: 767px) {
- .collapsible-sidebar.closed {
- display: none; }
- .collapsible-sidebar .kbnCollapsibleSidebar__collapseButton {
- display: none; } }
-
-@media only screen and (min-width: 768px) and (max-width: 991px) {
- .collapsible-sidebar.closed {
- display: none; }
- .collapsible-sidebar .kbnCollapsibleSidebar__collapseButton {
- display: none; } }
-
-/**
- * 1. Stack content vertically so the table can scroll when its constrained by a fixed container height.
- */
-doc-table {
- overflow: auto;
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 100%;
- -ms-flex: 1 1 100%;
- flex: 1 1 100%;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- /* 1 */ }
- doc-table th {
- text-align: left;
- font-weight: bold; }
- doc-table .spinner {
- position: absolute;
- top: 40%;
- left: 0;
- right: 0;
- z-index: 1000;
- opacity: 0.5; }
-
-.kbnDocTable__container.loading {
- opacity: 0.5; }
-
-.kbnDocTable {
- font-size: 12px; }
- .kbnDocTable dl.source {
- margin-bottom: 0;
- line-height: 2em;
- word-break: break-word; }
- .kbnDocTable dl.source dt, .kbnDocTable dl.source dd {
- display: inline; }
- .kbnDocTable dl.source dt {
- background-color: rgba(22, 135, 196, 0.1);
- color: #DFE5EF;
- padding: 2px 4px;
- margin-right: 4px;
- word-break: normal;
- border-radius: 4px; }
- .kbnDocTable th {
- white-space: nowrap;
- padding-right: 8px; }
- .kbnDocTable th .fa {
- font-size: 1.1em; }
-
-.kbnDocTable__row td {
- position: relative; }
- .kbnDocTable__row td:hover .kbnDocTableRowFilterButton {
- opacity: 1; }
-
-.kbnDocTable__row--highlight td,
-.kbnDocTable__row--highlight .kbnDocTableRowFilterButton {
- background-color: #08334a; }
-
-.kbnDocTable__bar {
- margin: 4px 4px 0; }
-
-.kbnDocTable__bar--footer {
- position: relative;
- margin: -48px 4px 0; }
-
-.kbnDocTable__padBottom {
- padding-bottom: 32px; }
-
-.kbnDocTable__error {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
- -webkit-box-flex: 1;
- -webkit-flex: 1 0 100%;
- -ms-flex: 1 0 100%;
- flex: 1 0 100%;
- text-align: center; }
-
-.kbnDocTableHeader button {
- margin-left: 4px; }
-
-.kbnDocTableHeader__move,
-.kbnDocTableHeader__sortChange {
- opacity: 0; }
- th:hover .kbnDocTableHeader__move, .kbnDocTableHeader__move:focus, th:hover
- .kbnDocTableHeader__sortChange,
- .kbnDocTableHeader__sortChange:focus {
- opacity: 1; }
-
-.kbnDocTableCell__dataField {
- white-space: pre-wrap; }
-
-.kbnDocTableCell__toggleDetails {
- padding: 4px 0 0 0 !important; }
-
-.kbnDocTableCell__filter {
- position: absolute;
- white-space: nowrap;
- right: 0; }
-
-/**
- * 1. Align icon with text in cell.
- * 2. Use opacity to make this element accessible to screen readers and keyboard.
- * 3. Show on focus to enable keyboard accessibility.
- */
-.kbnDocTableRowFilterButton {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- background-color: #1D1E24;
- border: none;
- padding: 0 4px;
- font-size: 14px;
- line-height: 1;
- /* 1 */
- display: inline-block;
- opacity: 0;
- /* 2 */ }
- .kbnDocTableRowFilterButton:focus {
- opacity: 1;
- /* 3 */ }
-
-/**
- * 1. Visually align the actions with the tabs. We can improve this by using flexbox instead, at a later point.
- */
-.kbnDocTableDetails__actions {
- float: right;
- padding-top: 8px;
- /* 1 */ }
-
-.kbnDocTableDetails__row > td {
- padding: 24px !important; }
- .kbnDocTableDetails__row > td tr:hover td {
- background: #1e1e25; }
-
-.kbnDocTableDetails__row td {
- border-top: none !important; }
-
-/**
- * 1. When switching between open and closed, the toggle changes size
- * slightly which is a problem because it forces the entire table to
- * re-render which is SLOW.
- */
-.kbnDocTableOpen__button {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- background-color: transparent;
- padding: 0;
- border: none;
- width: 14px;
- /* 1 */
- height: 14px; }
-
-.cxtSizePicker {
- text-align: center;
- width: 80px; }
- .cxtSizePicker::-webkit-outer-spin-button, .cxtSizePicker::-webkit-inner-spin-button {
- -webkit-appearance: none;
- appearance: none;
- margin: 0; }
-
-/**
- * 1. We want the kbnDocTable__container to scroll only when embedded in an embeddable panel
- * 2. Force a better looking scrollbar
- */
-.embPanel .kbnDocTable__container {
- scrollbar-width: thin;
- /* 2 */
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 0;
- -ms-flex: 1 1 0px;
- flex: 1 1 0;
- /* 1 */
- overflow: auto;
- /* 1 */ }
- .embPanel .kbnDocTable__container::-webkit-scrollbar {
- width: 16px;
- height: 16px; }
- .embPanel .kbnDocTable__container::-webkit-scrollbar-thumb {
- background-color: rgba(152, 162, 179, 0.5);
- border: 6px solid transparent;
- background-clip: content-box; }
- .embPanel .kbnDocTable__container::-webkit-scrollbar-corner, .embPanel .kbnDocTable__container::-webkit-scrollbar-track {
- background-color: transparent; }
-
-.leaflet-touch .leaflet-bar,
-.leaflet-draw-actions {
- -webkit-box-shadow: 0 6px 12px -1px rgba(0, 0, 0, 0.2), 0 4px 4px -1px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.2);
- box-shadow: 0 6px 12px -1px rgba(0, 0, 0, 0.2), 0 4px 4px -1px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.2);
- border: none; }
-
-.leaflet-container {
- background: #1D1E24;
- min-width: 1px !important;
- min-height: 1px !important; }
-
-.leaflet-clickable:hover {
- stroke-width: 8px;
- stroke-opacity: 0.8; }
-
-/**
- * 1. Since Leaflet is an external library, we also have to provide EUI variables
- * to non-override colors for darkmode.
- */
-.leaflet-draw-actions a,
-.leaflet-control a {
- background-color: #343741;
- /* 1 */
- border-color: #535966 !important;
- /* 1 */
- color: #DFE5EF !important;
- /* 1 */ }
- .leaflet-draw-actions a:hover,
- .leaflet-control a:hover {
- background-color: #25262E; }
-
-.leaflet-touch .leaflet-bar a:first-child {
- border-top-left-radius: 4px;
- border-top-right-radius: 4px; }
-
-.leaflet-touch .leaflet-bar a:last-child {
- border-bottom-left-radius: 4px;
- border-bottom-right-radius: 4px; }
-
-.leaflet-retina .leaflet-draw-toolbar a {
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 60' height='60' width='600'%3E%3Cg fill='rgb%28223, 229, 239%29'%3E%3Cg%3E%3Cpath d='M18 36v6h6v-6h-6zm4 4h-2v-2h2v2z'/%3E%3Cpath d='M36 18v6h6v-6h-6zm4 4h-2v-2h2v2z'/%3E%3Cpath d='M23.142 39.145l-2.285-2.29 16-15.998 2.285 2.285z'/%3E%3C/g%3E%3Cpath d='M100 24.565l-2.096 14.83L83.07 42 76 28.773 86.463 18z'/%3E%3Cpath d='M140 20h20v20h-20z'/%3E%3Cpath d='M221 30c0 6.078-4.926 11-11 11s-11-4.922-11-11c0-6.074 4.926-11 11-11s11 4.926 11 11z'/%3E%3Cpath d='M270,19c-4.971,0-9,4.029-9,9c0,4.971,5.001,12,9,14c4.001-2,9-9.029,9-14C279,23.029,274.971,19,270,19z M270,31.5c-2.484,0-4.5-2.014-4.5-4.5c0-2.484,2.016-4.5,4.5-4.5c2.485,0,4.5,2.016,4.5,4.5C274.5,29.486,272.485,31.5,270,31.5z'/%3E%3Cg%3E%3Cpath d='M337,30.156v0.407v5.604c0,1.658-1.344,3-3,3h-10c-1.655,0-3-1.342-3-3v-10c0-1.657,1.345-3,3-3h6.345 l3.19-3.17H324c-3.313,0-6,2.687-6,6v10c0,3.313,2.687,6,6,6h10c3.314,0,6-2.687,6-6v-8.809L337,30.156'/%3E%3Cpath d='M338.72 24.637l-8.892 8.892H327V30.7l8.89-8.89z'/%3E%3Cpath d='M338.697 17.826h4v4h-4z' transform='rotate(-134.99 340.703 19.817)'/%3E%3C/g%3E%3Cg%3E%3Cpath d='M381 42h18V24h-18v18zm14-16h2v14h-2V26zm-4 0h2v14h-2V26zm-4 0h2v14h-2V26zm-4 0h2v14h-2V26z'/%3E%3Cpath d='M395 20v-4h-10v4h-6v2h22v-2h-6zm-2 0h-6v-2h6v2z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E%0A");
- /* 1 */ }
-
-.leaflet-control-layers-expanded {
- padding: 0;
- margin: 0;
- font-size: 11px;
- font-size: 0.6875rem;
- font-family: "Inter UI", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- font-weight: 500;
- line-height: 1.5; }
- .leaflet-control-layers-expanded label {
- font-weight: 500;
- margin: 0;
- padding: 0; }
-
-/* over-rides leaflet popup styles to look like kibana tooltip */
-.leaflet-popup-content-wrapper {
- margin: 0;
- padding: 0;
- background: #1a1a1a;
- color: #FFF;
- border-radius: 4px !important; }
-
-.leaflet-popup {
- pointer-events: none; }
-
-.leaflet-popup-content {
- margin: 0;
- font-size: 14px;
- font-size: 0.875rem;
- line-height: 1.5;
- font-weight: 400;
- word-wrap: break-word;
- overflow: hidden;
- pointer-events: none; }
- .leaflet-popup-content > * {
- margin: 8px 8px 0; }
- .leaflet-popup-content > :last-child {
- margin-bottom: 8px; }
- .leaflet-popup-content table td, .leaflet-popup-content table th {
- padding: 4px; }
-
-.leaflet-popup-tip-container,
-.leaflet-popup-close-button,
-.leaflet-draw-tooltip {
- display: none !important; }
-
-.leaflet-container .leaflet-control-attribution {
- background-color: rgba(29, 30, 36, 0.3);
- color: #98A2B3; }
- .leaflet-container .leaflet-control-attribution p {
- display: inline; }
-
-.leaflet-touch .leaflet-control-zoom-in,
-.leaflet-touch .leaflet-control-zoom-out {
- text-indent: -10000px;
- background-repeat: no-repeat;
- background-position: center; }
-
-.leaflet-touch .leaflet-control-zoom-in {
- background-image: url("data:image/svg+xml,%0A%3Csvg width='15px' height='15px' viewBox='0 0 15 15' version='1.1' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='rgb%28223, 229, 239%29' d='M8,7 L8,3.5 C8,3.22385763 7.77614237,3 7.5,3 C7.22385763,3 7,3.22385763 7,3.5 L7,7 L3.5,7 C3.22385763,7 3,7.22385763 3,7.5 C3,7.77614237 3.22385763,8 3.5,8 L7,8 L7,11.5 C7,11.7761424 7.22385763,12 7.5,12 C7.77614237,12 8,11.7761424 8,11.5 L8,8 L11.5,8 C11.7761424,8 12,7.77614237 12,7.5 C12,7.22385763 11.7761424,7 11.5,7 L8,7 Z M7.5,15 C3.35786438,15 0,11.6421356 0,7.5 C0,3.35786438 3.35786438,0 7.5,0 C11.6421356,0 15,3.35786438 15,7.5 C15,11.6421356 11.6421356,15 7.5,15 Z' /%3E%3C/svg%3E"); }
-
-.leaflet-touch .leaflet-control-zoom-out {
- background-image: url("data:image/svg+xml,%0A%3Csvg width='15px' height='15px' viewBox='0 0 15 15' version='1.1' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='rgb%28223, 229, 239%29' d='M7.5,0 C11.6355882,0 15,3.36441176 15,7.5 C15,11.6355882 11.6355882,15 7.5,15 C3.36441176,15 0,11.6355882 0,7.5 C0,3.36441176 3.36441176,0 7.5,0 Z M3.5,7 C3.22385763,7 3,7.22385763 3,7.5 C3,7.77614237 3.22385763,8 3.5,8 L11.5,8 C11.7761424,8 12,7.77614237 12,7.5 C12,7.22385763 11.7761424,7 11.5,7 L3.5,7 Z' /%3E%3C/svg%3E"); }
-
-img.leaflet-tile {
- -webkit-filter: invert(1) brightness(1.75) grayscale(1);
- filter: invert(1) brightness(1.75) grayscale(1); }
-
-img.leaflet-tile.filters-off {
- -webkit-filter: none;
- filter: none; }
-
-.visMapLegend {
- font-size: 11px;
- font-size: 0.6875rem;
- -webkit-box-shadow: 0 6px 12px -1px rgba(0, 0, 0, 0.1), 0 4px 4px -1px rgba(0, 0, 0, 0.1), 0 2px 2px 0 rgba(0, 0, 0, 0.1);
- box-shadow: 0 6px 12px -1px rgba(0, 0, 0, 0.1), 0 4px 4px -1px rgba(0, 0, 0, 0.1), 0 2px 2px 0 rgba(0, 0, 0, 0.1);
- font-family: "Inter UI", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- font-weight: 500;
- line-height: 1.5;
- color: #98A2B3;
- padding: 8px;
- background: rgba(29, 30, 36, 0.8);
- border-radius: 4px; }
- .visMapLegend i {
- width: 10px;
- height: 10px;
- display: inline-block;
- margin: 3px 4px 0 0;
- border-radius: 50%;
- border: 1px solid #98A2B3;
- background: #98A2B3; }
-
-.visMapLegend__title {
- font-weight: 700; }
-
-.leaflet-top.leaflet-left .visMapLegend__wrapper {
- position: absolute;
- left: 40px;
- white-space: nowrap; }
-
-.homAddData__card {
- border: none;
- -webkit-box-shadow: none;
- box-shadow: none; }
-
-.homAddData__cardDivider {
- position: relative; }
- .homAddData__cardDivider:after {
- position: absolute;
- content: '';
- width: 1px;
- right: -8px;
- top: 0;
- bottom: 0;
- background: #343741; }
-
-.homAddData__icon {
- width: 64px;
- height: 64px; }
-
-.homAddData__footerItem--highlight {
- background-color: #08334a;
- padding: 16px; }
-
-.homAddData__footerItem {
- text-align: center; }
-
-.homAddData__logo {
- margin-left: 16px; }
-
-@media only screen and (max-width: 574px) {
- .homeAddData__flexGroup {
- -webkit-flex-wrap: wrap;
- -ms-flex-wrap: wrap;
- flex-wrap: wrap; } }
-
-@media only screen and (min-width: 575px) and (max-width: 767px) {
- .homeAddData__flexGroup {
- -webkit-flex-wrap: wrap;
- -ms-flex-wrap: wrap;
- flex-wrap: wrap; } }
-
-@media only screen and (max-width: 574px) {
- .homAddDat__flexTablet {
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column; }
- .homAddData__cardDivider:after {
- display: none; }
- .homAddData__cardDivider {
- -webkit-box-flex: 0 !important;
- -webkit-flex-grow: 0 !important;
- -ms-flex-positive: 0 !important;
- flex-grow: 0 !important;
- -webkit-flex-basis: 100% !important;
- -ms-flex-preferred-size: 100% !important;
- flex-basis: 100% !important; } }
-
-@media only screen and (min-width: 575px) and (max-width: 767px) {
- .homAddDat__flexTablet {
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column; }
- .homAddData__cardDivider:after {
- display: none; }
- .homAddData__cardDivider {
- -webkit-box-flex: 0 !important;
- -webkit-flex-grow: 0 !important;
- -ms-flex-positive: 0 !important;
- flex-grow: 0 !important;
- -webkit-flex-basis: 100% !important;
- -ms-flex-preferred-size: 100% !important;
- flex-basis: 100% !important; } }
-
-@media only screen and (min-width: 768px) and (max-width: 991px) {
- .homAddDat__flexTablet {
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column; }
- .homAddData__cardDivider:after {
- display: none; }
- .homAddData__cardDivider {
- -webkit-box-flex: 0 !important;
- -webkit-flex-grow: 0 !important;
- -ms-flex-positive: 0 !important;
- flex-grow: 0 !important;
- -webkit-flex-basis: 100% !important;
- -ms-flex-preferred-size: 100% !important;
- flex-basis: 100% !important; } }
-
-@media only screen and (min-width: 992px) and (max-width: 1199px) {
- .homeAddData__flexGroup {
- -webkit-flex-wrap: nowrap;
- -ms-flex-wrap: nowrap;
- flex-wrap: nowrap; } }
-
-@media only screen and (min-width: 1200px) {
- .homeAddData__flexGroup {
- -webkit-flex-wrap: nowrap;
- -ms-flex-wrap: nowrap;
- flex-wrap: nowrap; } }
-
-@media only screen and (max-width: 574px) {
- .homHome__synopsisItem {
- -webkit-flex-basis: 100% !important;
- -ms-flex-preferred-size: 100% !important;
- flex-basis: 100% !important; } }
-
-@media only screen and (min-width: 575px) and (max-width: 767px) {
- .homHome__synopsisItem {
- -webkit-flex-basis: 100% !important;
- -ms-flex-preferred-size: 100% !important;
- flex-basis: 100% !important; } }
-
-@media only screen and (min-width: 768px) and (max-width: 991px) {
- .homHome__synopsisItem {
- -webkit-flex-basis: 100% !important;
- -ms-flex-preferred-size: 100% !important;
- flex-basis: 100% !important; } }
-
-.homSampleDataSetCards {
- min-height: 1px; }
-
-.homSynopsis__card.homSynopsis__card--noPanel {
- border: none;
- -webkit-box-shadow: none;
- box-shadow: none; }
-
-.homSynopsis__card .euiCard__content {
- padding-top: 0 !important; }
-
-.homWelcome {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- z-index: 7000;
- background: inherit;
- background-color: #1a1b20;
- opacity: 0;
- overflow: auto;
- -webkit-animation: kibanaFullScreenGraphics_FadeIn 500ms cubic-bezier(0.694, 0.0482, 0.335, 1) 0s forwards;
- animation: kibanaFullScreenGraphics_FadeIn 500ms cubic-bezier(0.694, 0.0482, 0.335, 1) 0s forwards; }
- .homWelcome::before {
- position: absolute;
- top: 0;
- left: 0;
- z-index: 1;
- width: 310px;
- height: 477px;
- content: url("/ui/images/bg_top_branded_dark.svg"); }
- .homWelcome::after {
- position: fixed;
- bottom: 0;
- right: 0;
- z-index: 1;
- width: 313px;
- height: 461px;
- content: url("/ui/images/bg_bottom_branded_dark.svg"); }
-
-@-webkit-keyframes kibanaFullScreenGraphics_FadeIn {
- from {
- opacity: 0;
- -webkit-transform: translateY(200px), scale(0.75);
- transform: translateY(200px), scale(0.75); }
- to {
- opacity: 1;
- -webkit-transform: translateY(0), scale(1);
- transform: translateY(0), scale(1); } }
-
-@keyframes kibanaFullScreenGraphics_FadeIn {
- from {
- opacity: 0;
- -webkit-transform: translateY(200px), scale(0.75);
- transform: translateY(200px), scale(0.75); }
- to {
- opacity: 1;
- -webkit-transform: translateY(0), scale(1);
- transform: translateY(0), scale(1); } }
-
-.homWelcome__header {
- position: relative;
- padding: 32px;
- z-index: 10; }
-
-.homWelcome__logo {
- margin-bottom: 32px;
- display: inline-block;
- width: 80px;
- height: 80px;
- line-height: 80px;
- text-align: center;
- background-color: #1D1E24;
- border-radius: 100%;
- padding: 16px;
- -webkit-box-shadow: 0 6px 12px -1px rgba(0, 0, 0, 0.2), 0 4px 4px -1px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.2);
- box-shadow: 0 6px 12px -1px rgba(0, 0, 0, 0.2), 0 4px 4px -1px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.2); }
- .homWelcome__logo .euiIcon {
- vertical-align: baseline; }
-
-.homWelcome__footerAction {
- margin-right: 8px; }
-
-.homWelcome__content {
- position: relative;
- margin: auto;
- max-width: 512px;
- padding-left: 32px;
- padding-right: 32px;
- z-index: 10; }
-
-.homTutorial__notFoundPanel {
- background: #1D1E24;
- padding: 24px; }
-
-.homTutorial__instruction {
- -webkit-flex-shrink: 0;
- -ms-flex-negative: 0;
- flex-shrink: 0; }
-
-kbn-management-app,
-kbn-management-landing,
-kbn-management-indices,
-kbn-management-indices-edit,
-kbn-management-indices-create,
-kbn-management-advanced,
-kbn-management-objects,
-kbn-management-objects-view {
- display: block; }
-
-#management-landing {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex; }
-
-.kbn-management-tab:first-letter {
- text-transform: capitalize; }
-
-kbn-management-objects-view .ace_editor {
- height: 300px; }
-
-.mgtPage__body {
- max-width: 1200px; }
-
-.mgtPanel {
- margin-bottom: 16px;
- background: #1D1E24; }
-
-/**
- * 1. Override kuiPanelBody styles to accommodate padding of items within the panel body..
- */
-.mgtPanel__body {
- padding: 5px 10px;
- /* 1 */ }
-
-/**
- * 1. Create vertical space between items when they wrap.
- */
-.mgtPanel__item {
- padding: 5px 15px;
- /* 1 */ }
-
-.mgtPanel__link {
- font-size: 20px;
- font-size: 1.25rem;
- line-height: 1.5;
- line-height: 1.5; }
- .mgtPanel__link.mgtPanel__link--disabled {
- opacity: #98A2B3;
- cursor: default; }
- .mgtPanel__link.mgtPanel__link--disabled:hover, .mgtPanel__link.mgtPanel__link--disabled:visited {
- color: #1BA9F5; }
-
-kbn-management-objects form {
- margin-bottom: 16px; }
-
-kbn-management-objects .list-unstyled li {
- border-bottom: 1px solid #343741;
- padding: 8px; }
-
-kbn-management-objects .empty {
- color: #98A2B3; }
-
-kbn-management-objects .item {
- padding: 12px; }
- kbn-management-objects .item .item-title {
- margin-left: 24px; }
- kbn-management-objects .item .actions {
- margin-top: 4px; }
-
-kbn-management-objects .header .title, kbn-management-objects .header .controls {
- padding-right: 1em;
- display: inline-block; }
-
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-.mgtAdvancedSettings__field + * {
- margin-top: 16px; }
-
-.mgtAdvancedSettings__field .mgtAdvancedSettings__fieldTitle {
- padding-left: 8px;
- margin-left: -8px; }
-
-.mgtAdvancedSettings__field--unsaved .mgtAdvancedSettings__fieldTitle {
- -webkit-box-shadow: -4px 0px #FFCE7A;
- box-shadow: -4px 0px #FFCE7A; }
-
-.mgtAdvancedSettings__field--invalid .mgtAdvancedSettings__fieldTitle {
- -webkit-box-shadow: -4px 0px #F66;
- box-shadow: -4px 0px #F66; }
-
-@media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {
- .mgtAdvancedSettings__field {
- min-height: 1px; }
- .mgtAdvancedSettings__fieldRow {
- min-height: 1px; } }
-
-.mgtAdvancedSettings__fieldTitleUnsavedIcon {
- margin-left: 8px; }
-
-@media only screen and (max-width: 574px) {
- .mgtAdvancedSettingsForm__unsavedCount {
- display: none; } }
-
-.mgtAdvancedSettingsForm__unsavedCountMessage {
- -webkit-box-shadow: -4px 0px #FFCE7A;
- box-shadow: -4px 0px #FFCE7A;
- padding-left: 8px; }
-
-.mgtAdvancedSettingsForm__button {
- width: 100%; }
-
-.mgtAdvancedSettingsForm__bottomBar {
- margin-left: 48px;
- z-index: 9; }
- .mgtAdvancedSettingsForm__bottomBar--pushForNav {
- margin-left: 240px; }
- @media only screen and (max-width: 574px) {
- .mgtAdvancedSettingsForm__bottomBar {
- margin-left: 0; } }
- @media only screen and (min-width: 575px) and (max-width: 767px) {
- .mgtAdvancedSettingsForm__bottomBar {
- margin-left: 0; } }
-
-#indexPatternListReact {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex; }
- #indexPatternListReact .indexPatternList__headerWrapper {
- padding-bottom: 8px; }
- #indexPatternListReact .euiButtonEmpty__content {
- -webkit-box-pack: left;
- -webkit-justify-content: left;
- -ms-flex-pack: left;
- justify-content: left;
- padding: 0; }
- #indexPatternListReact .euiButtonEmpty__content span {
- text-overflow: ellipsis;
- overflow: hidden; }
- #indexPatternListReact .indexPatternListPrompt__descList {
- text-align: left; }
-
-.indexPatternList__badge {
- margin-left: 8px; }
-
-.kbnLocalApplicationWrapper {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- -webkit-box-flex: 1;
- -webkit-flex-grow: 1;
- -ms-flex-positive: 1;
- flex-grow: 1; }
-
- .kbnDocViewerTable {
- margin-top: 8px; }
-
- .kbnDocViewer pre,
- .kbnDocViewer .kbnDocViewer__value {
- display: inline-block;
- word-break: break-all;
- word-wrap: break-word;
- white-space: pre-wrap;
- color: #FFF;
- vertical-align: top;
- padding-top: 2px; }
-
- .kbnDocViewer .kbnDocViewer__field {
- padding-top: 8px; }
-
- .kbnDocViewer .dscFieldName {
- color: #98A2B3; }
-
- .kbnDocViewer td,
- .kbnDocViewer pre {
- font-family: "Roboto Mono", Consolas, Menlo, Courier, monospace; }
-
- .kbnDocViewer tr:first-child td {
- border-top-color: transparent; }
-
- .kbnDocViewer tr:hover .kbnDocViewer__actionButton {
- opacity: 1; }
-
- .kbnDocViewer__buttons,
- .kbnDocViewer__field {
- white-space: nowrap; }
-
- .kbnDocViewer__buttons {
- width: 60px; }
- .kbnDocViewer__buttons:focus-within .kbnDocViewer__actionButton {
- opacity: 1; }
-
- .kbnDocViewer__field {
- width: 160px; }
-
- .kbnDocViewer__actionButton {
- opacity: 0; }
- .kbnDocViewer__actionButton:focus {
- opacity: 1; }
-
- .kbnDocViewer__warning {
- margin-right: 8px; }
diff --git a/public/styles/7.9.0/index.light.scss b/public/styles/7.9.0/index.light.scss
deleted file mode 100644
index 0e21631113..0000000000
--- a/public/styles/7.9.0/index.light.scss
+++ /dev/null
@@ -1,2803 +0,0 @@
-.invisible {
- visibility: hidden; }
-
-.echChartStatus {
- visibility: hidden;
- pointer-events: none;
- z-index: -100000;
- width: 0;
- height: 0;
- position: absolute; }
-
-.echChart {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- height: 100%;
- position: relative; }
- .echChart--column {
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column; }
-
-.echContainer {
- -webkit-box-flex: 1;
- -webkit-flex: 1;
- -ms-flex: 1;
- flex: 1;
- position: relative; }
-
-.echChartPointerContainer {
- position: absolute;
- top: 0;
- bottom: 0;
- right: 0;
- left: 0;
- -webkit-box-sizing: border-box;
- box-sizing: border-box;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none; }
-
-.echChartResizer {
- z-index: -10000000;
- position: absolute;
- bottom: 0;
- top: 0;
- left: 0;
- right: 0;
- -webkit-box-sizing: border-box;
- box-sizing: border-box; }
-
-#echAnnotationContainerPortal {
- position: absolute;
- pointer-events: none; }
-
-.echAnnotation {
- pointer-events: none;
- position: absolute;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- font-size: 12px;
- font-weight: 700; }
-
-.echAnnotation--hidden,
-.echAnnotation__tooltip--hidden {
- opacity: 0; }
-
-.echAnnotation__tooltip {
- -webkit-box-shadow: 0 12px 24px 0 rgba(0, 0, 0, 0.1), 0 6px 12px 0 rgba(0, 0, 0, 0.1), 0 4px 4px 0 rgba(0, 0, 0, 0.1), 0 2px 2px 0 rgba(0, 0, 0, 0.1);
- box-shadow: 0 12px 24px 0 rgba(0, 0, 0, 0.1), 0 6px 12px 0 rgba(0, 0, 0, 0.1), 0 4px 4px 0 rgba(0, 0, 0, 0.1), 0 2px 2px 0 rgba(0, 0, 0, 0.1);
- border-radius: 4px;
- background-color: #404040;
- color: #FFF;
- z-index: 9000;
- max-width: 256px;
- overflow-wrap: break-word;
- font-size: 14px;
- font-size: 0.875rem;
- line-height: 1.5;
- padding: 12px;
- font-size: 12px;
- font-size: 0.75rem;
- line-height: 1.5;
- position: absolute;
- padding: 0;
- -webkit-transition: opacity 250ms;
- transition: opacity 250ms;
- pointer-events: none;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none; }
-
-.echAnnotation__header {
- font-weight: 700;
- border-bottom: solid 1px #595959;
- padding-bottom: 4px;
- margin-bottom: 4px;
- padding: 4px 8px; }
-
-.echAnnotation__details {
- padding: 4px 8px; }
-
-#echTooltipContainerPortal {
- position: absolute;
- pointer-events: none;
- z-index: 10000000; }
-
-.echTooltip {
- position: absolute;
- -webkit-box-shadow: 0 12px 24px 0 rgba(0, 0, 0, 0.1), 0 6px 12px 0 rgba(0, 0, 0, 0.1), 0 4px 4px 0 rgba(0, 0, 0, 0.1), 0 2px 2px 0 rgba(0, 0, 0, 0.1);
- box-shadow: 0 12px 24px 0 rgba(0, 0, 0, 0.1), 0 6px 12px 0 rgba(0, 0, 0, 0.1), 0 4px 4px 0 rgba(0, 0, 0, 0.1), 0 2px 2px 0 rgba(0, 0, 0, 0.1);
- border-radius: 4px;
- background-color: #404040;
- color: #FFF;
- z-index: 9000;
- max-width: 256px;
- overflow-wrap: break-word;
- font-size: 14px;
- font-size: 0.875rem;
- line-height: 1.5;
- padding: 12px;
- font-size: 12px;
- font-size: 0.75rem;
- line-height: 1.5;
- padding: 0;
- -webkit-transition: opacity 250ms;
- transition: opacity 250ms;
- pointer-events: none;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- margin-bottom: 4px; }
- .echTooltip__list {
- padding: 4px; }
- .echTooltip__header {
- font-weight: 700;
- border-bottom: solid 1px #595959;
- padding-bottom: 4px;
- margin-bottom: 4px;
- margin-bottom: 0;
- padding: 4px 8px; }
- .echTooltip__item {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- padding: 3px;
- -webkit-box-sizing: border-box;
- box-sizing: border-box;
- border-left: 4px solid transparent;
- min-width: 1px; }
- .echTooltip__label {
- overflow-wrap: break-word;
- word-wrap: break-word;
- min-width: 1px;
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 auto;
- -ms-flex: 1 1 auto;
- flex: 1 1 auto; }
- .echTooltip__value {
- font-weight: 700;
- text-align: right;
- -webkit-font-feature-settings: 'tnum';
- font-feature-settings: 'tnum';
- margin-left: 8px; }
- .echTooltip__rowHighlighted {
- background-color: rgba(255, 255, 255, 0.1); }
- .echTooltip--hidden {
- opacity: 0; }
-
-.echIcon {
- -webkit-flex-shrink: 0;
- -ms-flex-negative: 0;
- flex-shrink: 0;
- display: inline-block;
- vertical-align: middle;
- fill: currentColor; }
- .echIcon svg {
- -webkit-transform: translate(0, 0);
- transform: translate(0, 0); }
- .echIcon:focus {
- opacity: 1;
- background: #e6f0f8; }
-
-.echLegend--top .echLegendList, .echLegend--bottom .echLegendList {
- display: grid;
- grid-column-gap: 24px;
- grid-row-gap: 8px;
- margin-top: 8px;
- margin-bottom: 8px; }
- @media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {
- .echLegend--top .echLegendList, .echLegend--bottom .echLegendList {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: horizontal;
- -webkit-box-direction: normal;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-flex-wrap: wrap;
- -ms-flex-wrap: wrap;
- flex-wrap: wrap; } }
-
-.echLegend--left .echLegendList, .echLegend--right .echLegendList {
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column; }
-
-.echLegend--top, .echLegend--left {
- -webkit-box-ordinal-group: 1;
- -webkit-order: 0;
- -ms-flex-order: 0;
- order: 0; }
-
-.echLegend--bottom, .echLegend--right {
- -webkit-box-ordinal-group: 2;
- -webkit-order: 1;
- -ms-flex-order: 1;
- order: 1; }
-
-.echLegend--debug {
- background: red; }
-
-.echLegend .echLegendListContainer {
- scrollbar-width: thin;
- height: 100%;
- overflow-y: auto;
- -webkit-mask-image: linear-gradient(to bottom, rgba(255, 0, 0, 0.1) 0%, red 7.5px, red calc(100% - 7.5px), rgba(255, 0, 0, 0.1) 100%);
- mask-image: linear-gradient(to bottom, rgba(255, 0, 0, 0.1) 0%, red 7.5px, red calc(100% - 7.5px), rgba(255, 0, 0, 0.1) 100%);
- width: 100%;
- overflow-y: auto;
- overflow-x: hidden; }
- .echLegend .echLegendListContainer::-webkit-scrollbar {
- width: 16px;
- height: 16px; }
- .echLegend .echLegendListContainer::-webkit-scrollbar-thumb {
- background-color: rgba(105, 112, 125, 0.5);
- border: 6px solid transparent;
- background-clip: content-box; }
- .echLegend .echLegendListContainer::-webkit-scrollbar-corner, .echLegend .echLegendListContainer::-webkit-scrollbar-track {
- background-color: transparent; }
-
-.echLegendItem {
- color: #343741;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-flex-wrap: nowrap;
- -ms-flex-wrap: nowrap;
- flex-wrap: nowrap;
- -webkit-box-pack: justify;
- -webkit-justify-content: space-between;
- -ms-flex-pack: justify;
- justify-content: space-between;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
- -webkit-box-align: center;
- -webkit-align-items: center;
- -ms-flex-align: center;
- align-items: center;
- width: 100%; }
- .echLegendItem:not(.echLegendItem--hidden) .echLegendItem__color--changable {
- cursor: pointer; }
- .echLegendItem__color {
- margin-right: 4px; }
- .echLegendItem__visibility {
- margin-right: 4px; }
- .echLegendItem__visibility:hover {
- cursor: pointer; }
- .echLegendItem__label {
- font-size: 12px;
- font-size: 0.75rem;
- line-height: 1.5;
- max-width: 100%;
- overflow: hidden !important;
- text-overflow: ellipsis !important;
- white-space: nowrap !important;
- word-wrap: normal !important;
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 auto;
- -ms-flex: 1 1 auto;
- flex: 1 1 auto; }
- .echLegendItem__label--clickable:hover {
- cursor: pointer;
- text-decoration: underline; }
- .echLegendItem__extra {
- font-size: 12px;
- font-size: 0.75rem;
- line-height: 1.5;
- text-align: right;
- margin-left: 4px;
- -webkit-font-feature-settings: 'tnum';
- font-feature-settings: 'tnum'; }
- .echLegendItem__extra--hidden {
- display: none; }
- .echLegendItem--right, .echLegendItem--left {
- padding-top: 4px;
- padding-bottom: 4px; }
- @media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {
- .echLegendItem {
- padding-top: 4px;
- padding-bottom: 4px; }
- .echLegendItem--bottom, .echLegendItem--top {
- width: 200px;
- margin-right: 24px; } }
- .echLegendItem--hidden {
- color: #69707D; }
-
-.echReactiveChart_unavailable {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-align: center;
- -webkit-align-items: center;
- -ms-flex-align: center;
- align-items: center;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
- width: 100%;
- height: 100%;
- font-size: 12px;
- font-size: 0.75rem;
- line-height: 1.5;
- color: #69707D; }
-
-.echHighlighter {
- position: absolute;
- z-index: 1000;
- pointer-events: none;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- width: 100%;
- height: 100%; }
-
-.echHighlighterOverlay__fill {
- fill: rgba(255, 255, 255, 0.2); }
-
-.echHighlighterOverlay__stroke {
- stroke: rgba(255, 255, 255, 0.2); }
-
-.echHighlighter__mask {
- fill: rgba(255, 255, 255, 0.5); }
-
-.echCrosshair,
-.echCrosshair__band,
-.echCrosshair__line {
- position: absolute;
- pointer-events: none; }
-
-.echCrosshair__line {
- z-index: 8000; }
-
-.echBrushTool {
- position: absolute;
- top: 0;
- left: 0;
- margin: 0;
- padding: 0;
- -webkit-box-sizing: border-box;
- box-sizing: border-box;
- overflow: hidden;
- pointer-events: none; }
-
-.echCanvasRenderer {
- position: absolute;
- top: 0;
- left: 0;
- padding: 0;
- margin: 0;
- border: 0;
- background: transparent; }
-
-.echAnnotation {
- font-size: 12px;
- font-weight: 700; }
-
-input.ng-invalid.ng-dirty, input.ng-invalid.ng-touched,
-textarea.ng-invalid.ng-dirty,
-textarea.ng-invalid.ng-touched,
-select.ng-invalid.ng-dirty,
-select.ng-invalid.ng-touched {
- border-color: #BD271E !important; }
-
-input[type='radio'][disabled],
-fieldset[disabled] input[type='radio'],
-input[type='checkbox'][disabled],
-fieldset[disabled]
-input[type='checkbox'],
-.radio[disabled],
-fieldset[disabled]
-.radio,
-.radio-inline[disabled],
-fieldset[disabled]
-.radio-inline,
-.checkbox[disabled],
-fieldset[disabled]
-.checkbox,
-.checkbox-inline[disabled],
-fieldset[disabled]
-.checkbox-inline {
- cursor: default;
- opacity: 0.8; }
-
-.checkbox label {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-align: center;
- -webkit-align-items: center;
- -ms-flex-align: center;
- align-items: center;
- padding-left: 0 !important; }
- .checkbox label input[type='checkbox'] {
- float: none;
- margin: 0 4px;
- position: static; }
-
-.chrHeaderWrapper:not(.headerWrapper) .content {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: horizontal;
- -webkit-box-direction: normal;
- -webkit-flex-flow: row nowrap;
- -ms-flex-flow: row nowrap;
- flex-flow: row nowrap;
- width: 100%;
- height: 100%;
- overflow: hidden; }
-
-.application > *,
-.app-container > * {
- position: relative; }
-
-.application > config,
-.app-container > config {
- z-index: 1; }
-
-.application > navbar,
-.app-container > navbar {
- padding-bottom: 8px; }
-
-.application .globalQueryBar,
-.app-container .globalQueryBar {
- padding: 0px 8px 8px 8px; }
-
-.application > nav,
-.application > navbar,
-.app-container > nav,
-.app-container > navbar {
- z-index: 2 !important; }
-
-.application {
- position: relative;
- z-index: 0;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-flex: 1;
- -webkit-flex-grow: 1;
- -ms-flex-positive: 1;
- flex-grow: 1;
- -webkit-flex-shrink: 0;
- -ms-flex-negative: 0;
- flex-shrink: 0;
- -webkit-flex-basis: auto;
- -ms-flex-preferred-size: auto;
- flex-basis: auto;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column; }
- .application > * {
- -webkit-flex-shrink: 0;
- -ms-flex-negative: 0;
- flex-shrink: 0; }
-
-[fixed-scroll] {
- overflow-x: auto;
- padding-bottom: 0; }
- [fixed-scroll] + .fixed-scroll-scroller {
- position: fixed;
- bottom: 0;
- overflow-x: auto;
- overflow-y: hidden; }
-
-.page-row {
- padding: 0 16px;
- margin: 16px 0; }
-
-.page-row-text {
- color: #69707D;
- font-size: 14px; }
-
-:focus:not([class^='eui']):not(.kbn-resetFocusState) {
- -webkit-animation: 350ms cubic-bezier(0.694, 0.0482, 0.335, 1) 1 normal forwards focusRingAnimate !important;
- animation: 350ms cubic-bezier(0.694, 0.0482, 0.335, 1) 1 normal forwards focusRingAnimate !important; }
-
-.euiComboBox input:not([class^='eui']):focus {
- -webkit-animation: none !important;
- animation: none !important; }
-
-.euiBody--collapsibleNavIsDocked .euiBottomBar {
- margin-left: 320px; }
-
-.fullWidth {
- width: 100% !important; }
-
-.small {
- font-size: 0.9em !important; }
-
-.smaller {
- font-size: 0.8em !important; }
-
-.smallest {
- font-size: 0.7em !important; }
-
-.text-monospace {
- font-family: "Roboto Mono", Consolas, Menlo, Courier, monospace; }
-
-.application .ace-tm {
- background-color: #F5F7FA;
- color: #343741; }
- .application .ace-tm .ace_scrollbar {
- scrollbar-width: thin; }
- .application .ace-tm .ace_scrollbar::-webkit-scrollbar {
- width: 16px;
- height: 16px; }
- .application .ace-tm .ace_scrollbar::-webkit-scrollbar-thumb {
- background-color: rgba(105, 112, 125, 0.5);
- border: 6px solid transparent;
- background-clip: content-box; }
- .application .ace-tm .ace_scrollbar::-webkit-scrollbar-corner, .application .ace-tm .ace_scrollbar::-webkit-scrollbar-track {
- background-color: transparent; }
- .application .ace-tm .ace_gutter-active-line,
- .application .ace-tm .ace_marker-layer .ace_active-line {
- background-color: rgba(211, 218, 230, 0.7); }
- .application .ace-tm .ace_snippet-marker {
- width: 100%;
- background-color: #e9edf3;
- border: none; }
- .application .ace-tm .ace_indent-guide {
- background: linear-gradient(to left, #98A2B3 0%, #98A2B3 1px, transparent 1px, transparent 100%); }
- .application .ace-tm .ace_search {
- z-index: 1001; }
- .application .ace-tm .ace_layer.ace_marker-layer {
- overflow: visible; }
- .application .ace-tm .ace_warning {
- color: #BD271E; }
- .application .ace-tm .ace_method {
- color: #c80a68; }
- .application .ace-tm .ace_url,
- .application .ace-tm .ace_start_triple_quote,
- .application .ace-tm .ace_end_triple_quote {
- color: #00756c; }
- .application .ace-tm .ace_multi_string {
- color: #007c1e;
- font-style: italic; }
- .application .ace-tm .ace_gutter {
- background-color: #FFF;
- color: #69707D;
- border-left: 1px solid #e9edf3; }
- .application .ace-tm .ace_print-margin {
- width: 1px;
- background: #D3DAE6; }
- .application .ace-tm .ace_fold {
- background-color: #6B72E6; }
- .application .ace-tm .ace_cursor {
- color: #000; }
- .application .ace-tm .ace_invisible {
- color: #D3DAE6; }
- .application .ace-tm .ace_storage,
- .application .ace-tm .ace_keyword {
- color: #00739d; }
- .application .ace-tm .ace_constant {
- color: #900; }
- .application .ace-tm .ace_constant.ace_buildin {
- color: #5848f6; }
- .application .ace-tm .ace_constant.ace_language {
- color: #5457ea; }
- .application .ace-tm .ace_constant.ace_library {
- color: #007c1e; }
- .application .ace-tm .ace_invalid {
- background-color: #f8e9e9;
- color: #bd271e; }
- .application .ace-tm .ace_support.ace_function {
- color: #3c4c72; }
- .application .ace-tm .ace_support.ace_constant {
- color: #007c1e; }
- .application .ace-tm .ace_support.ace_type,
- .application .ace-tm .ace_support.ace_class {
- color: #5963b5; }
- .application .ace-tm .ace_keyword.ace_operator {
- color: #646a77; }
- .application .ace-tm .ace_string {
- color: #007c1e; }
- .application .ace-tm .ace_comment {
- color: #41755c; }
- .application .ace-tm .ace_comment.ace_doc {
- color: #00739d; }
- .application .ace-tm .ace_comment.ace_doc.ace_tag {
- color: #656b77; }
- .application .ace-tm .ace_constant.ace_numeric {
- color: #00739d; }
- .application .ace-tm .ace_variable {
- color: #00739d; }
- .application .ace-tm .ace_xml-pe {
- color: #646a77; }
- .application .ace-tm .ace_entity.ace_name.ace_function {
- color: #0000A2; }
- .application .ace-tm .ace_heading {
- color: #0c07ff; }
- .application .ace-tm .ace_list {
- color: #b90690; }
- .application .ace-tm .ace_meta.ace_tag {
- color: #00168e; }
- .application .ace-tm .ace_string.ace_regex {
- color: #d00000; }
- .application .ace-tm .ace_marker-layer .ace_selection {
- background: #b3d3e9; }
- .application .ace-tm.ace_multiselect .ace_selection.ace_start {
- -webkit-box-shadow: 0 0 3px 0px #FFF;
- box-shadow: 0 0 3px 0px #FFF; }
- .application .ace-tm .ace_marker-layer .ace_step {
- background: #fdedcc; }
- .application .ace-tm .ace_marker-layer .ace_stack {
- background: #cce5e3; }
- .application .ace-tm .ace_marker-layer .ace_bracket {
- margin: -1px 0 0 -1px;
- border: 1px solid #D3DAE6; }
- .application .ace-tm .ace_marker-layer .ace_selected-word {
- background: #F5F7FA;
- border: 1px solid #D3DAE6; }
-
-.control-group, navbar {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-flex: 0;
- -webkit-flex: 0 0 auto;
- -ms-flex: 0 0 auto;
- flex: 0 0 auto;
- -webkit-box-orient: horizontal;
- -webkit-box-direction: normal;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row;
- -webkit-flex-wrap: wrap;
- -ms-flex-wrap: wrap;
- flex-wrap: wrap;
- -webkit-box-align: stretch;
- -webkit-align-items: stretch;
- -ms-flex-align: stretch;
- align-items: stretch;
- padding: 4px 16px; }
- .control-group > *, navbar > * {
- padding-right: 16px;
- -webkit-box-flex: 0;
- -webkit-flex: 0 0 auto;
- -ms-flex: 0 0 auto;
- flex: 0 0 auto; }
- .control-group > *:last-child, navbar > *:last-child {
- padding-right: 0; }
- .control-group .inline-form .input-group, navbar .inline-form .input-group {
- margin-bottom: 0;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex; }
- .control-group .inline-form .input-group > *, navbar .inline-form .input-group > * {
- border-radius: 0; }
- .control-group .inline-form .input-group > :first-child, navbar .inline-form .input-group > :first-child {
- border-bottom-left-radius: 4px;
- border-top-left-radius: 4px; }
- .control-group .inline-form .input-group > :last-child, navbar .inline-form .input-group > :last-child {
- border-bottom-right-radius: 4px;
- border-top-right-radius: 4px; }
- .control-group .inline-form, navbar .inline-form {
- -webkit-box-flex: 0;
- -webkit-flex: 0 0 auto;
- -ms-flex: 0 0 auto;
- flex: 0 0 auto;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- display: flex; }
- .control-group .inline-form > *, navbar .inline-form > * {
- -webkit-flex-shrink: 0;
- -ms-flex-negative: 0;
- flex-shrink: 0; }
- .control-group .inline-form > .typeahead, navbar .inline-form > .typeahead {
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 auto;
- -ms-flex: 1 1 auto;
- flex: 1 1 auto;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column; }
- .control-group .inline-form > .typeahead > *, navbar .inline-form > .typeahead > * {
- -webkit-flex-shrink: 0;
- -ms-flex-negative: 0;
- flex-shrink: 0; }
- .control-group .inline-form > .typeahead > .input-group, navbar .inline-form > .typeahead > .input-group {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-flex: 1;
- -webkit-flex: 1 0 auto;
- -ms-flex: 1 0 auto;
- flex: 1 0 auto; }
- .control-group .inline-form > .typeahead > .input-group > *, navbar .inline-form > .typeahead > .input-group > * {
- float: none;
- height: auto;
- width: auto;
- -webkit-box-flex: 0;
- -webkit-flex: 0 0 auto;
- -ms-flex: 0 0 auto;
- flex: 0 0 auto; }
- .control-group .inline-form > .typeahead > .input-group input[type="text"], navbar .inline-form > .typeahead > .input-group input[type="text"] {
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 100%;
- -ms-flex: 1 1 100%;
- flex: 1 1 100%; }
- .control-group > .fill, navbar > .fill {
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 1%;
- -ms-flex: 1 1 1%;
- flex: 1 1 1%; }
-
-.hintbox {
- padding: 8px 12px;
- border-radius: 4px;
- margin-bottom: 8px;
- background-color: #D3DAE6;
- line-height: 1.5; }
- .hintbox a {
- color: #006BB4 !important; }
- .hintbox a:hover {
- color: #004d81 !important; }
- .hintbox pre {
- background-color: #FFF; }
- .hintbox ul, .hintbox ol {
- padding-left: 24px; }
- .hintbox > * {
- margin: 0; }
- .hintbox > * + * {
- margin-top: 8px; }
- .hintbox .table-bordered {
- border: 1px solid #D3DAE6; }
- .hintbox .table-bordered > thead > tr > th,
- .hintbox .table-bordered > thead > tr > td,
- .hintbox .table-bordered > tbody > tr > th,
- .hintbox .table-bordered > tbody > tr > td,
- .hintbox .table-bordered > tfoot > tr > th,
- .hintbox .table-bordered > tfoot > tr > td {
- border: 1px solid #D3DAE6; }
- .hintbox .table-bordered > thead > tr > th,
- .hintbox .table-bordered > thead > tr > td {
- border-bottom-width: 2px; }
-
-.hintbox-label,
-.hintbox-label[ng-click] {
- cursor: help; }
-
-i.input-error {
- position: absolute;
- margin-left: -24px;
- color: #BD271E;
- margin-top: 8px;
- z-index: 5; }
-
-select {
- color: #343741;
- background-color: #FFF; }
-
-.form-control {
- display: block;
- width: 100%;
- height: 32px;
- padding: 4px 12px;
- font-size: 14px;
- font-size: 0.875rem;
- line-height: 1.5;
- border: 1px solid #D3DAE6;
- background-color: #fbfcfd;
- color: #343741;
- border-radius: 4px;
- cursor: pointer; }
- .form-control:not([type='range']) {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none; }
- .form-control:focus {
- border-color: #006BB4;
- outline: none;
- -webkit-box-shadow: none;
- box-shadow: none; }
-
-select.form-control {
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath fill='rgb%2852, 55, 65%29' d='M13.0688508,5.15725038 L8.38423975,9.76827428 C8.17054415,9.97861308 7.82999214,9.97914095 7.61576025,9.76827428 L2.93114915,5.15725038 C2.7181359,4.94758321 2.37277319,4.94758321 2.15975994,5.15725038 C1.94674669,5.36691756 1.94674669,5.70685522 2.15975994,5.9165224 L6.84437104,10.5275463 C7.48517424,11.1582836 8.51644979,11.1566851 9.15562896,10.5275463 L13.8402401,5.9165224 C14.0532533,5.70685522 14.0532533,5.36691756 13.8402401,5.15725038 C13.6272268,4.94758321 13.2818641,4.94758321 13.0688508,5.15725038 Z'/%3E%3C/svg%3E");
- background-size: 16px;
- background-repeat: no-repeat;
- background-position: calc(100% - 8px);
- padding-right: 32px; }
- select.form-control::-ms-expand {
- display: none; }
- select.form-control:focus::-ms-value {
- color: #343741;
- background: transparent; }
-
-.kuiFormSection {
- margin-bottom: 16px; }
-
-.kuiFormLabel {
- font-size: 12px;
- font-weight: 600;
- color: #343741;
- display: block;
- margin-bottom: 5px; }
- .kuiFormLabel[for] {
- cursor: pointer; }
-
-.kuiInputNote {
- margin: 4px 0 8px; }
-
-.kuiInputNote--danger {
- color: #BD271E; }
-
-.kuiInputNote--warning {
- color: #F5A700; }
-
-.list-group-menu.select-mode a {
- outline: none;
- color: #1a7abc; }
-
-.list-group-menu .list-group-menu-item {
- list-style: none;
- color: #1a7abc; }
- .list-group-menu .list-group-menu-item.active {
- font-weight: bold;
- background-color: #D3DAE6; }
- .list-group-menu .list-group-menu-item:hover {
- background-color: #e6f0f8; }
- .list-group-menu .list-group-menu-item li {
- list-style: none;
- color: #1a7abc; }
-
-navbar {
- max-height: 340px;
- margin-bottom: 0;
- padding: 0 8px 4px;
- color: #69707D;
- background-color: #D3DAE6;
- border: none;
- z-index: 1000; }
- navbar > * {
- padding-right: 8px; }
- navbar .navbar-text {
- margin-top: 4px;
- margin-bottom: 4px; }
- navbar > .name {
- max-width: 100%;
- overflow: hidden !important;
- text-overflow: ellipsis !important;
- white-space: nowrap !important;
- word-wrap: normal !important;
- -webkit-align-self: center;
- -ms-flex-item-align: center;
- align-self: center;
- font-size: 20px; }
- navbar button {
- color: #69707D;
- background-color: transparent; }
- navbar button:hover, navbar button:focus {
- color: #69707D;
- background-color: transparent; }
- navbar button:active, navbar button.active {
- color: #343741;
- background-color: transparent;
- -webkit-box-shadow: none;
- box-shadow: none; }
- navbar button:active:focus, navbar button.active:focus {
- outline: none; }
- navbar button[disabled] {
- color: #98A2B3;
- background-color: transparent; }
- navbar .inline-form .input-group button {
- color: #FFF;
- background-color: #69707D;
- border: none; }
- @media only screen and (min-width: 992px) and (max-width: 1199px) {
- navbar > .name {
- max-width: 500px; } }
- @media only screen and (min-width: 1200px) {
- navbar > .name {
- max-width: 500px; } }
- @media only screen and (max-width: 574px) {
- navbar > .fill {
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 992px;
- -ms-flex: 1 1 992px;
- flex: 1 1 992px; } }
- @media only screen and (min-width: 575px) and (max-width: 767px) {
- navbar > .fill {
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 992px;
- -ms-flex: 1 1 992px;
- flex: 1 1 992px; } }
- @media only screen and (min-width: 768px) and (max-width: 991px) {
- navbar > .fill {
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 992px;
- -ms-flex: 1 1 992px;
- flex: 1 1 992px; } }
- @media only screen and (max-width: 574px) {
- navbar > .name {
- max-width: 100%; } }
- @media only screen and (min-width: 575px) and (max-width: 767px) {
- navbar > .name {
- max-width: 100%; } }
-
-.config {
- border-bottom: 1px solid transparent; }
- .config .container-fluid {
- background-color: #fafbfd;
- padding: 8px; }
-
-paginate {
- display: block; }
- paginate paginate-controls {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-align: center;
- -webkit-align-items: center;
- -ms-flex-align: center;
- align-items: center;
- padding: 4px 4px 8px;
- text-align: center; }
- paginate paginate-controls .pagination-other-pages {
- -webkit-box-flex: 1;
- -webkit-flex: 1 0 auto;
- -ms-flex: 1 0 auto;
- flex: 1 0 auto;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center; }
- paginate paginate-controls .pagination-other-pages-list {
- -webkit-box-flex: 0;
- -webkit-flex: 0 0 auto;
- -ms-flex: 0 0 auto;
- flex: 0 0 auto;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
- padding: 0;
- margin: 0;
- list-style: none; }
- paginate paginate-controls .pagination-other-pages-list > li {
- -webkit-box-flex: 0;
- -webkit-flex: 0 0 auto;
- -ms-flex: 0 0 auto;
- flex: 0 0 auto;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none; }
- paginate paginate-controls .pagination-other-pages-list > li a {
- text-decoration: none;
- background-color: #F5F7FA;
- margin-left: 2px;
- padding: 8px 12px; }
- paginate paginate-controls .pagination-other-pages-list > li a:hover {
- text-decoration: underline; }
- paginate paginate-controls .pagination-other-pages-list > li.active a {
- text-decoration: none !important;
- font-weight: 700;
- color: #69707D;
- cursor: default; }
- paginate paginate-controls .pagination-size {
- -webkit-box-flex: 0;
- -webkit-flex: 0 0 auto;
- -ms-flex: 0 0 auto;
- flex: 0 0 auto; }
- paginate paginate-controls .pagination-size input[type=number] {
- width: 3em; }
-
-.spinner.ng-hide {
- visibility: hidden;
- display: block !important;
- opacity: 0;
- -webkit-transition-delay: 0.25s;
- transition-delay: 0.25s; }
-
-/**
-* Style ES document _source in table view key: value
-* Use alpha so this will stand out against non-white backgrounds, e.g. the highlighted
-* row in the Context Log.
-*/
-.table .table {
- background-color: #FFF; }
-
-kbn-table dl.source, .kbn-table dl.source, tbody[kbn-rows] dl.source {
- margin-bottom: 0;
- line-height: 2em;
- word-break: break-word; }
- kbn-table dl.source dt, kbn-table dl.source dd, .kbn-table dl.source dt, .kbn-table dl.source dd, tbody[kbn-rows] dl.source dt, tbody[kbn-rows] dl.source dd {
- display: inline; }
- kbn-table dl.source dt, .kbn-table dl.source dt, tbody[kbn-rows] dl.source dt {
- background-color: rgba(0, 86, 144, 0.1);
- color: #343741;
- padding: 2px 4px;
- margin-right: 4px;
- word-break: normal;
- border-radius: 4px; }
-
-kbn-table .table .table, .kbn-table .table .table, tbody[kbn-rows] .table .table {
- margin-bottom: 0; }
- kbn-table .table .table tr:first-child > td, .kbn-table .table .table tr:first-child > td, tbody[kbn-rows] .table .table tr:first-child > td {
- border-top: none; }
- kbn-table .table .table td.field-name, .kbn-table .table .table td.field-name, tbody[kbn-rows] .table .table td.field-name {
- font-weight: 700; }
-
-table th i.fa-sort {
- color: #D3DAE6; }
-
-table th button.fa-sort-asc,
-table th button.fa-sort-down,
-table th i.fa-sort-asc,
-table th i.fa-sort-down {
- color: #006BB4; }
-
-table th button.fa-sort-desc,
-table th button.fa-sort-up,
-table th i.fa-sort-desc,
-table th i.fa-sort-up {
- color: #006BB4; }
-
-.truncate-by-height {
- overflow: hidden; }
-
-/*!
- * ui-select
- * http://github.com/angular-ui/ui-select
- * Version: 0.19.5 - 2016-10-24T23:13:59.551Z
- * License: MIT
- */
-/* Style when highlighting a search. */
-.ui-select-highlight {
- font-weight: bold; }
-
-.ui-select-offscreen {
- clip: rect(0 0 0 0) !important;
- width: 1px !important;
- height: 1px !important;
- border: 0 !important;
- margin: 0 !important;
- padding: 0 !important;
- overflow: hidden !important;
- position: absolute !important;
- outline: 0 !important;
- left: 0px !important;
- top: 0px !important; }
-
-.ui-select-choices-row:hover {
- background-color: #F5F7FA; }
-
-/* Select2 theme */
-/* Mark invalid Select2 */
-.ng-dirty.ng-invalid > a.select2-choice {
- border-color: #BD271E; }
-
-.select2-result-single {
- padding-left: 0; }
-
-.select2-locked > .select2-search-choice-close {
- display: none; }
-
-.select-locked > .ui-select-match-close {
- display: none; }
-
-body > .select2-container.open {
- z-index: 9999;
- /* The z-index Select2 applies to the select2-drop */ }
-
-/* Handle up direction Select2 */
-.ui-select-container[theme='select2'].direction-up .ui-select-match,
-.ui-select-container.select2.direction-up .ui-select-match {
- border-radius: 4px;
- /* FIXME hardcoded value :-/ */
- border-top-left-radius: 0;
- border-top-right-radius: 0; }
-
-.ui-select-container[theme='select2'].direction-up .ui-select-dropdown,
-.ui-select-container.select2.direction-up .ui-select-dropdown {
- border-radius: 4px;
- /* FIXME hardcoded value :-/ */
- border-bottom-left-radius: 0;
- border-bottom-right-radius: 0;
- border-top-width: 1px;
- /* FIXME hardcoded value :-/ */
- border-top-style: solid;
- -webkit-box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25);
- box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25);
- margin-top: -4px;
- /* FIXME hardcoded value :-/ */ }
-
-.ui-select-container[theme='select2'].direction-up .ui-select-dropdown .select2-search,
-.ui-select-container.select2.direction-up .ui-select-dropdown .select2-search {
- margin-top: 4px;
- /* FIXME hardcoded value :-/ */ }
-
-.ui-select-container[theme='select2'].direction-up.select2-dropdown-open .ui-select-match,
-.ui-select-container.select2.direction-up.select2-dropdown-open .ui-select-match {
- border-bottom-color: #006BB4; }
-
-.ui-select-container[theme='select2'] .ui-select-dropdown .ui-select-search-hidden,
-.ui-select-container[theme='select2'] .ui-select-dropdown .ui-select-search-hidden input {
- opacity: 0;
- height: 0;
- min-height: 0;
- padding: 0;
- margin: 0;
- border: 0; }
-
-/* Bootstrap theme */
-/* Helper class to show styles when focus */
-.btn-default-focus {
- color: #343741;
- background-color: #FFF;
- border-color: #006BB4;
- text-decoration: none;
- outline: none;
- -webkit-box-shadow: none;
- box-shadow: none; }
-
-.ui-select-bootstrap .ui-select-toggle {
- display: block;
- width: 100%;
- height: 32px;
- padding: 4px 12px;
- font-size: 14px;
- font-size: 0.875rem;
- line-height: 1.5;
- border: 1px solid #D3DAE6;
- background-color: #fbfcfd;
- color: #343741;
- border-radius: 4px;
- cursor: pointer;
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath fill='rgb%2852, 55, 65%29' d='M13.0688508,5.15725038 L8.38423975,9.76827428 C8.17054415,9.97861308 7.82999214,9.97914095 7.61576025,9.76827428 L2.93114915,5.15725038 C2.7181359,4.94758321 2.37277319,4.94758321 2.15975994,5.15725038 C1.94674669,5.36691756 1.94674669,5.70685522 2.15975994,5.9165224 L6.84437104,10.5275463 C7.48517424,11.1582836 8.51644979,11.1566851 9.15562896,10.5275463 L13.8402401,5.9165224 C14.0532533,5.70685522 14.0532533,5.36691756 13.8402401,5.15725038 C13.6272268,4.94758321 13.2818641,4.94758321 13.0688508,5.15725038 Z'/%3E%3C/svg%3E");
- background-size: 16px;
- background-repeat: no-repeat;
- background-position: calc(100% - 8px);
- padding-right: 32px; }
- .ui-select-bootstrap .ui-select-toggle:not([type='range']) {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none; }
- .ui-select-bootstrap .ui-select-toggle:focus {
- border-color: #006BB4;
- outline: none;
- -webkit-box-shadow: none;
- box-shadow: none; }
- .ui-select-bootstrap .ui-select-toggle::-ms-expand {
- display: none; }
- .ui-select-bootstrap .ui-select-toggle:focus::-ms-value {
- color: #343741;
- background: transparent; }
-
-.ui-select-bootstrap .ui-select-toggle > .caret {
- display: none; }
-
-/* Fix Bootstrap dropdown position when inside a input-group */
-.input-group > .ui-select-bootstrap.dropdown {
- /* Instead of relative */
- position: static; }
-
-.input-group > .ui-select-bootstrap > input.ui-select-search.form-control {
- border-radius: 4px;
- /* FIXME hardcoded value :-/ */
- border-top-right-radius: 0;
- border-bottom-right-radius: 0; }
-
-.input-group > .ui-select-bootstrap > input.ui-select-search.form-control.direction-up {
- border-radius: 4px !important;
- /* FIXME hardcoded value :-/ */
- border-top-right-radius: 0 !important;
- border-bottom-right-radius: 0 !important; }
-
-.ui-select-bootstrap .ui-select-search-hidden {
- opacity: 0;
- height: 0;
- min-height: 0;
- padding: 0;
- margin: 0;
- border: 0; }
-
-.ui-select-bootstrap > .ui-select-match > .btn {
- display: block;
- width: 100%;
- height: 32px;
- padding: 4px 12px;
- font-size: 14px;
- font-size: 0.875rem;
- line-height: 1.5;
- border: 1px solid #D3DAE6;
- background-color: #fbfcfd;
- color: #343741;
- border-radius: 4px;
- cursor: pointer;
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Cpath fill='rgb%2852, 55, 65%29' d='M13.0688508,5.15725038 L8.38423975,9.76827428 C8.17054415,9.97861308 7.82999214,9.97914095 7.61576025,9.76827428 L2.93114915,5.15725038 C2.7181359,4.94758321 2.37277319,4.94758321 2.15975994,5.15725038 C1.94674669,5.36691756 1.94674669,5.70685522 2.15975994,5.9165224 L6.84437104,10.5275463 C7.48517424,11.1582836 8.51644979,11.1566851 9.15562896,10.5275463 L13.8402401,5.9165224 C14.0532533,5.70685522 14.0532533,5.36691756 13.8402401,5.15725038 C13.6272268,4.94758321 13.2818641,4.94758321 13.0688508,5.15725038 Z'/%3E%3C/svg%3E");
- background-size: 16px;
- background-repeat: no-repeat;
- background-position: calc(100% - 8px);
- padding-right: 32px;
- text-align: left !important; }
- .ui-select-bootstrap > .ui-select-match > .btn:not([type='range']) {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none; }
- .ui-select-bootstrap > .ui-select-match > .btn:focus {
- border-color: #006BB4;
- outline: none;
- -webkit-box-shadow: none;
- box-shadow: none; }
- .ui-select-bootstrap > .ui-select-match > .btn::-ms-expand {
- display: none; }
- .ui-select-bootstrap > .ui-select-match > .btn:focus::-ms-value {
- color: #343741;
- background: transparent; }
- .ui-select-bootstrap > .ui-select-match > .btn .ui-select-placeholder {
- color: #98A2B3; }
- .ui-select-bootstrap > .ui-select-match > .btn:focus, .ui-select-bootstrap > .ui-select-match > .btn:active {
- background-color: #FFF;
- color: #343741;
- outline: none; }
-
-.ui-select-bootstrap > .ui-select-match > .caret {
- display: none; }
-
-/* See Scrollable Menu with Bootstrap 3 http://stackoverflow.com/questions/19227496 */
-.ui-select-bootstrap > .ui-select-choices,
-.ui-select-bootstrap > .ui-select-no-choice {
- width: 100%;
- height: auto;
- max-height: 224px;
- overflow-x: hidden; }
-
-body > .ui-select-bootstrap.open {
- z-index: 2000; }
-
-.ui-select-multiple.ui-select-bootstrap {
- height: auto;
- padding: 3px 5px 2px;
- border: 1px solid #D3DAE6;
- background-color: #fbfcfd; }
- .ui-select-multiple.ui-select-bootstrap.kuiInputError {
- border-color: #BD271E; }
-
-.ui-select-multiple.ui-select-bootstrap input.ui-select-search {
- background-color: transparent !important;
- /* To prevent double background when disabled */
- border: none;
- outline: none;
- height: 1.666666em;
- margin-bottom: 3px; }
-
-.ui-select-multiple.ui-select-bootstrap .ui-select-match .close {
- font-size: 1.6em;
- line-height: 0.75; }
-
-.ui-select-multiple.ui-select-bootstrap .ui-select-match-item {
- outline: 0;
- margin: 0 3px 3px 0; }
-
-.ui-select-multiple .ui-select-match-item {
- position: relative; }
-
-.ui-select-multiple .ui-select-match-item.dropping .ui-select-match-close {
- pointer-events: none; }
-
-.ui-select-multiple:hover .ui-select-match-item.dropping-before:before {
- content: '';
- position: absolute;
- top: 0;
- right: 100%;
- height: 100%;
- margin-right: 2px;
- border-left: 1px solid #006BB4; }
-
-.ui-select-multiple:hover .ui-select-match-item.dropping-after:after {
- content: '';
- position: absolute;
- top: 0;
- left: 100%;
- height: 100%;
- margin-left: 2px;
- border-right: 1px solid #006BB4; }
-
-.ui-select-bootstrap .ui-select-choices-row > span {
- font-size: 14px;
- font-size: 0.875rem;
- line-height: 1.5;
- max-width: 100%;
- overflow: hidden !important;
- text-overflow: ellipsis !important;
- white-space: nowrap !important;
- word-wrap: normal !important;
- font-weight: inherit;
- cursor: pointer;
- display: block;
- padding: 4px 16px;
- clear: both;
- color: #343741;
- white-space: nowrap; }
- .ui-select-bootstrap .ui-select-choices-row > span:hover, .ui-select-bootstrap .ui-select-choices-row > span:focus {
- text-decoration: none;
- color: #343741;
- background-color: #e6f0f8; }
-
-.ui-select-bootstrap .ui-select-choices-row.active > span {
- color: #343741;
- text-decoration: none;
- outline: 0;
- background-color: #e6f0f8; }
-
-.ui-select-bootstrap .ui-select-choices-row.disabled > span,
-.ui-select-bootstrap .ui-select-choices-row.active.disabled > span {
- color: #c2c3c6;
- cursor: not-allowed;
- background-color: transparent; }
-
-/* fix hide/show angular animation */
-.ui-select-match.ng-hide-add,
-.ui-select-search.ng-hide-add {
- display: none !important; }
-
-/* Mark invalid Bootstrap */
-.ui-select-bootstrap.ng-dirty.ng-invalid > button.btn.ui-select-match {
- border-color: #BD271E; }
-
-/* Handle up direction Bootstrap */
-.ui-select-container[theme='bootstrap'].direction-up .ui-select-dropdown {
- -webkit-box-shadow: 0 6px 12px -1px rgba(152, 162, 179, 0.2), 0 4px 4px -1px rgba(152, 162, 179, 0.2), 0 2px 2px 0 rgba(152, 162, 179, 0.2);
- box-shadow: 0 6px 12px -1px rgba(152, 162, 179, 0.2), 0 4px 4px -1px rgba(152, 162, 179, 0.2), 0 2px 2px 0 rgba(152, 162, 179, 0.2); }
-
-.ui-select-bootstrap .ui-select-match-text {
- width: 100%;
- padding-right: 1em; }
-
-.ui-select-bootstrap .ui-select-match-text span {
- display: inline-block;
- width: 100%;
- overflow: hidden; }
-
-.ui-select-bootstrap .ui-select-toggle > a.btn {
- position: absolute;
- height: 10px;
- right: 10px;
- margin-top: -2px; }
-
-/* Spinner */
-.ui-select-refreshing {
- position: absolute;
- right: 0;
- padding: 8px 27px;
- top: 1px;
- display: inline-block;
- font-family: 'Glyphicons Halflings';
- font-style: normal;
- font-weight: normal;
- line-height: 1;
- -webkit-font-smoothing: antialiased; }
-
-@-webkit-keyframes ui-select-spin {
- 0% {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg); }
- 100% {
- -webkit-transform: rotate(359deg);
- transform: rotate(359deg); } }
-
-@keyframes ui-select-spin {
- 0% {
- -webkit-transform: rotate(0deg);
- transform: rotate(0deg); }
- 100% {
- -webkit-transform: rotate(359deg);
- transform: rotate(359deg); } }
-
-.ui-select-spin {
- -webkit-animation: ui-select-spin 2s infinite linear;
- animation: ui-select-spin 2s infinite linear; }
-
-.ui-select-refreshing.ng-animate {
- -webkit-animation: none 0s; }
-
-/**
- * 1. Fix appearance of ui-select in the Filtering UI.
- */
-.btn-default .ui-select-placeholder {
- color: #98A2B3;
- /* 1 */ }
-
-.uiSelectMatch--ellipsis {
- max-width: 100%;
- overflow: hidden !important;
- text-overflow: ellipsis !important;
- white-space: nowrap !important;
- word-wrap: normal !important; }
-
-.ui-select-choices-group-label {
- color: #1a1c21;
- font-size: 12px;
- font-size: 0.75rem;
- line-height: 1.5rem;
- font-weight: 700;
- max-width: 100%;
- overflow: hidden !important;
- text-overflow: ellipsis !important;
- white-space: nowrap !important;
- word-wrap: normal !important;
- padding: 4px; }
-
-.kbnUiAceKeyboardHint {
- position: absolute;
- top: 0;
- bottom: 0;
- right: 0;
- left: 0;
- background: rgba(255, 255, 255, 0.7);
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
- -webkit-box-align: center;
- -webkit-align-items: center;
- -ms-flex-align: center;
- align-items: center;
- text-align: center;
- opacity: 0; }
- .kbnUiAceKeyboardHint:focus {
- opacity: 1;
- border: 2px solid #006BB4;
- z-index: 1000; }
- .kbnUiAceKeyboardHint.kbnUiAceKeyboardHint-isInactive {
- display: none; }
-
-.input-datetime-format {
- font-size: 12px;
- color: #98A2B3;
- padding: 4px 16px; }
-
-saved-object-finder .list-sort-button,
-paginated-selectable-list .list-sort-button {
- border-top-left-radius: 0 !important;
- border-top-right-radius: 0 !important;
- border: none;
- padding: 8px 16px;
- font-weight: 400;
- background-color: #F5F7FA; }
-
-saved-object-finder ul.li-striped li,
-paginated-selectable-list ul.li-striped li {
- border: none; }
-
-saved-object-finder ul.li-striped li:nth-child(even),
-paginated-selectable-list ul.li-striped li:nth-child(even) {
- background-color: #F5F7FA; }
-
-saved-object-finder ul.li-striped li:nth-child(odd),
-paginated-selectable-list ul.li-striped li:nth-child(odd) {
- background-color: #FFF; }
-
-saved-object-finder ul.li-striped .paginate-heading,
-paginated-selectable-list ul.li-striped .paginate-heading {
- font-weight: 400;
- color: #343741; }
-
-saved-object-finder ul.li-striped .list-group-item,
-paginated-selectable-list ul.li-striped .list-group-item {
- padding: 8px 16px; }
- saved-object-finder ul.li-striped .list-group-item ul,
- paginated-selectable-list ul.li-striped .list-group-item ul {
- padding: 0;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: horizontal;
- -webkit-box-direction: normal;
- -webkit-flex-direction: row;
- -ms-flex-direction: row;
- flex-direction: row; }
- saved-object-finder ul.li-striped .list-group-item ul .finder-type,
- paginated-selectable-list ul.li-striped .list-group-item ul .finder-type {
- margin-right: 8px; }
- saved-object-finder ul.li-striped .list-group-item a,
- paginated-selectable-list ul.li-striped .list-group-item a {
- display: block;
- color: #006BB4 !important; }
- saved-object-finder ul.li-striped .list-group-item a i,
- paginated-selectable-list ul.li-striped .list-group-item a i {
- color: #0060a2 !important;
- margin-right: 8px; }
- saved-object-finder ul.li-striped .list-group-item:first-child,
- paginated-selectable-list ul.li-striped .list-group-item:first-child {
- border-top-left-radius: 0 !important;
- border-top-right-radius: 0 !important; }
- saved-object-finder ul.li-striped .list-group-item.list-group-no-results p,
- paginated-selectable-list ul.li-striped .list-group-item.list-group-no-results p {
- margin-bottom: 0 !important; }
-
-saved-object-finder paginate paginate-controls,
-paginated-selectable-list paginate paginate-controls {
- margin: 16px; }
-
-.kbnError--url-overflow-app {
- padding: 24px; }
-
-/**
- * 1. override the z-index: 1 applied to all non-eui elements that are in :focus via kui
- * - see packages/kbn-ui-framework/src/global_styling/reset/_reset.scss
- */
-.dshExitFullScreenButton {
- -webkit-box-shadow: 0 12px 24px 0 rgba(65, 78, 101, 0.1), 0 6px 12px 0 rgba(65, 78, 101, 0.1), 0 4px 4px 0 rgba(65, 78, 101, 0.1), 0 2px 2px 0 rgba(65, 78, 101, 0.1);
- box-shadow: 0 12px 24px 0 rgba(65, 78, 101, 0.1), 0 6px 12px 0 rgba(65, 78, 101, 0.1), 0 4px 4px 0 rgba(65, 78, 101, 0.1), 0 2px 2px 0 rgba(65, 78, 101, 0.1);
- left: 8px;
- bottom: 8px;
- position: fixed;
- display: block;
- padding: 4px 8px;
- border: none;
- background: none;
- z-index: 5;
- background: #000;
- border-radius: 4px;
- text-align: left; }
- .dshExitFullScreenButton:hover {
- background: #000; }
- .dshExitFullScreenButton:hover .dshExitFullScreenButton__icon {
- color: #FFF; }
-
-.dshExitFullScreenButton__text {
- line-height: 1.2;
- color: #98A2B3; }
-
-.dshExitFullScreenButton__icon {
- color: #98A2B3; }
-
-.kbnFieldFormatEditor__samples audio {
- max-width: 100%; }
-
-.testScript__searchBar .globalQueryBar {
- padding: 16px 0 0; }
-
-style-compile {
- display: none; }
-
-.mgtSideBarNav {
- width: 192px; }
-
-@media only screen and (max-width: 574px) {
- .mgtSideBarNav {
- width: auto;
- margin-bottom: 16px; } }
-
-@media only screen and (min-width: 575px) and (max-width: 767px) {
- .mgtSideBarNav {
- width: auto;
- margin-bottom: 16px; } }
-
-/**
-* Style ES document _source in table view key: value
-* Use alpha so this will stand out against non-white backgrounds, e.g. the highlighted
-* row in the Context Log.
-*/
-discover-app {
- -webkit-box-flex: 1;
- -webkit-flex-grow: 1;
- -ms-flex-positive: 1;
- flex-grow: 1; }
-
-.dscHistogram {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- height: 200px;
- padding: 8px; }
-
-.dscWrapper {
- padding-right: 8px;
- padding-left: 32px;
- z-index: 1; }
-
-.dscWrapper__content {
- -webkit-box-shadow: 0 2px 2px -1px rgba(152, 162, 179, 0.3), 0 1px 5px -2px rgba(152, 162, 179, 0.3);
- box-shadow: 0 2px 2px -1px rgba(152, 162, 179, 0.3), 0 1px 5px -2px rgba(152, 162, 179, 0.3);
- background-color: #FFF;
- border: 1px solid #D3DAE6;
- border-radius: 4px;
- -webkit-box-flex: 1;
- -webkit-flex-grow: 1;
- -ms-flex-positive: 1;
- flex-grow: 1; }
- .dscWrapper__content.dscWrapper__content--flexGrowZero {
- -webkit-box-flex: 0;
- -webkit-flex-grow: 0;
- -ms-flex-positive: 0;
- flex-grow: 0; }
- .dscWrapper__content.dscWrapper__content--isClickable {
- display: block;
- width: 100%;
- text-align: left;
- -webkit-transition: all 150ms cubic-bezier(0.694, 0.0482, 0.335, 1);
- transition: all 150ms cubic-bezier(0.694, 0.0482, 0.335, 1); }
- .dscWrapper__content.dscWrapper__content--isClickable:hover, .dscWrapper__content.dscWrapper__content--isClickable:focus {
- -webkit-box-shadow: 0 4px 8px 0 rgba(152, 162, 179, 0.15), 0 2px 2px -1px rgba(152, 162, 179, 0.3);
- box-shadow: 0 4px 8px 0 rgba(152, 162, 179, 0.15), 0 2px 2px -1px rgba(152, 162, 179, 0.3);
- -webkit-transform: translateY(-2px);
- transform: translateY(-2px);
- cursor: pointer; }
- .dscWrapper__content.dscWrapper__content--shadow {
- -webkit-box-shadow: 0 6px 12px -1px rgba(152, 162, 179, 0.2), 0 4px 4px -1px rgba(152, 162, 179, 0.2), 0 2px 2px 0 rgba(152, 162, 179, 0.2);
- box-shadow: 0 6px 12px -1px rgba(152, 162, 179, 0.2), 0 4px 4px -1px rgba(152, 162, 179, 0.2), 0 2px 2px 0 rgba(152, 162, 179, 0.2);
- border-bottom-color: rgba(152, 162, 179, 0.5); }
- .dscWrapper__content.dscWrapper__content--shadow.dscWrapper__content--isClickable:hover, .dscWrapper__content.dscWrapper__content--shadow.dscWrapper__content--isClickable:focus {
- -webkit-box-shadow: 0 12px 24px 0 rgba(152, 162, 179, 0.2), 0 6px 12px 0 rgba(152, 162, 179, 0.2), 0 4px 4px 0 rgba(152, 162, 179, 0.2), 0 2px 2px 0 rgba(152, 162, 179, 0.2);
- box-shadow: 0 12px 24px 0 rgba(152, 162, 179, 0.2), 0 6px 12px 0 rgba(152, 162, 179, 0.2), 0 4px 4px 0 rgba(152, 162, 179, 0.2), 0 2px 2px 0 rgba(152, 162, 179, 0.2); }
-
-.dscWrapper__content {
- padding-top: 4px;
- background-color: #FFF; }
- .dscWrapper__content .kbn-table {
- margin-bottom: 0; }
-
-.dscTimechart {
- display: block;
- position: relative; }
- .dscTimechart .series > rect {
- fill-opacity: 0.5;
- stroke-width: 1; }
-
-.dscResultCount {
- text-align: center;
- padding-top: 4px;
- padding-left: 12px; }
- .dscResultCount .dscResultHits {
- padding-left: 4px; }
- .dscResultCount > .kuiLink {
- padding-left: 12px; }
-
-.dscTimechart__header {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
- min-height: 40px;
- padding: 4px 0; }
-
-.dscOverlay {
- position: absolute;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 20;
- padding-top: 12px;
- opacity: 0.75;
- text-align: center;
- background-color: transparent; }
-
-.dscTable {
- overflow: auto; }
- .dscTable .kbnDocTable__row {
- font-family: "Roboto Mono", Consolas, Menlo, Courier, monospace;
- font-size: 12px; }
-
-.dscTable__footer {
- background-color: #D3DAE6;
- padding: 5px 10px;
- text-align: center; }
-
-.dscResults h3 {
- margin: -20px 0 10px 0;
- text-align: center; }
-
-.dscResults__interval {
- display: inline-block;
- width: auto; }
-
-.dscSkipButton {
- position: absolute;
- left: -10000px;
- top: 4px;
- width: 1px;
- height: 1px;
- overflow: hidden; }
- .dscSkipButton:focus {
- left: initial;
- right: 16px;
- width: auto;
- height: auto; }
-
-.tab-discover {
- overflow: hidden; }
-
-.discoverFetchError {
- max-width: 1000px; }
-
-.dscSidebar__container {
- padding-left: 0 !important;
- padding-right: 0 !important;
- background-color: transparent;
- border-right-color: transparent;
- border-bottom-color: transparent; }
-
-.dscIndexPattern__container {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-align: center;
- -webkit-align-items: center;
- -ms-flex-align: center;
- align-items: center;
- height: 48px;
- margin-top: -8px; }
-
-.dscIndexPattern__triggerButton {
- color: #1a1c21;
- font-size: 16px;
- font-size: 1rem;
- line-height: 1.5rem;
- font-weight: 600;
- letter-spacing: -0.02em;
- line-height: 40px; }
-
-.dscFieldList {
- list-style: none;
- margin-bottom: 0; }
-
-.dscFieldList--selected,
-.dscFieldList--unpopular,
-.dscFieldList--popular {
- padding-left: 8px;
- padding-right: 8px; }
-
-.dscFieldListHeader {
- padding: 8px 8px 0 8px;
- background-color: #e6f0f8; }
-
-.dscFieldList--popular {
- background-color: #e6f0f8; }
-
-.dscFieldChooser {
- padding-left: 8px !important;
- padding-right: 8px !important; }
-
-.dscFieldChooser__toggle {
- color: #98A2B3;
- margin-left: 8px !important; }
-
-.dscSidebarItem {
- border-top: 1px solid transparent;
- position: relative;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-align: center;
- -webkit-align-items: center;
- -ms-flex-align: center;
- align-items: center;
- -webkit-box-pack: justify;
- -webkit-justify-content: space-between;
- -ms-flex-pack: justify;
- justify-content: space-between;
- padding: 0 2px;
- cursor: pointer;
- font-size: 12px;
- border-top: solid 1px transparent;
- border-bottom: solid 1px transparent;
- line-height: normal; }
- .dscSidebarItem:hover .dscSidebarItem__action, .dscSidebarItem:focus .dscSidebarItem__action {
- opacity: 1; }
-
-.dscSidebarItem--active {
- border-top: 1px solid #D3DAE6;
- background: #e9ebee;
- color: #000; }
- .dscSidebarItem--active .euiText {
- font-weight: bold; }
-
-.dscSidebarField {
- padding: 4px 0;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-align: start;
- -webkit-align-items: flex-start;
- -ms-flex-align: start;
- align-items: flex-start;
- max-width: 100%;
- margin: 0;
- width: 100%;
- border: none;
- border-radius: 0;
- text-align: left; }
-
-.dscSidebarField__name {
- margin-left: 8px;
- -webkit-box-flex: 1;
- -webkit-flex-grow: 1;
- -ms-flex-positive: 1;
- flex-grow: 1; }
-
-.dscSidebarField__fieldIcon {
- margin-top: 2px;
- margin-right: 2px; }
-
-/**
- * 1. Only visually hide the action, so that it's still accessible to screen readers.
- * 2. When tabbed to, this element needs to be visible for keyboard accessibility.
- */
-.dscSidebarItem__action {
- opacity: 0;
- /* 1 */
- -webkit-transition: none;
- transition: none;
- font-size: 12px;
- padding: 2px 6px !important;
- height: 22px !important;
- min-width: auto !important; }
- .dscSidebarItem__action:focus {
- opacity: 1;
- /* 2 */ }
- .dscSidebarItem__action .euiButton__content {
- padding: 0 4px; }
-
-/*
- Fixes EUI known issue https://github.com/elastic/eui/issues/1749
-*/
-.dscProgressBarTooltip__anchor {
- display: block; }
-
-.dscFieldSearch {
- padding: 8px; }
-
-.dscFieldSearch__toggleButton {
- width: calc(100% - 8px);
- color: #006BB4;
- padding-left: 4px;
- margin-left: 4px; }
-
-.dscFieldSearch__filterWrapper {
- -webkit-box-flex: 0;
- -webkit-flex-grow: 0;
- -ms-flex-positive: 0;
- flex-grow: 0; }
-
-.dscFieldSearch__formWrapper {
- padding: 12px; }
-
-.dscFieldDetails {
- padding: 8px;
- background-color: #F5F7FA;
- color: #343741;
- margin-bottom: 8px; }
-
-.dscNoResults {
- max-width: 1000px; }
-
-.dscHistogram__header--partial {
- font-weight: 400;
- min-width: 192px; }
-
-/**
- * 1. The local nav contains tooltips which should pop over the filter bar.
- * 2. The filter and local nav components should always appear above the dashboard grid items.
- * 3. The filter and local nav components should always appear above the discover content.
- * 4. The sidebar collapser button should appear above the main Discover content but below the top elements.
- * 5. Dragged panels in dashboard should always appear above other panels.
- */
-/* 1 */
-/* 1 */
-/* 2 */
-/* 5 */
-/* 3 */
-/* 4 */
-.collapsible-sidebar {
- position: relative;
- z-index: 2; }
- .collapsible-sidebar .kbnCollapsibleSidebar__collapseButton {
- position: absolute;
- top: 0;
- right: -21px;
- cursor: pointer;
- z-index: -1; }
- .collapsible-sidebar.closed {
- width: 0 !important;
- border-right-width: 0;
- border-left-width: 0; }
- .collapsible-sidebar.closed > * {
- visibility: hidden; }
- .collapsible-sidebar.closed .kbnCollapsibleSidebar__collapseButton {
- visibility: visible; }
- .collapsible-sidebar.closed .kbnCollapsibleSidebar__collapseButton .chevron-cont:before {
- content: "\F138"; }
-
-@media only screen and (max-width: 574px) {
- .collapsible-sidebar.closed {
- display: none; }
- .collapsible-sidebar .kbnCollapsibleSidebar__collapseButton {
- display: none; } }
-
-@media only screen and (min-width: 575px) and (max-width: 767px) {
- .collapsible-sidebar.closed {
- display: none; }
- .collapsible-sidebar .kbnCollapsibleSidebar__collapseButton {
- display: none; } }
-
-@media only screen and (min-width: 768px) and (max-width: 991px) {
- .collapsible-sidebar.closed {
- display: none; }
- .collapsible-sidebar .kbnCollapsibleSidebar__collapseButton {
- display: none; } }
-
-/**
- * 1. Stack content vertically so the table can scroll when its constrained by a fixed container height.
- */
-doc-table {
- overflow: auto;
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 100%;
- -ms-flex: 1 1 100%;
- flex: 1 1 100%;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- /* 1 */ }
- doc-table th {
- text-align: left;
- font-weight: bold; }
- doc-table .spinner {
- position: absolute;
- top: 40%;
- left: 0;
- right: 0;
- z-index: 1000;
- opacity: 0.5; }
-
-.kbnDocTable__container.loading {
- opacity: 0.5; }
-
-.kbnDocTable {
- font-size: 12px; }
- .kbnDocTable dl.source {
- margin-bottom: 0;
- line-height: 2em;
- word-break: break-word; }
- .kbnDocTable dl.source dt, .kbnDocTable dl.source dd {
- display: inline; }
- .kbnDocTable dl.source dt {
- background-color: rgba(0, 86, 144, 0.1);
- color: #343741;
- padding: 2px 4px;
- margin-right: 4px;
- word-break: normal;
- border-radius: 4px; }
- .kbnDocTable th {
- white-space: nowrap;
- padding-right: 8px; }
- .kbnDocTable th .fa {
- font-size: 1.1em; }
-
-.kbnDocTable__row td {
- position: relative; }
- .kbnDocTable__row td:hover .kbnDocTableRowFilterButton {
- opacity: 1; }
-
-.kbnDocTable__row--highlight td,
-.kbnDocTable__row--highlight .kbnDocTableRowFilterButton {
- background-color: #e6f0f8; }
-
-.kbnDocTable__bar {
- margin: 4px 4px 0; }
-
-.kbnDocTable__bar--footer {
- position: relative;
- margin: -48px 4px 0; }
-
-.kbnDocTable__padBottom {
- padding-bottom: 32px; }
-
-.kbnDocTable__error {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- -webkit-box-pack: center;
- -webkit-justify-content: center;
- -ms-flex-pack: center;
- justify-content: center;
- -webkit-box-flex: 1;
- -webkit-flex: 1 0 100%;
- -ms-flex: 1 0 100%;
- flex: 1 0 100%;
- text-align: center; }
-
-.kbnDocTableHeader button {
- margin-left: 4px; }
-
-.kbnDocTableHeader__move,
-.kbnDocTableHeader__sortChange {
- opacity: 0; }
- th:hover .kbnDocTableHeader__move, .kbnDocTableHeader__move:focus, th:hover
- .kbnDocTableHeader__sortChange,
- .kbnDocTableHeader__sortChange:focus {
- opacity: 1; }
-
-.kbnDocTableCell__dataField {
- white-space: pre-wrap; }
-
-.kbnDocTableCell__toggleDetails {
- padding: 4px 0 0 0 !important; }
-
-.kbnDocTableCell__filter {
- position: absolute;
- white-space: nowrap;
- right: 0; }
-
-/**
- * 1. Align icon with text in cell.
- * 2. Use opacity to make this element accessible to screen readers and keyboard.
- * 3. Show on focus to enable keyboard accessibility.
- */
-.kbnDocTableRowFilterButton {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- background-color: #FFF;
- border: none;
- padding: 0 4px;
- font-size: 14px;
- line-height: 1;
- /* 1 */
- display: inline-block;
- opacity: 0;
- /* 2 */ }
- .kbnDocTableRowFilterButton:focus {
- opacity: 1;
- /* 3 */ }
-
-/**
- * 1. Visually align the actions with the tabs. We can improve this by using flexbox instead, at a later point.
- */
-.kbnDocTableDetails__actions {
- float: right;
- padding-top: 8px;
- /* 1 */ }
-
-.kbnDocTableDetails__row > td {
- padding: 24px !important; }
- .kbnDocTableDetails__row > td tr:hover td {
- background: #fafbfd; }
-
-.kbnDocTableDetails__row td {
- border-top: none !important; }
-
-/**
- * 1. When switching between open and closed, the toggle changes size
- * slightly which is a problem because it forces the entire table to
- * re-render which is SLOW.
- */
-.kbnDocTableOpen__button {
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
- background-color: transparent;
- padding: 0;
- border: none;
- width: 14px;
- /* 1 */
- height: 14px; }
-
-.cxtSizePicker {
- text-align: center;
- width: 80px; }
- .cxtSizePicker::-webkit-outer-spin-button, .cxtSizePicker::-webkit-inner-spin-button {
- -webkit-appearance: none;
- appearance: none;
- margin: 0; }
-
-/**
- * 1. We want the kbnDocTable__container to scroll only when embedded in an embeddable panel
- * 2. Force a better looking scrollbar
- */
-.embPanel .kbnDocTable__container {
- scrollbar-width: thin;
- /* 2 */
- -webkit-box-flex: 1;
- -webkit-flex: 1 1 0;
- -ms-flex: 1 1 0px;
- flex: 1 1 0;
- /* 1 */
- overflow: auto;
- /* 1 */ }
- .embPanel .kbnDocTable__container::-webkit-scrollbar {
- width: 16px;
- height: 16px; }
- .embPanel .kbnDocTable__container::-webkit-scrollbar-thumb {
- background-color: rgba(105, 112, 125, 0.5);
- border: 6px solid transparent;
- background-clip: content-box; }
- .embPanel .kbnDocTable__container::-webkit-scrollbar-corner, .embPanel .kbnDocTable__container::-webkit-scrollbar-track {
- background-color: transparent; }
-
-.leaflet-touch .leaflet-bar,
-.leaflet-draw-actions {
- -webkit-box-shadow: 0 6px 12px -1px rgba(65, 78, 101, 0.2), 0 4px 4px -1px rgba(65, 78, 101, 0.2), 0 2px 2px 0 rgba(65, 78, 101, 0.2);
- box-shadow: 0 6px 12px -1px rgba(65, 78, 101, 0.2), 0 4px 4px -1px rgba(65, 78, 101, 0.2), 0 2px 2px 0 rgba(65, 78, 101, 0.2);
- border: none; }
-
-.leaflet-container {
- background: #FFF;
- min-width: 1px !important;
- min-height: 1px !important; }
-
-.leaflet-clickable:hover {
- stroke-width: 8px;
- stroke-opacity: 0.8; }
-
-/**
- * 1. Since Leaflet is an external library, we also have to provide EUI variables
- * to non-override colors for darkmode.
- */
-.leaflet-draw-actions a,
-.leaflet-control a {
- background-color: #FFF;
- /* 1 */
- border-color: #D3DAE6 !important;
- /* 1 */
- color: #343741 !important;
- /* 1 */ }
- .leaflet-draw-actions a:hover,
- .leaflet-control a:hover {
- background-color: #F5F7FA; }
-
-.leaflet-touch .leaflet-bar a:first-child {
- border-top-left-radius: 4px;
- border-top-right-radius: 4px; }
-
-.leaflet-touch .leaflet-bar a:last-child {
- border-bottom-left-radius: 4px;
- border-bottom-right-radius: 4px; }
-
-.leaflet-retina .leaflet-draw-toolbar a {
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 60' height='60' width='600'%3E%3Cg fill='rgb%2852, 55, 65%29'%3E%3Cg%3E%3Cpath d='M18 36v6h6v-6h-6zm4 4h-2v-2h2v2z'/%3E%3Cpath d='M36 18v6h6v-6h-6zm4 4h-2v-2h2v2z'/%3E%3Cpath d='M23.142 39.145l-2.285-2.29 16-15.998 2.285 2.285z'/%3E%3C/g%3E%3Cpath d='M100 24.565l-2.096 14.83L83.07 42 76 28.773 86.463 18z'/%3E%3Cpath d='M140 20h20v20h-20z'/%3E%3Cpath d='M221 30c0 6.078-4.926 11-11 11s-11-4.922-11-11c0-6.074 4.926-11 11-11s11 4.926 11 11z'/%3E%3Cpath d='M270,19c-4.971,0-9,4.029-9,9c0,4.971,5.001,12,9,14c4.001-2,9-9.029,9-14C279,23.029,274.971,19,270,19z M270,31.5c-2.484,0-4.5-2.014-4.5-4.5c0-2.484,2.016-4.5,4.5-4.5c2.485,0,4.5,2.016,4.5,4.5C274.5,29.486,272.485,31.5,270,31.5z'/%3E%3Cg%3E%3Cpath d='M337,30.156v0.407v5.604c0,1.658-1.344,3-3,3h-10c-1.655,0-3-1.342-3-3v-10c0-1.657,1.345-3,3-3h6.345 l3.19-3.17H324c-3.313,0-6,2.687-6,6v10c0,3.313,2.687,6,6,6h10c3.314,0,6-2.687,6-6v-8.809L337,30.156'/%3E%3Cpath d='M338.72 24.637l-8.892 8.892H327V30.7l8.89-8.89z'/%3E%3Cpath d='M338.697 17.826h4v4h-4z' transform='rotate(-134.99 340.703 19.817)'/%3E%3C/g%3E%3Cg%3E%3Cpath d='M381 42h18V24h-18v18zm14-16h2v14h-2V26zm-4 0h2v14h-2V26zm-4 0h2v14h-2V26zm-4 0h2v14h-2V26z'/%3E%3Cpath d='M395 20v-4h-10v4h-6v2h22v-2h-6zm-2 0h-6v-2h6v2z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E%0A");
- /* 1 */ }
-
-.leaflet-control-layers-expanded {
- padding: 0;
- margin: 0;
- font-size: 11px;
- font-size: 0.6875rem;
- font-family: "Inter UI", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- font-weight: 500;
- line-height: 1.5; }
- .leaflet-control-layers-expanded label {
- font-weight: 500;
- margin: 0;
- padding: 0; }
-
-/* over-rides leaflet popup styles to look like kibana tooltip */
-.leaflet-popup-content-wrapper {
- margin: 0;
- padding: 0;
- background: #404040;
- color: #FFF;
- border-radius: 4px !important; }
-
-.leaflet-popup {
- pointer-events: none; }
-
-.leaflet-popup-content {
- margin: 0;
- font-size: 14px;
- font-size: 0.875rem;
- line-height: 1.5;
- font-weight: 400;
- word-wrap: break-word;
- overflow: hidden;
- pointer-events: none; }
- .leaflet-popup-content > * {
- margin: 8px 8px 0; }
- .leaflet-popup-content > :last-child {
- margin-bottom: 8px; }
- .leaflet-popup-content table td, .leaflet-popup-content table th {
- padding: 4px; }
-
-.leaflet-popup-tip-container,
-.leaflet-popup-close-button,
-.leaflet-draw-tooltip {
- display: none !important; }
-
-.leaflet-container .leaflet-control-attribution {
- background-color: rgba(255, 255, 255, 0.3);
- color: #69707D; }
- .leaflet-container .leaflet-control-attribution p {
- display: inline; }
-
-.leaflet-touch .leaflet-control-zoom-in,
-.leaflet-touch .leaflet-control-zoom-out {
- text-indent: -10000px;
- background-repeat: no-repeat;
- background-position: center; }
-
-.leaflet-touch .leaflet-control-zoom-in {
- background-image: url("data:image/svg+xml,%0A%3Csvg width='15px' height='15px' viewBox='0 0 15 15' version='1.1' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='rgb%2852, 55, 65%29' d='M8,7 L8,3.5 C8,3.22385763 7.77614237,3 7.5,3 C7.22385763,3 7,3.22385763 7,3.5 L7,7 L3.5,7 C3.22385763,7 3,7.22385763 3,7.5 C3,7.77614237 3.22385763,8 3.5,8 L7,8 L7,11.5 C7,11.7761424 7.22385763,12 7.5,12 C7.77614237,12 8,11.7761424 8,11.5 L8,8 L11.5,8 C11.7761424,8 12,7.77614237 12,7.5 C12,7.22385763 11.7761424,7 11.5,7 L8,7 Z M7.5,15 C3.35786438,15 0,11.6421356 0,7.5 C0,3.35786438 3.35786438,0 7.5,0 C11.6421356,0 15,3.35786438 15,7.5 C15,11.6421356 11.6421356,15 7.5,15 Z' /%3E%3C/svg%3E"); }
-
-.leaflet-touch .leaflet-control-zoom-out {
- background-image: url("data:image/svg+xml,%0A%3Csvg width='15px' height='15px' viewBox='0 0 15 15' version='1.1' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='rgb%2852, 55, 65%29' d='M7.5,0 C11.6355882,0 15,3.36441176 15,7.5 C15,11.6355882 11.6355882,15 7.5,15 C3.36441176,15 0,11.6355882 0,7.5 C0,3.36441176 3.36441176,0 7.5,0 Z M3.5,7 C3.22385763,7 3,7.22385763 3,7.5 C3,7.77614237 3.22385763,8 3.5,8 L11.5,8 C11.7761424,8 12,7.77614237 12,7.5 C12,7.22385763 11.7761424,7 11.5,7 L3.5,7 Z' /%3E%3C/svg%3E"); }
-
-img.leaflet-tile {
- -webkit-filter: brightness(1.03) grayscale(0.73);
- filter: brightness(1.03) grayscale(0.73); }
-
-img.leaflet-tile.filters-off {
- -webkit-filter: none;
- filter: none; }
-
-.visMapLegend {
- font-size: 11px;
- font-size: 0.6875rem;
- -webkit-box-shadow: 0 6px 12px -1px rgba(65, 78, 101, 0.1), 0 4px 4px -1px rgba(65, 78, 101, 0.1), 0 2px 2px 0 rgba(65, 78, 101, 0.1);
- box-shadow: 0 6px 12px -1px rgba(65, 78, 101, 0.1), 0 4px 4px -1px rgba(65, 78, 101, 0.1), 0 2px 2px 0 rgba(65, 78, 101, 0.1);
- font-family: "Inter UI", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
- font-weight: 500;
- line-height: 1.5;
- color: #69707D;
- padding: 8px;
- background: rgba(255, 255, 255, 0.8);
- border-radius: 4px; }
- .visMapLegend i {
- width: 10px;
- height: 10px;
- display: inline-block;
- margin: 3px 4px 0 0;
- border-radius: 50%;
- border: 1px solid #69707D;
- background: #69707D; }
-
-.visMapLegend__title {
- font-weight: 700; }
-
-.leaflet-top.leaflet-left .visMapLegend__wrapper {
- position: absolute;
- left: 40px;
- white-space: nowrap; }
-
-.homAddData__card {
- border: none;
- -webkit-box-shadow: none;
- box-shadow: none; }
-
-.homAddData__cardDivider {
- position: relative; }
- .homAddData__cardDivider:after {
- position: absolute;
- content: '';
- width: 1px;
- right: -8px;
- top: 0;
- bottom: 0;
- background: #D3DAE6; }
-
-.homAddData__icon {
- width: 64px;
- height: 64px; }
-
-.homAddData__footerItem--highlight {
- background-color: #e6f0f8;
- padding: 16px; }
-
-.homAddData__footerItem {
- text-align: center; }
-
-.homAddData__logo {
- margin-left: 16px; }
-
-@media only screen and (max-width: 574px) {
- .homeAddData__flexGroup {
- -webkit-flex-wrap: wrap;
- -ms-flex-wrap: wrap;
- flex-wrap: wrap; } }
-
-@media only screen and (min-width: 575px) and (max-width: 767px) {
- .homeAddData__flexGroup {
- -webkit-flex-wrap: wrap;
- -ms-flex-wrap: wrap;
- flex-wrap: wrap; } }
-
-@media only screen and (max-width: 574px) {
- .homAddDat__flexTablet {
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column; }
- .homAddData__cardDivider:after {
- display: none; }
- .homAddData__cardDivider {
- -webkit-box-flex: 0 !important;
- -webkit-flex-grow: 0 !important;
- -ms-flex-positive: 0 !important;
- flex-grow: 0 !important;
- -webkit-flex-basis: 100% !important;
- -ms-flex-preferred-size: 100% !important;
- flex-basis: 100% !important; } }
-
-@media only screen and (min-width: 575px) and (max-width: 767px) {
- .homAddDat__flexTablet {
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column; }
- .homAddData__cardDivider:after {
- display: none; }
- .homAddData__cardDivider {
- -webkit-box-flex: 0 !important;
- -webkit-flex-grow: 0 !important;
- -ms-flex-positive: 0 !important;
- flex-grow: 0 !important;
- -webkit-flex-basis: 100% !important;
- -ms-flex-preferred-size: 100% !important;
- flex-basis: 100% !important; } }
-
-@media only screen and (min-width: 768px) and (max-width: 991px) {
- .homAddDat__flexTablet {
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column; }
- .homAddData__cardDivider:after {
- display: none; }
- .homAddData__cardDivider {
- -webkit-box-flex: 0 !important;
- -webkit-flex-grow: 0 !important;
- -ms-flex-positive: 0 !important;
- flex-grow: 0 !important;
- -webkit-flex-basis: 100% !important;
- -ms-flex-preferred-size: 100% !important;
- flex-basis: 100% !important; } }
-
-@media only screen and (min-width: 992px) and (max-width: 1199px) {
- .homeAddData__flexGroup {
- -webkit-flex-wrap: nowrap;
- -ms-flex-wrap: nowrap;
- flex-wrap: nowrap; } }
-
-@media only screen and (min-width: 1200px) {
- .homeAddData__flexGroup {
- -webkit-flex-wrap: nowrap;
- -ms-flex-wrap: nowrap;
- flex-wrap: nowrap; } }
-
-@media only screen and (max-width: 574px) {
- .homHome__synopsisItem {
- -webkit-flex-basis: 100% !important;
- -ms-flex-preferred-size: 100% !important;
- flex-basis: 100% !important; } }
-
-@media only screen and (min-width: 575px) and (max-width: 767px) {
- .homHome__synopsisItem {
- -webkit-flex-basis: 100% !important;
- -ms-flex-preferred-size: 100% !important;
- flex-basis: 100% !important; } }
-
-@media only screen and (min-width: 768px) and (max-width: 991px) {
- .homHome__synopsisItem {
- -webkit-flex-basis: 100% !important;
- -ms-flex-preferred-size: 100% !important;
- flex-basis: 100% !important; } }
-
-.homSampleDataSetCards {
- min-height: 1px; }
-
-.homSynopsis__card.homSynopsis__card--noPanel {
- border: none;
- -webkit-box-shadow: none;
- box-shadow: none; }
-
-.homSynopsis__card .euiCard__content {
- padding-top: 0 !important; }
-
-.homWelcome {
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- z-index: 7000;
- background: inherit;
- background-color: #fafbfd;
- opacity: 0;
- overflow: auto;
- -webkit-animation: kibanaFullScreenGraphics_FadeIn 500ms cubic-bezier(0.694, 0.0482, 0.335, 1) 0s forwards;
- animation: kibanaFullScreenGraphics_FadeIn 500ms cubic-bezier(0.694, 0.0482, 0.335, 1) 0s forwards; }
- .homWelcome::before {
- position: absolute;
- top: 0;
- left: 0;
- z-index: 1;
- width: 310px;
- height: 477px;
- content: url("/ui/images/bg_top_branded.svg"); }
- .homWelcome::after {
- position: fixed;
- bottom: 0;
- right: 0;
- z-index: 1;
- width: 313px;
- height: 461px;
- content: url("/ui/images/bg_bottom_branded.svg"); }
-
-@-webkit-keyframes kibanaFullScreenGraphics_FadeIn {
- from {
- opacity: 0;
- -webkit-transform: translateY(200px), scale(0.75);
- transform: translateY(200px), scale(0.75); }
- to {
- opacity: 1;
- -webkit-transform: translateY(0), scale(1);
- transform: translateY(0), scale(1); } }
-
-@keyframes kibanaFullScreenGraphics_FadeIn {
- from {
- opacity: 0;
- -webkit-transform: translateY(200px), scale(0.75);
- transform: translateY(200px), scale(0.75); }
- to {
- opacity: 1;
- -webkit-transform: translateY(0), scale(1);
- transform: translateY(0), scale(1); } }
-
-.homWelcome__header {
- position: relative;
- padding: 32px;
- z-index: 10; }
-
-.homWelcome__logo {
- margin-bottom: 32px;
- display: inline-block;
- width: 80px;
- height: 80px;
- line-height: 80px;
- text-align: center;
- background-color: #FFF;
- border-radius: 100%;
- padding: 16px;
- -webkit-box-shadow: 0 6px 12px -1px rgba(152, 162, 179, 0.2), 0 4px 4px -1px rgba(152, 162, 179, 0.2), 0 2px 2px 0 rgba(152, 162, 179, 0.2);
- box-shadow: 0 6px 12px -1px rgba(152, 162, 179, 0.2), 0 4px 4px -1px rgba(152, 162, 179, 0.2), 0 2px 2px 0 rgba(152, 162, 179, 0.2); }
- .homWelcome__logo .euiIcon {
- vertical-align: baseline; }
-
-.homWelcome__footerAction {
- margin-right: 8px; }
-
-.homWelcome__content {
- position: relative;
- margin: auto;
- max-width: 512px;
- padding-left: 32px;
- padding-right: 32px;
- z-index: 10; }
-
-.homTutorial__notFoundPanel {
- background: #FFF;
- padding: 24px; }
-
-.homTutorial__instruction {
- -webkit-flex-shrink: 0;
- -ms-flex-negative: 0;
- flex-shrink: 0; }
-
-kbn-management-app,
-kbn-management-landing,
-kbn-management-indices,
-kbn-management-indices-edit,
-kbn-management-indices-create,
-kbn-management-advanced,
-kbn-management-objects,
-kbn-management-objects-view {
- display: block; }
-
-#management-landing {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex; }
-
-.kbn-management-tab:first-letter {
- text-transform: capitalize; }
-
-kbn-management-objects-view .ace_editor {
- height: 300px; }
-
-.mgtPage__body {
- max-width: 1200px; }
-
-.mgtPanel {
- margin-bottom: 16px;
- background: #FFF; }
-
-/**
- * 1. Override kuiPanelBody styles to accommodate padding of items within the panel body..
- */
-.mgtPanel__body {
- padding: 5px 10px;
- /* 1 */ }
-
-/**
- * 1. Create vertical space between items when they wrap.
- */
-.mgtPanel__item {
- padding: 5px 15px;
- /* 1 */ }
-
-.mgtPanel__link {
- font-size: 20px;
- font-size: 1.25rem;
- line-height: 1.5;
- line-height: 1.5; }
- .mgtPanel__link.mgtPanel__link--disabled {
- opacity: #69707D;
- cursor: default; }
- .mgtPanel__link.mgtPanel__link--disabled:hover, .mgtPanel__link.mgtPanel__link--disabled:visited {
- color: #006BB4; }
-
-kbn-management-objects form {
- margin-bottom: 16px; }
-
-kbn-management-objects .list-unstyled li {
- border-bottom: 1px solid #D3DAE6;
- padding: 8px; }
-
-kbn-management-objects .empty {
- color: #69707D; }
-
-kbn-management-objects .item {
- padding: 12px; }
- kbn-management-objects .item .item-title {
- margin-left: 24px; }
- kbn-management-objects .item .actions {
- margin-top: 4px; }
-
-kbn-management-objects .header .title, kbn-management-objects .header .controls {
- padding-right: 1em;
- display: inline-block; }
-
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-/*
- * Licensed to Elasticsearch B.V. under one or more contributor
- * license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright
- * ownership. Elasticsearch B.V. licenses this file to you under
- * the Apache License, Version 2.0 (the "License"); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-.mgtAdvancedSettings__field + * {
- margin-top: 16px; }
-
-.mgtAdvancedSettings__field .mgtAdvancedSettings__fieldTitle {
- padding-left: 8px;
- margin-left: -8px; }
-
-.mgtAdvancedSettings__field--unsaved .mgtAdvancedSettings__fieldTitle {
- -webkit-box-shadow: -4px 0px #F5A700;
- box-shadow: -4px 0px #F5A700; }
-
-.mgtAdvancedSettings__field--invalid .mgtAdvancedSettings__fieldTitle {
- -webkit-box-shadow: -4px 0px #BD271E;
- box-shadow: -4px 0px #BD271E; }
-
-@media screen and (-ms-high-contrast: active), screen and (-ms-high-contrast: none) {
- .mgtAdvancedSettings__field {
- min-height: 1px; }
- .mgtAdvancedSettings__fieldRow {
- min-height: 1px; } }
-
-.mgtAdvancedSettings__fieldTitleUnsavedIcon {
- margin-left: 8px; }
-
-@media only screen and (max-width: 574px) {
- .mgtAdvancedSettingsForm__unsavedCount {
- display: none; } }
-
-.mgtAdvancedSettingsForm__unsavedCountMessage {
- -webkit-box-shadow: -4px 0px #F5A700;
- box-shadow: -4px 0px #F5A700;
- padding-left: 8px; }
-
-.mgtAdvancedSettingsForm__button {
- width: 100%; }
-
-.mgtAdvancedSettingsForm__bottomBar {
- margin-left: 48px;
- z-index: 9; }
- .mgtAdvancedSettingsForm__bottomBar--pushForNav {
- margin-left: 240px; }
- @media only screen and (max-width: 574px) {
- .mgtAdvancedSettingsForm__bottomBar {
- margin-left: 0; } }
- @media only screen and (min-width: 575px) and (max-width: 767px) {
- .mgtAdvancedSettingsForm__bottomBar {
- margin-left: 0; } }
-
-#indexPatternListReact {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex; }
- #indexPatternListReact .indexPatternList__headerWrapper {
- padding-bottom: 8px; }
- #indexPatternListReact .euiButtonEmpty__content {
- -webkit-box-pack: left;
- -webkit-justify-content: left;
- -ms-flex-pack: left;
- justify-content: left;
- padding: 0; }
- #indexPatternListReact .euiButtonEmpty__content span {
- text-overflow: ellipsis;
- overflow: hidden; }
- #indexPatternListReact .indexPatternListPrompt__descList {
- text-align: left; }
-
-.indexPatternList__badge {
- margin-left: 8px; }
-
-.kbnLocalApplicationWrapper {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- -webkit-box-orient: vertical;
- -webkit-box-direction: normal;
- -webkit-flex-direction: column;
- -ms-flex-direction: column;
- flex-direction: column;
- -webkit-box-flex: 1;
- -webkit-flex-grow: 1;
- -ms-flex-positive: 1;
- flex-grow: 1; }
-
- .kbnDocViewerTable {
- margin-top: 8px; }
-
- .kbnDocViewer pre,
- .kbnDocViewer .kbnDocViewer__value {
- display: inline-block;
- word-break: break-all;
- word-wrap: break-word;
- white-space: pre-wrap;
- color: #000;
- vertical-align: top;
- padding-top: 2px; }
-
- .kbnDocViewer .kbnDocViewer__field {
- padding-top: 8px; }
-
- .kbnDocViewer .dscFieldName {
- color: #69707D; }
-
- .kbnDocViewer td,
- .kbnDocViewer pre {
- font-family: "Roboto Mono", Consolas, Menlo, Courier, monospace; }
-
- .kbnDocViewer tr:first-child td {
- border-top-color: transparent; }
-
- .kbnDocViewer tr:hover .kbnDocViewer__actionButton {
- opacity: 1; }
-
- .kbnDocViewer__buttons,
- .kbnDocViewer__field {
- white-space: nowrap; }
-
- .kbnDocViewer__buttons {
- width: 60px; }
- .kbnDocViewer__buttons:focus-within .kbnDocViewer__actionButton {
- opacity: 1; }
-
- .kbnDocViewer__field {
- width: 160px; }
-
- .kbnDocViewer__actionButton {
- opacity: 0; }
- .kbnDocViewer__actionButton:focus {
- opacity: 1; }
-
- .kbnDocViewer__warning {
- margin-right: 8px; }
\ No newline at end of file
diff --git a/public/styles/common.scss b/public/styles/common.scss
index 12c46a1b1e..0a566d1895 100644
--- a/public/styles/common.scss
+++ b/public/styles/common.scss
@@ -1561,7 +1561,7 @@ div.euiPopover__panel.euiPopover__panel-isOpen.euiPopover__panel--bottom.wz-menu
overflow: hidden;
}
}
- }
+ }
}
@media (min-width: 1600px) {
@@ -1717,31 +1717,39 @@ iframe.width-changed {
text-align: center;
}
-.withUserLogged-logo{
+.withUserLogged-logo {
width: 140px;
margin: 0 auto;
}
-.withUserLogged-loader{
+.withUserLogged-loader {
width: 20px;
margin: 0 auto;
}
-.custom-charts-bar span.euiLoadingChart__bar{
+.custom-charts-bar span.euiLoadingChart__bar {
width: 15px;
}
-.wz-width-100{
+.wz-width-100 {
width: 100%;
}
-.wz-user-select-none{
+.wz-txt-capitalize {
+ text-transform: capitalize;
+}
+
+.wz-user-select-none {
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
+.wz-flex-basis-auto {
+ flex-basis: auto !important;
+}
+
.wz-euiCard-no-title{
.euiCard__title,
.euiCard__description
@@ -1752,11 +1760,11 @@ iframe.width-changed {
/* Custom Searchbar styles */
-.application .filters-search-bar .globalQueryBar, .app-container .filters-search-bar .globalQueryBar{
+.application .filters-search-bar .globalQueryBar, .app-container .filters-search-bar .globalQueryBar {
padding: 0 !important;
}
-@media only screen and (max-width: 960px){
+@media only screen and (max-width: 960px) {
.custom-kbn-search-bar .euiSuperUpdateButton .euiSuperUpdateButton__text {
display: none;
}
@@ -1766,7 +1774,7 @@ iframe.width-changed {
}
}
-@media only screen and (max-width: 767px){
+@media only screen and (max-width: 767px) {
.header-global-wrapper + .app-wrapper:not(.hidden-chrome) {
left: 0!important;
}
@@ -1787,4 +1795,18 @@ iframe.width-changed {
.euiButtonEmpty__text {
font-size: 0.8rem;
}
-}
\ No newline at end of file
+}
+
+.wz-flex {
+ display: flex;
+}
+
+.wz-callout-message {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: row;
+}
+
+.wz-overflow-auto{
+ overflow: auto;
+}
diff --git a/public/styles/component.scss b/public/styles/component.scss
index 733122d86f..7fa8976546 100644
--- a/public/styles/component.scss
+++ b/public/styles/component.scss
@@ -16,106 +16,122 @@
/* Custom nav bar styles */
-.wz-nav-bar .md-nav-bar{
- height: auto !important;
+.wz-nav-bar .md-nav-bar {
+ height: auto !important;
}
.wz-nav-item button,
.wz-no-padding {
- padding: 0 5px!important;
+ padding: 0 5px !important;
}
.wz-nav-item button.md-primary {
- color: rgb(0, 121, 165) !important;
- background: #f5fafb !important;
- border-bottom: 2px solid #006BB4;
+ color: rgb(0, 121, 165) !important;
+ background: #f5fafb !important;
+ border-bottom: 2px solid #006bb4;
}
.wz-nav-item button.md-unselected {
- color: rgba(0, 0, 0, 0.87) !important;
+ color: rgba(0, 0, 0, 0.87) !important;
}
.wz-nav-bar md-nav-ink-bar {
- color: rgb(0, 121, 165) !important;
- background: rgb(0, 121, 165) !important;
+ color: rgb(0, 121, 165) !important;
+ background: rgb(0, 121, 165) !important;
}
.wz-nav-bar md-nav-ink-bar._md-left,
.wz-nav-bar md-nav-ink-bar._md-right {
- transition: none !important;
+ transition: none !important;
}
/* Custom tooltip styles */
.wz-tooltip {
- background-color: rgba(0,0,0,0.87) !important;
- color: #FFF !important;
+ background-color: rgba(0, 0, 0, 0.87) !important;
+ color: #fff !important;
}
/* Custom switch styles */
.wz-switch {
- margin: 0 !important;
+ margin: 0 !important;
}
/* Custom chips styles */
.wz-chips .md-chips {
- box-shadow: none !important;
- padding-bottom: 0;
+ box-shadow: none !important;
+ padding-bottom: 0;
}
.wz-chip {
- font-size: 12px;
- color: white;
- background-color: #006BB4;
- height: 26px !important;
- line-height: 26px !important;
- margin: 0 8px 0 0 !important;
+ font-size: 12px;
+ color: white;
+ background-color: #006bb4;
+ height: 26px !important;
+ line-height: 26px !important;
+ margin: 0 8px 0 0 !important;
}
-
.sca-chart-widget {
- margin: 0 auto;
- //width:350px;
- margin-top:50px;
- background-color: #222D3A;
- border-radius: 5px;
- box-shadow: 0px 0px 1px 0px #06060d;
-
+ margin: 0 auto;
+ //width:350px;
+ margin-top: 50px;
+ background-color: #222d3a;
+ border-radius: 5px;
+ box-shadow: 0px 0px 1px 0px #06060d;
}
-.sca-chart-header{
- background-color: #29384D;
- height:40px;
- color:#929DAF;
- text-align: center;
- line-height: 40px;
- border-top-left-radius: 7px;
- border-top-right-radius: 7px;
- font-weight: 400;
- font-size: 1.5em;
- text-shadow: 1px 1px #06060d;
+.sca-chart-header {
+ background-color: #29384d;
+ height: 40px;
+ color: #929daf;
+ text-align: center;
+ line-height: 40px;
+ border-top-left-radius: 7px;
+ border-top-right-radius: 7px;
+ font-weight: 400;
+ font-size: 1.5em;
+ text-shadow: 1px 1px #06060d;
}
-.sca-chart{
- padding:12px;
+.sca-chart {
+ padding: 12px;
}
.sca-chart-shadow {
- -webkit-filter: drop-shadow( 0px 3px 3px rgba(0,0,0,.5) );
- filter: drop-shadow( 0px 3px 3px rgba(0,0,0,.5) );
+ -webkit-filter: drop-shadow(0px 3px 3px rgba(0, 0, 0, 0.5));
+ filter: drop-shadow(0px 3px 3px rgba(0, 0, 0, 0.5));
}
kbn-dis doc-table .kbnDocViewer__warning {
- display: none;
+ display: none;
}
/* Custom Breadcrumb styles*/
.header__breadcrumbsWithExtensionContainer .euiHeaderBreadcrumbs {
- flex-grow: 1;
- margin-right: 12px;
+ flex-grow: 1;
+ margin-right: 12px;
}
.header__breadcrumbsWithExtensionContainer .header__breadcrumbsAppendExtension {
- flex-grow: 0;
+ flex-grow: 0;
+}
+
+.osButtonsStyle {
+ display: grid;
+ grid-template-columns: repeat(5, 1fr);
+ grid-gap: 10px;
+}
+
+.osButtonsStyleMac {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ grid-gap: 10px;
+}
+
+.message {
+ margin-top: 10px;
+ display: flex;
+ flex-direction: row;
}
diff --git a/public/styles/index.ts b/public/styles/index.ts
index 3bb528da76..a06d502a87 100644
--- a/public/styles/index.ts
+++ b/public/styles/index.ts
@@ -27,9 +27,7 @@ const IS_DARK_THEME = getUiSettings().get('theme:darkMode');
/* tslint-disable no-undef */
if (IS_DARK_THEME) {
import('./theme/dark/index.dark.scss').then();
- import('./7.9.0/index.dark.scss').then();
}else{
import('./theme/light/index.light.scss').then();
- import('./7.9.0/index.light.scss').then();
}
/* tslint-enable no-undef */
diff --git a/public/templates/agents-prev/agents-prev.head b/public/templates/agents-prev/agents-prev.head
deleted file mode 100644
index c11412d214..0000000000
--- a/public/templates/agents-prev/agents-prev.head
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/public/templates/agents-prev/agents-prev.html b/public/templates/agents-prev/agents-prev.html
index b13271f47f..cec8cb3637 100644
--- a/public/templates/agents-prev/agents-prev.html
+++ b/public/templates/agents-prev/agents-prev.html
@@ -36,7 +36,7 @@
layout="column"
layout-align="start space-around"
>
-
+
diff --git a/public/templates/agents-prev/agents-prev.old.html b/public/templates/agents-prev/agents-prev.old.html
deleted file mode 100644
index 7594c55b33..0000000000
--- a/public/templates/agents-prev/agents-prev.old.html
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
- {{ ctrl.errorInit || 'Internal error' }}
-
-
-
-
- Refresh
-
-
-
-
-
-
-
-
diff --git a/public/templates/agents-prev/agents-prev.pug b/public/templates/agents-prev/agents-prev.pug
deleted file mode 100644
index 055019940a..0000000000
--- a/public/templates/agents-prev/agents-prev.pug
+++ /dev/null
@@ -1,3 +0,0 @@
-include ./agents-prev.head
-include ./agents-prev.html
-include ../footer.foot
diff --git a/public/templates/agents/agents-module.html b/public/templates/agents/agents-module.html
deleted file mode 100644
index 5549b81555..0000000000
--- a/public/templates/agents/agents-module.html
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{loadingStatus}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{reportStatus}}
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/public/templates/agents/agents-syscollector.html b/public/templates/agents/agents-syscollector.html
deleted file mode 100644
index 720938ff45..0000000000
--- a/public/templates/agents/agents-syscollector.html
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/public/templates/agents/agents-welcome.html b/public/templates/agents/agents-welcome.html
deleted file mode 100644
index ad7fe432c4..0000000000
--- a/public/templates/agents/agents-welcome.html
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- Try again
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/public/templates/agents/dashboards.head b/public/templates/agents/dashboards.head
deleted file mode 100644
index 075e566cb5..0000000000
--- a/public/templates/agents/dashboards.head
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/public/templates/agents/dashboards.pug b/public/templates/agents/dashboards.pug
deleted file mode 100644
index 2f576b7e7a..0000000000
--- a/public/templates/agents/dashboards.pug
+++ /dev/null
@@ -1,6 +0,0 @@
-include ./dashboards.head
-include ./agents-welcome.html
-include ./agents-module.html
-include ./agents-syscollector.html
-
-include ../footer.foot
diff --git a/public/templates/agents/visualizations.js b/public/templates/agents/visualizations.js
index 5522c74d65..169299fdf9 100644
--- a/public/templates/agents/visualizations.js
+++ b/public/templates/agents/visualizations.js
@@ -44,21 +44,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-General-Alerts-summary',
- width: 60
- },
- {
- title: 'Groups summary',
- id: 'Wazuh-App-Agents-General-Groups-summary',
- width: 40
- }
- ]
- }
]
},
fim: {
@@ -103,15 +88,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-FIM-Alerts-summary'
- }
- ]
- }
]
},
pci: {
@@ -151,15 +127,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-PCI-Last-alerts'
- }
- ]
- }
]
},
gdpr: {
@@ -199,15 +166,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-GDPR-Last-alerts'
- }
- ]
- }
]
},
nist: {
@@ -241,15 +199,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-NIST-Last-alerts'
- }
- ]
- }
]
},
tsc: {
@@ -296,15 +245,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-TSC-Alerts-summary'
- }
- ]
- }
]
},
hipaa: {
@@ -344,15 +284,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-HIPAA-Last-alerts'
- }
- ]
- }
]
},
virustotal: {
@@ -381,15 +312,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-Virustotal-Alerts-summary'
- }
- ]
- }
]
},
osquery: {
@@ -424,15 +346,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Overview-Osquery-Alerts-summary'
- }
- ]
- }
]
},
docker: {
@@ -466,15 +379,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-Docker-Events-summary'
- }
- ]
- }
]
},
oscap: {
@@ -528,15 +432,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-OSCAP-Last-alerts'
- }
- ]
- }
]
},
ciscat: {
@@ -556,15 +451,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-app-Agents-CISCAT-alerts-summary'
- }
- ]
- }
]
},
pm: {
@@ -593,15 +479,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-PM-Alerts-summary'
- }
- ]
- }
]
},
audit: {
@@ -635,15 +512,6 @@ export const visualizations = {
}
]
},
- {
- hide: true,
- vis: [
- {
- title: 'Alerts summary',
- id: 'Wazuh-App-Agents-Audit-Last-alerts'
- }
- ]
- }
]
}
};
diff --git a/public/templates/footer.foot b/public/templates/footer.foot
deleted file mode 100644
index 7f5eaa32ef..0000000000
--- a/public/templates/footer.foot
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/templates/management/groups/groups.html b/public/templates/management/groups/groups.html
deleted file mode 100644
index 988c98b2c9..0000000000
--- a/public/templates/management/groups/groups.html
+++ /dev/null
@@ -1,11 +0,0 @@
-
\ No newline at end of file
diff --git a/public/templates/management/management-welcome.html b/public/templates/management/management-welcome.html
deleted file mode 100644
index b2132f1323..0000000000
--- a/public/templates/management/management-welcome.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/public/templates/management/management.head b/public/templates/management/management.head
deleted file mode 100644
index ba67439b63..0000000000
--- a/public/templates/management/management.head
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
- {{ mctrl.tabNames[mctrl.tab] }}
- / {{ mctrl.currentGroup.name }}
-
-
-
-
diff --git a/public/templates/management/management.html b/public/templates/management/management.html
index 9e8586a415..43d8a15677 100644
--- a/public/templates/management/management.html
+++ b/public/templates/management/management.html
@@ -111,7 +111,7 @@
- IP
+ IP address
{{configuration.nodes[0] || '-'}}
@@ -226,7 +226,7 @@
-
+
-
-
\ No newline at end of file
diff --git a/public/templates/management/management.pug b/public/templates/management/management.pug
deleted file mode 100644
index a688f9d61a..0000000000
--- a/public/templates/management/management.pug
+++ /dev/null
@@ -1,9 +0,0 @@
-include ./management.head
-include ./management-welcome.html
-include ./monitoring/monitoring.pug
-include ./statistics/statistics.html
-include ./management.html
-
-include ./groups/groups.html
-
-include ../footer.foot
\ No newline at end of file
diff --git a/public/templates/management/monitoring/configuration.html b/public/templates/management/monitoring/configuration.html
deleted file mode 100644
index 04558c17fe..0000000000
--- a/public/templates/management/monitoring/configuration.html
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- There are no results for selected
- time
- range. Try another one.
-
-
-
-
-
-
Configuration
-
-
-
- Disabled
- {{configuration.disabled}}
-
-
- Hidden
- {{configuration.hidden}}
-
-
- Name
- {{configuration.name}}
-
-
- Node name
- {{configuration.node_name}}
-
-
- Node type
- {{configuration.node_type}}
-
-
- Bind address
- {{configuration.bind_addr}}
-
-
- IP
- {{configuration.nodes[0] || '-'}}
-
-
- Port
- {{configuration.port}}
-
-
-
-
-
-
\ No newline at end of file
diff --git a/public/templates/management/monitoring/main-timelions.html b/public/templates/management/monitoring/main-timelions.html
deleted file mode 100644
index 6f7a6d4d80..0000000000
--- a/public/templates/management/monitoring/main-timelions.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/public/templates/management/monitoring/main.html b/public/templates/management/monitoring/main.html
deleted file mode 100644
index ae4d15f937..0000000000
--- a/public/templates/management/monitoring/main.html
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-
-
Details
- View
- Overview
-
-
-
-
-
- IP
- {{configuration.nodes[0] || '-'}}
-
-
- Running
- {{ status || 'no' }}
-
-
- Version
- {{version}}
-
-
-
-
-
-
-
-
-
Information
-
-
-
- Nodes
- {{nodesCount}}
-
-
-
- Agents
- {{agentsCount}}
-
-
-
-
-
\ No newline at end of file
diff --git a/public/templates/management/monitoring/monitoring.html b/public/templates/management/monitoring/monitoring.html
deleted file mode 100644
index 4a296bb6d9..0000000000
--- a/public/templates/management/monitoring/monitoring.html
+++ /dev/null
@@ -1,442 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{loadingStatus}}
-
-
-
-
-
-
-
-
-
-
-
-
-
Details
-
- View Overview
-
-
-
-
-
- IP
- {{configuration.nodes[0] || '-'}}
-
-
- Running
- {{ status || 'no' }}
-
-
- Version
- {{version}}
-
-
-
-
-
-
-
-
-
Information
-
-
-
- Nodes
- {{nodesCount}}
-
-
-
- Agents
- {{agentsCount}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- There are no results for selected time range. Try another one.
-
-
-
-
-
-
Configuration
-
-
-
- Disabled
- {{configuration.disabled}}
-
-
- Hidden
- {{configuration.hidden}}
-
-
- Name
- {{configuration.name}}
-
-
- Node name
- {{configuration.node_name}}
-
-
- Node type
- {{configuration.node_type}}
-
-
- Bind address
- {{configuration.bind_addr}}
-
-
- IP
- {{configuration.nodes[0] || '-'}}
-
-
- Port
- {{configuration.port}}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Node {{ currentNode.name }}
-
-
-
-
-
-
-
-
-
-
-
-
-
Node information
-
-
- IP
- {{currentNode.healthCheck.info.ip}}
-
-
- Version
- {{currentNode.healthCheck.info.version}}
-
-
- Type
- {{currentNode.healthCheck.info.type}}
-
-
- Name
- {{currentNode.healthCheck.info.name}}
-
-
- Active agents
- {{ currentNode.healthCheck.info.n_active_agents }}
-
-
-
-
-
-
-
-
Last files integrity synchronization
-
-
- Last sync
- {{currentNode.healthCheck.status.last_sync_integrity.date_end_master}}
-
-
- Duration
- {{currentNode.healthCheck.status.last_sync_integrity.duration}}
-
-
- Total shared files
- {{currentNode.healthCheck.status.last_sync_integrity.total_files.shared}}
-
-
- Total missing files
- {{currentNode.healthCheck.status.last_sync_integrity.total_files.missing}}
-
-
- Total extra but valid files
- {{currentNode.healthCheck.status.last_sync_integrity.total_files.extra_valid}}
-
-
- Total extra files
- {{currentNode.healthCheck.status.last_sync_integrity.total_files.extra}}
-
-
-
-
-
-
-
-
-
-
-
-
Last agents information synchronization
-
-
- Last sync
- {{currentNode.healthCheck.status.last_sync_agentinfo.date_end_master}}
-
-
- Duration
- {{currentNode.healthCheck.status.last_sync_agentinfo.duration}}
-
-
- Total agent info
- {{currentNode.healthCheck.status.last_sync_agentinfo.total_agentinfo}}
-
-
-
-
-
-
-
-
Last agents groups synchronization
-
-
- Last sync
- {{currentNode.healthCheck.status.last_sync_agentgroups.date_end_master}}
-
-
- Duration
- {{currentNode.healthCheck.status.last_sync_agentgroups.duration}}
-
-
- Total agent info
- {{currentNode.healthCheck.status.last_sync_agentgroups.total_agentgroups}}
-
-
-
-
-
-
-
-
diff --git a/public/templates/management/monitoring/monitoring.old.html b/public/templates/management/monitoring/monitoring.old.html
deleted file mode 100644
index 273d21c316..0000000000
--- a/public/templates/management/monitoring/monitoring.old.html
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{loadingStatus}}
-
-
-
-
\ No newline at end of file
diff --git a/public/templates/management/monitoring/monitoring.pug b/public/templates/management/monitoring/monitoring.pug
deleted file mode 100644
index cd4150c842..0000000000
--- a/public/templates/management/monitoring/monitoring.pug
+++ /dev/null
@@ -1,7 +0,0 @@
-include ./monitoring.html
-include ./main.html
-include ./main-timelions.html
-include ./configuration.html
-include ./nodes-list.html
-include ./nodes-detail.html
-include ../../footer.foot
\ No newline at end of file
diff --git a/public/templates/management/monitoring/nodes-detail.html b/public/templates/management/monitoring/nodes-detail.html
deleted file mode 100644
index 6654dcc28d..0000000000
--- a/public/templates/management/monitoring/nodes-detail.html
+++ /dev/null
@@ -1,145 +0,0 @@
-
-
-
-
-
-
- Node {{ currentNode.name }}
-
-
-
-
-
-
-
-
-
-
-
-
-
Node information
-
-
- IP
- {{currentNode.healthCheck.info.ip}}
-
-
- Version
- {{currentNode.healthCheck.info.version}}
-
-
- Type
- {{currentNode.healthCheck.info.type}}
-
-
- Name
- {{currentNode.healthCheck.info.name}}
-
-
- Active agents
- {{ currentNode.healthCheck.info.n_active_agents }}
-
-
-
-
-
-
-
-
Last files integrity synchronization
-
-
- Last sync
- {{currentNode.healthCheck.status.last_sync_integrity.date_end_master}}
-
-
- Duration
- {{currentNode.healthCheck.status.last_sync_integrity.duration}}
-
-
- Total shared files
- {{currentNode.healthCheck.status.last_sync_integrity.total_files.shared}}
-
-
- Total missing files
- {{currentNode.healthCheck.status.last_sync_integrity.total_files.missing}}
-
-
- Total extra but valid files
- {{currentNode.healthCheck.status.last_sync_integrity.total_files.extra_valid}}
-
-
- Total extra files
- {{currentNode.healthCheck.status.last_sync_integrity.total_files.extra}}
-
-
-
-
-
-
-
-
-
-
-
-
Last agents information synchronization
-
-
- Last sync
- {{currentNode.healthCheck.status.last_sync_agentinfo.date_end_master}}
-
-
- Duration
- {{currentNode.healthCheck.status.last_sync_agentinfo.duration}}
-
-
- Total agent info
- {{currentNode.healthCheck.status.last_sync_agentinfo.total_agentinfo}}
-
-
-
-
-
-
-
-
Last agents groups synchronization
-
-
- Last sync
- {{currentNode.healthCheck.status.last_sync_agentgroups.date_end_master}}
-
-
- Duration
- {{currentNode.healthCheck.status.last_sync_agentgroups.duration}}
-
-
- Total agent info
- {{currentNode.healthCheck.status.last_sync_agentgroups.total_agentgroups}}
-
-
-
-
-
-
\ No newline at end of file
diff --git a/public/templates/management/monitoring/nodes-list.html b/public/templates/management/monitoring/nodes-list.html
deleted file mode 100644
index 31e90df48c..0000000000
--- a/public/templates/management/monitoring/nodes-list.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/public/templates/management/ruleset/logtest.html b/public/templates/management/ruleset/logtest.html
deleted file mode 100644
index 0b59c24ec1..0000000000
--- a/public/templates/management/ruleset/logtest.html
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/public/templates/management/statistics/statistics.html b/public/templates/management/statistics/statistics.html
deleted file mode 100644
index c2e3a380ac..0000000000
--- a/public/templates/management/statistics/statistics.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/public/templates/settings/settings-about.html b/public/templates/settings/settings-about.html
deleted file mode 100644
index 83d03a5d60..0000000000
--- a/public/templates/settings/settings-about.html
+++ /dev/null
@@ -1,70 +0,0 @@
-
-
-
-
-
-
App version: {{ctrl.appInfo["app-version"]}}
-
App revision: {{ctrl.appInfo["revision"]}}
-
Install date: {{ctrl.appInfo["installationDate"] | date : "medium"}}
-
-
-
-
-
-
-
-
-
-
-
-
Welcome to the Wazuh app for Kibana {{ctrl.pluginPlatformVersion}}
-
-
-
-
-
-
-
- Wazuh Kibana plugin provides management and monitoring capabilities, giving users control
- over the Wazuh infrastructure. Using this plugin you can monitor your agents status and
- configuration, query and visualize your alert data and monitor manager rules and
- configuration.
-
-
-
-
-
-
-
-
-
-
- Enjoy your Wazuh experience and please don't hesitate to give us your feedback.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/public/templates/settings/settings-api.html b/public/templates/settings/settings-api.html
deleted file mode 100644
index 8e39ec9d3a..0000000000
--- a/public/templates/settings/settings-api.html
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/public/templates/settings/settings-configuration.html b/public/templates/settings/settings-configuration.html
deleted file mode 100644
index cf695f950e..0000000000
--- a/public/templates/settings/settings-configuration.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/public/templates/settings/settings-logs.html b/public/templates/settings/settings-logs.html
deleted file mode 100644
index f8b50bb531..0000000000
--- a/public/templates/settings/settings-logs.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/public/templates/settings/settings-modules.html b/public/templates/settings/settings-modules.html
deleted file mode 100644
index 75fd2ab3c9..0000000000
--- a/public/templates/settings/settings-modules.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/public/templates/settings/settings-sample-data.html b/public/templates/settings/settings-sample-data.html
deleted file mode 100644
index 356cdd80cc..0000000000
--- a/public/templates/settings/settings-sample-data.html
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/public/templates/settings/settings.head b/public/templates/settings/settings.head
deleted file mode 100644
index 7ae19cc2ed..0000000000
--- a/public/templates/settings/settings.head
+++ /dev/null
@@ -1,8 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/public/templates/settings/settings.html b/public/templates/settings/settings.html
index 10e56dcf72..e842bfff8e 100644
--- a/public/templates/settings/settings.html
+++ b/public/templates/settings/settings.html
@@ -87,7 +87,7 @@
>
- Welcome to the Wazuh app for {{ctrl.pluginPlatformName}} {{ctrl.pluginPlatformVersion}}
+ Welcome to the {{ctrl.pluginAppName}}
@@ -96,8 +96,8 @@
- Wazuh {{ctrl.pluginPlatformName}} plugin provides management and monitoring capabilities, giving users
- control over the Wazuh infrastructure. Using this plugin you can monitor your agents
+ {{ctrl.pluginAppName}} provides management and monitoring capabilities, giving users
+ control over the Wazuh infrastructure. You can monitor your agents
status and configuration, query and visualize your alert data and monitor manager
rules and configuration.
@@ -137,7 +137,7 @@
Community
diff --git a/public/templates/settings/settings.pug b/public/templates/settings/settings.pug
deleted file mode 100644
index 854982ea67..0000000000
--- a/public/templates/settings/settings.pug
+++ /dev/null
@@ -1,8 +0,0 @@
-include ./settings.head
-include ./settings-api.html
-include ./settings-modules.html
-include ./settings-configuration.html
-include ./settings-logs.html
-include ./settings-about.html
-include ./settings-sample-data.html
-include ../footer.foot
diff --git a/public/templates/tools/dev-tools.html b/public/templates/tools/dev-tools.html
deleted file mode 100644
index b78b52d4fa..0000000000
--- a/public/templates/tools/dev-tools.html
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/public/templates/tools/tools.head b/public/templates/tools/tools.head
deleted file mode 100644
index 331f6506e0..0000000000
--- a/public/templates/tools/tools.head
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/templates/tools/tools.pug b/public/templates/tools/tools.pug
deleted file mode 100644
index 2b1b3d0639..0000000000
--- a/public/templates/tools/tools.pug
+++ /dev/null
@@ -1 +0,0 @@
-include ./dev-tools.html
diff --git a/public/templates/visualize/dashboards.old.html b/public/templates/visualize/dashboards.old.html
deleted file mode 100644
index 79b04fba62..0000000000
--- a/public/templates/visualize/dashboards.old.html
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{{reportStatus}}
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/public/templates/visualize/dashboards.pug b/public/templates/visualize/dashboards.pug
deleted file mode 100644
index 28b3512190..0000000000
--- a/public/templates/visualize/dashboards.pug
+++ /dev/null
@@ -1,3 +0,0 @@
-include ./dashboards.html
-include ./overview-welcome.html
-include ./footer.foot
diff --git a/public/templates/visualize/footer.foot b/public/templates/visualize/footer.foot
deleted file mode 100644
index 2d8bb3eb2c..0000000000
--- a/public/templates/visualize/footer.foot
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/public/templates/visualize/overview-welcome.html b/public/templates/visualize/overview-welcome.html
deleted file mode 100644
index 906b5f0143..0000000000
--- a/public/templates/visualize/overview-welcome.html
+++ /dev/null
@@ -1,6 +0,0 @@
-
\ No newline at end of file
diff --git a/public/types.ts b/public/types.ts
index c8a5c4306e..3a75c7fdc6 100644
--- a/public/types.ts
+++ b/public/types.ts
@@ -1,4 +1,4 @@
-import { AppMountParameters, CoreStart } from 'kibana/public';
+import { AppMountParameters, CoreStart } from 'opensearch_dashboards/public';
import { ChartsPluginStart } from '../../../src/plugins/charts/public/plugin';
import { DiscoverStart } from '../../../src/plugins/discover/public';
import { VisualizationsSetup, VisualizationsStart } from '../../../src/plugins/visualizations/public';
@@ -22,7 +22,7 @@ export interface AppPluginStartDependencies {
export interface AppDependencies {
core: CoreStart;
plugins: AppPluginStartDependencies;
- params: AppMountParameters;
+ params: AppMountParameters;
}
export type WazuhSetupPlugins = {
diff --git a/public/utils/check-plugin-version.tsx b/public/utils/check-plugin-version.tsx
index 635ff1cb4a..a7ba8e1afc 100644
--- a/public/utils/check-plugin-version.tsx
+++ b/public/utils/check-plugin-version.tsx
@@ -14,10 +14,10 @@ import { AxiosResponse } from 'axios';
import _ from 'lodash';
import { version as appVersion, revision as appRevision } from '../../package.json';
import { getCookies, getToasts } from '../kibana-services';
-import { ErrorToastOptions } from 'kibana/public';
+import { ErrorToastOptions } from 'opensearch_dashboards/public';
import React from 'react';
import { ReactNode } from 'x-pack/node_modules/@types/react';
-import { PLUGIN_PLATFORM_NAME } from '../../common/constants';
+import { PLUGIN_PLATFORM_NAME, PLUGIN_APP_NAME } from '../../common/constants';
import { webDocumentationLink } from '../../common/services/web_documentation';
type TAppInfo = {
@@ -46,21 +46,19 @@ export const checkPluginVersion = async () => {
const checkClientAppVersion = (appInfo: TAppInfo) => {
if (appInfo['app-version'] !== appVersion || appInfo.revision !== appRevision) {
const toastOptions: ErrorToastOptions = {
- title: 'Conflict with the Wazuh app version',
+ title: `Conflict with the ${PLUGIN_APP_NAME} version`,
toastLifeTimeMs: 50000,
- toastMessage: `The version of the Wazuh app in your browser does not correspond with the app version installed in ${PLUGIN_PLATFORM_NAME}. Please, clear your browser cache. For more info check the full error.`,
+ toastMessage: `The version of the ${PLUGIN_APP_NAME} in your browser does not correspond with the app version installed in ${PLUGIN_PLATFORM_NAME}. Please, clear your browser cache. For more info check the full error.`,
};
-
const troubleshootingUrl = webDocumentationLink('user-manual/elasticsearch/troubleshooting.html');
-
const message: ReactNode = (
<>
- The version of the Wazuh app in your browser{' '}
+ The version of the {PLUGIN_APP_NAME} in your browser{' '}
{appVersion} - {appRevision}
{' '}
- does not correspond with the app version installed in {PLUGIN_PLATFORM_NAME}{' '}
+ does not correspond with the version installed in {PLUGIN_PLATFORM_NAME}{' '}
{appInfo['app-version']} - {appInfo.revision}
@@ -70,7 +68,11 @@ const checkClientAppVersion = (appInfo: TAppInfo) => {
If the error persists, restart {PLUGIN_PLATFORM_NAME} as well.
For more information check our troubleshooting section{' '}
-
+
here.
diff --git a/public/utils/index.ts b/public/utils/index.ts
index 3691c70d1c..007a96971b 100644
--- a/public/utils/index.ts
+++ b/public/utils/index.ts
@@ -1,5 +1,3 @@
-export * as OdfeUtils from './odfe-utils';
-
export { checkPluginVersion } from './check-plugin-version';
export { addHelpMenuToAppChrome } from './add_help_menu_to_app';
\ No newline at end of file
diff --git a/public/utils/odfe-utils.ts b/public/utils/odfe-utils.ts
deleted file mode 100644
index d030a60b43..0000000000
--- a/public/utils/odfe-utils.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Wazuh app - Module with utilities for Opendistro
- * Copyright (C) 2015-2022 Wazuh, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * Find more information about this on the LICENSE file.
- */
-import { AxiosError } from 'axios'
-
-type TAuthenticationRequiredError = {
- statusCode: 401
- error: 'Unauthorized'
- message: 'Authentication required'
-}
-
-const isAuthenticationRequired = (e: any): e is TAuthenticationRequiredError => {
- const statusCode = e.statusCode && e.statusCode === 401;
- const error = e.error && e.error === 'Unauthorized';
- const message = e.message && e.message === 'Authentication required';
- return statusCode && error && message;
-}
-
-export const checkOdfeSessionExpired = (error: AxiosError
) => {
- const { data } = (error || {}).response || {};
- if (isAuthenticationRequired(data || {})) {
- location.reload();
- }
-}
diff --git a/scripts/generate-api-4.0-info/generate-api-4.0-info.js b/scripts/generate-api-4.0-info/generate-api-4.0-info.js
index 1b18e94dca..c022a46794 100755
--- a/scripts/generate-api-4.0-info/generate-api-4.0-info.js
+++ b/scripts/generate-api-4.0-info/generate-api-4.0-info.js
@@ -55,7 +55,7 @@ const main = () => {
if(!WAZUH_API_URL.startsWith('http') ){
exitWithMessage(`Wazuh API url is not valid. It should start with "http". Example: https://172.16.1.2:55000`);
};
-
+
// Log the configuration:
console.log('--------------- Configuration ---------------');
console.log(`Wazuh API url: ${WAZUH_API_URL}`);
@@ -113,6 +113,7 @@ const generateAPISecurityActionsInformation = async () => {
const password = 'wazuh';
try{
const authenticationResponse = await request(`${WAZUH_API_URL}/security/user/authenticate`, {
+ method: 'POST',
headers: {
'Authorization': 'Basic ' + Buffer.from(username + ':' + password).toString('base64')
}
@@ -121,7 +122,7 @@ const generateAPISecurityActionsInformation = async () => {
const { token } = JSON.parse(authenticationResponse).data;
const securityActionsResponse = await request(`${WAZUH_API_URL}/security/actions`, {
headers: {
- 'Authorization': `Bearer ${token}`
+ 'Authorization': `Bearer ${token}`
}
});
const securityActions = JSON.parse(securityActionsResponse).data;
diff --git a/scripts/generate-build-version.js b/scripts/generate-build-version.js
index a03dd975fe..4fde0cf017 100644
--- a/scripts/generate-build-version.js
+++ b/scripts/generate-build-version.js
@@ -2,8 +2,10 @@ const fs = require('fs');
const packageJson = require('../package.json');
const { version, revision } = packageJson;
-//replaces kibana.json with last
-fs.readFile('kibana.json', 'utf-8', function (err, data) {
+//replaces the plugin manifest file with the current app version when building the plugin package
+const pluginManifestFilename = 'opensearch_dashboards.json';
+
+fs.readFile(pluginManifestFilename, 'utf-8', function (err, data) {
if (err) {
console.log(err);
return;
@@ -15,12 +17,12 @@ fs.readFile('kibana.json', 'utf-8', function (err, data) {
const jsonConfig = JSON.stringify(config, null, 2);
- fs.writeFile('kibana.json', jsonConfig, 'utf8', function (err) {
+ fs.writeFile(pluginManifestFilename, jsonConfig, 'utf8', function (err) {
if (err) {
- console.log('An error occurred while writing JSON Object to kibana.json');
+ console.log(`An error occurred while writing JSON Object to ${pluginManifestFilename}`);
return console.log(err);
}
- console.log('kibana.json file has been saved with latest version number');
+ console.log(`${pluginManifestFilename} file has been saved with latest version number`);
});
});
diff --git a/scripts/tag.py b/scripts/tag.py
new file mode 100644
index 0000000000..811e1733c2
--- /dev/null
+++ b/scripts/tag.py
@@ -0,0 +1,111 @@
+import json
+import logging
+import os
+import subprocess
+
+# ==================== CONFIGURATION ==================== #
+# Values to modify:
+# - version
+# - revision
+# - stage
+# - supported_versions & kbn_versions ONLY IF NEEDED (e.g. new Kibana version)
+# ======================================================= #
+
+# Wazuh version: major.minor.patch
+version = '4.4.0'
+# App's revision number (previous rev + 1)
+revision = '02'
+# One of 'pre-alpha', 'alpha', 'beta', 'release-candidate', 'stable'
+stage = 'rc1'
+
+# Global variable. Will be set later
+branch = None
+minor = ".".join(version.split('.')[:2])
+
+# Supported versions of Kibana
+kbn_versions = [
+ [f'7.16.{x}' for x in range(0, 4)],
+ [f'7.17.{x}' for x in range(0, 9)]
+]
+
+# Platforms versions
+supported_versions = {
+ 'OpenDistro': {
+ 'branch': f'{minor}-7.10',
+ 'versions': ['7.10.2']
+ },
+ 'Kibana': {
+ 'branch': f'{minor}-7.16',
+ # Flatten 2D list kbn_versions using lists comprehension
+ 'versions': [item for sublist in kbn_versions for item in sublist]
+ },
+ 'Wazuh Dashboard': {
+ 'branch': f'{minor}-2.4-wzd',
+ 'versions': ['2.4.1']
+ }
+}
+
+
+def get_git_revision_short_hash() -> str:
+ return subprocess.check_output(['git', 'rev-parse', '--short', branch]).decode('ascii').strip()
+
+
+def update_package_json(v: str) -> tuple:
+ logging.info(f'Updating package.json')
+ data, success = {}, True
+
+ # Read JSON and update keys.
+ with open('package.json', 'r') as f:
+ data, success = json.load(f), False
+
+ # Update file
+ data['commit'] = get_git_revision_short_hash()
+ data['version'] = version
+ data['revision'] = revision
+ data['stage'] = stage
+ data['pluginPlatform']['version'] = v
+
+ with open('package.json', 'w') as f:
+ json.dump(data, f, indent=2)
+
+ os.system('node scripts/generate-build-version')
+
+ return data, success
+
+
+def setup():
+ logging.info(
+ f'Switching to branch "{branch}" and removing outdated tags...')
+ os.system(f'git checkout {branch}')
+ os.system('git fetch --prune --prune-tags')
+
+
+def main(platform: str, versions: list):
+ for v in versions:
+ tag = f'v{version}-{v}-{stage}'
+ logging.info(f'Generating tag "{tag}"')
+ update_package_json(v)
+ os.system(f'git commit -am "Bump {tag}"')
+ os.system(
+ f'git tag -a {tag} -m "Wazuh {version} for {platform} {v}"')
+ logging.info(f'Pushing tag "{tag}" to remote.')
+ os.system(f'git push origin {tag}')
+ # Undo latest commit
+ os.system(f'git reset --hard origin/{branch}')
+ # Save created tags to file
+ os.system(f'git tag | grep -P -i "^v{version}-.*-{stage}" > tags.txt')
+
+
+if __name__ == '__main__':
+ logging.basicConfig(
+ filename='output.log',
+ level=logging.INFO,
+ format='%(asctime)s %(message)s'
+ )
+ logging.info(
+ f'Wazuh version is "{version}". App revision is "{revision}". Stage is "{stage}"')
+
+ for platform_name, platform_data in supported_versions.items():
+ branch, versions = platform_data['branch'], platform_data['versions']
+ setup()
+ main(platform_name, versions)
diff --git a/server/controllers/wazuh-api.ts b/server/controllers/wazuh-api.ts
index a5490e03e1..2dc0e1bb13 100644
--- a/server/controllers/wazuh-api.ts
+++ b/server/controllers/wazuh-api.ts
@@ -17,12 +17,14 @@ import { log } from '../lib/logger';
import { KeyEquivalence } from '../../common/csv-key-equivalence';
import { ApiErrorEquivalence } from '../lib/api-errors-equivalence';
import apiRequestList from '../../common/api-info/endpoints';
+import { HTTP_STATUS_CODES } from '../../common/constants';
+import { getCustomizationSetting } from '../../common/services/settings';
import { addJobToQueue } from '../start/queue';
import fs from 'fs';
import { ManageHosts } from '../lib/manage-hosts';
import { UpdateRegistry } from '../lib/update-registry';
import jwtDecode from 'jwt-decode';
-import { KibanaRequest, RequestHandlerContext, KibanaResponseFactory } from 'src/core/server';
+import { OpenSearchDashboardsRequest, RequestHandlerContext, OpenSearchDashboardsResponseFactory } from 'src/core/server';
import { APIUserAllowRunAs, CacheInMemoryAPIUserAllowRunAs, API_USER_STATUS_RUN_AS } from '../lib/cache-api-user-has-run-as';
import { getCookieValueByName } from '../lib/cookie';
import { SecurityObj } from '../lib/security-factory';
@@ -37,7 +39,7 @@ export class WazuhApiCtrl {
this.updateRegistry = new UpdateRegistry();
}
- async getToken(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async getToken(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
const { force, idHost } = request.body;
const { username } = await context.wazuh.security.getCurrentUser(request, context);
@@ -85,7 +87,7 @@ export class WazuhApiCtrl {
return ErrorResponse(
`Error getting the authorization token: ${errorMessage}`,
3000,
- 500,
+ error?.response?.status || HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
response
);
}
@@ -98,7 +100,7 @@ export class WazuhApiCtrl {
* @param {Object} response
* @returns {Object} status obj or ErrorResponse
*/
- async checkStoredAPI(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async checkStoredAPI(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
// Get config from wazuh.yml
const id = request.body.id;
@@ -123,13 +125,13 @@ export class WazuhApiCtrl {
return ErrorResponse(
`ERROR3099 - ${responseManagerInfo.data.detail || 'Wazuh not ready yet'}`,
3099,
- 500,
+ HTTP_STATUS_CODES.SERVICE_UNAVAILABLE,
response
);
}
// If we have a valid response from the Wazuh API
- if (responseManagerInfo.status === 200 && responseManagerInfo.data) {
+ if (responseManagerInfo.status === HTTP_STATUS_CODES.OK && responseManagerInfo.data) {
// Clear and update cluster information before being sent back to frontend
delete api.cluster_info;
const responseAgents = await context.wazuh.api.client.asInternalUser.request(
@@ -139,7 +141,7 @@ export class WazuhApiCtrl {
{ apiHostID: id }
);
- if (responseAgents.status === 200) {
+ if (responseAgents.status === HTTP_STATUS_CODES.OK) {
const managerName = responseAgents.data.data.affected_items[0].manager;
const responseClusterStatus = await context.wazuh.api.client.asInternalUser.request(
@@ -148,7 +150,7 @@ export class WazuhApiCtrl {
{},
{ apiHostID: id }
);
- if (responseClusterStatus.status === 200) {
+ if (responseClusterStatus.status === HTTP_STATUS_CODES.OK) {
if (responseClusterStatus.data.data.enabled === 'yes') {
const responseClusterLocalInfo = await context.wazuh.api.client.asInternalUser.request(
'GET',
@@ -156,7 +158,7 @@ export class WazuhApiCtrl {
{},
{ apiHostID: id }
);
- if (responseClusterLocalInfo.status === 200) {
+ if (responseClusterLocalInfo.status === HTTP_STATUS_CODES.OK) {
const clusterEnabled = responseClusterStatus.data.data.enabled === 'yes';
api.cluster_info = {
status: clusterEnabled ? 'enabled' : 'disabled',
@@ -195,7 +197,7 @@ export class WazuhApiCtrl {
return response.ok({
body: {
- statusCode: 200,
+ statusCode: HTTP_STATUS_CODES.OK,
data: copied,
idChanged: request.body.idChanged || null,
}
@@ -210,14 +212,14 @@ export class WazuhApiCtrl {
if (error.code === 'EPROTO') {
return response.ok({
body: {
- statusCode: 200,
+ statusCode: HTTP_STATUS_CODES.OK,
data: { apiIsDown: true },
}
});
} else if (error.code === 'ECONNREFUSED') {
return response.ok({
body: {
- statusCode: 200,
+ statusCode: HTTP_STATUS_CODES.OK,
data: { apiIsDown: true },
}
});
@@ -239,11 +241,11 @@ export class WazuhApiCtrl {
return ErrorResponse(
`ERROR3099 - ${response.data.detail || 'Wazuh not ready yet'}`,
3099,
- 500,
+ HTTP_STATUS_CODES.SERVICE_UNAVAILABLE,
response
);
}
- if (responseManagerInfo.status === 200) {
+ if (responseManagerInfo.status === HTTP_STATUS_CODES.OK) {
request.body.id = id;
request.body.idChanged = id;
return await this.checkStoredAPI(context, request, response);
@@ -252,10 +254,20 @@ export class WazuhApiCtrl {
}
} catch (error) {
log('wazuh-api:checkStoredAPI', error.message || error);
- return ErrorResponse(error.message || error, 3020, 500, response);
+ return ErrorResponse(
+ error.message || error,
+ 3020,
+ error?.response?.status || HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
+ response
+ );
}
log('wazuh-api:checkStoredAPI', error.message || error);
- return ErrorResponse(error.message || error, 3002, 500, response);
+ return ErrorResponse(
+ error.message || error,
+ 3002,
+ error?.response?.status || HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
+ response
+ );
}
}
}
@@ -295,11 +307,11 @@ export class WazuhApiCtrl {
* @param {Object} response
* @returns {Object} status obj or ErrorResponse
*/
- async checkAPI(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async checkAPI(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
let apiAvailable = null;
// const notValid = this.validateCheckApiParams(request.body);
- // if (notValid) return ErrorResponse(notValid, 3003, 500, response);
+ // if (notValid) return ErrorResponse(notValid, 3003, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response);
log('wazuh-api:checkAPI', `${request.body.id} is valid`, 'debug');
// Check if a Wazuh API id is given (already stored API)
const data = await this.manageHosts.getHostById(request.body.id);
@@ -307,7 +319,12 @@ export class WazuhApiCtrl {
apiAvailable = data;
} else {
log('wazuh-api:checkAPI', `API ${request.body.id} not found`);
- return ErrorResponse(`The API ${request.body.id} was not found`, 3029, 500, response);
+ return ErrorResponse(
+ `The API ${request.body.id} was not found`,
+ 3029,
+ HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
+ response
+ );
}
const options = { apiHostID: request.body.id };
if (request.body.forceRefresh) {
@@ -325,13 +342,13 @@ export class WazuhApiCtrl {
return ErrorResponse(
`ERROR3099 - ${error.response?.data?.detail || 'Wazuh not ready yet'}`,
3099,
- 500,
+ error?.response?.status || HTTP_STATUS_CODES.SERVICE_UNAVAILABLE,
response
);
}
log('wazuh-api:checkAPI', `${request.body.id} credentials are valid`, 'debug');
- if (responseManagerInfo.status === 200 && responseManagerInfo.data) {
+ if (responseManagerInfo.status === HTTP_STATUS_CODES.OK && responseManagerInfo.data) {
let responseAgents = await context.wazuh.api.client.asInternalUser.request(
'GET',
`/agents`,
@@ -339,7 +356,7 @@ export class WazuhApiCtrl {
{ apiHostID: request.body.id }
);
- if (responseAgents.status === 200) {
+ if (responseAgents.status === HTTP_STATUS_CODES.OK) {
const managerName = responseAgents.data.data.affected_items[0].manager;
let responseCluster = await context.wazuh.api.client.asInternalUser.request(
@@ -357,7 +374,7 @@ export class WazuhApiCtrl {
{},
{ apiHostID: request.body.id }
);
- if (responseApiUserAllowRunAs.status === 200) {
+ if (responseApiUserAllowRunAs.status === HTTP_STATUS_CODES.OK) {
const allow_run_as = responseApiUserAllowRunAs.data.data.affected_items[0].allow_run_as;
if (allow_run_as && apiAvailable && apiAvailable.run_as) // HOST AND USER ENABLED
@@ -378,7 +395,7 @@ export class WazuhApiCtrl {
apiUserAllowRunAs
);
- if (responseCluster.status === 200) {
+ if (responseCluster.status === HTTP_STATUS_CODES.OK) {
log('wazuh-api:checkStoredAPI', `Wazuh API response is valid`, 'debug');
if (responseCluster.data.data.enabled === 'yes') {
// If cluster mode is active
@@ -389,7 +406,7 @@ export class WazuhApiCtrl {
{ apiHostID: request.body.id }
);
- if (responseClusterLocal.status === 200) {
+ if (responseClusterLocal.status === HTTP_STATUS_CODES.OK) {
return response.ok({
body: {
manager: managerName,
@@ -417,19 +434,19 @@ export class WazuhApiCtrl {
} catch (error) {
log('wazuh-api:checkAPI', error.message || error);
- if (error && error.response && error.response.status === 401) {
+ if (error && error.response && error.response.status === HTTP_STATUS_CODES.UNAUTHORIZED) {
return ErrorResponse(
`Unathorized. Please check API credentials. ${error.response.data.message}`,
- 401,
- 401,
+ HTTP_STATUS_CODES.UNAUTHORIZED,
+ HTTP_STATUS_CODES.UNAUTHORIZED,
response
);
}
if (error && error.response && error.response.data && error.response.data.detail) {
return ErrorResponse(
error.response.data.detail,
- error.response.status || 500,
- error.response.status || 500,
+ error.response.status || HTTP_STATUS_CODES.SERVICE_UNAVAILABLE,
+ error.response.status || HTTP_STATUS_CODES.SERVICE_UNAVAILABLE,
response
);
}
@@ -437,16 +454,21 @@ export class WazuhApiCtrl {
return ErrorResponse(
'Wrong protocol being used to connect to the Wazuh API',
3005,
- 500,
+ HTTP_STATUS_CODES.BAD_REQUEST,
response
);
}
- return ErrorResponse(error.message || error, 3005, 500, response);
+ return ErrorResponse(
+ error.message || error,
+ 3005,
+ error?.response?.status || HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
+ response
+ );
}
}
checkResponseIsDown(response) {
- if (response.status !== 200) {
+ if (response.status !== HTTP_STATUS_CODES.OK) {
// Avoid "Error communicating with socket" like errors
const socketErrorCodes = [1013, 1014, 1017, 1018, 1019];
const status = (response.data || {}).status || 1
@@ -539,7 +561,7 @@ export class WazuhApiCtrl {
* @returns {Object} API response or ErrorResponse
*/
async makeRequest(context, method, path, data, id, response) {
-
+
const devTools = !!(data || {}).devTools;
try {
const api = await this.manageHosts.getHostById(id);
@@ -550,7 +572,7 @@ export class WazuhApiCtrl {
if (!Object.keys(api).length) {
log('wazuh-api:makeRequest', 'Could not get host credentials');
//Can not get credentials from wazuh-hosts
- return ErrorResponse('Could not get host credentials', 3011, 404, response);
+ return ErrorResponse('Could not get host credentials', 3011, HTTP_STATUS_CODES.NOT_FOUND, response);
}
if (!data) {
@@ -608,7 +630,7 @@ export class WazuhApiCtrl {
return ErrorResponse(
`ERROR3099 - ${error.message || 'Wazuh not ready yet'}`,
3099,
- 500,
+ HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
response
);
}
@@ -637,7 +659,7 @@ export class WazuhApiCtrl {
return ErrorResponse(
`ERROR3099 - ${response.body.message || 'Wazuh not ready yet'}`,
3099,
- 500,
+ HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
response
);
}
@@ -649,7 +671,7 @@ export class WazuhApiCtrl {
: false;
response.data = responseBody;
}
- const responseError = response.status !== 200 ? response.status : false;
+ const responseError = response.status !== HTTP_STATUS_CODES.OK ? response.status : false;
if (!responseError && responseBody) {
//cleanKeys(response);
@@ -667,11 +689,11 @@ export class WazuhApiCtrl {
? { message: responseBody.detail, code: responseError }
: new Error('Unexpected error fetching data from the Wazuh API');
} catch (error) {
- if (error && error.response && error.response.status === 401) {
+ if (error && error.response && error.response.status === HTTP_STATUS_CODES.UNAUTHORIZED) {
return ErrorResponse(
error.message || error,
error.code ? `Wazuh API error: ${error.code}` : 3013,
- 401,
+ HTTP_STATUS_CODES.UNAUTHORIZED,
response
);
}
@@ -688,7 +710,7 @@ export class WazuhApiCtrl {
return ErrorResponse(
errorMsg.detail || error,
error.code ? `Wazuh API error: ${error.code}` : 3013,
- 500,
+ HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
response
);
}
@@ -702,29 +724,29 @@ export class WazuhApiCtrl {
* @param {Object} response
* @returns {Object} api response or ErrorResponse
*/
- requestApi(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ requestApi(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
const idApi = getCookieValueByName(request.headers.cookie, 'wz-api');
if (idApi !== request.body.id) { // if the current token belongs to a different API id, we relogin to obtain a new token
return ErrorResponse(
'status code 401',
- 401,
- 401,
+ HTTP_STATUS_CODES.UNAUTHORIZED,
+ HTTP_STATUS_CODES.UNAUTHORIZED,
response
);
}
if (!request.body.method) {
- return ErrorResponse('Missing param: method', 3015, 400, response);
+ return ErrorResponse('Missing param: method', 3015, HTTP_STATUS_CODES.BAD_REQUEST, response);
} else if (!request.body.method.match(/^(?:GET|PUT|POST|DELETE)$/)) {
log('wazuh-api:makeRequest', 'Request method is not valid.');
//Method is not a valid HTTP request method
- return ErrorResponse('Request method is not valid.', 3015, 400, response);
+ return ErrorResponse('Request method is not valid.', 3015, HTTP_STATUS_CODES.BAD_REQUEST, response);
} else if (!request.body.path) {
- return ErrorResponse('Missing param: path', 3016, 400, response);
+ return ErrorResponse('Missing param: path', 3016, HTTP_STATUS_CODES.BAD_REQUEST, response);
} else if (!request.body.path.startsWith('/')) {
log('wazuh-api:makeRequest', 'Request path is not valid.');
//Path doesn't start with '/'
- return ErrorResponse('Request path is not valid.', 3015, 400, response);
+ return ErrorResponse('Request path is not valid.', 3015, HTTP_STATUS_CODES.BAD_REQUEST, response);
} else {
return this.makeRequest(
@@ -745,7 +767,7 @@ export class WazuhApiCtrl {
* @param {Object} response
* @returns {Object} csv or ErrorResponse
*/
- async csv(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async csv(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
if (!request.body || !request.body.path) throw new Error('Field path is required');
if (!request.body.id) throw new Error('Field id is required');
@@ -873,12 +895,12 @@ export class WazuhApiCtrl {
}
} catch (error) {
log('wazuh-api:csv', error.message || error);
- return ErrorResponse(error.message || error, 3034, 500, response);
+ return ErrorResponse(error.message || error, 3034, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response);
}
}
// Get de list of available requests in the API
- getRequestList(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ getRequestList(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
//Read a static JSON until the api call has implemented
return response.ok({
body: apiRequestList
@@ -892,7 +914,7 @@ export class WazuhApiCtrl {
* @param {Object} response
* @returns {Object} timestamp field or ErrorResponse
*/
- getTimeStamp(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ getTimeStamp(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
const source = JSON.parse(fs.readFileSync(this.updateRegistry.file, 'utf8'));
if (source.installationDate && source.lastRestart) {
@@ -915,7 +937,7 @@ export class WazuhApiCtrl {
return ErrorResponse(
error.message || 'Could not fetch wazuh-version registry',
4001,
- 500,
+ HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
response
);
}
@@ -928,14 +950,14 @@ export class WazuhApiCtrl {
* @param {Object} response
* @returns {Object} extensions object or ErrorResponse
*/
- async setExtensions(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async setExtensions(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
const { id, extensions } = request.body;
// Update cluster information in the wazuh-registry.json
await this.updateRegistry.updateAPIExtensions(id, extensions);
return response.ok({
body: {
- statusCode: 200
+ statusCode: HTTP_STATUS_CODES.OK
}
});
} catch (error) {
@@ -943,7 +965,7 @@ export class WazuhApiCtrl {
return ErrorResponse(
error.message || 'Could not set extensions',
4001,
- 500,
+ HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
response
);
}
@@ -956,7 +978,7 @@ export class WazuhApiCtrl {
* @param {Object} response
* @returns {Object} extensions object or ErrorResponse
*/
- getExtensions(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ getExtensions(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
const source = JSON.parse(
fs.readFileSync(this.updateRegistry.file, 'utf8')
@@ -971,7 +993,7 @@ export class WazuhApiCtrl {
return ErrorResponse(
error.message || 'Could not fetch wazuh-version registry',
4001,
- 500,
+ HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
response
);
}
@@ -984,12 +1006,12 @@ export class WazuhApiCtrl {
* @param {Object} response
* @returns {Object} setup info or ErrorResponse
*/
- async getSetupInfo(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async getSetupInfo(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
const source = JSON.parse(fs.readFileSync(this.updateRegistry.file, 'utf8'));
return response.ok({
body: {
- statusCode: 200,
+ statusCode: HTTP_STATUS_CODES.OK,
data: !Object.values(source).length ? '' : source
}
});
@@ -998,7 +1020,7 @@ export class WazuhApiCtrl {
return ErrorResponse(
`Could not get data from wazuh-version registry due to ${error.message || error}`,
4005,
- 500,
+ HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR,
response
);
}
@@ -1011,7 +1033,7 @@ export class WazuhApiCtrl {
* @param {Object} response
* @returns {Object} Basic syscollector information
*/
- async getSyscollector(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async getSyscollector(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
const apiHostID = getCookieValueByName(request.headers.cookie,'wz-api');
if (!request.params || !apiHostID || !request.params.agent) {
@@ -1045,19 +1067,19 @@ export class WazuhApiCtrl {
});
} catch (error) {
log('wazuh-api:getSyscollector', error.message || error);
- return ErrorResponse(error.message || error, 3035, 500, response);
+ return ErrorResponse(error.message || error, 3035, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response);
}
}
/**
* Check if user assigned roles disable Wazuh Plugin
- * @param context
- * @param request
- * @param response
- * @returns {object} Returns { isWazuhDisabled: boolean parsed integer }
+ * @param context
+ * @param request
+ * @param response
+ * @returns {object} Returns { isWazuhDisabled: boolean parsed integer }
*/
- async isWazuhDisabled(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async isWazuhDisabled(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
-
+
const disabledRoles = ( await getConfiguration() )['disabled_roles'] || [];
const logoSidebar = ( await getConfiguration() )['customization.logo.sidebar'];
const data = (await context.wazuh.security.getCurrentUser(request, context)).authContext;
@@ -1069,8 +1091,37 @@ export class WazuhApiCtrl {
});
} catch (error) {
log('wazuh-api:isWazuhDisabled', error.message || error);
- return ErrorResponse(error.message || error, 3035, 500, response);
+ return ErrorResponse(error.message || error, 3035, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response);
}
-
+
+ }
+
+ /**
+ * Gets custom logos configuration (path)
+ * @param context
+ * @param request
+ * @param response
+ */
+ async getAppLogos(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
+ try {
+ const configuration = getConfiguration();
+ const SIDEBAR_LOGO = 'customization.logo.sidebar';
+ const APP_LOGO = 'customization.logo.app';
+ const HEALTHCHECK_LOGO = 'customization.logo.healthcheck';
+
+ const logos= {
+ [SIDEBAR_LOGO]: getCustomizationSetting(configuration, SIDEBAR_LOGO),
+ [APP_LOGO]: getCustomizationSetting(configuration, APP_LOGO),
+ [HEALTHCHECK_LOGO]: getCustomizationSetting(configuration, HEALTHCHECK_LOGO),
+ }
+
+ return response.ok({
+ body: { logos }
+ });
+ } catch (error) {
+ log('wazuh-api:getAppLogos', error.message || error);
+ return ErrorResponse(error.message || error, 3035, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response);
+ }
+
}
}
diff --git a/server/controllers/wazuh-elastic.ts b/server/controllers/wazuh-elastic.ts
index 4ef33c063a..3e43202b68 100644
--- a/server/controllers/wazuh-elastic.ts
+++ b/server/controllers/wazuh-elastic.ts
@@ -19,12 +19,14 @@ import {
} from '../integration-files/visualizations';
import { generateAlerts } from '../lib/generate-alerts/generate-alerts-script';
-import { WAZUH_MONITORING_PATTERN, WAZUH_SAMPLE_ALERT_PREFIX, WAZUH_ROLE_ADMINISTRATOR_ID, WAZUH_SAMPLE_ALERTS_INDEX_SHARDS, WAZUH_SAMPLE_ALERTS_INDEX_REPLICAS } from '../../common/constants';
+import { WAZUH_ROLE_ADMINISTRATOR_ID, WAZUH_SAMPLE_ALERTS_INDEX_SHARDS, WAZUH_SAMPLE_ALERTS_INDEX_REPLICAS } from '../../common/constants';
import jwtDecode from 'jwt-decode';
import { ManageHosts } from '../lib/manage-hosts';
-import { KibanaRequest, RequestHandlerContext, KibanaResponseFactory, SavedObject, SavedObjectsFindResponse } from 'src/core/server';
+import { OpenSearchDashboardsRequest, RequestHandlerContext, OpenSearchDashboardsResponseFactory, SavedObject, SavedObjectsFindResponse } from 'src/core/server';
import { getCookieValueByName } from '../lib/cookie';
import { WAZUH_SAMPLE_ALERTS_CATEGORIES_TYPE_ALERTS, WAZUH_SAMPLE_ALERTS_DEFAULT_NUMBER_ALERTS } from '../../common/constants'
+import { getSettingDefaultValue } from '../../common/services/settings';
+import { WAZUH_INDEXER_NAME } from '../../common/constants'
export class WazuhElasticCtrl {
wzSampleAlertsIndexPrefix: string
@@ -47,7 +49,7 @@ export class WazuhElasticCtrl {
*/
getSampleAlertPrefix(): string {
const config = getConfiguration();
- return config['alerts.sample.prefix'] || WAZUH_SAMPLE_ALERT_PREFIX;
+ return config['alerts.sample.prefix'] || getSettingDefaultValue('alerts.sample.prefix');
}
/**
@@ -57,14 +59,14 @@ export class WazuhElasticCtrl {
* @param {Object} response
* @returns {Object} template or ErrorResponse
*/
- async getTemplate(context: RequestHandlerContext, request: KibanaRequest<{ pattern: string }>, response: KibanaResponseFactory) {
+ async getTemplate(context: RequestHandlerContext, request: OpenSearchDashboardsRequest<{ pattern: string }>, response: OpenSearchDashboardsResponseFactory) {
try {
- const data = await context.core.elasticsearch.client.asInternalUser.cat.templates();
+ const data = await context.core.opensearch.client.asInternalUser.cat.templates();
const templates = data.body;
if (!templates || typeof templates !== 'string') {
throw new Error(
- 'An unknown error occurred when fetching templates from Elasticseach'
+ `An unknown error occurred when fetching templates from ${WAZUH_INDEXER_NAME}`
);
}
@@ -125,7 +127,7 @@ export class WazuhElasticCtrl {
} catch (error) {
log('wazuh-elastic:getTemplate', error.message || error);
return ErrorResponse(
- `Could not retrieve templates from Elasticsearch due to ${error.message ||
+ `Could not retrieve templates from ${WAZUH_INDEXER_NAME} due to ${error.message ||
error}`,
4002,
500,
@@ -141,41 +143,6 @@ export class WazuhElasticCtrl {
* @param {Object} response
* @returns {Object} status obj or ErrorResponse
*/
- async checkPattern(context: RequestHandlerContext, request: KibanaRequest<{ pattern: string }>, response: KibanaResponseFactory) {
- try {
- const data = await context.core.savedObjects.client.find>({ type: 'index-pattern' });
-
- const existsIndexPattern = data.saved_objects.find(
- item => item.attributes.title === request.params.pattern
- );
- log(
- 'wazuh-elastic:checkPattern',
- `Index pattern found: ${existsIndexPattern ? existsIndexPattern.attributes.title : 'no'}`,
- 'debug'
- );
- return existsIndexPattern
- ? response.ok({
- body: { statusCode: 200, status: true, data: 'Index pattern found' }
- })
- : response.ok({
- body: {
- statusCode: 500,
- status: false,
- error: 10020,
- message: 'Index pattern not found'
- }
- });
- } catch (error) {
- log('wazuh-elastic:checkPattern', error.message || error);
- return ErrorResponse(
- `Something went wrong retrieving index-patterns from Elasticsearch due to ${error.message ||
- error}`,
- 4003,
- 500,
- response
- );
- }
- }
/**
* This get the fields keys
@@ -184,7 +151,7 @@ export class WazuhElasticCtrl {
* @param {Object} response
* @returns {Array} fields or ErrorResponse
*/
- async getFieldTop(context: RequestHandlerContext, request: KibanaRequest<{ mode: string, cluster: string, field: string, pattern: string }, { agentsList: string }>, response: KibanaResponseFactory) {
+ async getFieldTop(context: RequestHandlerContext, request: OpenSearchDashboardsRequest<{ mode: string, cluster: string, field: string, pattern: string }, { agentsList: string }>, response: OpenSearchDashboardsResponseFactory) {
try {
// Top field payload
let payload = {
@@ -238,7 +205,7 @@ export class WazuhElasticCtrl {
);
payload.aggs['2'].terms.field = request.params.field;
- const data = await context.core.elasticsearch.client.asCurrentUser.search({
+ const data = await context.core.opensearch.client.asCurrentUser.search({
size: 1,
index: request.params.pattern,
body: payload
@@ -275,7 +242,7 @@ export class WazuhElasticCtrl {
let results = false,
forbidden = false;
try {
- results = await context.core.elasticsearch.client.asCurrentUser.search({
+ results = await context.core.opensearch.client.asCurrentUser.search({
index: item.title
});
} catch (error) {
@@ -323,7 +290,7 @@ export class WazuhElasticCtrl {
* @param {Object} reply
* @returns {String}
*/
- async getCurrentPlatform(context: RequestHandlerContext, request: KibanaRequest<{ user: string }>, response: KibanaResponseFactory) {
+ async getCurrentPlatform(context: RequestHandlerContext, request: OpenSearchDashboardsRequest<{ user: string }>, response: OpenSearchDashboardsResponseFactory) {
try {
return response.ok({
body: {
@@ -345,7 +312,7 @@ export class WazuhElasticCtrl {
try {
const config = getConfiguration();
let monitoringPattern =
- (config || {})['wazuh.monitoring.pattern'] || WAZUH_MONITORING_PATTERN;
+ (config || {})['wazuh.monitoring.pattern'] || getSettingDefaultValue('wazuh.monitoring.pattern');
log(
'wazuh-elastic:buildVisualizationsRaw',
`Building ${app_objects.length} visualizations`,
@@ -514,7 +481,7 @@ export class WazuhElasticCtrl {
* @param {Object} response
* @returns {Object} vis obj or ErrorResponse
*/
- async createVis(context: RequestHandlerContext, request: KibanaRequest<{ pattern: string, tab: string }>, response: KibanaResponseFactory) {
+ async createVis(context: RequestHandlerContext, request: OpenSearchDashboardsRequest<{ pattern: string, tab: string }>, response: OpenSearchDashboardsResponseFactory) {
try {
if (
(!request.params.tab.includes('overview-') &&
@@ -538,11 +505,9 @@ export class WazuhElasticCtrl {
return response.notFound({body:{message: `Visualizations not found for ${request.params.tab}`}});
}
log('wazuh-elastic:createVis', `${tabPrefix}[${tabSufix}] with index pattern ${request.params.pattern}`, 'debug');
- const namespace = context.wazuh.plugins.spaces && context.wazuh.plugins.spaces.spacesService && context.wazuh.plugins.spaces.spacesService.getSpaceId(request);
const raw = await this.buildVisualizationsRaw(
file,
- request.params.pattern,
- namespace
+ request.params.pattern
);
return response.ok({
body: { acknowledge: true, raw: raw }
@@ -560,7 +525,7 @@ export class WazuhElasticCtrl {
* @param {Object} response
* @returns {Object} vis obj or ErrorResponse
*/
- async createClusterVis(context: RequestHandlerContext, request: KibanaRequest<{ pattern: string, tab: string }, unknown, any>, response: KibanaResponseFactory) {
+ async createClusterVis(context: RequestHandlerContext, request: OpenSearchDashboardsRequest<{ pattern: string, tab: string }, unknown, any>, response: OpenSearchDashboardsResponseFactory) {
try {
if (
!request.params.pattern ||
@@ -609,11 +574,11 @@ export class WazuhElasticCtrl {
* @param {*} response
* {alerts: [...]} or ErrorResponse
*/
- async haveSampleAlerts(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async haveSampleAlerts(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
// Check if wazuh sample alerts index exists
const results = await Promise.all(Object.keys(WAZUH_SAMPLE_ALERTS_CATEGORIES_TYPE_ALERTS)
- .map((category) => context.core.elasticsearch.client.asCurrentUser.indices.exists({
+ .map((category) => context.core.opensearch.client.asCurrentUser.indices.exists({
index: this.buildSampleIndexByCategory(category)
})));
return response.ok({
@@ -631,11 +596,11 @@ export class WazuhElasticCtrl {
* @param {*} response
* {alerts: [...]} or ErrorResponse
*/
- async haveSampleAlertsOfCategory(context: RequestHandlerContext, request: KibanaRequest<{ category: string }>, response: KibanaResponseFactory) {
+ async haveSampleAlertsOfCategory(context: RequestHandlerContext, request: OpenSearchDashboardsRequest<{ category: string }>, response: OpenSearchDashboardsResponseFactory) {
try {
const sampleAlertsIndex = this.buildSampleIndexByCategory(request.params.category);
// Check if wazuh sample alerts index exists
- const existsSampleIndex = await context.core.elasticsearch.client.asCurrentUser.indices.exists({
+ const existsSampleIndex = await context.core.opensearch.client.asCurrentUser.indices.exists({
index: sampleAlertsIndex
});
return response.ok({
@@ -668,7 +633,7 @@ export class WazuhElasticCtrl {
* @param {*} response
* {index: string, alerts: [...], count: number} or ErrorResponse
*/
- async createSampleAlerts(context: RequestHandlerContext, request: KibanaRequest<{ category: string }>, response: KibanaResponseFactory) {
+ async createSampleAlerts(context: RequestHandlerContext, request: OpenSearchDashboardsRequest<{ category: string }>, response: OpenSearchDashboardsResponseFactory) {
const sampleAlertsIndex = this.buildSampleIndexByCategory(request.params.category);
try {
@@ -707,7 +672,7 @@ export class WazuhElasticCtrl {
// Index alerts
// Check if wazuh sample alerts index exists
- const existsSampleIndex = await context.core.elasticsearch.client.asCurrentUser.indices.exists({
+ const existsSampleIndex = await context.core.opensearch.client.asCurrentUser.indices.exists({
index: sampleAlertsIndex
});
if (!existsSampleIndex.body) {
@@ -722,7 +687,7 @@ export class WazuhElasticCtrl {
}
};
- await context.core.elasticsearch.client.asCurrentUser.indices.create({
+ await context.core.opensearch.client.asCurrentUser.indices.create({
index: sampleAlertsIndex,
body: configuration
});
@@ -733,7 +698,7 @@ export class WazuhElasticCtrl {
);
}
- await context.core.elasticsearch.client.asCurrentUser.bulk({
+ await context.core.opensearch.client.asCurrentUser.bulk({
index: sampleAlertsIndex,
body: bulk
});
@@ -763,7 +728,7 @@ export class WazuhElasticCtrl {
* @param {*} response
* {result: "deleted", index: string} or ErrorResponse
*/
- async deleteSampleAlerts(context: RequestHandlerContext, request: KibanaRequest<{ category: string }>, response: KibanaResponseFactory) {
+ async deleteSampleAlerts(context: RequestHandlerContext, request: OpenSearchDashboardsRequest<{ category: string }>, response: OpenSearchDashboardsResponseFactory) {
// Delete Wazuh sample alert index
const sampleAlertsIndex = this.buildSampleIndexByCategory(request.params.category);
@@ -792,12 +757,12 @@ export class WazuhElasticCtrl {
};
// Check if Wazuh sample alerts index exists
- const existsSampleIndex = await context.core.elasticsearch.client.asCurrentUser.indices.exists({
+ const existsSampleIndex = await context.core.opensearch.client.asCurrentUser.indices.exists({
index: sampleAlertsIndex
});
if (existsSampleIndex.body) {
// Delete Wazuh sample alerts index
- await context.core.elasticsearch.client.asCurrentUser.indices.delete({ index: sampleAlertsIndex });
+ await context.core.opensearch.client.asCurrentUser.indices.delete({ index: sampleAlertsIndex });
log(
'wazuh-elastic:deleteSampleAlerts',
`Deleted ${sampleAlertsIndex} index`,
@@ -820,9 +785,9 @@ export class WazuhElasticCtrl {
}
}
- async alerts(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async alerts(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
- const data = await context.core.elasticsearch.client.asCurrentUser.search(request.body);
+ const data = await context.core.opensearch.client.asCurrentUser.search(request.body);
return response.ok({
body: data.body
});
@@ -833,11 +798,11 @@ export class WazuhElasticCtrl {
}
// Check if there are indices for Statistics
- async existStatisticsIndices(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async existStatisticsIndices(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
const config = getConfiguration();
const statisticsPattern = `${config['cron.prefix'] || 'wazuh'}-${config['cron.statistics.index.name'] || 'statistics'}*`; //TODO: replace by default as constants instead hardcoded ('wazuh' and 'statistics')
- const existIndex = await context.core.elasticsearch.client.asCurrentUser.indices.exists({
+ const existIndex = await context.core.opensearch.client.asCurrentUser.indices.exists({
index: statisticsPattern,
allow_no_indices: false
});
@@ -850,17 +815,6 @@ export class WazuhElasticCtrl {
}
}
- async usingCredentials(context) {
- try {
- const data = await context.core.elasticsearch.client.asInternalUser.cluster.getSettings(
- { include_defaults: true }
- );
- return (((((data || {}).body || {}).defaults || {}).xpack || {}).security || {}).user !== null;
- } catch (error) {
- return Promise.reject(error);
- }
- };
-
getErrorDetails(error){
const statusCode = error?.meta?.statusCode || 500;
let errorMessage = error.message;
diff --git a/server/controllers/wazuh-hosts.ts b/server/controllers/wazuh-hosts.ts
index 289370479a..9d6a1d1779 100644
--- a/server/controllers/wazuh-hosts.ts
+++ b/server/controllers/wazuh-hosts.ts
@@ -10,7 +10,11 @@
* Find more information about this on the LICENSE file.
*/
-import { KibanaRequest, KibanaResponseFactory, RequestHandlerContext } from 'src/core/server';
+import {
+ OpenSearchDashboardsRequest,
+ RequestHandlerContext,
+ OpenSearchDashboardsResponseFactory,
+} from 'src/core/server';
import {
PLUGIN_PLATFORM_INSTALLATION_USER,
PLUGIN_PLATFORM_INSTALLATION_USER_GROUP,
@@ -38,7 +42,7 @@ export class WazuhHostsCtrl {
* @param {Object} response
* API entries or ErrorResponse
*/
- async getHostsEntries(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async getHostsEntries(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
const removePassword = true;
const hosts = await this.manageHosts.getHosts();
@@ -96,7 +100,7 @@ export class WazuhHostsCtrl {
* @param {Object} response
* Status response or ErrorResponse
*/
- async updateClusterInfo(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async updateClusterInfo(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
const { id } = request.params;
const { cluster_info } = request.body;
@@ -126,7 +130,7 @@ export class WazuhHostsCtrl {
* @param {Object} request
* @param {Object} response
*/
- async removeOrphanEntries(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async removeOrphanEntries(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
const { entries } = request.body;
log('wazuh-hosts:cleanRegistry', 'Cleaning registry', 'debug');
diff --git a/server/controllers/wazuh-reporting-security-endpoint-handler.test.ts b/server/controllers/wazuh-reporting-security-endpoint-handler.test.ts
index 634b04192f..5e0c8c4e15 100644
--- a/server/controllers/wazuh-reporting-security-endpoint-handler.test.ts
+++ b/server/controllers/wazuh-reporting-security-endpoint-handler.test.ts
@@ -6,6 +6,11 @@ jest.mock('../lib/logger', () => ({
log: jest.fn()
}));
+jest.mock('../lib/reporting/extended-information', () => ({
+ extendedInformation: () => {},
+ buildAgentsTable: () => {}
+}));
+
jest.mock('../lib/reporting/printer', () => {
class ReportPrinterMock {
constructor() { }
@@ -143,16 +148,15 @@ describe('[security] POST /reports', () => {
it.each`
titleTest | username | moduleID | valid
- ${'Get report'} | ${'admin'} | ${'general'} | ${true}
+ ${'Create report'} | ${'admin'} | ${'general'} | ${true}
${'Endpoint protected'} | ${'admin'} | ${'../general'} | ${false}
- ${'Get report'} | ${'../../etc'} | ${'general'} | ${true}
+ ${'Create report'} | ${'../../etc'} | ${'general'} | ${true}
${'Endpoint protected'} | ${'../../etc'} | ${'../general'} | ${false}
`(`$titleTest: POST /reports/modules/$moduleID
username: $username
valid: $valid`, async ({ username, moduleID, valid }) => {
jest.spyOn(endpointController, 'renderHeader').mockImplementation(() => true);
jest.spyOn(endpointController, 'sanitizeKibanaFilters').mockImplementation(() => [false, false]);
- jest.spyOn(endpointController, 'extendedInformation').mockImplementation(() => true);
const mockRequest = {
body: {
diff --git a/server/controllers/wazuh-reporting-security-endpoint-parameters-validation.test.ts b/server/controllers/wazuh-reporting-security-endpoint-parameters-validation.test.ts
index 55b33257b7..edd829d9fa 100644
--- a/server/controllers/wazuh-reporting-security-endpoint-parameters-validation.test.ts
+++ b/server/controllers/wazuh-reporting-security-endpoint-parameters-validation.test.ts
@@ -1,7 +1,7 @@
import { Router } from '../../../../src/core/server/http/router/router';
import { HttpServer } from '../../../../src/core/server/http/http_server';
import { loggingSystemMock } from '../../../../src/core/server/logging/logging_system.mock';
-import { ByteSizeValue } from '@kbn/config-schema';
+import { ByteSizeValue } from '@osd/config-schema';
import supertest from 'supertest';
import { WazuhReportingRoutes } from '../routes/wazuh-reporting';
import md5 from 'md5';
diff --git a/server/controllers/wazuh-reporting.ts b/server/controllers/wazuh-reporting.ts
index 6fde591779..51cd76ea6f 100644
--- a/server/controllers/wazuh-reporting.ts
+++ b/server/controllers/wazuh-reporting.ts
@@ -14,43 +14,35 @@ import fs from 'fs';
import { WAZUH_MODULES } from '../../common/wazuh-modules';
import * as TimSort from 'timsort';
import { ErrorResponse } from '../lib/error-response';
-import * as VulnerabilityRequest from '../lib/reporting/vulnerability-request';
-import * as OverviewRequest from '../lib/reporting/overview-request';
-import * as RootcheckRequest from '../lib/reporting/rootcheck-request';
-import * as PCIRequest from '../lib/reporting/pci-request';
-import * as GDPRRequest from '../lib/reporting/gdpr-request';
-import * as TSCRequest from '../lib/reporting/tsc-request';
-import * as AuditRequest from '../lib/reporting/audit-request';
-import * as SyscheckRequest from '../lib/reporting/syscheck-request';
-import PCI from '../integration-files/pci-requirements-pdfmake';
-import GDPR from '../integration-files/gdpr-requirements-pdfmake';
-import TSC from '../integration-files/tsc-requirements-pdfmake';
import ProcessEquivalence from '../lib/process-state-equivalence';
import { KeyEquivalence } from '../../common/csv-key-equivalence';
import { AgentConfiguration } from '../lib/reporting/agent-configuration';
-import { KibanaRequest, RequestHandlerContext, KibanaResponseFactory } from 'src/core/server';
+import { OpenSearchDashboardsRequest, RequestHandlerContext, OpenSearchDashboardsResponseFactory } from 'src/core/server';
+import { extendedInformation, buildAgentsTable } from '../lib/reporting/extended-information';
import { ReportPrinter } from '../lib/reporting/printer';
import { log } from '../lib/logger';
import {
- WAZUH_ALERTS_PATTERN,
WAZUH_DATA_DOWNLOADS_DIRECTORY_PATH,
WAZUH_DATA_DOWNLOADS_REPORTS_DIRECTORY_PATH,
AUTHORIZED_AGENTS,
API_NAME_AGENT_STATUS,
} from '../../common/constants';
import { createDirectoryIfNotExists, createDataDirectoryIfNotExists } from '../lib/filesystem';
-import moment from 'moment';
import { agentStatusLabelByAgentStatus } from '../../common/services/wz_agent_status';
+interface AgentsFilter {
+ query: any;
+ agentsText: string;
+}
+
export class WazuhReportingCtrl {
constructor() {}
-
/**
* This do format to filters
* @param {String} filters E.g: cluster.name: wazuh AND rule.groups: vulnerability
* @param {String} searchBar search term
*/
- private sanitizeKibanaFilters(filters: any, searchBar?: string): [string, string] {
+ private sanitizeKibanaFilters(filters: any, searchBar?: string): [string, AgentsFilter] {
log('reporting:sanitizeKibanaFilters', `Started to sanitize filters`, 'info');
log(
'reporting:sanitizeKibanaFilters',
@@ -59,12 +51,14 @@ export class WazuhReportingCtrl {
);
let str = '';
- const agentsFilter: any = [];
+ const agentsFilter: AgentsFilter = { query: {}, agentsText: '' };
+ const agentsList: string[] = [];
//separate agents filter
filters = filters.filter((filter) => {
if (filter.meta.controlledBy === AUTHORIZED_AGENTS) {
- agentsFilter.push(filter);
+ agentsFilter.query = filter.query;
+ agentsList.push(filter);
return false;
}
return filter;
@@ -79,9 +73,9 @@ export class WazuhReportingCtrl {
str += `${
type === 'range'
? `${params.gte}-${params.lt}`
- : type === 'phrases'
- ? '(' + params.join(" OR ") + ')'
- : type === 'exists'
+ : type === 'phrases'
+ ? '(' + params.join(" OR ") + ')'
+ : type === 'exists'
? '*'
: !!value
? value
@@ -94,15 +88,15 @@ export class WazuhReportingCtrl {
str += ` AND (${ searchBar})`;
}
- const agentsFilterStr = agentsFilter.map((filter) => filter.meta.value).join(',');
+ agentsFilter.agentsText = agentsList.map((filter) => filter.meta.value).join(',');
log(
'reporting:sanitizeKibanaFilters',
- `str: ${str}, agentsFilterStr: ${agentsFilterStr}`,
+ `str: ${str}, agentsFilterStr: ${agentsFilter.agentsText}`,
'debug'
);
- return [str, agentsFilterStr];
+ return [str, agentsFilter];
}
/**
@@ -141,7 +135,7 @@ export class WazuhReportingCtrl {
}
if (isAgents && typeof isAgents === 'object') {
- await this.buildAgentsTable(
+ await buildAgentsTable(
context,
printer,
isAgents,
@@ -164,7 +158,7 @@ export class WazuhReportingCtrl {
style: 'standard',
});
}
- await this.buildAgentsTable(context, printer, [isAgents], apiId);
+ await buildAgentsTable(context, printer, [isAgents], apiId);
if (agentData && agentData.group) {
const agentGroups = agentData.group.join(', ');
@@ -186,846 +180,6 @@ export class WazuhReportingCtrl {
}
}
- /**
- * This build the agents table
- * @param {Array} ids ids of agents
- * @param {String} apiId API id
- */
- private async buildAgentsTable(context, printer: ReportPrinter, agentIDs: string[], apiId: string, groupID: string = '') {
- const dateFormat = await context.core.uiSettings.client.get('dateFormat');
- if ((!agentIDs || !agentIDs.length) && !groupID) return;
- log('reporting:buildAgentsTable', `${agentIDs.length} agents for API ${apiId}`, 'info');
- try {
- let agentsData = [];
- if (groupID) {
- let totalAgentsInGroup = null;
- do{
- const { data: { data: { affected_items, total_affected_items } } } = await context.wazuh.api.client.asCurrentUser.request(
- 'GET',
- `/groups/${groupID}/agents`,
- {
- params: {
- offset: agentsData.length,
- select: 'dateAdd,id,ip,lastKeepAlive,manager,name,os.name,os.version,version',
- }
- },
- { apiHostID: apiId }
- );
- !totalAgentsInGroup && (totalAgentsInGroup = total_affected_items);
- agentsData = [...agentsData, ...affected_items];
- }while(agentsData.length < totalAgentsInGroup);
- } else {
- for (const agentID of agentIDs) {
- try {
- const { data: { data: { affected_items: [agent] } } } = await context.wazuh.api.client.asCurrentUser.request(
- 'GET',
- `/agents`,
- {
- params: {
- q: `id=${agentID}`,
- select: 'dateAdd,id,ip,lastKeepAlive,manager,name,os.name,os.version,version',
- }
- },
- { apiHostID: apiId }
- );
- agentsData.push(agent);
- } catch (error) {
- log(
- 'reporting:buildAgentsTable',
- `Skip agent due to: ${error.message || error}`,
- 'debug'
- );
- }
- }
- }
-
- if(agentsData.length){
- // Print a table with agent/s information
- printer.addSimpleTable({
- columns: [
- { id: 'id', label: 'ID' },
- { id: 'name', label: 'Name' },
- { id: 'ip', label: 'IP' },
- { id: 'version', label: 'Version' },
- { id: 'manager', label: 'Manager' },
- { id: 'os', label: 'OS' },
- { id: 'dateAdd', label: 'Registration date' },
- { id: 'lastKeepAlive', label: 'Last keep alive' },
- ],
- items: agentsData.map((agent) => {
- return {
- ...agent,
- os: (agent.os && agent.os.name && agent.os.version) ? `${agent.os.name} ${agent.os.version}` : '',
- lastKeepAlive: moment(agent.lastKeepAlive).format(dateFormat),
- dateAdd: moment(agent.dateAdd).format(dateFormat)
- }
- }),
- });
- }else if(!agentsData.length && groupID){
- // For group reports when there is no agents in the group
- printer.addContent({
- text: 'There are no agents in this group.',
- style: { fontSize: 12, color: '#000' },
- });
- }
-
- } catch (error) {
- log('reporting:buildAgentsTable', error.message || error);
- return Promise.reject(error);
- }
- }
-
- /**
- * This load more information
- * @param {*} context Endpoint context
- * @param {*} printer printer instance
- * @param {String} section section target
- * @param {Object} tab tab target
- * @param {String} apiId ID of API
- * @param {Number} from Timestamp (ms) from
- * @param {Number} to Timestamp (ms) to
- * @param {String} filters E.g: cluster.name: wazuh AND rule.groups: vulnerability
- * @param {String} pattern
- * @param {Object} agent agent target
- * @returns {Object} Extended information
- */
- private async extendedInformation(
- context,
- printer,
- section,
- tab,
- apiId,
- from,
- to,
- filters,
- pattern = WAZUH_ALERTS_PATTERN,
- agent = null
- ) {
- try {
- log(
- 'reporting:extendedInformation',
- `Section ${section} and tab ${tab}, API is ${apiId}. From ${from} to ${to}. Filters ${filters}. Index pattern ${pattern}`,
- 'info'
- );
- if (section === 'agents' && !agent) {
- throw new Error('Reporting for specific agent needs an agent ID in order to work properly');
- }
-
- const agents = await context.wazuh.api.client.asCurrentUser.request(
- 'GET',
- '/agents',
- { params: { limit: 1 } },
- { apiHostID: apiId }
- );
-
- const totalAgents = agents.data.data.total_affected_items;
-
- if (section === 'overview' && tab === 'vuls') {
- log(
- 'reporting:extendedInformation',
- 'Fetching overview vulnerability detector metrics',
- 'debug'
- );
- const vulnerabilitiesLevels = ['Low', 'Medium', 'High', 'Critical'];
-
- const vulnerabilitiesResponsesCount = (
- await Promise.all(
- vulnerabilitiesLevels.map(async (vulnerabilitiesLevel) => {
- try {
- const count = await VulnerabilityRequest.uniqueSeverityCount(
- context,
- from,
- to,
- vulnerabilitiesLevel,
- filters,
- pattern
- );
- return count
- ? `${count} of ${totalAgents} agents have ${vulnerabilitiesLevel.toLocaleLowerCase()} vulnerabilities.`
- : undefined;
- } catch (error) {}
- })
- )
- ).filter((vulnerabilitiesResponse) => vulnerabilitiesResponse);
-
- printer.addList({
- title: { text: 'Summary', style: 'h2' },
- list: vulnerabilitiesResponsesCount,
- });
-
- log(
- 'reporting:extendedInformation',
- 'Fetching overview vulnerability detector top 3 agents by category',
- 'debug'
- );
- const lowRank = await VulnerabilityRequest.topAgentCount(
- context,
- from,
- to,
- 'Low',
- filters,
- pattern
- );
- const mediumRank = await VulnerabilityRequest.topAgentCount(
- context,
- from,
- to,
- 'Medium',
- filters,
- pattern
- );
- const highRank = await VulnerabilityRequest.topAgentCount(
- context,
- from,
- to,
- 'High',
- filters,
- pattern
- );
- const criticalRank = await VulnerabilityRequest.topAgentCount(
- context,
- from,
- to,
- 'Critical',
- filters,
- pattern
- );
- log(
- 'reporting:extendedInformation',
- 'Adding overview vulnerability detector top 3 agents by category',
- 'debug'
- );
- if (criticalRank && criticalRank.length) {
- printer.addContentWithNewLine({
- text: 'Top 3 agents with critical severity vulnerabilities',
- style: 'h3',
- });
- await this.buildAgentsTable(context, printer, criticalRank, apiId);
- printer.addNewLine();
- }
-
- if (highRank && highRank.length) {
- printer.addContentWithNewLine({
- text: 'Top 3 agents with high severity vulnerabilities',
- style: 'h3',
- });
- await this.buildAgentsTable(context, printer, highRank, apiId);
- printer.addNewLine();
- }
-
- if (mediumRank && mediumRank.length) {
- printer.addContentWithNewLine({
- text: 'Top 3 agents with medium severity vulnerabilities',
- style: 'h3',
- });
- await this.buildAgentsTable(context, printer, mediumRank, apiId);
- printer.addNewLine();
- }
-
- if (lowRank && lowRank.length) {
- printer.addContentWithNewLine({
- text: 'Top 3 agents with low severity vulnerabilities',
- style: 'h3',
- });
- await this.buildAgentsTable(context, printer, lowRank, apiId);
- printer.addNewLine();
- }
-
- log(
- 'reporting:extendedInformation',
- 'Fetching overview vulnerability detector top 3 CVEs',
- 'debug'
- );
- const cveRank = await VulnerabilityRequest.topCVECount(context, from, to, filters, pattern);
- log(
- 'reporting:extendedInformation',
- 'Adding overview vulnerability detector top 3 CVEs',
- 'debug'
- );
- if (cveRank && cveRank.length) {
- printer.addSimpleTable({
- title: { text: 'Top 3 CVE', style: 'h2' },
- columns: [
- { id: 'top', label: 'Top' },
- { id: 'cve', label: 'CVE' },
- ],
- items: cveRank.map((item) => ({ top: cveRank.indexOf(item) + 1, cve: item })),
- });
- }
- }
-
- if (section === 'overview' && tab === 'general') {
- log('reporting:extendedInformation', 'Fetching top 3 agents with level 15 alerts', 'debug');
-
- const level15Rank = await OverviewRequest.topLevel15(context, from, to, filters, pattern);
-
- log('reporting:extendedInformation', 'Adding top 3 agents with level 15 alerts', 'debug');
- if (level15Rank.length) {
- printer.addContent({
- text: 'Top 3 agents with level 15 alerts',
- style: 'h2',
- });
- await this.buildAgentsTable(context, printer, level15Rank, apiId);
- }
- }
-
- if (section === 'overview' && tab === 'pm') {
- log('reporting:extendedInformation', 'Fetching most common rootkits', 'debug');
- const top5RootkitsRank = await RootcheckRequest.top5RootkitsDetected(
- context,
- from,
- to,
- filters,
- pattern
- );
- log('reporting:extendedInformation', 'Adding most common rootkits', 'debug');
- if (top5RootkitsRank && top5RootkitsRank.length) {
- printer
- .addContentWithNewLine({
- text: 'Most common rootkits found among your agents',
- style: 'h2',
- })
- .addContentWithNewLine({
- text:
- 'Rootkits are a set of software tools that enable an unauthorized user to gain control of a computer system without being detected.',
- style: 'standard',
- })
- .addSimpleTable({
- items: top5RootkitsRank.map((item) => {
- return { top: top5RootkitsRank.indexOf(item) + 1, name: item };
- }),
- columns: [
- { id: 'top', label: 'Top' },
- { id: 'name', label: 'Rootkit' },
- ],
- });
- }
- log('reporting:extendedInformation', 'Fetching hidden pids', 'debug');
- const hiddenPids = await RootcheckRequest.agentsWithHiddenPids(
- context,
- from,
- to,
- filters,
- pattern
- );
- hiddenPids &&
- printer.addContent({
- text: `${hiddenPids} of ${totalAgents} agents have hidden processes`,
- style: 'h3',
- });
- !hiddenPids &&
- printer.addContentWithNewLine({
- text: `No agents have hidden processes`,
- style: 'h3',
- });
-
- const hiddenPorts = await RootcheckRequest.agentsWithHiddenPorts(
- context,
- from,
- to,
- filters,
- pattern
- );
- hiddenPorts &&
- printer.addContent({
- text: `${hiddenPorts} of ${totalAgents} agents have hidden ports`,
- style: 'h3',
- });
- !hiddenPorts &&
- printer.addContent({
- text: `No agents have hidden ports`,
- style: 'h3',
- });
- printer.addNewLine();
- }
-
- if (['overview', 'agents'].includes(section) && tab === 'pci') {
- log('reporting:extendedInformation', 'Fetching top PCI DSS requirements', 'debug');
- const topPciRequirements = await PCIRequest.topPCIRequirements(
- context,
- from,
- to,
- filters,
- pattern
- );
- printer.addContentWithNewLine({
- text: 'Most common PCI DSS requirements alerts found',
- style: 'h2',
- });
- for (const item of topPciRequirements) {
- const rules = await PCIRequest.getRulesByRequirement(
- context,
- from,
- to,
- filters,
- item,
- pattern
- );
- printer.addContentWithNewLine({ text: `Requirement ${item}`, style: 'h3' });
-
- if (PCI[item]) {
- const content =
- typeof PCI[item] === 'string' ? { text: PCI[item], style: 'standard' } : PCI[item];
- printer.addContentWithNewLine(content);
- }
-
- rules &&
- rules.length &&
- printer.addSimpleTable({
- columns: [
- { id: 'ruleID', label: 'Rule ID' },
- { id: 'ruleDescription', label: 'Description' },
- ],
- items: rules,
- title: `Top rules for ${item} requirement`,
- });
- }
- }
-
- if (['overview', 'agents'].includes(section) && tab === 'tsc') {
- log('reporting:extendedInformation', 'Fetching top TSC requirements', 'debug');
- const topTSCRequirements = await TSCRequest.topTSCRequirements(
- context,
- from,
- to,
- filters,
- pattern
- );
- printer.addContentWithNewLine({
- text: 'Most common TSC requirements alerts found',
- style: 'h2',
- });
- for (const item of topTSCRequirements) {
- const rules = await TSCRequest.getRulesByRequirement(
- context,
- from,
- to,
- filters,
- item,
- pattern
- );
- printer.addContentWithNewLine({ text: `Requirement ${item}`, style: 'h3' });
-
- if (TSC[item]) {
- const content =
- typeof TSC[item] === 'string' ? { text: TSC[item], style: 'standard' } : TSC[item];
- printer.addContentWithNewLine(content);
- }
-
- rules &&
- rules.length &&
- printer.addSimpleTable({
- columns: [
- { id: 'ruleID', label: 'Rule ID' },
- { id: 'ruleDescription', label: 'Description' },
- ],
- items: rules,
- title: `Top rules for ${item} requirement`,
- });
- }
- }
-
- if (['overview', 'agents'].includes(section) && tab === 'gdpr') {
- log('reporting:extendedInformation', 'Fetching top GDPR requirements', 'debug');
- const topGdprRequirements = await GDPRRequest.topGDPRRequirements(
- context,
- from,
- to,
- filters,
- pattern
- );
- printer.addContentWithNewLine({
- text: 'Most common GDPR requirements alerts found',
- style: 'h2',
- });
- for (const item of topGdprRequirements) {
- const rules = await GDPRRequest.getRulesByRequirement(
- context,
- from,
- to,
- filters,
- item,
- pattern
- );
- printer.addContentWithNewLine({ text: `Requirement ${item}`, style: 'h3' });
-
- if (GDPR && GDPR[item]) {
- const content =
- typeof GDPR[item] === 'string' ? { text: GDPR[item], style: 'standard' } : GDPR[item];
- printer.addContentWithNewLine(content);
- }
-
- rules &&
- rules.length &&
- printer.addSimpleTable({
- columns: [
- { id: 'ruleID', label: 'Rule ID' },
- { id: 'ruleDescription', label: 'Description' },
- ],
- items: rules,
- title: `Top rules for ${item} requirement`,
- });
- }
- printer.addNewLine();
- }
-
- if (section === 'overview' && tab === 'audit') {
- log(
- 'reporting:extendedInformation',
- 'Fetching agents with high number of failed sudo commands',
- 'debug'
- );
- const auditAgentsNonSuccess = await AuditRequest.getTop3AgentsSudoNonSuccessful(
- context,
- from,
- to,
- filters,
- pattern
- );
- if (auditAgentsNonSuccess && auditAgentsNonSuccess.length) {
- printer.addContent({
- text: 'Agents with high number of failed sudo commands',
- style: 'h2',
- });
- await this.buildAgentsTable(context, printer, auditAgentsNonSuccess, apiId);
- }
- const auditAgentsFailedSyscall = await AuditRequest.getTop3AgentsFailedSyscalls(
- context,
- from,
- to,
- filters,
- pattern
- );
- if (auditAgentsFailedSyscall && auditAgentsFailedSyscall.length) {
- printer.addSimpleTable({
- columns: [
- { id: 'agent', label: 'Agent ID' },
- { id: 'syscall_id', label: 'Syscall ID' },
- { id: 'syscall_syscall', label: 'Syscall' },
- ],
- items: auditAgentsFailedSyscall.map((item) => ({
- agent: item.agent,
- syscall_id: item.syscall.id,
- syscall_syscall: item.syscall.syscall,
- })),
- title: {
- text: 'Most common failing syscalls',
- style: 'h2',
- },
- });
- }
- }
-
- if (section === 'overview' && tab === 'fim') {
- log('reporting:extendedInformation', 'Fetching top 3 rules for FIM', 'debug');
- const rules = await SyscheckRequest.top3Rules(context, from, to, filters, pattern);
-
- if (rules && rules.length) {
- printer.addContentWithNewLine({ text: 'Top 3 FIM rules', style: 'h2' }).addSimpleTable({
- columns: [
- { id: 'ruleID', label: 'Rule ID' },
- { id: 'ruleDescription', label: 'Description' },
- ],
- items: rules,
- title: {
- text: 'Top 3 rules that are generating most alerts.',
- style: 'standard',
- },
- });
- }
-
- log('reporting:extendedInformation', 'Fetching top 3 agents for FIM', 'debug');
- const agents = await SyscheckRequest.top3agents(context, from, to, filters, pattern);
-
- if (agents && agents.length) {
- printer.addContentWithNewLine({
- text: 'Agents with suspicious FIM activity',
- style: 'h2',
- });
- printer.addContentWithNewLine({
- text:
- 'Top 3 agents that have most FIM alerts from level 7 to level 15. Take care about them.',
- style: 'standard',
- });
- await this.buildAgentsTable(context, printer, agents, apiId);
- }
- }
-
- if (section === 'agents' && tab === 'audit') {
- log('reporting:extendedInformation', `Fetching most common failed syscalls`, 'debug');
- const auditFailedSyscall = await AuditRequest.getTopFailedSyscalls(
- context,
- from,
- to,
- filters,
- pattern
- );
- auditFailedSyscall &&
- auditFailedSyscall.length &&
- printer.addSimpleTable({
- columns: [
- { id: 'id', label: 'id' },
- { id: 'syscall', label: 'Syscall' },
- ],
- items: auditFailedSyscall,
- title: 'Most common failing syscalls',
- });
- }
-
- if (section === 'agents' && tab === 'fim') {
- log(
- 'reporting:extendedInformation',
- `Fetching syscheck database for agent ${agent}`,
- 'debug'
- );
-
- const lastScanResponse = await context.wazuh.api.client.asCurrentUser.request(
- 'GET',
- `/syscheck/${agent}/last_scan`,
- {},
- { apiHostID: apiId }
- );
-
- if (lastScanResponse && lastScanResponse.data) {
- const lastScanData = lastScanResponse.data.data.affected_items[0];
- if (lastScanData.start && lastScanData.end) {
- printer.addContent({
- text: `Last file integrity monitoring scan was executed from ${lastScanData.start} to ${lastScanData.end}.`,
- });
- } else if (lastScanData.start) {
- printer.addContent({
- text: `File integrity monitoring scan is currently in progress for this agent (started on ${lastScanData.start}).`,
- });
- } else {
- printer.addContent({
- text: `File integrity monitoring scan is currently in progress for this agent.`,
- });
- }
- printer.addNewLine();
- }
-
- log('reporting:extendedInformation', `Fetching last 10 deleted files for FIM`, 'debug');
- const lastTenDeleted = await SyscheckRequest.lastTenDeletedFiles(
- context,
- from,
- to,
- filters,
- pattern
- );
-
- lastTenDeleted &&
- lastTenDeleted.length &&
- printer.addSimpleTable({
- columns: [
- { id: 'path', label: 'Path' },
- { id: 'date', label: 'Date' },
- ],
- items: lastTenDeleted,
- title: 'Last 10 deleted files',
- });
-
- log('reporting:extendedInformation', `Fetching last 10 modified files`, 'debug');
- const lastTenModified = await SyscheckRequest.lastTenModifiedFiles(
- context,
- from,
- to,
- filters,
- pattern
- );
-
- lastTenModified &&
- lastTenModified.length &&
- printer.addSimpleTable({
- columns: [
- { id: 'path', label: 'Path' },
- { id: 'date', label: 'Date' },
- ],
- items: lastTenModified,
- title: 'Last 10 modified files',
- });
- }
-
- if (section === 'agents' && tab === 'syscollector') {
- log(
- 'reporting:extendedInformation',
- `Fetching hardware information for agent ${agent}`,
- 'debug'
- );
- const requestsSyscollectorLists = [
- {
- endpoint: `/syscollector/${agent}/hardware`,
- loggerMessage: `Fetching Hardware information for agent ${agent}`,
- list: {
- title: { text: 'Hardware information', style: 'h2' },
- },
- mapResponse: (hardware) => [
- hardware.cpu && hardware.cpu.cores && `${hardware.cpu.cores} cores`,
- hardware.cpu && hardware.cpu.name,
- hardware.ram &&
- hardware.ram.total &&
- `${Number(hardware.ram.total / 1024 / 1024).toFixed(2)}GB RAM`,
- ],
- },
- {
- endpoint: `/syscollector/${agent}/os`,
- loggerMessage: `Fetching OS information for agent ${agent}`,
- list: {
- title: { text: 'OS information', style: 'h2' },
- },
- mapResponse: (osData) => [
- osData.sysname,
- osData.version,
- osData.architecture,
- osData.release,
- osData.os &&
- osData.os.name &&
- osData.os.version &&
- `${osData.os.name} ${osData.os.version}`,
- ],
- },
- ];
-
- const syscollectorLists = await Promise.all(
- requestsSyscollectorLists.map(async (requestSyscollector) => {
- try {
- log('reporting:extendedInformation', requestSyscollector.loggerMessage, 'debug');
- const responseSyscollector = await context.wazuh.api.client.asCurrentUser.request(
- 'GET',
- requestSyscollector.endpoint,
- {},
- { apiHostID: apiId }
- );
- const [data] =
- (responseSyscollector &&
- responseSyscollector.data &&
- responseSyscollector.data.data &&
- responseSyscollector.data.data.affected_items) ||
- [];
- if (data) {
- return {
- ...requestSyscollector.list,
- list: requestSyscollector.mapResponse(data),
- };
- }
- } catch (error) {
- log('reporting:extendedInformation', error.message || error);
- }
- })
- );
-
- if (syscollectorLists) {
- syscollectorLists
- .filter((syscollectorList) => syscollectorList)
- .forEach((syscollectorList) => printer.addList(syscollectorList));
- }
-
- const vulnerabilitiesRequests = ['Critical', 'High'];
-
- const vulnerabilitiesResponsesItems = (
- await Promise.all(
- vulnerabilitiesRequests.map(async (vulnerabilitiesLevel) => {
- try {
- log(
- 'reporting:extendedInformation',
- `Fetching top ${vulnerabilitiesLevel} packages`,
- 'debug'
- );
-
- return await VulnerabilityRequest.topPackages(
- context,
- from,
- to,
- vulnerabilitiesLevel,
- filters,
- pattern
- );
- } catch (error) {
- log('reporting:extendedInformation', error.message || error);
- }
- })
- )
- )
- .filter((vulnerabilitiesResponse) => vulnerabilitiesResponse)
- .flat();
-
- if (vulnerabilitiesResponsesItems && vulnerabilitiesResponsesItems.length) {
- printer.addSimpleTable({
- title: { text: 'Vulnerable packages found (last 24 hours)', style: 'h2' },
- columns: [
- { id: 'package', label: 'Package' },
- { id: 'severity', label: 'Severity' },
- ],
- items: vulnerabilitiesResponsesItems,
- });
- }
- }
-
- if (section === 'agents' && tab === 'vuls') {
- const topCriticalPackages = await VulnerabilityRequest.topPackagesWithCVE(
- context,
- from,
- to,
- 'Critical',
- filters,
- pattern
- );
- if (topCriticalPackages && topCriticalPackages.length) {
- printer.addContentWithNewLine({ text: 'Critical severity', style: 'h2' });
- printer.addContentWithNewLine({
- text:
- 'These vulnerabilties are critical, please review your agent. Click on each link to read more about each found vulnerability.',
- style: 'standard',
- });
- const customul = [];
- for (const critical of topCriticalPackages) {
- customul.push({ text: critical.package, style: 'standard' });
- customul.push({
- ul: critical.references.map((item) => ({
- text: item.substring(0, 80) + '...',
- link: item,
- color: '#1EA5C8',
- })),
- });
- }
- printer.addContentWithNewLine({ ul: customul });
- }
-
- const topHighPackages = await VulnerabilityRequest.topPackagesWithCVE(
- context,
- from,
- to,
- 'High',
- filters,
- pattern
- );
- if (topHighPackages && topHighPackages.length) {
- printer.addContentWithNewLine({ text: 'High severity', style: 'h2' });
- printer.addContentWithNewLine({
- text: 'Click on each link to read more about each found vulnerability.',
- style: 'standard',
- });
- const customul = [];
- for (const critical of topHighPackages) {
- customul.push({ text: critical.package, style: 'standard' });
- customul.push({
- ul: critical.references.map((item) => ({
- text: item,
- color: '#1EA5C8',
- })),
- });
- }
- customul && customul.length && printer.addContent({ ul: customul });
- printer.addNewLine();
- }
- }
-
- return false;
- } catch (error) {
- log('reporting:extendedInformation', error.message || error);
- return Promise.reject(error);
- }
- }
-
private getConfigRows(data, labels) {
log('reporting:getConfigRows', `Building configuration rows`, 'info');
const result = [];
@@ -1126,8 +280,8 @@ export class WazuhReportingCtrl {
*/
createReportsModules = this.checkReportsUserDirectoryIsValidRouteDecorator(async (
context: RequestHandlerContext,
- request: KibanaRequest,
- response: KibanaResponseFactory
+ request: OpenSearchDashboardsRequest,
+ response: OpenSearchDashboardsResponseFactory
) => {
try {
log('reporting:createReportsModules', `Report started`, 'info');
@@ -1145,6 +299,7 @@ export class WazuhReportingCtrl {
} = request.body;
const { moduleID } = request.params;
const { from, to } = time || {};
+ let additionalTables = [];
// Init
const printer = new ReportPrinter();
@@ -1157,14 +312,14 @@ export class WazuhReportingCtrl {
const [sanitizedFilters, agentsFilter] = filters
? this.sanitizeKibanaFilters(filters, searchBar)
- : [false, false];
+ : [false, null];
if (time && sanitizedFilters) {
printer.addTimeRangeAndFilters(from, to, sanitizedFilters, browserTimezone);
}
if (time) {
- await this.extendedInformation(
+ additionalTables = await extendedInformation(
context,
printer,
section,
@@ -1173,6 +328,7 @@ export class WazuhReportingCtrl {
new Date(from).getTime(),
new Date(to).getTime(),
sanitizedFilters,
+ agentsFilter,
indexPatternTitle,
agents
);
@@ -1181,12 +337,12 @@ export class WazuhReportingCtrl {
printer.addVisualizations(array, agents, moduleID);
if (tables) {
- printer.addTables(tables);
+ printer.addTables([...tables, ...(additionalTables || [])]);
}
//add authorized agents
- if (agentsFilter) {
- printer.addAgentsFilters(agentsFilter);
+ if (agentsFilter?.agentsText) {
+ printer.addAgentsFilters(agentsFilter.agentsText);
}
await printer.print(context.wazuhEndpointParams.pathFilename);
@@ -1211,8 +367,8 @@ export class WazuhReportingCtrl {
*/
createReportsGroups = this.checkReportsUserDirectoryIsValidRouteDecorator(async(
context: RequestHandlerContext,
- request: KibanaRequest,
- response: KibanaResponseFactory
+ request: OpenSearchDashboardsRequest,
+ response: OpenSearchDashboardsResponseFactory
) => {
try {
log('reporting:createReportsGroups', `Report started`, 'info');
@@ -1468,8 +624,8 @@ export class WazuhReportingCtrl {
*/
createReportsAgentsConfiguration = this.checkReportsUserDirectoryIsValidRouteDecorator( async (
context: RequestHandlerContext,
- request: KibanaRequest,
- response: KibanaResponseFactory
+ request: OpenSearchDashboardsRequest,
+ response: OpenSearchDashboardsResponseFactory
) => {
try {
log('reporting:createReportsAgentsConfiguration', `Report started`, 'info');
@@ -1715,8 +871,8 @@ export class WazuhReportingCtrl {
*/
createReportsAgentsInventory = this.checkReportsUserDirectoryIsValidRouteDecorator( async (
context: RequestHandlerContext,
- request: KibanaRequest,
- response: KibanaResponseFactory
+ request: OpenSearchDashboardsRequest,
+ response: OpenSearchDashboardsResponseFactory
) => {
try {
log('reporting:createReportsAgentsInventory', `Report started`, 'info');
@@ -1733,7 +889,7 @@ export class WazuhReportingCtrl {
createDirectoryIfNotExists(path.join(WAZUH_DATA_DOWNLOADS_REPORTS_DIRECTORY_PATH, hashUsername));
log('reporting:createReportsAgentsInventory', `Syscollector report`, 'debug');
- const sanitizedFilters = filters ? this.sanitizeKibanaFilters(filters, searchBar) : false;
+ const [sanitizedFilters, agentsFilter] = filters ? this.sanitizeKibanaFilters(filters, searchBar) : [false, null];
// Get the agent OS
let agentOs = '';
@@ -1756,7 +912,7 @@ export class WazuhReportingCtrl {
});
// Add table with the agent info
- await this.buildAgentsTable(context, printer, [agentID], apiId);
+ await buildAgentsTable(context, printer, [agentID], apiId);
// Get syscollector packages and processes
const agentRequestsInventory = [
@@ -1813,14 +969,14 @@ export class WazuhReportingCtrl {
columns:
agentOs === 'windows'
? [
- { id: 'local_ip', label: 'Local IP' },
+ { id: 'local_ip', label: 'Local IP address' },
{ id: 'local_port', label: 'Local port' },
{ id: 'process', label: 'Process' },
{ id: 'state', label: 'State' },
{ id: 'protocol', label: 'Protocol' },
]
: [
- { id: 'local_ip', label: 'Local IP' },
+ { id: 'local_ip', label: 'Local IP address' },
{ id: 'local_port', label: 'Local port' },
{ id: 'state', label: 'State' },
{ id: 'protocol', label: 'Protocol' },
@@ -1853,7 +1009,7 @@ export class WazuhReportingCtrl {
title: 'Network settings',
columns: [
{ id: 'iface', label: 'Interface' },
- { id: 'address', label: 'address' },
+ { id: 'address', label: 'Address' },
{ id: 'netmask', label: 'Netmask' },
{ id: 'proto', label: 'Protocol' },
{ id: 'broadcast', label: 'Broadcast' },
@@ -1906,7 +1062,7 @@ export class WazuhReportingCtrl {
};
if (time) {
- await this.extendedInformation(
+ await extendedInformation(
context,
printer,
'agents',
@@ -1915,6 +1071,7 @@ export class WazuhReportingCtrl {
from,
to,
sanitizedFilters + ' AND rule.groups: "vulnerability-detector"',
+ agentsFilter,
indexPatternTitle,
agentID
);
@@ -1949,8 +1106,8 @@ export class WazuhReportingCtrl {
*/
async getReports(
context: RequestHandlerContext,
- request: KibanaRequest,
- response: KibanaResponseFactory
+ request: OpenSearchDashboardsRequest,
+ response: OpenSearchDashboardsResponseFactory
) {
try {
log('reporting:getReports', `Fetching created reports`, 'info');
@@ -1998,8 +1155,8 @@ export class WazuhReportingCtrl {
*/
getReportByName = this.checkReportsUserDirectoryIsValidRouteDecorator(async (
context: RequestHandlerContext,
- request: KibanaRequest,
- response: KibanaResponseFactory
+ request: OpenSearchDashboardsRequest,
+ response: OpenSearchDashboardsResponseFactory
) => {
try {
log('reporting:getReportByName', `Getting ${context.wazuhEndpointParams.pathFilename} report`, 'debug');
@@ -2023,8 +1180,8 @@ export class WazuhReportingCtrl {
*/
deleteReportByName = this.checkReportsUserDirectoryIsValidRouteDecorator(async (
context: RequestHandlerContext,
- request: KibanaRequest,
- response: KibanaResponseFactory
+ request: OpenSearchDashboardsRequest,
+ response: OpenSearchDashboardsResponseFactory
) => {
try {
log('reporting:deleteReportByName', `Deleting ${context.wazuhEndpointParams.pathFilename} report`, 'debug');
@@ -2042,8 +1199,8 @@ export class WazuhReportingCtrl {
checkReportsUserDirectoryIsValidRouteDecorator(routeHandler, reportFileNameAccessor){
return (async (
context: RequestHandlerContext,
- request: KibanaRequest,
- response: KibanaResponseFactory
+ request: OpenSearchDashboardsRequest,
+ response: OpenSearchDashboardsResponseFactory
) => {
try{
const { username, hashUsername } = await context.wazuh.security.getCurrentUser(request, context);
diff --git a/server/controllers/wazuh-utils/ui-logs.controller.ts b/server/controllers/wazuh-utils/ui-logs.controller.ts
index 56d971f659..76afd26add 100644
--- a/server/controllers/wazuh-utils/ui-logs.controller.ts
+++ b/server/controllers/wazuh-utils/ui-logs.controller.ts
@@ -14,7 +14,7 @@
import { ErrorResponse } from '../../lib/error-response';
import { read } from 'read-last-lines';
import { WAZUH_UI_LOGS_RAW_PATH } from '../../../common/constants';
-import { KibanaRequest, KibanaResponseFactory } from 'src/core/server';
+import { OpenSearchDashboardsRequest, OpenSearchDashboardsResponseFactory } from 'src/core/server';
import uiLogger from '../../lib/ui-logger';
export class UiLogsCtrl {
@@ -29,7 +29,7 @@ export class UiLogsCtrl {
* @param {Object} response
* @returns {Array} app logs or ErrorResponse
*/
- async getUiLogs(response: KibanaResponseFactory) {
+ async getUiLogs(response: OpenSearchDashboardsResponseFactory) {
try {
return uiLogger.initDirectory().then(async () => {
if (!uiLogger.checkFileExist(WAZUH_UI_LOGS_RAW_PATH)) {
@@ -60,7 +60,7 @@ export class UiLogsCtrl {
* @param response
* @returns success message or ErrorResponse
*/
- async createUiLogs(request: KibanaRequest, response: KibanaResponseFactory) {
+ async createUiLogs(request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
const { location, message, level } = request.body;
await uiLogger.log(location, message, level);
diff --git a/server/controllers/wazuh-utils/wazuh-utils.ts b/server/controllers/wazuh-utils/wazuh-utils.ts
index 9a33c3c649..dfaba3b656 100644
--- a/server/controllers/wazuh-utils/wazuh-utils.ts
+++ b/server/controllers/wazuh-utils/wazuh-utils.ts
@@ -16,13 +16,19 @@ import { getConfiguration } from '../../lib/get-configuration';
import { read } from 'read-last-lines';
import { UpdateConfigurationFile } from '../../lib/update-configuration';
import jwtDecode from 'jwt-decode';
-import { WAZUH_ROLE_ADMINISTRATOR_ID, WAZUH_DATA_LOGS_RAW_PATH, WAZUH_UI_LOGS_RAW_PATH } from '../../../common/constants';
+import { WAZUH_ROLE_ADMINISTRATOR_ID, WAZUH_DATA_LOGS_RAW_PATH, PLUGIN_SETTINGS } from '../../../common/constants';
import { ManageHosts } from '../../lib/manage-hosts';
-import { KibanaRequest, RequestHandlerContext, KibanaResponseFactory } from 'src/core/server';
+import { OpenSearchDashboardsRequest, RequestHandlerContext, OpenSearchDashboardsResponseFactory } from 'src/core/server';
import { getCookieValueByName } from '../../lib/cookie';
+import fs from 'fs';
+import path from 'path';
+import { createDirectoryIfNotExists } from '../../lib/filesystem';
+import glob from 'glob';
+import { getFileExtensionFromBuffer } from '../../../common/services/file-extension';
const updateConfigurationFile = new UpdateConfigurationFile();
+// TODO: these controllers have no logs. We should include them.
export class WazuhUtilsCtrl {
/**
* Constructor
@@ -39,7 +45,7 @@ export class WazuhUtilsCtrl {
* @param {Object} response
* @returns {Object} Configuration File or ErrorResponse
*/
- getConfigurationFile(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ getConfigurationFile(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
const configFile = getConfiguration();
@@ -62,50 +68,44 @@ export class WazuhUtilsCtrl {
* @param {Object} response
* @returns {Object} Configuration File or ErrorResponse
*/
- async updateConfigurationFile(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
- try {
- // Check if user has administrator role in token
- const token = getCookieValueByName(request.headers.cookie,'wz-token');
- if(!token){
- return ErrorResponse('No token provided', 401, 401, response);
- };
- const decodedToken = jwtDecode(token);
- if(!decodedToken){
- return ErrorResponse('No permissions in token', 401, 401, response);
- };
- if(!decodedToken.rbac_roles || !decodedToken.rbac_roles.includes(WAZUH_ROLE_ADMINISTRATOR_ID)){
- return ErrorResponse('No administrator role', 401, 401, response);
- };response
- // Check the provided token is valid
- const apiHostID = getCookieValueByName(request.headers.cookie,'wz-api');
- if( !apiHostID ){
- return ErrorResponse('No API id provided', 401, 401, response);
- };
- const responseTokenIsWorking = await context.wazuh.api.client.asCurrentUser.request('GET', '/', {}, {apiHostID});
- if(responseTokenIsWorking.status !== 200){
- return ErrorResponse('Token is not valid', 401, 401, response);
+ updateConfigurationFile = this.routeDecoratorProtectedAdministratorRoleValidToken(
+ async (context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) => {
+
+ let requiresRunningHealthCheck: boolean = false,
+ requiresReloadingBrowserTab: boolean = false,
+ requiresRestartingPluginPlatform: boolean = false;
+
+ // Plugin settings configurables in the configuration file.
+ const pluginSettingsConfigurableFile = Object.keys(request.body)
+ .filter(pluginSettingKey => PLUGIN_SETTINGS[pluginSettingKey].isConfigurableFromFile)
+ .reduce((accum, pluginSettingKey: string) => ({ ...accum, [pluginSettingKey]: request.body[pluginSettingKey] }), {});
+
+ if (Object.keys(pluginSettingsConfigurableFile).length) {
+ // Update the configuration file.
+ await updateConfigurationFile.updateConfiguration(pluginSettingsConfigurableFile);
+
+ requiresRunningHealthCheck = Object.keys(pluginSettingsConfigurableFile).some((pluginSettingKey: string) => Boolean(PLUGIN_SETTINGS[pluginSettingKey].requiresRunningHealthCheck)) || requiresRunningHealthCheck;
+ requiresReloadingBrowserTab = Object.keys(pluginSettingsConfigurableFile).some((pluginSettingKey: string) => Boolean(PLUGIN_SETTINGS[pluginSettingKey].requiresReloadingBrowserTab)) || requiresReloadingBrowserTab;
+ requiresRestartingPluginPlatform = Object.keys(pluginSettingsConfigurableFile).some((pluginSettingKey: string) => Boolean(PLUGIN_SETTINGS[pluginSettingKey].requiresRestartingPluginPlatform)) || requiresRestartingPluginPlatform;
};
- const result = await updateConfigurationFile.updateConfiguration(request);
+
return response.ok({
body: {
- statusCode: 200,
- error: 0,
- data: result
+ data: { requiresRunningHealthCheck, requiresReloadingBrowserTab, requiresRestartingPluginPlatform, updatedConfiguration: pluginSettingsConfigurableFile }
}
});
- } catch (error) {
- return ErrorResponse(error.message || error, 3021, 500, response);
- }
- }
+ },
+ 3021
+ )
/**
* Returns Wazuh app logs
- * @param {Object} context
+ * @param {Object} context
* @param {Object} request
* @param {Object} response
* @returns {Array} app logs or ErrorResponse
*/
- async getAppLogs(context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) {
+ async getAppLogs(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) {
try {
const lastLogs = await read(
WAZUH_DATA_LOGS_RAW_PATH,
@@ -127,5 +127,127 @@ export class WazuhUtilsCtrl {
}
}
+ /**
+ * Upload a file
+ * @param {Object} context
+ * @param {Object} request
+ * @param {Object} response
+ * @returns {Object} Configuration File or ErrorResponse
+ */
+ uploadFile = this.routeDecoratorProtectedAdministratorRoleValidToken(
+ async (context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) => {
+ const { key } = request.params;
+ const { file: bufferFile } = request.body;
+ const pluginSetting = PLUGIN_SETTINGS[key];
+
+ // Check file extension
+ const fileExtension = getFileExtensionFromBuffer(bufferFile);
+
+ // Check if the extension is valid for the setting.
+ if (!pluginSetting.options.file.extensions.includes(`.${fileExtension}`)) {
+ return response.badRequest({
+ body: `File extension is not valid for setting [${key}] setting. Allowed file extensions: ${pluginSetting.options.file.extensions.join(', ')}`
+ });
+ };
+
+ const fileNamePath = `${key}.${fileExtension}`;
+
+ // Create target directory
+ const targetDirectory = path.join(__dirname, '../../..', pluginSetting.options.file.store.relativePathFileSystem);
+ createDirectoryIfNotExists(targetDirectory);
+ // Get the files related to the setting and remove them
+ const files = glob.sync(path.join(targetDirectory, `${key}.*`));
+ files.forEach(fs.unlinkSync);
+ // Store the file in the target directory.
+ fs.writeFileSync(path.join(targetDirectory, fileNamePath), bufferFile);
+
+ // Update the setting in the configuration cache
+ const pluginSettingValue = pluginSetting.options.file.store.resolveStaticURL(fileNamePath);
+ await updateConfigurationFile.updateConfiguration({ [key]: pluginSettingValue });
+
+ return response.ok({
+ body: {
+ data: {
+ requiresRunningHealthCheck: Boolean(pluginSetting.requiresRunningHealthCheck),
+ requiresReloadingBrowserTab: Boolean(pluginSetting.requiresReloadingBrowserTab),
+ requiresRestartingPluginPlatform: Boolean(pluginSetting.requiresRestartingPluginPlatform),
+ updatedConfiguration: {
+ [key]: pluginSettingValue
+ }
+ }
+ }
+ });
+ },
+ 3022
+ )
+
+ /**
+ * Delete a file
+ * @param {Object} context
+ * @param {Object} request
+ * @param {Object} response
+ * @returns {Object} Configuration File or ErrorResponse
+ */
+ deleteFile = this.routeDecoratorProtectedAdministratorRoleValidToken(
+ async (context: RequestHandlerContext, request: KibanaRequest, response: KibanaResponseFactory) => {
+ const { key } = request.params;
+ const pluginSetting = PLUGIN_SETTINGS[key];
+
+ // Get the files related to the setting and remove them
+ const targetDirectory = path.join(__dirname, '../../..', pluginSetting.options.file.store.relativePathFileSystem);
+ const files = glob.sync(path.join(targetDirectory, `${key}.*`));
+ files.forEach(fs.unlinkSync);
+
+ // Update the setting in the configuration cache
+ const pluginSettingValue = pluginSetting.defaultValue;
+ await updateConfigurationFile.updateConfiguration({ [key]: pluginSettingValue });
+
+ return response.ok({
+ body: {
+ message: 'All files were removed and the configuration file was updated.',
+ data: {
+ requiresRunningHealthCheck: Boolean(pluginSetting.requiresRunningHealthCheck),
+ requiresReloadingBrowserTab: Boolean(pluginSetting.requiresReloadingBrowserTab),
+ requiresRestartingPluginPlatform: Boolean(pluginSetting.requiresRestartingPluginPlatform),
+ updatedConfiguration: {
+ [key]: pluginSettingValue
+ }
+ }
+ }
+ });
+ },
+ 3023
+ )
+
+ private routeDecoratorProtectedAdministratorRoleValidToken(routeHandler, errorCode: number) {
+ return async (context, request, response) => {
+ try {
+ // Check if user has administrator role in token
+ const token = getCookieValueByName(request.headers.cookie, 'wz-token');
+ if (!token) {
+ return ErrorResponse('No token provided', 401, 401, response);
+ };
+ const decodedToken = jwtDecode(token);
+ if (!decodedToken) {
+ return ErrorResponse('No permissions in token', 401, 401, response);
+ };
+ if (!decodedToken.rbac_roles || !decodedToken.rbac_roles.includes(WAZUH_ROLE_ADMINISTRATOR_ID)) {
+ return ErrorResponse('No administrator role', 401, 401, response);
+ };
+ // Check the provided token is valid
+ const apiHostID = getCookieValueByName(request.headers.cookie, 'wz-api');
+ if (!apiHostID) {
+ return ErrorResponse('No API id provided', 401, 401, response);
+ };
+ const responseTokenIsWorking = await context.wazuh.api.client.asCurrentUser.request('GET', '/', {}, { apiHostID });
+ if (responseTokenIsWorking.status !== 200) {
+ return ErrorResponse('Token is not valid', 401, 401, response);
+ };
+ return await routeHandler(context, request, response)
+ } catch (error) {
+ return ErrorResponse(error.message || error, errorCode, 500, response);
+ }
+ }
+ }
}
diff --git a/server/index.ts b/server/index.ts
index 6286a55684..b9ce06ee35 100644
--- a/server/index.ts
+++ b/server/index.ts
@@ -1,4 +1,4 @@
-import { PluginInitializerContext } from 'kibana/server';
+import { PluginInitializerContext } from 'opensearch_dashboards/server';
import { WazuhPlugin } from './plugin';
diff --git a/server/integration-files/visualizations/agents/agents-github.ts b/server/integration-files/visualizations/agents/agents-github.ts
index 959cd54465..17ac6e85c9 100644
--- a/server/integration-files/visualizations/agents/agents-github.ts
+++ b/server/integration-files/visualizations/agents/agents-github.ts
@@ -12,7 +12,7 @@
export default [
{
- _id: 'Wazuh-App-Overview-GitHub-Alerts-Evolution-By-Organization',
+ _id: 'Wazuh-App-Agents-GitHub-Alerts-Evolution-By-Organization',
_source: {
title: 'Alerts evolution by organization',
visState: JSON.stringify({
@@ -152,7 +152,7 @@ export default [
_type: 'visualization',
},
{
- _id: 'Wazuh-App-Overview-GitHub-Top-5-Organizations-By-Alerts',
+ _id: 'Wazuh-App-Agents-GitHub-Top-5-Organizations-By-Alerts',
_source: {
title: 'Top 5 organizations by alerts',
visState: JSON.stringify({
@@ -207,7 +207,7 @@ export default [
_type: 'visualization',
},
{
- _id: 'Wazuh-App-Overview-GitHub-Users-With-More-Alerts',
+ _id: 'Wazuh-App-Agents-GitHub-Users-With-More-Alerts',
_source: {
title: 'Users with more alerts',
visState: JSON.stringify({
@@ -341,7 +341,7 @@ export default [
_type: 'visualization',
},
{
- _id: 'Wazuh-App-Overview-GitHub-Alert-Action-Type-By-Organization',
+ _id: 'Wazuh-App-Agents-GitHub-Alert-Action-Type-By-Organization',
_source: {
title: 'Top alerts by alert action type and organization',
visState: JSON.stringify({
@@ -412,11 +412,11 @@ export default [
_type: 'visualization',
},
{
- _id: 'Wazuh-App-Overview-GitHub-Alert-Summary',
+ _id: 'Wazuh-App-Agents-GitHub-Alert-Summary',
_source: {
- title: 'Alert summary',
+ title: 'Alerts summary',
visState: JSON.stringify({
- "title": "Alert summary",
+ "title": "Alerts summary",
"type": "table",
"aggs": [
{
diff --git a/server/integration-files/visualizations/overview/overview-github.ts b/server/integration-files/visualizations/overview/overview-github.ts
index ceb5720036..d46e4c7aff 100644
--- a/server/integration-files/visualizations/overview/overview-github.ts
+++ b/server/integration-files/visualizations/overview/overview-github.ts
@@ -417,9 +417,9 @@ export default [
{
_id: 'Wazuh-App-Overview-GitHub-Alert-Summary',
_source: {
- title: 'Alert summary',
+ title: 'Alerts summary',
visState: JSON.stringify({
- title: 'Alert summary',
+ title: 'Alerts summary',
type: 'table',
aggs: [
{
diff --git a/server/integration-files/visualizations/overview/overview-nist.ts b/server/integration-files/visualizations/overview/overview-nist.ts
index d7e629126a..1c8836bdd5 100644
--- a/server/integration-files/visualizations/overview/overview-nist.ts
+++ b/server/integration-files/visualizations/overview/overview-nist.ts
@@ -268,7 +268,7 @@ export default [
{
_id: 'Wazuh-App-Overview-NIST-requirements-by-agents',
_source: {
- title: 'Requiments distribution by agent',
+ title: 'Requirements distribution by agent',
visState: JSON.stringify({
title: 'NIST-Top-requirements-by-agent',
type: 'area',
diff --git a/server/integration-files/visualizations/overview/overview-office.ts b/server/integration-files/visualizations/overview/overview-office.ts
index 902b76128a..2a7858cd1a 100644
--- a/server/integration-files/visualizations/overview/overview-office.ts
+++ b/server/integration-files/visualizations/overview/overview-office.ts
@@ -1175,7 +1175,7 @@ export default [
otherBucketLabel: 'Others',
missingBucket: false,
missingBucketLabel: 'Missing',
- customLabel: 'Client IP',
+ customLabel: 'Client IP address',
},
schema: 'bucket',
},
diff --git a/server/integration-files/visualizations/overview/overview-virustotal.ts b/server/integration-files/visualizations/overview/overview-virustotal.ts
index 6e5fd2e52a..6effe6cefa 100644
--- a/server/integration-files/visualizations/overview/overview-virustotal.ts
+++ b/server/integration-files/visualizations/overview/overview-virustotal.ts
@@ -693,8 +693,8 @@ export default [
params: {
date: true,
interval: 'PT3H',
- intervalESValue: 3,
- intervalESUnit: 'h',
+ intervalOpenSearchValue: 3,
+ intervalOpenSearchUnit: 'h',
format: 'YYYY-MM-DD HH:mm',
bounds: { min: '2020-04-17T12:11:35.943Z', max: '2020-04-24T12:11:35.944Z' },
},
diff --git a/server/lib/api-interceptor.ts b/server/lib/api-interceptor.ts
index b3e8f3e72c..256eaede05 100644
--- a/server/lib/api-interceptor.ts
+++ b/server/lib/api-interceptor.ts
@@ -15,7 +15,7 @@ import { ManageHosts } from './manage-hosts';
import https from 'https';
const httpsAgent = new https.Agent({
- rejectUnauthorized: false,
+ rejectUnauthorized: false,
});
const _axios = axios.create({ httpsAgent });
@@ -47,7 +47,7 @@ export const authenticate = async (apiHostID: string, authContext?: any): Promis
try{
const api: APIHost = await manageHosts.getHostById(apiHostID);
const optionsRequest = {
- method: !!authContext ? 'POST' : 'GET',
+ method: 'POST',
headers: {
'content-type': 'application/json',
},
diff --git a/server/lib/api-request-list.json b/server/lib/api-request-list.json
index 44df2521e1..ac6edae481 100644
--- a/server/lib/api-request-list.json
+++ b/server/lib/api-request-list.json
@@ -6878,25 +6878,6 @@
}
]
},
- {
- "name": "/security/user/authenticate",
- "documentation": "https://documentation.wazuh.com/current/user-manual/api/reference.html#operation/api.controllers.security_controller.login_user",
- "description": "This method should be called to get an API token. This token will expire after auth_token_exp_timeout seconds (default: 900). This value can be changed using PUT /security/config",
- "summary": "Login",
- "tags": [
- "Security"
- ],
- "query": [
- {
- "name": "raw",
- "description": "Format response in plain text",
- "required": false,
- "schema": {
- "type": "boolean"
- }
- }
- ]
- },
{
"name": "/security/users",
"documentation": "https://documentation.wazuh.com/current/user-manual/api/reference.html#operation/api.controllers.security_controller.get_users",
@@ -10503,6 +10484,25 @@
}
]
},
+ {
+ "name": "/security/user/authenticate",
+ "documentation": "https://documentation.wazuh.com/current/user-manual/api/reference.html#operation/api.controllers.security_controller.login_user",
+ "description": "This method should be called to get an API token. This token will expire after auth_token_exp_timeout seconds (default: 900). This value can be changed using PUT /security/config",
+ "summary": "Login",
+ "tags": [
+ "Security"
+ ],
+ "query": [
+ {
+ "name": "raw",
+ "description": "Format response in plain text",
+ "required": false,
+ "schema": {
+ "type": "boolean"
+ }
+ }
+ ]
+ },
{
"name": "/security/user/authenticate/run_as",
"documentation": "https://documentation.wazuh.com/current/user-manual/api/reference.html#operation/api.controllers.security_controller.run_as_login",
@@ -11662,4 +11662,4 @@
}
]
}
-]
\ No newline at end of file
+]
diff --git a/server/lib/filesystem.ts b/server/lib/filesystem.ts
index d4aeab1bd5..68fe41c878 100644
--- a/server/lib/filesystem.ts
+++ b/server/lib/filesystem.ts
@@ -4,7 +4,7 @@ import { WAZUH_DATA_ABSOLUTE_PATH } from '../../common/constants';
export const createDirectoryIfNotExists = (directory: string): void => {
if (!fs.existsSync(directory)) {
- fs.mkdirSync(directory);
+ fs.mkdirSync(directory, { recursive: true });
}
};
@@ -19,7 +19,7 @@ export const createDataDirectoryIfNotExists = (directory?: string) => {
? path.join(WAZUH_DATA_ABSOLUTE_PATH, directory)
: WAZUH_DATA_ABSOLUTE_PATH;
if (!fs.existsSync(absoluteRoute)) {
- fs.mkdirSync(absoluteRoute);
+ fs.mkdirSync(absoluteRoute, { recursive: true });
}
};
diff --git a/server/lib/get-configuration.ts b/server/lib/get-configuration.ts
index 8e6d2d5d2a..01edd1cf6d 100644
--- a/server/lib/get-configuration.ts
+++ b/server/lib/get-configuration.ts
@@ -11,29 +11,62 @@
*/
import fs from 'fs';
import yml from 'js-yaml';
-import { WAZUH_DATA_CONFIG_APP_PATH, WAZUH_CONFIGURATION_CACHE_TIME } from '../../common/constants';
+import { WAZUH_DATA_CONFIG_APP_PATH, WAZUH_CONFIGURATION_CACHE_TIME, PLUGIN_SETTINGS, EpluginSettingType } from '../../common/constants';
let cachedConfiguration: any = null;
let lastAssign: number = new Date().getTime();
-export function getConfiguration(isUpdating: boolean = false) {
+/**
+ * Get the plugin configuration and cache it.
+ * @param options.force Force to read the configuration and no use the cache .
+ * @returns plugin configuration in JSON
+ */
+export function getConfiguration(options: {force?: boolean} = {}) {
try {
const now = new Date().getTime();
const dateDiffer = now - lastAssign;
- if (!cachedConfiguration || dateDiffer >= WAZUH_CONFIGURATION_CACHE_TIME || isUpdating) {
- const raw = fs.readFileSync(WAZUH_DATA_CONFIG_APP_PATH, { encoding: 'utf-8' });
- const file = yml.load(raw);
+ if (!cachedConfiguration || dateDiffer >= WAZUH_CONFIGURATION_CACHE_TIME || options?.force) {
+ cachedConfiguration = obfuscateHostsConfiguration(
+ readPluginConfigurationFile(WAZUH_DATA_CONFIG_APP_PATH),
+ ['password']
+ );
- for (const host of file.hosts) {
- Object.keys(host).forEach((k) => {
- host[k].password = '*****';
- });
- }
- cachedConfiguration = { ...file };
lastAssign = now;
}
return cachedConfiguration;
} catch (error) {
return false;
- }
-}
+ };
+};
+
+/**
+ * Read the configuration file and transform to JSON.
+ * @param path File path of the plugin configuration file.
+ * @returns Configuration as JSON.
+ */
+ function readPluginConfigurationFile(filepath: string) {
+ const content = fs.readFileSync(filepath, { encoding: 'utf-8' });
+ return yml.load(content);
+};
+
+/**
+ * Obfuscate fields of the hosts configuration.
+ * @param configuration Plugin configuration as JSON.
+ * @param obfuscateHostConfigurationKeys Keys to obfuscate its value in the hosts configuration.
+ * @returns
+ */
+function obfuscateHostsConfiguration(configuration: any, obfuscateHostConfigurationKeys: string[]){
+ if(configuration.hosts){
+ configuration.hosts = Object.entries(configuration.hosts)
+ .reduce((accum, [hostID, hostConfiguration]) => {
+ return {...accum, [hostID]: {
+ ...hostConfiguration,
+ ...(obfuscateHostConfigurationKeys
+ .reduce((accumObfuscateHostConfigurationKeys, obfuscateHostConfigurationKey) =>
+ ({...accumObfuscateHostConfigurationKeys, [obfuscateHostConfigurationKey]: '*****'}), {})
+ )
+ }}
+ }, {});
+ };
+ return configuration;
+};
diff --git a/server/lib/initial-wazuh-config.test.ts b/server/lib/initial-wazuh-config.test.ts
new file mode 100644
index 0000000000..032184387f
--- /dev/null
+++ b/server/lib/initial-wazuh-config.test.ts
@@ -0,0 +1,104 @@
+import { PLUGIN_SETTINGS_CATEGORIES } from '../../common/constants';
+import {
+ header,
+ hostsConfiguration,
+ initialWazuhConfig,
+ printSetting,
+ printSettingCategory,
+ printSettingValue,
+ printSection,
+} from './initial-wazuh-config';
+import { getSettingsDefaultList, groupSettingsByCategory } from '../../common/services/settings';
+
+describe('[configuration-file] Default configuration file content', () => {
+
+ it('Include the header', () => {
+ expect(initialWazuhConfig).toContain(header);
+ });
+
+ it('Include all the expected categories and settings', () => {
+
+ const pluginSettingsConfigurationFile = getSettingsDefaultList()
+ .filter(categorySetting => categorySetting.isConfigurableFromFile);
+
+ const pluginSettingsConfigurationFileGroupByCategory = groupSettingsByCategory(pluginSettingsConfigurationFile);
+
+ pluginSettingsConfigurationFileGroupByCategory.forEach(({category, settings}) => {
+ // Category
+ expect(initialWazuhConfig).toContain(printSettingCategory(PLUGIN_SETTINGS_CATEGORIES[category]));
+
+ // Category settings
+ settings.forEach(setting => {
+ expect(initialWazuhConfig).toContain(printSetting(setting));
+ });
+ });
+
+ });
+
+ it('Include the host configuration', () => {
+ expect(initialWazuhConfig).toContain(hostsConfiguration);
+ });
+});
+
+describe('[configuration-file] Methods', () => {
+
+ it.each`
+ text | options
+ ${'Test'} | ${{}}
+ ${'Test'} | ${{ maxLength: 60, prefix: '# '}}
+ ${'Test'} | ${{ maxLength: 60, fill: '-', prefix: '# '}}
+ `('printSection: $options', ({text, options}) => {
+ const result = printSection(text, options);
+ expect(result).toHaveLength(options?.maxLength ?? 80);
+ options.prefix && expect(result).toMatch(new RegExp(`^${options.prefix}`));
+ expect(result).toMatch(new RegExp(`${options?.fill ?? ' '}$`));
+ expect(result).toContain(`${' '.repeat(options.spaceAround | 1)}${text}${' '.repeat(options.spaceAround | 1)}`);
+ });
+
+ it.each`
+ input | expected
+ ${{title: 'Test', description: 'Test description'}} | ${'# ------------------------------------ Test ------------------------------------\n#\n# Test description'}
+ ${{title: 'Test 2', description: 'Test description'}} | ${'# ----------------------------------- Test 2 -----------------------------------\n#\n# Test description'}
+ ${{title: 'Test 2', description: 'Test description'}} | ${'# ----------------------------------- Test 2 -----------------------------------\n#\n# Test description'}
+ `('printSettingValue: input: $input , expected: $expected', ({input, expected}) => {
+ const result = printSettingCategory(input);
+ expect(result).toBe(expected);
+ });
+
+ it.each(
+ [
+ {
+ input: {key: 'test', description: 'Test description', defaultValue: 0},
+ expected: '# Test description\n# test: 0'
+ },
+ {
+ input: {key: 'test', description: 'Test description. Test description. Test description. Test description. Test description. Test description. Test description. Test description. Test description. Test description. Test description. ', defaultValue: 0},
+ expected: '# Test description. Test description. Test description. Test description. Test\n# description. Test description. Test description. Test description. Test\n# description. Test description. Test description.\n# test: 0'
+ },
+ {
+ input: {key: 'test', description: 'Test description', defaultValue: 0, options: {select: [{text: 'Option1', value: 'option'},{text: 'Option2', value: 'option2'}]}},
+ expected: '# Test description Allowed values: option (Option1), option2 (Option2).\n# test: 0'
+ },
+ {
+ input: {key: 'test', description: 'Test description', defaultValue: 0, options: {switch: {values: { disabled: {label: 'Enabled', value: 'disabled'}, enabled: {label: 'Enabled', value: 'enabled'}, }}}},
+ expected: '# Test description Allowed values: enabled (Enabled), disabled (Enabled).\n# test: 0'
+ }
+
+ ]
+ )('printSetting: input: $input , expected: $expected', ({input, expected}) => {
+ const result = printSetting(input);
+ expect(result).toMatch(expected);
+ });
+
+ it.each`
+ input | expected
+ ${4} | ${4}
+ ${''} | ${"''"}
+ ${'test'} | ${'test'}
+ ${{key: 'value'}} | ${'{\"key\":\"value\"}'}
+ ${[]} | ${"[]"}
+ ${''} | ${"''"}
+ `('printSettingValue: input: $input , expected: $expected', ({input, expected}) => {
+ expect(printSettingValue(input)).toBe(expected);
+ });
+});
diff --git a/server/lib/initial-wazuh-config.ts b/server/lib/initial-wazuh-config.ts
index 9e99873a11..31a913cf71 100644
--- a/server/lib/initial-wazuh-config.ts
+++ b/server/lib/initial-wazuh-config.ts
@@ -11,47 +11,16 @@
*/
import {
- WAZUH_ALERTS_PATTERN,
- WAZUH_DEFAULT_APP_CONFIG,
- WAZUH_MONITORING_DEFAULT_CREATION,
- WAZUH_MONITORING_DEFAULT_ENABLED,
- WAZUH_MONITORING_DEFAULT_FREQUENCY,
- WAZUH_MONITORING_DEFAULT_INDICES_REPLICAS,
- WAZUH_MONITORING_DEFAULT_INDICES_SHARDS,
- WAZUH_MONITORING_PATTERN,
- WAZUH_SAMPLE_ALERT_PREFIX,
- WAZUH_STATISTICS_DEFAULT_CREATION,
- WAZUH_STATISTICS_DEFAULT_CRON_FREQ,
- WAZUH_STATISTICS_DEFAULT_INDICES_REPLICAS,
- WAZUH_STATISTICS_DEFAULT_INDICES_SHARDS,
- WAZUH_STATISTICS_DEFAULT_NAME,
- WAZUH_STATISTICS_DEFAULT_PREFIX,
- WAZUH_STATISTICS_DEFAULT_STATUS,
+ PLUGIN_APP_NAME,
+ PLUGIN_SETTINGS_CATEGORIES,
+ TPluginSettingWithKey,
} from '../../common/constants';
+import { getPluginSettingDescription, getSettingsDefaultList, groupSettingsByCategory } from '../../common/services/settings';
import { webDocumentationLink } from '../../common/services/web_documentation';
-import { configEquivalences } from '../../common/config-equivalences';
-/**
- * Given a string, this function builds a multine string, each line about 70
- * characters long, splitted at the closest whitespace character to that lentgh.
- *
- * This function is used to transform the settings description stored in the
- * configEquivalences map into a multiline string to be used as the setting
- * documentation.
- *
- * The # character is also appended to the beginning of each line.
- *
- * @param text
- * @returns multine string
- */
-function splitDescription(text: string = ''): string {
- const lines = text.match(/.{1,80}(?=\s|$)/g) || [];
- return lines.map((z) => '# ' + z.trim()).join('\n');
-}
-
-export const initialWazuhConfig: string = `---
+export const header: string = `---
#
-# Wazuh app - App configuration file
+# ${PLUGIN_APP_NAME} - App configuration file
# Copyright (C) 2015-2022 Wazuh, Inc.
#
# This program is free software; you can redistribute it and/or modify
@@ -61,200 +30,93 @@ export const initialWazuhConfig: string = `---
#
# Find more information about this on the LICENSE file.
#
-# ======================== Wazuh app configuration file ========================
+${printSection('Wazuh app configuration file', { prefix: '# ', fill: '=' })}
#
# Please check the documentation for more information about configuration options:
# ${webDocumentationLink('user-manual/wazuh-dashboard/config-file.html')}
#
# Also, you can check our repository:
-# https://github.com/wazuh/wazuh-kibana-app
-#
-# ---------------------------- Unauthorized roles ------------------------------
-#
-# Disable Wazuh for the Elasticsearch / OpenSearch roles defined here.
-# disabled_roles:
-# - wazuh_disabled
-#
-# ------------------------------- Index patterns -------------------------------
-#
-${splitDescription(configEquivalences.pattern)}
-# pattern: ${WAZUH_ALERTS_PATTERN}
-#
-# ----------------------------------- Checks -----------------------------------
-#
-# Define which checks will be executed by the App's HealthCheck.
-# Allowed values are: true, false
-#
-${splitDescription(configEquivalences['checks.pattern'])}
-# checks.pattern: ${WAZUH_DEFAULT_APP_CONFIG['checks.pattern']}
-#
-${splitDescription(configEquivalences['checks.template'])}
-# checks.template: ${WAZUH_DEFAULT_APP_CONFIG['checks.template']}
-#
-${splitDescription(configEquivalences['checks.api'])}
-# checks.api: ${WAZUH_DEFAULT_APP_CONFIG['checks.api']}
-#
-${splitDescription(configEquivalences['checks.setup'])}
-# checks.setup: ${WAZUH_DEFAULT_APP_CONFIG['checks.setup']}
-#
-${splitDescription(configEquivalences['checks.fields'])}
-# checks.fields: ${WAZUH_DEFAULT_APP_CONFIG['checks.fields']}
-#
-${splitDescription(configEquivalences['checks.metaFields'])}
-# checks.metaFields: ${WAZUH_DEFAULT_APP_CONFIG['checks.metaFields']}
-#
-${splitDescription(configEquivalences['checks.timeFilter'])}
-# checks.timeFilter: ${WAZUH_DEFAULT_APP_CONFIG['checks.timeFilter']}
-#
-${splitDescription(configEquivalences['checks.maxBuckets'])}
-# checks.maxBuckets: ${WAZUH_DEFAULT_APP_CONFIG['checks.maxBuckets']}
-#
-# --------------------------------- Extensions ---------------------------------
-#
-# Define the initial state of the extensions (enabled / disabled) for recently
-# added hosts. The extensions can be enabled or disabled anytime using the UI.
-# Allowed values are: true, false
-#
-${splitDescription(configEquivalences['extensions.pci'])}
-# extensions.pci: ${WAZUH_DEFAULT_APP_CONFIG['extensions.pci']}
-#
-${splitDescription(configEquivalences['extensions.gdpr'])}
-# extensions.gdpr: ${WAZUH_DEFAULT_APP_CONFIG['extensions.gdpr']}
-#
-${splitDescription(configEquivalences['extensions.hipaa'])}
-# extensions.hipaa: ${WAZUH_DEFAULT_APP_CONFIG['extensions.hipaa']}
-#
-${splitDescription(configEquivalences['extensions.nist'])}
-# extensions.nist: ${WAZUH_DEFAULT_APP_CONFIG['extensions.nist']}
-#
-${splitDescription(configEquivalences['extensions.tsc'])}
-# extensions.tsc: ${WAZUH_DEFAULT_APP_CONFIG['extensions.tsc']}
-#
-${splitDescription(configEquivalences['extensions.audit'])}
-# extensions.audit: ${WAZUH_DEFAULT_APP_CONFIG['extensions.audit']}
-#
-${splitDescription(configEquivalences['extensions.oscap'])}
-# extensions.oscap: ${WAZUH_DEFAULT_APP_CONFIG['extensions.oscap']}
-#
-${splitDescription(configEquivalences['extensions.ciscat'])}
-# extensions.ciscat: ${WAZUH_DEFAULT_APP_CONFIG['extensions.ciscat']}
-#
-${splitDescription(configEquivalences['extensions.aws'])}
-# extensions.aws: ${WAZUH_DEFAULT_APP_CONFIG['extensions.aws']}
-#
-${splitDescription(configEquivalences['extensions.gcp'])}
-# extensions.gcp: ${WAZUH_DEFAULT_APP_CONFIG['extensions.gcp']}
-#
-${splitDescription(configEquivalences['extensions.virustotal'])}
-# extensions.virustotal: ${WAZUH_DEFAULT_APP_CONFIG['extensions.virustotal']}
-#
-${splitDescription(configEquivalences['extensions.osquery'])}
-# extensions.osquery: ${WAZUH_DEFAULT_APP_CONFIG['extensions.osquery']}
-#
-${splitDescription(configEquivalences['extensions.docker'])}
-# extensions.docker: ${WAZUH_DEFAULT_APP_CONFIG['extensions.docker']}
-#
-# ------------------------------- Timeout --------------------------------------
-#
-${splitDescription(configEquivalences.timeout)}
-# timeout: ${WAZUH_DEFAULT_APP_CONFIG.timeout}
-#
-# --------------------------- Index pattern selector ---------------------------
-#
-${splitDescription(configEquivalences['ip.selector'])}
-# ip.selector: ${WAZUH_DEFAULT_APP_CONFIG['ip.selector']}
-#
-${splitDescription(configEquivalences['ip.ignore'])}
-# ip.ignore: ${WAZUH_DEFAULT_APP_CONFIG['ip.ignore']}
-#
-# ------------------------------ Monitoring ------------------------------------
-#
-${splitDescription(configEquivalences['wazuh.monitoring.enabled'])}
-# wazuh.monitoring.enabled: ${WAZUH_MONITORING_DEFAULT_ENABLED}
-#
-${splitDescription(configEquivalences['wazuh.monitoring.frequency'])}
-# wazuh.monitoring.frequency: ${WAZUH_MONITORING_DEFAULT_FREQUENCY}
-#
-${splitDescription(configEquivalences['wazuh.monitoring.shards'])}
-# wazuh.monitoring.shards: ${WAZUH_MONITORING_DEFAULT_INDICES_SHARDS}
-#
-${splitDescription(configEquivalences['wazuh.monitoring.replicas'])}
-# wazuh.monitoring.replicas: ${WAZUH_MONITORING_DEFAULT_INDICES_REPLICAS}
-#
-${splitDescription(configEquivalences['wazuh.monitoring.creation'])}
-# Allowed values are: h (hourly), d (daily), w (weekly), m (monthly)
-# wazuh.monitoring.creation: ${WAZUH_MONITORING_DEFAULT_CREATION}
-#
-${splitDescription(configEquivalences['wazuh.monitoring.pattern'])}
-# wazuh.monitoring.pattern: ${WAZUH_MONITORING_PATTERN}
-#
-# --------------------------------- Sample data --------------------------------
-#
-${splitDescription(configEquivalences['alerts.sample.prefix'])}
-# alerts.sample.prefix: ${WAZUH_SAMPLE_ALERT_PREFIX}
-#
-# ------------------------------ Background tasks ------------------------------
-#
-${splitDescription(configEquivalences['cron.prefix'])}
-# cron.prefix: ${WAZUH_STATISTICS_DEFAULT_PREFIX}
-#
-# ------------------------------ Wazuh Statistics ------------------------------
-#
-${splitDescription(configEquivalences['cron.statistics.status'])}
-# cron.statistics.status: ${WAZUH_STATISTICS_DEFAULT_STATUS}
-#
-${splitDescription(configEquivalences['cron.statistics.apis'])}
-# cron.statistics.apis: ${WAZUH_DEFAULT_APP_CONFIG['cron.statistics.apis']}
-#
-${splitDescription(configEquivalences['cron.statistics.interval'])}
-# cron.statistics.interval: ${WAZUH_STATISTICS_DEFAULT_CRON_FREQ}
-#
-${splitDescription(configEquivalences['cron.statistics.index.name'])}
-# cron.statistics.index.name: ${WAZUH_STATISTICS_DEFAULT_NAME}
-#
-${splitDescription(configEquivalences['cron.statistics.index.creation'])}
-# cron.statistics.index.creation: ${WAZUH_STATISTICS_DEFAULT_CREATION}
-#
-${splitDescription(configEquivalences['cron.statistics.index.shards'])}
-# cron.statistics.shards: ${WAZUH_STATISTICS_DEFAULT_INDICES_SHARDS}
-#
-${splitDescription(configEquivalences['cron.statistics.index.replicas'])}
-# cron.statistics.replicas: ${WAZUH_STATISTICS_DEFAULT_INDICES_REPLICAS}
-#
-# ------------------------------ Logo customization ----------------------------
-#
-${splitDescription(configEquivalences['customization.logo.app'])}
-# customization.logo.app: ${WAZUH_DEFAULT_APP_CONFIG['customization.logo.app']}
-#
-${splitDescription(configEquivalences['customization.logo.sidebar'])}
-# customization.logo.sidebar: ${WAZUH_DEFAULT_APP_CONFIG['customization.logo.sidebar']}
-#
-${splitDescription(configEquivalences['customization.logo.healthcheck'])}
-# customization.logo.healthcheck: ${WAZUH_DEFAULT_APP_CONFIG['customization.logo.healthcheck']}
-#
-${splitDescription(configEquivalences['customization.logo.reports'])}
-# customization.logo.reports: ${WAZUH_DEFAULT_APP_CONFIG['customization.logo.reports']}
-#
-# ---------------------------- Hide manager alerts -----------------------------
-#
-${splitDescription(configEquivalences.hideManagerAlerts)}
-# hideManagerAlerts: ${WAZUH_DEFAULT_APP_CONFIG.hideManagerAlerts}
-#
-# ------------------------------- App logging level ----------------------------
-#
-${splitDescription(configEquivalences['logs.level'])}
-# Allowed values are: info, debug
-# logs.level: ${WAZUH_DEFAULT_APP_CONFIG['logs.level']}
-#
-# ------------------------------- Agent enrollment -----------------------------
-#
-${splitDescription(configEquivalences['enrollment.dns'])}
-# enrollment.dns: ${WAZUH_DEFAULT_APP_CONFIG['enrollment.dns']}
-#
-${splitDescription(configEquivalences['enrollment.password'])}
-# enrollment.password: ${WAZUH_DEFAULT_APP_CONFIG['enrollment.password']}
-#
-#-------------------------------- Wazuh hosts ----------------------------------
+# https://github.com/wazuh/wazuh-kibana-app`;
+
+const pluginSettingsConfigurationFile = getSettingsDefaultList().filter(({ isConfigurableFromFile }) => isConfigurableFromFile);
+
+const pluginSettingsConfigurationFileGroupByCategory = groupSettingsByCategory(pluginSettingsConfigurationFile);
+
+const pluginSettingsConfiguration = pluginSettingsConfigurationFileGroupByCategory.map(({ category: categoryID, settings }) => {
+ const category = printSettingCategory(PLUGIN_SETTINGS_CATEGORIES[categoryID]);
+
+ const pluginSettingsOfCategory = settings
+ .map(setting => printSetting(setting)
+ ).join('\n#\n');
+ /*
+ #------------------- {category name} --------------
+ #
+ # {category description}
+ #
+ # {setting description}
+ # settingKey: settingDefaultValue
+ #
+ # {setting description}
+ # settingKey: settingDefaultValue
+ # ...
+ */
+ return [category, pluginSettingsOfCategory].join('\n#\n');
+}).join('\n#\n');
+
+
+export function printSettingValue(value: unknown): any {
+ if (typeof value === 'object') {
+ return JSON.stringify(value)
+ };
+
+ if (typeof value === 'string' && value.length === 0) {
+ return `''`
+ };
+
+ return value;
+};
+
+export function printSetting(setting: TPluginSettingWithKey): string {
+ /*
+ # {setting description}
+ # {settingKey}: {settingDefaultValue}
+ */
+ return [
+ splitDescription(getPluginSettingDescription(setting)),
+ `# ${setting.key}: ${printSettingValue(setting.defaultValue)}`
+ ].join('\n')
+}
+
+export function printSettingCategory({ title, description }) {
+ /*
+ #------------------------------- {category title} -------------------------------
+ # {category description}
+ #
+ */
+ return [
+ printSection(title, { prefix: '# ', fill: '-' }),
+ ...(description ? [splitDescription(description)] : [''])
+ ].join('\n#\n')
+};
+
+export function printSection(text: string, options?: { maxLength?: number, prefix?: string, suffix?: string, spaceAround?: number, fill?: string }) {
+ const maxLength = options?.maxLength ?? 80;
+ const prefix = options?.prefix ?? '';
+ const sufix = options?.suffix ?? '';
+ const spaceAround = options?.spaceAround ?? 1;
+ const fill = options?.fill ?? ' ';
+ const fillLength = maxLength - prefix.length - sufix.length - (2 * spaceAround) - text.length;
+
+ return [
+ prefix,
+ fill.repeat(Math.floor(fillLength / 2)),
+ ` ${text} `,
+ fill.repeat(Math.ceil(fillLength / 2)),
+ sufix
+ ].join('');
+};
+
+export const hostsConfiguration = `${printSection('Wazuh hosts', { prefix: '# ', fill: '-' })}
#
# The following configuration is the default structure to define a host.
#
@@ -286,3 +148,22 @@ hosts:
password: wazuh-wui
run_as: false
`;
+
+/**
+ * Given a string, this function builds a multine string, each line about 70
+ * characters long, splitted at the closest whitespace character to that lentgh.
+ *
+ * This function is used to transform the settings description
+ * into a multiline string to be used as the setting documentation.
+ *
+ * The # character is also appended to the beginning of each line.
+ *
+ * @param text
+ * @returns multine string
+ */
+export function splitDescription(text: string = ''): string {
+ const lines = text.match(/.{1,80}(?=\s|$)/g) || [];
+ return lines.map((z) => '# ' + z.trim()).join('\n');
+}
+
+export const initialWazuhConfig: string = [header, pluginSettingsConfiguration, hostsConfiguration].join('\n#\n');
diff --git a/server/lib/reporting/agent-configuration.ts b/server/lib/reporting/agent-configuration.ts
index 2b1fbfe02c..6721e7d2b3 100644
--- a/server/lib/reporting/agent-configuration.ts
+++ b/server/lib/reporting/agent-configuration.ts
@@ -163,7 +163,7 @@ export const AgentConfiguration = {
subtitle: 'Inventory data',
docuLink: webDocumentationLink('user-manual/reference/ossec-conf/wodle-syscollector.html'),
desc:
- 'Gather relevant information about system OS, hardware, networking and packages',
+ 'Gather relevant information about the operating system, hardware, networking and packages',
wodle: [{ name: 'syscollector' }],
labels: [
{
diff --git a/server/lib/reporting/audit-request.ts b/server/lib/reporting/audit-request.ts
index cb67d0b192..21fb8dfb12 100644
--- a/server/lib/reporting/audit-request.ts
+++ b/server/lib/reporting/audit-request.ts
@@ -11,7 +11,7 @@
*/
import { Base } from './base-query';
import AuditMap from './audit-map';
-import { WAZUH_ALERTS_PATTERN } from '../../../common/constants';
+import { getSettingDefaultValue } from '../../../common/services/settings';
/**
* Returns top 3 agents that execute sudo commands without success
@@ -26,12 +26,13 @@ export const getTop3AgentsSudoNonSuccessful = async (
gte,
lte,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'3': {
@@ -69,7 +70,7 @@ export const getTop3AgentsSudoNonSuccessful = async (
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
@@ -93,12 +94,13 @@ export const getTop3AgentsFailedSyscalls = async (
gte,
lte,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'3': {
@@ -131,14 +133,14 @@ export const getTop3AgentsFailedSyscalls = async (
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
const { buckets } = response.body.aggregations['3'];
return buckets.map(bucket => {
- try{
+ try {
const agent = bucket.key;
const syscall = {
id: bucket['4'].buckets[0].key,
@@ -150,7 +152,7 @@ export const getTop3AgentsFailedSyscalls = async (
agent,
syscall
};
- }catch(error){
+ } catch (error) {
return undefined;
}
}).filter(bucket => bucket);
@@ -172,12 +174,13 @@ export const getTopFailedSyscalls = async (
gte,
lte,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -199,7 +202,7 @@ export const getTopFailedSyscalls = async (
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
diff --git a/server/lib/reporting/base-query.ts b/server/lib/reporting/base-query.ts
index de1de445da..09d1f35f50 100644
--- a/server/lib/reporting/base-query.ts
+++ b/server/lib/reporting/base-query.ts
@@ -9,10 +9,10 @@
*
* Find more information about this on the LICENSE file.
*/
-export function Base(pattern: string, filters: any, gte: number, lte: number) {
- return {
+export function Base(pattern: string, filters: any, gte: number, lte: number, allowedAgentsFilter: any = null) {
+ const base = {
// index: pattern,
-
+
from: 0,
size: 500,
aggs: {},
@@ -42,4 +42,12 @@ export function Base(pattern: string, filters: any, gte: number, lte: number) {
}
}
};
+
+ //Add allowed agents filter
+ if(allowedAgentsFilter?.query?.bool){
+ base.query.bool.minimum_should_match = allowedAgentsFilter.query.bool.minimum_should_match;
+ base.query.bool.should = allowedAgentsFilter.query.bool.should;
+ }
+
+ return base;
}
diff --git a/server/lib/reporting/extended-information.ts b/server/lib/reporting/extended-information.ts
new file mode 100644
index 0000000000..a533abff0b
--- /dev/null
+++ b/server/lib/reporting/extended-information.ts
@@ -0,0 +1,916 @@
+import { log } from '../logger';
+import SummaryTable from './summary-table';
+import summaryTablesDefinitions from './summary-tables-definitions';
+import * as VulnerabilityRequest from './vulnerability-request';
+import * as OverviewRequest from './overview-request';
+import * as RootcheckRequest from './rootcheck-request';
+import * as PCIRequest from './pci-request';
+import * as GDPRRequest from './gdpr-request';
+import * as TSCRequest from './tsc-request';
+import * as AuditRequest from './audit-request';
+import * as SyscheckRequest from './syscheck-request';
+import PCI from '../../integration-files/pci-requirements-pdfmake';
+import GDPR from '../../integration-files/gdpr-requirements-pdfmake';
+import TSC from '../../integration-files/tsc-requirements-pdfmake';
+import { ReportPrinter } from './printer';
+import moment from 'moment';
+import { getSettingDefaultValue } from '../../../common/services/settings';
+
+
+
+
+/**
+ * This build the agents table
+ * @param {Array} ids ids of agents
+ * @param {String} apiId API id
+ */
+ export async function buildAgentsTable(context, printer: ReportPrinter, agentIDs: string[], apiId: string, groupID: string = '') {
+ const dateFormat = await context.core.uiSettings.client.get('dateFormat');
+ if ((!agentIDs || !agentIDs.length) && !groupID) return;
+ log('reporting:buildAgentsTable', `${agentIDs.length} agents for API ${apiId}`, 'info');
+ try {
+ let agentsData = [];
+ if (groupID) {
+ let totalAgentsInGroup = null;
+ do{
+ const { data: { data: { affected_items, total_affected_items } } } = await context.wazuh.api.client.asCurrentUser.request(
+ 'GET',
+ `/groups/${groupID}/agents`,
+ {
+ params: {
+ offset: agentsData.length,
+ select: 'dateAdd,id,ip,lastKeepAlive,manager,name,os.name,os.version,version',
+ }
+ },
+ { apiHostID: apiId }
+ );
+ !totalAgentsInGroup && (totalAgentsInGroup = total_affected_items);
+ agentsData = [...agentsData, ...affected_items];
+ }while(agentsData.length < totalAgentsInGroup);
+ } else {
+ for (const agentID of agentIDs) {
+ try {
+ const { data: { data: { affected_items: [agent] } } } = await context.wazuh.api.client.asCurrentUser.request(
+ 'GET',
+ `/agents`,
+ {
+ params: {
+ q: `id=${agentID}`,
+ select: 'dateAdd,id,ip,lastKeepAlive,manager,name,os.name,os.version,version',
+ }
+ },
+ { apiHostID: apiId }
+ );
+ agentsData.push(agent);
+ } catch (error) {
+ log(
+ 'reporting:buildAgentsTable',
+ `Skip agent due to: ${error.message || error}`,
+ 'debug'
+ );
+ }
+ }
+ }
+
+ if(agentsData.length){
+ // Print a table with agent/s information
+ printer.addSimpleTable({
+ columns: [
+ { id: 'id', label: 'ID' },
+ { id: 'name', label: 'Name' },
+ { id: 'ip', label: 'IP address' },
+ { id: 'version', label: 'Version' },
+ { id: 'manager', label: 'Manager' },
+ { id: 'os', label: 'Operating system' },
+ { id: 'dateAdd', label: 'Registration date' },
+ { id: 'lastKeepAlive', label: 'Last keep alive' },
+ ],
+ items: agentsData
+ .filter(agent => agent) // Remove undefined agents when Wazuh API no longer finds and agentID
+ .map((agent) => {
+ return {
+ ...agent,
+ os: (agent.os && agent.os.name && agent.os.version) ? `${agent.os.name} ${agent.os.version}` : '',
+ lastKeepAlive: moment(agent.lastKeepAlive).format(dateFormat),
+ dateAdd: moment(agent.dateAdd).format(dateFormat)
+ }
+ }),
+ });
+ }else if(!agentsData.length && groupID){
+ // For group reports when there is no agents in the group
+ printer.addContent({
+ text: 'There are no agents in this group.',
+ style: { fontSize: 12, color: '#000' },
+ });
+ }
+
+ } catch (error) {
+ log('reporting:buildAgentsTable', error.message || error);
+ return Promise.reject(error);
+ }
+}
+
+/**
+ * This load more information
+ * @param {*} context Endpoint context
+ * @param {*} printer printer instance
+ * @param {String} section section target
+ * @param {Object} tab tab target
+ * @param {String} apiId ID of API
+ * @param {Number} from Timestamp (ms) from
+ * @param {Number} to Timestamp (ms) to
+ * @param {String} filters E.g: cluster.name: wazuh AND rule.groups: vulnerability
+ * @param {String} pattern
+ * @param {Object} agent agent target
+ * @returns {Object} Extended information
+ */
+export async function extendedInformation(
+ context,
+ printer,
+ section,
+ tab,
+ apiId,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern'),
+ agent = null
+) {
+ try {
+ log(
+ 'reporting:extendedInformation',
+ `Section ${section} and tab ${tab}, API is ${apiId}. From ${from} to ${to}. Filters ${filters}. Index pattern ${pattern}`,
+ 'info'
+ );
+ if (section === 'agents' && !agent) {
+ throw new Error('Reporting for specific agent needs an agent ID in order to work properly');
+ }
+
+ const agents = await context.wazuh.api.client.asCurrentUser.request(
+ 'GET',
+ '/agents',
+ { params: { limit: 1 } },
+ { apiHostID: apiId }
+ );
+
+ const totalAgents = agents.data.data.total_affected_items;
+
+ //--- OVERVIEW - VULS
+ if (section === 'overview' && tab === 'vuls') {
+ log(
+ 'reporting:extendedInformation',
+ 'Fetching overview vulnerability detector metrics',
+ 'debug'
+ );
+ const vulnerabilitiesLevels = ['Low', 'Medium', 'High', 'Critical'];
+
+ const vulnerabilitiesResponsesCount = (
+ await Promise.all(
+ vulnerabilitiesLevels.map(async (vulnerabilitiesLevel) => {
+ try {
+ const count = await VulnerabilityRequest.uniqueSeverityCount(
+ context,
+ from,
+ to,
+ vulnerabilitiesLevel,
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ return count
+ ? `${count} of ${totalAgents} agents have ${vulnerabilitiesLevel.toLocaleLowerCase()} vulnerabilities.`
+ : undefined;
+ } catch (error) {}
+ })
+ )
+ ).filter((vulnerabilitiesResponse) => vulnerabilitiesResponse);
+
+ printer.addList({
+ title: { text: 'Summary', style: 'h2' },
+ list: vulnerabilitiesResponsesCount,
+ });
+
+ log(
+ 'reporting:extendedInformation',
+ 'Fetching overview vulnerability detector top 3 agents by category',
+ 'debug'
+ );
+ const lowRank = await VulnerabilityRequest.topAgentCount(
+ context,
+ from,
+ to,
+ 'Low',
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ const mediumRank = await VulnerabilityRequest.topAgentCount(
+ context,
+ from,
+ to,
+ 'Medium',
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ const highRank = await VulnerabilityRequest.topAgentCount(
+ context,
+ from,
+ to,
+ 'High',
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ const criticalRank = await VulnerabilityRequest.topAgentCount(
+ context,
+ from,
+ to,
+ 'Critical',
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ log(
+ 'reporting:extendedInformation',
+ 'Adding overview vulnerability detector top 3 agents by category',
+ 'debug'
+ );
+ if (criticalRank && criticalRank.length) {
+ printer.addContentWithNewLine({
+ text: 'Top 3 agents with critical severity vulnerabilities',
+ style: 'h3',
+ });
+ await buildAgentsTable(context, printer, criticalRank, apiId);
+ printer.addNewLine();
+ }
+
+ if (highRank && highRank.length) {
+ printer.addContentWithNewLine({
+ text: 'Top 3 agents with high severity vulnerabilities',
+ style: 'h3',
+ });
+ await buildAgentsTable(context, printer, highRank, apiId);
+ printer.addNewLine();
+ }
+
+ if (mediumRank && mediumRank.length) {
+ printer.addContentWithNewLine({
+ text: 'Top 3 agents with medium severity vulnerabilities',
+ style: 'h3',
+ });
+ await buildAgentsTable(context, printer, mediumRank, apiId);
+ printer.addNewLine();
+ }
+
+ if (lowRank && lowRank.length) {
+ printer.addContentWithNewLine({
+ text: 'Top 3 agents with low severity vulnerabilities',
+ style: 'h3',
+ });
+ await buildAgentsTable(context, printer, lowRank, apiId);
+ printer.addNewLine();
+ }
+
+ log(
+ 'reporting:extendedInformation',
+ 'Fetching overview vulnerability detector top 3 CVEs',
+ 'debug'
+ );
+ const cveRank = await VulnerabilityRequest.topCVECount(context, from, to, filters, allowedAgentsFilter, pattern);
+ log(
+ 'reporting:extendedInformation',
+ 'Adding overview vulnerability detector top 3 CVEs',
+ 'debug'
+ );
+ if (cveRank && cveRank.length) {
+ printer.addSimpleTable({
+ title: { text: 'Top 3 CVE', style: 'h2' },
+ columns: [
+ { id: 'top', label: 'Top' },
+ { id: 'cve', label: 'CVE' },
+ ],
+ items: cveRank.map((item) => ({ top: cveRank.indexOf(item) + 1, cve: item })),
+ });
+ }
+ }
+
+ //--- OVERVIEW - GENERAL
+ if (section === 'overview' && tab === 'general') {
+ log('reporting:extendedInformation', 'Fetching top 3 agents with level 15 alerts', 'debug');
+
+ const level15Rank = await OverviewRequest.topLevel15(context, from, to, filters, allowedAgentsFilter, pattern);
+
+ log('reporting:extendedInformation', 'Adding top 3 agents with level 15 alerts', 'debug');
+ if (level15Rank.length) {
+ printer.addContent({
+ text: 'Top 3 agents with level 15 alerts',
+ style: 'h2',
+ });
+ await buildAgentsTable(context, printer, level15Rank, apiId);
+ }
+ }
+
+ //--- OVERVIEW - PM
+ if (section === 'overview' && tab === 'pm') {
+ log('reporting:extendedInformation', 'Fetching most common rootkits', 'debug');
+ const top5RootkitsRank = await RootcheckRequest.top5RootkitsDetected(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ log('reporting:extendedInformation', 'Adding most common rootkits', 'debug');
+ if (top5RootkitsRank && top5RootkitsRank.length) {
+ printer
+ .addContentWithNewLine({
+ text: 'Most common rootkits found among your agents',
+ style: 'h2',
+ })
+ .addContentWithNewLine({
+ text:
+ 'Rootkits are a set of software tools that enable an unauthorized user to gain control of a computer system without being detected.',
+ style: 'standard',
+ })
+ .addSimpleTable({
+ items: top5RootkitsRank.map((item) => {
+ return { top: top5RootkitsRank.indexOf(item) + 1, name: item };
+ }),
+ columns: [
+ { id: 'top', label: 'Top' },
+ { id: 'name', label: 'Rootkit' },
+ ],
+ });
+ }
+ log('reporting:extendedInformation', 'Fetching hidden pids', 'debug');
+ const hiddenPids = await RootcheckRequest.agentsWithHiddenPids(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ hiddenPids &&
+ printer.addContent({
+ text: `${hiddenPids} of ${totalAgents} agents have hidden processes`,
+ style: 'h3',
+ });
+ !hiddenPids &&
+ printer.addContentWithNewLine({
+ text: `No agents have hidden processes`,
+ style: 'h3',
+ });
+
+ const hiddenPorts = await RootcheckRequest.agentsWithHiddenPorts(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ hiddenPorts &&
+ printer.addContent({
+ text: `${hiddenPorts} of ${totalAgents} agents have hidden ports`,
+ style: 'h3',
+ });
+ !hiddenPorts &&
+ printer.addContent({
+ text: `No agents have hidden ports`,
+ style: 'h3',
+ });
+ printer.addNewLine();
+ }
+
+ //--- OVERVIEW/AGENTS - PCI
+ if (['overview', 'agents'].includes(section) && tab === 'pci') {
+ log('reporting:extendedInformation', 'Fetching top PCI DSS requirements', 'debug');
+ const topPciRequirements = await PCIRequest.topPCIRequirements(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ printer.addContentWithNewLine({
+ text: 'Most common PCI DSS requirements alerts found',
+ style: 'h2',
+ });
+ for (const item of topPciRequirements) {
+ const rules = await PCIRequest.getRulesByRequirement(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ item,
+ pattern
+ );
+ printer.addContentWithNewLine({ text: `Requirement ${item}`, style: 'h3' });
+
+ if (PCI[item]) {
+ const content =
+ typeof PCI[item] === 'string' ? { text: PCI[item], style: 'standard' } : PCI[item];
+ printer.addContentWithNewLine(content);
+ }
+
+ rules &&
+ rules.length &&
+ printer.addSimpleTable({
+ columns: [
+ { id: 'ruleID', label: 'Rule ID' },
+ { id: 'ruleDescription', label: 'Description' },
+ ],
+ items: rules,
+ title: `Top rules for ${item} requirement`,
+ });
+ }
+ }
+
+ //--- OVERVIEW/AGENTS - TSC
+ if (['overview', 'agents'].includes(section) && tab === 'tsc') {
+ log('reporting:extendedInformation', 'Fetching top TSC requirements', 'debug');
+ const topTSCRequirements = await TSCRequest.topTSCRequirements(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ printer.addContentWithNewLine({
+ text: 'Most common TSC requirements alerts found',
+ style: 'h2',
+ });
+ for (const item of topTSCRequirements) {
+ const rules = await TSCRequest.getRulesByRequirement(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ item,
+ pattern
+ );
+ printer.addContentWithNewLine({ text: `Requirement ${item}`, style: 'h3' });
+
+ if (TSC[item]) {
+ const content =
+ typeof TSC[item] === 'string' ? { text: TSC[item], style: 'standard' } : TSC[item];
+ printer.addContentWithNewLine(content);
+ }
+
+ rules &&
+ rules.length &&
+ printer.addSimpleTable({
+ columns: [
+ { id: 'ruleID', label: 'Rule ID' },
+ { id: 'ruleDescription', label: 'Description' },
+ ],
+ items: rules,
+ title: `Top rules for ${item} requirement`,
+ });
+ }
+ }
+
+ //--- OVERVIEW/AGENTS - GDPR
+ if (['overview', 'agents'].includes(section) && tab === 'gdpr') {
+ log('reporting:extendedInformation', 'Fetching top GDPR requirements', 'debug');
+ const topGdprRequirements = await GDPRRequest.topGDPRRequirements(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ printer.addContentWithNewLine({
+ text: 'Most common GDPR requirements alerts found',
+ style: 'h2',
+ });
+ for (const item of topGdprRequirements) {
+ const rules = await GDPRRequest.getRulesByRequirement(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ item,
+ pattern
+ );
+ printer.addContentWithNewLine({ text: `Requirement ${item}`, style: 'h3' });
+
+ if (GDPR && GDPR[item]) {
+ const content =
+ typeof GDPR[item] === 'string' ? { text: GDPR[item], style: 'standard' } : GDPR[item];
+ printer.addContentWithNewLine(content);
+ }
+
+ rules &&
+ rules.length &&
+ printer.addSimpleTable({
+ columns: [
+ { id: 'ruleID', label: 'Rule ID' },
+ { id: 'ruleDescription', label: 'Description' },
+ ],
+ items: rules,
+ title: `Top rules for ${item} requirement`,
+ });
+ }
+ printer.addNewLine();
+ }
+
+ //--- OVERVIEW - AUDIT
+ if (section === 'overview' && tab === 'audit') {
+ log(
+ 'reporting:extendedInformation',
+ 'Fetching agents with high number of failed sudo commands',
+ 'debug'
+ );
+ const auditAgentsNonSuccess = await AuditRequest.getTop3AgentsSudoNonSuccessful(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ if (auditAgentsNonSuccess && auditAgentsNonSuccess.length) {
+ printer.addContent({
+ text: 'Agents with high number of failed sudo commands',
+ style: 'h2',
+ });
+ await buildAgentsTable(context, printer, auditAgentsNonSuccess, apiId);
+ }
+ const auditAgentsFailedSyscall = await AuditRequest.getTop3AgentsFailedSyscalls(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ if (auditAgentsFailedSyscall && auditAgentsFailedSyscall.length) {
+ printer.addSimpleTable({
+ columns: [
+ { id: 'agent', label: 'Agent ID' },
+ { id: 'syscall_id', label: 'Syscall ID' },
+ { id: 'syscall_syscall', label: 'Syscall' },
+ ],
+ items: auditAgentsFailedSyscall.map((item) => ({
+ agent: item.agent,
+ syscall_id: item.syscall.id,
+ syscall_syscall: item.syscall.syscall,
+ })),
+ title: {
+ text: 'Most common failing syscalls',
+ style: 'h2',
+ },
+ });
+ }
+ }
+
+ //--- OVERVIEW - FIM
+ if (section === 'overview' && tab === 'fim') {
+ log('reporting:extendedInformation', 'Fetching top 3 rules for FIM', 'debug');
+ const rules = await SyscheckRequest.top3Rules(context, from, to, filters, allowedAgentsFilter, pattern);
+
+ if (rules && rules.length) {
+ printer.addContentWithNewLine({ text: 'Top 3 FIM rules', style: 'h2' }).addSimpleTable({
+ columns: [
+ { id: 'ruleID', label: 'Rule ID' },
+ { id: 'ruleDescription', label: 'Description' },
+ ],
+ items: rules,
+ title: {
+ text: 'Top 3 rules that are generating most alerts.',
+ style: 'standard',
+ },
+ });
+ }
+
+ log('reporting:extendedInformation', 'Fetching top 3 agents for FIM', 'debug');
+ const agents = await SyscheckRequest.top3agents(context, from, to, filters, allowedAgentsFilter, pattern);
+
+ if (agents && agents.length) {
+ printer.addContentWithNewLine({
+ text: 'Agents with suspicious FIM activity',
+ style: 'h2',
+ });
+ printer.addContentWithNewLine({
+ text:
+ 'Top 3 agents that have most FIM alerts from level 7 to level 15. Take care about them.',
+ style: 'standard',
+ });
+ await buildAgentsTable(context, printer, agents, apiId);
+ }
+ }
+
+ //--- AGENTS - AUDIT
+ if (section === 'agents' && tab === 'audit') {
+ log('reporting:extendedInformation', `Fetching most common failed syscalls`, 'debug');
+ const auditFailedSyscall = await AuditRequest.getTopFailedSyscalls(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ auditFailedSyscall &&
+ auditFailedSyscall.length &&
+ printer.addSimpleTable({
+ columns: [
+ { id: 'id', label: 'id' },
+ { id: 'syscall', label: 'Syscall' },
+ ],
+ items: auditFailedSyscall,
+ title: 'Most common failing syscalls',
+ });
+ }
+
+ //--- AGENTS - FIM
+ if (section === 'agents' && tab === 'fim') {
+ log(
+ 'reporting:extendedInformation',
+ `Fetching syscheck database for agent ${agent}`,
+ 'debug'
+ );
+
+ const lastScanResponse = await context.wazuh.api.client.asCurrentUser.request(
+ 'GET',
+ `/syscheck/${agent}/last_scan`,
+ {},
+ { apiHostID: apiId }
+ );
+
+ if (lastScanResponse && lastScanResponse.data) {
+ const lastScanData = lastScanResponse.data.data.affected_items[0];
+ if (lastScanData.start && lastScanData.end) {
+ printer.addContent({
+ text: `Last file integrity monitoring scan was executed from ${lastScanData.start} to ${lastScanData.end}.`,
+ });
+ } else if (lastScanData.start) {
+ printer.addContent({
+ text: `File integrity monitoring scan is currently in progress for this agent (started on ${lastScanData.start}).`,
+ });
+ } else {
+ printer.addContent({
+ text: `File integrity monitoring scan is currently in progress for this agent.`,
+ });
+ }
+ printer.addNewLine();
+ }
+
+ log('reporting:extendedInformation', `Fetching last 10 deleted files for FIM`, 'debug');
+ const lastTenDeleted = await SyscheckRequest.lastTenDeletedFiles(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+
+ lastTenDeleted &&
+ lastTenDeleted.length &&
+ printer.addSimpleTable({
+ columns: [
+ { id: 'path', label: 'Path' },
+ { id: 'date', label: 'Date' },
+ ],
+ items: lastTenDeleted,
+ title: 'Last 10 deleted files',
+ });
+
+ log('reporting:extendedInformation', `Fetching last 10 modified files`, 'debug');
+ const lastTenModified = await SyscheckRequest.lastTenModifiedFiles(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+
+ lastTenModified &&
+ lastTenModified.length &&
+ printer.addSimpleTable({
+ columns: [
+ { id: 'path', label: 'Path' },
+ { id: 'date', label: 'Date' },
+ ],
+ items: lastTenModified,
+ title: 'Last 10 modified files',
+ });
+ }
+
+ //--- AGENTS - SYSCOLLECTOR
+ if (section === 'agents' && tab === 'syscollector') {
+ log(
+ 'reporting:extendedInformation',
+ `Fetching hardware information for agent ${agent}`,
+ 'debug'
+ );
+ const requestsSyscollectorLists = [
+ {
+ endpoint: `/syscollector/${agent}/hardware`,
+ loggerMessage: `Fetching Hardware information for agent ${agent}`,
+ list: {
+ title: { text: 'Hardware information', style: 'h2' },
+ },
+ mapResponse: (hardware) => [
+ hardware.cpu && hardware.cpu.cores && `${hardware.cpu.cores} cores`,
+ hardware.cpu && hardware.cpu.name,
+ hardware.ram &&
+ hardware.ram.total &&
+ `${Number(hardware.ram.total / 1024 / 1024).toFixed(2)}GB RAM`,
+ ],
+ },
+ {
+ endpoint: `/syscollector/${agent}/os`,
+ loggerMessage: `Fetching operating system information for agent ${agent}`,
+ list: {
+ title: { text: 'Operating system information', style: 'h2' },
+ },
+ mapResponse: (osData) => [
+ osData.sysname,
+ osData.version,
+ osData.architecture,
+ osData.release,
+ osData.os &&
+ osData.os.name &&
+ osData.os.version &&
+ `${osData.os.name} ${osData.os.version}`,
+ ],
+ },
+ ];
+
+ const syscollectorLists = await Promise.all(
+ requestsSyscollectorLists.map(async (requestSyscollector) => {
+ try {
+ log('reporting:extendedInformation', requestSyscollector.loggerMessage, 'debug');
+ const responseSyscollector = await context.wazuh.api.client.asCurrentUser.request(
+ 'GET',
+ requestSyscollector.endpoint,
+ {},
+ { apiHostID: apiId }
+ );
+ const [data] =
+ (responseSyscollector &&
+ responseSyscollector.data &&
+ responseSyscollector.data.data &&
+ responseSyscollector.data.data.affected_items) ||
+ [];
+ if (data) {
+ return {
+ ...requestSyscollector.list,
+ list: requestSyscollector.mapResponse(data),
+ };
+ }
+ } catch (error) {
+ log('reporting:extendedInformation', error.message || error);
+ }
+ })
+ );
+
+ if (syscollectorLists) {
+ syscollectorLists
+ .filter((syscollectorList) => syscollectorList)
+ .forEach((syscollectorList) => printer.addList(syscollectorList));
+ }
+
+ const vulnerabilitiesRequests = ['Critical', 'High'];
+
+ const vulnerabilitiesResponsesItems = (
+ await Promise.all(
+ vulnerabilitiesRequests.map(async (vulnerabilitiesLevel) => {
+ try {
+ log(
+ 'reporting:extendedInformation',
+ `Fetching top ${vulnerabilitiesLevel} packages`,
+ 'debug'
+ );
+
+ return await VulnerabilityRequest.topPackages(
+ context,
+ from,
+ to,
+ vulnerabilitiesLevel,
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ } catch (error) {
+ log('reporting:extendedInformation', error.message || error);
+ }
+ })
+ )
+ )
+ .filter((vulnerabilitiesResponse) => vulnerabilitiesResponse)
+ .flat();
+
+ if (vulnerabilitiesResponsesItems && vulnerabilitiesResponsesItems.length) {
+ printer.addSimpleTable({
+ title: { text: 'Vulnerable packages found (last 24 hours)', style: 'h2' },
+ columns: [
+ { id: 'package', label: 'Package' },
+ { id: 'severity', label: 'Severity' },
+ ],
+ items: vulnerabilitiesResponsesItems,
+ });
+ }
+ }
+
+ //--- AGENTS - VULNERABILITIES
+ if (section === 'agents' && tab === 'vuls') {
+ const topCriticalPackages = await VulnerabilityRequest.topPackagesWithCVE(
+ context,
+ from,
+ to,
+ 'Critical',
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ if (topCriticalPackages && topCriticalPackages.length) {
+ printer.addContentWithNewLine({ text: 'Critical severity', style: 'h2' });
+ printer.addContentWithNewLine({
+ text:
+ 'These vulnerabilties are critical, please review your agent. Click on each link to read more about each found vulnerability.',
+ style: 'standard',
+ });
+ const customul = [];
+ for (const critical of topCriticalPackages) {
+ customul.push({ text: critical.package, style: 'standard' });
+ customul.push({
+ ul: critical.references.map((item) => ({
+ text: item.substring(0, 80) + '...',
+ link: item,
+ color: '#1EA5C8',
+ })),
+ });
+ }
+ printer.addContentWithNewLine({ ul: customul });
+ }
+
+ const topHighPackages = await VulnerabilityRequest.topPackagesWithCVE(
+ context,
+ from,
+ to,
+ 'High',
+ filters,
+ allowedAgentsFilter,
+ pattern
+ );
+ if (topHighPackages && topHighPackages.length) {
+ printer.addContentWithNewLine({ text: 'High severity', style: 'h2' });
+ printer.addContentWithNewLine({
+ text: 'Click on each link to read more about each found vulnerability.',
+ style: 'standard',
+ });
+ const customul = [];
+ for (const critical of topHighPackages) {
+ customul.push({ text: critical.package, style: 'standard' });
+ customul.push({
+ ul: critical.references.map((item) => ({
+ text: item,
+ color: '#1EA5C8',
+ })),
+ });
+ }
+ customul && customul.length && printer.addContent({ ul: customul });
+ printer.addNewLine();
+ }
+ }
+
+ //--- SUMMARY TABLES
+ let extraSummaryTables = [];
+ if (Array.isArray(summaryTablesDefinitions[section][tab])) {
+ const tablesPromises = summaryTablesDefinitions[section][tab].map((summaryTable) => {
+ log('reporting:AlertsTable', `Fetching ${summaryTable.title} Table`, 'debug');
+ const alertsSummaryTable = new SummaryTable(
+ context,
+ from,
+ to,
+ filters,
+ allowedAgentsFilter,
+ summaryTable,
+ pattern
+ );
+ return alertsSummaryTable.fetch();
+ });
+ extraSummaryTables = await Promise.all(tablesPromises);
+ }
+
+ return extraSummaryTables;
+ } catch (error) {
+ log('reporting:extendedInformation', error.message || error);
+ return Promise.reject(error);
+ }
+}
diff --git a/server/lib/reporting/gdpr-request.ts b/server/lib/reporting/gdpr-request.ts
index c6cc5f97cb..e058804be2 100644
--- a/server/lib/reporting/gdpr-request.ts
+++ b/server/lib/reporting/gdpr-request.ts
@@ -10,7 +10,7 @@
* Find more information about this on the LICENSE file.
*/
import { Base } from './base-query';
-import { WAZUH_ALERTS_PATTERN } from '../../../common/constants';
+import { getSettingDefaultValue } from '../../../common/services/settings';
/**
* Returns top 5 GDPR requirements
@@ -21,11 +21,12 @@ import { WAZUH_ALERTS_PATTERN } from '../../../common/constants';
* @returns {Array}
*/
export const topGDPRRequirements = async (
- context,
- gte,
- lte,
- filters,
- pattern = WAZUH_ALERTS_PATTERN
+ context,
+ gte,
+ lte,
+ filters,
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
if (filters.includes('rule.gdpr: exists')) {
const [head, tail] = filters.split('AND rule.gdpr: exists');
@@ -35,7 +36,7 @@ export const topGDPRRequirements = async (
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -55,7 +56,7 @@ export const topGDPRRequirements = async (
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
@@ -76,13 +77,14 @@ export const topGDPRRequirements = async (
* @param {String} filters E.g: cluster.name: wazuh AND rule.groups: vulnerability
* @returns {Array}
*/
-export const getRulesByRequirement= async (
+export const getRulesByRequirement = async (
context,
gte,
lte,
filters,
+ allowedAgentsFilter,
requirement,
- pattern = WAZUH_ALERTS_PATTERN
+ pattern = getSettingDefaultValue('pattern')
) => {
if (filters.includes('rule.gdpr: exists')) {
const [head, tail] = filters.split('AND rule.gdpr: exists');
@@ -92,7 +94,7 @@ export const getRulesByRequirement= async (
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -120,7 +122,7 @@ export const getRulesByRequirement= async (
base.query.bool.must[0].query_string.query =
base.query.bool.must[0].query_string.query + ` AND rule.gdpr: "${requirement}"`;
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
@@ -136,7 +138,7 @@ export const getRulesByRequirement= async (
) {
return accum;
};
- accum.push({ruleID: bucket['3'].buckets[0].key, ruleDescription: bucket.key});
+ accum.push({ ruleID: bucket['3'].buckets[0].key, ruleDescription: bucket.key });
return accum;
}, []);
} catch (error) {
diff --git a/server/lib/reporting/overview-request.ts b/server/lib/reporting/overview-request.ts
index 748ceffd3b..7f8c587d81 100644
--- a/server/lib/reporting/overview-request.ts
+++ b/server/lib/reporting/overview-request.ts
@@ -10,7 +10,7 @@
* Find more information about this on the LICENSE file.
*/
import { Base } from './base-query';
-import { WAZUH_ALERTS_PATTERN } from '../../../common/constants';
+import { getSettingDefaultValue } from '../../../common/services/settings';
/**
* Returns top 3 agents with level 15 alerts
@@ -20,11 +20,11 @@ import { WAZUH_ALERTS_PATTERN } from '../../../common/constants';
* @param {String} filters E.g: cluster.name: wazuh AND rule.groups: vulnerability
* @returns {Array} E.g:['000','130','300']
*/
-export const topLevel15 = async (context, gte, lte, filters, pattern = WAZUH_ALERTS_PATTERN) => {
+export const topLevel15 = async (context, gte, lte, filters, allowedAgentsFilter, pattern = getSettingDefaultValue('pattern')) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -45,7 +45,7 @@ export const topLevel15 = async (context, gte, lte, filters, pattern = WAZUH_ALE
}
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
diff --git a/server/lib/reporting/pci-request.ts b/server/lib/reporting/pci-request.ts
index e579532d89..811d615561 100644
--- a/server/lib/reporting/pci-request.ts
+++ b/server/lib/reporting/pci-request.ts
@@ -10,7 +10,7 @@
* Find more information about this on the LICENSE file.
*/
import { Base } from './base-query';
-import { WAZUH_ALERTS_PATTERN } from '../../../common/constants';
+import { getSettingDefaultValue } from '../../../common/services/settings';
/**
* Returns top 5 PCI DSS requirements
@@ -25,7 +25,8 @@ export const topPCIRequirements = async (
gte,
lte,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
if (filters.includes('rule.pci_dss: exists')) {
filters = filters.replace('AND rule.pci_dss: exists', '');
@@ -34,7 +35,7 @@ export const topPCIRequirements = async (
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -54,7 +55,7 @@ export const topPCIRequirements = async (
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
@@ -95,8 +96,9 @@ export const getRulesByRequirement = async (
gte,
lte,
filters,
+ allowedAgentsFilter,
requirement,
- pattern = WAZUH_ALERTS_PATTERN
+ pattern = getSettingDefaultValue('pattern')
) => {
if (filters.includes('rule.pci_dss: exists')) {
filters = filters.replace('AND rule.pci_dss: exists', '');
@@ -105,7 +107,7 @@ export const getRulesByRequirement = async (
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -136,7 +138,7 @@ export const getRulesByRequirement = async (
requirement +
'"';
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
diff --git a/server/lib/reporting/printer.ts b/server/lib/reporting/printer.ts
index 7a2e09dba8..f31f2ea374 100644
--- a/server/lib/reporting/printer.ts
+++ b/server/lib/reporting/printer.ts
@@ -10,13 +10,14 @@ import {
import { log } from '../logger';
import * as TimSort from 'timsort';
import { getConfiguration } from '../get-configuration';
-import { REPORTS_PRIMARY_COLOR, REPORTS_LOGO_IMAGE_ASSETS_RELATIVE_PATH, REPORTS_PAGE_FOOTER_TEXT, REPORTS_PAGE_HEADER_TEXT } from '../../../common/constants';
+import { REPORTS_PRIMARY_COLOR} from '../../../common/constants';
+import { getCustomizationSetting } from '../../../common/services/settings';
const COLORS = {
PRIMARY: REPORTS_PRIMARY_COLOR
};
-const pageConfiguration = (nameLogo) => ({
+const pageConfiguration = ({ pathToLogo, pageHeader, pageFooter }) => ({
styles: {
h1: {
fontSize: 22,
@@ -54,14 +55,15 @@ const pageConfiguration = (nameLogo) => ({
margin: [40, 20, 0, 0],
columns: [
{
- image: path.join(__dirname, `../../../public/assets/${nameLogo}`),
- width: 190
+ image: path.join(__dirname, `../../../public/assets/${pathToLogo}`),
+ fit: [190, 50]
},
{
- text: REPORTS_PAGE_HEADER_TEXT,
+ text: pageHeader,
alignment: 'right',
margin: [0, 0, 40, 0],
- color: COLORS.PRIMARY
+ color: COLORS.PRIMARY,
+ width: 'auto'
}
]
},
@@ -70,7 +72,7 @@ const pageConfiguration = (nameLogo) => ({
return {
columns: [
{
- text: REPORTS_PAGE_FOOTER_TEXT,
+ text: pageFooter,
color: COLORS.PRIMARY,
margin: [40, 40, 0, 0]
},
@@ -78,7 +80,8 @@ const pageConfiguration = (nameLogo) => ({
text: 'Page ' + currentPage.toString() + ' of ' + pageCount,
alignment: 'right',
margin: [0, 40, 40, 0],
- color: COLORS.PRIMARY
+ color: COLORS.PRIMARY,
+ width: 'auto'
}
]
};
@@ -473,7 +476,7 @@ export class ReportPrinter{
this.addContent(typeof title === 'string' ? { text: title, style: 'h4' } : title)
.addNewLine();
}
-
+
if (!items || !items.length) {
this.addContent({
text: 'No results match your search criteria',
@@ -494,23 +497,23 @@ export class ReportPrinter{
style: 'standard'
}
})
- });
+ });
// 385 is the max initial width per column
let totalLength = columns.length - 1;
const widthColumn = 385/totalLength;
let totalWidth = totalLength * widthColumn;
-
+
const widths:(number)[] = [];
-
+
for (let step = 0; step < columns.length - 1; step++) {
let columnLength = this.getColumnWidth(columns[step], tableRows, step);
-
+
if (columnLength <= Math.round(totalWidth / totalLength)) {
widths.push(columnLength);
totalWidth -= columnLength;
- }
+ }
else {
widths.push(Math.round(totalWidth / totalLength));
totalWidth -= Math.round((totalWidth / totalLength));
@@ -518,7 +521,7 @@ export class ReportPrinter{
totalLength--;
}
widths.push('*');
-
+
this.addContent({
fontSize: 8,
table: {
@@ -562,9 +565,9 @@ export class ReportPrinter{
`agents: ${agents}`,
'debug'
);
-
+
this.addNewLine();
-
+
this.addContent({
text:
'NOTE: This report only includes the authorized agents of the user who generated the report',
@@ -613,22 +616,36 @@ export class ReportPrinter{
);
}
- async print(reportPath: string){
- const nameLogo = ( await getConfiguration() )['customization.logo.reports'] || REPORTS_LOGO_IMAGE_ASSETS_RELATIVE_PATH;
+ async print(reportPath: string) {
+ return new Promise((resolve, reject) => {
+ try {
+ const configuration = getConfiguration();
- const document = this._printer.createPdfKitDocument({...pageConfiguration(nameLogo), content: this._content});
- await document.pipe(
- fs.createWriteStream(reportPath)
- );
- document.end();
+ const pathToLogo = getCustomizationSetting(configuration, 'customization.logo.reports');
+ const pageHeader = getCustomizationSetting(configuration, 'customization.reports.header');
+ const pageFooter = getCustomizationSetting(configuration, 'customization.reports.footer');
+
+ const document = this._printer.createPdfKitDocument({ ...pageConfiguration({ pathToLogo, pageHeader, pageFooter }), content: this._content });
+
+ document.on('error', reject);
+ document.on('end', resolve);
+
+ document.pipe(
+ fs.createWriteStream(reportPath)
+ );
+ document.end();
+ } catch (ex) {
+ reject(ex);
+ }
+ });
}
/**
* Returns the width of a given column
- *
- * @param column
- * @param tableRows
- * @param step
+ *
+ * @param column
+ * @param tableRows
+ * @param step
* @returns {number}
*/
getColumnWidth(column, tableRows, index){
diff --git a/server/lib/reporting/rootcheck-request.ts b/server/lib/reporting/rootcheck-request.ts
index c7d4cdd510..0eede80de9 100644
--- a/server/lib/reporting/rootcheck-request.ts
+++ b/server/lib/reporting/rootcheck-request.ts
@@ -10,7 +10,7 @@
* Find more information about this on the LICENSE file.
*/
import { Base } from './base-query';
-import { WAZUH_ALERTS_PATTERN } from '../../../common/constants';
+import { getSettingDefaultValue } from '../../../common/services/settings';
/**
* Returns top 5 rootkits found along all agents
@@ -25,13 +25,14 @@ export const top5RootkitsDetected = async (
gte,
lte,
filters,
- pattern = WAZUH_ALERTS_PATTERN,
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern'),
size = 5
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -49,7 +50,7 @@ export const top5RootkitsDetected = async (
base.query.bool.must[0].query_string.query +
' AND "rootkit" AND "detected"';
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
@@ -80,12 +81,13 @@ export const agentsWithHiddenPids = async (
gte,
lte,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'1': {
@@ -100,7 +102,7 @@ export const agentsWithHiddenPids = async (
' AND "process" AND "hidden"';
// "aggregations": { "1": { "value": 1 } }
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
@@ -129,12 +131,13 @@ export const agentsWithHiddenPorts = async(
gte,
lte,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'1': {
@@ -148,7 +151,7 @@ export const agentsWithHiddenPorts = async(
base.query.bool.must[0].query_string.query + ' AND "port" AND "hidden"';
// "aggregations": { "1": { "value": 1 } }
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
diff --git a/server/lib/reporting/summary-table.ts b/server/lib/reporting/summary-table.ts
new file mode 100644
index 0000000000..649f0895d5
--- /dev/null
+++ b/server/lib/reporting/summary-table.ts
@@ -0,0 +1,152 @@
+/*
+ * Wazuh app - Specific methods to fetch Wazuh overview data from Elasticsearch
+ * Copyright (C) 2015-2022 Wazuh, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Find more information about this on the LICENSE file.
+ */
+import { Base } from './base-query';
+import { getSettingDefaultValue } from '../../../common/services/settings';
+
+interface SummarySetup {
+ title: string;
+ aggs: any
+}
+
+export default class SummaryTable {
+ constructor(
+ context,
+ gte,
+ lte,
+ filters,
+ allowedAgentsFilter,
+ summarySetup: SummarySetup,
+ pattern = getSettingDefaultValue('pattern')
+ ) {
+
+ this._context = context;
+ this._pattern = pattern;
+ this._summarySetup = summarySetup;
+ this._base = { aggs: {} };
+ this._columns = [];
+ this._rows = [];
+ this._title = summarySetup.title;
+
+ Object.assign(this._base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
+
+ this._parseSummarySetup(summarySetup);
+
+ }
+
+ /**
+ * Parse the summary table setup to build the query
+ * @param summarySetup
+ */
+ _parseSummarySetup(summarySetup: SummarySetup) {
+ let baseAggRef = this._base.aggs;
+ summarySetup.aggs.forEach((agg, key) => {
+ this._columns.push(agg.customLabel);
+ this._parseAggregation(baseAggRef, agg, key);
+
+ if (summarySetup.aggs.length > key + 1) {
+ baseAggRef[`${key + 2}`].aggs = {};
+ baseAggRef = baseAggRef[`${key + 2}`].aggs;
+ } else {
+ this._columns.push('Count');
+ }
+ }, this);
+ }
+
+ /**
+ * Parse each aggregation to build the query
+ * @param baseAggRef
+ * @param agg
+ * @param key
+ */
+ _parseAggregation(baseAggRef: any, agg: any, key: string) {
+ const { field, size, order, missing } = agg;
+
+ baseAggRef[`${key + 2}`] = {
+ terms: {
+ field,
+ order: {
+ _count: order
+ },
+ size
+ }
+ };
+ if (missing) {
+ baseAggRef[`${key + 2}`].terms.missing = missing;
+ }
+ }
+
+ /**
+ * Returns the response formatted to a table
+ * @description The response is an object with the following structure:{
+ * title: 'Alerts summary',
+ * columns: ['Rule ID','Description','Level', 'Count'],
+ * rows: [
+ * ['502', 'Ossec server started', 3, 22],
+ * ['502', 'Ossec server started', 3, 22],
+ * ]
+ * }
+ * @param rawResponse
+ */
+ _formatResponseToTable(rawResponse) {
+ const firstKey = parseInt(Object.keys(rawResponse)[0]);
+
+ this._rows = rawResponse[firstKey].buckets.reduce((totalRows, bucket) => {
+ const nextKey = firstKey + 1;
+ this._buildRow(bucket, nextKey, totalRows);
+ return totalRows;
+ }, []);
+
+ return {
+ rows: this._rows,
+ columns: this._columns,
+ title: this._title,
+ }
+ }
+
+ /**
+ * Makes a row from the response
+ * @param bucket
+ * @param nextAggKey
+ * @param row
+ */
+ _buildRow(bucket: any, nextAggKey: number, totalRows: any[], row: any[] = []): any[] {
+ const newRow = [...row, bucket.key];
+ // If there is a next aggregation, repeat the process
+ if (bucket[nextAggKey.toString()]?.buckets?.length) {
+ bucket[nextAggKey.toString()].buckets.forEach(newBucket => {
+ this._buildRow(newBucket, (nextAggKey + 1), totalRows, newRow);
+ });
+ }
+ // Add the Count as the last item in the row
+ else if (bucket.doc_count) {
+ newRow.push(bucket.doc_count);
+ totalRows.push(newRow);
+ }
+ }
+
+ /**
+ * Executes the query and returns the response
+ */
+ async fetch() {
+ try {
+ const response = await this._context.core.opensearch.client.asCurrentUser.search({
+ index: this._pattern,
+ body: this._base
+ });
+ const alertsTable = this._formatResponseToTable(response.body.aggregations);
+ return alertsTable;
+ } catch (error) {
+ return Promise.reject(error);
+ }
+ }
+
+}
diff --git a/server/lib/reporting/summary-tables-definitions/agents/index.ts b/server/lib/reporting/summary-tables-definitions/agents/index.ts
new file mode 100644
index 0000000000..46dee71df3
--- /dev/null
+++ b/server/lib/reporting/summary-tables-definitions/agents/index.ts
@@ -0,0 +1,194 @@
+import { AggregationFields } from '../aggregation_fields';
+
+const generalAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.id'],
+ AggregationFields['rule.description'],
+ AggregationFields['rule.level'],
+ ]
+}
+
+const generalGroupsSummary = {
+ title: 'Groups summary',
+ aggs: [
+ AggregationFields['rule.groups'],
+ ]
+}
+
+const awsAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.id'],
+ AggregationFields['rule.description'],
+ AggregationFields['rule.level'],
+ ]
+}
+
+const fimAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['syscheck.path'],
+ AggregationFields['rule.description'],
+ ]
+}
+const gcpAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.id'],
+ AggregationFields['rule.description'],
+ AggregationFields['rule.level'],
+ ]
+}
+
+const virustotalAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.id'],
+ AggregationFields['rule.description'],
+ AggregationFields['rule.level'],
+ ]
+}
+
+const osqueryAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['data.osquery.name'],
+ AggregationFields['data.osquery.action'],
+ AggregationFields['agent.name'],
+ AggregationFields['data.osquery.pack'],
+ AggregationFields['data.osquery.calendarTime'],
+ ]
+}
+
+const mitreAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.id'],
+ AggregationFields['rule.description'],
+ AggregationFields['rule.level'],
+ ]
+}
+
+const ciscatAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['data.cis.rule_title'],
+ AggregationFields['data.cis.group'],
+ AggregationFields['data.cis.result'],
+ ]
+}
+
+const pmAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.description'],
+ AggregationFields['data.title'],
+ ]
+}
+
+const tscAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['agent.name'],
+ AggregationFields['rule.tsc'],
+ AggregationFields['rule.description'],
+ ]
+}
+
+const githubAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['agent.name'],
+ AggregationFields['data.github.org'],
+ AggregationFields['rule.description'],
+ ]
+}
+
+// 'Wazuh-App-Agents-GDPR-Last-alerts'
+const gdprLastAlerts = {
+ title: 'Last alerts',
+ aggs: [
+ AggregationFields['rule.gdpr'],
+ AggregationFields['rule.description'],
+ ]
+
+}
+
+// 'Wazuh-App-Agents-PCI-Last-alerts'
+const pciLastAlerts = {
+ title: 'Last alerts',
+ aggs: [
+ AggregationFields['rule.pci_dss'],
+ AggregationFields['rule.description'],
+ ]
+}
+
+// 'Wazuh-App-Agents-NIST-Last-alerts'
+const nistLastAlerts = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.nist_800_53'],
+ AggregationFields['rule.level'],
+ AggregationFields['rule.description'],
+ ]
+}
+
+// 'Wazuh-App-Agents-HIPAA-Last-alerts'
+const hipaaLastAlerts = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.hipaa'],
+ AggregationFields['rule.level'],
+ AggregationFields['rule.description'],
+ ]
+}
+
+// 'Wazuh-App-Agents-OSCAP-Last-alerts'
+const oscapLastAlerts = {
+ title: 'Last alerts',
+ aggs: [
+ AggregationFields['data.oscap.check.title'],
+ AggregationFields['data.oscap.scan.profile.title'],
+ ]
+}
+
+// 'Wazuh-App-Agents-Audit-Last-alerts'
+const auditLastAlerts = {
+ title: 'Last alerts',
+ aggs: [
+ AggregationFields['rule.description'],
+ AggregationFields['data.audit.exe'],
+ AggregationFields['data.audit.type'],
+ ]
+}
+
+const dockerAlertsSummary = {
+ title: 'Events summary',
+ aggs: [
+ AggregationFields['data.docker.Actor.Attributes.name'],
+ AggregationFields['data.docker.Action'],
+ AggregationFields['timestamp'],
+ ]
+}
+
+export default {
+ general: [generalAlertsSummary, generalGroupsSummary],
+ aws: [awsAlertsSummary],
+ fim: [fimAlertsSummary],
+ github: [githubAlertsSummary],
+ hipaa: [hipaaLastAlerts],
+ nist: [nistLastAlerts],
+ gcp: [gcpAlertsSummary],
+ tsc: [tscAlertsSummary],
+ virustotal: [virustotalAlertsSummary],
+ osquery: [osqueryAlertsSummary],
+ mitre: [mitreAlertsSummary],
+ ciscat: [ciscatAlertsSummary],
+ pm: [pmAlertsSummary],
+ audit: [auditLastAlerts],
+ oscap: [oscapLastAlerts],
+ gdpr: [gdprLastAlerts],
+ pci: [pciLastAlerts],
+ docker: [dockerAlertsSummary],
+}
diff --git a/server/lib/reporting/summary-tables-definitions/aggregation_fields.ts b/server/lib/reporting/summary-tables-definitions/aggregation_fields.ts
new file mode 100644
index 0000000000..d1088e8dd9
--- /dev/null
+++ b/server/lib/reporting/summary-tables-definitions/aggregation_fields.ts
@@ -0,0 +1,222 @@
+export const AggregationFields = {
+ 'rule.id': {
+ field: 'rule.id',
+ size: 50,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Rule ID',
+ },
+ 'rule.description': {
+ field: 'rule.description',
+ size: 20,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Description',
+ },
+ 'rule.level': {
+ field: 'rule.level',
+ size: 12,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Level',
+ },
+ 'rule.groups': {
+ field: 'rule.groups',
+ size: 50,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Groups',
+ missing: '-',
+ },
+ 'agent.name': {
+ field: 'agent.name',
+ size: 1000,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Agent name',
+ missing: '-',
+ },
+ 'syscheck.path': {
+ field: 'syscheck.path',
+ size: 20,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Path',
+ missing: '-',
+ },
+ 'syscheck.event': {
+ field: 'syscheck.event',
+ size: 12,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Action',
+ missing: '-',
+ },
+ 'rule.pci_dss': {
+ field: 'rule.pci_dss',
+ size: 10,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Requirement',
+ missing: '-',
+ },
+ 'rule.gdpr': {
+ field: 'rule.gdpr',
+ size: 10,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Requirement',
+ missing: '-',
+ },
+ 'rule.nist_800_53': {
+ field: 'rule.nist_800_53',
+ size: 10,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Requirement',
+ missing: '-',
+ },
+ 'rule.hipaa': {
+ field: 'rule.hipaa',
+ size: 10,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Requirement',
+ missing: '-',
+ },
+ 'rule.tsc': {
+ field: 'rule.tsc',
+ size: 10,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Requirement',
+ missing: '-',
+ },
+ 'data.audit.exe': {
+ field: 'data.audit.exe',
+ size: 10,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Command',
+ missing: '-',
+ },
+ 'data.audit.type': {
+ field: 'data.audit.type',
+ size: 5,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Type',
+ missing: '-',
+ },
+ 'data.osquery.name': {
+ field: 'data.osquery.name',
+ size: 20,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Name',
+ missing: '-',
+ },
+ 'data.osquery.action': {
+ field: 'data.osquery.action',
+ size: 5,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Action',
+ missing: '-',
+ },
+ 'data.osquery.pack': {
+ field: 'data.osquery.pack',
+ size: 5,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Pack',
+ missing: '-',
+ },
+ 'data.osquery.calendarTime': {
+ field: 'data.osquery.calendarTime',
+ size: 2,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Date',
+ missing: '-',
+ },
+ 'data.cis.rule_title': {
+ field: 'data.cis.rule_title',
+ size: 50,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Rule title',
+ missing: '-',
+ },
+ 'data.cis.group': {
+ field: 'data.cis.group',
+ size: 50,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Group',
+ missing: '-',
+ },
+ 'data.cis.result': {
+ field: 'data.cis.result',
+ size: 10,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Result',
+ missing: '-',
+ },
+ 'data.title': {
+ field: 'data.title',
+ size: 10,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Control',
+ missing: '-',
+ },
+ 'data.docker.Actor.Attributes.name': {
+ field: 'data.docker.Actor.Attributes.name',
+ size: 50,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Container',
+ missing: '-',
+ },
+ 'data.docker.Action': {
+ field: 'data.docker.Action',
+ size: 20,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Action',
+ missing: '-',
+ },
+ 'timestamp': {
+ field: 'timestamp',
+ size: 5,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Date',
+ },
+ 'data.github.org': {
+ field: 'data.github.org',
+ size: 10,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Organization',
+ missing: '-',
+ },
+ 'data.oscap.check.title': {
+ field: 'data.oscap.check.title',
+ size: 5,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Title',
+ missing: '-',
+ },
+ 'data.oscap.scan.profile.title': {
+ field: 'data.oscap.scan.profile.title',
+ size: 5,
+ order: 'desc',
+ orderBy: '1',
+ customLabel: 'Profile',
+ missing: '-',
+ },
+};
diff --git a/server/lib/reporting/summary-tables-definitions/index.ts b/server/lib/reporting/summary-tables-definitions/index.ts
new file mode 100644
index 0000000000..1b25e9820f
--- /dev/null
+++ b/server/lib/reporting/summary-tables-definitions/index.ts
@@ -0,0 +1,6 @@
+import agents from './agents';
+import overview from './overview';
+export default {
+ agents,
+ overview
+}
diff --git a/server/lib/reporting/summary-tables-definitions/overview/index.ts b/server/lib/reporting/summary-tables-definitions/overview/index.ts
new file mode 100644
index 0000000000..e701729fce
--- /dev/null
+++ b/server/lib/reporting/summary-tables-definitions/overview/index.ts
@@ -0,0 +1,194 @@
+import { AggregationFields } from '../aggregation_fields';
+const generalAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.id'],
+ AggregationFields['rule.description'],
+ AggregationFields['rule.level'],
+ ]
+}
+
+const awsAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.id'],
+ AggregationFields['rule.description'],
+ AggregationFields['rule.level'],
+ ]
+}
+
+const fimAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['agent.name'],
+ AggregationFields['syscheck.path'],
+ AggregationFields['syscheck.event'],
+ ]
+}
+
+const gcpAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.id'],
+ AggregationFields['rule.description'],
+ AggregationFields['rule.level'],
+ ]
+}
+
+const officeAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.id'],
+ AggregationFields['rule.description'],
+ AggregationFields['rule.level'],
+ ]
+}
+
+const pciAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['agent.name'],
+ AggregationFields['rule.pci_dss'],
+ AggregationFields['rule.description'],
+ ]
+}
+
+const gdprAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['agent.name'],
+ AggregationFields['rule.gdpr'],
+ AggregationFields['rule.description'],
+ ]
+}
+
+const nistAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['agent.name'],
+ AggregationFields['rule.nist_800_53'],
+ AggregationFields['rule.level'],
+ ]
+}
+
+const hipaaAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['agent.name'],
+ AggregationFields['rule.hipaa'],
+ AggregationFields['rule.level'],
+ ]
+}
+
+const tscAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['agent.name'],
+ AggregationFields['rule.tsc'],
+ AggregationFields['rule.description'],
+ ]
+}
+
+const virustotalAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.id'],
+ AggregationFields['rule.description'],
+ AggregationFields['rule.level'],
+ ]
+}
+
+const osqueryAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['data.osquery.name'],
+ AggregationFields['data.osquery.action'],
+ AggregationFields['agent.name'],
+ AggregationFields['data.osquery.pack'],
+ AggregationFields['data.osquery.calendarTime'],
+ ]
+}
+
+const mitreAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.id'],
+ AggregationFields['rule.description'],
+ AggregationFields['rule.level'],
+ ]
+}
+const ciscatAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['data.cis.rule_title'],
+ AggregationFields['data.cis.group'],
+ AggregationFields['data.cis.result'],
+ ]
+}
+const pmAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['rule.description'],
+ AggregationFields['data.title'],
+ ]
+}
+
+const dockerAlertsSummary = {
+ title: 'Events summary',
+ aggs: [
+ AggregationFields['data.docker.Actor.Attributes.name'],
+ AggregationFields['data.docker.Action'],
+ AggregationFields['timestamp'],
+ ]
+}
+
+const githubAlertsSummary = {
+ title: 'Alerts summary',
+ aggs: [
+ AggregationFields['agent.name'],
+ AggregationFields['data.github.org'],
+ AggregationFields['rule.description'],
+ ]
+}
+
+// 'Wazuh-App-Overview-OSCAP-Last-alerts'
+const oscapLastAlerts = {
+ title: 'Last alerts',
+ aggs: [
+ AggregationFields['agent.name'],
+ AggregationFields['data.oscap.check.title'],
+ AggregationFields['data.oscap.scan.profile.title'],
+ ]
+}
+
+// 'Wazuh-App-Overview-Audit-Last-alerts'
+const auditLastAlerts = {
+ title: 'Last alerts',
+ aggs: [
+ AggregationFields['agent.name'],
+ AggregationFields['rule.description'],
+ AggregationFields['data.audit.exe'],
+ ]
+}
+
+export default {
+ aws: [awsAlertsSummary],
+ ciscat: [ciscatAlertsSummary],
+ docker: [dockerAlertsSummary],
+ fim: [fimAlertsSummary],
+ gcp: [gcpAlertsSummary],
+ gdpr: [gdprAlertsSummary],
+ general: [generalAlertsSummary],
+ github: [githubAlertsSummary],
+ hipaa: [hipaaAlertsSummary],
+ mitre: [mitreAlertsSummary],
+ nist: [nistAlertsSummary],
+ office: [officeAlertsSummary],
+ oscap: [oscapLastAlerts],
+ osquery: [osqueryAlertsSummary],
+ pci: [pciAlertsSummary],
+ pm: [pmAlertsSummary],
+ tsc: [tscAlertsSummary],
+ virustotal: [virustotalAlertsSummary],
+ audit: [auditLastAlerts],
+}
diff --git a/server/lib/reporting/syscheck-request.ts b/server/lib/reporting/syscheck-request.ts
index 9016a93ee6..2e3981c18d 100644
--- a/server/lib/reporting/syscheck-request.ts
+++ b/server/lib/reporting/syscheck-request.ts
@@ -10,7 +10,7 @@
* Find more information about this on the LICENSE file.
*/
import { Base } from './base-query';
-import { WAZUH_ALERTS_PATTERN } from '../../../common/constants';
+import { getSettingDefaultValue } from '../../../common/services/settings';
/**
@@ -22,16 +22,17 @@ import { WAZUH_ALERTS_PATTERN } from '../../../common/constants';
* @returns {Array}
*/
export const top3agents = async (
- context,
- gte,
- lte,
+ context,
+ gte,
+ lte,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -54,7 +55,7 @@ export const top3agents = async (
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
@@ -78,12 +79,13 @@ export const top3Rules = async (
gte,
lte,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -108,7 +110,7 @@ export const top3Rules = async (
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
@@ -137,12 +139,13 @@ export const lastTenDeletedFiles = async (
gte,
lte,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -171,7 +174,7 @@ export const lastTenDeletedFiles = async (
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
@@ -190,12 +193,13 @@ export const lastTenModifiedFiles = async (
gte,
lte,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -224,7 +228,7 @@ export const lastTenModifiedFiles = async (
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
diff --git a/server/lib/reporting/tsc-request.ts b/server/lib/reporting/tsc-request.ts
index 753258a38e..aa59d6f6bc 100644
--- a/server/lib/reporting/tsc-request.ts
+++ b/server/lib/reporting/tsc-request.ts
@@ -10,7 +10,7 @@
* Find more information about this on the LICENSE file.
*/
import { Base } from './base-query';
-import { WAZUH_ALERTS_PATTERN } from '../../../common/constants';
+import { getSettingDefaultValue } from '../../../common/services/settings';
/**
* Returns top 5 TSC requirements
@@ -25,7 +25,8 @@ export const topTSCRequirements = async (
gte,
lte,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
if (filters.includes('rule.tsc: exists')) {
filters = filters.replace('AND rule.tsc: exists', '');
@@ -34,7 +35,7 @@ export const topTSCRequirements = async (
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -54,7 +55,7 @@ export const topTSCRequirements = async (
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
@@ -91,12 +92,13 @@ export const topTSCRequirements = async (
* @returns {Array}
*/
export const getRulesByRequirement = async (
- context,
+ context,
gte,
lte,
filters,
+ allowedAgentsFilter,
requirement,
- pattern = WAZUH_ALERTS_PATTERN
+ pattern = getSettingDefaultValue('pattern')
) => {
if (filters.includes('rule.tsc: exists')) {
filters = filters.replace('AND rule.tsc: exists', '');
@@ -105,7 +107,7 @@ export const getRulesByRequirement = async (
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -136,7 +138,7 @@ export const getRulesByRequirement = async (
requirement +
'"';
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
diff --git a/server/lib/reporting/vulnerability-request.ts b/server/lib/reporting/vulnerability-request.ts
index c5e1c62d4b..a60bc46c4b 100644
--- a/server/lib/reporting/vulnerability-request.ts
+++ b/server/lib/reporting/vulnerability-request.ts
@@ -9,8 +9,8 @@
*
* Find more information about this on the LICENSE file.
*/
+import { getSettingDefaultValue } from '../../../common/services/settings';
import { Base } from './base-query';
-import { WAZUH_ALERTS_PATTERN } from '../../../common/constants';
/**
* Returns top 3 agents for specific severity
@@ -27,12 +27,13 @@ export const topAgentCount = async (
lte,
severity,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -54,7 +55,7 @@ export const topAgentCount = async (
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
@@ -75,16 +76,17 @@ export const topAgentCount = async (
* @returns {Array}
*/
export const topCVECount = async (
- context,
- gte,
- lte,
- filters,
- pattern = WAZUH_ALERTS_PATTERN
+ context,
+ gte,
+ lte,
+ filters,
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -98,7 +100,7 @@ export const topCVECount = async (
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
@@ -125,12 +127,13 @@ export const uniqueSeverityCount = async (
lte,
severity,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'1': {
@@ -148,7 +151,7 @@ export const uniqueSeverityCount = async (
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
@@ -170,12 +173,13 @@ export const topPackages = async (
lte,
severity,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -197,7 +201,7 @@ export const topPackages = async (
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
@@ -213,18 +217,19 @@ export const topPackages = async (
}
}
-export const topPackagesWithCVE = async(
+export const topPackagesWithCVE = async (
context,
gte,
lte,
severity,
filters,
- pattern = WAZUH_ALERTS_PATTERN
+ allowedAgentsFilter,
+ pattern = getSettingDefaultValue('pattern')
) => {
try {
const base = {};
- Object.assign(base, Base(pattern, filters, gte, lte));
+ Object.assign(base, Base(pattern, filters, gte, lte, allowedAgentsFilter));
Object.assign(base.aggs, {
'2': {
@@ -257,7 +262,7 @@ export const topPackagesWithCVE = async(
}
});
- const response = await context.core.elasticsearch.client.asCurrentUser.search({
+ const response = await context.core.opensearch.client.asCurrentUser.search({
index: pattern,
body: base
});
diff --git a/server/lib/security-factory/factories/default-factory.ts b/server/lib/security-factory/factories/default-factory.ts
index 76cd520552..4c29ef5130 100644
--- a/server/lib/security-factory/factories/default-factory.ts
+++ b/server/lib/security-factory/factories/default-factory.ts
@@ -1,15 +1,15 @@
import { ISecurityFactory } from '../';
+import { OpenSearchDashboardsRequest, RequestHandlerContext } from 'src/core/server';
import { ELASTIC_NAME } from '../../../../common/constants';
-import { KibanaRequest, RequestHandlerContext } from 'src/core/server';
import md5 from 'md5';
export class DefaultFactory implements ISecurityFactory{
platform: string = '';
- async getCurrentUser(request: KibanaRequest, context?:RequestHandlerContext) {
- return {
+ async getCurrentUser(request: OpenSearchDashboardsRequest, context?:RequestHandlerContext) {
+ return {
username: ELASTIC_NAME,
authContext: { username: ELASTIC_NAME },
hashUsername: md5(ELASTIC_NAME)
};
}
-}
\ No newline at end of file
+}
diff --git a/server/lib/security-factory/factories/index.ts b/server/lib/security-factory/factories/index.ts
index f00687b9ae..b02efdd30a 100644
--- a/server/lib/security-factory/factories/index.ts
+++ b/server/lib/security-factory/factories/index.ts
@@ -1,3 +1,2 @@
-export { OpendistroFactory } from './opendistro-factory';
-export { XpackFactory } from './xpack-factory';
+export { OpenSearchDashboardsSecurityFactory } from './opensearch-dashboards-security-factory';
export { DefaultFactory } from './default-factory';
\ No newline at end of file
diff --git a/server/lib/security-factory/factories/opendistro-factory.ts b/server/lib/security-factory/factories/opendistro-factory.ts
deleted file mode 100644
index b6d6e820f9..0000000000
--- a/server/lib/security-factory/factories/opendistro-factory.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { ISecurityFactory } from '../'
-import { KibanaRequest, RequestHandlerContext } from 'src/core/server';
-import { WAZUH_SECURITY_PLUGIN_OPEN_DISTRO_FOR_ELASTICSEARCH } from '../../../../common/constants';
-import md5 from 'md5';
-
-export class OpendistroFactory implements ISecurityFactory {
- platform: string = WAZUH_SECURITY_PLUGIN_OPEN_DISTRO_FOR_ELASTICSEARCH;
-
- constructor(private opendistroSecurityKibana: any) {
- }
-
- async getCurrentUser(request: KibanaRequest, context:RequestHandlerContext) {
- try {
- const params = {
- path: `/_opendistro/_security/api/account`,
- method: 'GET',
- };
-
- const {body: authContext} = await context.core.elasticsearch.client.asCurrentUser.transport.request(params);
- const username = this.getUserName(authContext);
- return { username, authContext, hashUsername: md5(username) };
- } catch (error) {
- throw error;
- }
- }
-
- getUserName(authContext:any) {
- return authContext['user_name']
- }
-}
\ No newline at end of file
diff --git a/server/lib/security-factory/factories/opensearch-dashboards-security-factory.ts b/server/lib/security-factory/factories/opensearch-dashboards-security-factory.ts
new file mode 100644
index 0000000000..b0cf81dbfc
--- /dev/null
+++ b/server/lib/security-factory/factories/opensearch-dashboards-security-factory.ts
@@ -0,0 +1,30 @@
+import { ISecurityFactory } from '..'
+import { OpenSearchDashboardsRequest, RequestHandlerContext } from 'src/core/server';
+import { WAZUH_SECURITY_PLUGIN_OPENSEARCH_DASHBOARDS_SECURITY } from '../../../../common/constants';
+import md5 from 'md5';
+
+export class OpenSearchDashboardsSecurityFactory implements ISecurityFactory {
+ platform: string = WAZUH_SECURITY_PLUGIN_OPENSEARCH_DASHBOARDS_SECURITY;
+
+ constructor(private securityDashboards: any) {
+ }
+
+ async getCurrentUser(request: OpenSearchDashboardsRequest, context:RequestHandlerContext) {
+ try {
+ const params = {
+ path: `/_opendistro/_security/api/account`,
+ method: 'GET',
+ };
+
+ const {body: authContext} = await context.core.opensearch.client.asCurrentUser.transport.request(params);
+ const username = this.getUserName(authContext);
+ return { username, authContext, hashUsername: md5(username) };
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ getUserName(authContext:any) {
+ return authContext['user_name']
+ }
+}
diff --git a/server/lib/security-factory/factories/xpack-factory.ts b/server/lib/security-factory/factories/xpack-factory.ts
deleted file mode 100644
index 7df643f8d5..0000000000
--- a/server/lib/security-factory/factories/xpack-factory.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { ISecurityFactory } from '../'
-import { SecurityPluginSetup } from 'x-pack/plugins/security/server';
-import { KibanaRequest } from 'src/core/server';
-import { WAZUH_SECURITY_PLUGIN_XPACK_SECURITY, ELASTIC_NAME } from '../../../../common/constants';
-import md5 from 'md5';
-
-export class XpackFactory implements ISecurityFactory {
- platform: string = WAZUH_SECURITY_PLUGIN_XPACK_SECURITY;
- constructor(private security: SecurityPluginSetup) {}
-
- async getCurrentUser(request: KibanaRequest) {
- try {
- const authContext = await this.security.authc.getCurrentUser(request);
- if(!authContext) return {hashUsername: md5(ELASTIC_NAME), username: ELASTIC_NAME, authContext: { username: ELASTIC_NAME}};
- const username = this.getUserName(authContext);
- return { username, authContext, hashUsername: md5(username) };
- } catch (error) {
- throw error;
- }
- }
-
- getUserName(authContext:any) {
- return authContext['username'];
- }
-}
\ No newline at end of file
diff --git a/server/lib/security-factory/security-factory.ts b/server/lib/security-factory/security-factory.ts
index 38b32ce189..e1df0e11ce 100644
--- a/server/lib/security-factory/security-factory.ts
+++ b/server/lib/security-factory/security-factory.ts
@@ -1,5 +1,5 @@
-import { OpendistroFactory, XpackFactory, DefaultFactory } from './factories';
-import { KibanaRequest, RequestHandlerContext } from 'src/core/server';
+import { OpenSearchDashboardsSecurityFactory, DefaultFactory } from './factories';
+import { OpenSearchDashboardsRequest, RequestHandlerContext } from 'src/core/server';
import { PluginSetup } from '../../types';
type CurrentUser = {
@@ -9,34 +9,13 @@ type CurrentUser = {
export interface ISecurityFactory {
platform?: string;
- getCurrentUser(request: KibanaRequest, context?: RequestHandlerContext): Promise;
+ getCurrentUser(request: OpenSearchDashboardsRequest, context?: RequestHandlerContext): Promise;
}
export async function SecurityObj(
- { security, opendistroSecurityKibana }: PluginSetup,
- context?: RequestHandlerContext
+ { securityDashboards }: PluginSetup
): Promise {
- const params = {
- path: `/_security/user`,
- method: 'GET',
- };
- if (!!security) {
- try {
- const responseCurl = await context.core.elasticsearch.client.asInternalUser.transport.request(
- params
- );
- return new XpackFactory(security);
- } catch (error) {
-
- // In case of an forbidden resource error it's still good to know if it uses xpack
- const validErrors: [number] = [403];
- if (validErrors.includes(error?.meta?.statusCode)) return new XpackFactory(security);
-
- return new DefaultFactory();
- }
- } else {
- return !!opendistroSecurityKibana
- ? new OpendistroFactory(opendistroSecurityKibana)
- : new DefaultFactory();
- }
+ return !!securityDashboards
+ ? new OpenSearchDashboardsSecurityFactory(securityDashboards)
+ : new DefaultFactory();
}
diff --git a/server/lib/update-configuration.ts b/server/lib/update-configuration.ts
index 67bb9be148..0c9adb84d2 100644
--- a/server/lib/update-configuration.ts
+++ b/server/lib/update-configuration.ts
@@ -12,7 +12,8 @@
import fs from 'fs';
import { log } from './logger';
import { getConfiguration } from './get-configuration';
-import { WAZUH_DATA_CONFIG_APP_PATH, WAZUH_CONFIGURATION_SETTINGS_NEED_RESTART, WAZUH_CONFIGURATION_SETTINGS_NEED_RELOAD, WAZUH_CONFIGURATION_SETTINGS_NEED_HEALTH_CHECK } from '../../common/constants';
+import { WAZUH_DATA_CONFIG_APP_PATH } from '../../common/constants';
+import { formatSettingValueToFile } from '../../common/services/settings';
export class UpdateConfigurationFile {
constructor() {
@@ -30,7 +31,7 @@ export class UpdateConfigurationFile {
try {
const data = fs.readFileSync(this.file, { encoding: 'utf-8' });
const re = new RegExp(`^${key}\\s{0,}:\\s{1,}.*`, 'gm');
- const formatedValue = this.formatValue(value);
+ const formatedValue = formatSettingValueToFile(value);
const result = exists
? data.replace(re, `${key}: ${formatedValue}`)
: `${data}\n${key}: ${formatedValue}`;
@@ -43,33 +44,26 @@ export class UpdateConfigurationFile {
}
}
- formatValue = (value) => typeof value === 'string'
- ? isNaN(Number(value)) ? `'${value}'` : value
- : typeof value === 'object'
- ? JSON.stringify(value)
- : value
-
- formatValueCachedConfiguration = (value) => typeof value === 'string'
- ? isNaN(Number(value)) ? value : Number(value)
- : value;
/**
* Updates wazuh.yml file. If it fails, it throws the error to the next function.
- * @param {Object} input
+ * @param {Object} updatedConfiguration
*/
- updateConfiguration(input) {
+ updateConfiguration(updatedConfiguration) {
try {
if (this.busy) {
throw new Error('Another process is updating the configuration file');
}
this.busy = true;
- const configuration = getConfiguration(true) || {};
-
- const { key, value } = (input || {}).body || {};
- this.updateLine(key, value, typeof configuration[key] !== 'undefined');
+ const pluginConfiguration = getConfiguration({force: true}) || {};
- // Update the app configuration server-cached setting in memory with the new value
- configuration[key] = this.formatValueCachedConfiguration(value);
+ for(const pluginSettingKey in updatedConfiguration){
+ // Store the configuration in the configuration file.
+ const value = updatedConfiguration[pluginSettingKey];
+ this.updateLine(pluginSettingKey, value, typeof pluginConfiguration[pluginSettingKey] !== 'undefined');
+ // Update the app configuration server-cached setting in memory with the new value.
+ pluginConfiguration[pluginSettingKey] = value;
+ };
this.busy = false;
log(
@@ -77,11 +71,6 @@ export class UpdateConfigurationFile {
'Updating configuration',
'debug'
);
- return {
- needRestart: WAZUH_CONFIGURATION_SETTINGS_NEED_RESTART.includes(key),
- needReload: WAZUH_CONFIGURATION_SETTINGS_NEED_RELOAD.includes(key),
- needHealtCheck: WAZUH_CONFIGURATION_SETTINGS_NEED_HEALTH_CHECK.includes(key)
- };
} catch (error) {
log('update-configuration:updateConfiguration', error.message || error);
this.busy = false;
diff --git a/server/plugin.ts b/server/plugin.ts
index 8fcd37351b..788d281ea2 100644
--- a/server/plugin.ts
+++ b/server/plugin.ts
@@ -23,8 +23,8 @@ import {
Logger,
Plugin,
PluginInitializerContext,
- SharedGlobalConfig
-} from 'kibana/server';
+ SharedGlobalConfig,
+} from 'opensearch_dashboards/server';
import { WazuhPluginSetup, WazuhPluginStart, PluginSetup } from './types';
import { SecurityObj, ISecurityFactory } from './lib/security-factory';
@@ -32,11 +32,11 @@ import { setupRoutes } from './routes';
import { jobInitializeRun, jobMonitoringRun, jobSchedulerRun, jobQueueRun, jobMigrationTasksRun } from './start';
import { getCookieValueByName } from './lib/cookie';
import * as ApiInterceptor from './lib/api-interceptor';
-import { schema, TypeOf } from '@kbn/config-schema';
+import { schema, TypeOf } from '@osd/config-schema';
import type { Observable } from 'rxjs';
import { first } from 'rxjs/operators';
-declare module 'kibana/server' {
+declare module 'opensearch_dashboards/server' {
interface RequestHandlerContext {
wazuh: {
logger: Logger,
@@ -68,15 +68,14 @@ export class WazuhPlugin implements Plugin {
public async setup(core: CoreSetup, plugins: PluginSetup) {
this.logger.debug('Wazuh-wui: Setup');
+ const wazuhSecurity = await SecurityObj(plugins);
const serverInfo = core.http.getServerInfo();
- let wazuhSecurity;
- core.http.registerRouteHandlerContext('wazuh', async(context, request) => {
- !wazuhSecurity && (wazuhSecurity = await SecurityObj(plugins, context));
+ core.http.registerRouteHandlerContext('wazuh', (context, request) => {
return {
logger: this.logger,
server: {
- info: serverInfo,
+ info: serverInfo,
},
plugins,
security: wazuhSecurity,
@@ -127,7 +126,7 @@ export class WazuhPlugin implements Plugin {
// Initialize
jobInitializeRun({
- core,
+ core,
wazuh: {
logger: this.logger.get('initialize'),
api: wazuhApiClient
@@ -167,7 +166,7 @@ export class WazuhPlugin implements Plugin {
// Queue
jobQueueRun({
- core,
+ core,
wazuh: {
logger: this.logger.get('queue'),
api: wazuhApiClient
diff --git a/server/routes/index.ts b/server/routes/index.ts
index 8af0e65dc0..fee6396e3b 100644
--- a/server/routes/index.ts
+++ b/server/routes/index.ts
@@ -1,4 +1,4 @@
-import { IRouter } from 'kibana/server';
+import { IRouter } from 'opensearch_dashboards/server';
import { WazuhApiRoutes } from './wazuh-api';
import { WazuhElasticRoutes } from "./wazuh-elastic";
import { WazuhHostsRoutes } from "./wazuh-hosts";
diff --git a/server/routes/wazuh-api-http-status.test.ts b/server/routes/wazuh-api-http-status.test.ts
new file mode 100644
index 0000000000..5a7edad40c
--- /dev/null
+++ b/server/routes/wazuh-api-http-status.test.ts
@@ -0,0 +1,113 @@
+// To launch this file
+// yarn test:jest --testEnvironment node --verbose server/routes/wazuh-api-http-status.test.ts
+import { Router } from '../../../../src/core/server/http/router/router';
+import { HttpServer } from '../../../../src/core/server/http/http_server';
+import { loggingSystemMock } from '../../../../src/core/server/logging/logging_system.mock';
+import { ByteSizeValue } from '@osd/config-schema';
+import supertest from 'supertest';
+import { WazuhApiRoutes } from './wazuh-api';
+import { createDataDirectoryIfNotExists, createDirectoryIfNotExists } from '../lib/filesystem';
+import {
+ HTTP_STATUS_CODES,
+ WAZUH_DATA_ABSOLUTE_PATH,
+ WAZUH_DATA_CONFIG_APP_PATH,
+ WAZUH_DATA_CONFIG_DIRECTORY_PATH,
+ WAZUH_DATA_LOGS_DIRECTORY_PATH
+} from '../../common/constants';
+import { execSync } from 'child_process';
+import fs from 'fs';
+
+const loggingService = loggingSystemMock.create();
+const logger = loggingService.get();
+const context = {
+ wazuh: {
+ security: {
+ getCurrentUser: () => 'wazuh'
+ }
+ }
+};
+
+const enhanceWithContext = (fn: (...args: any[]) => any) => fn.bind(null, context);
+let server, innerServer;
+
+beforeAll(async () => {
+
+ // Create /data/wazuh directory.
+ createDataDirectoryIfNotExists();
+ // Create /data/wazuh/config directory.
+ createDirectoryIfNotExists(WAZUH_DATA_CONFIG_DIRECTORY_PATH);
+ // Create /data/wazuh/logs directory.
+ createDirectoryIfNotExists(WAZUH_DATA_LOGS_DIRECTORY_PATH);
+
+ // Create server
+ const config = {
+ name: 'plugin_platform',
+ host: '127.0.0.1',
+ maxPayload: new ByteSizeValue(1024),
+ port: 10002,
+ ssl: { enabled: false },
+ compression: { enabled: true },
+ requestId: {
+ allowFromAnyIp: true,
+ ipAllowlist: [],
+ },
+ } as any;
+ server = new HttpServer(loggingService, 'tests');
+ const router = new Router('', logger, enhanceWithContext);
+ const { registerRouter, server: innerServerTest, ...rest } = await server.setup(config);
+ innerServer = innerServerTest;
+
+ // Register routes
+ WazuhApiRoutes(router);
+
+ // Register router
+ registerRouter(router);
+
+ // start server
+ await server.start();
+});
+
+afterAll(async () => {
+ // Stop server
+ await server.stop();
+
+ // Clear all mocks
+ jest.clearAllMocks();
+
+ // Remove /data/wazuh directory.
+ execSync(`rm -rf ${WAZUH_DATA_ABSOLUTE_PATH}`);
+});
+
+describe('[endpoint] GET /api/check-api', () => {
+ beforeAll(() => {
+ // Create the configuration file with custom content
+ const fileContent = `---
+pattern: test-alerts-*
+hosts:
+ - default:
+ url: https://localhost
+ port: 55000
+ username: wazuh-wui
+ password: wazuh-wui
+ run_as: false
+`;
+
+ fs.writeFileSync(WAZUH_DATA_CONFIG_APP_PATH, fileContent, 'utf8');
+ });
+
+ afterAll(() => {
+ // Remove the configuration file
+ fs.unlinkSync(WAZUH_DATA_CONFIG_APP_PATH);
+ });
+
+ it.each`
+ apiId | statusCode
+ ${'default'} | ${HTTP_STATUS_CODES.SERVICE_UNAVAILABLE}
+ `(`Get API configuration POST /api/check-api - apiID - $statusCode`, async ({ apiId, statusCode }) => {
+ const body = { id: apiId, forceRefresh: false };
+ const response = await supertest(innerServer.listener)
+ .post('/api/check-api')
+ .send(body)
+ .expect(statusCode);
+ });
+});
diff --git a/server/routes/wazuh-api.ts b/server/routes/wazuh-api.ts
index 3b41dd9f6f..7734e94962 100644
--- a/server/routes/wazuh-api.ts
+++ b/server/routes/wazuh-api.ts
@@ -1,7 +1,7 @@
-import { IRouter } from 'kibana/server';
+import { IRouter } from 'opensearch_dashboards/server';
import { WazuhApiCtrl } from '../controllers';
-import { schema } from '@kbn/config-schema';
+import { schema } from '@osd/config-schema';
export function WazuhApiRoutes(router: IRouter) {
const ctrl = new WazuhApiCtrl();
@@ -153,4 +153,13 @@ export function WazuhApiRoutes(router: IRouter) {
},
async (context, request, response) => ctrl.isWazuhDisabled(context, request, response)
);
+
+ // Return app logos configuration
+ router.get({
+ path: '/api/logos',
+ validate: false,
+ options: { authRequired: false }
+ },
+ async (context, request, response) => ctrl.getAppLogos(context, request, response)
+ );
}
diff --git a/server/routes/wazuh-elastic.test.ts b/server/routes/wazuh-elastic.test.ts
index 34b821db1c..cdc74a0431 100644
--- a/server/routes/wazuh-elastic.test.ts
+++ b/server/routes/wazuh-elastic.test.ts
@@ -67,17 +67,6 @@ describe.skip('Wazuh Elastic', () => {
});
});
- describe('Wazuh API - /elastic/index-patterns/{pattern}', () => {
- test('[200] Check if there an index pattern with the pattern', () => {
- const options = buildAxiosOptions('get', '/elastic/index-patterns/wazuh-alerts-*');
- return axios(options).then((response) => {
- expect(response.status).toBe(200);
- expect(typeof response.data.status).toBe('boolean');
- expect(typeof response.data.data).toBe('string');
- });
- });
- });
-
// TODO: This test need to be defined
// describe('Wazuh API - /elastic/top/{mode}/{cluster}/{field}/{pattern}', () => {
// test('[200] Check if there an index pattern with the pattern', () => {
diff --git a/server/routes/wazuh-elastic.ts b/server/routes/wazuh-elastic.ts
index edc151e521..af448efacd 100644
--- a/server/routes/wazuh-elastic.ts
+++ b/server/routes/wazuh-elastic.ts
@@ -10,8 +10,8 @@
* Find more information about this on the LICENSE file.
*/
import { WazuhElasticCtrl } from '../controllers';
-import { IRouter } from 'kibana/server';
-import { schema } from '@kbn/config-schema';
+import { IRouter } from 'opensearch_dashboards/server';
+import { schema } from '@osd/config-schema';
import { WAZUH_SAMPLE_ALERTS_CATEGORY_SECURITY, WAZUH_SAMPLE_ALERTS_CATEGORY_AUDITING_POLICY_MONITORING, WAZUH_SAMPLE_ALERTS_CATEGORY_THREAT_DETECTION } from '../../common/constants';
export function WazuhElasticRoutes(router: IRouter) {
@@ -70,18 +70,6 @@ export function WazuhElasticRoutes(router: IRouter) {
async (context, request, response) => ctrl.getTemplate(context, request, response)
);
- router.get(
- {
- path: '/elastic/index-patterns/{pattern}',
- validate: {
- params: schema.object({
- pattern: schema.string(),
- })
- }
- },
- async (context, request, response) => ctrl.checkPattern(context, request, response)
- );
-
router.get(
{
path: '/elastic/top/{mode}/{cluster}/{field}/{pattern}',
diff --git a/server/routes/wazuh-hosts.ts b/server/routes/wazuh-hosts.ts
index 9a1916e0e5..8e61adcf32 100644
--- a/server/routes/wazuh-hosts.ts
+++ b/server/routes/wazuh-hosts.ts
@@ -10,8 +10,8 @@
* Find more information about this on the LICENSE file.
*/
import { WazuhHostsCtrl } from '../controllers';
-import { IRouter } from 'kibana/server';
-import { schema } from '@kbn/config-schema';
+import { IRouter } from 'opensearch_dashboards/server';
+import { schema } from '@osd/config-schema';
export function WazuhHostsRoutes(router: IRouter) {
const ctrl = new WazuhHostsCtrl();
@@ -23,7 +23,7 @@ export function WazuhHostsRoutes(router: IRouter) {
},
async (context, request, response) => ctrl.getHostsEntries(context, request, response)
);
-
+
// Updates the cluster-info or manager-info
router.put(
{
diff --git a/server/routes/wazuh-reporting.test.ts b/server/routes/wazuh-reporting.test.ts
index b56ea7b2ff..034377cbeb 100644
--- a/server/routes/wazuh-reporting.test.ts
+++ b/server/routes/wazuh-reporting.test.ts
@@ -1,96 +1,231 @@
// To launch this file
// yarn test:jest --testEnvironment node --verbose server/routes/wazuh-reporting
-import axios from 'axios';
-import { PLUGIN_PLATFORM_REQUEST_HEADERS } from '../../common/constants';
-
-function buildAxiosOptions(method: string, path: string, data: any = {}, headers: any = {}){
- return {
- method: method,
- headers: { ...PLUGIN_PLATFORM_REQUEST_HEADERS, 'content-type': 'application/json', ...headers },
- url: `http://localhost:5601${path}`,
- data: data
- };
+import { Router } from '../../../../src/core/server/http/router/router';
+import { HttpServer } from '../../../../src/core/server/http/http_server';
+import { loggingSystemMock } from '../../../../src/core/server/logging/logging_system.mock';
+import { ByteSizeValue } from '@osd/config-schema';
+import supertest from 'supertest';
+import { WazuhUtilsRoutes } from './wazuh-utils';
+import { WazuhReportingRoutes } from './wazuh-reporting';
+import { WazuhUtilsCtrl } from '../controllers/wazuh-utils/wazuh-utils';
+import md5 from 'md5';
+import path from 'path';
+import { createDataDirectoryIfNotExists, createDirectoryIfNotExists } from '../lib/filesystem';
+import {
+ WAZUH_DATA_CONFIG_APP_PATH,
+ WAZUH_DATA_CONFIG_DIRECTORY_PATH,
+ WAZUH_DATA_DOWNLOADS_REPORTS_DIRECTORY_PATH,
+ WAZUH_DATA_LOGS_DIRECTORY_PATH,
+ WAZUH_DATA_ABSOLUTE_PATH,
+ WAZUH_DATA_DOWNLOADS_DIRECTORY_PATH
+} from '../../common/constants';
+import { execSync } from 'child_process';
+import fs from 'fs';
+
+jest.mock('../lib/reporting/extended-information', () => ({
+ extendedInformation: jest.fn()
+}));
+const USER_NAME = 'admin';
+const loggingService = loggingSystemMock.create();
+const logger = loggingService.get();
+const context = {
+ wazuh: {
+ security: {
+ getCurrentUser: (request) => {
+ // x-test-username header doesn't exist when the platform or plugin are running.
+ // It is used to generate the output of this method so we can simulate the user
+ // that does the request to the endpoint and is expected by the endpoint handlers
+ // of the plugin.
+ const username = request.headers['x-test-username'];
+ return { username, hashUsername: md5(username) }
+ }
+ }
+ }
};
+const enhanceWithContext = (fn: (...args: any[]) => any) => fn.bind(null, context);
+let server, innerServer;
+
+// BEFORE ALL
+beforeAll(async () => {
+ // Create /data/wazuh directory.
+ createDataDirectoryIfNotExists();
+
+ // Create /data/wazuh/config directory.
+ createDirectoryIfNotExists(WAZUH_DATA_CONFIG_DIRECTORY_PATH);
+
+ // Create /data/wazuh/logs directory.
+ createDirectoryIfNotExists(WAZUH_DATA_LOGS_DIRECTORY_PATH);
+
+ // Create server
+ const config = {
+ name: 'plugin_platform',
+ host: '127.0.0.1',
+ maxPayload: new ByteSizeValue(1024),
+ port: 10002,
+ ssl: { enabled: false },
+ compression: { enabled: true },
+ requestId: {
+ allowFromAnyIp: true,
+ ipAllowlist: [],
+ },
+ } as any;
+ server = new HttpServer(loggingService, 'tests');
+ const router = new Router('', logger, enhanceWithContext);
+ const { registerRouter, server: innerServerTest, ...rest } = await server.setup(config);
+ innerServer = innerServerTest;
+
+ // Mock decorator
+ jest.spyOn(WazuhUtilsCtrl.prototype as any, 'routeDecoratorProtectedAdministratorRoleValidToken')
+ .mockImplementation((handler) => async (...args) => handler(...args));
+
+ // Register routes
+ WazuhUtilsRoutes(router);
+ WazuhReportingRoutes(router);
+
+ // Register router
+ registerRouter(router);
+
+ // start server
+ await server.start();
+});
+
+afterAll(async () => {
+ // Stop server
+ await server.stop();
+
+ // Clear all mocks
+ jest.clearAllMocks();
+
+ // Remove /data/wazuh directory.
+ execSync(`rm -rf ${WAZUH_DATA_ABSOLUTE_PATH}`);
+});
+
+describe('[endpoint] GET /reports', () => {
+ const directories = [
+ { username: 'admin', files: 0 },
+ { username: '../../etc', files: 1 },
+ ];
+ beforeAll(() => {
+ // Create /data/wazuh directory.
+ createDataDirectoryIfNotExists();
+
+ // Create /data/wazuh/config directory.
+ createDirectoryIfNotExists(WAZUH_DATA_CONFIG_DIRECTORY_PATH);
+
+ // Create /data/wazuh/logs directory.
+ createDirectoryIfNotExists(WAZUH_DATA_LOGS_DIRECTORY_PATH);
+
+ // Create /data/wazuh/downloads directory.
+ createDirectoryIfNotExists(WAZUH_DATA_DOWNLOADS_DIRECTORY_PATH);
+
+ // Create /data/wazuh/downloads/reports directory.
+ createDirectoryIfNotExists(WAZUH_DATA_DOWNLOADS_REPORTS_DIRECTORY_PATH);
-describe.skip('Wazuh Reporting', () => {
- describe('Wazuh API - /reports', () => {
- test('[200] Returns the available reports for user', () => {
- const options = buildAxiosOptions('get', '/reports', {}, {
- cookie: 'wz-user=elastic'
- });
- return axios(options).then(response => {
- expect(response.status).toBe(200);
- expect(Array.isArray(response.data.reports)).toBe(true);
- }).catch(error => {throw error})
+ // Create directories and file/s within directory.
+ directories.forEach(({ username, files }) => {
+ const hashUsername = md5(username);
+ createDirectoryIfNotExists(path.join(WAZUH_DATA_DOWNLOADS_REPORTS_DIRECTORY_PATH, hashUsername));
+ if (files) {
+ Array.from(Array(files).keys()).forEach(indexFile => {
+ console.log('Generating', username, indexFile)
+ fs.closeSync(fs.openSync(path.join(WAZUH_DATA_DOWNLOADS_REPORTS_DIRECTORY_PATH, hashUsername, `report_${indexFile}.pdf`), 'w'));
+ });
+ }
});
});
- //TODO: do the test for these endpoints
- // describe('Wazuh API - /reports/{name}', () => {
- // test('[200] Returns the available reports for user and name', () => {
- // const options = buildAxiosOptions('get', '/reports/wazuh-report.pdf', {}, {
- // cookie: 'wz-user=elastic'
- // });
- // return axios(options).then(response => {
- // expect(response.status).toBe(200);
- // expect(Array.isArray(response.data.reports)).toBe(true);
- // }).catch(error => {throw error})
- // });
-
- // test('[200] Returns the available reports for user and name', () => {
- // const options = buildAxiosOptions('delete', '/reports/wazuh-report.pdf', {}, {
- // cookie: 'wz-user=elastic'
- // });
- // return axios(options).then(response => {
- // }).catch(error => {throw error})
- // });
- // });
-
- // describe('Wazuh API - /reports/modules/{moduleID}', () => {
- // test('[200] Generates a modules reports the available reports for user and name', () => {
- // const options = buildAxiosOptions('post', '/reports/modules/{moduleID}', {}, {
- // cookie: 'wz-user=elastic'
- // });
- // return axios(options).then(response => {
- // expect(response.status).toBe(200);
- // expect(Array.isArray(response.data.reports)).toBe(true);
- // }).catch(error => {throw error})
- // });
- // });
-
- // describe('Wazuh API - /reports/groups/{groupID}', () => {
- // test('[200] Generates a modules reports the available reports for user and name', () => {
- // const options = buildAxiosOptions('post', '/reports/groups/{groupID}', {}, {
- // cookie: 'wz-user=elastic'
- // });
- // return axios(options).then(response => {
- // expect(response.status).toBe(200);
- // expect(Array.isArray(response.data.reports)).toBe(true);
- // }).catch(error => {throw error})
- // });
- // });
-
- // describe('Wazuh API - /reports/agents/{agentID}', () => {
- // test('[200] Generates a modules reports the available reports for user and name', () => {
- // const options = buildAxiosOptions('post', '/reports/agents/{agentID}', {}, {
- // cookie: 'wz-user=elastic'
- // });
- // return axios(options).then(response => {
- // expect(response.status).toBe(200);
- // expect(Array.isArray(response.data.reports)).toBe(true);
- // }).catch(error => {throw error})
- // });
- // });
-
- // describe('Wazuh API - /reports/agents/{agentID}/inventory', () => {
- // test('[200] Generates a modules reports the available reports for user and name', () => {
- // const options = buildAxiosOptions('post', '/reports/agents/{agentID}/inventory', {}, {
- // cookie: 'wz-user=elastic'
- // });
- // return axios(options).then(response => {
- // expect(response.status).toBe(200);
- // expect(Array.isArray(response.data.reports)).toBe(true);
- // }).catch(error => {throw error})
- // });
- // });
+ afterAll(async () => {
+ // Remove /data/wazuh/downloads directory.
+ execSync(`rm -rf ${WAZUH_DATA_DOWNLOADS_DIRECTORY_PATH}`);
+ });
+
+ it.each(directories)('get reports of $username. status response: $responseStatus', async ({ username, files }) => {
+ const response = await supertest(innerServer.listener)
+ .get(`/reports`)
+ .set('x-test-username', username)
+ .expect(200);
+ expect(response.body.reports).toHaveLength(files);
+ });
+});
+
+describe('[endpoint] PUT /utils/configuration', () => {
+ beforeEach(() => {
+ // Create the configuration file with custom content
+ const fileContent = `---
+ pattern: test-alerts-*
+
+ hosts:
+ - default:
+ url: https://localhost
+ port: 55000
+ username: wazuh-wui
+ password: wazuh-wui
+ run_as: false
+ `;
+
+ fs.writeFileSync(WAZUH_DATA_CONFIG_APP_PATH, fileContent, 'utf8');
+ });
+
+ afterEach(() => {
+ // Remove the configuration file
+ fs.unlinkSync(WAZUH_DATA_CONFIG_APP_PATH);
+ });
+
+ // expectedMD5 variable is a verified md5 of a report generated with this header and footer
+ // If any of the parameters is changed this variable should be updated with the new md5
+ it.each`
+ footer | header | responseStatusCode | expectedMD5 | tab
+ ${null} | ${null} | ${200} | ${'7b6fa0e2a5911880d17168800c173f89'} | ${'pm'}
+ ${'Custom\nFooter'} | ${'info@company.com\nFake Avenue 123'}| ${200} | ${'51b268066bb5107e5eb0a9d791a89d0c'} | ${'general'}
+ ${''} | ${''} | ${200} | ${'23d5e0eedce38dc6df9e98e898628f68'} | ${'fim'}
+ ${'Custom Footer'} | ${null} | ${200} | ${'2b16be2ea88d3891cda7acb6075826d9'} | ${'aws'}
+ ${null} | ${'Custom Header'} | ${200} | ${'91e30564f157942718afdd97db3b4ddf'} | ${'gcp'}
+`(`Set custom report header and footer - Verify PDF output`, async ({footer, header, responseStatusCode, expectedMD5, tab}) => {
+
+ // Mock PDF report parameters
+ const reportBody = { "array": [], "filters": [], "time": { "from": '2022-10-01T09:59:40.825Z', "to": '2022-10-04T09:59:40.825Z' }, "searchBar": "", "tables": [], "tab": tab, "section": "overview", "agents": false, "browserTimezone": "Europe/Madrid", "indexPatternTitle": "wazuh-alerts-*", "apiId": "default" };
+
+ // Define custom configuration
+ const configurationBody = {};
+
+ if (typeof footer == 'string') {
+ configurationBody['customization.reports.footer'] = footer;
+ }
+ if (typeof header == 'string') {
+ configurationBody['customization.reports.header'] = header;
+ }
+
+ // Set custom report header and footer
+ if (typeof footer == 'string' || typeof header == 'string') {
+ const responseConfig = await supertest(innerServer.listener)
+ .put('/utils/configuration')
+ .send(configurationBody)
+ .expect(responseStatusCode);
+
+ if (typeof footer == 'string') {
+ expect(responseConfig.body?.data?.updatedConfiguration?.['customization.reports.footer']).toMatch(configurationBody['customization.reports.footer']);
+ }
+ if (typeof header == 'string') {
+ expect(responseConfig.body?.data?.updatedConfiguration?.['customization.reports.header']).toMatch(configurationBody['customization.reports.header']);
+ }
+ }
+
+ // Generate PDF report
+ const responseReport = await supertest(innerServer.listener)
+ .post(`/reports/modules/${tab}`)
+ .set('x-test-username', USER_NAME)
+ .send(reportBody)
+ .expect(200);
+ const fileName = responseReport.body?.message.match(/([A-Z-0-9]*\.pdf)/gi)[0];
+ const userPath = md5(USER_NAME);
+ const reportPath = `${WAZUH_DATA_DOWNLOADS_REPORTS_DIRECTORY_PATH}/${userPath}/${fileName}`;
+ const PDFbuffer = fs.readFileSync(reportPath);
+ const PDFcontent = PDFbuffer.toString('utf8');
+ const content = PDFcontent
+ .replace(/\[<[a-z0-9].+> <[a-z0-9].+>\]/gi, '')
+ .replace(/(obj\n\(D:[0-9].+Z\)\nendobj)/gi, '');
+ const PDFmd5 = md5(content);
+
+ expect(PDFmd5).toBe(expectedMD5);
+ });
});
diff --git a/server/routes/wazuh-reporting.ts b/server/routes/wazuh-reporting.ts
index 5b4988e707..946e73ac5d 100644
--- a/server/routes/wazuh-reporting.ts
+++ b/server/routes/wazuh-reporting.ts
@@ -10,8 +10,8 @@
* Find more information about this on the LICENSE file.
*/
import { WazuhReportingCtrl } from '../controllers';
-import { IRouter } from 'kibana/server';
-import { schema } from '@kbn/config-schema';
+import { IRouter } from 'opensearch_dashboards/server';
+import { schema } from '@osd/config-schema';
export function WazuhReportingRoutes(router: IRouter) {
const ctrl = new WazuhReportingCtrl();
diff --git a/server/routes/wazuh-utils/fixtures/fixture_file.txt b/server/routes/wazuh-utils/fixtures/fixture_file.txt
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/server/routes/wazuh-utils/fixtures/fixture_image_big.png b/server/routes/wazuh-utils/fixtures/fixture_image_big.png
new file mode 100644
index 0000000000..9c574f937d
Binary files /dev/null and b/server/routes/wazuh-utils/fixtures/fixture_image_big.png differ
diff --git a/server/routes/wazuh-utils/fixtures/fixture_image_small.jpg b/server/routes/wazuh-utils/fixtures/fixture_image_small.jpg
new file mode 100644
index 0000000000..19c02a553b
Binary files /dev/null and b/server/routes/wazuh-utils/fixtures/fixture_image_small.jpg differ
diff --git a/server/routes/wazuh-utils/fixtures/fixture_image_small.png b/server/routes/wazuh-utils/fixtures/fixture_image_small.png
new file mode 100644
index 0000000000..ba9bc4dae9
Binary files /dev/null and b/server/routes/wazuh-utils/fixtures/fixture_image_small.png differ
diff --git a/server/routes/wazuh-utils/fixtures/fixture_image_small.svg b/server/routes/wazuh-utils/fixtures/fixture_image_small.svg
new file mode 100644
index 0000000000..f6d72ed8ce
--- /dev/null
+++ b/server/routes/wazuh-utils/fixtures/fixture_image_small.svg
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
diff --git a/server/routes/wazuh-utils/ui-logs.ts b/server/routes/wazuh-utils/ui-logs.ts
index ff70d958d8..0298e630e9 100644
--- a/server/routes/wazuh-utils/ui-logs.ts
+++ b/server/routes/wazuh-utils/ui-logs.ts
@@ -10,8 +10,8 @@
* Find more information about this on the LICENSE file.
*/
import { UiLogsCtrl } from '../../controllers';
-import { IRouter } from 'kibana/server';
-import { schema } from '@kbn/config-schema';
+import { IRouter } from 'opensearch_dashboards/server';
+import { schema } from '@osd/config-schema';
export const UiLogsRoutes = (router: IRouter) => {
const ctrl = new UiLogsCtrl();
diff --git a/server/routes/wazuh-utils/wazuh-utils.test.ts b/server/routes/wazuh-utils/wazuh-utils.test.ts
index 166e5331a9..e32fc5b7aa 100644
--- a/server/routes/wazuh-utils/wazuh-utils.test.ts
+++ b/server/routes/wazuh-utils/wazuh-utils.test.ts
@@ -1,76 +1,618 @@
-// To launch this file
+// To run this file:
// yarn test:jest --testEnvironment node --verbose server/routes/wazuh-utils
-import axios from 'axios';
-import { PLUGIN_PLATFORM_REQUEST_HEADERS } from '../../../common/constants';
-
-function buildAxiosOptions(method: string, path: string, data: any = {}, headers: any = {}) {
- return {
- method: method,
- headers: { ...PLUGIN_PLATFORM_REQUEST_HEADERS, 'content-type': 'application/json', ...headers },
- url: `http://localhost:5601${path}`,
- data: data,
- };
-}
-
-describe.skip('Wazuh API - utils', () => {
- describe('Wazuh API - /utils/configuration', () => {
- test('[200] Returns the app configuration', () => {
- const options = buildAxiosOptions('get', '/utils/configuration');
- return axios(options)
- .then((response) => {
- expect(response.status).toBe(200);
- expect(typeof response.data.data).toBe('object');
- expect(typeof response.data.data.hosts).toBe('object');
- })
- .catch((error) => {
- throw error;
- });
- });
- });
-
- describe('Wazuh API - /utils/configuration', () => {
- let userToken = null;
- beforeAll(() => {
- const optionsAuthenticate = buildAxiosOptions('post', '/api/login', {
- idHost: 'default',
- });
- return axios(optionsAuthenticate).then((response) => {
- userToken = response.data.token;
- return response.data.token;
- });
- });
- test('[200] Updates the app configuration', () => {
- const options = buildAxiosOptions(
- 'put',
- '/utils/configuration',
- {
- key: 'logs.level',
- value: 'debug',
- },
- {
- cookie: `wz-token=${userToken};wz-api=default;`,
- }
- );
- return axios(options)
- .then((response) => {
- expect(response.status).toBe(200);
- })
- .catch((error) => {
- throw error;
- });
- });
- });
-
- describe('Wazuh API - /utils/logs', () => {
- test('[200] Get the app logs', () => {
- const options = buildAxiosOptions('get', '/utils/logs');
- return axios(options)
- .then((response) => {
- expect(response.status).toBe(200);
- })
- .catch((error) => {
- throw error;
- });
- });
+import { Router } from '../../../../../src/core/server/http/router/router';
+import { HttpServer } from '../../../../../src/core/server/http/http_server';
+import { loggingSystemMock } from '../../../../../src/core/server/logging/logging_system.mock';
+import { ByteSizeValue } from '@osd/config-schema';
+import supertest from 'supertest';
+import { WazuhUtilsRoutes } from './wazuh-utils';
+import { WazuhUtilsCtrl } from '../../controllers/wazuh-utils/wazuh-utils';
+import { createDataDirectoryIfNotExists, createDirectoryIfNotExists } from '../../lib/filesystem';
+import {
+ PLUGIN_SETTINGS,
+ WAZUH_DATA_ABSOLUTE_PATH,
+ WAZUH_DATA_CONFIG_APP_PATH,
+ WAZUH_DATA_CONFIG_DIRECTORY_PATH,
+ WAZUH_DATA_LOGS_DIRECTORY_PATH,
+ WAZUH_DATA_LOGS_RAW_PATH,
+} from "../../../common/constants";
+import { execSync } from 'child_process';
+import fs from 'fs';
+import path from 'path';
+import glob from 'glob';
+
+const loggingService = loggingSystemMock.create();
+const logger = loggingService.get();
+const context = {
+ wazuh: {
+ }
+};
+
+const enhanceWithContext = (fn: (...args: any[]) => any) => fn.bind(null, context);
+let server, innerServer;
+
+beforeAll(async () => {
+ // Create /data/wazuh directory.
+ createDataDirectoryIfNotExists();
+ // Create /data/wazuh/config directory.
+ createDirectoryIfNotExists(WAZUH_DATA_CONFIG_DIRECTORY_PATH);
+
+ // Create /data/wazuh/logs directory.
+ createDirectoryIfNotExists(WAZUH_DATA_LOGS_DIRECTORY_PATH);
+
+ // Create server
+ const config = {
+ name: 'plugin_platform',
+ host: '127.0.0.1',
+ maxPayload: new ByteSizeValue(1024),
+ port: 10002,
+ ssl: { enabled: false },
+ compression: { enabled: true },
+ requestId: {
+ allowFromAnyIp: true,
+ ipAllowlist: [],
+ },
+ } as any;
+ server = new HttpServer(loggingService, 'tests');
+ const router = new Router('', logger, enhanceWithContext);
+ const { registerRouter, server: innerServerTest, ...rest } = await server.setup(config);
+ innerServer = innerServerTest;
+
+ const spyRouteDecoratorProtectedAdministratorRoleValidToken = jest.spyOn(WazuhUtilsCtrl.prototype as any, 'routeDecoratorProtectedAdministratorRoleValidToken')
+ .mockImplementation((handler) => async (...args) => handler(...args));
+
+ // Register routes
+ WazuhUtilsRoutes(router);
+
+ // Register router
+ registerRouter(router);
+
+ // start server
+ await server.start();
+});
+
+afterAll(async () => {
+ // Stop server
+ await server.stop();
+
+ // Clear all mocks
+ jest.clearAllMocks();
+
+ // Remove /data/wazuh directory.
+ execSync(`rm -rf ${WAZUH_DATA_ABSOLUTE_PATH}`);
+});
+
+describe('[endpoint] GET /utils/configuration', () => {
+ beforeAll(() => {
+ // Create the configuration file with custom content
+ const fileContent = `---
+pattern: test-alerts-*
+
+hosts:
+ - default:
+ url: https://localhost
+ port: 55000
+ username: wazuh-wui
+ password: wazuh-wui
+ run_as: false
+`;
+
+ fs.writeFileSync(WAZUH_DATA_CONFIG_APP_PATH, fileContent, 'utf8');
+ });
+
+ afterAll(() => {
+ // Remove the configuration file
+ fs.unlinkSync(WAZUH_DATA_CONFIG_APP_PATH);
+ });
+
+ it(`Get plugin configuration GET /utils/configuration - 200`, async () => {
+ const response = await supertest(innerServer.listener)
+ .get('/utils/configuration')
+ .expect(200);
+ expect(response.body.data).toBeDefined();
+ expect(response.body.data.pattern).toBeDefined();
+ expect(response.body.data.hosts).toBeDefined();
+ });
+});
+
+describe('[endpoint] PUT /utils/configuration', () => {
+ beforeAll(() => {
+ // Create the configuration file with custom content
+ const fileContent = `---
+pattern: test-alerts-*
+
+hosts:
+ - default:
+ url: https://localhost
+ port: 55000
+ username: wazuh-wui
+ password: wazuh-wui
+ run_as: false
+`;
+
+ fs.writeFileSync(WAZUH_DATA_CONFIG_APP_PATH, fileContent, 'utf8');
+ });
+
+ afterAll(() => {
+ // Remove the configuration file
+ fs.unlinkSync(WAZUH_DATA_CONFIG_APP_PATH);
+ });
+
+ it.each`
+ settings | responseStatusCode
+ ${{ pattern: 'test-alerts-groupA-*' }} | ${200}
+ ${{ pattern: 'test-alerts-groupA-*', 'logs.level': 'debug' }} | ${200}
+ `(`Update the plugin configuration: $settings. PUT /utils/configuration - $responseStatusCode`, async ({ responseStatusCode, settings }) => {
+ const response = await supertest(innerServer.listener)
+ .put('/utils/configuration')
+ .send(settings)
+ .expect(responseStatusCode);
+
+ expect(response.body.data.updatedConfiguration).toEqual(settings);
+ expect(response.body.data.requiresRunningHealthCheck).toBeDefined();
+ expect(response.body.data.requiresReloadingBrowserTab).toBeDefined();
+ expect(response.body.data.requiresRestartingPluginPlatform).toBeDefined();
+ });
+
+ it.each([
+ {
+ testTitle: 'Update the plugin configuration',
+ settings: { pattern: 'test-alerts-groupA-*' },
+ responseStatusCode: 200,
+ responseBodyMessage: null
+ },
+ {
+ testTitle: 'Update the plugin configuration',
+ settings: { pattern: 'test-alerts-groupA-*', 'logs.level': 'debug' },
+ responseStatusCode: 200,
+ responseBodyMessage: null
+ },
+ {
+ testTitle: 'Bad request, wrong value type.',
+ settings: { pattern: 5 },
+ responseStatusCode: 400,
+ responseBodyMessage: '[request body.pattern]: expected value of type [string] but got [number]'
+ },
+ {
+ testTitle: 'Bad request, unknown setting',
+ settings: { 'unknown.setting': 'test-alerts-groupA-*' },
+ responseStatusCode: 400,
+ responseBodyMessage: '[request body.unknown.setting]: definition for this key is missing'
+ },
+ {
+ testTitle: 'Bad request, unknown setting',
+ settings: { 'unknown.setting': 'test-alerts-groupA-*', 'logs.level': 'debug' },
+ responseStatusCode: 400,
+ responseBodyMessage: '[request body.unknown.setting]: definition for this key is missing'
+ },
+ {
+ testTitle: 'Bad request, unknown setting',
+ settings: { 'cron.statistics.apis': [0, 'test'] },
+ responseStatusCode: 400,
+ responseBodyMessage: '[request body.cron.statistics.apis.0]: expected value of type [string] but got [number]'
+ }
+ ])(`$testTitle: $settings. PUT /utils/configuration - $responseStatusCode`, async ({ responseBodyMessage, responseStatusCode, settings }) => {
+ const response = await supertest(innerServer.listener)
+ .put('/utils/configuration')
+ .send(settings)
+ .expect(responseStatusCode);
+
+ responseStatusCode === 200 && expect(response.body.data.updatedConfiguration).toEqual(settings);
+ responseStatusCode === 200 && expect(response.body.data.requiresRunningHealthCheck).toBeDefined();
+ responseStatusCode === 200 && expect(response.body.data.requiresReloadingBrowserTab).toBeDefined();
+ responseStatusCode === 200 && expect(response.body.data.requiresRestartingPluginPlatform).toBeDefined();
+ responseBodyMessage && expect(response.body.message).toMatch(responseBodyMessage);
+ });
+
+ it.each`
+ setting | value | responseStatusCode | responseBodyMessage
+ ${'alerts.sample.prefix'} | ${'test'} | ${200} | ${null}
+ ${'alerts.sample.prefix'} | ${''} | ${400} | ${"[request body.alerts.sample.prefix]: Value can not be empty."}
+ ${'alerts.sample.prefix'} | ${'test space'} | ${400} | ${"[request body.alerts.sample.prefix]: No whitespaces allowed."}
+ ${'alerts.sample.prefix'} | ${4} | ${400} | ${'[request body.alerts.sample.prefix]: expected value of type [string] but got [number]'}
+ ${'alerts.sample.prefix'} | ${'-test'} | ${400} | ${"[request body.alerts.sample.prefix]: It can't start with: -, _, +, .."}
+ ${'alerts.sample.prefix'} | ${'_test'} | ${400} | ${"[request body.alerts.sample.prefix]: It can't start with: -, _, +, .."}
+ ${'alerts.sample.prefix'} | ${'+test'} | ${400} | ${"[request body.alerts.sample.prefix]: It can't start with: -, _, +, .."}
+ ${'alerts.sample.prefix'} | ${'.test'} | ${400} | ${"[request body.alerts.sample.prefix]: It can't start with: -, _, +, .."}
+ ${'alerts.sample.prefix'} | ${'test\\'} | ${400} | ${"[request body.alerts.sample.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test/'} | ${400} | ${"[request body.alerts.sample.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test?'} | ${400} | ${"[request body.alerts.sample.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test"'} | ${400} | ${"[request body.alerts.sample.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test<'} | ${400} | ${"[request body.alerts.sample.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test>'} | ${400} | ${"[request body.alerts.sample.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test|'} | ${400} | ${"[request body.alerts.sample.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test,'} | ${400} | ${"[request body.alerts.sample.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test#'} | ${400} | ${"[request body.alerts.sample.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'alerts.sample.prefix'} | ${'test*'} | ${400} | ${"[request body.alerts.sample.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'checks.api'} | ${true} | ${200} | ${null}
+ ${'checks.api'} | ${0} | ${400} | ${'[request body.checks.api]: expected value of type [boolean] but got [number]'}
+ ${'checks.fields'} | ${true} | ${200} | ${null}
+ ${'checks.fields'} | ${0} | ${400} | ${'[request body.checks.fields]: expected value of type [boolean] but got [number]'}
+ ${'checks.maxBuckets'} | ${true} | ${200} | ${null}
+ ${'checks.maxBuckets'} | ${0} | ${400} | ${'[request body.checks.maxBuckets]: expected value of type [boolean] but got [number]'}
+ ${'checks.pattern'} | ${true} | ${200} | ${null}
+ ${'checks.pattern'} | ${0} | ${400} | ${'[request body.checks.pattern]: expected value of type [boolean] but got [number]'}
+ ${'checks.setup'} | ${true} | ${200} | ${null}
+ ${'checks.setup'} | ${0} | ${400} | ${'[request body.checks.setup]: expected value of type [boolean] but got [number]'}
+ ${'checks.template'} | ${true} | ${200} | ${null}
+ ${'checks.template'} | ${0} | ${400} | ${'[request body.checks.template]: expected value of type [boolean] but got [number]'}
+ ${'checks.timeFilter'} | ${true} | ${200} | ${null}
+ ${'checks.timeFilter'} | ${0} | ${400} | ${'[request body.checks.timeFilter]: expected value of type [boolean] but got [number]'}
+ ${'cron.prefix'} | ${'test'} | ${200} | ${null}
+ ${'cron.prefix'} | ${'test space'} | ${400} | ${"[request body.cron.prefix]: No whitespaces allowed."}
+ ${'cron.prefix'} | ${''} | ${400} | ${"[request body.cron.prefix]: Value can not be empty."}
+ ${'cron.prefix'} | ${4} | ${400} | ${'[request body.cron.prefix]: expected value of type [string] but got [number]'}
+ ${'cron.prefix'} | ${'-test'} | ${400} | ${"[request body.cron.prefix]: It can't start with: -, _, +, .."}
+ ${'cron.prefix'} | ${'_test'} | ${400} | ${"[request body.cron.prefix]: It can't start with: -, _, +, .."}
+ ${'cron.prefix'} | ${'+test'} | ${400} | ${"[request body.cron.prefix]: It can't start with: -, _, +, .."}
+ ${'cron.prefix'} | ${'.test'} | ${400} | ${"[request body.cron.prefix]: It can't start with: -, _, +, .."}
+ ${'cron.prefix'} | ${'test\\'} | ${400} | ${"[request body.cron.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test/'} | ${400} | ${"[request body.cron.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test?'} | ${400} | ${"[request body.cron.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test"'} | ${400} | ${"[request body.cron.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test<'} | ${400} | ${"[request body.cron.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test>'} | ${400} | ${"[request body.cron.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test|'} | ${400} | ${"[request body.cron.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test,'} | ${400} | ${"[request body.cron.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test#'} | ${400} | ${"[request body.cron.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.prefix'} | ${'test*'} | ${400} | ${"[request body.cron.prefix]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.apis'} | ${['test']} | ${200} | ${null}
+ ${'cron.statistics.apis'} | ${['test ']} | ${400} | ${"[request body.cron.statistics.apis.0]: No whitespaces allowed."}
+ ${'cron.statistics.apis'} | ${['']} | ${400} | ${"[request body.cron.statistics.apis.0]: Value can not be empty."}
+ ${'cron.statistics.apis'} | ${['test', 4]} | ${400} | ${"[request body.cron.statistics.apis.1]: expected value of type [string] but got [number]"}
+ ${'cron.statistics.apis'} | ${'test space'} | ${400} | ${"[request body.cron.statistics.apis]: could not parse array value from json input"}
+ ${'cron.statistics.apis'} | ${true} | ${400} | ${"[request body.cron.statistics.apis]: expected value of type [array] but got [boolean]"}
+ ${'cron.statistics.index.creation'} | ${'h'} | ${200} | ${null}
+ ${'cron.statistics.index.creation'} | ${'d'} | ${200} | ${null}
+ ${'cron.statistics.index.creation'} | ${'w'} | ${200} | ${null}
+ ${'cron.statistics.index.creation'} | ${'m'} | ${200} | ${null}
+ ${'cron.statistics.index.creation'} | ${'test'} | ${400} | ${"[request body.cron.statistics.index.creation]: types that failed validation:\n- [request body.cron.statistics.index.creation.0]: expected value to equal [h]\n- [request body.cron.statistics.index.creation.1]: expected value to equal [d]\n- [request body.cron.statistics.index.creation.2]: expected value to equal [w]\n- [request body.cron.statistics.index.creation.3]: expected value to equal [m]"}
+ ${'cron.statistics.index.name'} | ${'test'} | ${200} | ${null}
+ ${'cron.statistics.index.name'} | ${''} | ${400} | ${"[request body.cron.statistics.index.name]: Value can not be empty."}
+ ${'cron.statistics.index.name'} | ${'test space'} | ${400} | ${"[request body.cron.statistics.index.name]: No whitespaces allowed."}
+ ${'cron.statistics.index.name'} | ${true} | ${400} | ${"[request body.cron.statistics.index.name]: expected value of type [string] but got [boolean]"}
+ ${'cron.statistics.index.name'} | ${'-test'} | ${400} | ${"[request body.cron.statistics.index.name]: It can't start with: -, _, +, .."}
+ ${'cron.statistics.index.name'} | ${'_test'} | ${400} | ${"[request body.cron.statistics.index.name]: It can't start with: -, _, +, .."}
+ ${'cron.statistics.index.name'} | ${'+test'} | ${400} | ${"[request body.cron.statistics.index.name]: It can't start with: -, _, +, .."}
+ ${'cron.statistics.index.name'} | ${'.test'} | ${400} | ${"[request body.cron.statistics.index.name]: It can't start with: -, _, +, .."}
+ ${'cron.statistics.index.name'} | ${'test\\'} | ${400} | ${"[request body.cron.statistics.index.name]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test/'} | ${400} | ${"[request body.cron.statistics.index.name]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test?'} | ${400} | ${"[request body.cron.statistics.index.name]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test"'} | ${400} | ${"[request body.cron.statistics.index.name]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test<'} | ${400} | ${"[request body.cron.statistics.index.name]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test>'} | ${400} | ${"[request body.cron.statistics.index.name]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test|'} | ${400} | ${"[request body.cron.statistics.index.name]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test,'} | ${400} | ${"[request body.cron.statistics.index.name]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test#'} | ${400} | ${"[request body.cron.statistics.index.name]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.name'} | ${'test*'} | ${400} | ${"[request body.cron.statistics.index.name]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #, *."}
+ ${'cron.statistics.index.replicas'} | ${0} | ${200} | ${null}
+ ${'cron.statistics.index.replicas'} | ${-1} | ${400} | ${"[request body.cron.statistics.index.replicas]: Value should be greater or equal than 0."}
+ ${'cron.statistics.index.replicas'} | ${'custom'} | ${400} | ${"[request body.cron.statistics.index.replicas]: expected value of type [number] but got [string]"}
+ ${'cron.statistics.index.replicas'} | ${1.2} | ${400} | ${"[request body.cron.statistics.index.replicas]: Number should be an integer."}
+ ${'cron.statistics.index.shards'} | ${1} | ${200} | ${null}
+ ${'cron.statistics.index.shards'} | ${-1} | ${400} | ${"[request body.cron.statistics.index.shards]: Value should be greater or equal than 1."}
+ ${'cron.statistics.index.shards'} | ${1.2} | ${400} | ${"[request body.cron.statistics.index.shards]: Number should be an integer."}
+ ${'cron.statistics.interval'} | ${'0 */5 * * * *'} | ${200} | ${null}
+ ${'cron.statistics.interval'} | ${'0 */5 * * *'} | ${200} | ${null}
+ ${'cron.statistics.interval'} | ${'custom'} | ${400} | ${"[request body.cron.statistics.interval]: Interval is not valid."}
+ ${'cron.statistics.interval'} | ${true} | ${400} | ${"[request body.cron.statistics.interval]: expected value of type [string] but got [boolean]"}
+ ${'cron.statistics.status'} | ${true} | ${200} | ${null}
+ ${'cron.statistics.status'} | ${0} | ${400} | ${'[request body.cron.statistics.status]: expected value of type [boolean] but got [number]'}
+ ${'customization.enabled'} | ${true} | ${200} | ${null}
+ ${'customization.enabled'} | ${0} | ${400} | ${'[request body.customization.enabled]: expected value of type [boolean] but got [number]'}
+ ${'customization.reports.footer'} | ${'Test'} | ${200} | ${null}
+ ${'customization.reports.footer'} | ${'Test\nTest'} | ${200} | ${null}
+ ${'customization.reports.footer'} | ${'Test\nTest\nTest\nTest\nTest'} | ${400} | ${"[request body.customization.reports.footer]: The string should have less or equal to 2 line/s."}
+ ${'customization.reports.footer'} | ${'Line with 30 characters \nTest'} | ${200} | ${undefined}
+ ${'customization.reports.footer'} | ${'Testing the maximum length of a line of 50 characters\nTest'}| ${400} | ${"[request body.customization.reports.footer]: The maximum length of a line is 50 characters."}
+ ${'customization.reports.footer'} | ${true} | ${400} | ${'[request body.customization.reports.footer]: expected value of type [string] but got [boolean]'}
+ ${'customization.reports.header'} | ${'Test'} | ${200} | ${null}
+ ${'customization.reports.header'} | ${'Test\nTest'} | ${200} | ${null}
+ ${'customization.reports.header'} | ${'Test\nTest\nTest\nTest\nTest'} | ${400} | ${"[request body.customization.reports.header]: The string should have less or equal to 3 line/s."}
+ ${'customization.reports.header'} | ${'Line with 20 charact\nTest'} | ${200} | ${undefined}
+ ${'customization.reports.header'} | ${'Testing maximum length of a line of 40 characters\nTest'} | ${400} | ${"[request body.customization.reports.header]: The maximum length of a line is 40 characters."}
+ ${'customization.reports.header'} | ${true} | ${400} | ${'[request body.customization.reports.header]: expected value of type [string] but got [boolean]'}
+ ${'disabled_roles'} | ${['test']} | ${200} | ${null}
+ ${'disabled_roles'} | ${['']} | ${400} | ${'[request body.disabled_roles.0]: Value can not be empty.'}
+ ${'disabled_roles'} | ${['test space']} | ${400} | ${"[request body.disabled_roles.0]: No whitespaces allowed."}
+ ${'disabled_roles'} | ${['test', 4]} | ${400} | ${"[request body.disabled_roles.1]: expected value of type [string] but got [number]"}
+ ${'enrollment.dns'} | ${'test'} | ${200} | ${null}
+ ${'enrollment.dns'} | ${''} | ${200} | ${null}
+ ${'enrollment.dns'} | ${'test space'} | ${400} | ${"[request body.enrollment.dns]: No whitespaces allowed."}
+ ${'enrollment.dns'} | ${true} | ${400} | ${'[request body.enrollment.dns]: expected value of type [string] but got [boolean]'}
+ ${'enrollment.password'} | ${'test'} | ${200} | ${null}
+ ${'enrollment.password'} | ${''} | ${400} | ${"[request body.enrollment.password]: Value can not be empty."}
+ ${'enrollment.password'} | ${'test space'} | ${200} | ${null}
+ ${'enrollment.password'} | ${true} | ${400} | ${'[request body.enrollment.password]: expected value of type [string] but got [boolean]'}
+ ${'extensions.audit'} | ${true} | ${200} | ${null}
+ ${'extensions.audit'} | ${0} | ${400} | ${'[request body.extensions.audit]: expected value of type [boolean] but got [number]'}
+ ${'extensions.aws'} | ${true} | ${200} | ${null}
+ ${'extensions.aws'} | ${0} | ${400} | ${'[request body.extensions.aws]: expected value of type [boolean] but got [number]'}
+ ${'extensions.ciscat'} | ${true} | ${200} | ${null}
+ ${'extensions.ciscat'} | ${0} | ${400} | ${'[request body.extensions.ciscat]: expected value of type [boolean] but got [number]'}
+ ${'extensions.gcp'} | ${true} | ${200} | ${null}
+ ${'extensions.gcp'} | ${0} | ${400} | ${'[request body.extensions.gcp]: expected value of type [boolean] but got [number]'}
+ ${'extensions.gdpr'} | ${true} | ${200} | ${null}
+ ${'extensions.gdpr'} | ${0} | ${400} | ${'[request body.extensions.gdpr]: expected value of type [boolean] but got [number]'}
+ ${'extensions.hipaa'} | ${true} | ${200} | ${null}
+ ${'extensions.hipaa'} | ${0} | ${400} | ${'[request body.extensions.hipaa]: expected value of type [boolean] but got [number]'}
+ ${'extensions.nist'} | ${true} | ${200} | ${null}
+ ${'extensions.nist'} | ${0} | ${400} | ${'[request body.extensions.nist]: expected value of type [boolean] but got [number]'}
+ ${'extensions.oscap'} | ${true} | ${200} | ${null}
+ ${'extensions.oscap'} | ${0} | ${400} | ${'[request body.extensions.oscap]: expected value of type [boolean] but got [number]'}
+ ${'extensions.osquery'} | ${true} | ${200} | ${null}
+ ${'extensions.osquery'} | ${0} | ${400} | ${'[request body.extensions.osquery]: expected value of type [boolean] but got [number]'}
+ ${'extensions.pci'} | ${true} | ${200} | ${null}
+ ${'extensions.pci'} | ${0} | ${400} | ${'[request body.extensions.pci]: expected value of type [boolean] but got [number]'}
+ ${'extensions.tsc'} | ${true} | ${200} | ${null}
+ ${'extensions.tsc'} | ${0} | ${400} | ${'[request body.extensions.tsc]: expected value of type [boolean] but got [number]'}
+ ${'extensions.virustotal'} | ${true} | ${200} | ${null}
+ ${'extensions.virustotal'} | ${0} | ${400} | ${'[request body.extensions.virustotal]: expected value of type [boolean] but got [number]'}
+ ${'ip.ignore'} | ${['test']} | ${200} | ${null}
+ ${'ip.ignore'} | ${['test*']} | ${200} | ${null}
+ ${'ip.ignore'} | ${['']} | ${400} | ${'[request body.ip.ignore.0]: Value can not be empty.'}
+ ${'ip.ignore'} | ${['test space']} | ${400} | ${"[request body.ip.ignore.0]: No whitespaces allowed."}
+ ${'ip.ignore'} | ${true} | ${400} | ${"[request body.ip.ignore]: expected value of type [array] but got [boolean]"}
+ ${'ip.ignore'} | ${['-test']} | ${400} | ${"[request body.ip.ignore.0]: It can't start with: -, _, +, .."}
+ ${'ip.ignore'} | ${['_test']} | ${400} | ${"[request body.ip.ignore.0]: It can't start with: -, _, +, .."}
+ ${'ip.ignore'} | ${['+test']} | ${400} | ${"[request body.ip.ignore.0]: It can't start with: -, _, +, .."}
+ ${'ip.ignore'} | ${['.test']} | ${400} | ${"[request body.ip.ignore.0]: It can't start with: -, _, +, .."}
+ ${'ip.ignore'} | ${['test\\']} | ${400} | ${"[request body.ip.ignore.0]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test/']} | ${400} | ${"[request body.ip.ignore.0]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test?']} | ${400} | ${"[request body.ip.ignore.0]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test"']} | ${400} | ${"[request body.ip.ignore.0]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test<']} | ${400} | ${"[request body.ip.ignore.0]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test>']} | ${400} | ${"[request body.ip.ignore.0]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test|']} | ${400} | ${"[request body.ip.ignore.0]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test,']} | ${400} | ${"[request body.ip.ignore.0]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test#']} | ${400} | ${"[request body.ip.ignore.0]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.ignore'} | ${['test', 'test#']} | ${400} | ${"[request body.ip.ignore.1]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'ip.selector'} | ${true} | ${200} | ${null}
+ ${'ip.selector'} | ${''} | ${400} | ${'[request body.ip.selector]: expected value of type [boolean] but got [string]'}
+ ${'logs.level'} | ${'info'} | ${200} | ${null}
+ ${'logs.level'} | ${'debug'} | ${200} | ${null}
+ ${'logs.level'} | ${''} | ${400} | ${'[request body.logs.level]: types that failed validation:\n- [request body.logs.level.0]: expected value to equal [info]\n- [request body.logs.level.1]: expected value to equal [debug]'}
+ ${'pattern'} | ${'test'} | ${200} | ${null}
+ ${'pattern'} | ${'test*'} | ${200} | ${null}
+ ${'pattern'} | ${''} | ${400} | ${'[request body.pattern]: Value can not be empty.'}
+ ${'pattern'} | ${'test space'} | ${400} | ${"[request body.pattern]: No whitespaces allowed."}
+ ${'pattern'} | ${true} | ${400} | ${'[request body.pattern]: expected value of type [string] but got [boolean]'}
+ ${'pattern'} | ${'-test'} | ${400} | ${"[request body.pattern]: It can't start with: -, _, +, .."}
+ ${'pattern'} | ${'_test'} | ${400} | ${"[request body.pattern]: It can't start with: -, _, +, .."}
+ ${'pattern'} | ${'+test'} | ${400} | ${"[request body.pattern]: It can't start with: -, _, +, .."}
+ ${'pattern'} | ${'.test'} | ${400} | ${"[request body.pattern]: It can't start with: -, _, +, .."}
+ ${'pattern'} | ${'test\\'} | ${400} | ${"[request body.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test/'} | ${400} | ${"[request body.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test?'} | ${400} | ${"[request body.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test"'} | ${400} | ${"[request body.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test<'} | ${400} | ${"[request body.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test>'} | ${400} | ${"[request body.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test|'} | ${400} | ${"[request body.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test,'} | ${400} | ${"[request body.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'pattern'} | ${'test#'} | ${400} | ${"[request body.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'timeout'} | ${15000} | ${200} | ${null}
+ ${'timeout'} | ${1000} | ${400} | ${'[request body.timeout]: Value should be greater or equal than 1500.'}
+ ${'timeout'} | ${''} | ${400} | ${'[request body.timeout]: expected value of type [number] but got [string]'}
+ ${'timeout'} | ${1.2} | ${400} | ${"[request body.timeout]: Number should be an integer."}
+ ${'wazuh.monitoring.creation'} | ${'h'} | ${200} | ${null}
+ ${'wazuh.monitoring.creation'} | ${'d'} | ${200} | ${null}
+ ${'wazuh.monitoring.creation'} | ${'w'} | ${200} | ${null}
+ ${'wazuh.monitoring.creation'} | ${'m'} | ${200} | ${null}
+ ${'wazuh.monitoring.creation'} | ${'test'} | ${400} | ${"[request body.wazuh.monitoring.creation]: types that failed validation:\n- [request body.wazuh.monitoring.creation.0]: expected value to equal [h]\n- [request body.wazuh.monitoring.creation.1]: expected value to equal [d]\n- [request body.wazuh.monitoring.creation.2]: expected value to equal [w]\n- [request body.wazuh.monitoring.creation.3]: expected value to equal [m]"}
+ ${'wazuh.monitoring.enabled'} | ${true} | ${200} | ${null}
+ ${'wazuh.monitoring.enabled'} | ${0} | ${400} | ${'[request body.wazuh.monitoring.enabled]: expected value of type [boolean] but got [number]'}
+ ${'wazuh.monitoring.frequency'} | ${100} | ${200} | ${null}
+ ${'wazuh.monitoring.frequency'} | ${40} | ${400} | ${"[request body.wazuh.monitoring.frequency]: Value should be greater or equal than 60."}
+ ${'wazuh.monitoring.frequency'} | ${1.2} | ${400} | ${"[request body.wazuh.monitoring.frequency]: Number should be an integer."}
+ ${'wazuh.monitoring.frequency'} | ${''} | ${400} | ${'[request body.wazuh.monitoring.frequency]: expected value of type [number] but got [string]'}
+ ${'wazuh.monitoring.pattern'} | ${'test'} | ${200} | ${null}
+ ${'wazuh.monitoring.pattern'} | ${'test*'} | ${200} | ${null}
+ ${'wazuh.monitoring.pattern'} | ${''} | ${400} | ${'[request body.wazuh.monitoring.pattern]: value has length [0] but it must have a minimum length of [1].'}
+ ${'wazuh.monitoring.pattern'} | ${true} | ${400} | ${'[request body.wazuh.monitoring.pattern]: expected value of type [string] but got [boolean]'}
+ ${'wazuh.monitoring.pattern'} | ${'-test'} | ${400} | ${"[request body.wazuh.monitoring.pattern]: It can't start with: -, _, +, .."}
+ ${'wazuh.monitoring.pattern'} | ${'_test'} | ${400} | ${"[request body.wazuh.monitoring.pattern]: It can't start with: -, _, +, .."}
+ ${'wazuh.monitoring.pattern'} | ${'+test'} | ${400} | ${"[request body.wazuh.monitoring.pattern]: It can't start with: -, _, +, .."}
+ ${'wazuh.monitoring.pattern'} | ${'.test'} | ${400} | ${"[request body.wazuh.monitoring.pattern]: It can't start with: -, _, +, .."}
+ ${'wazuh.monitoring.pattern'} | ${'test\\'} | ${400} | ${"[request body.wazuh.monitoring.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test/'} | ${400} | ${"[request body.wazuh.monitoring.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test?'} | ${400} | ${"[request body.wazuh.monitoring.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test"'} | ${400} | ${"[request body.wazuh.monitoring.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test<'} | ${400} | ${"[request body.wazuh.monitoring.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test>'} | ${400} | ${"[request body.wazuh.monitoring.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test|'} | ${400} | ${"[request body.wazuh.monitoring.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test,'} | ${400} | ${"[request body.wazuh.monitoring.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.pattern'} | ${'test#'} | ${400} | ${"[request body.wazuh.monitoring.pattern]: It can't contain invalid characters: \\, /, ?, \", <, >, |, ,, #."}
+ ${'wazuh.monitoring.replicas'} | ${0} | ${200} | ${null}
+ ${'wazuh.monitoring.replicas'} | ${-1} | ${400} | ${"[request body.wazuh.monitoring.replicas]: Value should be greater or equal than 0."}
+ ${'wazuh.monitoring.replicas'} | ${1.2} | ${400} | ${"[request body.wazuh.monitoring.replicas]: Number should be an integer."}
+ ${'wazuh.monitoring.replicas'} | ${'custom'} | ${400} | ${"[request body.wazuh.monitoring.replicas]: expected value of type [number] but got [string]"}
+ ${'wazuh.monitoring.shards'} | ${1} | ${200} | ${null}
+ ${'wazuh.monitoring.shards'} | ${-1} | ${400} | ${"[request body.wazuh.monitoring.shards]: Value should be greater or equal than 1."}
+ ${'wazuh.monitoring.shards'} | ${1.2} | ${400} | ${"[request body.wazuh.monitoring.shards]: Number should be an integer."}
+ ${'wazuh.monitoring.shards'} | ${'custom'} | ${400} | ${"[request body.wazuh.monitoring.shards]: expected value of type [number] but got [string]"}
+ `(`$setting: $value - PUT /utils/configuration - $responseStatusCode`, async ({ responseBodyMessage, responseStatusCode, setting, value }) => {
+ const body = { [setting]: value };
+ const response = await supertest(innerServer.listener)
+ .put('/utils/configuration')
+ .send(body)
+ .expect(responseStatusCode);
+
+ responseStatusCode === 200 && expect(response.body.data.updatedConfiguration).toEqual(body);
+ responseStatusCode === 200 && expect(response.body.data.requiresRunningHealthCheck).toBe(Boolean(PLUGIN_SETTINGS[setting].requiresRunningHealthCheck));
+ responseStatusCode === 200 && expect(response.body.data.requiresReloadingBrowserTab).toBe(Boolean(PLUGIN_SETTINGS[setting].requiresReloadingBrowserTab));
+ responseStatusCode === 200 && expect(response.body.data.requiresRestartingPluginPlatform).toBe(Boolean(PLUGIN_SETTINGS[setting].requiresRestartingPluginPlatform));
+ responseBodyMessage && expect(response.body.message).toMatch(responseBodyMessage);
+ });
+});
+
+describe('[endpoint] PUT /utils/configuration/files/{key} - Upload file', () => {
+
+ const PUBLIC_CUSTOM_ASSETS_PATH = path.join(__dirname, '../../../', 'public/assets/custom');
+
+ beforeAll(() => {
+ // Remove /public/assets/custom directory.
+ execSync(`rm -rf ${PUBLIC_CUSTOM_ASSETS_PATH}`);
+
+ // Create the configuration file with custom content
+ const fileContent = `---
+pattern: test-alerts-*
+
+hosts:
+ - default:
+ url: https://localhost
+ port: 55000
+ username: wazuh-wui
+ password: wazuh-wui
+ run_as: false
+`;
+
+ fs.writeFileSync(WAZUH_DATA_CONFIG_APP_PATH, fileContent, 'utf8');
+ });
+
+ afterAll(() => {
+ // Remove /public/assets/custom directory.
+ execSync(`rm -rf ${PUBLIC_CUSTOM_ASSETS_PATH}`);
+
+ // Remove the configuration file
+ fs.unlinkSync(WAZUH_DATA_CONFIG_APP_PATH);
+ });
+
+ it.each`
+ setting | filename | responseStatusCode | responseBodyMessage
+ ${'customization.logo.unknown'} | ${'fixture_image_small.jpg'} | ${400} | ${'[request params.key]: types that failed validation:\n- [request params.key.0]: expected value to equal [customization.logo.app]\n- [request params.key.1]: expected value to equal [customization.logo.healthcheck]\n- [request params.key.2]: expected value to equal [customization.logo.reports]\n- [request params.key.3]: expected value to equal [customization.logo.sidebar]'}
+ ${'customization.logo.app'} | ${'fixture_image_small.jpg'} | ${200} | ${null}
+ ${'customization.logo.app'} | ${'fixture_image_small.png'} | ${200} | ${null}
+ ${'customization.logo.app'} | ${'fixture_image_small.svg'} | ${200} | ${null}
+ ${'customization.logo.app'} | ${'fixture_image_big.png'} | ${413} | ${'Payload content length greater than maximum allowed: 1048576'}
+ ${'customization.logo.healthcheck'} | ${'fixture_image_small.jpg'} | ${200} | ${null}
+ ${'customization.logo.healthcheck'} | ${'fixture_image_small.png'} | ${200} | ${null}
+ ${'customization.logo.healthcheck'} | ${'fixture_image_small.svg'} | ${200} | ${null}
+ ${'customization.logo.healthcheck'} | ${'fixture_image_big.png'} | ${413} | ${'Payload content length greater than maximum allowed: 1048576'}
+ ${'customization.logo.reports'} | ${'fixture_image_small.jpg'} | ${200} | ${null}
+ ${'customization.logo.reports'} | ${'fixture_image_small.png'} | ${200} | ${null}
+ ${'customization.logo.reports'} | ${'fixture_image_big.png'} | ${413} | ${'Payload content length greater than maximum allowed: 1048576'}
+ ${'customization.logo.reports'} | ${'fixture_image_small.svg'} | ${400} | ${"File extension is not valid for setting [customization.logo.reports] setting. Allowed file extensions: .jpeg, .jpg, .png"}
+ ${'customization.logo.sidebar'} | ${'fixture_image_small.jpg'} | ${200} | ${null}
+ ${'customization.logo.sidebar'} | ${'fixture_image_small.png'} | ${200} | ${null}
+ ${'customization.logo.sidebar'} | ${'fixture_image_small.svg'} | ${200} | ${null}
+ ${'customization.logo.sidebar'} | ${'fixture_image_big.png'} | ${413} | ${'Payload content length greater than maximum allowed: 1048576'}
+ `(`$setting: $filename - PUT /utils/configuration/files/{key} - $responseStatusCode`, async ({ responseBodyMessage, responseStatusCode, setting, filename }) => {
+ const filePath = path.join(__dirname, 'fixtures', filename);
+ const extension = path.extname(filename);
+
+ const response = await supertest(innerServer.listener)
+ .put(`/utils/configuration/files/${setting}`)
+ .attach('file', filePath)
+ .expect(responseStatusCode);
+
+ responseStatusCode === 200 && expect(response.body.data.updatedConfiguration[setting]).toBeDefined();
+ responseStatusCode === 200 && expect(response.body.data.updatedConfiguration[setting]).toMatch(`${setting}${extension}`);
+ responseStatusCode === 200 && expect(response.body.data.requiresRunningHealthCheck).toBe(Boolean(PLUGIN_SETTINGS[setting].requiresRunningHealthCheck));
+ responseStatusCode === 200 && expect(response.body.data.requiresReloadingBrowserTab).toBe(Boolean(PLUGIN_SETTINGS[setting].requiresReloadingBrowserTab));
+ responseStatusCode === 200 && expect(response.body.data.requiresRestartingPluginPlatform).toBe(Boolean(PLUGIN_SETTINGS[setting].requiresRestartingPluginPlatform));
+ responseBodyMessage && expect(response.body.message).toMatch(responseBodyMessage);
+
+ // Check the file was created in the expected path of the file system.
+ if (response?.body?.data?.updatedConfiguration?.[setting]) {
+ const targetFilepath = path.join(__dirname, '../../../', PLUGIN_SETTINGS[setting].options.file.store.relativePathFileSystem, `${PLUGIN_SETTINGS[setting].options.file.store.filename}${extension}`);
+ const files = glob.sync(path.join(targetFilepath));
+ expect(files[0]).toBeDefined();
+ };
+ });
+});
+
+describe('[endpoint] DELETE /utils/configuration/files/{key} - Delete file', () => {
+
+ const PUBLIC_CUSTOM_ASSETS_PATH = path.join(__dirname, '../../../', 'public/assets/custom');
+
+ beforeAll(() => {
+ // Remove /public/assets/custom directory.
+ execSync(`rm -rf ${PUBLIC_CUSTOM_ASSETS_PATH}`);
+
+ // Create the configuration file with custom content
+ const fileContent = `---
+pattern: test-alerts-*
+
+hosts:
+ - default:
+ url: https://localhost
+ port: 55000
+ username: wazuh-wui
+ password: wazuh-wui
+ run_as: false
+`;
+
+ fs.writeFileSync(WAZUH_DATA_CONFIG_APP_PATH, fileContent, 'utf8');
+
+ createDirectoryIfNotExists(PUBLIC_CUSTOM_ASSETS_PATH);
+ });
+
+ afterAll(() => {
+ // Remove /public/assets/custom directory.
+ execSync(`rm -rf ${PUBLIC_CUSTOM_ASSETS_PATH}`);
+
+ // Remove the configuration file
+ fs.unlinkSync(WAZUH_DATA_CONFIG_APP_PATH);
+ });
+
+ it.each`
+ setting | expectedValue | responseStatusCode | responseBodyMessage
+ ${'customization.logo.unknown'} | ${''} | ${400} | ${'[request params.key]: types that failed validation:\n- [request params.key.0]: expected value to equal [customization.logo.app]\n- [request params.key.1]: expected value to equal [customization.logo.healthcheck]\n- [request params.key.2]: expected value to equal [customization.logo.reports]\n- [request params.key.3]: expected value to equal [customization.logo.sidebar]'}
+ ${'customization.logo.app'} | ${''} | ${200} | ${'All files were removed and the configuration file was updated.'}
+ ${'customization.logo.healthcheck'} | ${''} | ${200} | ${'All files were removed and the configuration file was updated.'}
+ ${'customization.logo.reports'} | ${''} | ${200} | ${'All files were removed and the configuration file was updated.'}
+ ${'customization.logo.sidebar'} | ${''} | ${200} | ${'All files were removed and the configuration file was updated.'}
+ `(`$setting - PUT /utils/configuration - $responseStatusCode`, async ({ responseBodyMessage, responseStatusCode, setting, expectedValue }) => {
+
+ // If the setting is defined in the plugin
+ if (PLUGIN_SETTINGS[setting]) {
+ // Create the directory where the asset was stored.
+ createDirectoryIfNotExists(path.join(__dirname, '../../../', PLUGIN_SETTINGS[setting].options.file.store.relativePathFileSystem));
+
+ // Create a empty file
+ fs.writeFileSync(path.join(__dirname, '../../../', PLUGIN_SETTINGS[setting].options.file.store.relativePathFileSystem, `${PLUGIN_SETTINGS[setting].options.file.store.filename}.jpg`), '', 'utf8');
+ };
+
+ const response = await supertest(innerServer.listener)
+ .delete(`/utils/configuration/files/${setting}`)
+ .expect(responseStatusCode);
+
+ responseStatusCode === 200 && expect(response.body.data.updatedConfiguration[setting]).toBeDefined();
+ responseStatusCode === 200 && expect(response.body.data.updatedConfiguration[setting]).toMatch(expectedValue);
+ responseStatusCode === 200 && expect(response.body.data.requiresRunningHealthCheck).toBe(Boolean(PLUGIN_SETTINGS[setting].requiresRunningHealthCheck));
+ responseStatusCode === 200 && expect(response.body.data.requiresReloadingBrowserTab).toBe(Boolean(PLUGIN_SETTINGS[setting].requiresReloadingBrowserTab));
+ responseStatusCode === 200 && expect(response.body.data.requiresRestartingPluginPlatform).toBe(Boolean(PLUGIN_SETTINGS[setting].requiresRestartingPluginPlatform));
+ responseBodyMessage && expect(response.body.message).toMatch(responseBodyMessage);
+
+ // Check the file was deleted from the expected path of the file system.
+ if (response?.body?.data?.updatedConfiguration?.[setting]) {
+ const targetFilepath = path.join(__dirname, '../../../', PLUGIN_SETTINGS[setting].options.file.store.relativePathFileSystem, `${PLUGIN_SETTINGS[setting].options.file.store.filename}.*`);
+ const files = glob.sync(path.join(targetFilepath));
+ expect(files).toHaveLength(0);
+ };
+ });
+});
+
+describe('[endpoint] GET /utils/logs', () => {
+ beforeAll(() => {
+ // Create the configuration file with custom content
+ const fileContent = `---
+{"date":"2022-09-20T08:36:16.688Z","level":"info","location":"initialize","message":"Kibana index: .kibana"}
+{"date":"2022-09-20T08:36:16.689Z","level":"info","location":"initialize","message":"App revision: 4400"}
+`;
+ fs.writeFileSync(WAZUH_DATA_LOGS_RAW_PATH, fileContent, 'utf8');
+ });
+
+ afterAll(() => {
+ // Remove the configuration file
+ fs.unlinkSync(WAZUH_DATA_LOGS_RAW_PATH);
+ });
+
+ it(`Get plugin logs. GET /utils/logs`, async () => {
+ const response = await supertest(innerServer.listener)
+ .get('/utils/logs')
+ .expect(200);
+
+ expect(response.body.lastLogs).toBeDefined();
});
});
diff --git a/server/routes/wazuh-utils/wazuh-utils.ts b/server/routes/wazuh-utils/wazuh-utils.ts
index 30ba0b0992..4e7821270f 100644
--- a/server/routes/wazuh-utils/wazuh-utils.ts
+++ b/server/routes/wazuh-utils/wazuh-utils.ts
@@ -10,8 +10,9 @@
* Find more information about this on the LICENSE file.
*/
import { WazuhUtilsCtrl } from '../../controllers';
-import { IRouter } from 'kibana/server';
-import { schema } from '@kbn/config-schema';
+import { IRouter } from 'opensearch_dashboards/server';
+import { schema } from '@osd/config-schema';
+import { CUSTOMIZATION_ENDPOINT_PAYLOAD_UPLOAD_CUSTOM_FILE_MAXIMUM_BYTES, EpluginSettingType, PLUGIN_SETTINGS } from '../../../common/constants';
export function WazuhUtilsRoutes(router: IRouter) {
const ctrl = new WazuhUtilsCtrl();
@@ -30,13 +31,66 @@ export function WazuhUtilsRoutes(router: IRouter) {
{
path: '/utils/configuration',
validate: {
+ body: schema.object(
+ Object.entries(PLUGIN_SETTINGS)
+ .filter(([, { isConfigurableFromFile }]) => isConfigurableFromFile)
+ .reduce(
+ (accum, [pluginSettingKey, pluginSettingConfiguration]) => ({
+ ...accum,
+ [pluginSettingKey]: schema.maybe(
+ pluginSettingConfiguration.validateBackend
+ ? pluginSettingConfiguration.validateBackend(schema)
+ : schema.any()
+ ),
+ }),
+ {}
+ )
+ )
+ }
+ },
+ async (context, request, response) => ctrl.updateConfigurationFile(context, request, response)
+ );
+
+ const pluginSettingsTypeFilepicker = Object.entries(PLUGIN_SETTINGS)
+ .filter(([_, { type, isConfigurableFromFile }]) => type === EpluginSettingType.filepicker && isConfigurableFromFile);
+
+ const schemaPluginSettingsTypeFilepicker = schema.oneOf(pluginSettingsTypeFilepicker.map(([pluginSettingKey]) => schema.literal(pluginSettingKey)));
+
+ // Upload an asset
+ router.put(
+ {
+ path: '/utils/configuration/files/{key}',
+ validate: {
+ params: schema.object({
+ // key parameter should be a plugin setting of `filepicker` type
+ key: schemaPluginSettingsTypeFilepicker
+ }),
body: schema.object({
- key: schema.string(),
- value: schema.any()
+ // file: buffer
+ file: schema.buffer(),
})
+ },
+ options: {
+ body: {
+ maxBytes: CUSTOMIZATION_ENDPOINT_PAYLOAD_UPLOAD_CUSTOM_FILE_MAXIMUM_BYTES,
+ },
}
},
- async (context, request, response) => ctrl.updateConfigurationFile(context, request, response)
+ async (context, request, response) => ctrl.uploadFile(context, request, response)
+ );
+
+ // Remove an asset
+ router.delete(
+ {
+ path: '/utils/configuration/files/{key}',
+ validate: {
+ params: schema.object({
+ // key parameter should be a plugin setting of `filepicker` type
+ key: schemaPluginSettingsTypeFilepicker
+ })
+ }
+ },
+ async (context, request, response) => ctrl.deleteFile(context, request, response)
);
// Returns Wazuh app logs
@@ -45,6 +99,6 @@ export function WazuhUtilsRoutes(router: IRouter) {
path: '/utils/logs',
validate: false
},
- async (context, request, response) => ctrl.getAppLogs(context,request, response)
+ async (context, request, response) => ctrl.getAppLogs(context, request, response)
);
}
diff --git a/server/start/cron-scheduler/save-document.test.ts b/server/start/cron-scheduler/save-document.test.ts
index 735f50dbe0..fe90baab66 100644
--- a/server/start/cron-scheduler/save-document.test.ts
+++ b/server/start/cron-scheduler/save-document.test.ts
@@ -4,7 +4,7 @@ import elasticsearch from 'elasticsearch';
describe('SaveDocument', () => {
const fakeServer = {
core: {
- elasticsearch: {
+ opensearch: {
client: { asInternalUser: '' },
getCluster: (data) => {
return {
diff --git a/server/start/cron-scheduler/save-document.ts b/server/start/cron-scheduler/save-document.ts
index dac3d30e8f..87b2203a37 100644
--- a/server/start/cron-scheduler/save-document.ts
+++ b/server/start/cron-scheduler/save-document.ts
@@ -20,10 +20,10 @@ export class SaveDocument {
constructor(context) {
this.context = context;
- this.esClientInternalUser = context.core.elasticsearch.client.asInternalUser;
+ this.esClientInternalUser = context.core.opensearch.client.asInternalUser;
}
- async save(doc: object[], indexConfig: IIndexConfiguration) {
+ async save(doc: object[], indexConfig: IIndexConfiguration) {
const { name, creation, mapping, shards, replicas } = indexConfig;
const index = this.addIndexPrefix(name);
const indexCreation = `${index}-${indexDate(creation)}`;
@@ -76,15 +76,11 @@ export class SaveDocument {
private createDocument(doc, index, mapping: string): BulkIndexDocumentsParams {
const createDocumentObject: BulkIndexDocumentsParams = {
index,
- type: '_doc',
- body: doc.flatMap(item => [{
- index: { _index: index }
- },
- {
+ body: doc.map(item => `{"index": { "_index": "${index}" }}\n${JSON.stringify({
...this.buildData(item, mapping),
timestamp: new Date(Date.now()).toISOString()
- }
- ])
+ })}\n`)
+ .join('')
};
log(this.logPath, `Document object: ${JSON.stringify(createDocumentObject)}`, 'debug');
return createDocumentObject;
@@ -99,7 +95,7 @@ export class SaveDocument {
if (keys.length === 1) {
if(key.match(/\[.*\]/)){
return getItemArray(
- item[key.replace(/\[.*\]/, '')],
+ item[key.replace(/\[.*\]/, '')],
key.match(/\[(.*)\]/)[1]
);
}
@@ -115,7 +111,7 @@ export class SaveDocument {
)
return JSON.parse(data);
}
-
+
if (typeof item.data === 'object') {
return item.data;
}
@@ -128,4 +124,4 @@ export class SaveDocument {
return `${prefix}-${index}`;
}
-}
\ No newline at end of file
+}
diff --git a/server/start/cron-scheduler/scheduler-handler.ts b/server/start/cron-scheduler/scheduler-handler.ts
index 25515fb296..4da8234bca 100644
--- a/server/start/cron-scheduler/scheduler-handler.ts
+++ b/server/start/cron-scheduler/scheduler-handler.ts
@@ -3,9 +3,10 @@ import { configuredJobs } from './configured-jobs';
import { log } from '../../lib/logger';
import { getConfiguration } from '../../lib/get-configuration';
import cron from 'node-cron';
-import { WAZUH_STATISTICS_DEFAULT_PREFIX, WAZUH_STATISTICS_DEFAULT_NAME, WAZUH_STATISTICS_TEMPLATE_NAME } from '../../../common/constants';
+import { WAZUH_STATISTICS_TEMPLATE_NAME } from '../../../common/constants';
import { statisticsTemplate } from '../../integration-files/statistics-template';
import { delayAsPromise } from '../../../common/utils';
+import { getSettingDefaultValue } from '../../../common/services/settings';
const blueWazuh = '\u001b[34mwazuh\u001b[39m';
const schedulerErrorLogColors = [blueWazuh, 'scheduler', 'error'];
@@ -21,7 +22,7 @@ const checkPluginPlatformStatus = async function (context) {
'Waiting for Kibana and Elasticsearch servers to be ready...',
'debug'
);
-
+
await checkElasticsearchServer(context);
await checkTemplate(context);
return;
@@ -36,17 +37,17 @@ const checkPluginPlatformStatus = async function (context) {
}catch(error){};
}
}
-
-
+
+
/**
* Check Elasticsearch Server status and Kibana index presence
*/
const checkElasticsearchServer = async function (context) {
try {
- const data = await context.core.elasticsearch.client.asInternalUser.indices.exists({
- index: context.server.config.kibana.index
+ const data = await context.core.opensearch.client.asInternalUser.indices.exists({
+ index: context.server.config.opensearchDashboards.index
});
-
+
return data.body;
} catch (error) {
log('scheduler-handler:checkElasticsearchServer', error.message || error);
@@ -67,13 +68,13 @@ const checkTemplate = async function (context) {
);
const appConfig = await getConfiguration();
- const prefixTemplateName = appConfig['cron.prefix'] || WAZUH_STATISTICS_DEFAULT_PREFIX;
- const statisticsIndicesTemplateName = appConfig['cron.statistics.index.name'] || WAZUH_STATISTICS_DEFAULT_NAME;
+ const prefixTemplateName = appConfig['cron.prefix'] || getSettingDefaultValue('cron.prefix');
+ const statisticsIndicesTemplateName = appConfig['cron.statistics.index.name'] || getSettingDefaultValue('cron.statistics.index.name');
const pattern = `${prefixTemplateName}-${statisticsIndicesTemplateName}-*`;
try {
// Check if the template already exists
- const currentTemplate = await context.core.elasticsearch.client.asInternalUser.indices.getTemplate({
+ const currentTemplate = await context.core.opensearch.client.asInternalUser.indices.getTemplate({
name: WAZUH_STATISTICS_TEMPLATE_NAME
});
// Copy already created index patterns
@@ -89,7 +90,7 @@ const checkTemplate = async function (context) {
};
// Update the statistics template
- await context.core.elasticsearch.client.asInternalUser.indices.putTemplate({
+ await context.core.opensearch.client.asInternalUser.indices.putTemplate({
name: WAZUH_STATISTICS_TEMPLATE_NAME,
body: statisticsTemplate
});
@@ -120,4 +121,4 @@ export async function jobSchedulerRun(context){
() => schedulerJob.run(),
);
}
-}
\ No newline at end of file
+}
diff --git a/server/start/initialize/index.test.ts b/server/start/initialize/index.test.ts
index dc62b29002..96c776281d 100644
--- a/server/start/initialize/index.test.ts
+++ b/server/start/initialize/index.test.ts
@@ -1,7 +1,5 @@
import fs from 'fs';
-import md5 from 'md5';
import { execSync } from 'child_process';
-import path from 'path';
import { jobInitializeRun } from './index';
import { createDataDirectoryIfNotExists, createDirectoryIfNotExists } from '../../lib/filesystem';
import { WAZUH_DATA_ABSOLUTE_PATH, WAZUH_DATA_CONFIG_DIRECTORY_PATH, WAZUH_DATA_CONFIG_REGISTRY_PATH } from '../../../common/constants';
@@ -31,13 +29,13 @@ function mockContextCreator(loggerLevel: string) {
},
server: {
config: {
- kibana: {
+ opensearchDashboards: {
index: '.kibana'
}
}
},
core: {
- elasticsearch: {
+ opensearch: {
client: {
asInternalUser: {
indices: {
@@ -87,7 +85,7 @@ describe("[initialize] `wazuh-registry.json` not created", () => {
await jobInitializeRun(mockContext);
const contentRegistry = JSON.parse(fs.readFileSync(WAZUH_DATA_CONFIG_REGISTRY_PATH, 'utf8'));
- expect(contentRegistry.name).toMatch('Wazuh App');
+ expect(contentRegistry.name).toMatch('Wazuh dashboard');
expect(contentRegistry['app-version']).toMatch(packageInfo.version);
expect(contentRegistry['revision']).toMatch(packageInfo.revision);
expect(typeof contentRegistry.installationDate).toBe('string');
@@ -101,7 +99,7 @@ describe("[initialize] `wazuh-registry.json` created", () => {
const contentRegistryFile = [
{
before: {
- name: 'Wazuh App',
+ name: 'Wazuh dashboard',
'app-version': packageInfo.version,
revision: packageInfo.revision,
installationDate: '2022-07-25T13:55:04.363Z',
@@ -109,7 +107,7 @@ describe("[initialize] `wazuh-registry.json` created", () => {
hosts: {}
},
after: {
- name: 'Wazuh App',
+ name: 'Wazuh dashboard',
'app-version': packageInfo.version,
revision: packageInfo.revision,
installationDate: '2022-07-25T13:55:04.363Z',
@@ -119,7 +117,7 @@ describe("[initialize] `wazuh-registry.json` created", () => {
},
{
before: {
- name: 'Wazuh App',
+ name: 'Wazuh dashboard',
'app-version': '0.0.0',
revision: '0',
installationDate: '2022-07-25T13:55:04.363Z',
@@ -127,7 +125,7 @@ describe("[initialize] `wazuh-registry.json` created", () => {
hosts: {}
},
after: {
- name: 'Wazuh App',
+ name: 'Wazuh dashboard',
'app-version': packageInfo.version,
revision: packageInfo.revision,
installationDate: '2022-07-25T13:55:04.363Z',
@@ -137,7 +135,7 @@ describe("[initialize] `wazuh-registry.json` created", () => {
},
{
before: {
- name: 'Wazuh App',
+ name: 'Wazuh dashboard',
'app-version': '0.0.0',
revision: '0',
installationDate: '2022-07-25T13:55:04.363Z',
@@ -165,7 +163,7 @@ describe("[initialize] `wazuh-registry.json` created", () => {
}
},
after: {
- name: 'Wazuh App',
+ name: 'Wazuh dashboard',
'app-version': packageInfo.version,
revision: packageInfo.revision,
installationDate: '2022-07-25T13:55:04.363Z',
@@ -195,7 +193,7 @@ describe("[initialize] `wazuh-registry.json` created", () => {
},
{
before: {
- name: 'Wazuh App',
+ name: 'Wazuh dashboard',
'app-version': '0.0.0',
revision: '0',
installationDate: '2022-07-25T13:55:04.363Z',
@@ -222,7 +220,7 @@ describe("[initialize] `wazuh-registry.json` created", () => {
}
},
after: {
- name: 'Wazuh App',
+ name: 'Wazuh dashboard',
'app-version': packageInfo.version,
revision: packageInfo.revision,
installationDate: '2022-07-25T13:55:04.363Z',
@@ -252,7 +250,7 @@ describe("[initialize] `wazuh-registry.json` created", () => {
},
{
before: {
- name: 'Wazuh App',
+ name: 'Wazuh dashboard',
'app-version': '0.0.0',
revision: '0',
installationDate: '2022-07-25T13:55:04.363Z',
@@ -277,7 +275,7 @@ describe("[initialize] `wazuh-registry.json` created", () => {
}
},
after: {
- name: 'Wazuh App',
+ name: 'Wazuh dashboard',
'app-version': packageInfo.version,
revision: packageInfo.revision,
installationDate: '2022-07-25T13:55:04.363Z',
@@ -330,7 +328,7 @@ describe("[initialize] `wazuh-registry.json` created", () => {
await jobInitializeRun(mockContext);
const contentRegistryFile = JSON.parse(fs.readFileSync(WAZUH_DATA_CONFIG_REGISTRY_PATH, 'utf8'));
- expect(contentRegistryFile.name).toMatch('Wazuh App');
+ expect(contentRegistryFile.name).toMatch('Wazuh dashboard');
expect(contentRegistryFile['app-version']).toMatch(contentRegistryExpected['app-version']);
expect(contentRegistryFile['revision']).toMatch(contentRegistryExpected.revision);
expect(typeof contentRegistryFile.installationDate).toBe('string');
diff --git a/server/start/initialize/index.ts b/server/start/initialize/index.ts
index ab33b4f5d1..092317ddbf 100644
--- a/server/start/initialize/index.ts
+++ b/server/start/initialize/index.ts
@@ -15,13 +15,14 @@ import { pluginPlatformTemplate } from '../../integration-files/kibana-template'
import { getConfiguration } from '../../lib/get-configuration';
import { totalmem } from 'os';
import fs from 'fs';
-import { WAZUH_ALERTS_PATTERN, WAZUH_DATA_CONFIG_REGISTRY_PATH, WAZUH_PLUGIN_PLATFORM_TEMPLATE_NAME, WAZUH_DATA_PLUGIN_PLATFORM_BASE_ABSOLUTE_PATH, PLUGIN_PLATFORM_NAME, PLUGIN_PLATFORM_INSTALLATION_USER_GROUP, PLUGIN_PLATFORM_INSTALLATION_USER, WAZUH_DEFAULT_APP_CONFIG, PLUGIN_APP_NAME } from '../../../common/constants';
+import { WAZUH_DATA_CONFIG_REGISTRY_PATH, WAZUH_PLUGIN_PLATFORM_TEMPLATE_NAME, WAZUH_DATA_PLUGIN_PLATFORM_BASE_ABSOLUTE_PATH, PLUGIN_PLATFORM_NAME, PLUGIN_PLATFORM_INSTALLATION_USER_GROUP, PLUGIN_PLATFORM_INSTALLATION_USER, WAZUH_DEFAULT_APP_CONFIG, PLUGIN_APP_NAME } from '../../../common/constants';
import { createDataDirectoryIfNotExists } from '../../lib/filesystem';
import _ from 'lodash';
+import { getSettingDefaultValue, getSettingsDefault } from '../../../common/services/settings';
export function jobInitializeRun(context) {
- const PLUGIN_PLATFORM_INDEX = context.server.config.kibana.index;
+ const PLUGIN_PLATFORM_INDEX = context.server.config.opensearchDashboards.index;
log('initialize', `${PLUGIN_PLATFORM_NAME} index: ${PLUGIN_PLATFORM_INDEX}`, 'info');
log('initialize', `App revision: ${packageJSON.revision}`, 'info');
@@ -34,7 +35,7 @@ export function jobInitializeRun(context) {
pattern =
configurationFile && typeof configurationFile.pattern !== 'undefined'
? configurationFile.pattern
- : WAZUH_ALERTS_PATTERN;
+ : getSettingDefaultValue('pattern');
} catch (error) {
log('initialize', error.message || error);
context.wazuh.logger.error(
@@ -59,7 +60,7 @@ export function jobInitializeRun(context) {
const commonDate = new Date().toISOString();
const configuration = {
- name: 'Wazuh App',
+ name: PLUGIN_APP_NAME,
'app-version': packageJSON.version,
revision: packageJSON.revision,
installationDate: commonDate,
@@ -107,7 +108,7 @@ export function jobInitializeRun(context) {
'debug'
);
- if(!fs.existsSync(WAZUH_DATA_PLUGIN_PLATFORM_BASE_ABSOLUTE_PATH)){
+ if (!fs.existsSync(WAZUH_DATA_PLUGIN_PLATFORM_BASE_ABSOLUTE_PATH)) {
throw new Error(`The data directory is missing in the ${PLUGIN_PLATFORM_NAME} root instalation. Create the directory in ${WAZUH_DATA_PLUGIN_PLATFORM_BASE_ABSOLUTE_PATH} and give it the required permissions (sudo mkdir ${WAZUH_DATA_PLUGIN_PLATFORM_BASE_ABSOLUTE_PATH};sudo chown -R ${PLUGIN_PLATFORM_INSTALLATION_USER}:${PLUGIN_PLATFORM_INSTALLATION_USER_GROUP} ${WAZUH_DATA_PLUGIN_PLATFORM_BASE_ABSOLUTE_PATH}). After restart the ${PLUGIN_PLATFORM_NAME} service.`);
};
@@ -128,7 +129,7 @@ export function jobInitializeRun(context) {
const isUpgradedApp = packageJSON.revision !== source.revision || packageJSON.version !== source['app-version'];
// Rebuild the registry file if revision or version fields are differents
- if (isUpgradedApp) {
+ if (isUpgradedApp) {
log(
'initialize:checkwazuhRegistry',
'Wazuh app revision or version changed, regenerating wazuh-registry.json.',
@@ -138,11 +139,11 @@ export function jobInitializeRun(context) {
// Rebuild the registry file `wazuh-registry.json`
// Get the supported extensions for the installed plugin
- const supportedDefaultExtensionsConfiguration = Object.entries(WAZUH_DEFAULT_APP_CONFIG)
+ const supportedDefaultExtensionsConfiguration = Object.entries(getSettingsDefault())
.filter(([setting]) => setting.startsWith('extensions.'))
.map(([setting, settingValue]) => {
return [setting.split('.')[1], settingValue];
- });
+ });
// Get the supported extensions by ID
const supportedDefaultExtensionsNames = supportedDefaultExtensionsConfiguration.map(([setting]) => setting);
@@ -153,7 +154,7 @@ export function jobInitializeRun(context) {
// Remove the unsupported extensions for the installed plugin
const registryHostsData = Object.entries(source.hosts).reduce((accum, [hostID, hostData]) => {
accum[hostID] = hostData;
- if(accum[hostID].extensions){
+ if (accum[hostID].extensions) {
// Migrate extensions to those supported by the installed plugin
const defaultHostExtentionsConfiguration = Object.fromEntries(supportedDefaultExtensionsConfiguration);
// Select of current configuration the extension IDs that are supported in the installed plugin
@@ -197,7 +198,7 @@ export function jobInitializeRun(context) {
);
}
- return context.core.elasticsearch.client.asInternalUser.indices.putTemplate({
+ return context.core.opensearch.client.asInternalUser.indices.putTemplate({
name: WAZUH_PLUGIN_PLATFORM_TEMPLATE_NAME,
order: 0,
create: true,
@@ -212,7 +213,7 @@ export function jobInitializeRun(context) {
`Creating ${PLUGIN_PLATFORM_INDEX} index.`,
'info'
);
- await context.core.elasticsearch.client.asInternalUser.indices.create({
+ await context.core.opensearch.client.asInternalUser.indices.create({
index: PLUGIN_PLATFORM_INDEX
});
log(
@@ -224,8 +225,7 @@ export function jobInitializeRun(context) {
} catch (error) {
return Promise.reject(
new Error(
- `Error creating ${
- PLUGIN_PLATFORM_INDEX
+ `Error creating ${PLUGIN_PLATFORM_INDEX
} index due to ${error.message || error}`
)
);
@@ -244,8 +244,7 @@ export function jobInitializeRun(context) {
} catch (error) {
return Promise.reject(
new Error(
- `Error creating template for ${
- PLUGIN_PLATFORM_INDEX
+ `Error creating template for ${PLUGIN_PLATFORM_INDEX
} due to ${error.message || error}`
)
);
@@ -254,7 +253,7 @@ export function jobInitializeRun(context) {
const getTemplateByName = async () => {
try {
- await context.core.elasticsearch.client.asInternalUser.indices.getTemplate({
+ await context.core.opensearch.client.asInternalUser.indices.getTemplate({
name: WAZUH_PLUGIN_PLATFORM_TEMPLATE_NAME
});
log(
@@ -272,7 +271,7 @@ export function jobInitializeRun(context) {
// Does Kibana index exist?
const checkKibanaStatus = async () => {
try {
- const response = await context.core.elasticsearch.client.asInternalUser.indices.exists({
+ const response = await context.core.opensearch.client.asInternalUser.indices.exists({
index: PLUGIN_PLATFORM_INDEX
});
if (response.body) {
@@ -296,13 +295,13 @@ export function jobInitializeRun(context) {
// Wait until Elasticsearch js is ready
const checkStatus = async () => {
try {
- // TODO: wait until elasticsearch is ready?
- // await server.plugins.elasticsearch.waitUntilReady();
+ // TODO: wait until opensearch is ready?
+ // await server.plugins.opensearch.waitUntilReady();
return await checkKibanaStatus();
} catch (error) {
log(
'initialize:checkStatus',
- 'Waiting for elasticsearch plugin to be ready...',
+ 'Waiting for opensearch plugin to be ready...',
'debug'
);
setTimeout(() => checkStatus(), 3000);
diff --git a/server/start/monitoring/index.ts b/server/start/monitoring/index.ts
index e5e43853c8..c17e844897 100644
--- a/server/start/monitoring/index.ts
+++ b/server/start/monitoring/index.ts
@@ -17,17 +17,12 @@ import { parseCron } from '../../lib/parse-cron';
import { indexDate } from '../../lib/index-date';
import { buildIndexSettings } from '../../lib/build-index-settings';
import { WazuhHostsCtrl } from '../../controllers/wazuh-hosts';
-import {
- WAZUH_MONITORING_PATTERN,
+import {
WAZUH_MONITORING_TEMPLATE_NAME,
- WAZUH_MONITORING_DEFAULT_CREATION,
- WAZUH_MONITORING_DEFAULT_ENABLED,
- WAZUH_MONITORING_DEFAULT_FREQUENCY,
- WAZUH_MONITORING_DEFAULT_INDICES_SHARDS,
- WAZUH_MONITORING_DEFAULT_INDICES_REPLICAS,
} from '../../../common/constants';
import { tryCatchForIndexPermissionError } from '../tryCatchForIndexPermissionError';
import { delayAsPromise } from '../../../common/utils';
+import { getSettingDefaultValue } from '../../../common/services/settings';
const blueWazuh = '\u001b[34mwazuh\u001b[39m';
const monitoringErrorLogColors = [blueWazuh, 'monitoring', 'error'];
@@ -42,7 +37,7 @@ let MONITORING_ENABLED, MONITORING_FREQUENCY, MONITORING_CRON_FREQ, MONITORING_C
* @param configuration
* @param defaultValue
*/
-function getAppConfigurationSetting(setting: string, configuration: any, defaultValue: any){
+function getAppConfigurationSetting(setting: string, configuration: any, defaultValue: any) {
return typeof configuration[setting] !== 'undefined' ? configuration[setting] : defaultValue;
};
@@ -50,23 +45,23 @@ function getAppConfigurationSetting(setting: string, configuration: any, default
* Set the monitoring variables
* @param context
*/
-function initMonitoringConfiguration(context){
- try{
+function initMonitoringConfiguration(context) {
+ try {
const appConfig = getConfiguration();
MONITORING_ENABLED = appConfig && typeof appConfig['wazuh.monitoring.enabled'] !== 'undefined'
? appConfig['wazuh.monitoring.enabled'] &&
- appConfig['wazuh.monitoring.enabled'] !== 'worker'
- : WAZUH_MONITORING_DEFAULT_ENABLED;
- MONITORING_FREQUENCY = getAppConfigurationSetting('wazuh.monitoring.frequency', appConfig, WAZUH_MONITORING_DEFAULT_FREQUENCY);
+ appConfig['wazuh.monitoring.enabled'] !== 'worker'
+ : getSettingDefaultValue('wazuh.monitoring.enabled');
+ MONITORING_FREQUENCY = getAppConfigurationSetting('wazuh.monitoring.frequency', appConfig, getSettingDefaultValue('wazuh.monitoring.frequency'));
MONITORING_CRON_FREQ = parseCron(MONITORING_FREQUENCY);
- MONITORING_CREATION = getAppConfigurationSetting('wazuh.monitoring.creation', appConfig, WAZUH_MONITORING_DEFAULT_CREATION);
+ MONITORING_CREATION = getAppConfigurationSetting('wazuh.monitoring.creation', appConfig, getSettingDefaultValue('wazuh.monitoring.creation'));
- MONITORING_INDEX_PATTERN = getAppConfigurationSetting('wazuh.monitoring.pattern', appConfig, WAZUH_MONITORING_PATTERN);
+ MONITORING_INDEX_PATTERN = getAppConfigurationSetting('wazuh.monitoring.pattern', appConfig, getSettingDefaultValue('wazuh.monitoring.pattern'));
const lastCharIndexPattern = MONITORING_INDEX_PATTERN[MONITORING_INDEX_PATTERN.length - 1];
if (lastCharIndexPattern !== '*') {
MONITORING_INDEX_PATTERN += '*';
};
- MONITORING_INDEX_PREFIX = MONITORING_INDEX_PATTERN.slice(0,MONITORING_INDEX_PATTERN.length - 1);
+ MONITORING_INDEX_PREFIX = MONITORING_INDEX_PATTERN.slice(0, MONITORING_INDEX_PATTERN.length - 1);
log(
'monitoring:initMonitoringConfiguration',
@@ -85,7 +80,7 @@ function initMonitoringConfiguration(context){
`wazuh.monitoring.pattern: ${MONITORING_INDEX_PATTERN} (index prefix: ${MONITORING_INDEX_PREFIX})`,
'debug'
);
- }catch(error){
+ } catch (error) {
const errorMessage = error.message || error;
log(
'monitoring:initMonitoringConfiguration',
@@ -124,14 +119,14 @@ async function checkTemplate(context) {
try {
// Check if the template already exists
- const currentTemplate = await context.core.elasticsearch.client.asInternalUser.indices.getTemplate({
+ const currentTemplate = await context.core.opensearch.client.asInternalUser.indices.getTemplate({
name: WAZUH_MONITORING_TEMPLATE_NAME
});
// Copy already created index patterns
monitoringTemplate.index_patterns = currentTemplate.body[WAZUH_MONITORING_TEMPLATE_NAME].index_patterns;
- }catch (error) {
+ } catch (error) {
// Init with the default index pattern
- monitoringTemplate.index_patterns = [WAZUH_MONITORING_PATTERN];
+ monitoringTemplate.index_patterns = [getSettingDefaultValue('wazuh.monitoring.pattern')];
}
// Check if the user is using a custom pattern and add it to the template if it does
@@ -140,7 +135,7 @@ async function checkTemplate(context) {
};
// Update the monitoring template
- await context.core.elasticsearch.client.asInternalUser.indices.putTemplate({
+ await context.core.opensearch.client.asInternalUser.indices.putTemplate({
name: WAZUH_MONITORING_TEMPLATE_NAME,
body: monitoringTemplate
});
@@ -167,39 +162,39 @@ async function checkTemplate(context) {
*/
async function insertMonitoringDataElasticsearch(context, data) {
const monitoringIndexName = MONITORING_INDEX_PREFIX + indexDate(MONITORING_CREATION);
- if (!MONITORING_ENABLED){
- return;
- };
- try {
- await tryCatchForIndexPermissionError(monitoringIndexName) (async() => {
- const exists = await context.core.elasticsearch.client.asInternalUser.indices.exists({index: monitoringIndexName});
- if(!exists.body){
- await createIndex(context, monitoringIndexName);
- };
-
- // Update the index configuration
- const appConfig = getConfiguration();
- const indexConfiguration = buildIndexSettings(
- appConfig,
- 'wazuh.monitoring',
- WAZUH_MONITORING_DEFAULT_INDICES_SHARDS
- );
+ if (!MONITORING_ENABLED) {
+ return;
+ };
+ try {
+ await tryCatchForIndexPermissionError(monitoringIndexName)(async () => {
+ const exists = await context.core.opensearch.client.asInternalUser.indices.exists({ index: monitoringIndexName });
+ if (!exists.body) {
+ await createIndex(context, monitoringIndexName);
+ };
- // To update the index settings with this client is required close the index, update the settings and open it
- // Number of shards is not dynamic so delete that setting if it's given
- delete indexConfiguration.settings.index.number_of_shards;
- await context.core.elasticsearch.client.asInternalUser.indices.putSettings({
- index: monitoringIndexName,
- body: indexConfiguration
- });
-
- // Insert data to the monitoring index
- await insertDataToIndex(context, monitoringIndexName, data);
- })();
- }catch(error){
- log('monitoring:insertMonitoringDataElasticsearch', error.message || error);
- context.wazuh.logger.error(error.message);
- }
+ // Update the index configuration
+ const appConfig = getConfiguration();
+ const indexConfiguration = buildIndexSettings(
+ appConfig,
+ 'wazuh.monitoring',
+ getSettingDefaultValue('wazuh.monitoring.shards')
+ );
+
+ // To update the index settings with this client is required close the index, update the settings and open it
+ // Number of shards is not dynamic so delete that setting if it's given
+ delete indexConfiguration.settings.index.number_of_shards;
+ await context.core.opensearch.client.asInternalUser.indices.putSettings({
+ index: monitoringIndexName,
+ body: indexConfiguration
+ });
+
+ // Insert data to the monitoring index
+ await insertDataToIndex(context, monitoringIndexName, data);
+ })();
+ } catch (error) {
+ log('monitoring:insertMonitoringDataElasticsearch', error.message || error);
+ context.wazuh.logger.error(error.message);
+ }
}
/**
@@ -208,7 +203,7 @@ async function insertMonitoringDataElasticsearch(context, data) {
* @param {String} indexName The name for the index (e.g. daily: wazuh-monitoring-YYYY.MM.DD)
* @param {*} data
*/
-async function insertDataToIndex(context, indexName: string, data: {agents: any[], apiHost}) {
+async function insertDataToIndex(context, indexName: string, data: { agents: any[], apiHost }) {
const { agents, apiHost } = data;
try {
if (agents.length > 0) {
@@ -219,14 +214,14 @@ async function insertDataToIndex(context, indexName: string, data: {agents: any[
);
const bodyBulk = agents.map(agent => {
- const agentInfo = {...agent};
+ const agentInfo = { ...agent };
agentInfo['timestamp'] = new Date(Date.now()).toISOString();
agentInfo.host = agent.manager;
agentInfo.cluster = { name: apiHost.clusterName ? apiHost.clusterName : 'disabled' };
return `{ "index": { "_index": "${indexName}" } }\n${JSON.stringify(agentInfo)}\n`;
}).join('');
- await context.core.elasticsearch.client.asInternalUser.bulk({
+ await context.core.opensearch.client.asInternalUser.bulk({
index: indexName,
body: bodyBulk
});
@@ -240,7 +235,7 @@ async function insertDataToIndex(context, indexName: string, data: {agents: any[
log(
'monitoring:insertDataToIndex',
`Error inserting agent data into elasticsearch. Bulk request failed due to ${error.message ||
- error}`
+ error}`
);
}
}
@@ -258,13 +253,13 @@ async function createIndex(context, indexName: string) {
const IndexConfiguration = {
settings: {
index: {
- number_of_shards: getAppConfigurationSetting('wazuh.monitoring.shards', appConfig, WAZUH_MONITORING_DEFAULT_INDICES_SHARDS),
- number_of_replicas: getAppConfigurationSetting('wazuh.monitoring.replicas', appConfig, WAZUH_MONITORING_DEFAULT_INDICES_REPLICAS)
+ number_of_shards: getAppConfigurationSetting('wazuh.monitoring.shards', appConfig, getSettingDefaultValue('wazuh.monitoring.shards')),
+ number_of_replicas: getAppConfigurationSetting('wazuh.monitoring.replicas', appConfig, getSettingDefaultValue('wazuh.monitoring.replicas'))
}
}
};
- await context.core.elasticsearch.client.asInternalUser.indices.create({
+ await context.core.opensearch.client.asInternalUser.indices.create({
index: indexName,
body: IndexConfiguration
});
@@ -288,26 +283,26 @@ async function createIndex(context, indexName: string) {
* Wait until Kibana server is ready
*/
async function checkPluginPlatformStatus(context) {
- try {
+ try {
log(
'monitoring:checkPluginPlatformStatus',
'Waiting for Kibana and Elasticsearch servers to be ready...',
'debug'
);
- await checkElasticsearchServer(context);
- await init(context);
- return;
- } catch (error) {
+ await checkElasticsearchServer(context);
+ await init(context);
+ return;
+ } catch (error) {
log(
'monitoring:checkPluginPlatformStatus',
- error.mesage ||error
+ error.mesage || error
);
- try{
+ try {
await delayAsPromise(3000);
await checkPluginPlatformStatus(context);
- }catch(error){};
- }
+ } catch (error) { };
+ }
}
@@ -316,8 +311,8 @@ async function checkPluginPlatformStatus(context) {
*/
async function checkElasticsearchServer(context) {
try {
- const data = await context.core.elasticsearch.client.asInternalUser.indices.exists({
- index: context.server.config.kibana.index
+ const data = await context.core.opensearch.client.asInternalUser.indices.exists({
+ index: context.server.config.opensearchDashboards.index
});
return data.body;
@@ -370,7 +365,7 @@ async function getHostsConfiguration() {
*/
async function cronTask(context) {
try {
- const templateMonitoring = await context.core.elasticsearch.client.asInternalUser.indices.getTemplate({name: WAZUH_MONITORING_TEMPLATE_NAME});
+ const templateMonitoring = await context.core.opensearch.client.asInternalUser.indices.getTemplate({ name: WAZUH_MONITORING_TEMPLATE_NAME });
const apiHosts = await getHostsConfiguration();
const apiHostsUnique = (apiHosts || []).filter(
@@ -384,11 +379,11 @@ async function cronTask(context) {
t.port === apiHost.port
)
);
- for(let apiHost of apiHostsUnique){
- try{
- const { agents, apiHost: host} = await getApiInfo(context, apiHost);
- await insertMonitoringDataElasticsearch(context, {agents, apiHost: host});
- }catch(error){
+ for (let apiHost of apiHostsUnique) {
+ try {
+ const { agents, apiHost: host } = await getApiInfo(context, apiHost);
+ await insertMonitoringDataElasticsearch(context, { agents, apiHost: host });
+ } catch (error) {
};
}
@@ -415,18 +410,18 @@ async function cronTask(context) {
* @param context
* @param apiHost
*/
-async function getApiInfo(context, apiHost){
- try{
+async function getApiInfo(context, apiHost) {
+ try {
log('monitoring:getApiInfo', `Getting API info for ${apiHost.id}`, 'debug');
const responseIsCluster = await context.wazuh.api.client.asInternalUser.request('GET', '/cluster/status', {}, { apiHostID: apiHost.id });
const isCluster = (((responseIsCluster || {}).data || {}).data || {}).enabled === 'yes';
- if(isCluster){
- const responseClusterInfo = await context.wazuh.api.client.asInternalUser.request('GET', `/cluster/local/info`, {}, { apiHostID: apiHost.id });
+ if (isCluster) {
+ const responseClusterInfo = await context.wazuh.api.client.asInternalUser.request('GET', `/cluster/local/info`, {}, { apiHostID: apiHost.id });
apiHost.clusterName = responseClusterInfo.data.data.affected_items[0].cluster;
};
const agents = await fetchAllAgentsFromApiHost(context, apiHost);
return { agents, apiHost };
- }catch(error){
+ } catch (error) {
log('monitoring:getApiInfo', error.message || error);
throw error;
}
@@ -437,9 +432,9 @@ async function getApiInfo(context, apiHost){
* @param context
* @param apiHost
*/
-async function fetchAllAgentsFromApiHost(context, apiHost){
+async function fetchAllAgentsFromApiHost(context, apiHost) {
let agents = [];
- try{
+ try {
log('monitoring:fetchAllAgentsFromApiHost', `Getting all agents from ApiID: ${apiHost.id}`, 'debug');
const responseAgentsCount = await context.wazuh.api.client.asInternalUser.request(
'GET',
@@ -450,7 +445,7 @@ async function fetchAllAgentsFromApiHost(context, apiHost){
limit: 1,
q: 'id!=000'
}
- }, {apiHostID: apiHost.id});
+ }, { apiHostID: apiHost.id });
const agentsCount = responseAgentsCount.data.data.total_affected_items;
log('monitoring:fetchAllAgentsFromApiHost', `ApiID: ${apiHost.id}, Agent count: ${agentsCount}`, 'debug');
@@ -462,8 +457,8 @@ async function fetchAllAgentsFromApiHost(context, apiHost){
};
while (agents.length < agentsCount && payload.offset < agentsCount) {
- try{
- /*
+ try {
+ /*
TODO: Improve the performance of request with:
- Reduce the number of requests to the Wazuh API
- Reduce (if possible) the quantity of data to index by document
@@ -480,17 +475,17 @@ async function fetchAllAgentsFromApiHost(context, apiHost){
const responseAgents = await context.wazuh.api.client.asInternalUser.request(
'GET',
`/agents`,
- {params: payload},
- {apiHostID: apiHost.id}
+ { params: payload },
+ { apiHostID: apiHost.id }
);
agents = [...agents, ...responseAgents.data.data.affected_items];
payload.offset += payload.limit;
- }catch(error){
+ } catch (error) {
log('monitoring:fetchAllAgentsFromApiHost', `ApiID: ${apiHost.id}, Error request with offset/limit ${payload.offset}/${payload.limit}: ${error.message || error}`);
}
}
return agents;
- }catch(error){
+ } catch (error) {
log('monitoring:fetchAllAgentsFromApiHost', `ApiID: ${apiHost.id}. Error: ${error.message || error}`);
throw error;
}
diff --git a/server/types.ts b/server/types.ts
index f6dbc19a5f..bc80cd26bf 100644
--- a/server/types.ts
+++ b/server/types.ts
@@ -16,16 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { SecurityPluginSetup } from 'x-pack/plugins/security/server';
-import { SpacesPluginSetup } from 'x-pack/plugins/spaces/server';
export interface WazuhPluginSetup {}
export interface WazuhPluginStart {}
export type PluginSetup = {
- security?: SecurityPluginSetup,
- opendistroSecurityKibana?: {}, // TODO: Add ODFE interface
- spaces?: SpacesPluginSetup,
- searchguard?: {}, // TODO: Add searchguard interface
+ securityDashboards?: {}, // TODO: Add OpenSearch Dashboards Security interface
}
diff --git a/test/cypress/.eslintignore b/test/cypress/.eslintignore
new file mode 100644
index 0000000000..c2658d7d1b
--- /dev/null
+++ b/test/cypress/.eslintignore
@@ -0,0 +1 @@
+node_modules/
diff --git a/test/cypress/.eslintrc.json b/test/cypress/.eslintrc.json
new file mode 100644
index 0000000000..936efe81da
--- /dev/null
+++ b/test/cypress/.eslintrc.json
@@ -0,0 +1,18 @@
+{
+ "plugins": [
+ "cypress"
+ ],
+ "rules": {
+ "cypress/no-assigning-return-values": "error",
+ "cypress/no-unnecessary-waiting": "error",
+ "cypress/assertion-before-screenshot": "warn",
+ "cypress/no-force": "warn",
+ "cypress/no-async-tests": "error"
+ },
+ "env": {
+ "cypress/globals": true
+ },
+ "extends": [
+ "plugin:cypress/recommended"
+ ]
+}
diff --git a/test/cypress/.nvmrc b/test/cypress/.nvmrc
new file mode 100644
index 0000000000..c15795bf69
--- /dev/null
+++ b/test/cypress/.nvmrc
@@ -0,0 +1 @@
+17.3.0
\ No newline at end of file
diff --git a/test/cypress/.prettierrc b/test/cypress/.prettierrc
new file mode 100644
index 0000000000..d440171380
--- /dev/null
+++ b/test/cypress/.prettierrc
@@ -0,0 +1,5 @@
+{
+ "singleQuote": true,
+ "trailingComma": "es5",
+ "printWidth": 100
+}
diff --git a/test/cypress/CODEOWNERS b/test/cypress/CODEOWNERS
new file mode 100644
index 0000000000..4b5ea279ed
--- /dev/null
+++ b/test/cypress/CODEOWNERS
@@ -0,0 +1,5 @@
+# This should match the owning team set up in https://github.com/orgs/wazuh/teams
+* @wazuh/frontend
+
+@Mayons95
+@mauceballos
\ No newline at end of file
diff --git a/test/cypress/README.md b/test/cypress/README.md
new file mode 100644
index 0000000000..fda73b32ae
--- /dev/null
+++ b/test/cypress/README.md
@@ -0,0 +1,41 @@
+# Automation Cypress
+
+This project contains the [Cypress](https://www.cypress.io/) library for testing.\
+Remember to have run the `npm install` command. \
+If cypress doesn't install and unzip correctly run the following command `npm run cy:install`.\
+Before executing the command `npm start` remember to have the client's server up and running.
+
+## Configuration
+set your server ip on `"baseUrl":` parameter inside `cypress.json` file
+
+## Execute tests in debug
+run `cypress open`
+
+## Execute test using tags
+`npx cypress-tags run -e TAGS='@about'`
+
+## Run special environment variable commands
+
+example:
+`npm run start -- --env type=odfe --config baseUrl=https://localhost:5600`
+
+### default setting:
+type=`xpack`
+baseUrl=`https://localhost:5601/`
+
+
+### start automated test execution (emulated the execution locally)
+### Draft on Spanish
+* (generar imagen de Docker de Cypress con la rama que se quiere probar)
+* ingresar al template de "WZD" y modificar el .env con el nombre de la imagen de docker de cypress que se genero previamente
+* levantar el contenerdo con docker compose up -d
+* eliminar el paquete de WZD que viene pre-instalado:
+ - ./bin/opensearch-dashboards-plugin remove wazuh
+ - docker compose restart
+* instalar el paquete nuevo (el paquete que se usa en el GitHub Action) y ejecutar:
+ - ./bin/opensearch-dashboards-plugin install https://packages-dev.wazuh.com/pre-release/ui/dashboard/wazuh-4.3.5-1.zip
+ - reiciar docker
+ - check WZD
+* ingresar al Path del template de wzd y ejecutar:
+ - docker exec $(docker-compose ps -q cypress) bash -c " . /home/automation/nvm/nvm.sh && nvm use && npm run cypress:run-headless:github-actions:wzd"
+
diff --git a/test/cypress/STYLEGUIDE.md b/test/cypress/STYLEGUIDE.md
new file mode 100644
index 0000000000..d84d3ea3f2
--- /dev/null
+++ b/test/cypress/STYLEGUIDE.md
@@ -0,0 +1,863 @@
+# JavaScript Style Guide
+
+## Attribution
+
+This JavaScript guide forked from the [node style guide](https://github.com/felixge/node-style-guide) created by [Felix Geisendörfer](http://felixge.de/) and is
+licensed under the [CC BY-SA 3.0](http://creativecommons.org/licenses/by-sa/3.0/)
+license.
+
+## 2 Spaces for indention
+
+Use 2 spaces for indenting your code and swear an oath to never mix tabs and
+spaces - a special kind of hell is awaiting you otherwise.
+
+## Newlines
+
+Use UNIX-style newlines (`\n`), and a newline character as the last character
+of a file. Windows-style newlines (`\r\n`) are forbidden inside any repository.
+
+## No trailing whitespace
+
+Just like you brush your teeth after every meal, you clean up any trailing
+whitespace in your JS files before committing. Otherwise the rotten smell of
+careless neglect will eventually drive away contributors and/or co-workers.
+
+## Use Semicolons
+
+According to [scientific research][hnsemicolons], the usage of semicolons is
+a core value of our community. Consider the points of [the opposition][], but
+be a traditionalist when it comes to abusing error correction mechanisms for
+cheap syntactic pleasures.
+
+[the opposition]: http://blog.izs.me/post/2353458699/an-open-letter-to-javascript-leaders-regarding
+[hnsemicolons]: http://news.ycombinator.com/item?id=1547647
+
+## 100 characters per line
+
+You should limit your lines to 100 chars. Prettier will check for that line width where enabled.
+
+## Use `const` for variables
+
+Your variable references should rarely be mutable, so use `const` for almost
+everything. If you absolutely *must* mutate a reference, use `let`.
+
+```js
+// good
+const foo = 'bar';
+
+// if absolutely necessary, OK
+let foo;
+
+// bad
+var foo = 'bar';
+```
+
+## Use single quotes for fixed strings
+
+Use single quotes, unless you are writing JSON.
+
+```js
+// good
+const foo = 'bar';
+
+// bad
+const foo = "bar";
+```
+
+## Use template strings to interpolate variables into strings
+
+```js
+// good
+const foo = `Hello, ${name}`;
+
+// bad
+const foo = 'Hello, ' + name;
+```
+
+## Use template strings to avoid escaping single quotes
+
+Because readability is paramount.
+
+```js
+// good
+const foo = `You won't believe this.`;
+
+// bad
+const foo = 'You won\'t believe this.';
+```
+
+## Use object destructuring
+
+This helps avoid temporary references and helps prevent typo-related bugs.
+
+```js
+// best
+function fullName({ first, last }) {
+ return `${first} ${last}`;
+}
+
+// good
+function fullName(user) {
+ const { first, last } = user;
+ return `${first} ${last}`;
+}
+
+// bad
+function fullName(user) {
+ const first = user.first;
+ const last = user.last;
+ return `${first} ${last}`;
+}
+```
+
+## Use array destructuring
+
+Directly accessing array values via index should be avoided, but if it is
+necessary, use array destructuring:
+
+```js
+const arr = [1, 2, 3];
+
+// good
+const [first, second] = arr;
+
+// bad
+const first = arr[0];
+const second = arr[1];
+```
+
+## Opening braces go on the same line
+
+Your opening braces go on the same line as the statement.
+
+```js
+// good
+if (true) {
+ console.log('winning');
+}
+
+// bad
+if (true)
+{
+ console.log('losing');
+}
+```
+
+Also, notice the use of whitespace before and after the condition statement.
+
+## Always use braces for conditionals and loops
+
+```js
+// good
+if (err) {
+ return cb(err);
+}
+
+// bad
+if (err) cb(err);
+
+// bad
+if (err)
+ return cb(err);
+```
+
+## Declare one variable per line, wherever it makes the most sense
+
+This makes it easier to re-order the lines. However, ignore
+[Crockford][crockfordconvention] when it comes to declaring variables deeper
+inside a function, just put the declarations wherever they make sense.
+
+```js
+// good
+const keys = ['foo', 'bar'];
+const values = [23, 42];
+
+// bad
+const keys = ['foo', 'bar'],
+ values = [23, 42];
+```
+
+[crockfordconvention]: http://javascript.crockford.com/code.html
+
+## Use lowerCamelCase for variables, properties and function names
+
+Variables, properties and function names should use `lowerCamelCase`. They
+should also be descriptive. Single character variables and uncommon
+abbreviations should generally be avoided.
+
+```js
+// good
+const adminUser = getAdmin();
+
+// bad
+const admin_user = getAdmin();
+```
+
+## Use UpperCamelCase for class names (constructors)
+
+Class names should be capitalized using `UpperCamelCase`.
+
+```js
+// good
+class BankAccount {}
+
+// bad
+class bank_account {}
+class bankAccount {}
+```
+
+## Prefix private class methods with an underscore
+
+Identifying private class methods makes it easier to differentiate a class's public and internal
+APIs, and makes private methods easier to mark as `private` when the code is migrated to TypeScript.
+
+```js
+// good
+class BankAccount {
+ addFunds() {}
+
+ _calculateInterest() {}
+}
+```
+
+## Magic numbers/strings
+
+These are numbers (or other values) simply used in line in your code. *Do not
+use these*, give them a variable name so they can be understood and changed
+easily.
+
+```js
+// good
+const minWidth = 300;
+
+if (width < minWidth) {
+ ...
+}
+
+// bad
+if (width < 300) {
+ ...
+}
+```
+
+## Object properties and functions
+
+Use object method shorthand syntax for functions on objects:
+
+```js
+// good
+const foo = {
+ bar() {
+ ...
+ }
+};
+
+// bad
+const foo = {
+ bar: function () {
+ ...
+ }
+};
+```
+
+Use property value shorthand syntax for properties that share a name with a
+variable. And put them at the beginning:
+
+```js
+const bar = true;
+
+// good
+const foo = {
+ bar
+};
+
+// bad
+const foo = {
+ bar: bar
+};
+
+// also bad (bar should be first)
+const foo = {
+ baz: false,
+ bar
+};
+```
+
+## Modules
+
+Module dependencies should be written using native ES2015 syntax wherever
+possible (which is almost everywhere):
+
+```js
+// good
+import { mapValues } from 'lodash';
+export mapValues;
+
+// bad
+const _ = require('lodash');
+module.exports = _.mapValues;
+
+// worse
+define(['lodash'], function (_) {
+ ...
+});
+```
+
+In those extremely rare cases where you're writing server-side JavaScript in a
+file that does not pass run through webpack, then use CommonJS modules.
+
+In those even rarer cases where you're writing client-side code that does not
+run through webpack, then do not use a module loader at all.
+
+## Import only top-level modules
+
+The files inside a module are implementation details of that module. They
+should never be imported directly. Instead, you must only import the top-level
+API that's exported by the module itself.
+
+Without a clear mechanism in place in JS to encapsulate protected code, we make
+a broad assumption that anything beyond the root of a module is an
+implementation detail of that module.
+
+On the other hand, a module should be able to import parent and sibling
+modules.
+
+```js
+// good
+import foo from 'foo';
+import child from './child';
+import parent from '../';
+import ancestor from '../../../';
+import sibling from '../foo';
+
+// bad
+import inFoo from 'foo/child';
+import inSibling from '../foo/child';
+```
+
+## Use named exports only
+
+Favor named exports over default exports.
+
+```js
+// good
+import { foo } from 'foo';
+export foo;
+
+// bad
+import myDefaultModule from 'foo/child';
+export default myDefaultModule;
+```
+
+## Global definitions
+
+Don't do this. Everything should be wrapped in a module that can be depended on
+by other modules. Even things as simple as a single value should be a module.
+
+## Function definitions
+
+Use function declarations over function expressions, so that their names will
+show up in stack traces, making errors easier to debug.
+
+Also, keep function definitions above other code instead of relying on function
+hoisting.
+
+```js
+// good
+function myFunc() {
+ ...
+}
+
+// bad
+const myFunc = function () {
+ ...
+};
+```
+
+## Arrow functions
+
+If you must use a function expression, then use an arrow function:
+
+```js
+// good
+[1, 2, 3].map((n) => {
+ const m = doSomething(n);
+ return m - n;
+});
+
+// bad
+[1, 2, 3].map(function (n) {
+ const m = doSomething(n);
+ return m - n;
+});
+```
+
+If your function body does not include braces and only accepts one argument,
+then omit the argument parentheses:
+
+```js
+// good
+[1, 2, 3].map(n => n + 1);
+
+// bad
+[1, 2, 3].map((n) => n + 1);
+
+// bad
+[1, 2, 3].map(n => {
+ return n + 1;
+});
+```
+
+If your arrow function is only returning an object literal, then wrap the
+object in parentheses rather than using an explicit return:
+
+```js
+// good
+() => ({
+ foo: 'bar'
+})
+
+// bad
+() => {
+ return {
+ foo: 'bar'
+ };
+}
+```
+
+## Object / Array creation
+
+Use trailing commas and put *short* declarations on a single line. Only quote
+keys when your interpreter complains:
+
+```js
+// good
+const a = ['hello', 'world'];
+const b = {
+ good: 'code',
+ 'is generally': 'pretty'
+};
+
+// bad
+const a = [
+ 'hello', 'world'
+];
+const b = {'good': 'code'
+ , is generally: 'pretty'
+ };
+```
+
+## Object / Array iterations, transformations and operations
+
+Use native methods to iterate and transform arrays and objects where possible.
+Avoid `for` and `while` loops as they introduce the possibility of infinite
+loops and break out of our preferred convention of declarative programming.
+
+Use descriptive variable names in the closures.
+
+Use a utility library as needed and where it will make code more
+comprehensible.
+
+```js
+// best
+const userNames = users.map(user => user.name);
+
+// ok
+import { pluck } from 'lodash';
+const userNames = pluck(users, 'name');
+
+// bad
+const userNames = [];
+for (let i = 0; i < users.length; i++) {
+ userNames.push(users[i].name);
+}
+```
+
+## Use the spread operator (...) for copying arrays
+
+This helps with expressiveness and readability.
+
+```js
+const arr = [1, 2, 3];
+
+// good
+const arrCopy = [...arr];
+
+// bad
+const arrCopy = arr.slice();
+```
+
+## Use the === operator
+
+Programming is not about remembering [stupid rules][comparisonoperators]. Use
+the triple equality operator as it will work just as expected.
+
+```js
+const a = 0;
+
+// good
+if (a !== '') {
+ console.log('winning');
+}
+
+// bad
+if (a == '') {
+ console.log('losing');
+}
+```
+
+[comparisonoperators]: https://developer.mozilla.org/en/JavaScript/Reference/Operators/Comparison_Operators
+
+## Only use ternary operators for small, simple code
+
+And *never* use multiple ternaries together, because they make it more
+difficult to reason about how different values flow through the conditions
+involved. Instead, structure the logic for maximum readability.
+
+```js
+// good, a situation where only 1 ternary is needed
+const foo = (a === b) ? 1 : 2;
+
+// bad
+const foo = (a === b) ? 1 : (a === c) ? 2 : 3;
+```
+
+## Do not extend built-in prototypes
+
+Do not extend the prototype of native JavaScript objects. Your future self will
+be forever grateful.
+
+```js
+// bad
+Array.prototype.empty = function () {
+ return !this.length;
+}
+```
+
+## Use descriptive conditions
+
+Any non-trivial conditions should be converted to functions or assigned to
+descriptively named variables. By breaking up logic into smaller,
+self-contained blocks, it becomes easier to reason about the higher-level
+logic. Additionally, these blocks become good candidates for extraction into
+their own modules, with unit-tests.
+
+```js
+// best
+function isShape(thing) {
+ return thing instanceof Shape;
+}
+function notSquare(thing) {
+ return !(thing instanceof Square);
+}
+if (isShape(thing) && notSquare(thing)) {
+ ...
+}
+
+// good
+const isShape = thing instanceof Shape;
+const notSquare = !(thing instanceof Square);
+if (isShape && notSquare) {
+ ...
+}
+
+// bad
+if (thing instanceof Shape && !(thing instanceof Square)) {
+ ...
+}
+```
+
+## Name regular expressions
+
+```js
+// good
+const validPassword = /^(?=.*\d).{4,}$/;
+
+if (password.length >= 4 && validPassword.test(password)) {
+ console.log('password is valid');
+}
+
+// bad
+if (password.length >= 4 && /^(?=.*\d).{4,}$/.test(password)) {
+ console.log('losing');
+}
+```
+
+## Write small functions
+
+Keep your functions short. A good function fits on a slide that the people in
+the last row of a big room can comfortably read. So don't count on them having
+perfect vision and limit yourself to ~15 lines of code per function.
+
+## Use "rest" syntax rather than built-in `arguments`
+
+For expressiveness sake, and so you can be mix dynamic and explicit arguments.
+
+```js
+// good
+function something(foo, ...args) {
+ ...
+}
+
+// bad
+function something(foo) {
+ const args = Array.from(arguments).slice(1);
+ ...
+}
+```
+
+## Default argument syntax
+
+Always use the default argument syntax for optional arguments.
+
+```js
+// good
+function foo(options = {}) {
+ ...
+}
+
+// bad
+function foo(options) {
+ if (typeof options === 'undefined') {
+ options = {};
+ }
+ ...
+}
+```
+
+And put your optional arguments at the end.
+
+```js
+// good
+function foo(bar, options = {}) {
+ ...
+}
+
+// bad
+function foo(options = {}, bar) {
+ ...
+}
+```
+
+## Return/throw early from functions
+
+To avoid deep nesting of if-statements, always return a function's value as early
+as possible. And where possible, do any assertions first:
+
+```js
+// good
+function doStuff(val) {
+ if (val > 100) {
+ throw new Error('Too big');
+ }
+
+ if (val < 0) {
+ return false;
+ }
+
+ // ... stuff
+}
+
+// bad
+function doStuff(val) {
+ if (val >= 0) {
+ if (val < 100) {
+ // ... stuff
+ } else {
+ throw new Error('Too big');
+ }
+ } else {
+ return false;
+ }
+}
+```
+
+## Chaining operations
+
+When using a chaining syntax, indent the subsequent chained operations.
+
+Also, if the chain is long, each method should be on a new line.
+
+```js
+// good
+$http.get('/info')
+ .then(({ data }) => this.transformInfo(data))
+ .then((transformed) => $http.post('/new-info', transformed))
+ .then(({ data }) => console.log(data));
+
+// bad
+$http.get('/info')
+.then(({ data }) => this.transformInfo(data))
+.then((transformed) => $http.post('/new-info', transformed))
+.then(({ data }) => console.log(data));
+```
+
+## Avoid mutability and state
+
+Wherever possible, do not rely on mutable state. This means you should not
+reassign variables, modify object properties, or push values to arrays.
+Instead, create new variables, and shallow copies of objects and arrays:
+
+```js
+// good
+function addBar(foos, foo) {
+ const newFoo = {...foo, name: 'bar'};
+ return [...foos, newFoo];
+}
+
+// bad
+function addBar(foos, foo) {
+ foo.name = 'bar';
+ foos.push(foo);
+}
+```
+
+## Use thunks to create closures, where possible
+
+For trivial examples (like the one that follows), thunks will seem like
+overkill, but they encourage isolating the implementation details of a closure
+from the business logic of the calling code.
+
+```js
+// good
+function connectHandler(client, callback) {
+ return () => client.connect(callback);
+}
+setTimeout(connectHandler(client, afterConnect), 1000);
+
+// not as good
+setTimeout(() => {
+ client.connect(afterConnect);
+}, 1000);
+
+// bad
+setTimeout(() => {
+ client.connect(() => {
+ ...
+ });
+}, 1000);
+```
+
+## Use slashes for comments
+
+Use slashes for both single line and multi line comments. Try to write
+comments that explain higher level mechanisms or clarify difficult
+segments of your code. *Don't use comments to restate trivial things*.
+
+*Exception:* Comment blocks describing a function and its arguments
+(docblock) should start with `/**`, contain a single `*` at the beginning of
+each line, and end with `*/`.
+
+
+```js
+// good
+
+// 'ID_SOMETHING=VALUE' -> ['ID_SOMETHING=VALUE', 'SOMETHING', 'VALUE']
+const matches = item.match(/ID_([^\n]+)=([^\n]+)/));
+
+/**
+ * Fetches a user from...
+ * @param {string} id - id of the user
+ * @return {Promise}
+ */
+function loadUser(id) {
+ // This function has a nasty side effect where a failure to increment a
+ // redis counter used for statistics will cause an exception. This needs
+ // to be fixed in a later iteration.
+
+ ...
+}
+
+const isSessionValid = (session.expires < Date.now());
+if (isSessionValid) {
+ ...
+}
+
+// bad
+
+// Execute a regex
+const matches = item.match(/ID_([^\n]+)=([^\n]+)/));
+
+// Usage: loadUser(5, function() { ... })
+function loadUser(id, cb) {
+ // ...
+}
+
+// Check if the session is valid
+const isSessionValid = (session.expires < Date.now());
+// If the session is valid
+if (isSessionValid) {
+ ...
+}
+```
+
+## Do not comment out code
+
+We use a version management system. If a line of code is no longer needed,
+remove it, don't simply comment it out.
+
+## Classes/Constructors and Inheritance
+
+If you must use a constructor, then use the native `class` syntax. *Never* use
+third party "class" utilities, and never mutate prototypes.
+
+```js
+// best (no local state at all)
+function addUser(users, user) {
+ return [...users, user];
+}
+const users = addUser([], { name: 'foo' });
+
+// good
+class Users {
+ add(user) {
+ ...
+ }
+}
+const users = new Users();
+users.add({ name: 'foo' });
+
+// bad
+function Users() {
+ ...
+}
+Users.prototype.add = function () {
+ ...
+};
+const users = new Users();
+users.add({ name: 'foo' });
+```
+
+## Do not alias `this`
+
+Try not to rely on `this` at all, but if you must, then use arrow functions
+instead of aliasing it.
+
+```js
+// good
+class Users {
+ add(user) {
+ return createUser(user)
+ .then(response => this.users.push(response.user));
+ }
+}
+
+// bad
+class Users {
+ add(user) {
+ const self = this;
+ return createUser(user).then(function (response) {
+ self.users.push(response.user);
+ });
+ }
+}
+```
+
+## Getters and Setters
+
+Feel free to use getters that are free from [side effects][sideeffect], like
+providing a length property for a collection class.
+
+Do not use setters, they cause more problems than they can solve.
+
+[sideeffect]: http://en.wikipedia.org/wiki/Side_effect_(computer_science)
\ No newline at end of file
diff --git a/test/cypress/cookies.json b/test/cypress/cookies.json
new file mode 100644
index 0000000000..dd0f2b1643
--- /dev/null
+++ b/test/cypress/cookies.json
@@ -0,0 +1 @@
+[{"name":"currentPattern","value":"wazuh-alerts-*","path":"/app/wazuh","secure":false,"httpOnly":false,"expiry":1693322677,"domain":"localhost"},{"name":"currentApi","value":"%257B%2522name%2522%3A%2522wazuh_manager_filebeat_sources_cmake-v4.3.6-7.10.2%2522%2C%2522id%2522%3A%2522default%2522%257D","path":"/app/wazuh","secure":false,"httpOnly":false,"expiry":1693322678,"domain":"localhost"},{"name":"clusterInfo","value":"%257B%2522status%2522%3A%2522enabled%2522%2C%2522manager%2522%3A%2522wazuh_manager_filebeat_sources_cmake-v4.3.6-7.10.2%2522%2C%2522node%2522%3A%2522master-node%2522%2C%2522cluster%2522%3A%2522wazuh%2522%257D","path":"/app/wazuh","secure":false,"httpOnly":false,"expiry":1693322678,"domain":"localhost"},{"name":"appName","value":"wazuh","path":"/app/wazuh","secure":false,"httpOnly":false,"domain":"localhost"},{"name":"patternSelector","value":"true","path":"/app/wazuh","secure":false,"httpOnly":false,"domain":"localhost"},{"name":"wz-user","value":"elastic","path":"/","secure":false,"httpOnly":true,"domain":"localhost"},{"name":"wz-api","value":"default","path":"/","secure":false,"httpOnly":true,"domain":"localhost"},{"name":"wz-token","value":"eyJhbGciOiJFUzUxMiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ3YXp1aCIsImF1ZCI6IldhenVoIEFQSSBSRVNUIiwibmJmIjoxNjYxNzg2NjgxLCJleHAiOjE2NjE3ODc1ODEsInN1YiI6IndhenVoLXd1aSIsInJ1bl9hcyI6ZmFsc2UsInJiYWNfcm9sZXMiOlsxXSwicmJhY19tb2RlIjoid2hpdGUifQ.Af-6j0o54TsXPM-QbMACCPDkXJQ5kw_sDNKsb1P5FyvQP_xv8atqINLTs3YCRvAmx9RuGKhqJCwaGVd8qneJSV83AcwkLoTuAcrtVU7BR1czyq2uBRwuCPnkvUiHyfQBLrK-MIXRiTio0ro8pCdHpYoqjAWhN4NYLc2lnMUuifjue4z7","path":"/","secure":false,"httpOnly":true,"domain":"localhost"}]
\ No newline at end of file
diff --git a/test/cypress/cypress.json b/test/cypress/cypress.json
new file mode 100644
index 0000000000..05771af1a4
--- /dev/null
+++ b/test/cypress/cypress.json
@@ -0,0 +1,24 @@
+{
+ "baseUrl": "http://localhost:5601/",
+ "testFiles": ["**/*.{feature,features}"],
+ "defaultCommandTimeout": 40000,
+ "viewportWidth": 1400,
+ "viewportHeight": 1500,
+ "reporter": "mochawesome",
+ "watchForFileChanges": false,
+ "numTestsKeptInMemory": 0,
+ "reporterOptions": {
+ "charts": true,
+ "overwrite": false,
+ "html": true,
+ "json": true,
+ "reportDir": "cypress/report/mochawesome-report",
+ "mochaFile": "cypress/report/output.html"
+ },
+ "videosFolder": "cypress/report/video",
+ "screenshotsFolder": "cypress/report/screenshots",
+ "experimentalSessionAndOrigin": true,
+ "env": {
+ "type": "odfe"
+ }
+}
diff --git a/test/cypress/cypress/fixtures/configuration.panel.text.json b/test/cypress/cypress/fixtures/configuration.panel.text.json
new file mode 100644
index 0000000000..62752f61c8
--- /dev/null
+++ b/test/cypress/cypress/fixtures/configuration.panel.text.json
@@ -0,0 +1,206 @@
+{
+ "configurationTitle": "App current settings",
+ "configurationDescription": "Configuration file located at /usr/share/kibana/data/wazuh/config/wazuh.yml",
+ "Panel": [
+ {
+ "name": "General",
+ "items": [
+ {
+ "title": "Index pattern",
+ "subTitle": "Default index pattern to use on the app. If there's no valid index pattern, the app will automatically create one with the name indicated in this option.",
+ "label": "pattern"
+ },
+ {
+ "title": "Request timeout",
+ "subTitle": "Maximum time, in milliseconds, the app will wait for an API response when making requests to it. It will be ignored if the value is set under 1500 milliseconds.",
+ "label": "timeout"
+ },
+ {
+ "title": "IP selector",
+ "subTitle": "Define if the user is allowed to change the selected index pattern directly from the top menu bar.",
+ "label": "ip.selector"
+ },
+ {
+ "title": "IP ignore",
+ "subTitle": "Disable certain index pattern names from being available in index pattern selector from the Wazuh app.",
+ "label": "ip.ignore"
+ },
+ {
+ "title": "Cron prefix",
+ "subTitle": "Define the index prefix of predefined jobs.",
+ "label": "cron.prefix"
+ },
+ {
+ "title": "Sample alerts prefix",
+ "subTitle": "Define the index name prefix of sample alerts. It must match the template used by the index pattern to avoid unknown fields in dashboards.",
+ "label": "alerts.sample.prefix"
+ },
+ {
+ "title": "Hide manager alerts",
+ "subTitle": "Hide the alerts of the manager in every dashboard.",
+ "label": "hideManagerAlerts"
+ },
+ {
+ "title": "Log level",
+ "subTitle": "Logging level of the App.",
+ "label": "logs.level"
+ },
+ {
+ "title": "Enrollment DNS",
+ "subTitle": "Specifies the Wazuh registration server, used for the agent enrollment.",
+ "label": "enrollment.dns"
+ }
+ ]
+ },
+ {
+ "name": "Health Check",
+ "items": [
+ {
+ "title": "Index pattern",
+ "subTitle": "Enable or disable the index pattern health check when opening the app.",
+ "label": "checks.pattern"
+ },
+ {
+ "title": "Index template",
+ "subTitle": "Enable or disable the template health check when opening the app.",
+ "label": "checks.template"
+ },
+ {
+ "title": "API connection",
+ "subTitle": "Enable or disable the API health check when opening the app.",
+ "label": "checks.api"
+ },
+ {
+ "title": "API version",
+ "subTitle": "Enable or disable the setup health check when opening the app.",
+ "label": "checks.setup"
+ },
+ {
+ "title": "Known fields",
+ "subTitle": "Enable or disable the known fields health check when opening the app.",
+ "label": "checks.fields"
+ },
+ {
+ "title": "Remove meta fields",
+ "subTitle": "Change the default value of the Kibana metaField configuration",
+ "label": "checks.metaFields"
+ },
+ {
+ "title": "Set max buckets to 200000",
+ "subTitle": "Change the default value of the Kibana max buckets configuration",
+ "label": "checks.maxBuckets"
+ },
+ {
+ "title": "Set time filter to 24h",
+ "subTitle": "Change the default value of the Kibana timeFilter configuration",
+ "label": "checks.timeFilter"
+ }
+ ]
+ },
+ {
+ "name": "Monitoring",
+ "items": [
+ {
+ "title": "Status",
+ "subTitle": "Enable or disable the wazuh-monitoring index creation and/or visualization.",
+ "label": "wazuh.monitoring.enabled"
+ },
+ {
+ "title": "Frequency",
+ "subTitle": "Frequency, in seconds, of API requests to get the state of the agents and create a new document in the wazuh-monitoring index with this data.",
+ "label": "wazuh.monitoring.frequency"
+ },
+ {
+ "title": "Index shards",
+ "subTitle": "Define the number of shards to use for the wazuh-monitoring-* indices.",
+ "label": "wazuh.monitoring.shards"
+ },
+ {
+ "title": "Index replicas",
+ "subTitle": "Define the number of replicas to use for the wazuh-monitoring-* indices.",
+ "label": "wazuh.monitoring.replicas"
+ },
+ {
+ "title": "Index creation",
+ "subTitle": "Define the interval in which a new wazuh-monitoring index will be created.",
+ "label": "wazuh.monitoring.creation"
+ },
+ {
+ "title": "Index pattern",
+ "subTitle": "Default index pattern to use for Wazuh monitoring.",
+ "label": "wazuh.monitoring.pattern"
+ },
+ {
+ "title": "",
+ "subTitle": "",
+ "label": ""
+ }
+ ]
+ },
+ {
+ "name": "Statistics",
+ "items": [
+ {
+ "title": "Status",
+ "subTitle": "Enable or disable the statistics tasks.",
+ "label": "cron.statistics.status"
+ },
+ {
+ "title": "Includes apis",
+ "subTitle": "Enter the ID of the hosts you want to save data from, leave this empty to run the task on every host.",
+ "label": "cron.statistics.apis"
+ },
+ {
+ "title": "Interval",
+ "subTitle": "Define the frequency of task execution using cron schedule expressions.",
+ "label": "cron.statistics.interval"
+ },
+ {
+ "title": "Index name",
+ "subTitle": "Define the name of the index in which the documents will be saved.",
+ "label": "cron.statistics.index.name"
+ },
+ {
+ "title": "Index creation",
+ "subTitle": "Define the interval in which a new index will be created.",
+ "label": "cron.statistics.index.creation"
+ },
+ {
+ "title": "Index shards",
+ "subTitle": "Define the number of shards to use for the statistics indices.",
+ "label": "cron.statistics.index.shards"
+ },
+ {
+ "title": "Index replicas",
+ "subTitle": "Define the number of replicas to use for the statistics indices.",
+ "label": "cron.statistics.index.replicas"
+ }
+ ]
+ },
+ {
+ "name": "Logo Customization",
+ "items": [
+ {
+ "title": "Logo App",
+ "subTitle": "Set the name of the app logo stored at /plugins/wazuh/public/assets/",
+ "label": "customization.logo.app"
+ },
+ {
+ "title": "Logo Sidebar",
+ "subTitle": "Set the name of the sidebar logo stored at /plugins/wazuh/public/assets/",
+ "label": "customization.logo.sidebar"
+ },
+ {
+ "title": "Logo Health Check",
+ "subTitle": "Set the name of the health-check logo stored at /plugins/wazuh/public/assets/",
+ "label": "customization.logo.healthcheck"
+ },
+ {
+ "title": "Logo Reports",
+ "subTitle": "Set the name of the reports logo (.png) stored at /plugins/wazuh/public/assets/",
+ "label": "customization.logo.reports"
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/test/cypress/cypress/fixtures/example.json b/test/cypress/cypress/fixtures/example.json
new file mode 100644
index 0000000000..02e4254378
--- /dev/null
+++ b/test/cypress/cypress/fixtures/example.json
@@ -0,0 +1,5 @@
+{
+ "name": "Using fixtures to represent data",
+ "email": "hello@cypress.io",
+ "body": "Fixtures are a great way to mock data for responses to routes"
+}
diff --git a/test/cypress/cypress/integration/features/agents/add-agent-from-deploy-new-agent.feature b/test/cypress/cypress/integration/features/agents/add-agent-from-deploy-new-agent.feature
new file mode 100644
index 0000000000..5525a7be5c
--- /dev/null
+++ b/test/cypress/cypress/integration/features/agents/add-agent-from-deploy-new-agent.feature
@@ -0,0 +1,22 @@
+Feature: Validate that the config to added new agent
+
+ As a wazuh user
+ I want to add a new agent
+ in order to manage them
+
+ @agent @actions
+ Scenario Outline: Validate the information to add a new Agent
+ Given The wazuh admin user is logged
+ When The user navigates to the agent page
+ And The user selects a deploy new agent
+ Then The browser is on the new deploy agent page
+ And A box with four steps to the different settings is displayed
+ And A first step is displayed and the following options
+ And A second step with the are displayed and the following by default
+ And A third step with the are displayed and the following drop-down with Select group by default
+ And A fourth step with the by default is displayed
+ And An X button in the top right is displayed
+ Examples:
+ | subtitleFirst | options | subtitleSecond | descriptionsSecond | secondInformation | subtitleThird | descriptionThird | informationThird | subtitleFourth | message |
+ | 'Choose the Operating system' | 'Red Hat / CentOS,Debian / Ubuntu,Windows,MacOS' | 'Wazuh server address' | 'This is the address the agent uses to communicate with the Wazuh server. It can be an IP address or a fully qualified domain name (FQDN).' | '172.19.0.4 ' | 'Assign the agent to a group' | 'Select one or more existing groups' | 'Select group ' | 'Install and enroll the agent' | 'Please select the Operating system.' |
+
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/features/filters/Search-by-parameters.feature b/test/cypress/cypress/integration/features/filters/Search-by-parameters.feature
new file mode 100644
index 0000000000..1e7aaa3d7f
--- /dev/null
+++ b/test/cypress/cypress/integration/features/filters/Search-by-parameters.feature
@@ -0,0 +1,32 @@
+Feature: Search by parameters
+
+ As a Wazuh user
+ I want to pin a filter
+ in order to aplly it across the modules
+ Background:
+ Given The wazuh admin user is logged
+ And The sample data is loaded
+
+ Scenario Outline: Search by parameters with AND
+ When The user goes to
+ And The user types a particular search on the search bar
+ Then The query is accepted and the results should be displayed
+ Examples:
+ | Module Name | key |
+ | Security Events | cluster.name : "wazuh" and rule.level : "3" |
+ | Integrity Monitoring | cluster.name : "wazuh" and agent.id : "001" |
+ | NIST | cluster.name : "wazuh" and agent.name : "Ubuntu" |
+ | TSC | cluster.name : "wazuh" and agent.name : "Ubuntu" |
+ | PCIDSS | cluster.name : "wazuh" and agent.name : "Ubuntu" |
+
+ Scenario Outline: Search by parameters with OR
+ When The user goes to
+ And The user types a particular search on the search bar
+ Then The query is accepted and the results should be displayed
+ Examples:
+ | Module Name | key |
+ | Security Events | cluster.name : "wazuh" or rule.level : "3" |
+ | Integrity Monitoring | cluster.name : "wazuh" or agent.id : "001" |
+ | NIST | cluster.name : "wazuh" or agent.name : "Ubuntu" |
+ | TSC | cluster.name : "wazuh" or agent.name : "Ubuntu" |
+ | PCIDSS | cluster.name : "wazuh" or agent.name : "Ubuntu" |
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/features/filters/add-filter-from-agent-events.feature b/test/cypress/cypress/integration/features/filters/add-filter-from-agent-events.feature
new file mode 100644
index 0000000000..abff130fe1
--- /dev/null
+++ b/test/cypress/cypress/integration/features/filters/add-filter-from-agent-events.feature
@@ -0,0 +1,30 @@
+Feature: Validate that the pinned filter label is displayed - from event page
+
+ As a Wazuh user
+ i want to set a new filter from the agent page
+ in order to manage them
+ Background:
+ Given The wazuh admin user is logged
+ And The user navigates to the agent page
+ And The user navigates to the agent dashboard
+
+ @filter @actions
+ Scenario Outline: The user add and pin filter - Check across the modules - from event page -
+ When The user navigates to agentModule
+ And The user moves to events page
+ And The user adds a new filter
+ And The user pins a filter
+ And The user navigates to the agent page
+ And The user navigates to the agent dashboard
+ And The user navigates to agentModule
+ Then The user checks if the filter is displayed
+ Examples:
+ | Module Name |
+ | Security Events |
+ | Integrity Monitoring |
+ | System Auditing |
+ | Mitre & Attack |
+ | NIST |
+ | TSC |
+ | Policy Monitoring |
+ | PCIDSS |
diff --git a/test/cypress/cypress/integration/features/filters/add-filter-from-agent.feature b/test/cypress/cypress/integration/features/filters/add-filter-from-agent.feature
new file mode 100644
index 0000000000..9b6fe5db54
--- /dev/null
+++ b/test/cypress/cypress/integration/features/filters/add-filter-from-agent.feature
@@ -0,0 +1,29 @@
+Feature: Validate that the pinned filter label is displayed
+
+ As a Wazuh user
+ I want to set a new filter from the agent page
+ in order to manage them
+ Background:
+ Given The wazuh admin user is logged
+ And The user navigates to the agent page
+ And The user navigates to the agent dashboard
+
+ @filter @actions
+ Scenario Outline: The user add and pin filter - Check across the modules
+ When The user navigates to agentModule
+ And The user adds a new filter
+ And The user pins a filter
+ And The user navigates to the agent page
+ And The user navigates to the agent dashboard
+ And The user navigates to agentModule
+ Then The user checks if the filter is displayed
+ Examples:
+ | Module Name |
+ | Security Events |
+ | Integrity Monitoring |
+ | System Auditing |
+ | Mitre & Attack |
+ | NIST |
+ | TSC |
+ | Policy Monitoring |
+ | PCIDSS |
diff --git a/test/cypress/cypress/integration/features/filters/add-new-filter-from-events.feature b/test/cypress/cypress/integration/features/filters/add-new-filter-from-events.feature
new file mode 100644
index 0000000000..a60b83897f
--- /dev/null
+++ b/test/cypress/cypress/integration/features/filters/add-new-filter-from-events.feature
@@ -0,0 +1,27 @@
+Feature: Validate that the added filter label is displayed from the events page
+
+ As a Wazuh user
+ I want to set a new filter
+ in order to manage them
+ Background:
+ Given The wazuh admin user is logged
+
+ @filter @actions
+ Scenario Outline: The user add a new filer from the events page
+ When The user goes to
+ And The user moves to events page
+ And The user adds a new filter
+ And The user checks filter label is added
+ And The user navigates overview page
+ And The user goes to
+ Then The user checks filter label is not added
+ Examples:
+ | Module Name |
+ | Security Events |
+ | Integrity Monitoring |
+ | System Auditing |
+ | Mitre & Attack |
+ | NIST |
+ | TSC |
+ | Policy Monitoring |
+ | PCIDSS |
diff --git a/test/cypress/cypress/integration/features/filters/add-new-filter.feature b/test/cypress/cypress/integration/features/filters/add-new-filter.feature
new file mode 100644
index 0000000000..5c5ea6c364
--- /dev/null
+++ b/test/cypress/cypress/integration/features/filters/add-new-filter.feature
@@ -0,0 +1,26 @@
+Feature: Validate that the added filter label is displayed
+
+ As a Wazuh user
+ I want to set a new filter
+ in order to manage them
+ Background:
+ Given The wazuh admin user is logged
+
+ @filter @actions
+ Scenario Outline: The user add a new filer
+ When The user goes to
+ And The user adds a new filter
+ And The user checks filter label is added
+ And The user navigates overview page
+ And The user goes to
+ Then The user checks filter label is not added
+ Examples:
+ | Module Name |
+ | Security Events |
+ | Integrity Monitoring |
+ | System Auditing |
+ | Mitre & Attack |
+ | NIST |
+ | TSC |
+ | Policy Monitoring |
+ | PCIDSS |
diff --git a/test/cypress/cypress/integration/features/filters/pin-filter-from-dashboard-to-events.feature b/test/cypress/cypress/integration/features/filters/pin-filter-from-dashboard-to-events.feature
new file mode 100644
index 0000000000..43233d9670
--- /dev/null
+++ b/test/cypress/cypress/integration/features/filters/pin-filter-from-dashboard-to-events.feature
@@ -0,0 +1,29 @@
+Feature: Pin filter - from dashboard to event page
+
+ As a Wazuh user
+ I want to pin a filter
+ in order to aplly it across the modules
+ Background:
+ Given The wazuh admin user is logged
+
+ @filter @actions
+ Scenario Outline: The user add and pin new filer - across the modules - from dashboard to event page
+ When The user goes to
+ And The user adds a new filter
+ And The user checks filter label is added
+ And The user pins a filter
+ And The user checks if the filter is displayed
+ And The user navigates overview page
+ And The user goes to
+ And The user moves to events page
+ Then The user checks if the filter is displayed
+ Examples:
+ | Module Name |
+ | Security Events |
+ | Integrity Monitoring |
+ | System Auditing |
+ | Mitre & Attack |
+ | NIST |
+ | TSC |
+ | Policy Monitoring |
+ | PCIDSS |
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/features/filters/pin-filter-from-events-to-events.feature b/test/cypress/cypress/integration/features/filters/pin-filter-from-events-to-events.feature
new file mode 100644
index 0000000000..005886da27
--- /dev/null
+++ b/test/cypress/cypress/integration/features/filters/pin-filter-from-events-to-events.feature
@@ -0,0 +1,31 @@
+Feature: Pin filter - from event page
+
+ As a Wazuh user
+ I want to pin a filter
+ in order to aplly it across the modules
+ Background:
+ Given The wazuh admin user is logged
+
+ @filter @actions
+ Scenario Outline: The user add and pin new filer - across the modules - from event page
+ When The user goes to
+ And The user moves to events page
+ And The user adds a new filter
+ And The user checks filter label is added
+ And The user pins a filter
+ And The user checks if the filter is displayed
+ And The user navigates overview page
+ And The user goes to
+ And The user moves to events page
+ Then The user checks if the filter is displayed
+ Examples:
+ | Module Name |
+ | Security Events |
+ | Integrity Monitoring |
+ | System Auditing |
+ | Mitre & Attack |
+ | NIST |
+ | TSC |
+ | Policy Monitoring |
+ | PCIDSS |
+
diff --git a/test/cypress/cypress/integration/features/filters/pin-filter.feature b/test/cypress/cypress/integration/features/filters/pin-filter.feature
new file mode 100644
index 0000000000..25fcd360b4
--- /dev/null
+++ b/test/cypress/cypress/integration/features/filters/pin-filter.feature
@@ -0,0 +1,29 @@
+Feature: Pin filter - across the modules
+
+ As a Wazuh user
+ I want to pin a filter
+ in order to aplly it across the modules
+ Background:
+ Given The wazuh admin user is logged
+
+ @filter
+ Scenario Outline: The user add and pin new filer - across the modules
+ When The user goes to
+ And The user adds a new filter
+ And The user checks filter label is added
+ And The user pins a filter
+ And The user checks if the filter is displayed
+ And The user navigates overview page
+ And The user goes to
+ Then The user checks if the filter is displayed
+ Examples:
+ | Module Name |
+ | Security Events |
+ | Integrity Monitoring |
+ | System Auditing |
+ | Mitre & Attack |
+ | NIST |
+ | TSC |
+ | Policy Monitoring |
+ | PCIDSS |
+
diff --git a/test/cypress/cypress/integration/features/filters/remove-filter-from-agent-module-dashboard.feature b/test/cypress/cypress/integration/features/filters/remove-filter-from-agent-module-dashboard.feature
new file mode 100644
index 0000000000..ba9b3b1705
--- /dev/null
+++ b/test/cypress/cypress/integration/features/filters/remove-filter-from-agent-module-dashboard.feature
@@ -0,0 +1,27 @@
+Feature: Validate that the added filter label is remove after click remove filter option agent modules Dashboard
+
+ As a Wazuh user
+ I want to remove a selected filter
+ in order to manage them
+ Background:
+ Given The wazuh admin user is logged
+ And The user navigates to the agent page
+ And The user navigates to the agent dashboard
+
+ @filter
+ Scenario Outline: The user remove a filter from Agent - - Dashboard
+ When The user navigates to agentModule
+ And The user adds a new filter
+ And The user checks filter label is added
+ And The user removes the applied filter
+ Then The user checks filter label is not added
+ Examples:
+ | Module Name |
+ | Security Events |
+ | Integrity Monitoring |
+ | System Auditing |
+ | Mitre & Attack |
+ | NIST |
+ | TSC |
+ | Policy Monitoring |
+ | PCIDSS |
diff --git a/test/cypress/cypress/integration/features/filters/remove-filter-from-agent-module-events.feature b/test/cypress/cypress/integration/features/filters/remove-filter-from-agent-module-events.feature
new file mode 100644
index 0000000000..ad6ec3b6cb
--- /dev/null
+++ b/test/cypress/cypress/integration/features/filters/remove-filter-from-agent-module-events.feature
@@ -0,0 +1,28 @@
+Feature: Check that the added filter is removed after click on the removed button - Events
+
+ As a Wazuh user
+ I want to remove a selected filter
+ in order to manage them
+ Background:
+ Given The wazuh admin user is logged
+ And The user navigates to the agent page
+ And The user navigates to the agent dashboard
+
+ @filter
+ Scenario Outline: The user remove a filter from Agent - - Dashboard
+ When The user navigates to agentModule
+ And The user moves to events page
+ And The user adds a new filter
+ And The user checks filter label is added
+ And The user removes the applied filter
+ Then The user checks filter label is not added
+ Examples:
+ | Module Name |
+ | Security Events |
+ | Integrity Monitoring |
+ | System Auditing |
+ | Mitre & Attack |
+ | NIST |
+ | TSC |
+ | Policy Monitoring |
+ | PCIDSS |
diff --git a/test/cypress/cypress/integration/features/filters/remove-filter-from-module-dashboard.feature b/test/cypress/cypress/integration/features/filters/remove-filter-from-module-dashboard.feature
new file mode 100644
index 0000000000..cdd3b2db18
--- /dev/null
+++ b/test/cypress/cypress/integration/features/filters/remove-filter-from-module-dashboard.feature
@@ -0,0 +1,25 @@
+Feature: Validate that the added filter label is remove after click remove filter option modules Dashboard
+
+ As a Wazuh user
+ I want to set a new filter
+ in order to manage them
+ Background:
+ Given The wazuh admin user is logged
+
+ @filter
+ Scenario Outline: The user remove an added filter - Module - Dashboard
+ When The user goes to
+ And The user adds a new filter
+ And The user checks filter label is added
+ And The user removes the applied filter
+ Then The user checks filter label is not added
+ Examples:
+ | Module Name |
+ | Security Events |
+ | Integrity Monitoring |
+ | System Auditing |
+ | Mitre & Attack |
+ | NIST |
+ | TSC |
+ | Policy Monitoring |
+ | PCIDSS |
diff --git a/test/cypress/cypress/integration/features/filters/remove-filter-from-module-events.feature b/test/cypress/cypress/integration/features/filters/remove-filter-from-module-events.feature
new file mode 100644
index 0000000000..d0e34a1643
--- /dev/null
+++ b/test/cypress/cypress/integration/features/filters/remove-filter-from-module-events.feature
@@ -0,0 +1,28 @@
+Feature: Validate that the added filter label is remove after click remove filter option modules Events
+
+ As a Wazuh user
+ I want to set a new filter
+ in order to manage them
+ Background:
+ Given The wazuh admin user is logged
+
+ @filter
+ Scenario Outline: The user remove an added filter - Module - Events
+ When The user goes to
+ And The user moves to events page
+ And The user adds a new filter
+ And The user checks filter label is added
+ And The user removes the applied filter
+ Then The user checks filter label is not added
+ Examples:
+ | Module Name |
+ | Security Events |
+ | Integrity Monitoring |
+ | System Auditing |
+ | Vulnerabilities |
+ | Mitre & Attack |
+ | NIST |
+ | TSC |
+ | Policy Monitoring |
+ | PCIDSS |
+
diff --git a/test/cypress/cypress/integration/features/filters/unpinned-filter-from-agent-dashboard.feature b/test/cypress/cypress/integration/features/filters/unpinned-filter-from-agent-dashboard.feature
new file mode 100644
index 0000000000..08059c7b4a
--- /dev/null
+++ b/test/cypress/cypress/integration/features/filters/unpinned-filter-from-agent-dashboard.feature
@@ -0,0 +1,32 @@
+Feature: Unpinned filter from agent - Dashboard
+
+ As a Wazuh user
+ I want to unpin a selected filter
+ in order to apply it across the modules
+ Background:
+ Given The wazuh admin user is logged
+ And The user navigates to the agent page
+ And The user navigates to the agent dashboard
+
+ @filter @actions
+ Scenario Outline: The user adds a new pin filer and remove it - across the modules - from dashboard
+ When The user navigates to agentModule
+ And The user adds a new filter
+ And The user checks filter label is added
+ And The user pins a filter
+ And The user checks if the filter is displayed
+ And The user unpins the selected filter
+ And The user navigates to the agent page
+ And The user navigates to the agent dashboard
+ And The user navigates to agentModule
+ Then The user checks filter label is not added
+ Examples:
+ | Module Name |
+ | Security Events |
+ | Integrity Monitoring |
+ | System Auditing |
+ | Mitre & Attack |
+ | NIST |
+ | TSC |
+ | Policy Monitoring |
+ | PCIDSS |
diff --git a/test/cypress/cypress/integration/features/management/decoders/create-new-decoder.feature b/test/cypress/cypress/integration/features/management/decoders/create-new-decoder.feature
new file mode 100644
index 0000000000..f156afa70e
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/decoders/create-new-decoder.feature
@@ -0,0 +1,15 @@
+Feature: Should Displayes a message to restart the cluster after saves
+
+ As a wazuh user
+ i want to edit a custom decoder
+ in order to check if the save message it's displayed
+
+@decoders @actions
+ Scenario: Validate creation message is displayed after creating a new decoder
+ Given The wazuh admin user is logged
+ When The user navigates to decoders
+ And The user clicks the new decoders button
+ And The user writes a new decoder
+ And The user saves the decoder
+ Then The save message its displayed
+
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/features/management/decoders/edit-decoders-without-saving.feature b/test/cypress/cypress/integration/features/management/decoders/edit-decoders-without-saving.feature
new file mode 100644
index 0000000000..48f5600c5f
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/decoders/edit-decoders-without-saving.feature
@@ -0,0 +1,16 @@
+Feature: Should Displayes a warning modal - Management - edit decoders
+
+ As a kibana user
+ i want to edit a custom rule
+ in order to check if the warning no saving toast is displayed.
+
+@rules
+ Scenario: Validate confirmation when closing modal without saving - Management - edit decoders
+ Given The wazuh admin user is logged
+ When The user navigates to decoders
+ And The user clicks the custom decoders button
+ And The user selects a custom decoders to edit
+ And The user modify the selected decoders
+ And The user tries to exit edit decoders page without saving data
+ Then The informative modal is displayed
+
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/features/management/decoders/should-list-decoders-and-show-the-pager.feature b/test/cypress/cypress/integration/features/management/decoders/should-list-decoders-and-show-the-pager.feature
new file mode 100644
index 0000000000..62a6f2d2ca
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/decoders/should-list-decoders-and-show-the-pager.feature
@@ -0,0 +1,26 @@
+Feature: Should List Decoders And Show The Pager
+
+ As a wazuh user
+ i want to see the Decoders pages
+ in order to manage them
+
+ @decoder @actions
+ Scenario: Should List Decoders And Show The Pager
+ Given The wazuh admin user is logged
+ When The user navigates to decoders
+ Then The user should see the decoders
+
+ @decoder @actions
+ Scenario: Should List Custom Decoders And Show The Pager
+ Given The wazuh admin user is logged
+ When The user navigates to decoders
+ When The user clicks the custom decoders button
+ Then The user should see the decoders
+
+ @decoder @actions
+ Scenario: Should can edit a decoder
+ Given The wazuh admin user is logged
+ When The user navigates to decoders
+ When The user clicks the custom decoders button
+ When The user presses the edit decoders button and edits it
+ Then The user should see the message
diff --git a/test/cypress/cypress/integration/features/management/groups/edit-groups-without-saving.feature b/test/cypress/cypress/integration/features/management/groups/edit-groups-without-saving.feature
new file mode 100644
index 0000000000..3eb0762735
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/groups/edit-groups-without-saving.feature
@@ -0,0 +1,15 @@
+Feature: Should Displayes a warning modal - Management - edit groups
+
+ As a kibana user
+ i want to edit a custom rule
+ in order to check if the warning no saving toast is displayed.
+
+@rules @actions
+ Scenario: Validate confirmation when closing modal without saving - Management - edit groups
+ Given The wazuh admin user is logged
+ When The user navigates to groups page
+ And The user selects a group to edit
+ And The user modify the selected group
+ And The user tries to exit edit groups page without saving data
+ Then The informative modal is displayed
+
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/features/management/reporting/add-report-from-modules-agent.feature b/test/cypress/cypress/integration/features/management/reporting/add-report-from-modules-agent.feature
new file mode 100644
index 0000000000..7e67906e3e
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/reporting/add-report-from-modules-agent.feature
@@ -0,0 +1,26 @@
+Feature: Generating reports from module and agents
+
+ As a Wazuh user
+ i want to generate a report from modules and agents
+ in order to could access to the report from management/reporting
+Background:
+ Given The wazuh admin user is logged
+ And The sample data is loaded
+@report
+Scenario Outline: Create a report from modules and agents
+ When The user goes to
+ And The user generate a module report clicking on the generate report option
+ And The user choose an agent to apply filter
+ And The user generate a module report clicking on the generate report option
+ And The user navigates to management-reporting
+ Then The agent report is displayed in the table
+ Examples:
+ | Module Name |
+ | Security Events |
+ | Integrity Monitoring |
+ | System Auditing |
+ | Mitre & Attack |
+ | NIST |
+ | TSC |
+ | Policy Monitoring |
+ | PCIDSS |
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/features/management/reporting/add-report-from-modules.feature b/test/cypress/cypress/integration/features/management/reporting/add-report-from-modules.feature
new file mode 100644
index 0000000000..0863a446bf
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/reporting/add-report-from-modules.feature
@@ -0,0 +1,24 @@
+Feature: Generating reports from modules
+
+ As a Wazuh user
+ i want to generate a report
+ in order to could access to the report from management/reporting
+Background:
+ Given The wazuh admin user is logged
+ And The sample data is loaded
+@report
+Scenario Outline: Create a report from modules
+ When The user goes to
+ And The user generate a module report clicking on the generate report option
+ And The user navigates to management-reporting
+ Then The report is displayed in the table
+ Examples:
+ | Module Name |
+ | Security Events |
+ | Integrity Monitoring |
+ | System Auditing |
+ | Mitre & Attack |
+ | NIST |
+ | TSC |
+ | Policy Monitoring |
+ | PCIDSS |
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/features/management/rules/create-a-new-rule.feature b/test/cypress/cypress/integration/features/management/rules/create-a-new-rule.feature
new file mode 100644
index 0000000000..9359da0aaa
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/rules/create-a-new-rule.feature
@@ -0,0 +1,14 @@
+Feature: Should Displayes a message to restart the cluster after saves
+
+ As a wazuh user
+ i want to edit a custom rule
+ in order to check if the saves message its displayed
+
+@rules @actions
+Scenario: Validate creation message is displayed after creating a new rule
+ Given The wazuh admin user is logged
+ When The user navigates to rules
+ And The user clicks the new rules button
+ And The user writes a new rule
+ And The user saves the rule
+ Then The save message its displayed
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/features/management/rules/edit-rules-without-saving.feature b/test/cypress/cypress/integration/features/management/rules/edit-rules-without-saving.feature
new file mode 100644
index 0000000000..a8eddc669c
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/rules/edit-rules-without-saving.feature
@@ -0,0 +1,16 @@
+Feature: Should Displayes a warning modal - Management - edit rules
+
+ As a kibana user
+ i want to edit a custom rule
+ in order to check if the warning no saving toast is displayed.
+
+@rules @actions
+ Scenario: Validate confirmation when closing modal without saving - Management - edit rules
+ Given The wazuh admin user is logged
+ When The user navigates to rules
+ And The user clicks the custom rules button
+ And The user selects a custom rule to edit
+ And The user modify the selected rule
+ And The user tries to exit create rules page without saving data
+ Then The informative modal is displayed
+
diff --git a/test/cypress/cypress/integration/features/management/rules/filter-rules-is-displayed-after-refresh.feature b/test/cypress/cypress/integration/features/management/rules/filter-rules-is-displayed-after-refresh.feature
new file mode 100644
index 0000000000..87c687f802
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/rules/filter-rules-is-displayed-after-refresh.feature
@@ -0,0 +1,16 @@
+Feature: Validate Filter Rule refresh option is working fine
+
+ As a wazuh user
+ i want to see the Rules pages
+ in order to manage them
+
+ @rules
+ Scenario Outline: Filter Rule are displayed after refreshing the page
+ Given The wazuh admin user is logged
+ When The user navigates to rules
+ And The user search a rule by Level
+ And The user clicks the refresh button
+ Then The filtered label is still visible
+ Examples:
+ | condition |
+ | 2 |
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/features/management/rules/refresh-rules-page.feature b/test/cypress/cypress/integration/features/management/rules/refresh-rules-page.feature
new file mode 100644
index 0000000000..95278a8e3d
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/rules/refresh-rules-page.feature
@@ -0,0 +1,12 @@
+Feature: Validate refresh option is working fine
+
+ As a kibana user
+ i want to edit a custom rule
+ in order to check if the warning no saving toast is displayed.
+
+@rules @actions
+Scenario: Rules are displayed after refreshing the page
+Given The wazuh admin user is logged
+When The user navigates to rules
+And The user clicks the refresh button
+Then The user should be able to see the rules page
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/features/management/rules/should-list-rules-and-show-the-pager.feature b/test/cypress/cypress/integration/features/management/rules/should-list-rules-and-show-the-pager.feature
new file mode 100644
index 0000000000..210a950576
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/rules/should-list-rules-and-show-the-pager.feature
@@ -0,0 +1,18 @@
+Feature: Should List Rules And Show The Pager
+
+ As a wazuh user
+ i want to see the Rules pages
+ in order to manage them
+
+ @rules
+ Scenario: Should List Rules And Show The Pager
+ Given The wazuh admin user is logged
+ When The user navigates to rules
+ Then The user should see the rules
+
+ @rules
+ Scenario: Should List Custom Rules And Show The Pager
+ Given The wazuh admin user is logged
+ When The user navigates to rules
+ And The user clicks the custom rules button
+ Then The user should see the rules
diff --git a/test/cypress/cypress/integration/features/management/rules/should-list-rules-by-level.feature b/test/cypress/cypress/integration/features/management/rules/should-list-rules-by-level.feature
new file mode 100644
index 0000000000..1d0b0b7f55
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/rules/should-list-rules-by-level.feature
@@ -0,0 +1,16 @@
+Feature: Should List Rules filtered by Level be shown in the list of rules
+
+ As a wazuh user
+ i want to see the Rules pages
+ in order to manage them
+
+ @rules
+ Scenario Outline: Filter Rule By Level
+ Given The wazuh admin user is logged
+ When The user navigates to rules
+ And The user search a rule by Level
+ Then The filter label is displayed on the filter bar with the correct
+ And The user can see the rules that match with the
+ Examples:
+ | condition |
+ | 2 |
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/features/management/rules/validate-paginator.feature b/test/cypress/cypress/integration/features/management/rules/validate-paginator.feature
new file mode 100644
index 0000000000..0ba153eba3
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/rules/validate-paginator.feature
@@ -0,0 +1,41 @@
+Feature: Validate paginator on Rule page
+
+ As a wazuh user
+ i want to see the Rules pages
+ in order to manage them
+
+ Background: the user navigate to the Rules page
+ Given The wazuh admin user is logged
+ When The user navigates to rules
+ Then The user sees that the rule list is paginated
+
+ @actions
+ Scenario: Rules are displayed when user clicks the first page
+ When The user clicks on the second page button
+ And A new set of rules is displayed
+ And The user clicks on the first page button
+ Then The first page of rules is displayed
+
+ @actions
+ Scenario: Rules are displayed - Select a previous page
+ When The user clicks on the second page button
+ And The rule page is not the first available
+ And The user clicks on the previous page button
+ Then The user should be redirected to the next rule page available
+
+ @actions
+ Scenario: Rules are displayed - Select a next page
+ When The user clicks on the second page button
+ And The rule page is not the last available
+ And The user clicks on the next page button
+ Then The user should be redirected to the next rule page available
+
+ @actions
+ Scenario: Rules are displayed - Last Page
+ When The rule page is the last available page
+ Then The next page button should be disabled
+
+ @actions
+ Scenario: Rules are displayed - First Page
+ When The rule page is the first available page
+ Then The previous page button should be disabled
diff --git a/test/cypress/cypress/integration/features/management/rules/validator-rows-dropdow.feature b/test/cypress/cypress/integration/features/management/rules/validator-rows-dropdow.feature
new file mode 100644
index 0000000000..b4eb818e25
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/rules/validator-rows-dropdow.feature
@@ -0,0 +1,34 @@
+Feature: Validate row dropdown on Rule page
+
+ As a wazuh user
+ I want to see the Rules pages
+ in order to manage them
+
+ Background: the user navigate to the Rules page
+ Given The wazuh admin user is logged
+ When The user navigates to rules
+ And The user see that the rule list is displayed with a limit per rows
+
+ Scenario: Rules are displayed - Select 10 rows
+ When The user click the limit selector for 10 rows
+ Then a maximum of 10 rows of rules are displayed per page
+
+
+ Scenario: Rules are displayed - Select 15 rows
+ When The user click the limit selector for 15 rows
+ Then a maximum of 15 rows of rules are displayed per page
+
+
+ Scenario: Rules are displayed - Select 25 rows
+ When The user click the limit selector for 25 rows
+ Then a maximum of 25 rows of rules are displayed per page
+
+
+ Scenario: Rules are displayed - Select 50 rows
+ When The user click the limit selector for 50 rows
+ Then a maximum of 50 rows of rules are displayed per page
+
+
+ Scenario: Rules are displayed - Select 100 rows
+ When The user click the limit selector for 100 rows
+ Then a maximum of 100 rows of rules are displayed per page
diff --git a/test/cypress/cypress/integration/features/management/settings/about.feature b/test/cypress/cypress/integration/features/management/settings/about.feature
new file mode 100644
index 0000000000..271e5c7efb
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/settings/about.feature
@@ -0,0 +1,11 @@
+Feature: Wazuh version information
+
+ As a wazuh user
+ I want to check the about information
+ in order to see information about the system
+
+ @about @actions
+ Scenario: Check Wazuh version information
+ Given The wazuh admin user is logged
+ When The user navigates to About settings
+ Then The Wazuh information is displayed
diff --git a/test/cypress/cypress/integration/features/management/settings/api-configurations.feature b/test/cypress/cypress/integration/features/management/settings/api-configurations.feature
new file mode 100644
index 0000000000..fe5de4d1cc
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/settings/api-configurations.feature
@@ -0,0 +1,27 @@
+Feature: API configuration instructions and connection validation
+
+ As a wazuh user
+ I want to check API configuration settings
+ in order to see the instructions and test the connection
+
+ @apiConfiguration
+ Scenario: Check API configuration connection
+ Given The wazuh admin user is logged
+ When The user navigates to API configuration settings
+ And The user checks API configuration connection
+ Then The connection success toast is displayed
+
+ @apiConfiguration
+ Scenario: See API configuration instructions
+ Given The wazuh admin user is logged
+ When The user navigates to API configuration settings
+ And The user tries to add new API configuration
+ Then The instructions modal is displayed
+
+ @apiConfiguration
+ Scenario: See API configuration instructions
+ Given The wazuh admin user is logged
+ When The user navigates to API configuration settings
+ And The user tries to add new API configuration
+ And The user tests the API connection from the instructions
+ Then The connection success check box is filled
diff --git a/test/cypress/cypress/integration/features/management/settings/configuration.feature b/test/cypress/cypress/integration/features/management/settings/configuration.feature
new file mode 100644
index 0000000000..037bbc5d07
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/settings/configuration.feature
@@ -0,0 +1,11 @@
+Feature: add Configuration to modules
+
+ As a wazuh user
+ I want to add sample data indices
+ in order to check modules
+
+ @Configuration
+ Scenario: Add configuration data
+ Given The wazuh admin user is logged
+ When The user navigates to Configuration settings
+ Then The app current settings are displayed
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/features/management/settings/disable-modules.feature b/test/cypress/cypress/integration/features/management/settings/disable-modules.feature
new file mode 100644
index 0000000000..2927822bc6
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/settings/disable-modules.feature
@@ -0,0 +1,26 @@
+Feature: disable modules
+
+ As a wazuh user
+ I want to disable different modules
+ in order to see them in the modules directory
+
+ @DisableModules
+ Scenario Outline: Disable modules,
+ Given The wazuh admin user is logged
+ When The user navigates to Modules settings
+ And All modules are activates
+ And The user deactivates the modules with
+ Then The deactivated modules with are not displayed on home page
+ Examples:
+ | Module Name |
+ | Amazon AWS |
+ | Google Cloud Platform |
+ | GitHub |
+ | OpenSCAP |
+ | CIS-CAT |
+ | VirusTotal |
+ | Osquery |
+ | Docker listener |
+ | GDPR |
+ | HIPAA |
+ | TSC |
diff --git a/test/cypress/cypress/integration/features/management/settings/enable-modules.feature b/test/cypress/cypress/integration/features/management/settings/enable-modules.feature
new file mode 100644
index 0000000000..7a59e39068
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/settings/enable-modules.feature
@@ -0,0 +1,26 @@
+Feature: enable modules
+
+ As a wazuh user
+ I want to enable different modules
+ in order to see them in the modules directory
+
+ @EnableModules
+ Scenario Outline: Enable modules,
+ Given The wazuh admin user is logged
+ When The user navigates to Modules settings
+ And All modules are deactivates
+ And The user activates the modules with
+ Then The activated modules with are displayed on home page
+ Examples:
+ | Module Name |
+ | Amazon AWS |
+ | Google Cloud Platform |
+ | GitHub |
+ | OpenSCAP |
+ | CIS-CAT |
+ | VirusTotal |
+ | Osquery |
+ | Docker listener |
+ | GDPR |
+ | HIPAA |
+ | TSC |
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/features/management/settings/logs.feature b/test/cypress/cypress/integration/features/management/settings/logs.feature
new file mode 100644
index 0000000000..e7c187c843
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/settings/logs.feature
@@ -0,0 +1,19 @@
+Feature: Read Kibana logs
+
+ As a wazuh user
+ I want to check the app logs
+ in order to see information about the app logging
+
+ @logs
+ Scenario: Check Kibana logs
+ Given The wazuh admin user is logged
+ When The user navigates to Logs settings
+ Then The Logs are displayed
+
+ @logs
+ Scenario: Reload Kibana logs
+ Given The wazuh admin user is logged
+ When The user navigates to Logs settings
+ And The user reloads the logs
+ Then The Logs are displayed
+ And The backend response indicates that the logs are reloaded
diff --git a/test/cypress/cypress/integration/features/management/settings/miscellaneous.feature b/test/cypress/cypress/integration/features/management/settings/miscellaneous.feature
new file mode 100644
index 0000000000..0d97eb90e4
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/settings/miscellaneous.feature
@@ -0,0 +1,12 @@
+Feature: Run health checks
+
+ As a wazuh user
+ I want to run the health check
+ in order to validate everything is connected
+
+ @miscellaneous @actions
+ Scenario: Run health check
+ Given The wazuh admin user is logged
+ When The user navigates to Miscellaneous settings
+ And The user runs the health checks
+ Then The application navigates to the health checks page
diff --git a/test/cypress/cypress/integration/features/management/settings/sample-data.feature b/test/cypress/cypress/integration/features/management/settings/sample-data.feature
new file mode 100644
index 0000000000..fb5847fde9
--- /dev/null
+++ b/test/cypress/cypress/integration/features/management/settings/sample-data.feature
@@ -0,0 +1,27 @@
+Feature: Add/Delete Sample data to modules
+
+ As a wazuh user
+ I want to add sample data indices
+ in order to check modules
+
+ @sampleData @actions
+ Scenario: Add all sample data
+ Given The wazuh admin user is logged
+ When The user navigates to Sample data settings
+ And All buttons have add status
+ And The user adds sample data for
+ | security information |
+ | auditing and policy monitoring |
+ | threat detection and response |
+ Then The add data success toasts are displayed
+
+ @sampleData @actions
+ Scenario: Delete all sample data
+ Given The wazuh admin user is logged
+ When The user navigates to Sample data settings
+ And All buttons have remove status
+ And The user removes sample data for
+ | security information |
+ | auditing and policy monitoring |
+ | threat detection and response |
+ Then The remove data success toasts are displayed
diff --git a/test/cypress/cypress/integration/pageobjects/basic/agents/agents.page.js b/test/cypress/cypress/integration/pageobjects/basic/agents/agents.page.js
new file mode 100644
index 0000000000..f91a9c3d3a
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/agents/agents.page.js
@@ -0,0 +1,24 @@
+export const AGENTS_PAGE = {
+ firstAgentList: '[data-test-subj="row-001"]',
+ agSecurityEventsLink: '.WzManagementSideMenu [title="Security events"] div div',
+ agIntegrityMonitoringLink: '.WzManagementSideMenu [title="Integrity monitoring"] div div',
+ agSCALink: '.euiFlexItem.wz-module-header-agent-title > div > div:nth-child(4) button',
+ agSystemAuditingLink: '.WzManagementSideMenu [title="System Auditing"] div div',
+ agVulnerabilitiesLink: '.WzManagementSideMenu [title="Vulnerabilities"] div div',
+ agMitreAttackLink: '.WzManagementSideMenu [title="MITRE ATT&CK"] div div',
+ moreLink: '//*[contains(@class,"wz-module-header-agent-main")]//*/button//*/span[contains(text(),"More")]',
+ agPolicyMonitoring: '.WzManagementSideMenu [title="Policy Monitoring"] div div',
+ agPCIDSS: '.WzManagementSideMenu [title="PCI DSS"] div div',
+ agGDPR: '.WzManagementSideMenu [title="GDPR"] div div',
+ agHIPAA: '.WzManagementSideMenu [title="HIPAA"] div div',
+ agNIST: '.WzManagementSideMenu [title="NIST 800-53"] div div',
+ agTSC: '.WzManagementSideMenu [title="TSC"] div div',
+ statusChart: '.agents-status-pie > .euiPanel > .euiCard__content > .euiCard__children > .euiFlexGroup',
+ agentDetails: 'euiFlexItem euiFlexItem--flexGrowZero agents-details-card',
+ deployNewAgentButton: '//span[contains(text(),"Deploy new agent")]',
+ exploreAgentButton: '.wz-module-header-nav .euiFlexItem .euiToolTipAnchor .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Explore agent")',
+ firstAgentDisplayed: '.euiModal .euiTable .euiTableRow:nth-child(1)',
+ unPinnedAgentButton: '.wz-module-header-nav .euiFlexItem .euiToolTipAnchor .euiButtonIcon[aria-label="Unpin agent"]',
+ secundAgentDisplayed: '.euiModal .euiTable .euiTableRow:nth-child(2)',
+ agentID: '.euiModal .euiTable .euiTableRow:nth-child(1) .euiTableRowCell:nth-child(1) .euiTableCellContent__text',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/basic/agents/deploy-new-agent.page.js b/test/cypress/cypress/integration/pageobjects/basic/agents/deploy-new-agent.page.js
new file mode 100644
index 0000000000..664efa81cc
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/agents/deploy-new-agent.page.js
@@ -0,0 +1,35 @@
+export const DEPLOY_NEW_AGENT_PAGE = {
+ closeButton: "//span[contains(text(),'Close')]",
+ title: "[name='RegisterAgent'] h2",
+ deployNewAgentSections: "[name='RegisterAgent'] .euiStep",
+
+ operatingSystemSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(1) p",
+ redhatButton: '[data-text="Red Hat / CentOS"]',
+ debianUbuntuButton: '[data-text="Debian / Ubuntu"]',
+ windowsButton: '[data-text="Windows"]',
+ macOSButton: '[data-text="MacOS"]',
+
+ operationSystemTitle: "[name='RegisterAgent'] .euiStep:nth-child(1) .euiTitle",
+ operationSystemOption: "[name='RegisterAgent'] .euiStep:nth-child(1) fieldset label",
+
+ serverAddressSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(2) :nth-child(1) p.euiStep__title",
+ serverMessage: "[name='RegisterAgent'] .euiStep:nth-child(2) .euiStep__content p",
+ serverInputField: "[name='RegisterAgent'] .euiStep:nth-child(2) [placeholder='Server address']",
+
+ agentToGroupSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(3) .euiTitle",
+ agentToGroupMessage: "//*[@name='RegisterAgent']//*[3][contains(@class,'euiStep')]//*[contains(@class,'euiText')]/p", //cambiar a xpath
+ agentToGroupSelector: "[name='RegisterAgent'] .euiStep:nth-child(3) [data-test-subj='comboBoxInput']",
+
+ installAndEnrollAgentSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(4) .euiTitle",
+ installAndEnrollAgentDefaultLabel: "[name='RegisterAgent'] .euiStep:nth-child(4) .euiCallOutHeader__title",
+ // after selected these OS options
+ installAndEnrollAgentCommand: "[name='RegisterAgent'] .euiStep:nth-child(5) .euiCodeBlock__line",
+ installAndEnrollAgentCopyButton: "[name='RegisterAgent'] .euiStep:nth-child(5) .copy-codeblock-wrapper .copy-overlay",
+
+ startTheAgentTitle: "[name='RegisterAgent'] .euiStep:nth-child(6) p",
+ startTheAgentTabsLabels: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content .euiTabs button",
+ systemmdTabButton: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content .euiTabs button:nth-child(1)",
+ sysVTabButton: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content .euiTabs button:nth-child(2)",
+ startTheAgentCommandText: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content [role='tabpanel'] .euiText pre",
+ startTheAgentcopyButton: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content [role='tabpanel'] .euiText .copy-overlay",
+};
diff --git a/test/cypress/cypress/integration/pageobjects/basic/filters/filters.page.js b/test/cypress/cypress/integration/pageobjects/basic/filters/filters.page.js
new file mode 100644
index 0000000000..186eed7c86
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/filters/filters.page.js
@@ -0,0 +1,14 @@
+export const FILTERS_PAGE = {
+ addFilterButton: '[data-test-subj="addFilter"]',
+ filterSuggestionList: '[data-test-subj="filterFieldSuggestionList"]',
+ filterOperatorList: '[data-test-subj="filterOperatorList"] [data-test-subj="comboBoxToggleListButton"]',
+ filterParams: '[data-test-subj="filterParams"]',
+ saveFilterButton: '[data-test-subj="saveFilter"]',
+ stablishedFilter: '[data-test-subj="filter filter-enabled filter-key-rule.level filter-value-7 filter-unpinned"',
+ pinFilterAction: '[data-test-subj="pinFilter"]',
+ selectedOperator: '.euiFilterSelectItem[title="is"]',
+ pinnedFilter: '[data-test-subj="filter filter-enabled filter-key-rule.level filter-value-7 filter-pinned"]',
+ eventsButton: '//*[contains(@class,"euiTabs")]//*[contains(text(),"Events")]',
+ removeFilterButton: '//*[contains(@class,"euiContextMenuPanel")]//*[contains(text(),"Delete")]',
+ operatorList: '.euiPanel[data-test-subj="comboBoxOptionsList filterOperatorList-optionsList"] .euiComboBoxOptionsList__rowWrap'
+};
diff --git a/test/cypress/cypress/integration/pageobjects/basic/modules-directory.page.js b/test/cypress/cypress/integration/pageobjects/basic/modules-directory.page.js
new file mode 100644
index 0000000000..cfd9ee32a9
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/modules-directory.page.js
@@ -0,0 +1,14 @@
+export const MODULES_DIRECTORY_PAGE = {
+ amazonAWSCard: '[data-test-subj="overviewWelcomeAws"]',
+ gCPCard: '[data-test-subj="overviewWelcomeGcp"]',
+ openSCAPCard: '[data-test-subj="overviewWelcomeOscap"]',
+ cisCatCard: '[data-test-subj="overviewWelcomeCiscat"]',
+ virusTotalCard: '[data-test-subj="overviewWelcomeVirustotal"]',
+ osqueryCard: '[data-test-subj="overviewWelcomeOsquery"]',
+ dockerListenerCard: '[data-test-subj="overviewWelcomeDocker"]',
+ gDPRCard: '[data-test-subj="overviewWelcomeGdpr"]',
+ hIPAACard: '[data-test-subj="overviewWelcomeHipaa"]',
+ tSCCard: '[data-test-subj="overviewWelcomeTsc"]',
+ gitHubCard: '[data-test-subj="overviewWelcomeGithub"]',
+ userLoginCard: '[data-test-subj="userMenuAvatar"]',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/basic/overview/overview.page.js b/test/cypress/cypress/integration/pageobjects/basic/overview/overview.page.js
new file mode 100644
index 0000000000..b3fbf7b52f
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/overview/overview.page.js
@@ -0,0 +1,14 @@
+export const OVERVIEW_PAGE = {
+ securityEvents: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Security events")]',
+ integrityMonitoring: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Integrity monitoring")]',
+ policyMonitoring: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Policy monitoring")]',
+ systemAuditing: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"System auditing")]',
+ securityInformationAssessment: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Security configuration assessment")]',
+ vulnerabilities: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Vulnerabilities")]',
+ mitre: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"MITRE ATT&CK")]',
+ pciDSS: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"PCI DSS")]',
+ nist: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"NIST")]',
+ tsc: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"TSC")]',
+ gdpr: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"GDPR")]',
+ hipaa: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"HIPAA")]',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/basic/reporting/report.page.js b/test/cypress/cypress/integration/pageobjects/basic/reporting/report.page.js
new file mode 100644
index 0000000000..cc697415fd
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/reporting/report.page.js
@@ -0,0 +1,6 @@
+export const REPORTING_PAGE = {
+ generateReportButton: '.wz-welcome-page-agent-tabs .euiFlexItem .euiFlexItem .euiButtonEmpty[type="button"] .euiButtonEmpty__text:contains("Generate report")',
+ reportGeneratedToast: '.euiToast',
+ lastCreatedReport: '.euiTable .euiTableRow:nth-child(1) .euiTableRowCell .euiTableCellContent .euiTableCellContent__text',
+ disableGenerateReportButton: '.wz-welcome-page-agent-tabs .euiFlexItem .euiToolTipAnchor button.euiButtonEmpty-isDisabled',
+};
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/pageobjects/basic/settings/about.page.js b/test/cypress/cypress/integration/pageobjects/basic/settings/about.page.js
new file mode 100644
index 0000000000..4e851f055a
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/settings/about.page.js
@@ -0,0 +1,19 @@
+export const ABOUT_PAGE = {
+ appVersionTitle: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(1)',
+ appVersionNumber: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(1) > span',
+
+ appRevisionTitle: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(2)',
+ appRevisionNumber: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(2) > span',
+
+ installDateTitle: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(3)',
+ installDateInformation: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(3) > span',
+
+ welcomingCard: 'div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(1) > div',
+ welcomingCardTitle: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(1) > div h2.euiTitle',
+
+ communityCard: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div',
+ communityCardTitle: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div h2.euiTitle',
+ communitySlackLink: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div :nth-child(1) .euiButtonIcon',
+ communityGoogleGroupLink: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div :nth-child(2) .euiButtonIcon',
+ communityGithubLink: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div :nth-child(3) .euiButtonIcon',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/basic/settings/api-configuration.page.js b/test/cypress/cypress/integration/pageobjects/basic/settings/api-configuration.page.js
new file mode 100644
index 0000000000..9dd489442f
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/settings/api-configuration.page.js
@@ -0,0 +1,10 @@
+export const API_CONFIGURATION_PAGE = {
+ checkConnectionButton: 'div:nth-child(2) > span > button',
+ connectionSuccessToast: '.euiToast--success',
+ addNewConnectionButton: 'react-component > div > div > div:nth-child(1) > div:nth-child(2) > button > span',
+ addNewConnectionModal: 'react-component > div > div.euiFlexItem.min-guide-width > div',
+ addNewConnectionModalTitle: 'div.euiFlexGroup--responsive > div:nth-child(1) > div > h2',
+ newConnectionModalCheckConnectionButton: 'div.euiStep__content > div > button.euiButton > span > span',
+ testConnectionCheckBox: 'div:nth-child(2) > div.euiStep__titleWrapper > p',
+ testConnectionCheckBoxMarked: 'div:nth-child(2) > div.euiStep__titleWrapper .euiStep__circle > svg',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/basic/settings/configuration.page.js b/test/cypress/cypress/integration/pageobjects/basic/settings/configuration.page.js
new file mode 100644
index 0000000000..56efbbddc6
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/settings/configuration.page.js
@@ -0,0 +1,197 @@
+export const CONFIGURATION_PAGE = {
+ settingTitle: 'div > h2.euiTitle',
+ settingToolTip: 'div > h2.euiTitle > .euiToolTipAnchor',
+ settingSubTitle: '.euiPage .euiFlexItem:nth-child(1) .euiFlexItem:nth-child(2) .euiText.euiText--medium',
+ settingSearchBox: '.euiPage .euiFlexItem:nth-child(1) .euiFlexItem:nth-child(2).euiSearchBar__searchHolder',
+ settingCategoriesButton: '.euiPage header .euiFlexItem .euiFilterGroup',
+ settingCategotiesPanel: '.euiPageBody .euiPanel',
+
+ //General Panel
+ //General Panel
+ generalPanelTitle: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel h2',
+
+ generalPanelIndexPatternName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ generalPanelIndexPatternDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelIndexPatternLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelIndexPatternField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelRequestTimeoutName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ generalPanelRequestTimeoutDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelRequestLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelRequestField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelIpSelectorName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ generalPanelIpSelectorDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelIpSelectorLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelIpSelectorField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ generalPanelIpIgnoreName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ generalPanelIpIgnoreDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelIpIgnoreLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelIpIgnoreField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper',
+
+ generalPanelCronPrefixName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ generalPanelCronPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelCronLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelCronField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelSamplePrefixName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ generalPanelSamplePrefixDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelSampleLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelSampleField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelManagerAlertsPrefixName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) span',
+ generalPanelManagerAlertsPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelManagerAlertsLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelManagerAlertsField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ generalPanelLogLevelName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) span',
+ generalPanelLogLevelDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelLogLevelLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelLogLevelField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper select',
+
+ generalPanelEnrollmentName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(1) span',
+ generalPanelEnrollmentDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelEnrollmentLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelEnrollmentField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ //Health Check Panel
+ //Health Check Panel
+ healthCheckPanelTitle: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel h2',
+ healthCheckPanelIndexPatternPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelIndexPatternPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelIndexPatterLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelIndexPatterField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelIndexTemplatePrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelIndexTemplatePrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelIndexTemplateLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelIndexTemplateField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelApiConnectionPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelApiConnectionPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelApiConnectionLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelApiConnectionField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelApiVersionPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelApiVersionPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelApiVersionLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelApiVersionField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelKnowFieldsPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelKnowFieldsPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelKnowFieldsLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelKnowFieldsField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelRemoveMetaFieldsPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelRemoveMetaFieldsPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelRemoveMetaFieldsPrefixLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelRemoveMetaFieldsPrefixField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelSetBucketPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelSetBucketPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelSetBucketLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelSetBucketField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelSetTimePrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelSetTimePrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelSetTimeLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelSetTimeField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ //Monitoring Panel
+ //Monitoring Panel
+ monitoringPanelTitle: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel h2',
+
+ monitoringPanelStatusName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ monitoringPanelStatusDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelStatusPatterLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelStatusPatterField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ monitoringPanelFrequencyName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ monitoringPanelFrequencyDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelFrequencyLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelFrequencyField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ monitoringPanelIndexShardsName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexShardsDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelIndexShardsLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexShardsField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ monitoringPanelIndexReplicasName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexReplicasDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelPanelIndexReplicasLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexReplicasField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ monitoringPanelIndexCreationName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexCreationDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelIndexCreationLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexCreationField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper select',
+
+ monitoringPanelIndexPatternName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexPatternDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelIndexPatternLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexPatternField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ //Statistics Panel
+ //Statistics Panel
+ statisticsPanelTitle: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel h2',
+
+ StatisticsPanelStatusName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelStatusDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelStatusPatterLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelStatusPatterField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ StatisticsPanelIncludesApisName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIncludesApisDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIncludesApisLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIncludesApisField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper',
+
+ StatisticsPanelIndexIntervalName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexIntervalDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexIntervalLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexIntervalField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ StatisticsPanelIndexNameName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexNameDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexNameLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexNameField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ StatisticsPanelIndexCreationName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexCreationDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexCreationLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexCreationField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper select',
+
+ StatisticsPanelIndexShardsName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexShardsDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexShardsLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexShardsField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ StatisticsPanelIndexReplicasName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexReplicasDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexReplicasLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexReplicasField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ //Logo Customization Panel
+ //Logo Customization Panel
+ logoPanelTitle: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel h2',
+
+ LogosCustomizationPanelLogoAppName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogoAppDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogoAppPatterLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogoAppPatterField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ LogosCustomizationPanelLogosSidebarName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogosSidebarDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogosSidebarLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogosSidebarField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ LogosCustomizationPanelLogoHealthCheckName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogoHealthCheckDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogoHealthCheckLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogoHealthCheckField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ LogosCustomizationPanelLogoReportName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogoReportDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogoReportLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogoReportField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/basic/settings/logs.page.js b/test/cypress/cypress/integration/pageobjects/basic/settings/logs.page.js
new file mode 100644
index 0000000000..8fb85d0bdd
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/settings/logs.page.js
@@ -0,0 +1,6 @@
+export const LOGS_PAGE = {
+ logsTitle: 'div > .euiTitle',
+ logsContainer: 'div > .euiCodeBlock',
+ reloadLogsLink: 'div.euiFlexItem > button > span > span',
+ logsTitleText: 'App log messages',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/basic/settings/miscellaneous.page.js b/test/cypress/cypress/integration/pageobjects/basic/settings/miscellaneous.page.js
new file mode 100644
index 0000000000..7edd153931
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/settings/miscellaneous.page.js
@@ -0,0 +1,5 @@
+export const MISCELLANEOUS_PAGE = {
+ runHealthChecksButton: 'div.euiFlexItem > div > div > button.euiButton',
+ healthCheckContainer: 'div.health-check',
+ successCheckIconList: 'p > span.euiToolTipAnchor > svg.euiIcon',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/basic/settings/modules.page.js b/test/cypress/cypress/integration/pageobjects/basic/settings/modules.page.js
new file mode 100644
index 0000000000..2628f3faaa
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/settings/modules.page.js
@@ -0,0 +1,13 @@
+export const MODULES_PAGE = {
+ amazonAWSToggleButton: ':nth-child(1) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ gCPToggleButton: ':nth-child(1) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ gitHubCardToggleButton: ':nth-child(1) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(6) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ openSCAPToggleButton: ':nth-child(2) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ cisCatToggleButton: ':nth-child(2) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ virusTotalToggleButton: ':nth-child(3) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(3) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ osqueryToggleButton: ':nth-child(3) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ dockerListenerToggleButton: ':nth-child(3) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ gDPRToggleButton: ':nth-child(4) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(3) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ hIPAAToggleButton: ':nth-child(4) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ tSCToggleButton: ':nth-child(4) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/basic/settings/sample-data.page.js b/test/cypress/cypress/integration/pageobjects/basic/settings/sample-data.page.js
new file mode 100644
index 0000000000..95d2e86ef3
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/settings/sample-data.page.js
@@ -0,0 +1,9 @@
+export const SAMPLE_DATA_PAGE = {
+ addSecurityInformationDataButton: 'div:nth-child(1) > div > div.euiCard__footer > div > div > button',
+ securityInformationDataTitle:'div:nth-child(1) > div > div.euiCard__content span',
+ addAuditingAndPolicyMonitoringDataButton: 'div:nth-child(2) > div > div.euiCard__footer > div > div > button',
+ auditingAndPolicyMonitoringDataTitle: 'div:nth-child(2) > div > div.euiCard__content span',
+ addThreatDetectionAndResponseDataButton: 'div:nth-child(3) > div > div.euiCard__footer > div > div > button',
+ threatDetectionAndResponseDataTitle: 'div:nth-child(3) > div > div.euiCard__content span',
+ dataAddedSuccessfullyToast: '.euiCard__betaBadgeWrapper',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/basic/wazuh-menu/decoders.page.js b/test/cypress/cypress/integration/pageobjects/basic/wazuh-menu/decoders.page.js
new file mode 100644
index 0000000000..58c08f9a6c
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/wazuh-menu/decoders.page.js
@@ -0,0 +1,20 @@
+export const DECODERS_PAGE = {
+ titleSelector: '[class="euiTitle euiTitle--medium"]',
+ tableSelector: '[class="euiTableRow customRowClass euiTableRow-isClickable"]',
+ dropdownPaginationSelector: '[data-test-subj="tablePaginationPopoverButton"]',
+ listPages: 'nav[class="euiPagination"]',
+ customDecodersButtonSelector: '[data-test-subj="Custom decoders"]',
+ manageDecodersFilesButtonSelector: '.euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Manage decoders")',
+ editDecoderButtonSelector: 'tr.euiTableRow:nth-child(1) .euiToolTipAnchor .euiButtonIcon[aria-label="Edit content"]',
+ saveDecoderButtonSelector: '.euiFlexGroup .euiFlexItem button.euiButton span.euiButtonContent span.euiButton__text:contains("Save")',
+ messageConfirmSaveSelector: '.euiText > span',
+ buttonRestartSelector: '.euiCallOut.euiCallOut--primary .euiButton.euiButton--primary',
+ firstCustomDecoder: '[data-test-subj="row-local_decoder_example"]',
+ xmlDecoderFile:':nth-child(4) .euiTableCellContent .euiToolTipAnchor .euiLink',
+ codeEditorSelector: '[data-test-subj="codeEditorContainer"]',
+ backButtonSelector: '.euiFlexGroup .euiFlexItem .euiToolTipAnchor .euiButtonIcon',
+ confirmModalSelector: '[data-test-subj="confirmModalTitleText"]',
+ createNewDecoderSelector:'.euiFlexGroup .euiFlexItem .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Add new decoders file")',
+ decoderTitleSelector: '.euiFlexItem .euiFlexGroup .euiFormControlLayout input.euiFieldText',
+ saveDecoderMessage: '.euiText span:contains("Changes will not take effect until a restart is performed.")'
+};
diff --git a/test/cypress/cypress/integration/pageobjects/basic/wazuh-menu/groups-page.js b/test/cypress/cypress/integration/pageobjects/basic/wazuh-menu/groups-page.js
new file mode 100644
index 0000000000..8b56b67a9a
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/wazuh-menu/groups-page.js
@@ -0,0 +1,6 @@
+export const GROUPS_PAGE = {
+ editGroups:'.euiBasicTable .euiTable--responsive :nth-child(4) .euiTableCellContent :nth-child(2)',
+ codeEditorSelector: '[data-test-subj="codeEditorContainer"]',
+ backButtonSelector: '.euiFlexGroup .euiFlexItem .euiToolTipAnchor .euiButtonIcon',
+ confirmModalSelector: '[data-test-subj="confirmModalTitleText"]'
+};
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/pageobjects/basic/wazuh-menu/rules.page.js b/test/cypress/cypress/integration/pageobjects/basic/wazuh-menu/rules.page.js
new file mode 100644
index 0000000000..c2f08d2adc
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/wazuh-menu/rules.page.js
@@ -0,0 +1,36 @@
+export const RULES_PAGE = {
+ rulesButtonSelector: '[class="euiSideNavItem euiSideNavItem--trunk"]',
+ titleSelector: '[class="euiTitle euiTitle--medium"]',
+ tableSelector: '[class="euiTableRow customRowClass euiTableRow-isClickable"]',
+ dropdownPaginationSelector: '[data-test-subj="tablePaginationPopoverButton"]',
+ listPagesSelector: 'nav[class="euiPagination"]',
+ customRulesButtonSelector: '.euiButtonGroupButton.euiButtonGroupButton--text',
+ firstCustomRule: '[data-test-subj="row-100001"]',
+ xmlRuleFile:'.euiBasicTable .euiTable :nth-child(6) :nth-child(2) .euiToolTipAnchor .euiLink:contains("local_rules.xml")',
+ codeEditorSelector: '[data-test-subj="codeEditorContainer"]',
+ backButtonSelector: '.euiFlexGroup .euiFlexItem .euiToolTipAnchor .euiButtonIcon',
+ confirmModalSelector: '[data-test-subj="confirmModalTitleText"]',
+ createNewRulesSelector: '.euiFlexGroup .euiFlexItem .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Add new rules file")',
+ rulesTitleSelector:'.euiFlexItem .euiFlexGroup .euiFormControlLayout input.euiFieldText',
+ saveRulesButtonSelector: '.euiFlexGroup .euiFlexItem button.euiButton span.euiButtonContent span.euiButton__text:contains("Save")',
+ saveRulesMessage: '.euiText span:contains("Changes will not take effect until a restart is performed.")',
+ refreshButtonSelector: '.euiFlexGroup .euiFlexItem .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Refresh")',
+ rulestableSelector: '[name="WzManagement"] table tr',
+ rulesRowTableSelector: '[name="WzManagement"] tbody tr',
+ buttonListPageSelector: '[name="WzManagement"] button > span',
+ rulesFilterSelector: '.euiSuggestInput [placeholder="Filter or search"]',
+ dropdownFilterSelector: '.euiPanel.euiPopover__panel.euiPopover__panel--bottom',
+ filterLevelSelector: 'button:contains("level")',
+ filterNumberSelector: 'button:nth-child(0)',
+ filterLabelSelector: '.euiPopover.euiPopover--anchorDownLeft [data-testid="wz-search-badge-0"]',
+ paginatorSelector: '.euiBasicTable .euiPagination',
+ paginatorPreviousSelector: '[data-test-subj="pagination-button-previous"]',
+ paginatorNextSelector: '[data-test-subj="pagination-button-next"]',
+ paginatorFirstSelector: '.euiBasicTable .euiPagination li.euiPagination__item:first-child',
+ paginatorSecondSelector: '.euiBasicTable .euiPagination li.euiPagination__item:nth-child(2)',
+ paginatorthirdSelector: '.euiBasicTable .euiPagination li.euiPagination__item:nth-child(3)',
+ paginatorFourthSelector: '.euiBasicTable .euiPagination li.euiPagination__item:nth-child(4)',
+ paginatorLastSelector: '.euiBasicTable .euiPagination li.euiPagination__item:last-child',
+};
+
+
diff --git a/test/cypress/cypress/integration/pageobjects/basic/wazuh-menu/wazuh-menu.page.js b/test/cypress/cypress/integration/pageobjects/basic/wazuh-menu/wazuh-menu.page.js
new file mode 100644
index 0000000000..1f8d860b2c
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/basic/wazuh-menu/wazuh-menu.page.js
@@ -0,0 +1,81 @@
+export const WAZUH_MENU_PAGE = {
+ wazuhMenuLeft: '.wz-menu-left-side .wz-menu-sections',
+ wazuhMenuRight: '.wz-menu-right-side',
+ wazuhMenuSettingRight: '.wz-menu-right-side .WzManagementSideMenu',
+ wazuhMenuButton: '[data-test-subj=menuWazuhButton]',
+ //region Menu
+ //region Menu
+ modulesButton: '[data-test-subj=menuModulesButton]',
+ managementButton: '[data-test-subj=menuManagementButton]',
+ agentsButton: '[data-test-subj=menuAgentsButton]',
+ toolsButton: '[data-test-subj=menuToolsButton]',
+ securityButton: '[data-test-subj=menuSecurityButton]',
+ settingsButton: '[data-test-subj=menuSettingsButton]',
+ //endregion Menu
+ //region SubMenu
+ //region Modules
+ //endregion Menu
+ //region SubMenu
+ //region Modules
+ modulesDirectoryLink: '.wz-menu-right-side div.euiFlexGroup > div > button > span > span',
+ securityEventsLink: '[data-test-subj=menuModulesSecurityEventsLink]',
+ integrityMonitoringLink: '[data-test-subj=menuModulesFimLink]',
+ amazonAwsLink: '[data-test-subj=menuModulesAwsLink]',
+ googleCloudPlatformLink: '[data-test-subj=menuModulesGcpLink]',
+ policyMonitoringLink: '[data-test-subj=menuModulesPolicyMonitoringLink]',
+ systemAuditingLink: '[data-test-subj=menuModulesAuditLink]',
+ openScapLink: '[data-test-subj=menuModulesOpenScapLink]',
+ cisCatLink: '[data-test-subj=menuModulesCiscatLink]',
+ securityConfigurationAssessmentLink: '[data-test-subj=menuModulesScaLink]',
+ vulnerabilitiesLink: '[data-test-subj=menuModulesVulsLink]',
+ virusTotalLink: '[data-test-subj=menuModulesVirustotalLink]',
+ osqueryLink: '[data-test-subj=menuModulesOsqueryLink]',
+ dockerListenerLink: '[data-test-subj=menuModulesDockerLink]',
+ mitreAttackLink: '[data-test-subj=menuModulesMitreLink]',
+ pciDssLink: '[data-test-subj=menuModulesPciLink]',
+ gdprLink: '[data-test-subj=menuModulesGdprLink]',
+ hipaaLink: '[data-test-subj=menuModulesHipaaLink]',
+ nistLink: '[data-test-subj=menuModulesNistLink]',
+ tscLink: '[data-test-subj=menuModulesTscLink]',
+ //endregion
+ //region Management
+ //endregion
+ //region Management
+ rulesLink: '[data-test-subj=menuManagementRulesLink]',
+ decodersLink: '[data-test-subj=menuManagementDecodersLink]',
+ cdbListLink: '[data-test-subj=menuManagementCdbListsLink]',
+ groupsLink: '[data-test-subj=menuManagementGroupsLink]',
+ configurationLink: '[data-test-subj=menuManagementConfigurationLink]',
+ statusLink: '[data-test-subj=menuManagementStatusLink]',
+ clusterLink: '[data-test-subj=menuManagementMonitoringLink]',
+ statisticsLink: '[data-test-subj=menuManagementStatisticsLink]',
+ logsLink: '[data-test-subj=menuManagementLogsLink]',
+ reportingLink: '[data-test-subj=menuManagementReportingLink]',
+ //endregion
+ //region Tools
+ //endregion
+ //region Tools
+ apiConsoleLink: '[data-test-subj=menuToolsDevToolsLink]',
+ rulesetTestLink: '[data-test-subj=menuToolsLogtestLink]',
+ //endregion
+ //region Security
+ //endregion
+ //region Security
+ usersLink: '[data-test-subj=menuSecurityUsersLink]',
+ rolesLink: '[data-test-subj=menuSecurityRolesLink]',
+ policiesLink: '[data-test-subj=menuSecurityPoliciesLink]',
+ rolesMappingLink: '[data-test-subj=menuSecurityRoleMappingLink]',
+ //endregion
+ //region Settings
+ //endregion
+ //region Settings
+ settingsApiConfigurationLink: '[data-test-subj=menuSettingsApiLink]',
+ settingsModulesLink: '[data-test-subj=menuSettingsModulesLink]',
+ settingsSampleDataLink: '[data-test-subj=menuSettingsSampleDataLink]',
+ settingsConfigurationLink: '[data-test-subj=menuSettingsConfigurationLink]',
+ settingsLogsLink: '[data-test-subj=menuSettingsLogsLink]',
+ settingsMiscellaneousLink: '[data-test-subj=menuSettingsMiscellaneousLink]',
+ settingsAboutLink: '[data-test-subj=menuSettingsAboutLink]',
+ //endregion
+ //endregion
+};
diff --git a/test/cypress/cypress/integration/pageobjects/login/odef-login.page.js b/test/cypress/cypress/integration/pageobjects/login/odef-login.page.js
new file mode 100644
index 0000000000..8b0aa086c0
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/login/odef-login.page.js
@@ -0,0 +1,3 @@
+export const inputUsernameSelector = 'input[data-test-subj="user-name"]';
+export const inputPasswordSelector = 'input[data-test-subj="password"]';
+export const buttonSubmitSelector = 'button[data-test-subj="submit"]';
diff --git a/test/cypress/cypress/integration/pageobjects/login/wzd-login.page.js b/test/cypress/cypress/integration/pageobjects/login/wzd-login.page.js
new file mode 100644
index 0000000000..8b0aa086c0
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/login/wzd-login.page.js
@@ -0,0 +1,3 @@
+export const inputUsernameSelector = 'input[data-test-subj="user-name"]';
+export const inputPasswordSelector = 'input[data-test-subj="password"]';
+export const buttonSubmitSelector = 'button[data-test-subj="submit"]';
diff --git a/test/cypress/cypress/integration/pageobjects/login/xpack-login.page.js b/test/cypress/cypress/integration/pageobjects/login/xpack-login.page.js
new file mode 100644
index 0000000000..2b6938f7dc
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/login/xpack-login.page.js
@@ -0,0 +1,3 @@
+export const inputUsernameSelector = 'input[data-test-subj="loginUsername"]';
+export const inputPasswordSelector = 'input[data-test-subj="loginPassword"]';
+export const buttonSubmitSelector = 'button[data-test-subj="loginSubmit"]';
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/agents/agents.page.js b/test/cypress/cypress/integration/pageobjects/odfe/agents/agents.page.js
new file mode 100644
index 0000000000..f91a9c3d3a
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/agents/agents.page.js
@@ -0,0 +1,24 @@
+export const AGENTS_PAGE = {
+ firstAgentList: '[data-test-subj="row-001"]',
+ agSecurityEventsLink: '.WzManagementSideMenu [title="Security events"] div div',
+ agIntegrityMonitoringLink: '.WzManagementSideMenu [title="Integrity monitoring"] div div',
+ agSCALink: '.euiFlexItem.wz-module-header-agent-title > div > div:nth-child(4) button',
+ agSystemAuditingLink: '.WzManagementSideMenu [title="System Auditing"] div div',
+ agVulnerabilitiesLink: '.WzManagementSideMenu [title="Vulnerabilities"] div div',
+ agMitreAttackLink: '.WzManagementSideMenu [title="MITRE ATT&CK"] div div',
+ moreLink: '//*[contains(@class,"wz-module-header-agent-main")]//*/button//*/span[contains(text(),"More")]',
+ agPolicyMonitoring: '.WzManagementSideMenu [title="Policy Monitoring"] div div',
+ agPCIDSS: '.WzManagementSideMenu [title="PCI DSS"] div div',
+ agGDPR: '.WzManagementSideMenu [title="GDPR"] div div',
+ agHIPAA: '.WzManagementSideMenu [title="HIPAA"] div div',
+ agNIST: '.WzManagementSideMenu [title="NIST 800-53"] div div',
+ agTSC: '.WzManagementSideMenu [title="TSC"] div div',
+ statusChart: '.agents-status-pie > .euiPanel > .euiCard__content > .euiCard__children > .euiFlexGroup',
+ agentDetails: 'euiFlexItem euiFlexItem--flexGrowZero agents-details-card',
+ deployNewAgentButton: '//span[contains(text(),"Deploy new agent")]',
+ exploreAgentButton: '.wz-module-header-nav .euiFlexItem .euiToolTipAnchor .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Explore agent")',
+ firstAgentDisplayed: '.euiModal .euiTable .euiTableRow:nth-child(1)',
+ unPinnedAgentButton: '.wz-module-header-nav .euiFlexItem .euiToolTipAnchor .euiButtonIcon[aria-label="Unpin agent"]',
+ secundAgentDisplayed: '.euiModal .euiTable .euiTableRow:nth-child(2)',
+ agentID: '.euiModal .euiTable .euiTableRow:nth-child(1) .euiTableRowCell:nth-child(1) .euiTableCellContent__text',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/agents/deploy-new-agent.page.js b/test/cypress/cypress/integration/pageobjects/odfe/agents/deploy-new-agent.page.js
new file mode 100644
index 0000000000..664efa81cc
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/agents/deploy-new-agent.page.js
@@ -0,0 +1,35 @@
+export const DEPLOY_NEW_AGENT_PAGE = {
+ closeButton: "//span[contains(text(),'Close')]",
+ title: "[name='RegisterAgent'] h2",
+ deployNewAgentSections: "[name='RegisterAgent'] .euiStep",
+
+ operatingSystemSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(1) p",
+ redhatButton: '[data-text="Red Hat / CentOS"]',
+ debianUbuntuButton: '[data-text="Debian / Ubuntu"]',
+ windowsButton: '[data-text="Windows"]',
+ macOSButton: '[data-text="MacOS"]',
+
+ operationSystemTitle: "[name='RegisterAgent'] .euiStep:nth-child(1) .euiTitle",
+ operationSystemOption: "[name='RegisterAgent'] .euiStep:nth-child(1) fieldset label",
+
+ serverAddressSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(2) :nth-child(1) p.euiStep__title",
+ serverMessage: "[name='RegisterAgent'] .euiStep:nth-child(2) .euiStep__content p",
+ serverInputField: "[name='RegisterAgent'] .euiStep:nth-child(2) [placeholder='Server address']",
+
+ agentToGroupSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(3) .euiTitle",
+ agentToGroupMessage: "//*[@name='RegisterAgent']//*[3][contains(@class,'euiStep')]//*[contains(@class,'euiText')]/p", //cambiar a xpath
+ agentToGroupSelector: "[name='RegisterAgent'] .euiStep:nth-child(3) [data-test-subj='comboBoxInput']",
+
+ installAndEnrollAgentSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(4) .euiTitle",
+ installAndEnrollAgentDefaultLabel: "[name='RegisterAgent'] .euiStep:nth-child(4) .euiCallOutHeader__title",
+ // after selected these OS options
+ installAndEnrollAgentCommand: "[name='RegisterAgent'] .euiStep:nth-child(5) .euiCodeBlock__line",
+ installAndEnrollAgentCopyButton: "[name='RegisterAgent'] .euiStep:nth-child(5) .copy-codeblock-wrapper .copy-overlay",
+
+ startTheAgentTitle: "[name='RegisterAgent'] .euiStep:nth-child(6) p",
+ startTheAgentTabsLabels: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content .euiTabs button",
+ systemmdTabButton: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content .euiTabs button:nth-child(1)",
+ sysVTabButton: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content .euiTabs button:nth-child(2)",
+ startTheAgentCommandText: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content [role='tabpanel'] .euiText pre",
+ startTheAgentcopyButton: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content [role='tabpanel'] .euiText .copy-overlay",
+};
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/filters/filters.page.js b/test/cypress/cypress/integration/pageobjects/odfe/filters/filters.page.js
new file mode 100644
index 0000000000..186eed7c86
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/filters/filters.page.js
@@ -0,0 +1,14 @@
+export const FILTERS_PAGE = {
+ addFilterButton: '[data-test-subj="addFilter"]',
+ filterSuggestionList: '[data-test-subj="filterFieldSuggestionList"]',
+ filterOperatorList: '[data-test-subj="filterOperatorList"] [data-test-subj="comboBoxToggleListButton"]',
+ filterParams: '[data-test-subj="filterParams"]',
+ saveFilterButton: '[data-test-subj="saveFilter"]',
+ stablishedFilter: '[data-test-subj="filter filter-enabled filter-key-rule.level filter-value-7 filter-unpinned"',
+ pinFilterAction: '[data-test-subj="pinFilter"]',
+ selectedOperator: '.euiFilterSelectItem[title="is"]',
+ pinnedFilter: '[data-test-subj="filter filter-enabled filter-key-rule.level filter-value-7 filter-pinned"]',
+ eventsButton: '//*[contains(@class,"euiTabs")]//*[contains(text(),"Events")]',
+ removeFilterButton: '//*[contains(@class,"euiContextMenuPanel")]//*[contains(text(),"Delete")]',
+ operatorList: '.euiPanel[data-test-subj="comboBoxOptionsList filterOperatorList-optionsList"] .euiComboBoxOptionsList__rowWrap'
+};
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/modules-directory.page.js b/test/cypress/cypress/integration/pageobjects/odfe/modules-directory.page.js
new file mode 100644
index 0000000000..49a40d905a
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/modules-directory.page.js
@@ -0,0 +1,14 @@
+export const MODULES_DIRECTORY_PAGE = {
+ amazonAWSCard: '[data-test-subj="overviewWelcomeAws"]',
+ gCPCard: '[data-test-subj="overviewWelcomeGcp"]',
+ openSCAPCard: '[data-test-subj="overviewWelcomeOscap"]',
+ cisCatCard: '[data-test-subj="overviewWelcomeCiscat"]',
+ virusTotalCard: '[data-test-subj="overviewWelcomeVirustotal"]',
+ osqueryCard: '[data-test-subj="overviewWelcomeOsquery"]',
+ dockerListenerCard: '[data-test-subj="overviewWelcomeDocker"]',
+ gDPRCard: '[data-test-subj="overviewWelcomeGdpr"]',
+ hIPAACard: '[data-test-subj="overviewWelcomeHipaa"]',
+ tSCCard: '[data-test-subj="overviewWelcomeTsc"]',
+ gitHubCard: '[data-test-subj="overviewWelcomeGithub"]',
+ userLoginCard: '[data-test-subj="account-popover"]',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/overview/overview.page.js b/test/cypress/cypress/integration/pageobjects/odfe/overview/overview.page.js
new file mode 100644
index 0000000000..b3fbf7b52f
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/overview/overview.page.js
@@ -0,0 +1,14 @@
+export const OVERVIEW_PAGE = {
+ securityEvents: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Security events")]',
+ integrityMonitoring: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Integrity monitoring")]',
+ policyMonitoring: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Policy monitoring")]',
+ systemAuditing: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"System auditing")]',
+ securityInformationAssessment: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Security configuration assessment")]',
+ vulnerabilities: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Vulnerabilities")]',
+ mitre: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"MITRE ATT&CK")]',
+ pciDSS: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"PCI DSS")]',
+ nist: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"NIST")]',
+ tsc: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"TSC")]',
+ gdpr: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"GDPR")]',
+ hipaa: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"HIPAA")]',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/reporting/report.page.js b/test/cypress/cypress/integration/pageobjects/odfe/reporting/report.page.js
new file mode 100644
index 0000000000..cc697415fd
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/reporting/report.page.js
@@ -0,0 +1,6 @@
+export const REPORTING_PAGE = {
+ generateReportButton: '.wz-welcome-page-agent-tabs .euiFlexItem .euiFlexItem .euiButtonEmpty[type="button"] .euiButtonEmpty__text:contains("Generate report")',
+ reportGeneratedToast: '.euiToast',
+ lastCreatedReport: '.euiTable .euiTableRow:nth-child(1) .euiTableRowCell .euiTableCellContent .euiTableCellContent__text',
+ disableGenerateReportButton: '.wz-welcome-page-agent-tabs .euiFlexItem .euiToolTipAnchor button.euiButtonEmpty-isDisabled',
+};
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/settings/about.page.js b/test/cypress/cypress/integration/pageobjects/odfe/settings/about.page.js
new file mode 100644
index 0000000000..4e851f055a
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/settings/about.page.js
@@ -0,0 +1,19 @@
+export const ABOUT_PAGE = {
+ appVersionTitle: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(1)',
+ appVersionNumber: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(1) > span',
+
+ appRevisionTitle: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(2)',
+ appRevisionNumber: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(2) > span',
+
+ installDateTitle: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(3)',
+ installDateInformation: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(3) > span',
+
+ welcomingCard: 'div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(1) > div',
+ welcomingCardTitle: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(1) > div h2.euiTitle',
+
+ communityCard: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div',
+ communityCardTitle: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div h2.euiTitle',
+ communitySlackLink: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div :nth-child(1) .euiButtonIcon',
+ communityGoogleGroupLink: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div :nth-child(2) .euiButtonIcon',
+ communityGithubLink: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div :nth-child(3) .euiButtonIcon',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/settings/api-configuration.page.js b/test/cypress/cypress/integration/pageobjects/odfe/settings/api-configuration.page.js
new file mode 100644
index 0000000000..9dd489442f
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/settings/api-configuration.page.js
@@ -0,0 +1,10 @@
+export const API_CONFIGURATION_PAGE = {
+ checkConnectionButton: 'div:nth-child(2) > span > button',
+ connectionSuccessToast: '.euiToast--success',
+ addNewConnectionButton: 'react-component > div > div > div:nth-child(1) > div:nth-child(2) > button > span',
+ addNewConnectionModal: 'react-component > div > div.euiFlexItem.min-guide-width > div',
+ addNewConnectionModalTitle: 'div.euiFlexGroup--responsive > div:nth-child(1) > div > h2',
+ newConnectionModalCheckConnectionButton: 'div.euiStep__content > div > button.euiButton > span > span',
+ testConnectionCheckBox: 'div:nth-child(2) > div.euiStep__titleWrapper > p',
+ testConnectionCheckBoxMarked: 'div:nth-child(2) > div.euiStep__titleWrapper .euiStep__circle > svg',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/settings/configuration.page.js b/test/cypress/cypress/integration/pageobjects/odfe/settings/configuration.page.js
new file mode 100644
index 0000000000..56efbbddc6
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/settings/configuration.page.js
@@ -0,0 +1,197 @@
+export const CONFIGURATION_PAGE = {
+ settingTitle: 'div > h2.euiTitle',
+ settingToolTip: 'div > h2.euiTitle > .euiToolTipAnchor',
+ settingSubTitle: '.euiPage .euiFlexItem:nth-child(1) .euiFlexItem:nth-child(2) .euiText.euiText--medium',
+ settingSearchBox: '.euiPage .euiFlexItem:nth-child(1) .euiFlexItem:nth-child(2).euiSearchBar__searchHolder',
+ settingCategoriesButton: '.euiPage header .euiFlexItem .euiFilterGroup',
+ settingCategotiesPanel: '.euiPageBody .euiPanel',
+
+ //General Panel
+ //General Panel
+ generalPanelTitle: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel h2',
+
+ generalPanelIndexPatternName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ generalPanelIndexPatternDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelIndexPatternLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelIndexPatternField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelRequestTimeoutName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ generalPanelRequestTimeoutDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelRequestLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelRequestField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelIpSelectorName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ generalPanelIpSelectorDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelIpSelectorLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelIpSelectorField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ generalPanelIpIgnoreName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ generalPanelIpIgnoreDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelIpIgnoreLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelIpIgnoreField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper',
+
+ generalPanelCronPrefixName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ generalPanelCronPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelCronLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelCronField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelSamplePrefixName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ generalPanelSamplePrefixDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelSampleLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelSampleField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelManagerAlertsPrefixName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) span',
+ generalPanelManagerAlertsPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelManagerAlertsLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelManagerAlertsField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ generalPanelLogLevelName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) span',
+ generalPanelLogLevelDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelLogLevelLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelLogLevelField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper select',
+
+ generalPanelEnrollmentName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(1) span',
+ generalPanelEnrollmentDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelEnrollmentLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelEnrollmentField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ //Health Check Panel
+ //Health Check Panel
+ healthCheckPanelTitle: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel h2',
+ healthCheckPanelIndexPatternPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelIndexPatternPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelIndexPatterLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelIndexPatterField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelIndexTemplatePrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelIndexTemplatePrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelIndexTemplateLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelIndexTemplateField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelApiConnectionPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelApiConnectionPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelApiConnectionLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelApiConnectionField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelApiVersionPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelApiVersionPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelApiVersionLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelApiVersionField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelKnowFieldsPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelKnowFieldsPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelKnowFieldsLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelKnowFieldsField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelRemoveMetaFieldsPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelRemoveMetaFieldsPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelRemoveMetaFieldsPrefixLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelRemoveMetaFieldsPrefixField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelSetBucketPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelSetBucketPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelSetBucketLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelSetBucketField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelSetTimePrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelSetTimePrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelSetTimeLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelSetTimeField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ //Monitoring Panel
+ //Monitoring Panel
+ monitoringPanelTitle: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel h2',
+
+ monitoringPanelStatusName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ monitoringPanelStatusDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelStatusPatterLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelStatusPatterField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ monitoringPanelFrequencyName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ monitoringPanelFrequencyDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelFrequencyLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelFrequencyField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ monitoringPanelIndexShardsName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexShardsDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelIndexShardsLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexShardsField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ monitoringPanelIndexReplicasName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexReplicasDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelPanelIndexReplicasLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexReplicasField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ monitoringPanelIndexCreationName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexCreationDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelIndexCreationLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexCreationField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper select',
+
+ monitoringPanelIndexPatternName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexPatternDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelIndexPatternLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexPatternField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ //Statistics Panel
+ //Statistics Panel
+ statisticsPanelTitle: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel h2',
+
+ StatisticsPanelStatusName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelStatusDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelStatusPatterLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelStatusPatterField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ StatisticsPanelIncludesApisName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIncludesApisDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIncludesApisLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIncludesApisField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper',
+
+ StatisticsPanelIndexIntervalName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexIntervalDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexIntervalLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexIntervalField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ StatisticsPanelIndexNameName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexNameDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexNameLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexNameField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ StatisticsPanelIndexCreationName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexCreationDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexCreationLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexCreationField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper select',
+
+ StatisticsPanelIndexShardsName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexShardsDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexShardsLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexShardsField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ StatisticsPanelIndexReplicasName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexReplicasDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexReplicasLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexReplicasField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ //Logo Customization Panel
+ //Logo Customization Panel
+ logoPanelTitle: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel h2',
+
+ LogosCustomizationPanelLogoAppName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogoAppDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogoAppPatterLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogoAppPatterField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ LogosCustomizationPanelLogosSidebarName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogosSidebarDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogosSidebarLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogosSidebarField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ LogosCustomizationPanelLogoHealthCheckName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogoHealthCheckDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogoHealthCheckLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogoHealthCheckField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ LogosCustomizationPanelLogoReportName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogoReportDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogoReportLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogoReportField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/settings/logs.page.js b/test/cypress/cypress/integration/pageobjects/odfe/settings/logs.page.js
new file mode 100644
index 0000000000..8fb85d0bdd
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/settings/logs.page.js
@@ -0,0 +1,6 @@
+export const LOGS_PAGE = {
+ logsTitle: 'div > .euiTitle',
+ logsContainer: 'div > .euiCodeBlock',
+ reloadLogsLink: 'div.euiFlexItem > button > span > span',
+ logsTitleText: 'App log messages',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/settings/miscellaneous.page.js b/test/cypress/cypress/integration/pageobjects/odfe/settings/miscellaneous.page.js
new file mode 100644
index 0000000000..7edd153931
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/settings/miscellaneous.page.js
@@ -0,0 +1,5 @@
+export const MISCELLANEOUS_PAGE = {
+ runHealthChecksButton: 'div.euiFlexItem > div > div > button.euiButton',
+ healthCheckContainer: 'div.health-check',
+ successCheckIconList: 'p > span.euiToolTipAnchor > svg.euiIcon',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/settings/modules.page.js b/test/cypress/cypress/integration/pageobjects/odfe/settings/modules.page.js
new file mode 100644
index 0000000000..2628f3faaa
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/settings/modules.page.js
@@ -0,0 +1,13 @@
+export const MODULES_PAGE = {
+ amazonAWSToggleButton: ':nth-child(1) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ gCPToggleButton: ':nth-child(1) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ gitHubCardToggleButton: ':nth-child(1) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(6) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ openSCAPToggleButton: ':nth-child(2) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ cisCatToggleButton: ':nth-child(2) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ virusTotalToggleButton: ':nth-child(3) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(3) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ osqueryToggleButton: ':nth-child(3) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ dockerListenerToggleButton: ':nth-child(3) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ gDPRToggleButton: ':nth-child(4) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(3) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ hIPAAToggleButton: ':nth-child(4) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ tSCToggleButton: ':nth-child(4) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/settings/sample-data.page.js b/test/cypress/cypress/integration/pageobjects/odfe/settings/sample-data.page.js
new file mode 100644
index 0000000000..95d2e86ef3
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/settings/sample-data.page.js
@@ -0,0 +1,9 @@
+export const SAMPLE_DATA_PAGE = {
+ addSecurityInformationDataButton: 'div:nth-child(1) > div > div.euiCard__footer > div > div > button',
+ securityInformationDataTitle:'div:nth-child(1) > div > div.euiCard__content span',
+ addAuditingAndPolicyMonitoringDataButton: 'div:nth-child(2) > div > div.euiCard__footer > div > div > button',
+ auditingAndPolicyMonitoringDataTitle: 'div:nth-child(2) > div > div.euiCard__content span',
+ addThreatDetectionAndResponseDataButton: 'div:nth-child(3) > div > div.euiCard__footer > div > div > button',
+ threatDetectionAndResponseDataTitle: 'div:nth-child(3) > div > div.euiCard__content span',
+ dataAddedSuccessfullyToast: '.euiCard__betaBadgeWrapper',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/wazuh-menu/decoders.page.js b/test/cypress/cypress/integration/pageobjects/odfe/wazuh-menu/decoders.page.js
new file mode 100644
index 0000000000..58c08f9a6c
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/wazuh-menu/decoders.page.js
@@ -0,0 +1,20 @@
+export const DECODERS_PAGE = {
+ titleSelector: '[class="euiTitle euiTitle--medium"]',
+ tableSelector: '[class="euiTableRow customRowClass euiTableRow-isClickable"]',
+ dropdownPaginationSelector: '[data-test-subj="tablePaginationPopoverButton"]',
+ listPages: 'nav[class="euiPagination"]',
+ customDecodersButtonSelector: '[data-test-subj="Custom decoders"]',
+ manageDecodersFilesButtonSelector: '.euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Manage decoders")',
+ editDecoderButtonSelector: 'tr.euiTableRow:nth-child(1) .euiToolTipAnchor .euiButtonIcon[aria-label="Edit content"]',
+ saveDecoderButtonSelector: '.euiFlexGroup .euiFlexItem button.euiButton span.euiButtonContent span.euiButton__text:contains("Save")',
+ messageConfirmSaveSelector: '.euiText > span',
+ buttonRestartSelector: '.euiCallOut.euiCallOut--primary .euiButton.euiButton--primary',
+ firstCustomDecoder: '[data-test-subj="row-local_decoder_example"]',
+ xmlDecoderFile:':nth-child(4) .euiTableCellContent .euiToolTipAnchor .euiLink',
+ codeEditorSelector: '[data-test-subj="codeEditorContainer"]',
+ backButtonSelector: '.euiFlexGroup .euiFlexItem .euiToolTipAnchor .euiButtonIcon',
+ confirmModalSelector: '[data-test-subj="confirmModalTitleText"]',
+ createNewDecoderSelector:'.euiFlexGroup .euiFlexItem .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Add new decoders file")',
+ decoderTitleSelector: '.euiFlexItem .euiFlexGroup .euiFormControlLayout input.euiFieldText',
+ saveDecoderMessage: '.euiText span:contains("Changes will not take effect until a restart is performed.")'
+};
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/wazuh-menu/groups-page.js b/test/cypress/cypress/integration/pageobjects/odfe/wazuh-menu/groups-page.js
new file mode 100644
index 0000000000..8b56b67a9a
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/wazuh-menu/groups-page.js
@@ -0,0 +1,6 @@
+export const GROUPS_PAGE = {
+ editGroups:'.euiBasicTable .euiTable--responsive :nth-child(4) .euiTableCellContent :nth-child(2)',
+ codeEditorSelector: '[data-test-subj="codeEditorContainer"]',
+ backButtonSelector: '.euiFlexGroup .euiFlexItem .euiToolTipAnchor .euiButtonIcon',
+ confirmModalSelector: '[data-test-subj="confirmModalTitleText"]'
+};
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/wazuh-menu/rules.page.js b/test/cypress/cypress/integration/pageobjects/odfe/wazuh-menu/rules.page.js
new file mode 100644
index 0000000000..c2f08d2adc
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/wazuh-menu/rules.page.js
@@ -0,0 +1,36 @@
+export const RULES_PAGE = {
+ rulesButtonSelector: '[class="euiSideNavItem euiSideNavItem--trunk"]',
+ titleSelector: '[class="euiTitle euiTitle--medium"]',
+ tableSelector: '[class="euiTableRow customRowClass euiTableRow-isClickable"]',
+ dropdownPaginationSelector: '[data-test-subj="tablePaginationPopoverButton"]',
+ listPagesSelector: 'nav[class="euiPagination"]',
+ customRulesButtonSelector: '.euiButtonGroupButton.euiButtonGroupButton--text',
+ firstCustomRule: '[data-test-subj="row-100001"]',
+ xmlRuleFile:'.euiBasicTable .euiTable :nth-child(6) :nth-child(2) .euiToolTipAnchor .euiLink:contains("local_rules.xml")',
+ codeEditorSelector: '[data-test-subj="codeEditorContainer"]',
+ backButtonSelector: '.euiFlexGroup .euiFlexItem .euiToolTipAnchor .euiButtonIcon',
+ confirmModalSelector: '[data-test-subj="confirmModalTitleText"]',
+ createNewRulesSelector: '.euiFlexGroup .euiFlexItem .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Add new rules file")',
+ rulesTitleSelector:'.euiFlexItem .euiFlexGroup .euiFormControlLayout input.euiFieldText',
+ saveRulesButtonSelector: '.euiFlexGroup .euiFlexItem button.euiButton span.euiButtonContent span.euiButton__text:contains("Save")',
+ saveRulesMessage: '.euiText span:contains("Changes will not take effect until a restart is performed.")',
+ refreshButtonSelector: '.euiFlexGroup .euiFlexItem .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Refresh")',
+ rulestableSelector: '[name="WzManagement"] table tr',
+ rulesRowTableSelector: '[name="WzManagement"] tbody tr',
+ buttonListPageSelector: '[name="WzManagement"] button > span',
+ rulesFilterSelector: '.euiSuggestInput [placeholder="Filter or search"]',
+ dropdownFilterSelector: '.euiPanel.euiPopover__panel.euiPopover__panel--bottom',
+ filterLevelSelector: 'button:contains("level")',
+ filterNumberSelector: 'button:nth-child(0)',
+ filterLabelSelector: '.euiPopover.euiPopover--anchorDownLeft [data-testid="wz-search-badge-0"]',
+ paginatorSelector: '.euiBasicTable .euiPagination',
+ paginatorPreviousSelector: '[data-test-subj="pagination-button-previous"]',
+ paginatorNextSelector: '[data-test-subj="pagination-button-next"]',
+ paginatorFirstSelector: '.euiBasicTable .euiPagination li.euiPagination__item:first-child',
+ paginatorSecondSelector: '.euiBasicTable .euiPagination li.euiPagination__item:nth-child(2)',
+ paginatorthirdSelector: '.euiBasicTable .euiPagination li.euiPagination__item:nth-child(3)',
+ paginatorFourthSelector: '.euiBasicTable .euiPagination li.euiPagination__item:nth-child(4)',
+ paginatorLastSelector: '.euiBasicTable .euiPagination li.euiPagination__item:last-child',
+};
+
+
diff --git a/test/cypress/cypress/integration/pageobjects/odfe/wazuh-menu/wazuh-menu.page.js b/test/cypress/cypress/integration/pageobjects/odfe/wazuh-menu/wazuh-menu.page.js
new file mode 100644
index 0000000000..1f8d860b2c
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/odfe/wazuh-menu/wazuh-menu.page.js
@@ -0,0 +1,81 @@
+export const WAZUH_MENU_PAGE = {
+ wazuhMenuLeft: '.wz-menu-left-side .wz-menu-sections',
+ wazuhMenuRight: '.wz-menu-right-side',
+ wazuhMenuSettingRight: '.wz-menu-right-side .WzManagementSideMenu',
+ wazuhMenuButton: '[data-test-subj=menuWazuhButton]',
+ //region Menu
+ //region Menu
+ modulesButton: '[data-test-subj=menuModulesButton]',
+ managementButton: '[data-test-subj=menuManagementButton]',
+ agentsButton: '[data-test-subj=menuAgentsButton]',
+ toolsButton: '[data-test-subj=menuToolsButton]',
+ securityButton: '[data-test-subj=menuSecurityButton]',
+ settingsButton: '[data-test-subj=menuSettingsButton]',
+ //endregion Menu
+ //region SubMenu
+ //region Modules
+ //endregion Menu
+ //region SubMenu
+ //region Modules
+ modulesDirectoryLink: '.wz-menu-right-side div.euiFlexGroup > div > button > span > span',
+ securityEventsLink: '[data-test-subj=menuModulesSecurityEventsLink]',
+ integrityMonitoringLink: '[data-test-subj=menuModulesFimLink]',
+ amazonAwsLink: '[data-test-subj=menuModulesAwsLink]',
+ googleCloudPlatformLink: '[data-test-subj=menuModulesGcpLink]',
+ policyMonitoringLink: '[data-test-subj=menuModulesPolicyMonitoringLink]',
+ systemAuditingLink: '[data-test-subj=menuModulesAuditLink]',
+ openScapLink: '[data-test-subj=menuModulesOpenScapLink]',
+ cisCatLink: '[data-test-subj=menuModulesCiscatLink]',
+ securityConfigurationAssessmentLink: '[data-test-subj=menuModulesScaLink]',
+ vulnerabilitiesLink: '[data-test-subj=menuModulesVulsLink]',
+ virusTotalLink: '[data-test-subj=menuModulesVirustotalLink]',
+ osqueryLink: '[data-test-subj=menuModulesOsqueryLink]',
+ dockerListenerLink: '[data-test-subj=menuModulesDockerLink]',
+ mitreAttackLink: '[data-test-subj=menuModulesMitreLink]',
+ pciDssLink: '[data-test-subj=menuModulesPciLink]',
+ gdprLink: '[data-test-subj=menuModulesGdprLink]',
+ hipaaLink: '[data-test-subj=menuModulesHipaaLink]',
+ nistLink: '[data-test-subj=menuModulesNistLink]',
+ tscLink: '[data-test-subj=menuModulesTscLink]',
+ //endregion
+ //region Management
+ //endregion
+ //region Management
+ rulesLink: '[data-test-subj=menuManagementRulesLink]',
+ decodersLink: '[data-test-subj=menuManagementDecodersLink]',
+ cdbListLink: '[data-test-subj=menuManagementCdbListsLink]',
+ groupsLink: '[data-test-subj=menuManagementGroupsLink]',
+ configurationLink: '[data-test-subj=menuManagementConfigurationLink]',
+ statusLink: '[data-test-subj=menuManagementStatusLink]',
+ clusterLink: '[data-test-subj=menuManagementMonitoringLink]',
+ statisticsLink: '[data-test-subj=menuManagementStatisticsLink]',
+ logsLink: '[data-test-subj=menuManagementLogsLink]',
+ reportingLink: '[data-test-subj=menuManagementReportingLink]',
+ //endregion
+ //region Tools
+ //endregion
+ //region Tools
+ apiConsoleLink: '[data-test-subj=menuToolsDevToolsLink]',
+ rulesetTestLink: '[data-test-subj=menuToolsLogtestLink]',
+ //endregion
+ //region Security
+ //endregion
+ //region Security
+ usersLink: '[data-test-subj=menuSecurityUsersLink]',
+ rolesLink: '[data-test-subj=menuSecurityRolesLink]',
+ policiesLink: '[data-test-subj=menuSecurityPoliciesLink]',
+ rolesMappingLink: '[data-test-subj=menuSecurityRoleMappingLink]',
+ //endregion
+ //region Settings
+ //endregion
+ //region Settings
+ settingsApiConfigurationLink: '[data-test-subj=menuSettingsApiLink]',
+ settingsModulesLink: '[data-test-subj=menuSettingsModulesLink]',
+ settingsSampleDataLink: '[data-test-subj=menuSettingsSampleDataLink]',
+ settingsConfigurationLink: '[data-test-subj=menuSettingsConfigurationLink]',
+ settingsLogsLink: '[data-test-subj=menuSettingsLogsLink]',
+ settingsMiscellaneousLink: '[data-test-subj=menuSettingsMiscellaneousLink]',
+ settingsAboutLink: '[data-test-subj=menuSettingsAboutLink]',
+ //endregion
+ //endregion
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/agents/agents.page.js b/test/cypress/cypress/integration/pageobjects/wzd/agents/agents.page.js
new file mode 100644
index 0000000000..341cc728c7
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/agents/agents.page.js
@@ -0,0 +1,22 @@
+export const AGENTS_PAGE = {
+ firstAgentList: '[data-test-subj="row-001"]',
+ agSecurityEventsLink: ':nth-child(1) > .euiSideNav > .euiSideNav__content > .euiSideNavItem--root > .euiSideNavItem__items > :nth-child(1) > .euiSideNavItemButton > .euiSideNavItemButton__content > .euiSideNavItemButton__label > .euiFlexGroup > .euiFlexItem',
+ agIntegrityMonitoringLink: ':nth-child(1) > .euiSideNav > .euiSideNav__content > .euiSideNavItem--root > .euiSideNavItem__items > :nth-child(2) > .euiSideNavItemButton > .euiSideNavItemButton__content > .euiSideNavItemButton__label > .euiFlexGroup > .euiFlexItem',
+ agSCALink: ':nth-child(2) > .euiSideNav > .euiSideNav__content > .euiSideNavItem--root > .euiSideNavItem__items > :nth-child(3) > .euiSideNavItemButton > .euiSideNavItemButton__content > .euiSideNavItemButton__label > .euiFlexGroup > .euiFlexItem',
+ agSystemAuditingLink: ':nth-child(2) > .euiSideNav > .euiSideNav__content > .euiSideNavItem--root > .euiSideNavItem__items > :nth-child(2) > .euiSideNavItemButton > .euiSideNavItemButton__content > .euiSideNavItemButton__label > .euiFlexGroup > .euiFlexItem',
+ agVulnerabilitiesLink: ':nth-child(3) > .euiSideNav > .euiSideNav__content > .euiSideNavItem--root > .euiSideNavItem__items > :nth-child(1) > .euiSideNavItemButton > .euiSideNavItemButton__content > .euiSideNavItemButton__label > .euiFlexGroup > .euiFlexItem',
+ agMitreAttackLink: ':nth-child(3) > .euiSideNav > .euiSideNav__content > .euiSideNavItem--root > .euiSideNavItem__items > :nth-child(2) > .euiSideNavItemButton > .euiSideNavItemButton__content > .euiSideNavItemButton__label > .euiFlexGroup > .euiFlexItem',
+ moreLink: '//*[contains(@class,"wz-module-header-agent-main")]//*/button//*/span[contains(text(),"More")]',
+ agPolicyMonitoring: ':nth-child(2) > .euiSideNav > .euiSideNav__content > .euiSideNavItem--root > .euiSideNavItem__items > :nth-child(1) > .euiSideNavItemButton > .euiSideNavItemButton__content > .euiSideNavItemButton__label > .euiFlexGroup > .euiFlexItem',
+ agPCIDSS: ':nth-child(4) > .euiSideNav > .euiSideNav__content > .euiSideNavItem--root > .euiSideNavItem__items > :nth-child(1) > .euiSideNavItemButton > .euiSideNavItemButton__content > .euiSideNavItemButton__label > .euiFlexGroup > .euiFlexItem',
+ agNIST: ':nth-child(4) > .euiSideNav > .euiSideNav__content > .euiSideNavItem--root > .euiSideNavItem__items > :nth-child(2) > .euiSideNavItemButton > .euiSideNavItemButton__content > .euiSideNavItemButton__label > .euiFlexGroup > .euiFlexItem',
+ agTSC: ':nth-child(4) > .euiSideNav > .euiSideNav__content > .euiSideNavItem--root > .euiSideNavItem__items > :nth-child(3) > .euiSideNavItemButton > .euiSideNavItemButton__content > .euiSideNavItemButton__label > .euiFlexGroup > .euiFlexItem',
+ statusChart: '.agents-status-pie .euiCard .euiCard__content .euiFlexGroup--gutterLarge',
+ agentDetails: 'euiFlexItem euiFlexItem--flexGrowZero agents-details-card',
+ deployNewAgentButton: '//span[contains(text(),"Deploy new agent")]',
+ exploreAgentButton: '.wz-module-header-nav .euiFlexItem .euiToolTipAnchor .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Explore agent")',
+ firstAgentDisplayed: '.euiModal .euiTable .euiTableRow:nth-child(1)',
+ unPinnedAgentButton: '.wz-module-header-nav .euiFlexItem .euiToolTipAnchor .euiButtonIcon[aria-label="Unpin agent"]',
+ secundAgentDisplayed: '.euiModal .euiTable .euiTableRow:nth-child(2)',
+ agentID: '.euiModal .euiTable .euiTableRow:nth-child(1) .euiTableRowCell:nth-child(1) .euiTableCellContent__text',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/agents/deploy-new-agent.page.js b/test/cypress/cypress/integration/pageobjects/wzd/agents/deploy-new-agent.page.js
new file mode 100644
index 0000000000..ad59df55d7
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/agents/deploy-new-agent.page.js
@@ -0,0 +1,35 @@
+export const DEPLOY_NEW_AGENT_PAGE = {
+ closeButton: "//span[contains(text(),'Close')]",
+ title: "[name='RegisterAgent'] h2",
+ deployNewAgentSections: "[name='RegisterAgent'] .euiStep",
+
+ operatingSystemSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(1) p",
+ redhatButton: '[data-text="Red Hat / CentOS"]',
+ debianUbuntuButton: '[data-text="Debian / Ubuntu"]',
+ windowsButton: '[data-text="Windows"]',
+ macOSButton: '[data-text="MacOS"]',
+
+ operationSystemTitle: "[name='RegisterAgent'] .euiStep:nth-child(1) .euiTitle",
+ operationSystemOption: "[name='RegisterAgent'] .euiStep:nth-child(1) fieldset .euiButton__text",
+
+ serverAddressSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(2) :nth-child(1) p.euiStep__title",
+ serverMessage: "[name='RegisterAgent'] .euiStep:nth-child(2) .euiStep__content p",
+ serverInputField: "[name='RegisterAgent'] .euiStep:nth-child(2) [placeholder='Server address']",
+
+ agentToGroupSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(3) .euiTitle",
+ agentToGroupMessage: "//*[@name='RegisterAgent']//*[3][contains(@class,'euiStep')]//*[contains(@class,'euiText')]/p", //cambiar a xpath
+ agentToGroupSelector: "[name='RegisterAgent'] .euiStep:nth-child(3) [data-test-subj='comboBoxInput']",
+
+ installAndEnrollAgentSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(4) .euiTitle",
+ installAndEnrollAgentDefaultLabel: "[name='RegisterAgent'] .euiStep:nth-child(4) .euiCallOutHeader__title",
+ // after selected these OS options
+ installAndEnrollAgentCommand: "[name='RegisterAgent'] .euiStep:nth-child(5) .euiCodeBlock__line",
+ installAndEnrollAgentCopyButton: "[name='RegisterAgent'] .euiStep:nth-child(5) .copy-codeblock-wrapper .copy-overlay",
+
+ startTheAgentTitle: "[name='RegisterAgent'] .euiStep:nth-child(6) p",
+ startTheAgentTabsLabels: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content .euiTabs button",
+ systemmdTabButton: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content .euiTabs button:nth-child(1)",
+ sysVTabButton: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content .euiTabs button:nth-child(2)",
+ startTheAgentCommandText: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content [role='tabpanel'] .euiText pre",
+ startTheAgentcopyButton: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content [role='tabpanel'] .euiText .copy-overlay",
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/filters/filters.page.js b/test/cypress/cypress/integration/pageobjects/wzd/filters/filters.page.js
new file mode 100644
index 0000000000..fc673edc34
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/filters/filters.page.js
@@ -0,0 +1,20 @@
+export const FILTERS_PAGE = {
+ addFilterButton: '[data-test-subj="addFilter"]',
+ filterCard: '.euiPopover__panel-isOpen .euiFlexItem.euiFlexItem--flexGrowZero .euiForm',
+ filterSuggestionList: '[data-test-subj="filterFieldSuggestionList"]',
+ filterOperatorListObject:'[data-test-subj="comboBoxOptionsList filterOperatorList-optionsList"] [role="listBox"]',
+ filterOperatorList: '.euiFormRow__fieldWrapper [data-test-subj="filterOperatorList"] div div button.euiFormControlLayoutCustomIcon',
+ filterParams: '[data-test-subj="filterParams"] .euiFieldNumber',
+ saveFilterButton: '[data-test-subj="saveFilter"]',
+ stablishedFilter: '[data-test-subj="filter filter-enabled filter-key-rule.level filter-value-7 filter-unpinned "]',
+ pinFilterAction: '[data-test-subj="pinFilter"]',
+ selectedOperator: '.euiPanel[data-test-subj="comboBoxOptionsList filterOperatorList-optionsList"] .euiComboBoxOptionsList__rowWrap button.euiFilterSelectItem[title="is"]',
+ SelectedOperatorIs:'[data-test-subj="comboBoxOptionsList filterOperatorList-optionsList"] button[title="is"]',
+ pinnedFilter: '.euiBadge .euiBadge__content button.euiBadge__childButton[data-test-subj="filter filter-enabled filter-key-rule.level filter-value-7 filter-pinned "]',
+ eventsButton: '//*[contains(@class,"euiTabs")]//*[contains(text(),"Events")]',
+ removeFilterButton: '//*[contains(@class,"euiContextMenuPanel")]//*[contains(text(),"Delete")]',
+ operatorList: '.euiPanel[data-test-subj="comboBoxOptionsList filterOperatorList-optionsList"] .euiComboBoxOptionsList__rowWrap',
+ searchInputSelector: '[role="combobox"] [data-test-subj="queryInput"]',
+ noResultMessage: '#moduleDashboard .euiCallOut--warning span',
+ unPinFilterAction:'[data-test-subj="pinFilter"]'
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/modules-directory.page.js b/test/cypress/cypress/integration/pageobjects/wzd/modules-directory.page.js
new file mode 100644
index 0000000000..49a40d905a
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/modules-directory.page.js
@@ -0,0 +1,14 @@
+export const MODULES_DIRECTORY_PAGE = {
+ amazonAWSCard: '[data-test-subj="overviewWelcomeAws"]',
+ gCPCard: '[data-test-subj="overviewWelcomeGcp"]',
+ openSCAPCard: '[data-test-subj="overviewWelcomeOscap"]',
+ cisCatCard: '[data-test-subj="overviewWelcomeCiscat"]',
+ virusTotalCard: '[data-test-subj="overviewWelcomeVirustotal"]',
+ osqueryCard: '[data-test-subj="overviewWelcomeOsquery"]',
+ dockerListenerCard: '[data-test-subj="overviewWelcomeDocker"]',
+ gDPRCard: '[data-test-subj="overviewWelcomeGdpr"]',
+ hIPAACard: '[data-test-subj="overviewWelcomeHipaa"]',
+ tSCCard: '[data-test-subj="overviewWelcomeTsc"]',
+ gitHubCard: '[data-test-subj="overviewWelcomeGithub"]',
+ userLoginCard: '[data-test-subj="account-popover"]',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/overview/overview.page.js b/test/cypress/cypress/integration/pageobjects/wzd/overview/overview.page.js
new file mode 100644
index 0000000000..b3fbf7b52f
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/overview/overview.page.js
@@ -0,0 +1,14 @@
+export const OVERVIEW_PAGE = {
+ securityEvents: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Security events")]',
+ integrityMonitoring: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Integrity monitoring")]',
+ policyMonitoring: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Policy monitoring")]',
+ systemAuditing: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"System auditing")]',
+ securityInformationAssessment: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Security configuration assessment")]',
+ vulnerabilities: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Vulnerabilities")]',
+ mitre: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"MITRE ATT&CK")]',
+ pciDSS: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"PCI DSS")]',
+ nist: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"NIST")]',
+ tsc: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"TSC")]',
+ gdpr: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"GDPR")]',
+ hipaa: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"HIPAA")]',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/reporting/report.page.js b/test/cypress/cypress/integration/pageobjects/wzd/reporting/report.page.js
new file mode 100644
index 0000000000..cc697415fd
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/reporting/report.page.js
@@ -0,0 +1,6 @@
+export const REPORTING_PAGE = {
+ generateReportButton: '.wz-welcome-page-agent-tabs .euiFlexItem .euiFlexItem .euiButtonEmpty[type="button"] .euiButtonEmpty__text:contains("Generate report")',
+ reportGeneratedToast: '.euiToast',
+ lastCreatedReport: '.euiTable .euiTableRow:nth-child(1) .euiTableRowCell .euiTableCellContent .euiTableCellContent__text',
+ disableGenerateReportButton: '.wz-welcome-page-agent-tabs .euiFlexItem .euiToolTipAnchor button.euiButtonEmpty-isDisabled',
+};
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/settings/about.page.js b/test/cypress/cypress/integration/pageobjects/wzd/settings/about.page.js
new file mode 100644
index 0000000000..4e851f055a
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/settings/about.page.js
@@ -0,0 +1,19 @@
+export const ABOUT_PAGE = {
+ appVersionTitle: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(1)',
+ appVersionNumber: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(1) > span',
+
+ appRevisionTitle: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(2)',
+ appRevisionNumber: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(2) > span',
+
+ installDateTitle: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(3)',
+ installDateInformation: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(3) > span',
+
+ welcomingCard: 'div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(1) > div',
+ welcomingCardTitle: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(1) > div h2.euiTitle',
+
+ communityCard: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div',
+ communityCardTitle: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div h2.euiTitle',
+ communitySlackLink: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div :nth-child(1) .euiButtonIcon',
+ communityGoogleGroupLink: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div :nth-child(2) .euiButtonIcon',
+ communityGithubLink: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div :nth-child(3) .euiButtonIcon',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/settings/api-configuration.page.js b/test/cypress/cypress/integration/pageobjects/wzd/settings/api-configuration.page.js
new file mode 100644
index 0000000000..a220e363ed
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/settings/api-configuration.page.js
@@ -0,0 +1,10 @@
+export const API_CONFIGURATION_PAGE = {
+ checkConnectionButton: 'tbody tr:nth-child(1) div:nth-child(2) > span > button',
+ connectionSuccessToast: '.euiToast--success',
+ addNewConnectionButton: 'react-component > div > div > div:nth-child(1) > div:nth-child(2) > button > span',
+ addNewConnectionModal: 'react-component > div > div.euiFlexItem.min-guide-width > div',
+ addNewConnectionModalTitle: 'div.euiFlexGroup--responsive > div:nth-child(1) > div > h2',
+ newConnectionModalCheckConnectionButton: 'div.euiStep__content > div > button.euiButton > span > span',
+ testConnectionCheckBox: 'div:nth-child(2) > div.euiStep__titleWrapper > p',
+ testConnectionCheckBoxMarked: 'div:nth-child(2) > div.euiStep__titleWrapper .euiStep__circle > svg',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/settings/configuration.page.js b/test/cypress/cypress/integration/pageobjects/wzd/settings/configuration.page.js
new file mode 100644
index 0000000000..3751d61b05
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/settings/configuration.page.js
@@ -0,0 +1,197 @@
+export const CONFIGURATION_PAGE = {
+ settingTitle: 'div > h2.euiTitle',
+ settingToolTip: 'div > h2.euiTitle > .euiToolTipAnchor',
+ settingSubTitle: '.euiPage .euiFlexItem:nth-child(1) .euiFlexItem:nth-child(2) .euiText.euiText--medium div',
+ settingSearchBox: '.euiPage .euiFlexItem:nth-child(1) .euiFlexItem:nth-child(2).euiSearchBar__searchHolder',
+ settingCategoriesButton: '.euiPage header .euiFlexItem .euiFilterGroup',
+ settingCategotiesPanel: '.euiPageBody .euiPanel',
+
+ //General Panel
+ //General Panel
+ generalPanelTitle: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel h2',
+
+ generalPanelIndexPatternName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ generalPanelIndexPatternDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelIndexPatternLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelIndexPatternField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelRequestTimeoutName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ generalPanelRequestTimeoutDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelRequestLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelRequestField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelIpSelectorName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ generalPanelIpSelectorDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelIpSelectorLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelIpSelectorField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ generalPanelIpIgnoreName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ generalPanelIpIgnoreDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelIpIgnoreLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelIpIgnoreField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper',
+
+ generalPanelCronPrefixName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ generalPanelCronPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelCronLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelCronField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelSamplePrefixName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ generalPanelSamplePrefixDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelSampleLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelSampleField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelManagerAlertsPrefixName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) span',
+ generalPanelManagerAlertsPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelManagerAlertsLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelManagerAlertsField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ generalPanelLogLevelName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) span',
+ generalPanelLogLevelDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelLogLevelLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelLogLevelField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper select',
+
+ generalPanelEnrollmentName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(1) span',
+ generalPanelEnrollmentDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelEnrollmentLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelEnrollmentField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ //Health Check Panel
+ //Health Check Panel
+ healthCheckPanelTitle: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel h2',
+ healthCheckPanelIndexPatternPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelIndexPatternPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelIndexPatterLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelIndexPatterField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelIndexTemplatePrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelIndexTemplatePrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelIndexTemplateLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelIndexTemplateField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelApiConnectionPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelApiConnectionPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelApiConnectionLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelApiConnectionField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelApiVersionPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelApiVersionPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelApiVersionLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelApiVersionField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelKnowFieldsPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelKnowFieldsPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelKnowFieldsLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelKnowFieldsField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelRemoveMetaFieldsPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelRemoveMetaFieldsPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelRemoveMetaFieldsPrefixLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelRemoveMetaFieldsPrefixField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelSetBucketPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelSetBucketPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelSetBucketLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelSetBucketField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelSetTimePrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelSetTimePrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelSetTimeLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelSetTimeField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ //Monitoring Panel
+ //Monitoring Panel
+ monitoringPanelTitle: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel h2',
+
+ monitoringPanelStatusName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ monitoringPanelStatusDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelStatusPatterLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelStatusPatterField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ monitoringPanelFrequencyName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ monitoringPanelFrequencyDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelFrequencyLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelFrequencyField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ monitoringPanelIndexShardsName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexShardsDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelIndexShardsLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexShardsField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ monitoringPanelIndexReplicasName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexReplicasDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelPanelIndexReplicasLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexReplicasField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ monitoringPanelIndexCreationName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexCreationDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelIndexCreationLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexCreationField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper select',
+
+ monitoringPanelIndexPatternName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexPatternDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelIndexPatternLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexPatternField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ //Statistics Panel
+ //Statistics Panel
+ statisticsPanelTitle: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel h2',
+
+ StatisticsPanelStatusName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelStatusDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelStatusPatterLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelStatusPatterField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ StatisticsPanelIncludesApisName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIncludesApisDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIncludesApisLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIncludesApisField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper',
+
+ StatisticsPanelIndexIntervalName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexIntervalDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexIntervalLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexIntervalField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ StatisticsPanelIndexNameName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexNameDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexNameLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexNameField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ StatisticsPanelIndexCreationName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexCreationDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexCreationLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexCreationField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper select',
+
+ StatisticsPanelIndexShardsName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexShardsDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexShardsLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexShardsField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ StatisticsPanelIndexReplicasName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexReplicasDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexReplicasLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexReplicasField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ //Logo Customization Panel
+ //Logo Customization Panel
+ logoPanelTitle: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel h2',
+
+ LogosCustomizationPanelLogoAppName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogoAppDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogoAppPatterLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogoAppPatterField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ LogosCustomizationPanelLogosSidebarName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogosSidebarDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogosSidebarLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogosSidebarField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ LogosCustomizationPanelLogoHealthCheckName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogoHealthCheckDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogoHealthCheckLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogoHealthCheckField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ LogosCustomizationPanelLogoReportName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogoReportDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogoReportLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogoReportField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/settings/logs.page.js b/test/cypress/cypress/integration/pageobjects/wzd/settings/logs.page.js
new file mode 100644
index 0000000000..162591be66
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/settings/logs.page.js
@@ -0,0 +1,6 @@
+export const LOGS_PAGE = {
+ logsTitle: 'div > .euiTitle',
+ logsContainer: 'div > .euiCodeBlock',
+ reloadLogsLink: '[name="SettingsLogs"] .euiPanel div.euiFlexItem > button > span > span',
+ logsTitleText: 'App log messages',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/settings/miscellaneous.page.js b/test/cypress/cypress/integration/pageobjects/wzd/settings/miscellaneous.page.js
new file mode 100644
index 0000000000..7edd153931
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/settings/miscellaneous.page.js
@@ -0,0 +1,5 @@
+export const MISCELLANEOUS_PAGE = {
+ runHealthChecksButton: 'div.euiFlexItem > div > div > button.euiButton',
+ healthCheckContainer: 'div.health-check',
+ successCheckIconList: 'p > span.euiToolTipAnchor > svg.euiIcon',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/settings/modules.page.js b/test/cypress/cypress/integration/pageobjects/wzd/settings/modules.page.js
new file mode 100644
index 0000000000..2628f3faaa
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/settings/modules.page.js
@@ -0,0 +1,13 @@
+export const MODULES_PAGE = {
+ amazonAWSToggleButton: ':nth-child(1) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ gCPToggleButton: ':nth-child(1) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ gitHubCardToggleButton: ':nth-child(1) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(6) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ openSCAPToggleButton: ':nth-child(2) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ cisCatToggleButton: ':nth-child(2) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ virusTotalToggleButton: ':nth-child(3) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(3) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ osqueryToggleButton: ':nth-child(3) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ dockerListenerToggleButton: ':nth-child(3) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ gDPRToggleButton: ':nth-child(4) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(3) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ hIPAAToggleButton: ':nth-child(4) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ tSCToggleButton: ':nth-child(4) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/settings/sample-data.page.js b/test/cypress/cypress/integration/pageobjects/wzd/settings/sample-data.page.js
new file mode 100644
index 0000000000..95d2e86ef3
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/settings/sample-data.page.js
@@ -0,0 +1,9 @@
+export const SAMPLE_DATA_PAGE = {
+ addSecurityInformationDataButton: 'div:nth-child(1) > div > div.euiCard__footer > div > div > button',
+ securityInformationDataTitle:'div:nth-child(1) > div > div.euiCard__content span',
+ addAuditingAndPolicyMonitoringDataButton: 'div:nth-child(2) > div > div.euiCard__footer > div > div > button',
+ auditingAndPolicyMonitoringDataTitle: 'div:nth-child(2) > div > div.euiCard__content span',
+ addThreatDetectionAndResponseDataButton: 'div:nth-child(3) > div > div.euiCard__footer > div > div > button',
+ threatDetectionAndResponseDataTitle: 'div:nth-child(3) > div > div.euiCard__content span',
+ dataAddedSuccessfullyToast: '.euiCard__betaBadgeWrapper',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/wazuh-menu/decoders.page.js b/test/cypress/cypress/integration/pageobjects/wzd/wazuh-menu/decoders.page.js
new file mode 100644
index 0000000000..062818895a
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/wazuh-menu/decoders.page.js
@@ -0,0 +1,20 @@
+export const DECODERS_PAGE = {
+ titleSelector: '[class="euiTitle euiTitle--medium"]',
+ tableSelector: '[class="euiTableRow customRowClass euiTableRow-isClickable"]',
+ dropdownPaginationSelector: '[data-test-subj="tablePaginationPopoverButton"]',
+ listPages: 'nav[class="euiPagination"]',
+ customDecodersButtonSelector: '.euiToggle__input',
+ manageDecodersFilesButtonSelector: '.euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Manage decoders")',
+ editDecoderButtonSelector: 'tr.euiTableRow:nth-child(1) .euiToolTipAnchor .euiButtonIcon[aria-label="Edit content"]',
+ saveDecoderButtonSelector: '.euiFlexGroup .euiFlexItem button.euiButton span.euiButtonContent span.euiButton__text:contains("Save")',
+ messageConfirmSaveSelector: '.euiText > span',
+ buttonRestartSelector: '.euiCallOut.euiCallOut--primary .euiButton.euiButton--primary',
+ firstCustomDecoder: '[data-test-subj="row-local_decoder_example"]',
+ xmlDecoderFile: '.euiFlexItem tr:nth-child(1) :nth-child(4) .euiTableCellContent .euiToolTipAnchor .euiLink:contains("local_decoder.xml")',
+ codeEditorSelector: '.euiFlexItem [data-test-subj="codeEditorContainer"]',
+ backButtonSelector: '.euiFlexGroup .euiFlexItem .euiToolTipAnchor .euiButtonIcon',
+ confirmModalSelector: '[data-test-subj="confirmModalTitleText"]',
+ createNewDecoderSelector:'.euiFlexGroup .euiFlexItem .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Add new decoders file")',
+ decoderTitleSelector: '.euiFlexItem .euiFlexGroup .euiFormControlLayout input.euiFieldText',
+ saveDecoderMessage: '.euiText span:contains("Changes will not take effect until a restart is performed.")'
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/wazuh-menu/groups-page.js b/test/cypress/cypress/integration/pageobjects/wzd/wazuh-menu/groups-page.js
new file mode 100644
index 0000000000..8b56b67a9a
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/wazuh-menu/groups-page.js
@@ -0,0 +1,6 @@
+export const GROUPS_PAGE = {
+ editGroups:'.euiBasicTable .euiTable--responsive :nth-child(4) .euiTableCellContent :nth-child(2)',
+ codeEditorSelector: '[data-test-subj="codeEditorContainer"]',
+ backButtonSelector: '.euiFlexGroup .euiFlexItem .euiToolTipAnchor .euiButtonIcon',
+ confirmModalSelector: '[data-test-subj="confirmModalTitleText"]'
+};
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/wazuh-menu/rules.page.js b/test/cypress/cypress/integration/pageobjects/wzd/wazuh-menu/rules.page.js
new file mode 100644
index 0000000000..3ec906908f
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/wazuh-menu/rules.page.js
@@ -0,0 +1,34 @@
+export const RULES_PAGE = {
+ rulesButtonSelector: '[class="euiSideNavItem euiSideNavItem--trunk"]',
+ titleSelector: '[class="euiTitle euiTitle--medium"]',
+ tableSelector: '[class="euiTableRow customRowClass euiTableRow-isClickable"]',
+ dropdownPaginationSelector: '[data-test-subj="tablePaginationPopoverButton"]',
+ listPagesSelector: 'nav[class="euiPagination"]',
+ customRulesButtonSelector: '.euiButtonGroup .euiButton.euiButton--text',
+ firstCustomRule: '[data-test-subj="row-100001"]',
+ xmlRuleFile:'.euiBasicTable .euiTable :nth-child(6) :nth-child(2) .euiToolTipAnchor .euiLink:contains("local_rules.xml")',
+ codeEditorSelector: '.euiFlexItem [data-test-subj="codeEditorContainer"]',
+ backButtonSelector: '.euiFlexGroup .euiFlexItem .euiToolTipAnchor .euiButtonIcon',
+ confirmModalSelector: '[data-test-subj="confirmModalTitleText"]',
+ createNewRulesSelector: '.euiFlexGroup .euiFlexItem .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Add new rules file")',
+ rulesTitleSelector:'.euiFlexItem .euiFlexGroup .euiFormControlLayout input.euiFieldText',
+ saveRulesButtonSelector: '.euiFlexGroup .euiFlexItem button.euiButton span.euiButtonContent span.euiButton__text:contains("Save")',
+ saveRulesMessage: '.euiText span:contains("Changes will not take effect until a restart is performed.")',
+ refreshButtonSelector: '.euiFlexGroup .euiFlexItem .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Refresh")',
+ rulestableSelector: '[name="WzManagement"] table tr',
+ rulesRowTableSelector: '[name="WzManagement"] tbody tr',
+ buttonListPageSelector: '[name="WzManagement"] button > span',
+ rulesFilterSelector: '.euiSuggestInput [placeholder="Filter or search"]',
+ dropdownFilterSelector: '.euiPanel.euiPopover__panel.euiPopover__panel--bottom',
+ filterLevelSelector: 'button:contains("level")',
+ filterNumberSelector: 'button:nth-child(0)',
+ filterLabelSelector: '.euiPopover.euiPopover--anchorDownLeft [data-testid="wz-search-badge-0"]',
+ paginatorSelector: '.euiBasicTable .euiPagination',
+ paginatorPreviousSelector: '[data-test-subj="pagination-button-previous"]',
+ paginatorNextSelector: '[data-test-subj="pagination-button-next"]',
+ paginatorFirstSelector: '.euiBasicTable .euiPagination li.euiPagination__item:first-child',
+ paginatorSecondSelector: '.euiBasicTable .euiPagination li.euiPagination__item:nth-child(2)',
+ paginatorthirdSelector: '.euiBasicTable .euiPagination li.euiPagination__item:nth-child(3)',
+ paginatorFourthSelector: '.euiBasicTable .euiPagination li.euiPagination__item:nth-child(4)',
+ paginatorLastSelector: '.euiBasicTable .euiPagination li.euiPagination__item:last-child',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/wzd/wazuh-menu/wazuh-menu.page.js b/test/cypress/cypress/integration/pageobjects/wzd/wazuh-menu/wazuh-menu.page.js
new file mode 100644
index 0000000000..1f8d860b2c
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/wzd/wazuh-menu/wazuh-menu.page.js
@@ -0,0 +1,81 @@
+export const WAZUH_MENU_PAGE = {
+ wazuhMenuLeft: '.wz-menu-left-side .wz-menu-sections',
+ wazuhMenuRight: '.wz-menu-right-side',
+ wazuhMenuSettingRight: '.wz-menu-right-side .WzManagementSideMenu',
+ wazuhMenuButton: '[data-test-subj=menuWazuhButton]',
+ //region Menu
+ //region Menu
+ modulesButton: '[data-test-subj=menuModulesButton]',
+ managementButton: '[data-test-subj=menuManagementButton]',
+ agentsButton: '[data-test-subj=menuAgentsButton]',
+ toolsButton: '[data-test-subj=menuToolsButton]',
+ securityButton: '[data-test-subj=menuSecurityButton]',
+ settingsButton: '[data-test-subj=menuSettingsButton]',
+ //endregion Menu
+ //region SubMenu
+ //region Modules
+ //endregion Menu
+ //region SubMenu
+ //region Modules
+ modulesDirectoryLink: '.wz-menu-right-side div.euiFlexGroup > div > button > span > span',
+ securityEventsLink: '[data-test-subj=menuModulesSecurityEventsLink]',
+ integrityMonitoringLink: '[data-test-subj=menuModulesFimLink]',
+ amazonAwsLink: '[data-test-subj=menuModulesAwsLink]',
+ googleCloudPlatformLink: '[data-test-subj=menuModulesGcpLink]',
+ policyMonitoringLink: '[data-test-subj=menuModulesPolicyMonitoringLink]',
+ systemAuditingLink: '[data-test-subj=menuModulesAuditLink]',
+ openScapLink: '[data-test-subj=menuModulesOpenScapLink]',
+ cisCatLink: '[data-test-subj=menuModulesCiscatLink]',
+ securityConfigurationAssessmentLink: '[data-test-subj=menuModulesScaLink]',
+ vulnerabilitiesLink: '[data-test-subj=menuModulesVulsLink]',
+ virusTotalLink: '[data-test-subj=menuModulesVirustotalLink]',
+ osqueryLink: '[data-test-subj=menuModulesOsqueryLink]',
+ dockerListenerLink: '[data-test-subj=menuModulesDockerLink]',
+ mitreAttackLink: '[data-test-subj=menuModulesMitreLink]',
+ pciDssLink: '[data-test-subj=menuModulesPciLink]',
+ gdprLink: '[data-test-subj=menuModulesGdprLink]',
+ hipaaLink: '[data-test-subj=menuModulesHipaaLink]',
+ nistLink: '[data-test-subj=menuModulesNistLink]',
+ tscLink: '[data-test-subj=menuModulesTscLink]',
+ //endregion
+ //region Management
+ //endregion
+ //region Management
+ rulesLink: '[data-test-subj=menuManagementRulesLink]',
+ decodersLink: '[data-test-subj=menuManagementDecodersLink]',
+ cdbListLink: '[data-test-subj=menuManagementCdbListsLink]',
+ groupsLink: '[data-test-subj=menuManagementGroupsLink]',
+ configurationLink: '[data-test-subj=menuManagementConfigurationLink]',
+ statusLink: '[data-test-subj=menuManagementStatusLink]',
+ clusterLink: '[data-test-subj=menuManagementMonitoringLink]',
+ statisticsLink: '[data-test-subj=menuManagementStatisticsLink]',
+ logsLink: '[data-test-subj=menuManagementLogsLink]',
+ reportingLink: '[data-test-subj=menuManagementReportingLink]',
+ //endregion
+ //region Tools
+ //endregion
+ //region Tools
+ apiConsoleLink: '[data-test-subj=menuToolsDevToolsLink]',
+ rulesetTestLink: '[data-test-subj=menuToolsLogtestLink]',
+ //endregion
+ //region Security
+ //endregion
+ //region Security
+ usersLink: '[data-test-subj=menuSecurityUsersLink]',
+ rolesLink: '[data-test-subj=menuSecurityRolesLink]',
+ policiesLink: '[data-test-subj=menuSecurityPoliciesLink]',
+ rolesMappingLink: '[data-test-subj=menuSecurityRoleMappingLink]',
+ //endregion
+ //region Settings
+ //endregion
+ //region Settings
+ settingsApiConfigurationLink: '[data-test-subj=menuSettingsApiLink]',
+ settingsModulesLink: '[data-test-subj=menuSettingsModulesLink]',
+ settingsSampleDataLink: '[data-test-subj=menuSettingsSampleDataLink]',
+ settingsConfigurationLink: '[data-test-subj=menuSettingsConfigurationLink]',
+ settingsLogsLink: '[data-test-subj=menuSettingsLogsLink]',
+ settingsMiscellaneousLink: '[data-test-subj=menuSettingsMiscellaneousLink]',
+ settingsAboutLink: '[data-test-subj=menuSettingsAboutLink]',
+ //endregion
+ //endregion
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/agents/agents.page.js b/test/cypress/cypress/integration/pageobjects/xpack/agents/agents.page.js
new file mode 100644
index 0000000000..f91a9c3d3a
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/agents/agents.page.js
@@ -0,0 +1,24 @@
+export const AGENTS_PAGE = {
+ firstAgentList: '[data-test-subj="row-001"]',
+ agSecurityEventsLink: '.WzManagementSideMenu [title="Security events"] div div',
+ agIntegrityMonitoringLink: '.WzManagementSideMenu [title="Integrity monitoring"] div div',
+ agSCALink: '.euiFlexItem.wz-module-header-agent-title > div > div:nth-child(4) button',
+ agSystemAuditingLink: '.WzManagementSideMenu [title="System Auditing"] div div',
+ agVulnerabilitiesLink: '.WzManagementSideMenu [title="Vulnerabilities"] div div',
+ agMitreAttackLink: '.WzManagementSideMenu [title="MITRE ATT&CK"] div div',
+ moreLink: '//*[contains(@class,"wz-module-header-agent-main")]//*/button//*/span[contains(text(),"More")]',
+ agPolicyMonitoring: '.WzManagementSideMenu [title="Policy Monitoring"] div div',
+ agPCIDSS: '.WzManagementSideMenu [title="PCI DSS"] div div',
+ agGDPR: '.WzManagementSideMenu [title="GDPR"] div div',
+ agHIPAA: '.WzManagementSideMenu [title="HIPAA"] div div',
+ agNIST: '.WzManagementSideMenu [title="NIST 800-53"] div div',
+ agTSC: '.WzManagementSideMenu [title="TSC"] div div',
+ statusChart: '.agents-status-pie > .euiPanel > .euiCard__content > .euiCard__children > .euiFlexGroup',
+ agentDetails: 'euiFlexItem euiFlexItem--flexGrowZero agents-details-card',
+ deployNewAgentButton: '//span[contains(text(),"Deploy new agent")]',
+ exploreAgentButton: '.wz-module-header-nav .euiFlexItem .euiToolTipAnchor .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Explore agent")',
+ firstAgentDisplayed: '.euiModal .euiTable .euiTableRow:nth-child(1)',
+ unPinnedAgentButton: '.wz-module-header-nav .euiFlexItem .euiToolTipAnchor .euiButtonIcon[aria-label="Unpin agent"]',
+ secundAgentDisplayed: '.euiModal .euiTable .euiTableRow:nth-child(2)',
+ agentID: '.euiModal .euiTable .euiTableRow:nth-child(1) .euiTableRowCell:nth-child(1) .euiTableCellContent__text',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/agents/deploy-new-agent.page.js b/test/cypress/cypress/integration/pageobjects/xpack/agents/deploy-new-agent.page.js
new file mode 100644
index 0000000000..664efa81cc
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/agents/deploy-new-agent.page.js
@@ -0,0 +1,35 @@
+export const DEPLOY_NEW_AGENT_PAGE = {
+ closeButton: "//span[contains(text(),'Close')]",
+ title: "[name='RegisterAgent'] h2",
+ deployNewAgentSections: "[name='RegisterAgent'] .euiStep",
+
+ operatingSystemSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(1) p",
+ redhatButton: '[data-text="Red Hat / CentOS"]',
+ debianUbuntuButton: '[data-text="Debian / Ubuntu"]',
+ windowsButton: '[data-text="Windows"]',
+ macOSButton: '[data-text="MacOS"]',
+
+ operationSystemTitle: "[name='RegisterAgent'] .euiStep:nth-child(1) .euiTitle",
+ operationSystemOption: "[name='RegisterAgent'] .euiStep:nth-child(1) fieldset label",
+
+ serverAddressSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(2) :nth-child(1) p.euiStep__title",
+ serverMessage: "[name='RegisterAgent'] .euiStep:nth-child(2) .euiStep__content p",
+ serverInputField: "[name='RegisterAgent'] .euiStep:nth-child(2) [placeholder='Server address']",
+
+ agentToGroupSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(3) .euiTitle",
+ agentToGroupMessage: "//*[@name='RegisterAgent']//*[3][contains(@class,'euiStep')]//*[contains(@class,'euiText')]/p", //cambiar a xpath
+ agentToGroupSelector: "[name='RegisterAgent'] .euiStep:nth-child(3) [data-test-subj='comboBoxInput']",
+
+ installAndEnrollAgentSubTitle: "[name='RegisterAgent'] .euiStep:nth-child(4) .euiTitle",
+ installAndEnrollAgentDefaultLabel: "[name='RegisterAgent'] .euiStep:nth-child(4) .euiCallOutHeader__title",
+ // after selected these OS options
+ installAndEnrollAgentCommand: "[name='RegisterAgent'] .euiStep:nth-child(5) .euiCodeBlock__line",
+ installAndEnrollAgentCopyButton: "[name='RegisterAgent'] .euiStep:nth-child(5) .copy-codeblock-wrapper .copy-overlay",
+
+ startTheAgentTitle: "[name='RegisterAgent'] .euiStep:nth-child(6) p",
+ startTheAgentTabsLabels: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content .euiTabs button",
+ systemmdTabButton: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content .euiTabs button:nth-child(1)",
+ sysVTabButton: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content .euiTabs button:nth-child(2)",
+ startTheAgentCommandText: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content [role='tabpanel'] .euiText pre",
+ startTheAgentcopyButton: "[name='RegisterAgent'] .euiStep:nth-child(6) .euiStep__content [role='tabpanel'] .euiText .copy-overlay",
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/filters/filters.page.js b/test/cypress/cypress/integration/pageobjects/xpack/filters/filters.page.js
new file mode 100644
index 0000000000..4ea46d9228
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/filters/filters.page.js
@@ -0,0 +1,17 @@
+export const FILTERS_PAGE = {
+ addFilterButton: '[data-test-subj="addFilter"]',
+ filterCard: '.euiPopover__panel-isOpen .euiFlexItem.euiFlexItem--flexGrowZero .euiForm',
+ filterSuggestionList: '[data-test-subj="filterFieldSuggestionList"]',
+ filterOperatorListObject:'[data-test-subj="comboBoxOptionsList filterOperatorList-optionsList"] [role="listBox"]',
+ filterOperatorList: '[data-test-subj="filterOperatorList"] [data-test-subj="comboBoxToggleListButton"]',
+ filterParams: '[data-test-subj="filterParams"]',
+ saveFilterButton: '[data-test-subj="saveFilter"]',
+ stablishedFilter: '[data-test-subj="filter filter-enabled filter-key-rule.level filter-value-7 filter-unpinned"',
+ pinFilterAction: '[data-test-subj="pinFilter"]',
+ selectedOperator: '[title="is"]',
+ SelectedOperatorIs:'[data-test-subj="comboBoxOptionsList filterOperatorList-optionsList"] button[title="is"]',
+ pinnedFilter: '[data-test-subj="filter filter-enabled filter-key-rule.level filter-value-7 filter-pinned"]',
+ eventsButton: '//*[contains(@class,"euiTabs")]//*[contains(text(),"Events")]',
+ removeFilterButton: '//*[contains(@class,"euiContextMenuPanel")]//*[contains(text(),"Delete")]',
+ operatorList: '.euiPanel[data-test-subj="comboBoxOptionsList filterOperatorList-optionsList"] .euiComboBoxOptionsList__rowWrap'
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/modules-directory.page.js b/test/cypress/cypress/integration/pageobjects/xpack/modules-directory.page.js
new file mode 100644
index 0000000000..cfd9ee32a9
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/modules-directory.page.js
@@ -0,0 +1,14 @@
+export const MODULES_DIRECTORY_PAGE = {
+ amazonAWSCard: '[data-test-subj="overviewWelcomeAws"]',
+ gCPCard: '[data-test-subj="overviewWelcomeGcp"]',
+ openSCAPCard: '[data-test-subj="overviewWelcomeOscap"]',
+ cisCatCard: '[data-test-subj="overviewWelcomeCiscat"]',
+ virusTotalCard: '[data-test-subj="overviewWelcomeVirustotal"]',
+ osqueryCard: '[data-test-subj="overviewWelcomeOsquery"]',
+ dockerListenerCard: '[data-test-subj="overviewWelcomeDocker"]',
+ gDPRCard: '[data-test-subj="overviewWelcomeGdpr"]',
+ hIPAACard: '[data-test-subj="overviewWelcomeHipaa"]',
+ tSCCard: '[data-test-subj="overviewWelcomeTsc"]',
+ gitHubCard: '[data-test-subj="overviewWelcomeGithub"]',
+ userLoginCard: '[data-test-subj="userMenuAvatar"]',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/overview/overview.page.js b/test/cypress/cypress/integration/pageobjects/xpack/overview/overview.page.js
new file mode 100644
index 0000000000..b3fbf7b52f
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/overview/overview.page.js
@@ -0,0 +1,14 @@
+export const OVERVIEW_PAGE = {
+ securityEvents: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Security events")]',
+ integrityMonitoring: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Integrity monitoring")]',
+ policyMonitoring: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Policy monitoring")]',
+ systemAuditing: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"System auditing")]',
+ securityInformationAssessment: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Security configuration assessment")]',
+ vulnerabilities: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"Vulnerabilities")]',
+ mitre: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"MITRE ATT&CK")]',
+ pciDSS: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"PCI DSS")]',
+ nist: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"NIST")]',
+ tsc: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"TSC")]',
+ gdpr: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"GDPR")]',
+ hipaa: '//*[contains(@class,"euiTitle euiTitle--small euiCard__title")]//*[contains(text(),"HIPAA")]',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/reporting/report.page.js b/test/cypress/cypress/integration/pageobjects/xpack/reporting/report.page.js
new file mode 100644
index 0000000000..cc697415fd
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/reporting/report.page.js
@@ -0,0 +1,6 @@
+export const REPORTING_PAGE = {
+ generateReportButton: '.wz-welcome-page-agent-tabs .euiFlexItem .euiFlexItem .euiButtonEmpty[type="button"] .euiButtonEmpty__text:contains("Generate report")',
+ reportGeneratedToast: '.euiToast',
+ lastCreatedReport: '.euiTable .euiTableRow:nth-child(1) .euiTableRowCell .euiTableCellContent .euiTableCellContent__text',
+ disableGenerateReportButton: '.wz-welcome-page-agent-tabs .euiFlexItem .euiToolTipAnchor button.euiButtonEmpty-isDisabled',
+};
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/settings/about.page.js b/test/cypress/cypress/integration/pageobjects/xpack/settings/about.page.js
new file mode 100644
index 0000000000..4e851f055a
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/settings/about.page.js
@@ -0,0 +1,19 @@
+export const ABOUT_PAGE = {
+ appVersionTitle: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(1)',
+ appVersionNumber: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(1) > span',
+
+ appRevisionTitle: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(2)',
+ appRevisionNumber: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(2) > span',
+
+ installDateTitle: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(3)',
+ installDateInformation: 'div.mainView > div > div:nth-child(3) > div > div:nth-child(1) > div > .wz-text-truncatable:nth-child(3) > span',
+
+ welcomingCard: 'div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(1) > div',
+ welcomingCardTitle: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(1) > div h2.euiTitle',
+
+ communityCard: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div',
+ communityCardTitle: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div h2.euiTitle',
+ communitySlackLink: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div :nth-child(1) .euiButtonIcon',
+ communityGoogleGroupLink: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div :nth-child(2) .euiButtonIcon',
+ communityGithubLink: ' div:nth-child(3) > div > div.euiFlexGroup > div:nth-child(2) > div :nth-child(3) .euiButtonIcon',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/settings/api-configuration.page.js b/test/cypress/cypress/integration/pageobjects/xpack/settings/api-configuration.page.js
new file mode 100644
index 0000000000..9dd489442f
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/settings/api-configuration.page.js
@@ -0,0 +1,10 @@
+export const API_CONFIGURATION_PAGE = {
+ checkConnectionButton: 'div:nth-child(2) > span > button',
+ connectionSuccessToast: '.euiToast--success',
+ addNewConnectionButton: 'react-component > div > div > div:nth-child(1) > div:nth-child(2) > button > span',
+ addNewConnectionModal: 'react-component > div > div.euiFlexItem.min-guide-width > div',
+ addNewConnectionModalTitle: 'div.euiFlexGroup--responsive > div:nth-child(1) > div > h2',
+ newConnectionModalCheckConnectionButton: 'div.euiStep__content > div > button.euiButton > span > span',
+ testConnectionCheckBox: 'div:nth-child(2) > div.euiStep__titleWrapper > p',
+ testConnectionCheckBoxMarked: 'div:nth-child(2) > div.euiStep__titleWrapper .euiStep__circle > svg',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/settings/configuration.page.js b/test/cypress/cypress/integration/pageobjects/xpack/settings/configuration.page.js
new file mode 100644
index 0000000000..56efbbddc6
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/settings/configuration.page.js
@@ -0,0 +1,197 @@
+export const CONFIGURATION_PAGE = {
+ settingTitle: 'div > h2.euiTitle',
+ settingToolTip: 'div > h2.euiTitle > .euiToolTipAnchor',
+ settingSubTitle: '.euiPage .euiFlexItem:nth-child(1) .euiFlexItem:nth-child(2) .euiText.euiText--medium',
+ settingSearchBox: '.euiPage .euiFlexItem:nth-child(1) .euiFlexItem:nth-child(2).euiSearchBar__searchHolder',
+ settingCategoriesButton: '.euiPage header .euiFlexItem .euiFilterGroup',
+ settingCategotiesPanel: '.euiPageBody .euiPanel',
+
+ //General Panel
+ //General Panel
+ generalPanelTitle: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel h2',
+
+ generalPanelIndexPatternName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ generalPanelIndexPatternDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelIndexPatternLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelIndexPatternField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelRequestTimeoutName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ generalPanelRequestTimeoutDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelRequestLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelRequestField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelIpSelectorName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ generalPanelIpSelectorDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelIpSelectorLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelIpSelectorField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ generalPanelIpIgnoreName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ generalPanelIpIgnoreDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelIpIgnoreLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelIpIgnoreField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper',
+
+ generalPanelCronPrefixName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ generalPanelCronPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelCronLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelCronField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelSamplePrefixName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ generalPanelSamplePrefixDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelSampleLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelSampleField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ generalPanelManagerAlertsPrefixName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) span',
+ generalPanelManagerAlertsPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelManagerAlertsLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelManagerAlertsField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ generalPanelLogLevelName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) span',
+ generalPanelLogLevelDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelLogLevelLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelLogLevelField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper select',
+
+ generalPanelEnrollmentName: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(1) span',
+ generalPanelEnrollmentDescription: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(1) .euiText',
+ generalPanelEnrollmentLabel: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ generalPanelEnrollmentField: '.euiPageBody .euiFlexItem:nth-child(1) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(9) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ //Health Check Panel
+ //Health Check Panel
+ healthCheckPanelTitle: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel h2',
+ healthCheckPanelIndexPatternPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelIndexPatternPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelIndexPatterLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelIndexPatterField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelIndexTemplatePrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelIndexTemplatePrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelIndexTemplateLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelIndexTemplateField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelApiConnectionPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelApiConnectionPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelApiConnectionLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelApiConnectionField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelApiVersionPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelApiVersionPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelApiVersionLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelApiVersionField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelKnowFieldsPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelKnowFieldsPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelKnowFieldsLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelKnowFieldsField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelRemoveMetaFieldsPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelRemoveMetaFieldsPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelRemoveMetaFieldsPrefixLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelRemoveMetaFieldsPrefixField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelSetBucketPrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelSetBucketPrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelSetBucketLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelSetBucketField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ healthCheckPanelSetTimePrefixName: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) span',
+ healthCheckPanelSetTimePrefixDescription: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(1) .euiText',
+ healthCheckPanelSetTimeLabel: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ healthCheckPanelSetTimeField: '.euiPageBody .euiFlexItem:nth-child(2) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(8) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ //Monitoring Panel
+ //Monitoring Panel
+ monitoringPanelTitle: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel h2',
+
+ monitoringPanelStatusName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ monitoringPanelStatusDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelStatusPatterLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelStatusPatterField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ monitoringPanelFrequencyName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ monitoringPanelFrequencyDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelFrequencyLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelFrequencyField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ monitoringPanelIndexShardsName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexShardsDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelIndexShardsLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexShardsField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ monitoringPanelIndexReplicasName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexReplicasDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelPanelIndexReplicasLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexReplicasField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ monitoringPanelIndexCreationName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexCreationDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelIndexCreationLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexCreationField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper select',
+
+ monitoringPanelIndexPatternName: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ monitoringPanelIndexPatternDescription: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ monitoringPanelIndexPatternLabel: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ monitoringPanelIndexPatternField: '.euiPageBody .euiFlexItem:nth-child(3) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ //Statistics Panel
+ //Statistics Panel
+ statisticsPanelTitle: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel h2',
+
+ StatisticsPanelStatusName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelStatusDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelStatusPatterLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelStatusPatterField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper button',
+
+ StatisticsPanelIncludesApisName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIncludesApisDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIncludesApisLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIncludesApisField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper',
+
+ StatisticsPanelIndexIntervalName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexIntervalDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexIntervalLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexIntervalField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ StatisticsPanelIndexNameName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexNameDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexNameLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexNameField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ StatisticsPanelIndexCreationName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexCreationDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexCreationLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexCreationField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(5) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper select',
+
+ StatisticsPanelIndexShardsName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexShardsDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexShardsLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexShardsField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(6) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ StatisticsPanelIndexReplicasName: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) span',
+ StatisticsPanelIndexReplicasDescription: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(1) .euiText',
+ StatisticsPanelIndexReplicasLabel: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ StatisticsPanelIndexReplicasField: '.euiPageBody .euiFlexItem:nth-child(4) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(7) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ //Logo Customization Panel
+ //Logo Customization Panel
+ logoPanelTitle: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel h2',
+
+ LogosCustomizationPanelLogoAppName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogoAppDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogoAppPatterLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogoAppPatterField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(1) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ LogosCustomizationPanelLogosSidebarName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogosSidebarDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogosSidebarLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogosSidebarField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(2) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ LogosCustomizationPanelLogoHealthCheckName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogoHealthCheckDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogoHealthCheckLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogoHealthCheckField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(3) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+
+ LogosCustomizationPanelLogoReportName: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) span',
+ LogosCustomizationPanelLogoReportDescription: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(1) .euiText',
+ LogosCustomizationPanelLogoReportLabel: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__label',
+ LogosCustomizationPanelLogoReportField: '.euiPageBody .euiFlexItem:nth-child(5) .euiPanel .euiForm .euiDescribedFormGroup:nth-child(4) .euiFlexItem:nth-child(2) .euiFormRow__fieldWrapper input',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/settings/logs.page.js b/test/cypress/cypress/integration/pageobjects/xpack/settings/logs.page.js
new file mode 100644
index 0000000000..8fb85d0bdd
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/settings/logs.page.js
@@ -0,0 +1,6 @@
+export const LOGS_PAGE = {
+ logsTitle: 'div > .euiTitle',
+ logsContainer: 'div > .euiCodeBlock',
+ reloadLogsLink: 'div.euiFlexItem > button > span > span',
+ logsTitleText: 'App log messages',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/settings/miscellaneous.page.js b/test/cypress/cypress/integration/pageobjects/xpack/settings/miscellaneous.page.js
new file mode 100644
index 0000000000..7edd153931
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/settings/miscellaneous.page.js
@@ -0,0 +1,5 @@
+export const MISCELLANEOUS_PAGE = {
+ runHealthChecksButton: 'div.euiFlexItem > div > div > button.euiButton',
+ healthCheckContainer: 'div.health-check',
+ successCheckIconList: 'p > span.euiToolTipAnchor > svg.euiIcon',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/settings/modules.page.js b/test/cypress/cypress/integration/pageobjects/xpack/settings/modules.page.js
new file mode 100644
index 0000000000..2628f3faaa
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/settings/modules.page.js
@@ -0,0 +1,13 @@
+export const MODULES_PAGE = {
+ amazonAWSToggleButton: ':nth-child(1) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ gCPToggleButton: ':nth-child(1) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ gitHubCardToggleButton: ':nth-child(1) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(6) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ openSCAPToggleButton: ':nth-child(2) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ cisCatToggleButton: ':nth-child(2) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ virusTotalToggleButton: ':nth-child(3) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(3) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ osqueryToggleButton: ':nth-child(3) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ dockerListenerToggleButton: ':nth-child(3) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ gDPRToggleButton: ':nth-child(4) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(3) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ hIPAAToggleButton: ':nth-child(4) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(4) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+ tSCToggleButton: ':nth-child(4) > .euiPanel > :nth-child(3) > :nth-child(1) > :nth-child(1) > :nth-child(5) > .euiFlexItem--flexGrowZero > .euiSwitch > button',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/settings/sample-data.page.js b/test/cypress/cypress/integration/pageobjects/xpack/settings/sample-data.page.js
new file mode 100644
index 0000000000..95d2e86ef3
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/settings/sample-data.page.js
@@ -0,0 +1,9 @@
+export const SAMPLE_DATA_PAGE = {
+ addSecurityInformationDataButton: 'div:nth-child(1) > div > div.euiCard__footer > div > div > button',
+ securityInformationDataTitle:'div:nth-child(1) > div > div.euiCard__content span',
+ addAuditingAndPolicyMonitoringDataButton: 'div:nth-child(2) > div > div.euiCard__footer > div > div > button',
+ auditingAndPolicyMonitoringDataTitle: 'div:nth-child(2) > div > div.euiCard__content span',
+ addThreatDetectionAndResponseDataButton: 'div:nth-child(3) > div > div.euiCard__footer > div > div > button',
+ threatDetectionAndResponseDataTitle: 'div:nth-child(3) > div > div.euiCard__content span',
+ dataAddedSuccessfullyToast: '.euiCard__betaBadgeWrapper',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/wazuh-menu/decoders.page.js b/test/cypress/cypress/integration/pageobjects/xpack/wazuh-menu/decoders.page.js
new file mode 100644
index 0000000000..8929f83db1
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/wazuh-menu/decoders.page.js
@@ -0,0 +1,20 @@
+export const DECODERS_PAGE = {
+ titleSelector: '[class="euiTitle euiTitle--medium"]',
+ tableSelector: '[class="euiTableRow customRowClass euiTableRow-isClickable"]',
+ dropdownPaginationSelector: '[data-test-subj="tablePaginationPopoverButton"]',
+ listPages: 'nav[class="euiPagination"]',
+ customDecodersButtonSelector: '[data-test-subj="Custom decoders"]',
+ manageDecodersFilesButtonSelector: '.euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Manage decoders")',
+ editDecoderButtonSelector: 'tr.euiTableRow:nth-child(1) .euiToolTipAnchor .euiButtonIcon[aria-label="Edit content"]',
+ saveDecoderButtonSelector: '.euiFlexGroup .euiFlexItem button.euiButton span.euiButtonContent span.euiButton__text:contains("Save")',
+ messageConfirmSaveSelector: '.euiText > span',
+ buttonRestartSelector: '.euiCallOut.euiCallOut--primary .euiButton.euiButton--primary',
+ firstCustomDecoder: '[data-test-subj="row-local_decoder_example"]',
+ xmlDecoderFile:':nth-child(4) .euiTableCellContent .euiToolTipAnchor .euiLink:contains("local_decoder.xml")',
+ codeEditorSelector: '[data-test-subj="codeEditorContainer"]',
+ backButtonSelector: '.euiFlexGroup .euiFlexItem .euiToolTipAnchor .euiButtonIcon',
+ confirmModalSelector: '[data-test-subj="confirmModalTitleText"]',
+ createNewDecoderSelector:'.euiFlexGroup .euiFlexItem .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Add new decoders file")',
+ decoderTitleSelector: '.euiFlexItem .euiFlexGroup .euiFormControlLayout input.euiFieldText',
+ saveDecoderMessage: '.euiText span:contains("Changes will not take effect until a restart is performed.")'
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/wazuh-menu/groups.page.js b/test/cypress/cypress/integration/pageobjects/xpack/wazuh-menu/groups.page.js
new file mode 100644
index 0000000000..55815aff56
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/wazuh-menu/groups.page.js
@@ -0,0 +1,6 @@
+export const GROUPS_PAGE = {
+ editGroups:'.euiBasicTable .euiTable--responsive :nth-child(4) .euiTableCellContent :nth-child(2)',
+ codeEditorSelector: '[data-test-subj="codeEditorContainer"]',
+ backButtonSelector: '.euiFlexGroup .euiFlexItem .euiToolTipAnchor .euiButtonIcon',
+ confirmModalSelector: '[data-test-subj="confirmModalTitleText"]'
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/wazuh-menu/rules.page.js b/test/cypress/cypress/integration/pageobjects/xpack/wazuh-menu/rules.page.js
new file mode 100644
index 0000000000..aadc91316a
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/wazuh-menu/rules.page.js
@@ -0,0 +1,34 @@
+export const RULES_PAGE = {
+ rulesButtonSelector: '[class="euiSideNavItem euiSideNavItem--trunk"]',
+ titleSelector: '[class="euiTitle euiTitle--medium"]',
+ tableSelector: '[class="euiTableRow customRowClass euiTableRow-isClickable"]',
+ dropdownPaginationSelector: '[data-test-subj="tablePaginationPopoverButton"]',
+ listPagesSelector: 'nav[class="euiPagination"]',
+ customRulesButtonSelector: '.euiButtonGroupButton.euiButtonGroupButton--text',
+ firstCustomRule: '[data-test-subj="row-100001"]',
+ xmlRuleFile:'.euiBasicTable .euiTable :nth-child(6) :nth-child(2) .euiToolTipAnchor .euiLink:contains("local_rules.xml")',
+ codeEditorSelector: '[data-test-subj="codeEditorContainer"]',
+ backButtonSelector: '.euiFlexGroup .euiFlexItem .euiToolTipAnchor .euiButtonIcon',
+ confirmModalSelector: '[data-test-subj="confirmModalTitleText"]',
+ createNewRulesSelector: '.euiFlexGroup .euiFlexItem .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Add new rules file")',
+ rulesTitleSelector:'.euiFlexItem .euiFlexGroup .euiFormControlLayout input.euiFieldText',
+ saveRulesButtonSelector: '.euiFlexGroup .euiFlexItem button.euiButton span.euiButtonContent span.euiButton__text:contains("Save")',
+ saveRulesMessage: '.euiText span:contains("Changes will not take effect until a restart is performed.")',
+ refreshButtonSelector: '.euiFlexGroup .euiFlexItem .euiButtonEmpty .euiButtonContent .euiButtonEmpty__text:contains("Refresh")',
+ rulestableSelector: '[name="WzManagement"] table tr',
+ rulesRowTableSelector: '[name="WzManagement"] tbody tr',
+ buttonListPageSelector: '[name="WzManagement"] button > span',
+ rulesFilterSelector: '.euiSuggestInput [placeholder="Filter or search"]',
+ dropdownFilterSelector: '.euiPanel.euiPopover__panel.euiPopover__panel--bottom',
+ filterLevelSelector: 'button:contains("level")',
+ filterNumberSelector: 'button:nth-child(0)',
+ filterLabelSelector: '.euiPopover.euiPopover--anchorDownLeft [data-testid="wz-search-badge-0"]',
+ paginatorSelector: '.euiBasicTable .euiPagination',
+ paginatorPreviousSelector: '[data-test-subj="pagination-button-previous"]',
+ paginatorNextSelector: '[data-test-subj="pagination-button-next"]',
+ paginatorFirstSelector: '.euiBasicTable .euiPagination li.euiPagination__item:first-child',
+ paginatorSecondSelector: '.euiBasicTable .euiPagination li.euiPagination__item:nth-child(2)',
+ paginatorthirdSelector: '.euiBasicTable .euiPagination li.euiPagination__item:nth-child(3)',
+ paginatorFourthSelector: '.euiBasicTable .euiPagination li.euiPagination__item:nth-child(4)',
+ paginatorLastSelector: '.euiBasicTable .euiPagination li.euiPagination__item:last-child',
+};
diff --git a/test/cypress/cypress/integration/pageobjects/xpack/wazuh-menu/wazuh-menu.page.js b/test/cypress/cypress/integration/pageobjects/xpack/wazuh-menu/wazuh-menu.page.js
new file mode 100644
index 0000000000..7119d9ff65
--- /dev/null
+++ b/test/cypress/cypress/integration/pageobjects/xpack/wazuh-menu/wazuh-menu.page.js
@@ -0,0 +1,81 @@
+export const WAZUH_MENU_PAGE = {
+ wazuhMenuLeft: '.wz-menu-left-side .wz-menu-sections',
+ wazuhMenuRight: '.wz-menu-right-side',
+ wazuhMenuSettingRight: '.wz-menu-right-side .WzManagementSideMenu',
+ wazuhMenuButton: '[data-test-subj=menuWazuhButton]',
+ //region Menu
+ //region Menu
+ modulesButton: '[data-test-subj=menuModulesButton]',
+ managementButton: '[data-test-subj=menuManagementButton]',
+ agentsButton: '[data-test-subj=menuAgentsButton]',
+ toolsButton: '[data-test-subj=menuToolsButton]',
+ securityButton: '[data-test-subj=menuSecurityButton]',
+ settingsButton: '[data-test-subj=menuSettingsButton]',
+ //endregion Menu
+ //region SubMenu
+ //region Modules
+ //endregion Menu
+ //region SubMenu
+ //region Modules
+ modulesDirectoryLink: '.wz-menu-right-side div.euiFlexGroup > div > button > span > span',
+ securityEventsLink: '[data-test-subj=menuModulesSecurityEventsLink]',
+ integrityMonitoringLink: '[data-test-subj=menuModulesFimLink]',
+ amazonAwsLink: '[data-test-subj=menuModulesAwsLink]',
+ googleCloudPlatformLink: '[data-test-subj=menuModulesGcpLink]',
+ policyMonitoringLink: '[data-test-subj=menuModulesPolicyMonitoringLink]',
+ systemAuditingLink: '[data-test-subj=menuModulesAuditLink]',
+ openScapLink: '[data-test-subj=menuModulesOpenScapLink]',
+ cisCatLink: '[data-test-subj=menuModulesCiscatLink]',
+ securityConfigurationAssessmentLink: '[data-test-subj=menuModulesScaLink]',
+ vulnerabilitiesLink: '[data-test-subj=menuModulesVulsLink]',
+ virusTotalLink: '[data-test-subj=menuModulesVirustotalLink]',
+ osqueryLink: '[data-test-subj=menuModulesOsqueryLink]',
+ dockerListenerLink: '[data-test-subj=menuModulesDockerLink]',
+ mitreAttackLink: '[data-test-subj=menuModulesMitreLink]',
+ pciDssLink: '[data-test-subj=menuModulesPciLink]',
+ gdprLink: '[data-test-subj=menuModulesGdprLink]',
+ hipaaLink: '[data-test-subj=menuModulesHipaaLink]',
+ nistLink: '[data-test-subj=menuModulesNistLink]',
+ tscLink: '[data-test-subj=menuModulesTscLink]',
+ //endregion
+ //region Management
+ //endregion
+ //region Management
+ rulesLink: '[data-test-subj=menuManagementRulesLink]',
+ decodersLink: '[data-test-subj=menuManagementDecodersLink]',
+ cdbListLink: '[data-test-subj=menuManagementCdbListsLink]',
+ groupsLink: '[data-test-subj=menuManagementGroupsLink]',
+ configurationLink: '[data-test-subj=menuManagementConfigurationLink]',
+ statusLink: '[data-test-subj=menuManagementStatusLink]',
+ clusterLink: '[data-test-subj=menuManagementMonitoringLink]',
+ statisticsLink: '[data-test-subj=menuManagementStatisticsLink]',
+ logsLink: '[data-test-subj=menuManagementLogsLink]',
+ reportingLink: '[data-test-subj=menuManagementReportingLink]',
+ //endregion
+ //region Tools
+ //endregion
+ //region Tools
+ apiConsoleLink: '[data-test-subj=menuToolsDevToolsLink]',
+ rulesetTestLink: '[data-test-subj=menuToolsLogtestLink]',
+ //endregion
+ //region Security
+ //endregion
+ //region Security
+ usersLink: '[data-test-subj=menuSecurityUsersLink]',
+ rolesLink: '[data-test-subj=menuSecurityRolesLink]',
+ policiesLink: '[data-test-subj=menuSecurityPoliciesLink]',
+ rolesMappingLink: '[data-test-subj=menuSecurityRoleMappingLink]',
+ //endregion
+ //region Settings
+ //endregion
+ //region Settings
+ settingsApiConfigurationLink: '[data-test-subj=menuSettingsApiLink]',
+ settingsModulesLink: '.wz-menu-right-side .WzManagementSideMenu [data-test-subj=menuSettingsModulesLink]',
+ settingsSampleDataLink: '[data-test-subj=menuSettingsSampleDataLink]',
+ settingsConfigurationLink: '[data-test-subj=menuSettingsConfigurationLink]',
+ settingsLogsLink: '[data-test-subj=menuSettingsLogsLink]',
+ settingsMiscellaneousLink: '[data-test-subj=menuSettingsMiscellaneousLink]',
+ settingsAboutLink: '[data-test-subj=menuSettingsAboutLink]',
+ //endregion
+ //endregion
+};
diff --git a/test/cypress/cypress/integration/step-definitions/agents/The-user-selects-a-deploy-new-agent.and.js b/test/cypress/cypress/integration/step-definitions/agents/The-user-selects-a-deploy-new-agent.and.js
new file mode 100644
index 0000000000..8f2764eea8
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/agents/The-user-selects-a-deploy-new-agent.and.js
@@ -0,0 +1,10 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElementByXpath, xpathElementIsVisible, getSelector } from '../../utils/driver';
+
+import { AGENTS_PAGE as pageName} from '../../utils/pages-constants';
+const deployNewAgentButton = getSelector('deployNewAgentButton', pageName);
+
+When('The user selects a deploy new agent', () => {
+ xpathElementIsVisible(deployNewAgentButton);
+ clickElementByXpath(deployNewAgentButton);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/agents/first-step.then.js b/test/cypress/cypress/integration/step-definitions/agents/first-step.then.js
new file mode 100644
index 0000000000..79d723f666
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/agents/first-step.then.js
@@ -0,0 +1,23 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import {
+ elementIsVisible,
+ xpathElementIsVisible,
+ checkInformationElement,
+ getSelector,
+} from '../../utils/driver';
+
+import { DEPLOY_NEW_AGENT_PAGE as pageName} from '../../utils/pages-constants';
+const operationSystemTitle = getSelector('operationSystemTitle', pageName);
+const operationSystemOption = getSelector('operationSystemOption', pageName);
+const closeButton = getSelector('closeButton', pageName);
+
+Then('A first step {string} is displayed and the following {string} options', (title, option) => {
+ elementIsVisible(operationSystemTitle);
+ elementIsVisible(operationSystemOption);
+ checkInformationElement(operationSystemTitle, title, 1);
+ checkInformationElement(operationSystemOption, option, 4);
+});
+
+Then('An X button in the top right is displayed', () => {
+ xpathElementIsVisible(closeButton);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/agents/fourth-step.then.js b/test/cypress/cypress/integration/step-definitions/agents/fourth-step.then.js
new file mode 100644
index 0000000000..badcf0e964
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/agents/fourth-step.then.js
@@ -0,0 +1,13 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, checkInformationElement, getSelector } from '../../utils/driver';
+
+import { DEPLOY_NEW_AGENT_PAGE as pageName} from '../../utils/pages-constants';
+const installAndEnrollAgentSubTitle = getSelector('installAndEnrollAgentSubTitle', pageName);
+const installAndEnrollAgentDefaultLabel = getSelector('installAndEnrollAgentDefaultLabel', pageName);
+
+Then('A fourth step {string} with the {string} by default is displayed', (title, message) => {
+ elementIsVisible(installAndEnrollAgentSubTitle);
+ elementIsVisible(installAndEnrollAgentDefaultLabel);
+ checkInformationElement(installAndEnrollAgentSubTitle, title, 1);
+ checkInformationElement(installAndEnrollAgentDefaultLabel, message, 1);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/agents/second-step.then.js b/test/cypress/cypress/integration/step-definitions/agents/second-step.then.js
new file mode 100644
index 0000000000..4d0a223503
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/agents/second-step.then.js
@@ -0,0 +1,16 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, checkInformationElement, getSelector } from '../../utils/driver';
+
+import { DEPLOY_NEW_AGENT_PAGE as pageName} from '../../utils/pages-constants';
+const serverAddressSubTitle = getSelector('serverAddressSubTitle', pageName);
+const serverMessage = getSelector('serverMessage', pageName);
+const serverInputField = getSelector('serverInputField', pageName);
+
+When('A second step {string} with the {string} are displayed and the following {string} by default', (subtitleSecond, descriptionsSecond, secondInformation) => {
+ elementIsVisible(serverAddressSubTitle);
+ elementIsVisible(serverMessage);
+ elementIsVisible(serverInputField);
+ checkInformationElement(serverAddressSubTitle, subtitleSecond, 1);
+ checkInformationElement(serverMessage, descriptionsSecond, 1);
+ checkInformationElement(serverInputField, secondInformation, 1);
+});
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/agents/steps-config-agent-page.and.js b/test/cypress/cypress/integration/step-definitions/agents/steps-config-agent-page.and.js
new file mode 100644
index 0000000000..7f20f9827b
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/agents/steps-config-agent-page.and.js
@@ -0,0 +1,9 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { getElement, getSelector } from '../../utils/driver';
+
+import { DEPLOY_NEW_AGENT_PAGE as pageName} from '../../utils/pages-constants';
+const deployNewAgentSections = getSelector('deployNewAgentSections', pageName);
+
+Then('A box with four steps to the different settings is displayed', () => {
+ getElement(deployNewAgentSections).its('length').should('eq', 4)
+});
diff --git a/test/cypress/cypress/integration/step-definitions/agents/the-browser-is-on-the-new-deploy-agent-page.then.js b/test/cypress/cypress/integration/step-definitions/agents/the-browser-is-on-the-new-deploy-agent-page.then.js
new file mode 100644
index 0000000000..584ae428b3
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/agents/the-browser-is-on-the-new-deploy-agent-page.then.js
@@ -0,0 +1,9 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, getSelector } from '../../utils/driver';
+
+import { DEPLOY_NEW_AGENT_PAGE as pageName} from '../../utils/pages-constants';
+const deployNewAgentSections = getSelector('deployNewAgentSections', pageName);
+
+Then('The browser is on the new deploy agent page', () => {
+ elementIsVisible(deployNewAgentSections);
+});
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/agents/third-step.then.js b/test/cypress/cypress/integration/step-definitions/agents/third-step.then.js
new file mode 100644
index 0000000000..4bc0a20cc5
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/agents/third-step.then.js
@@ -0,0 +1,17 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible,xpathElementIsVisible, xpathCheckInformationElement, checkInformationElement, getSelector } from '../../utils/driver';
+
+import { DEPLOY_NEW_AGENT_PAGE as pageName} from '../../utils/pages-constants';
+const agentToGroupSubTitle = getSelector('agentToGroupSubTitle', pageName);
+const agentToGroupMessage = getSelector('agentToGroupMessage', pageName);
+const agentToGroupSelector = getSelector('agentToGroupSelector', pageName);
+
+Then('A third step {string} with the {string} are displayed and the following drop-down with Select group by default {string}', (title, discription, information) => {
+ elementIsVisible(agentToGroupSubTitle);
+ xpathElementIsVisible(agentToGroupMessage);
+ elementIsVisible(agentToGroupSelector);
+ checkInformationElement(agentToGroupSubTitle, title, 1);
+ xpathCheckInformationElement(agentToGroupMessage, discription, 1);
+ //TODO: skip WZD because on this UI the "agentToGroupSelector" is disable combo-box
+ if (Cypress.env('type') != 'wzd') {checkInformationElement(agentToGroupSelector, information, 1)};
+});
diff --git a/test/cypress/cypress/integration/step-definitions/filters/The-user-types-particular-search.when.js b/test/cypress/cypress/integration/step-definitions/filters/The-user-types-particular-search.when.js
new file mode 100644
index 0000000000..d8f8e3c0fd
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/The-user-types-particular-search.when.js
@@ -0,0 +1,10 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { fillField, elementIsVisible, getSelector, forceEnter} from '../../utils/driver';
+import { FILTERS_PAGE as pageName} from '../../utils/pages-constants';
+const searchInputSelector = getSelector('searchInputSelector', pageName);
+
+When('The user types a particular search {} on the search bar', (key) => {
+ elementIsVisible(searchInputSelector);
+ fillField(searchInputSelector, key);
+ forceEnter(searchInputSelector);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/filters/filters-are-displayed-in-agents-modules.and.js b/test/cypress/cypress/integration/step-definitions/filters/filters-are-displayed-in-agents-modules.and.js
new file mode 100644
index 0000000000..c6fa107793
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/filters-are-displayed-in-agents-modules.and.js
@@ -0,0 +1,9 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, getSelector} from '../../utils/driver';
+
+import { FILTERS_PAGE as pageName} from '../../utils/pages-constants';
+const stablishedFilter = getSelector('stablishedFilter', pageName);
+
+Then('The user check filter label is added', () => {
+ elementIsVisible(stablishedFilter);
+ });
diff --git a/test/cypress/cypress/integration/step-definitions/filters/nav-to-the-agent-page.when.js b/test/cypress/cypress/integration/step-definitions/filters/nav-to-the-agent-page.when.js
new file mode 100644
index 0000000000..c98dbbb1b5
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/nav-to-the-agent-page.when.js
@@ -0,0 +1,12 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector} from '../../utils/driver';
+
+import { WAZUH_MENU_PAGE as pageName} from '../../utils/pages-constants';
+const wazuhMenuButton = getSelector('wazuhMenuButton', pageName);
+const agentsButton = getSelector('agentsButton', pageName);
+
+When('The user navigates to the agent page', () => {
+ clickElement(wazuhMenuButton);
+ elementIsVisible(agentsButton);
+ clickElement(agentsButton);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/filters/navigate-agent-dashboard.when.js b/test/cypress/cypress/integration/step-definitions/filters/navigate-agent-dashboard.when.js
new file mode 100644
index 0000000000..20311a2c0b
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/navigate-agent-dashboard.when.js
@@ -0,0 +1,12 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector} from '../../utils/driver';
+
+import { AGENTS_PAGE as pageName} from '../../utils/pages-constants';
+const firstAgentList = getSelector('firstAgentList', pageName);
+const statusChart = getSelector('statusChart', pageName);
+
+When('The user navigates to the agent dashboard', () => {
+ elementIsVisible(statusChart);
+ elementIsVisible(firstAgentList);
+ clickElement(firstAgentList);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/filters/navigate-to-agent-module.when.js b/test/cypress/cypress/integration/step-definitions/filters/navigate-to-agent-module.when.js
new file mode 100644
index 0000000000..b3e9cdfb95
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/navigate-to-agent-module.when.js
@@ -0,0 +1,13 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, xpathElementIsVisible, clickElementByXpath, forceClickElement, getSelector} from '../../utils/driver';
+
+import { AGENTS_PAGE as pageName, AGENT_MODULES} from '../../utils/pages-constants';
+const moreLink = getSelector('moreLink', pageName);
+
+When('The user navigates to agentModule {}', (moduleName) => {
+ xpathElementIsVisible(moreLink);
+ clickElementByXpath(moreLink);
+ elementIsVisible(getSelector(moduleName, AGENT_MODULES));
+ forceClickElement(getSelector(moduleName, AGENT_MODULES));
+ });
+
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/filters/navigate-to-modules.when.js b/test/cypress/cypress/integration/step-definitions/filters/navigate-to-modules.when.js
new file mode 100644
index 0000000000..5d0c380ac9
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/navigate-to-modules.when.js
@@ -0,0 +1,15 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { xpathElementIsVisible, forceClickElementByXpath, getSelector, forceClickElement, elementIsVisible} from '../../utils/driver';
+
+import { BASIC_MODULES} from '../../utils/pages-constants';
+import { WAZUH_MENU_PAGE as pageName} from '../../utils/pages-constants';
+const wazuhMenuButton = getSelector('wazuhMenuButton', pageName);
+When('The user goes to {}', (moduleName) => {
+
+ cy.wait(500);
+ elementIsVisible(wazuhMenuButton);
+ cy.wait(500);
+ forceClickElement(wazuhMenuButton);
+ xpathElementIsVisible(getSelector(moduleName, BASIC_MODULES));
+ forceClickElementByXpath(getSelector(moduleName, BASIC_MODULES));
+});
diff --git a/test/cypress/cypress/integration/step-definitions/filters/the-query-is-accepted.then.js b/test/cypress/cypress/integration/step-definitions/filters/the-query-is-accepted.then.js
new file mode 100644
index 0000000000..50c71bde7d
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/the-query-is-accepted.then.js
@@ -0,0 +1,8 @@
+import { Then } from "cypress-cucumber-preprocessor/steps";
+import { elementIsNotVisible, getSelector } from '../../utils/driver';
+import { FILTERS_PAGE as pageName} from '../../utils/pages-constants';
+const noResultMessage = getSelector('noResultMessage', pageName);
+
+Then('The query is accepted and the results should be displayed', () => {
+ elementIsNotVisible(noResultMessage)
+})
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/filters/the-user-adds-a-new-filter.when.js b/test/cypress/cypress/integration/step-definitions/filters/the-user-adds-a-new-filter.when.js
new file mode 100644
index 0000000000..fd2059ae6f
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/the-user-adds-a-new-filter.when.js
@@ -0,0 +1,36 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, fillField, elementIsVisible, getSelector, forceClickElement, forceEnter} from '../../utils/driver';
+import { FILTERS_PAGE as pageName} from '../../utils/pages-constants';
+const addFilterButton = getSelector('addFilterButton', pageName);
+const filterSuggestionList = getSelector('filterSuggestionList', pageName);
+const filterOperatorList = getSelector('filterOperatorList', pageName);
+const filterParams = getSelector('filterParams', pageName);
+const saveFilterButton = getSelector('saveFilterButton', pageName);
+const selectedOperator = getSelector('selectedOperator', pageName);
+const SelectedOperatorIs = getSelector('SelectedOperatorIs', pageName);
+const operatorList = getSelector('operatorList', pageName);
+const filterCard = getSelector('filterCard', pageName);
+const filterOperatorListObject = getSelector('filterOperatorListObject', pageName);
+
+
+When('The user adds a new filter', () => {
+ //+ Add Filter
+ elementIsVisible(addFilterButton);
+ clickElement(addFilterButton);
+ //Card
+ elementIsVisible(filterCard);
+ elementIsVisible(filterSuggestionList);
+ fillField(filterSuggestionList,'rule.level');
+ forceEnter(filterSuggestionList);
+ elementIsVisible(filterOperatorList);
+ forceClickElement(filterOperatorList);
+ cy.wait(100);
+ elementIsVisible(operatorList);
+ elementIsVisible(filterOperatorListObject);
+ cy.wait(150);
+ cy.get(SelectedOperatorIs).click({force:true});
+ elementIsVisible(filterParams);
+ clickElement(filterParams);
+ fillField(filterParams,'7')
+ clickElement(saveFilterButton);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/filters/the-user-checks-filter-apply-all-modules.then.js b/test/cypress/cypress/integration/step-definitions/filters/the-user-checks-filter-apply-all-modules.then.js
new file mode 100644
index 0000000000..98470cd111
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/the-user-checks-filter-apply-all-modules.then.js
@@ -0,0 +1,11 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import {getElement, getSelector} from '../../utils/driver';
+import { FILTERS_PAGE as pageName} from '../../utils/pages-constants';
+const pinnedFilter = getSelector('pinnedFilter', pageName);
+
+Then('The user checks if the filter is displayed', () => {
+ getElement(pinnedFilter)
+ .should('exist')
+ .should('be.visible');
+ });
+
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/filters/the-user-checks-filter-is-not-displayed.then.js b/test/cypress/cypress/integration/step-definitions/filters/the-user-checks-filter-is-not-displayed.then.js
new file mode 100644
index 0000000000..d8aa9be9c3
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/the-user-checks-filter-is-not-displayed.then.js
@@ -0,0 +1,8 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsNotVisible, getSelector} from '../../utils/driver';
+import { FILTERS_PAGE as pageName} from '../../utils/pages-constants';
+const stablishedFilter = getSelector('stablishedFilter', pageName);
+
+Then('The user checks filter label is not added', () => {
+ elementIsNotVisible(stablishedFilter);
+ });
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/filters/the-user-checks-filter-label-is-added.then.js b/test/cypress/cypress/integration/step-definitions/filters/the-user-checks-filter-label-is-added.then.js
new file mode 100644
index 0000000000..232ce02574
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/the-user-checks-filter-label-is-added.then.js
@@ -0,0 +1,8 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, getSelector} from '../../utils/driver';
+import { FILTERS_PAGE as pageName} from '../../utils/pages-constants';
+const stablishedFilter = getSelector('stablishedFilter', pageName);
+
+Then('The user checks filter label is added', () => {
+ elementIsVisible(stablishedFilter);
+ });
diff --git a/test/cypress/cypress/integration/step-definitions/filters/the-user-go-to-the-events-page.when.js b/test/cypress/cypress/integration/step-definitions/filters/the-user-go-to-the-events-page.when.js
new file mode 100644
index 0000000000..43865d76b3
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/the-user-go-to-the-events-page.when.js
@@ -0,0 +1,10 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElementByXpath, xpathElementIsVisible, getSelector} from '../../utils/driver';
+import { FILTERS_PAGE as pageName} from '../../utils/pages-constants';
+const eventsButton = getSelector('eventsButton', pageName);
+
+When('The user moves to events page', () => {
+ xpathElementIsVisible(eventsButton);
+ clickElementByXpath(eventsButton);
+});
+
diff --git a/test/cypress/cypress/integration/step-definitions/filters/the-user-navigates-to-the-overview-page.when.js b/test/cypress/cypress/integration/step-definitions/filters/the-user-navigates-to-the-overview-page.when.js
new file mode 100644
index 0000000000..c87db2e401
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/the-user-navigates-to-the-overview-page.when.js
@@ -0,0 +1,15 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector} from '../../utils/driver';
+import { WAZUH_MENU_PAGE as pageName} from '../../utils/pages-constants';
+const wazuhMenuButton = getSelector('wazuhMenuButton', pageName);
+const modulesDirectoryLink = getSelector('modulesDirectoryLink', pageName);
+const modulesButton = getSelector('modulesButton', pageName);
+
+When('The user navigates overview page', () => {
+ elementIsVisible(wazuhMenuButton);
+ clickElement(wazuhMenuButton);
+ elementIsVisible(modulesButton);
+ clickElement(modulesButton);
+ elementIsVisible(modulesDirectoryLink);
+ clickElement(modulesDirectoryLink);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/filters/the-user-pins-a-filter.when.js b/test/cypress/cypress/integration/step-definitions/filters/the-user-pins-a-filter.when.js
new file mode 100644
index 0000000000..cac4c78985
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/the-user-pins-a-filter.when.js
@@ -0,0 +1,16 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector} from '../../utils/driver';
+import { FILTERS_PAGE as pageName} from '../../utils/pages-constants';
+const stablishedFilter = getSelector('stablishedFilter', pageName);
+const pinFilterAction = getSelector('pinFilterAction', pageName);
+const pinnedFilter = getSelector('pinnedFilter', pageName);
+
+When('The user pins a filter', () => {
+ cy.wait(500);
+ elementIsVisible(stablishedFilter);
+ clickElement(stablishedFilter);
+ elementIsVisible(pinFilterAction);
+ clickElement(pinFilterAction);
+ elementIsVisible(pinnedFilter);
+ });
+
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/filters/the-user-removes-applied-filter-on-agent.when.js b/test/cypress/cypress/integration/step-definitions/filters/the-user-removes-applied-filter-on-agent.when.js
new file mode 100644
index 0000000000..778664937f
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/the-user-removes-applied-filter-on-agent.when.js
@@ -0,0 +1,12 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, xpathElementIsVisible, clickElement, getSelector} from '../../utils/driver';
+import { FILTERS_PAGE as pageName} from '../../utils/pages-constants';
+const removeFilterButton = getSelector('removeFilterButton', pageName);
+const stablishedFilter = getSelector('stablishedFilter', pageName);
+
+When('The user removes the applied filter on the agent page', () => {
+ elementIsVisible(stablishedFilter);
+ clickElement(stablishedFilter);
+ xpathElementIsVisible(removeFilterButton);
+ clickElement(removeFilterButton);
+})
diff --git a/test/cypress/cypress/integration/step-definitions/filters/the-user-removes-the-applied-filter.when.js b/test/cypress/cypress/integration/step-definitions/filters/the-user-removes-the-applied-filter.when.js
new file mode 100644
index 0000000000..11ae39ffbd
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/the-user-removes-the-applied-filter.when.js
@@ -0,0 +1,12 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, xpathElementIsVisible, clickElement, clickElementByXpath, getSelector} from '../../utils/driver';
+import { FILTERS_PAGE as pageName} from '../../utils/pages-constants';
+const removeFilterButton = getSelector('removeFilterButton', pageName);
+const stablishedFilter = getSelector('stablishedFilter', pageName);
+
+When('The user removes the applied filter', () => {
+ elementIsVisible(stablishedFilter);
+ clickElement(stablishedFilter);
+ xpathElementIsVisible(removeFilterButton);
+ clickElementByXpath(removeFilterButton);
+})
diff --git a/test/cypress/cypress/integration/step-definitions/filters/the-user-unppined-the-selected-filter-when.js b/test/cypress/cypress/integration/step-definitions/filters/the-user-unppined-the-selected-filter-when.js
new file mode 100644
index 0000000000..50b8e202b7
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/filters/the-user-unppined-the-selected-filter-when.js
@@ -0,0 +1,15 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, clickElement, getSelector} from '../../utils/driver';
+import { FILTERS_PAGE as pageName} from '../../utils/pages-constants';
+const pinnedFilter = getSelector('pinnedFilter', pageName);
+const unPinFilterAction = getSelector('unPinFilterAction', pageName);
+
+
+When('The user unpins the selected filter', () => {
+ elementIsVisible(pinnedFilter);
+ cy.wait(1000);
+ clickElement(pinnedFilter);
+ cy.wait(1000);
+ elementIsVisible(unPinFilterAction);
+ clickElement(unPinFilterAction);
+})
diff --git a/test/cypress/cypress/integration/step-definitions/login/login-basic.js b/test/cypress/cypress/integration/step-definitions/login/login-basic.js
new file mode 100644
index 0000000000..ecd28c6dff
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/login/login-basic.js
@@ -0,0 +1,3 @@
+export const loginBasic = () => {
+ //placeholder if we ever need login logic with basic authentication
+};
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/login/login-odfe.js b/test/cypress/cypress/integration/step-definitions/login/login-odfe.js
new file mode 100644
index 0000000000..47348ae5e6
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/login/login-odfe.js
@@ -0,0 +1,29 @@
+import { ODFE_PASSWORD, ODFE_USERNAME } from '../../utils/login-constants';
+import {
+ buttonSubmitSelector,
+ inputPasswordSelector,
+ inputUsernameSelector,
+} from '../../pageobjects/login/odef-login.page';
+import { clickElement, fillField } from '../../utils/driver';
+
+const fillUsernameFieldODFE = (userName) => {
+ fillField(inputUsernameSelector, userName);
+ return this;
+};
+
+const fillPasswordFieldODFE = (password) => {
+ fillField(inputPasswordSelector, password);
+ return this;
+};
+
+const clickSubmitButtonODFE = () => {
+ clickElement(buttonSubmitSelector);
+};
+
+const loginOdfe = () => {
+ fillUsernameFieldODFE(ODFE_USERNAME);
+ fillPasswordFieldODFE(ODFE_PASSWORD);
+ clickSubmitButtonODFE();
+};
+
+export { loginOdfe };
diff --git a/test/cypress/cypress/integration/step-definitions/login/login-wzd.js b/test/cypress/cypress/integration/step-definitions/login/login-wzd.js
new file mode 100644
index 0000000000..afc12500b9
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/login/login-wzd.js
@@ -0,0 +1,29 @@
+import { WZD_PASSWORD, WZD_USERNAME } from '../../utils/login-constants';
+import {
+ buttonSubmitSelector,
+ inputPasswordSelector,
+ inputUsernameSelector,
+} from '../../pageobjects/login/wzd-login.page';
+import { clickElement, fillField } from '../../utils/driver';
+
+const fillUsernameFieldWzd = (userName) => {
+ fillField(inputUsernameSelector, userName);
+ return this;
+};
+
+const fillPasswordFieldWzd = (password) => {
+ fillField(inputPasswordSelector, password);
+ return this;
+};
+
+const clickSubmitButtonWzd = () => {
+ clickElement(buttonSubmitSelector);
+};
+
+const loginWzd = () => {
+ fillUsernameFieldWzd(WZD_USERNAME);
+ fillPasswordFieldWzd(WZD_PASSWORD);
+ clickSubmitButtonWzd();
+};
+
+export { loginWzd };
diff --git a/test/cypress/cypress/integration/step-definitions/login/login-xpack.js b/test/cypress/cypress/integration/step-definitions/login/login-xpack.js
new file mode 100644
index 0000000000..8acbd34f45
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/login/login-xpack.js
@@ -0,0 +1,29 @@
+import { XPACK_PASSWORD, XPACK_USERNAME } from '../../utils/login-constants';
+import {
+ buttonSubmitSelector,
+ inputPasswordSelector,
+ inputUsernameSelector,
+} from '../../pageobjects/login/xpack-login.page';
+import { clickElement, fillField } from '../../utils/driver';
+
+const fillUsernameFieldXPack = (userName) => {
+ fillField(inputUsernameSelector, userName);
+ return this;
+};
+
+const fillPasswordFieldXPack = (password) => {
+ fillField(inputPasswordSelector, password);
+ return this;
+};
+
+const clickSubmitButtonXPack = () => {
+ clickElement(buttonSubmitSelector);
+};
+
+const loginXpack = () => {
+ fillUsernameFieldXPack(XPACK_USERNAME);
+ fillPasswordFieldXPack(XPACK_PASSWORD);
+ clickSubmitButtonXPack();
+};
+
+export { loginXpack };
diff --git a/test/cypress/cypress/integration/step-definitions/management/decoders/navigate-to-decoders.when.js b/test/cypress/cypress/integration/step-definitions/management/decoders/navigate-to-decoders.when.js
new file mode 100644
index 0000000000..d783238474
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/decoders/navigate-to-decoders.when.js
@@ -0,0 +1,15 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector } from '../../../utils/driver';
+import { WAZUH_MENU_PAGE as pageName} from '../../../utils/pages-constants';
+const decodersLink = getSelector('decodersLink', pageName);
+const wazuhMenuButton = getSelector('wazuhMenuButton', pageName);
+const managementButton = getSelector('managementButton', pageName);
+
+When('The user navigates to decoders', () => {
+ elementIsVisible(wazuhMenuButton);
+ clickElement(wazuhMenuButton);
+ elementIsVisible(managementButton);
+ clickElement(managementButton);
+ elementIsVisible(decodersLink);
+ clickElement(decodersLink);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/decoders/the-confirm-modal-is-displayed-then.js b/test/cypress/cypress/integration/step-definitions/management/decoders/the-confirm-modal-is-displayed-then.js
new file mode 100644
index 0000000000..be56dec55b
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/decoders/the-confirm-modal-is-displayed-then.js
@@ -0,0 +1,8 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, getSelector } from '../../../utils/driver';
+import { DECODERS_PAGE as pageName} from '../../../utils/pages-constants';
+const confirmModalSelector = getSelector('confirmModalSelector', pageName);
+
+Then('The informative modal is displayed', () => {
+ elementIsVisible(confirmModalSelector);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/decoders/the-saved-message-its-displayed-then.js b/test/cypress/cypress/integration/step-definitions/management/decoders/the-saved-message-its-displayed-then.js
new file mode 100644
index 0000000000..c71e82cba4
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/decoders/the-saved-message-its-displayed-then.js
@@ -0,0 +1,10 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, getSelector } from '../../../utils/driver';
+import { DECODERS_PAGE as pageName} from '../../../utils/pages-constants';
+const saveDecoderMessage = getSelector('saveDecoderMessage', pageName);
+const buttonRestartSelector = getSelector('buttonRestartSelector', pageName);
+
+Then('The save message its displayed', () => {
+ elementIsVisible(saveDecoderMessage);
+ elementIsVisible(buttonRestartSelector);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-clicks-decoders-save-button-when.js b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-clicks-decoders-save-button-when.js
new file mode 100644
index 0000000000..ba2c915199
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-clicks-decoders-save-button-when.js
@@ -0,0 +1,9 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector } from '../../../utils/driver';
+import { DECODERS_PAGE as pageName} from '../../../utils/pages-constants';
+const saveDecoderButtonSelector = getSelector('saveDecoderButtonSelector', pageName);
+
+When('The user saves the decoder', () => {
+ elementIsVisible(saveDecoderButtonSelector);
+ clickElement(saveDecoderButtonSelector);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-clicks-the-new-decoder-option-when.js b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-clicks-the-new-decoder-option-when.js
new file mode 100644
index 0000000000..0d4db62a23
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-clicks-the-new-decoder-option-when.js
@@ -0,0 +1,9 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector } from '../../../utils/driver';
+import { DECODERS_PAGE as pageName} from '../../../utils/pages-constants';
+const createNewDecoderSelector = getSelector('createNewDecoderSelector', pageName);
+
+When('The user clicks the new decoders button', () => {
+ elementIsVisible(createNewDecoderSelector);
+ clickElement(createNewDecoderSelector);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-creates-a-new-decoder-when.js b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-creates-a-new-decoder-when.js
new file mode 100644
index 0000000000..0990c0201c
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-creates-a-new-decoder-when.js
@@ -0,0 +1,12 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { fillField, elementIsVisible, getSelector, generateRandomName } from '../../../utils/driver';
+import { DECODERS_PAGE as pageName} from '../../../utils/pages-constants';
+const decoderTitleSelector = getSelector('decoderTitleSelector', pageName);
+const codeEditorSelector = getSelector('codeEditorSelector', pageName);
+const testXmlText = '^wazuh2: ';
+
+When('The user writes a new decoder', () => {
+ elementIsVisible(decoderTitleSelector);
+ fillField(decoderTitleSelector,generateRandomName());
+ fillField(codeEditorSelector,testXmlText);
+});
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-edit-the-selected-decoder-when.js b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-edit-the-selected-decoder-when.js
new file mode 100644
index 0000000000..304c654205
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-edit-the-selected-decoder-when.js
@@ -0,0 +1,10 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector, fillField } from '../../../utils/driver';
+import { DECODERS_PAGE as pageName} from '../../../utils/pages-constants';
+const codeEditorSelector = getSelector('codeEditorSelector', pageName);
+
+When('The user modify the selected decoders', () => {
+ elementIsVisible(codeEditorSelector);
+ clickElement(codeEditorSelector);
+ fillField(codeEditorSelector,"Test");
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-exit-without-saving-decoder-when.js b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-exit-without-saving-decoder-when.js
new file mode 100644
index 0000000000..ba5a1681ff
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-exit-without-saving-decoder-when.js
@@ -0,0 +1,9 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector } from '../../../utils/driver';
+import { DECODERS_PAGE as pageName} from '../../../utils/pages-constants';
+const backButtonSelector = getSelector('backButtonSelector', pageName);
+
+When('The user tries to exit edit decoders page without saving data', () => {
+ elementIsVisible(backButtonSelector);
+ clickElement(backButtonSelector);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-press-button-custom-decoders.when.js b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-press-button-custom-decoders.when.js
new file mode 100644
index 0000000000..95bcdb281c
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-press-button-custom-decoders.when.js
@@ -0,0 +1,15 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, getSelector, getElement, elementIsVisible } from '../../../utils/driver';
+import { DECODERS_PAGE as pageName} from '../../../utils/pages-constants';
+const customDecodersButtonSelector = getSelector('customDecodersButtonSelector', pageName);
+
+When('The user clicks the custom decoders button', () => {
+ if(Cypress.env('type') == 'wzd'){
+ cy.wait(1500);
+ getElement(customDecodersButtonSelector).check()
+ }
+ else {
+ elementIsVisible(customDecodersButtonSelector);
+ clickElement(customDecodersButtonSelector);
+ }
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-presses-the-edit-decoder-button-and-edits-it.when.js b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-presses-the-edit-decoder-button-and-edits-it.when.js
new file mode 100644
index 0000000000..f639f98ac5
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-presses-the-edit-decoder-button-and-edits-it.when.js
@@ -0,0 +1,15 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement ,elementIsVisible, getSelector } from '../../../utils/driver';
+import { DECODERS_PAGE as pageName} from '../../../utils/pages-constants';
+const editDecoderButtonSelector = getSelector('editDecoderButtonSelector', pageName);
+const manageDecodersFilesButtonSelector = getSelector('manageDecodersFilesButtonSelector', pageName);
+const saveDecoderButtonSelector = getSelector('saveDecoderButtonSelector', pageName);
+
+When('The user presses the edit decoders button and edits it', () => {
+ elementIsVisible(manageDecodersFilesButtonSelector);
+ clickElement(manageDecodersFilesButtonSelector);
+ elementIsVisible(editDecoderButtonSelector);
+ clickElement(editDecoderButtonSelector);
+ elementIsVisible(saveDecoderButtonSelector);
+ clickElement(saveDecoderButtonSelector);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-selects-a-custom-decoder-when.js b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-selects-a-custom-decoder-when.js
new file mode 100644
index 0000000000..cd77a14e65
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-selects-a-custom-decoder-when.js
@@ -0,0 +1,12 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector } from '../../../utils/driver';
+import { DECODERS_PAGE as pageName } from '../../../utils/pages-constants';
+const firstCustomDecoder = getSelector('firstCustomDecoder', pageName);
+const xmlDecoderFile = getSelector('xmlDecoderFile', pageName);
+
+When('The user selects a custom decoders to edit', () => {
+ elementIsVisible(firstCustomDecoder);
+ clickElement(firstCustomDecoder);
+ elementIsVisible(xmlDecoderFile);
+ clickElement(xmlDecoderFile);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-should-see-the-decoders.then.js b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-should-see-the-decoders.then.js
new file mode 100644
index 0000000000..f2e825bf7c
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-should-see-the-decoders.then.js
@@ -0,0 +1,21 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { getElement, getSelector } from '../../../utils/driver';
+import { DECODERS_PAGE as pageName} from '../../../utils/pages-constants';
+const titleSelector = getSelector('titleSelector', pageName);
+const tableSelector = getSelector('tableSelector', pageName);
+const dropdownPaginationSelector = getSelector('dropdownPaginationSelector', pageName);
+const listPages = getSelector('listPages', pageName);
+
+Then('The user should see the decoders', () => {
+ getElement(titleSelector)
+ .should('exist')
+ .should('contain', 'Decoders');
+ getElement(tableSelector)
+ .should('exist');
+ getElement(dropdownPaginationSelector)
+ .should('exist')
+ .should('be.visible');
+ getElement(listPages)
+ .should('exist')
+ .should('be.visible');
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-should-see-the-message.then.js b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-should-see-the-message.then.js
new file mode 100644
index 0000000000..273d3b434c
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/decoders/the-user-should-see-the-message.then.js
@@ -0,0 +1,13 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { getElement, getSelector } from '../../../utils/driver';
+import { DECODERS_PAGE as pageName} from '../../../utils/pages-constants';
+const buttonRestartSelector = getSelector('buttonRestartSelector', pageName);
+const messageConfirmSaveSelector = getSelector('messageConfirmSaveSelector', pageName);
+
+Then('The user should see the message', () => {
+ getElement(messageConfirmSaveSelector)
+ .should('have.text', 'Changes will not take effect until a restart is performed.');
+ getElement(buttonRestartSelector)
+ .should('exist')
+ .should('be.visible');
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/groups/the-confirm-modal-is-displayed-then.js b/test/cypress/cypress/integration/step-definitions/management/groups/the-confirm-modal-is-displayed-then.js
new file mode 100644
index 0000000000..6275153f49
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/groups/the-confirm-modal-is-displayed-then.js
@@ -0,0 +1,8 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, getSelector } from '../../../utils/driver';
+import { GROUPS_PAGE as pageName} from '../../../utils/pages-constants';
+const confirmModalSelector = getSelector('confirmModalSelector', pageName);
+
+Then('The informative modal is displayed', () => {
+ elementIsVisible(confirmModalSelector);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/groups/the-user-click-edit-groups-option-when.js b/test/cypress/cypress/integration/step-definitions/management/groups/the-user-click-edit-groups-option-when.js
new file mode 100644
index 0000000000..65e7b18911
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/groups/the-user-click-edit-groups-option-when.js
@@ -0,0 +1,9 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement ,elementIsVisible, getSelector } from '../../../utils/driver';
+import {GROUPS_PAGE as pageName} from '../../../utils/pages-constants';
+const editGroups = getSelector('editGroups', pageName);
+
+When('The user selects a group to edit', () => {
+ elementIsVisible(editGroups);
+ clickElement(editGroups);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/groups/the-user-edits-the-selected-group-configuration-when.js b/test/cypress/cypress/integration/step-definitions/management/groups/the-user-edits-the-selected-group-configuration-when.js
new file mode 100644
index 0000000000..0fc409bd0b
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/groups/the-user-edits-the-selected-group-configuration-when.js
@@ -0,0 +1,10 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector, fillField } from '../../../utils/driver';
+import { GROUPS_PAGE as pageName} from '../../../utils/pages-constants';
+const codeEditorSelector = getSelector('codeEditorSelector', pageName);
+
+When('The user modify the selected group', () => {
+ elementIsVisible(codeEditorSelector);
+ clickElement(codeEditorSelector);
+ fillField(codeEditorSelector,"Test");
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/groups/the-user-exit-edit-page-without-saving-changes-when.js b/test/cypress/cypress/integration/step-definitions/management/groups/the-user-exit-edit-page-without-saving-changes-when.js
new file mode 100644
index 0000000000..7b0dfb3f76
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/groups/the-user-exit-edit-page-without-saving-changes-when.js
@@ -0,0 +1,9 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector } from '../../../utils/driver';
+import { GROUPS_PAGE as pageName} from '../../../utils/pages-constants';
+const backButtonSelector = getSelector('backButtonSelector', pageName);
+
+When('The user tries to exit edit groups page without saving data', () => {
+ elementIsVisible(backButtonSelector);
+ clickElement(backButtonSelector);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/groups/the-user-navigates-to-groups-when.js b/test/cypress/cypress/integration/step-definitions/management/groups/the-user-navigates-to-groups-when.js
new file mode 100644
index 0000000000..b1ffe30ec7
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/groups/the-user-navigates-to-groups-when.js
@@ -0,0 +1,15 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector } from '../../../utils/driver';
+import { WAZUH_MENU_PAGE as pageName} from '../../../utils/pages-constants';
+const groupsLink = getSelector('groupsLink', pageName);
+const wazuhMenuButton = getSelector('wazuhMenuButton', pageName);
+const managementButton = getSelector('managementButton', pageName);
+
+When('The user navigates to groups page', () => {
+ elementIsVisible(wazuhMenuButton);
+ clickElement(wazuhMenuButton);
+ elementIsVisible(managementButton);
+ clickElement(managementButton);
+ elementIsVisible(groupsLink);
+ clickElement(groupsLink);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/The-user-clicks-on-the-page-when.js b/test/cypress/cypress/integration/step-definitions/management/rules/The-user-clicks-on-the-page-when.js
new file mode 100644
index 0000000000..035d219988
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/The-user-clicks-on-the-page-when.js
@@ -0,0 +1,40 @@
+import { Then, When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector } from '../../../utils/driver';
+import { RULES_PAGE as pageName } from '../../../utils/pages-constants';
+const paginatorSelector = getSelector('paginatorSelector', pageName);
+const paginatorSecondSelector = getSelector('paginatorSecondSelector', pageName);
+const paginatorNextSelector = getSelector('paginatorNextSelector', pageName);
+const paginatorPreviousSelector = getSelector('paginatorPreviousSelector', pageName);
+const paginatorFirstSelector = getSelector('paginatorFirstSelector', pageName);
+
+When('The user clicks on the {} page button', (page) => {
+ let selector;
+ elementIsVisible(paginatorSelector);
+ switch (page) {
+ case 'first':
+ selector = paginatorFirstSelector;
+ break;
+ case 'second':
+ selector = paginatorSecondSelector;
+ break;
+ case 'next':
+ selector = paginatorNextSelector;
+ break;
+ case 'previous':
+ selector = paginatorPreviousSelector;
+ break;
+ default:
+ throw new Error(`The page ${page} is not defined`);
+ }
+ clickElement(selector);
+ cy.wait(3000);
+});
+
+
+
+
+
+
+
+
+
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/a-maximum-rules-are-displayed-then.js b/test/cypress/cypress/integration/step-definitions/management/rules/a-maximum-rules-are-displayed-then.js
new file mode 100644
index 0000000000..a30fe0e6ad
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/a-maximum-rules-are-displayed-then.js
@@ -0,0 +1,13 @@
+import { Then } from "cypress-cucumber-preprocessor/steps";
+import { getSelector, elementIsVisible } from "../../../utils/driver";
+import { RULES_PAGE as pageName } from '../../../utils/pages-constants';
+const dropdownPaginationSelector = getSelector('dropdownPaginationSelector', pageName);
+const rulesRowTableSelector = getSelector('rulesRowTableSelector', pageName);
+
+Then('a maximum of {} rows of rules are displayed per page', (countRulesPerPage) => {
+ elementIsVisible(dropdownPaginationSelector);
+ elementIsVisible(rulesRowTableSelector);
+ cy.get(rulesRowTableSelector).then(($list) => {
+ expect($list.length).to.equal(parseInt(countRulesPerPage));
+ });
+});
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/a-new-set-of-rules-displayed.when.js b/test/cypress/cypress/integration/step-definitions/management/rules/a-new-set-of-rules-displayed.when.js
new file mode 100644
index 0000000000..394bf843c2
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/a-new-set-of-rules-displayed.when.js
@@ -0,0 +1,10 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, getSelector } from '../../../utils/driver';
+import { RULES_PAGE as pageName } from '../../../utils/pages-constants';
+const paginatorSelector = getSelector('paginatorSelector', pageName);
+
+
+When('A new set of rules is displayed', () => {
+ cy.wait(2500);
+ elementIsVisible(paginatorSelector);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/navigate-to-rules.when.js b/test/cypress/cypress/integration/step-definitions/management/rules/navigate-to-rules.when.js
new file mode 100644
index 0000000000..3849c5a38a
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/navigate-to-rules.when.js
@@ -0,0 +1,16 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, validateURLIncludes, getSelector } from '../../../utils/driver';
+import { WAZUH_MENU_PAGE as pageName} from '../../../utils/pages-constants';
+const managementButton = getSelector('managementButton', pageName);
+const wazuhMenuButton = getSelector('wazuhMenuButton', pageName);
+const rulesLink = getSelector('rulesLink', pageName);
+
+When('The user navigates to rules', () => {
+ elementIsVisible(wazuhMenuButton);
+ clickElement(wazuhMenuButton);
+ elementIsVisible(managementButton);
+ clickElement(managementButton);
+ elementIsVisible(rulesLink);
+ clickElement(rulesLink);
+ validateURLIncludes('/manager/?tab=rules');
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-confirm-modal-is-displayed-then.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-confirm-modal-is-displayed-then.js
new file mode 100644
index 0000000000..e5e60b6504
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-confirm-modal-is-displayed-then.js
@@ -0,0 +1,8 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, getSelector } from '../../../utils/driver';
+import { RULES_PAGE as pageName} from '../../../utils/pages-constants';
+const confirmModalSelector = getSelector('confirmModalSelector', pageName);
+
+Then('The informative modal is displayed', () => {
+ elementIsVisible(confirmModalSelector);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-filter-label-is-displayed.then.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-filter-label-is-displayed.then.js
new file mode 100644
index 0000000000..03d9ee3198
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-filter-label-is-displayed.then.js
@@ -0,0 +1,14 @@
+
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, getSelector, getElement } from '../../../utils/driver';
+import { RULES_PAGE as pageName} from '../../../utils/pages-constants';
+const filterLabelSelector = getSelector('filterLabelSelector', pageName);
+
+
+Then('The filter label is displayed on the filter bar with the correct {}', (condition) => {
+ elementIsVisible(filterLabelSelector);
+ getElement(filterLabelSelector).then(($el) => {
+ expect($el.text()).to.equal("level: "+condition);
+ })
+
+});
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-filtered-label-is-still-visible-then.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-filtered-label-is-still-visible-then.js
new file mode 100644
index 0000000000..5680eb8f68
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-filtered-label-is-still-visible-then.js
@@ -0,0 +1,11 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, getSelector, getElement } from '../../../utils/driver';
+import { RULES_PAGE as pageName} from '../../../utils/pages-constants';
+const filterLabelSelector = getSelector('filterLabelSelector', pageName);
+
+Then('The filtered label {} is still visible', (condition) => {
+ elementIsVisible(filterLabelSelector);
+ getElement(filterLabelSelector).then(($el) => {
+ expect($el.text()).to.equal("level: "+condition);
+ })
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-first-page-is-displayed-then.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-first-page-is-displayed-then.js
new file mode 100644
index 0000000000..063cbf699a
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-first-page-is-displayed-then.js
@@ -0,0 +1,16 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { getSelector } from '../../../utils/driver';
+import { RULES_PAGE as pageName } from '../../../utils/pages-constants';
+const rulestableSelector = getSelector('rulestableSelector', pageName);
+
+Then('The first page of rules is displayed', () => {
+ cy.wait(1500);
+ cy.get(rulestableSelector).then(($rules) => {
+ const rulesText = $rules.text();
+ cy.log(rulesText);
+ cy.get('@listRulesText').then(($e) => {
+ expect(rulesText).to.be.equals($e);
+ })
+ })
+
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-page-button-disable.then.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-page-button-disable.then.js
new file mode 100644
index 0000000000..6f6dbc1e5a
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-page-button-disable.then.js
@@ -0,0 +1,11 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { getSelector } from '../../../utils/driver';
+import { RULES_PAGE as pageName } from '../../../utils/pages-constants';
+const paginatorNextSelector = getSelector('paginatorNextSelector', pageName);
+const paginatorPreviousSelector = getSelector('paginatorPreviousSelector', pageName);
+
+
+Then('The {} page button should be disabled',(positionPage) => {
+ cy.wait(2000);
+ (positionPage == 'next') ? cy.get(paginatorNextSelector).should('have.attr', 'disabled') : cy.get(paginatorPreviousSelector).should('have.attr', 'disabled');
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-rule-page-is-available.then.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-rule-page-is-available.then.js
new file mode 100644
index 0000000000..2d7e9458aa
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-rule-page-is-available.then.js
@@ -0,0 +1,16 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, getSelector, elementIsVisible } from '../../../utils/driver';
+import { RULES_PAGE as pageName } from '../../../utils/pages-constants';
+const paginatorFirstSelector = getSelector('paginatorFirstSelector', pageName);
+const paginatorLastSelector = getSelector('paginatorLastSelector', pageName);
+
+Then('The rule page is the {} available page', (page) => {
+ if (page == 'first') {
+ elementIsVisible(paginatorFirstSelector)
+ clickElement(paginatorFirstSelector)
+ } else {
+ elementIsVisible(paginatorLastSelector);
+ clickElement(paginatorLastSelector);
+ }
+ cy.wait(2000);
+});
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-rule-page-is-not-available.when.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-rule-page-is-not-available.when.js
new file mode 100644
index 0000000000..ce014e3aaf
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-rule-page-is-not-available.when.js
@@ -0,0 +1,9 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { getSelector } from '../../../utils/driver';
+import { RULES_PAGE as pageName } from '../../../utils/pages-constants';
+const paginatorFirstSelector = getSelector('paginatorFirstSelector', pageName);
+const paginatorLastSelector = getSelector('paginatorLastSelector', pageName);
+
+When('The rule page is not the {} available', (page) => {
+ (page == 'first') ? cy.get(paginatorFirstSelector).should('not.have.attr', 'disabled') : cy.get(paginatorLastSelector).should('not.have.attr', 'disabled');
+})
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-save-message-its-displayed-then.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-save-message-its-displayed-then.js
new file mode 100644
index 0000000000..6b6c097275
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-save-message-its-displayed-then.js
@@ -0,0 +1,9 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector} from '../../../utils/driver';
+import { RULES_PAGE as pageName} from '../../../utils/pages-constants';
+const saveRulesMessage = getSelector('saveRulesMessage', pageName);
+
+Then('The save message its displayed', () => {
+ elementIsVisible(saveRulesMessage);
+ clickElement(saveRulesMessage);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-can-see-the-rule-then.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-can-see-the-rule-then.js
new file mode 100644
index 0000000000..f820e3a95a
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-can-see-the-rule-then.js
@@ -0,0 +1,13 @@
+import { Then } from "cypress-cucumber-preprocessor/steps";
+
+
+Then('The user can see the rules that match with the {}', (condition) => {
+ cy.get('table tbody td:nth-child(5)')
+ .should(($el) => {
+ let values = Cypress._.map($el, 'innerText');
+ expect(values).to.include(condition);
+ }).then(($) => {
+ expect($.length).to.be.greaterThan(0);
+
+ })
+})
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-click-limit-row-when.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-click-limit-row-when.js
new file mode 100644
index 0000000000..d485299c5e
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-click-limit-row-when.js
@@ -0,0 +1,15 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { getSelector, elementIsVisible, clickElement } from "../../../utils/driver";
+import { RULES_PAGE as pageName } from '../../../utils/pages-constants';
+const dropdownPaginationSelector = getSelector('dropdownPaginationSelector', pageName);
+
+When('The user click the limit selector for {} rows', (countRulesPerPage) => {
+ clickElement(dropdownPaginationSelector);
+ let locator = '.euiContextMenuPanel [data-test-subj="tablePagination-'+countRulesPerPage+'-rows"]';
+ elementIsVisible(locator);
+ clickElement(locator);
+ cy.wait(2000);
+ cy.get(dropdownPaginationSelector).find('.euiButtonEmpty__text').then(($list) => {
+ cy.wrap($list).contains('Rows per page: ' + countRulesPerPage);
+ });
+ });
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-clicks-the-refresh-button-when.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-clicks-the-refresh-button-when.js
new file mode 100644
index 0000000000..4aa6da2814
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-clicks-the-refresh-button-when.js
@@ -0,0 +1,37 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector } from '../../../utils/driver';
+import { RULES_PAGE as pageName } from '../../../utils/pages-constants';
+const refreshButtonSelector = getSelector('refreshButtonSelector', pageName);
+const titleSelector = getSelector('titleSelector', pageName);
+const rulestableSelector = getSelector('rulestableSelector', pageName);
+const dropdownPaginationSelector = getSelector('dropdownPaginationSelector', pageName);
+const listPagesSelector = getSelector('listPagesSelector', pageName);
+const customRulesButtonSelector = getSelector('customRulesButtonSelector', pageName);
+const createNewRulesSelector = getSelector('createNewRulesSelector', pageName);
+const buttonListPageSelector = getSelector('buttonListPageSelector', pageName);
+
+
+When('The user clicks the refresh button', () => {
+ elementIsVisible(titleSelector);
+ elementIsVisible(rulestableSelector);
+ elementIsVisible(dropdownPaginationSelector);
+ elementIsVisible(listPagesSelector);
+ elementIsVisible(customRulesButtonSelector);
+ elementIsVisible(createNewRulesSelector);
+ elementIsVisible(refreshButtonSelector);
+ elementIsVisible(buttonListPageSelector);
+ cy.get(titleSelector).invoke('text').as('title');
+ cy.get(rulestableSelector).then(($e) =>{
+ cy.wrap($e.length).as('rulesLength');
+ })
+ cy.get(dropdownPaginationSelector).invoke('text').as('paginationRows');
+ cy.get(listPagesSelector).invoke('text').as('paginationPages');
+ cy.get(customRulesButtonSelector).invoke('text').as('customRules');
+ cy.get(createNewRulesSelector).invoke('text').as('createNewRules');
+ cy.get(refreshButtonSelector).invoke('text').as('refreshButton');
+ cy.get(buttonListPageSelector).then(($e) =>{
+ cy.wrap($e.length).as('buttonLength');
+ });
+ clickElement(refreshButtonSelector);
+ cy.wait(1500);
+});
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-clicks-the-search-bar-when.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-clicks-the-search-bar-when.js
new file mode 100644
index 0000000000..67383be499
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-clicks-the-search-bar-when.js
@@ -0,0 +1,21 @@
+
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector, fillField } from '../../../utils/driver';
+import { RULES_PAGE as pageName} from '../../../utils/pages-constants';
+const rulesFilterSelector = getSelector('rulesFilterSelector', pageName);
+const dropdownFilterSelector = getSelector('dropdownFilterSelector', pageName);
+const filterLevelSelector = getSelector('filterLevelSelector', pageName);
+const filterNumberSelector = getSelector('filterNumberSelector', pageName);
+
+When('The user search a rule by Level {}', (condition) => {
+ let value = parseInt(condition) + 1;
+ let filterNumberSelectorNew = filterNumberSelector.replace('0', value);
+ elementIsVisible(rulesFilterSelector);
+ clickElement(rulesFilterSelector);
+ elementIsVisible(dropdownFilterSelector);
+ clickElement(dropdownFilterSelector+' '+filterLevelSelector);
+ cy.wait(500);
+ elementIsVisible(dropdownFilterSelector+' '+filterNumberSelectorNew);
+ clickElement(dropdownFilterSelector+' '+filterNumberSelectorNew);
+ cy.wait(500);
+});
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-creates-a-new-rule-when.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-creates-a-new-rule-when.js
new file mode 100644
index 0000000000..c99ad8b00f
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-creates-a-new-rule-when.js
@@ -0,0 +1,9 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector} from '../../../utils/driver';
+import { RULES_PAGE as pageName} from '../../../utils/pages-constants';
+const createNewRulesSelector = getSelector('createNewRulesSelector', pageName);
+
+When('The user clicks the new rules button', () => {
+ elementIsVisible(createNewRulesSelector);
+ clickElement(createNewRulesSelector);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-edit-the-selected-rule-when.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-edit-the-selected-rule-when.js
new file mode 100644
index 0000000000..2d261f0906
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-edit-the-selected-rule-when.js
@@ -0,0 +1,10 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector, fillField } from '../../../utils/driver';
+import { RULES_PAGE as pageName} from '../../../utils/pages-constants';
+const codeEditorSelector = getSelector('codeEditorSelector', pageName);
+
+When('The user modify the selected rule', () => {
+ elementIsVisible(codeEditorSelector);
+ clickElement(codeEditorSelector);
+ fillField(codeEditorSelector,"Test");
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-exit-without-saving-rule-when.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-exit-without-saving-rule-when.js
new file mode 100644
index 0000000000..00d9a1034c
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-exit-without-saving-rule-when.js
@@ -0,0 +1,10 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector } from '../../../utils/driver';
+import { RULES_PAGE as pageName} from '../../../utils/pages-constants';
+const backButtonSelector = getSelector('backButtonSelector', pageName);
+
+When('The user tries to exit create rules page without saving data', () => {
+ elementIsVisible(backButtonSelector);
+ clickElement(backButtonSelector);
+});
+
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-navigates-to-custom-rules-when.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-navigates-to-custom-rules-when.js
new file mode 100644
index 0000000000..7a45c088c2
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-navigates-to-custom-rules-when.js
@@ -0,0 +1,10 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import "cypress-real-events/support";
+import { clickElement, elementIsVisible, getSelector } from '../../../utils/driver';
+import { RULES_PAGE as pageName} from '../../../utils/pages-constants';
+const customRulesButtonSelector = getSelector('customRulesButtonSelector', pageName);
+
+When('The user clicks the custom rules button', () => {
+ elementIsVisible(customRulesButtonSelector);
+ cy.get(customRulesButtonSelector).realHover().realClick();
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-redirected-next-rule-page-then.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-redirected-next-rule-page-then.js
new file mode 100644
index 0000000000..1765238c11
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-redirected-next-rule-page-then.js
@@ -0,0 +1,15 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { getSelector } from '../../../utils/driver';
+import { RULES_PAGE as pageName } from '../../../utils/pages-constants';
+const rulestableSelector = getSelector('rulestableSelector', pageName);
+
+Then('The user should be redirected to the next rule page available',() => {
+ cy.wait(3000);
+ cy.get(rulestableSelector).then(($rules) => {
+ const rulesText = $rules.text();
+ cy.log(rulesText);
+ assert.isNotEmpty(rulesText);
+ assert.isNotNaN(rulesText);
+ assert.isNotNull(rulesText);
+ })
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-saves-a-new-rule-when.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-saves-a-new-rule-when.js
new file mode 100644
index 0000000000..9cbada53ef
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-saves-a-new-rule-when.js
@@ -0,0 +1,9 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector} from '../../../utils/driver';
+import { RULES_PAGE as pageName} from '../../../utils/pages-constants';
+const saveRulesButtonSelector = getSelector('saveRulesButtonSelector', pageName);
+
+When('The user saves the rule', () => {
+ elementIsVisible(saveRulesButtonSelector);
+ clickElement(saveRulesButtonSelector);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-see-rule-list-per-row-when.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-see-rule-list-per-row-when.js
new file mode 100644
index 0000000000..25ec8e30b0
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-see-rule-list-per-row-when.js
@@ -0,0 +1,10 @@
+import { When } from "cypress-cucumber-preprocessor/steps";
+import { getSelector, elementIsVisible } from "../../../utils/driver";
+import { RULES_PAGE as pageName } from '../../../utils/pages-constants';
+const dropdownPaginationSelector = getSelector('dropdownPaginationSelector', pageName);
+const rulesRowTableSelector = getSelector('rulesRowTableSelector', pageName);
+
+When('The user see that the rule list is displayed with a limit per rows', () => {
+ elementIsVisible(dropdownPaginationSelector);
+ elementIsVisible(rulesRowTableSelector);
+})
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-see-that-the-rule-list-is-paginated.then.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-see-that-the-rule-list-is-paginated.then.js
new file mode 100644
index 0000000000..07f80f2c82
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-see-that-the-rule-list-is-paginated.then.js
@@ -0,0 +1,15 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, getSelector} from '../../../utils/driver';
+import { RULES_PAGE as pageName} from '../../../utils/pages-constants';
+const paginatorSelector = getSelector('paginatorSelector', pageName);
+const rulestableSelector = getSelector('rulestableSelector', pageName);
+
+Then('The user sees that the rule list is paginated', () => {
+ elementIsVisible(paginatorSelector);
+ cy.get(rulestableSelector).then(($e) =>{
+ const listRulesText = $e.text();
+ cy.log(listRulesText);
+ cy.wrap(listRulesText).as('listRulesText');
+ })
+ cy.wait(1500);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-selects-a-custom-rule-when.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-selects-a-custom-rule-when.js
new file mode 100644
index 0000000000..a5e5bdf17e
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-selects-a-custom-rule-when.js
@@ -0,0 +1,12 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector } from '../../../utils/driver';
+import { RULES_PAGE as pageName} from '../../../utils/pages-constants';
+const firstCustomRule = getSelector('firstCustomRule', pageName);
+const xmlRuleFile = getSelector('xmlRuleFile', pageName);
+
+When('The user selects a custom rule to edit', () => {
+ elementIsVisible(firstCustomRule);
+ clickElement(firstCustomRule);
+ elementIsVisible(xmlRuleFile);
+ clickElement(xmlRuleFile);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-should-see-the-rule-page.then.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-should-see-the-rule-page.then.js
new file mode 100644
index 0000000000..62baaded72
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-should-see-the-rule-page.then.js
@@ -0,0 +1,55 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { getSelector } from '../../../utils/driver';
+import { RULES_PAGE as pageName } from '../../../utils/pages-constants';
+const listPagesSelector = getSelector('listPagesSelector', pageName);
+const rulestableSelector = getSelector('rulestableSelector', pageName);
+const titleSelector = getSelector('titleSelector', pageName);
+const dropdownPaginationSelector = getSelector('dropdownPaginationSelector', pageName);
+const customRulesButtonSelector = getSelector('customRulesButtonSelector', pageName);
+const createNewRulesSelector = getSelector('createNewRulesSelector', pageName);
+const refreshButtonSelector = getSelector('refreshButtonSelector', pageName);
+const buttonListPageSelector = getSelector('buttonListPageSelector', pageName);
+
+Then('The user should be able to see the rules page', () => {
+
+ cy.get(titleSelector).then(($title) => {
+ cy.get('@title').then(($e) => {
+ expect($title.text()).to.be.eq($e);
+ })
+ })
+ cy.get(rulestableSelector).then(($rules) => {
+ cy.get('@rulesLength').then(($e) => {
+ expect($rules.length).to.be.eq($e);
+ })
+ })
+ cy.get(dropdownPaginationSelector).then(($pagination) => {
+ cy.get('@paginationRows').then(($e) => {
+ expect($pagination.text()).to.be.eq($e);
+ })
+ })
+ cy.get(listPagesSelector).then(($paginationPages) => {
+ cy.get('@paginationPages').then(($e) => {
+ expect($paginationPages.text()).to.be.eq($e);
+ })
+ })
+ cy.get(customRulesButtonSelector).then(($customRules) => {
+ cy.get('@customRules').then(($e) => {
+ expect($customRules.text()).to.be.eq($e);
+ })
+ })
+ cy.get(createNewRulesSelector).then(($createNewRules) => {
+ cy.get('@createNewRules').then(($e) => {
+ expect($createNewRules.text()).to.be.eq($e);
+ })
+ })
+ cy.get(refreshButtonSelector).then(($refreshButton) => {
+ cy.get('@refreshButton').then(($e) => {
+ expect($refreshButton.text()).to.be.eq($e);
+ })
+ })
+ cy.get(buttonListPageSelector).then(($buttonLength) => {
+ cy.get('@buttonLength').then(($e) => {
+ expect($buttonLength.length).to.be.eq($e);
+ })
+ })
+});
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-should-see-the-rules.then.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-should-see-the-rules.then.js
new file mode 100644
index 0000000000..fadbec4e92
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-should-see-the-rules.then.js
@@ -0,0 +1,22 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { getElement, getSelector } from '../../../utils/driver';
+import { RULES_PAGE as pageName} from '../../../utils/pages-constants';
+const dropdownPaginationSelector = getSelector('dropdownPaginationSelector', pageName);
+const listPagesSelector = getSelector('listPagesSelector', pageName);
+const tableSelector = getSelector('tableSelector', pageName);
+const titleSelector = getSelector('titleSelector', pageName);
+
+Then('The user should see the rules', () => {
+ getElement(titleSelector)
+ .should('exist')
+ .should('contain', 'Rules');
+ getElement(tableSelector)
+ .should('exist')
+ .should('be.visible');
+ getElement(dropdownPaginationSelector)
+ .should('exist')
+ .should('be.visible');
+ getElement(listPagesSelector)
+ .should('exist')
+ .should('be.visible');
+});
diff --git a/test/cypress/cypress/integration/step-definitions/management/rules/the-user-writes-a-new-rule-when.js b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-writes-a-new-rule-when.js
new file mode 100644
index 0000000000..93fa5435a9
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/management/rules/the-user-writes-a-new-rule-when.js
@@ -0,0 +1,13 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, getSelector, fillField, generateRandomName } from '../../../utils/driver';
+import { RULES_PAGE as pageName} from '../../../utils/pages-constants';
+const codeEditorSelector = getSelector('codeEditorSelector', pageName);
+const rulesTitleSelector = getSelector('rulesTitleSelector', pageName);
+const testXmlText = ' windows Generic template for all windows rules. ';
+
+When('The user writes a new rule', () => {
+ elementIsVisible(rulesTitleSelector);
+ fillField(rulesTitleSelector,generateRandomName())
+ elementIsVisible(codeEditorSelector);
+ fillField(codeEditorSelector,testXmlText);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/reporting/generate-module-report-when.js b/test/cypress/cypress/integration/step-definitions/reporting/generate-module-report-when.js
new file mode 100644
index 0000000000..81e622d33a
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/reporting/generate-module-report-when.js
@@ -0,0 +1,15 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { forceClickElement, elementIsVisible, getSelector, elementIsNotVisible} from '../../utils/driver';
+import { REPORTING_PAGE as pageName} from '../../utils/pages-constants';
+const generateReportButton = getSelector('generateReportButton', pageName);
+const reportGeneratedToast = getSelector('reportGeneratedToast', pageName);
+const disableGenerateReportButton = getSelector('disableGenerateReportButton', pageName);
+
+When('The user generate a module report clicking on the generate report option', () => {
+ elementIsVisible(generateReportButton);
+ cy.wait(500);
+ elementIsNotVisible(disableGenerateReportButton);
+ forceClickElement(generateReportButton);
+ cy.wait(500);
+ elementIsVisible(reportGeneratedToast);
+ });
diff --git a/test/cypress/cypress/integration/step-definitions/reporting/the-user-agent-report-is-displayed-in-the-table-then.js b/test/cypress/cypress/integration/step-definitions/reporting/the-user-agent-report-is-displayed-in-the-table-then.js
new file mode 100644
index 0000000000..4b7ab1999e
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/reporting/the-user-agent-report-is-displayed-in-the-table-then.js
@@ -0,0 +1,16 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, elementTextIncludes, getSelector} from '../../utils/driver';
+import {REPORT_NAME as reportName} from '../../utils/mappers/modules-mapper-report-data';
+import { REPORTING_PAGE as pageName} from '../../utils/pages-constants';
+const lastCreatedReport = getSelector('lastCreatedReport', pageName);
+
+Then('The agent report is displayed in the table {}', (moduleName) => {
+ elementIsVisible(lastCreatedReport);
+ cy.wait(2000);
+ cy.get('@agentId').then(($agentId) => {
+ expect($agentId).to.be.eq($agentId);
+ const agentID = $agentId;
+ elementTextIncludes(lastCreatedReport, 'agents-' + agentID + '-' + reportName[moduleName]);
+ });
+});
+
diff --git a/test/cypress/cypress/integration/step-definitions/reporting/the-user-choose-an-agent-to-apply-filter-when.js b/test/cypress/cypress/integration/step-definitions/reporting/the-user-choose-an-agent-to-apply-filter-when.js
new file mode 100644
index 0000000000..c1dc423ff3
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/reporting/the-user-choose-an-agent-to-apply-filter-when.js
@@ -0,0 +1,19 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector} from '../../utils/driver';
+
+import { AGENTS_PAGE as pageName} from '../../utils/pages-constants';
+const exploreAgentButton = getSelector('exploreAgentButton', pageName);
+const firstAgentDisplayed = getSelector('firstAgentDisplayed', pageName);
+const agentID = getSelector('agentID', pageName);
+
+When('The user choose an agent to apply filter', () => {
+ elementIsVisible(exploreAgentButton);
+ clickElement(exploreAgentButton);
+ cy.wait(500);
+ elementIsVisible(firstAgentDisplayed);
+ cy.get(agentID).then(($agentId) =>{
+ const agentId = $agentId.text();
+ cy.wrap(agentId).as('agentId');
+ })
+ clickElement(firstAgentDisplayed);
+ });
diff --git a/test/cypress/cypress/integration/step-definitions/reporting/the-user-navigates-to-management-reporting-when.js b/test/cypress/cypress/integration/step-definitions/reporting/the-user-navigates-to-management-reporting-when.js
new file mode 100644
index 0000000000..d1413fa6fe
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/reporting/the-user-navigates-to-management-reporting-when.js
@@ -0,0 +1,17 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector} from '../../utils/driver';
+
+import { WAZUH_MENU_PAGE as pageName} from '../../utils/pages-constants';
+const wazuhMenuButton = getSelector('wazuhMenuButton', pageName);
+const managementButton = getSelector('managementButton', pageName);
+const reportingLink = getSelector('reportingLink', pageName);
+
+When('The user navigates to management-reporting', () => {
+ elementIsVisible(wazuhMenuButton);
+ clickElement(wazuhMenuButton);
+ cy.wait(500);
+ elementIsVisible(managementButton);
+ clickElement(managementButton);
+ elementIsVisible(reportingLink);
+ clickElement(reportingLink);
+ });
diff --git a/test/cypress/cypress/integration/step-definitions/reporting/the-user-report-is-dispalyed-in-the-table-then.js b/test/cypress/cypress/integration/step-definitions/reporting/the-user-report-is-dispalyed-in-the-table-then.js
new file mode 100644
index 0000000000..0af2ab1496
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/reporting/the-user-report-is-dispalyed-in-the-table-then.js
@@ -0,0 +1,11 @@
+import { Then } from 'cypress-cucumber-preprocessor/steps';
+import { elementIsVisible, elementTextIncludes, getSelector} from '../../utils/driver';
+import {REPORT_NAME as reportName} from '../../utils/mappers/modules-mapper-report-data';
+import { REPORTING_PAGE as pageName} from '../../utils/pages-constants';
+const lastCreatedReport = getSelector('lastCreatedReport', pageName);
+
+Then('The report is displayed in the table {}', (moduleName) => {
+ elementIsVisible(lastCreatedReport);
+ cy.wait(500);
+ elementTextIncludes(lastCreatedReport, reportName[moduleName]);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/The-wazuh-admin-user-is-logged.given.js b/test/cypress/cypress/integration/step-definitions/settings/The-wazuh-admin-user-is-logged.given.js
new file mode 100644
index 0000000000..49c388d3af
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/The-wazuh-admin-user-is-logged.given.js
@@ -0,0 +1,47 @@
+import { Given } from 'cypress-cucumber-preprocessor/steps';
+import { navigate, elementIsVisible, getSelector, getCookiesFromBrowser } from '../../utils/driver';
+import { WAZUH_MENU_PAGE as pageName } from '../../utils/pages-constants';
+const wazuhMenuButton = getSelector('wazuhMenuButton', pageName);
+let urlsList = [
+ 'https://localhost:5601/elastic/samplealerts/security',
+ 'https://localhost:5601/elastic/samplealerts/auditing-policy-monitoring',
+ 'https://localhost:5601/elastic/samplealerts/threat-detection',
+];
+let urlBodys = [
+ { alertCount: 27000, index: 'wazuh-alerts-4.x-sample-security' },
+ { alertCount: 12000, index: 'wazuh-alerts-4.x-sample-auditing-policy-monitoring' },
+ { alertCount: 15000, index: 'wazuh-alerts-4.x-sample-threat-detection' },
+];
+
+Given('The wazuh admin user is logged', () => {
+ if (Cypress.env('type') != 'wzd') {
+ navigate('app/wazuh');
+ } else {
+ navigate('/');
+ }
+ elementIsVisible(wazuhMenuButton);
+});
+
+Given('The sample data is loaded', () => {
+ cy.readFile('cookies.json').then((cookies) => {
+ let headersFormat = {
+ 'content-type': 'application/json; charset=utf-8',
+ Cookie: getCookiesFromBrowser(cookies),
+ Accept: 'application/json, text/plain, */*',
+ 'Accept-Encoding': 'gzip, deflate, br',
+ };
+ Cypress.env('type') == 'xpack'
+ ? (headersFormat['kbn-xsrf'] = 'kibana')
+ : (headersFormat['osd-xsrf'] = 'kibana');
+ for (let i = 0; i < urlsList.length; i++) {
+ cy.request({
+ method: 'POST',
+ url: urlsList[i],
+ headers: headersFormat,
+ body: urlBodys[i],
+ }).should((response) => {
+ expect(response.status).to.eq(200);
+ });
+ }
+ });
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/about/validate-information-displayed.then.js b/test/cypress/cypress/integration/step-definitions/settings/about/validate-information-displayed.then.js
new file mode 100644
index 0000000000..9744a7b1e0
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/about/validate-information-displayed.then.js
@@ -0,0 +1,36 @@
+import { elementIsVisible, getSelector } from '../../../utils/driver';
+
+import { ABOUT_PAGE as pageName} from '../../../utils/pages-constants';
+const appRevisionNumber = getSelector('appRevisionNumber', pageName);
+const appRevisionTitle = getSelector('appRevisionTitle', pageName);
+const appVersionNumber = getSelector('appVersionNumber', pageName);
+const appVersionTitle = getSelector('appVersionTitle', pageName);
+const communityCard = getSelector('communityCard', pageName);
+const communityCardTitle = getSelector('communityCardTitle', pageName);
+const communityGithubLink = getSelector('communityGithubLink', pageName);
+const communityGoogleGroupLink = getSelector('communityGoogleGroupLink', pageName);
+const communitySlackLink = getSelector('communitySlackLink', pageName);
+const installDateInformation = getSelector('installDateInformation', pageName);
+const installDateTitle = getSelector('installDateTitle', pageName);
+const welcomingCard = getSelector('welcomingCard', pageName);
+const welcomingCardTitle = getSelector('welcomingCardTitle', pageName);
+
+Then('The Wazuh information is displayed', () => {
+ elementIsVisible(appVersionTitle);
+ elementIsVisible(appVersionNumber);
+
+ elementIsVisible(appRevisionTitle);
+ elementIsVisible(appRevisionNumber);
+
+ elementIsVisible(installDateTitle);
+ elementIsVisible(installDateInformation);
+
+ elementIsVisible(welcomingCard);
+ elementIsVisible(welcomingCardTitle);
+
+ elementIsVisible(communityCard);
+ elementIsVisible(communityCardTitle);
+ elementIsVisible(communitySlackLink);
+ elementIsVisible(communityGoogleGroupLink);
+ elementIsVisible(communityGithubLink);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/api-configuration/add-new-api-configuration.when.js b/test/cypress/cypress/integration/step-definitions/settings/api-configuration/add-new-api-configuration.when.js
new file mode 100644
index 0000000000..eae6fd2da0
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/api-configuration/add-new-api-configuration.when.js
@@ -0,0 +1,8 @@
+import { clickElement, getSelector } from '../../../utils/driver';
+
+import { API_CONFIGURATION_PAGE as pageName} from '../../../utils/pages-constants';
+const addNewConnectionButton = getSelector('addNewConnectionButton', pageName);
+
+When('The user tries to add new API configuration', () => {
+ clickElement(addNewConnectionButton);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/api-configuration/check-api-configuration-connection.when.js b/test/cypress/cypress/integration/step-definitions/settings/api-configuration/check-api-configuration-connection.when.js
new file mode 100644
index 0000000000..4769b295ee
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/api-configuration/check-api-configuration-connection.when.js
@@ -0,0 +1,8 @@
+import { clickElement, getSelector } from '../../../utils/driver';
+
+import { API_CONFIGURATION_PAGE as pageName} from '../../../utils/pages-constants';
+const checkConnectionButton = getSelector('checkConnectionButton', pageName);
+
+When('The user checks API configuration connection', () => {
+ clickElement(checkConnectionButton);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/api-configuration/check-api-connection-from-instructions-modal.when.js b/test/cypress/cypress/integration/step-definitions/settings/api-configuration/check-api-connection-from-instructions-modal.when.js
new file mode 100644
index 0000000000..6b27bd062b
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/api-configuration/check-api-connection-from-instructions-modal.when.js
@@ -0,0 +1,15 @@
+import { clickElement, getSelector } from '../../../utils/driver';
+
+import { API_CONFIGURATION_PAGE as pageName} from '../../../utils/pages-constants';
+const newConnectionModalCheckConnectionButton = getSelector('newConnectionModalCheckConnectionButton', pageName);
+
+When('The user tests the API connection from the instructions', () => {
+ cy.get('tbody tr td').then(($e) => {
+
+ let index = $e.findIndex((i, element) => {
+ return element.text().indexOf('wazuh-manage');
+ });
+ cy.get('tbody tr:nth-child('+index+') td:nth-child(9) button[aria-label="Check connection"]').click();
+ });
+ clickElement(newConnectionModalCheckConnectionButton);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/api-configuration/instruction-modal-connection-success.then.js b/test/cypress/cypress/integration/step-definitions/settings/api-configuration/instruction-modal-connection-success.then.js
new file mode 100644
index 0000000000..a525d981e7
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/api-configuration/instruction-modal-connection-success.then.js
@@ -0,0 +1,10 @@
+import { elementIsVisible, getSelector } from '../../../utils/driver';
+
+import { API_CONFIGURATION_PAGE as pageName} from '../../../utils/pages-constants';
+const testConnectionCheckBox = getSelector('newConnectionModalCheckConnectionButton', pageName);
+const testConnectionCheckBoxMarked = getSelector('newConnectionModalCheckConnectionButton', pageName);
+
+Then('The connection success check box is filled', () => {
+ elementIsVisible(testConnectionCheckBox);
+ elementIsVisible(testConnectionCheckBoxMarked);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/api-configuration/instructions-modals-displayed.then.js b/test/cypress/cypress/integration/step-definitions/settings/api-configuration/instructions-modals-displayed.then.js
new file mode 100644
index 0000000000..bae70c51d3
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/api-configuration/instructions-modals-displayed.then.js
@@ -0,0 +1,10 @@
+import { elementIsVisible, elementTextIncludes, getSelector } from '../../../utils/driver';
+
+import { API_CONFIGURATION_PAGE as pageName} from '../../../utils/pages-constants';
+const addNewConnectionModal = getSelector('addNewConnectionModal', pageName);
+const addNewConnectionModalTitle = getSelector('addNewConnectionModalTitle', pageName);
+
+Then('The instructions modal is displayed', () => {
+ elementIsVisible(addNewConnectionModal);
+ elementTextIncludes(addNewConnectionModalTitle, 'Getting started');
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/api-configuration/validate-connection-success.then.js b/test/cypress/cypress/integration/step-definitions/settings/api-configuration/validate-connection-success.then.js
new file mode 100644
index 0000000000..75313581b6
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/api-configuration/validate-connection-success.then.js
@@ -0,0 +1,8 @@
+import { elementTextIncludes, getSelector } from '../../../utils/driver';
+
+import { API_CONFIGURATION_PAGE as pageName} from '../../../utils/pages-constants';
+const connectionSuccessToast = getSelector('connectionSuccessToast', pageName);
+
+Then('The connection success toast is displayed', () => {
+ elementTextIncludes(connectionSuccessToast, 'Settings. Connection success');
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/configuration/valida-configuration.when.js b/test/cypress/cypress/integration/step-definitions/settings/configuration/valida-configuration.when.js
new file mode 100644
index 0000000000..4cbeb21f0a
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/configuration/valida-configuration.when.js
@@ -0,0 +1,447 @@
+import { elementTextIncludes, elementIsVisible, getSelector } from '../../../utils/driver';
+
+import { CONFIGURATION_PAGE as pageName } from '../../../utils/pages-constants';
+const settingTitle = getSelector('settingTitle', pageName);
+const generalPanelTitle = getSelector('generalPanelTitle', pageName);
+const generalPanelIndexPatternName = getSelector('generalPanelIndexPatternName', pageName);
+const generalPanelIndexPatternDescription = getSelector('generalPanelIndexPatternDescription', pageName);
+const generalPanelIndexPatternLabel = getSelector('generalPanelIndexPatternLabel', pageName);
+const generalPanelIndexPatternField = getSelector('generalPanelIndexPatternField', pageName);
+const generalPanelRequestTimeoutName = getSelector('generalPanelRequestTimeoutName', pageName);
+const generalPanelRequestTimeoutDescription = getSelector('generalPanelRequestTimeoutDescription', pageName);
+const generalPanelRequestLabel = getSelector('generalPanelRequestLabel', pageName);
+const generalPanelRequestField = getSelector('generalPanelRequestField', pageName);
+const generalPanelIpSelectorName = getSelector('generalPanelIpSelectorName', pageName);
+const generalPanelIpSelectorDescription = getSelector('generalPanelIpSelectorDescription', pageName);
+const generalPanelIpSelectorLabel = getSelector('generalPanelIpSelectorLabel', pageName);
+const generalPanelIpSelectorField = getSelector('generalPanelIpSelectorField', pageName);
+const generalPanelIpIgnoreName = getSelector('generalPanelIpIgnoreName', pageName);
+const generalPanelIpIgnoreDescription = getSelector('generalPanelIpIgnoreDescription', pageName);
+const generalPanelIpIgnoreLabel = getSelector('generalPanelIpIgnoreLabel', pageName);
+const generalPanelIpIgnoreField = getSelector('generalPanelIpIgnoreField', pageName);
+const generalPanelCronPrefixName = getSelector('generalPanelCronPrefixName', pageName);
+const generalPanelCronPrefixDescription = getSelector('generalPanelCronPrefixDescription', pageName);
+const generalPanelCronLabel = getSelector('generalPanelCronLabel', pageName);
+const generalPanelCronField = getSelector('generalPanelCronField', pageName);
+const generalPanelSamplePrefixName = getSelector('generalPanelSamplePrefixName', pageName);
+const generalPanelSamplePrefixDescription = getSelector('generalPanelSamplePrefixDescription', pageName);
+const generalPanelSampleLabel = getSelector('generalPanelSampleLabel', pageName);
+const generalPanelSampleField = getSelector('generalPanelSampleField', pageName);
+const generalPanelManagerAlertsPrefixName = getSelector('generalPanelManagerAlertsPrefixName', pageName);
+const generalPanelManagerAlertsPrefixDescription = getSelector('generalPanelManagerAlertsPrefixDescription', pageName);
+const generalPanelManagerAlertsLabel = getSelector('generalPanelManagerAlertsLabel', pageName);
+const generalPanelManagerAlertsField = getSelector('generalPanelManagerAlertsField', pageName);
+const generalPanelLogLevelName = getSelector('generalPanelLogLevelName', pageName);
+const generalPanelLogLevelDescription = getSelector('generalPanelLogLevelDescription', pageName);
+const generalPanelLogLevelLabel = getSelector('generalPanelLogLevelLabel', pageName);
+const generalPanelLogLevelField = getSelector('generalPanelLogLevelField', pageName);
+const generalPanelEnrollmentName = getSelector('generalPanelEnrollmentName', pageName);
+const generalPanelEnrollmentDescription = getSelector('generalPanelEnrollmentDescription', pageName);
+const generalPanelEnrollmentLabel = getSelector('generalPanelEnrollmentLabel', pageName);
+const generalPanelEnrollmentField = getSelector('generalPanelEnrollmentField', pageName);
+const healthCheckPanelTitle = getSelector('healthCheckPanelTitle', pageName);
+const healthCheckPanelIndexPatternPrefixName = getSelector('healthCheckPanelIndexPatternPrefixName', pageName);
+const healthCheckPanelIndexPatternPrefixDescription = getSelector('healthCheckPanelIndexPatternPrefixDescription', pageName);
+const healthCheckPanelIndexPatterLabel = getSelector('healthCheckPanelIndexPatterLabel', pageName);
+const healthCheckPanelIndexPatterField = getSelector('healthCheckPanelIndexPatterField', pageName);
+const healthCheckPanelIndexTemplatePrefixName = getSelector('healthCheckPanelIndexTemplatePrefixName', pageName);
+const healthCheckPanelIndexTemplatePrefixDescription = getSelector('healthCheckPanelIndexTemplatePrefixDescription', pageName);
+const healthCheckPanelIndexTemplateLabel = getSelector('healthCheckPanelIndexTemplateLabel', pageName);
+const healthCheckPanelIndexTemplateField = getSelector('healthCheckPanelIndexTemplateField', pageName);
+const healthCheckPanelApiConnectionPrefixName = getSelector('healthCheckPanelApiConnectionPrefixName', pageName);
+const healthCheckPanelApiConnectionPrefixDescription = getSelector('healthCheckPanelApiConnectionPrefixDescription', pageName);
+const healthCheckPanelApiConnectionLabel = getSelector('healthCheckPanelApiConnectionLabel', pageName);
+const healthCheckPanelApiConnectionField = getSelector('healthCheckPanelApiConnectionField', pageName);
+const healthCheckPanelApiVersionPrefixName = getSelector('healthCheckPanelApiVersionPrefixName', pageName);
+const healthCheckPanelApiVersionPrefixDescription = getSelector('healthCheckPanelApiVersionPrefixDescription', pageName);
+const healthCheckPanelApiVersionLabel = getSelector('healthCheckPanelApiVersionLabel', pageName);
+const healthCheckPanelApiVersionField = getSelector('healthCheckPanelApiVersionField', pageName);
+const healthCheckPanelKnowFieldsPrefixName = getSelector('healthCheckPanelKnowFieldsPrefixName', pageName);
+const healthCheckPanelKnowFieldsPrefixDescription = getSelector('healthCheckPanelKnowFieldsPrefixDescription', pageName);
+const healthCheckPanelKnowFieldsLabel = getSelector('healthCheckPanelKnowFieldsLabel', pageName);
+const healthCheckPanelKnowFieldsField = getSelector('healthCheckPanelKnowFieldsField', pageName);
+const healthCheckPanelRemoveMetaFieldsPrefixName = getSelector('healthCheckPanelRemoveMetaFieldsPrefixName', pageName);
+const healthCheckPanelRemoveMetaFieldsPrefixDescription = getSelector('healthCheckPanelRemoveMetaFieldsPrefixDescription', pageName);
+const healthCheckPanelRemoveMetaFieldsPrefixLabel = getSelector('healthCheckPanelRemoveMetaFieldsPrefixLabel', pageName);
+const healthCheckPanelRemoveMetaFieldsPrefixField = getSelector('healthCheckPanelRemoveMetaFieldsPrefixField', pageName);
+const healthCheckPanelSetBucketPrefixName = getSelector('healthCheckPanelSetBucketPrefixName', pageName);
+const healthCheckPanelSetBucketPrefixDescription = getSelector('healthCheckPanelSetBucketPrefixDescription', pageName);
+const healthCheckPanelSetBucketLabel = getSelector('healthCheckPanelSetBucketLabel', pageName);
+const healthCheckPanelSetBucketField = getSelector('healthCheckPanelSetBucketField', pageName);
+const healthCheckPanelSetTimePrefixName = getSelector('healthCheckPanelSetTimePrefixName', pageName);
+const healthCheckPanelSetTimePrefixDescription = getSelector('healthCheckPanelSetTimePrefixDescription', pageName);
+const healthCheckPanelSetTimeLabel = getSelector('healthCheckPanelSetTimeLabel', pageName);
+const healthCheckPanelSetTimeField = getSelector('healthCheckPanelSetTimeField', pageName);
+const monitoringPanelTitle = getSelector('monitoringPanelTitle', pageName);
+const monitoringPanelStatusName = getSelector('monitoringPanelStatusName', pageName);
+const monitoringPanelStatusDescription = getSelector('monitoringPanelStatusDescription', pageName);
+const monitoringPanelStatusPatterLabel = getSelector('monitoringPanelStatusPatterLabel', pageName);
+const monitoringPanelStatusPatterField = getSelector('monitoringPanelStatusPatterField', pageName);
+const monitoringPanelFrequencyName = getSelector('monitoringPanelFrequencyName', pageName);
+const monitoringPanelFrequencyDescription = getSelector('monitoringPanelFrequencyDescription', pageName);
+const monitoringPanelFrequencyLabel = getSelector('monitoringPanelFrequencyLabel', pageName);
+const monitoringPanelFrequencyField = getSelector('monitoringPanelFrequencyField', pageName);
+const monitoringPanelIndexShardsName = getSelector('monitoringPanelIndexShardsName', pageName);
+const monitoringPanelIndexShardsDescription = getSelector('monitoringPanelIndexShardsDescription', pageName);
+const monitoringPanelIndexShardsLabel = getSelector('monitoringPanelIndexShardsLabel', pageName);
+const monitoringPanelIndexShardsField = getSelector('monitoringPanelIndexShardsField', pageName);
+const monitoringPanelIndexReplicasName = getSelector('monitoringPanelIndexReplicasName', pageName);
+const monitoringPanelIndexReplicasDescription = getSelector('monitoringPanelIndexReplicasDescription', pageName);
+const monitoringPanelPanelIndexReplicasLabel = getSelector('monitoringPanelPanelIndexReplicasLabel', pageName);
+const monitoringPanelIndexReplicasField = getSelector('monitoringPanelIndexReplicasField', pageName);
+const monitoringPanelIndexCreationName = getSelector('monitoringPanelIndexCreationName', pageName);
+const monitoringPanelIndexCreationDescription = getSelector('monitoringPanelIndexCreationDescription', pageName);
+const monitoringPanelIndexCreationLabel = getSelector('monitoringPanelIndexCreationLabel', pageName);
+const monitoringPanelIndexCreationField = getSelector('monitoringPanelIndexCreationField', pageName);
+const monitoringPanelIndexPatternName = getSelector('monitoringPanelIndexPatternName', pageName);
+const monitoringPanelIndexPatternDescription = getSelector('monitoringPanelIndexPatternDescription', pageName);
+const monitoringPanelIndexPatternLabel = getSelector('monitoringPanelIndexPatternLabel', pageName);
+const monitoringPanelIndexPatternField = getSelector('monitoringPanelIndexPatternField', pageName);
+const statisticsPanelTitle = getSelector('statisticsPanelTitle', pageName);
+const StatisticsPanelStatusName = getSelector('StatisticsPanelStatusName', pageName);
+const StatisticsPanelStatusDescription = getSelector('StatisticsPanelStatusDescription', pageName);
+const StatisticsPanelStatusPatterLabel = getSelector('StatisticsPanelStatusPatterLabel', pageName);
+const StatisticsPanelStatusPatterField = getSelector('StatisticsPanelStatusPatterField', pageName);
+const StatisticsPanelIncludesApisName = getSelector('StatisticsPanelIncludesApisName', pageName);
+const StatisticsPanelIncludesApisDescription = getSelector('StatisticsPanelIncludesApisDescription', pageName);
+const StatisticsPanelIncludesApisLabel = getSelector('StatisticsPanelIncludesApisLabel', pageName);
+const StatisticsPanelIncludesApisField = getSelector('StatisticsPanelIncludesApisField', pageName);
+const StatisticsPanelIndexIntervalName = getSelector('StatisticsPanelIndexIntervalName', pageName);
+const StatisticsPanelIndexIntervalDescription = getSelector('StatisticsPanelIndexIntervalDescription', pageName);
+const StatisticsPanelIndexIntervalLabel = getSelector('StatisticsPanelIndexIntervalLabel', pageName);
+const StatisticsPanelIndexIntervalField = getSelector('StatisticsPanelIndexIntervalField', pageName);
+const StatisticsPanelIndexNameName = getSelector('StatisticsPanelIndexNameName', pageName);
+const StatisticsPanelIndexNameDescription = getSelector('StatisticsPanelIndexNameDescription', pageName);
+const StatisticsPanelIndexNameLabel = getSelector('StatisticsPanelIndexNameLabel', pageName);
+const StatisticsPanelIndexNameField = getSelector('StatisticsPanelIndexNameField', pageName);
+const StatisticsPanelIndexCreationName = getSelector('StatisticsPanelIndexCreationName', pageName);
+const StatisticsPanelIndexCreationDescription = getSelector('StatisticsPanelIndexCreationDescription', pageName);
+const StatisticsPanelIndexCreationLabel = getSelector('StatisticsPanelIndexCreationLabel', pageName);
+const StatisticsPanelIndexCreationField = getSelector('StatisticsPanelIndexCreationField', pageName);
+const StatisticsPanelIndexShardsName = getSelector('StatisticsPanelIndexShardsName', pageName);
+const StatisticsPanelIndexShardsDescription = getSelector('StatisticsPanelIndexShardsDescription', pageName);
+const StatisticsPanelIndexShardsLabel = getSelector('StatisticsPanelIndexShardsLabel', pageName);
+const StatisticsPanelIndexShardsField = getSelector('StatisticsPanelIndexShardsField', pageName);
+const StatisticsPanelIndexReplicasName = getSelector('StatisticsPanelIndexReplicasName', pageName);
+const StatisticsPanelIndexReplicasDescription = getSelector('StatisticsPanelIndexReplicasDescription', pageName);
+const StatisticsPanelIndexReplicasLabel = getSelector('StatisticsPanelIndexReplicasLabel', pageName);
+const StatisticsPanelIndexReplicasField = getSelector('StatisticsPanelIndexReplicasField', pageName);
+const logoPanelTitle = getSelector('logoPanelTitle', pageName);
+const LogosCustomizationPanelLogoAppName = getSelector('LogosCustomizationPanelLogoAppName', pageName);
+const LogosCustomizationPanelLogoAppDescription = getSelector('LogosCustomizationPanelLogoAppDescription', pageName);
+const LogosCustomizationPanelLogoAppPatterLabel = getSelector('LogosCustomizationPanelLogoAppPatterLabel', pageName);
+const LogosCustomizationPanelLogoAppPatterField = getSelector('LogosCustomizationPanelLogoAppPatterField', pageName);
+const settingSubTitle = getSelector('settingSubTitle', pageName);
+const LogosCustomizationPanelLogoReportField = getSelector('LogosCustomizationPanelLogoReportField', pageName);
+const LogosCustomizationPanelLogoReportLabel = getSelector('LogosCustomizationPanelLogoReportLabel', pageName);
+const LogosCustomizationPanelLogoReportDescription = getSelector('LogosCustomizationPanelLogoReportDescription', pageName);
+const LogosCustomizationPanelLogoReportName = getSelector('LogosCustomizationPanelLogoReportName', pageName);
+const LogosCustomizationPanelLogoHealthCheckField = getSelector('LogosCustomizationPanelLogoHealthCheckField', pageName);
+const LogosCustomizationPanelLogoHealthCheckLabel = getSelector('LogosCustomizationPanelLogoHealthCheckLabel', pageName);
+const LogosCustomizationPanelLogoHealthCheckDescription = getSelector('LogosCustomizationPanelLogoHealthCheckDescription', pageName);
+const LogosCustomizationPanelLogoHealthCheckName = getSelector('LogosCustomizationPanelLogoHealthCheckName', pageName);
+const LogosCustomizationPanelLogosSidebarField = getSelector('LogosCustomizationPanelLogosSidebarField', pageName);
+const LogosCustomizationPanelLogosSidebarLabel = getSelector('LogosCustomizationPanelLogosSidebarLabel', pageName);
+const LogosCustomizationPanelLogosSidebarDescription = getSelector('LogosCustomizationPanelLogosSidebarDescription', pageName);
+const LogosCustomizationPanelLogosSidebarName = getSelector('LogosCustomizationPanelLogosSidebarName', pageName);
+
+
+const texts = require('../../../../fixtures/configuration.panel.text.json');
+
+Then('The app current settings are displayed', () => {
+ elementTextIncludes(settingTitle, texts.configurationTitle);
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(settingSubTitle, 'Configuration file located at /usr/share/wazuh-dashboard/data/wazuh/config/wazuh.yml') : elementTextIncludes(settingSubTitle, texts.configurationDescription);
+
+ elementIsVisible(generalPanelTitle);
+ elementIsVisible(generalPanelIndexPatternName);
+ elementIsVisible(generalPanelIndexPatternDescription);
+ elementIsVisible(generalPanelIndexPatternLabel);
+ elementIsVisible(generalPanelIndexPatternField);
+ elementIsVisible(generalPanelRequestTimeoutName);
+ elementIsVisible(generalPanelRequestTimeoutDescription);
+ elementIsVisible(generalPanelRequestLabel);
+ elementIsVisible(generalPanelRequestField);
+ elementIsVisible(generalPanelIpSelectorName);
+ elementIsVisible(generalPanelIpSelectorDescription);
+ elementIsVisible(generalPanelIpSelectorLabel);
+ elementIsVisible(generalPanelIpSelectorField);
+ elementIsVisible(generalPanelIpIgnoreName);
+ elementIsVisible(generalPanelIpIgnoreDescription);
+ elementIsVisible(generalPanelIpIgnoreLabel);
+ elementIsVisible(generalPanelIpIgnoreField);
+ elementIsVisible(generalPanelCronPrefixName);
+ elementIsVisible(generalPanelCronPrefixDescription);
+ elementIsVisible(generalPanelCronLabel);
+ elementIsVisible(generalPanelCronField);
+ elementIsVisible(generalPanelSamplePrefixName);
+ elementIsVisible(generalPanelSamplePrefixDescription);
+ elementIsVisible(generalPanelSampleLabel);
+ elementIsVisible(generalPanelSampleField);
+ elementIsVisible(generalPanelManagerAlertsPrefixName);
+ elementIsVisible(generalPanelManagerAlertsPrefixDescription);
+ elementIsVisible(generalPanelManagerAlertsLabel);
+ elementIsVisible(generalPanelManagerAlertsField);
+ elementIsVisible(generalPanelLogLevelName);
+ elementIsVisible(generalPanelLogLevelDescription);
+ elementIsVisible(generalPanelLogLevelLabel);
+ elementIsVisible(generalPanelLogLevelField);
+ elementIsVisible(generalPanelEnrollmentName);
+ elementIsVisible(generalPanelEnrollmentDescription);
+ elementIsVisible(generalPanelEnrollmentLabel);
+ elementIsVisible(generalPanelEnrollmentField);
+ elementIsVisible(healthCheckPanelTitle);
+ elementIsVisible(healthCheckPanelIndexPatternPrefixName);
+ elementIsVisible(healthCheckPanelIndexPatternPrefixDescription);
+ elementIsVisible(healthCheckPanelIndexPatterLabel);
+ elementIsVisible(healthCheckPanelIndexPatterField);
+ elementIsVisible(healthCheckPanelIndexTemplatePrefixName);
+ elementIsVisible(healthCheckPanelIndexTemplatePrefixDescription);
+ elementIsVisible(healthCheckPanelIndexTemplateLabel);
+ elementIsVisible(healthCheckPanelIndexTemplateField);
+ elementIsVisible(healthCheckPanelApiConnectionPrefixName);
+ elementIsVisible(healthCheckPanelApiConnectionPrefixDescription);
+ elementIsVisible(healthCheckPanelApiConnectionLabel);
+ elementIsVisible(healthCheckPanelApiConnectionField);
+ elementIsVisible(healthCheckPanelApiVersionPrefixName);
+ elementIsVisible(healthCheckPanelApiVersionPrefixDescription);
+ elementIsVisible(healthCheckPanelApiVersionLabel);
+ elementIsVisible(healthCheckPanelApiVersionField);
+ elementIsVisible(healthCheckPanelKnowFieldsPrefixName);
+ elementIsVisible(healthCheckPanelKnowFieldsPrefixDescription);
+ elementIsVisible(healthCheckPanelKnowFieldsLabel);
+ elementIsVisible(healthCheckPanelKnowFieldsField);
+ elementIsVisible(healthCheckPanelRemoveMetaFieldsPrefixName);
+ elementIsVisible(healthCheckPanelRemoveMetaFieldsPrefixDescription);
+ elementIsVisible(healthCheckPanelRemoveMetaFieldsPrefixLabel);
+ elementIsVisible(healthCheckPanelRemoveMetaFieldsPrefixField);
+ elementIsVisible(healthCheckPanelSetBucketPrefixName);
+ elementIsVisible(healthCheckPanelSetBucketPrefixDescription);
+ elementIsVisible(healthCheckPanelSetBucketLabel);
+ elementIsVisible(healthCheckPanelSetBucketField);
+ elementIsVisible(healthCheckPanelSetTimePrefixName);
+ elementIsVisible(healthCheckPanelSetTimePrefixDescription);
+ elementIsVisible(healthCheckPanelSetTimeLabel);
+ elementIsVisible(healthCheckPanelSetTimeField);
+
+ elementIsVisible(monitoringPanelTitle);
+ elementIsVisible(monitoringPanelStatusName);
+ elementIsVisible(monitoringPanelStatusDescription);
+ elementIsVisible(monitoringPanelStatusPatterLabel);
+ elementIsVisible(monitoringPanelStatusPatterField);
+ elementIsVisible(monitoringPanelFrequencyName);
+ elementIsVisible(monitoringPanelFrequencyDescription);
+ elementIsVisible(monitoringPanelFrequencyLabel);
+ elementIsVisible(monitoringPanelFrequencyField);
+ elementIsVisible(monitoringPanelIndexShardsName);
+ elementIsVisible(monitoringPanelIndexShardsDescription);
+ elementIsVisible(monitoringPanelIndexShardsLabel);
+ elementIsVisible(monitoringPanelIndexShardsField);
+ elementIsVisible(monitoringPanelIndexReplicasName);
+ elementIsVisible(monitoringPanelIndexReplicasDescription);
+ elementIsVisible(monitoringPanelPanelIndexReplicasLabel);
+ elementIsVisible(monitoringPanelIndexReplicasField);
+ elementIsVisible(monitoringPanelIndexCreationName);
+ elementIsVisible(monitoringPanelIndexCreationDescription);
+ elementIsVisible(monitoringPanelIndexCreationLabel);
+ elementIsVisible(monitoringPanelIndexCreationField);
+ elementIsVisible(monitoringPanelIndexPatternName);
+ elementIsVisible(monitoringPanelIndexPatternDescription);
+ elementIsVisible(monitoringPanelIndexPatternLabel);
+ elementIsVisible(monitoringPanelIndexPatternField);
+
+ elementIsVisible(statisticsPanelTitle);
+ elementIsVisible(StatisticsPanelStatusName);
+ elementIsVisible(StatisticsPanelStatusDescription);
+ elementIsVisible(StatisticsPanelStatusPatterLabel);
+ elementIsVisible(StatisticsPanelStatusPatterField);
+ elementIsVisible(StatisticsPanelIncludesApisName);
+ elementIsVisible(StatisticsPanelIncludesApisDescription);
+ elementIsVisible(StatisticsPanelIncludesApisLabel);
+ elementIsVisible(StatisticsPanelIncludesApisField);
+ elementIsVisible(StatisticsPanelIndexIntervalName);
+ elementIsVisible(StatisticsPanelIndexIntervalDescription);
+ elementIsVisible(StatisticsPanelIndexIntervalLabel);
+ elementIsVisible(StatisticsPanelIndexIntervalField);
+ elementIsVisible(StatisticsPanelIndexNameName);
+ elementIsVisible(StatisticsPanelIndexNameDescription);
+ elementIsVisible(StatisticsPanelIndexNameLabel);
+ elementIsVisible(StatisticsPanelIndexNameField);
+ elementIsVisible(StatisticsPanelIndexCreationName);
+ elementIsVisible(StatisticsPanelIndexCreationDescription);
+ elementIsVisible(StatisticsPanelIndexCreationLabel);
+ elementIsVisible(StatisticsPanelIndexCreationField);
+ elementIsVisible(StatisticsPanelIndexShardsName);
+ elementIsVisible(StatisticsPanelIndexShardsDescription);
+ elementIsVisible(StatisticsPanelIndexShardsLabel);
+ elementIsVisible(StatisticsPanelIndexShardsField);
+ elementIsVisible(StatisticsPanelIndexReplicasName);
+ elementIsVisible(StatisticsPanelIndexReplicasDescription);
+ elementIsVisible(StatisticsPanelIndexReplicasLabel);
+ elementIsVisible(StatisticsPanelIndexReplicasField);
+
+ elementIsVisible(logoPanelTitle);
+ elementIsVisible(LogosCustomizationPanelLogoAppName);
+ elementIsVisible(LogosCustomizationPanelLogoAppDescription);
+ elementIsVisible(LogosCustomizationPanelLogoAppPatterLabel);
+ elementIsVisible(LogosCustomizationPanelLogoAppPatterField);
+ elementIsVisible(LogosCustomizationPanelLogosSidebarName);
+ elementIsVisible(LogosCustomizationPanelLogosSidebarDescription);
+ elementIsVisible(LogosCustomizationPanelLogosSidebarLabel);
+ elementIsVisible(LogosCustomizationPanelLogosSidebarField);
+ elementIsVisible(LogosCustomizationPanelLogoHealthCheckName);
+ elementIsVisible(LogosCustomizationPanelLogoHealthCheckDescription);
+ elementIsVisible(LogosCustomizationPanelLogoHealthCheckLabel);
+ elementIsVisible(LogosCustomizationPanelLogoHealthCheckField);
+ elementIsVisible(LogosCustomizationPanelLogoReportName);
+ elementIsVisible(LogosCustomizationPanelLogoReportDescription);
+ elementIsVisible(LogosCustomizationPanelLogoReportLabel);
+ elementIsVisible(LogosCustomizationPanelLogoReportField);
+
+
+ //check the title, subtitle and label texts
+ elementTextIncludes(generalPanelTitle, texts.Panel[0].name);
+ elementTextIncludes(generalPanelIndexPatternName, texts.Panel[0].items[0].title);
+ elementTextIncludes(generalPanelIndexPatternDescription, texts.Panel[0].items[0].subTitle);
+ elementTextIncludes(generalPanelIndexPatternLabel, texts.Panel[0].items[0].label);
+ elementTextIncludes(generalPanelRequestTimeoutName, texts.Panel[0].items[1].title);
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(generalPanelRequestTimeoutDescription, 'Maximum time, in milliseconds, the app will wait for an API response when making requests to it. It will be ignored if the value is set under 1500 milliseconds.') : elementTextIncludes(generalPanelRequestTimeoutDescription, texts.Panel[0].items[1].subTitle);
+ elementTextIncludes(generalPanelRequestLabel, texts.Panel[0].items[1].label);
+ elementTextIncludes(generalPanelIpSelectorName, texts.Panel[0].items[2].title);
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(generalPanelIpSelectorDescription, 'Define if the user is allowed to change the selected index pattern directly from the top menu bar.') : elementTextIncludes(generalPanelIpSelectorDescription, texts.Panel[0].items[2].subTitle);
+ elementTextIncludes(generalPanelIpSelectorLabel, texts.Panel[0].items[2].label);
+ elementTextIncludes(generalPanelIpIgnoreName, texts.Panel[0].items[3].title);
+ elementTextIncludes(generalPanelIpIgnoreDescription, texts.Panel[0].items[3].subTitle);
+ elementTextIncludes(generalPanelIpIgnoreLabel, texts.Panel[0].items[3].label);
+ elementTextIncludes(generalPanelCronPrefixName, texts.Panel[0].items[4].title);
+ elementTextIncludes(generalPanelCronPrefixDescription, texts.Panel[0].items[4].subTitle);
+ elementTextIncludes(generalPanelCronLabel, texts.Panel[0].items[4].label);
+ elementTextIncludes(generalPanelSamplePrefixName, texts.Panel[0].items[5].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(generalPanelSamplePrefixDescription, 'Define the index name prefix of sample alerts. It must match the template used by the index pattern to avoid unknown fields in dashboards.') : elementTextIncludes(generalPanelSamplePrefixDescription, texts.Panel[0].items[5].subTitle);
+
+ elementTextIncludes(generalPanelManagerAlertsPrefixName, texts.Panel[0].items[6].title);
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(generalPanelManagerAlertsPrefixDescription, 'Hide the alerts of the manager in every dashboard.') : elementTextIncludes(generalPanelManagerAlertsPrefixDescription, texts.Panel[0].items[6].subTitle);
+ elementTextIncludes(generalPanelManagerAlertsLabel, texts.Panel[0].items[6].label);
+ elementTextIncludes(generalPanelLogLevelName, texts.Panel[0].items[7].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(generalPanelLogLevelDescription, 'Logging level of the App.') : elementTextIncludes(generalPanelLogLevelDescription, texts.Panel[0].items[7].subTitle);
+
+ elementTextIncludes(generalPanelLogLevelLabel, texts.Panel[0].items[7].label);
+ elementTextIncludes(generalPanelEnrollmentName, texts.Panel[0].items[8].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(generalPanelEnrollmentDescription, 'Specifies the Wazuh registration server, used for the agent enrollment.') : elementTextIncludes(generalPanelEnrollmentDescription, texts.Panel[0].items[8].subTitle);
+
+ elementTextIncludes(generalPanelEnrollmentLabel, texts.Panel[0].items[8].label);
+
+
+ elementTextIncludes(healthCheckPanelTitle, texts.Panel[1].name);
+ elementTextIncludes(healthCheckPanelIndexPatternPrefixName, texts.Panel[1].items[0].title);
+ elementTextIncludes(healthCheckPanelIndexPatternPrefixDescription, texts.Panel[1].items[0].subTitle);
+ elementTextIncludes(healthCheckPanelIndexPatterLabel, texts.Panel[1].items[0].label);
+ elementTextIncludes(healthCheckPanelIndexTemplatePrefixName, texts.Panel[1].items[1].title);
+ elementTextIncludes(healthCheckPanelIndexTemplatePrefixDescription, texts.Panel[1].items[1].subTitle);
+ elementTextIncludes(healthCheckPanelIndexTemplateLabel, texts.Panel[1].items[1].label);
+ elementTextIncludes(healthCheckPanelApiConnectionPrefixName, texts.Panel[1].items[2].title);
+ elementTextIncludes(healthCheckPanelApiConnectionPrefixDescription, texts.Panel[1].items[2].subTitle);
+ elementTextIncludes(healthCheckPanelApiConnectionLabel, texts.Panel[1].items[2].label);
+ elementTextIncludes(healthCheckPanelApiVersionPrefixName, texts.Panel[1].items[3].title);
+ elementTextIncludes(healthCheckPanelApiVersionPrefixDescription, texts.Panel[1].items[3].subTitle);
+ elementTextIncludes(healthCheckPanelApiVersionLabel, texts.Panel[1].items[3].label);
+ elementTextIncludes(healthCheckPanelKnowFieldsPrefixName, texts.Panel[1].items[4].title);
+ elementTextIncludes(healthCheckPanelKnowFieldsPrefixDescription, texts.Panel[1].items[4].subTitle);
+ elementTextIncludes(healthCheckPanelKnowFieldsLabel, texts.Panel[1].items[4].label);
+ elementTextIncludes(healthCheckPanelRemoveMetaFieldsPrefixName, texts.Panel[1].items[5].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(healthCheckPanelRemoveMetaFieldsPrefixDescription, 'Change the default value of the Wazuh dashboard metaField configuration') : elementTextIncludes(healthCheckPanelRemoveMetaFieldsPrefixDescription, texts.Panel[1].items[5].subTitle);
+
+ elementTextIncludes(healthCheckPanelRemoveMetaFieldsPrefixLabel, texts.Panel[1].items[5].label);
+ elementTextIncludes(healthCheckPanelSetBucketPrefixName, texts.Panel[1].items[6].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(healthCheckPanelSetBucketPrefixDescription, 'Change the default value of the Wazuh dashboard max buckets configuration') : elementTextIncludes(healthCheckPanelSetBucketPrefixDescription, texts.Panel[1].items[6].subTitle);
+
+ elementTextIncludes(healthCheckPanelSetBucketLabel, texts.Panel[1].items[6].label);
+ elementTextIncludes(healthCheckPanelSetTimePrefixName, texts.Panel[1].items[7].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(healthCheckPanelSetTimePrefixDescription, 'Change the default value of the Wazuh dashboard timeFilter configuration') : elementTextIncludes(healthCheckPanelSetTimePrefixDescription, texts.Panel[1].items[7].subTitle);
+
+ elementTextIncludes(healthCheckPanelSetTimeLabel, texts.Panel[1].items[7].label);
+
+
+ elementTextIncludes(monitoringPanelTitle, texts.Panel[2].name);
+
+ elementTextIncludes(monitoringPanelStatusName, texts.Panel[2].items[0].title);
+ elementTextIncludes(monitoringPanelStatusDescription, texts.Panel[2].items[0].subTitle);
+ elementTextIncludes(monitoringPanelStatusPatterLabel, texts.Panel[2].items[0].label);
+ elementTextIncludes(monitoringPanelFrequencyName, texts.Panel[2].items[1].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(monitoringPanelFrequencyDescription, 'Frequency, in seconds, of API requests to get the state of the agents and create a new document in the wazuh-monitoring index with this data.') : elementTextIncludes(monitoringPanelFrequencyDescription, texts.Panel[2].items[1].subTitle);
+
+ elementTextIncludes(monitoringPanelFrequencyLabel, texts.Panel[2].items[1].label);
+ elementTextIncludes(monitoringPanelIndexShardsName, texts.Panel[2].items[2].title);
+ elementTextIncludes(monitoringPanelIndexShardsDescription, texts.Panel[2].items[2].subTitle);
+ elementTextIncludes(monitoringPanelIndexShardsLabel, texts.Panel[2].items[2].label);
+ elementTextIncludes(monitoringPanelIndexReplicasName, texts.Panel[2].items[3].title);
+ elementTextIncludes(monitoringPanelIndexReplicasDescription, texts.Panel[2].items[3].subTitle);
+ elementTextIncludes(monitoringPanelPanelIndexReplicasLabel, texts.Panel[2].items[3].label);
+ elementTextIncludes(monitoringPanelIndexCreationName, texts.Panel[2].items[4].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(monitoringPanelIndexCreationDescription, 'Define the interval in which a new wazuh-monitoring index will be created.') : elementTextIncludes(monitoringPanelIndexCreationDescription, texts.Panel[2].items[4].subTitle);
+
+ elementTextIncludes(monitoringPanelIndexCreationLabel, texts.Panel[2].items[4].label);
+ elementTextIncludes(monitoringPanelIndexPatternName, texts.Panel[2].items[5].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(monitoringPanelIndexPatternDescription, 'Default index pattern to use for Wazuh monitoring.') : elementTextIncludes(monitoringPanelIndexPatternDescription, texts.Panel[2].items[5].subTitle);
+
+ elementTextIncludes(monitoringPanelIndexPatternLabel, texts.Panel[2].items[5].label);
+
+ elementTextIncludes(statisticsPanelTitle, texts.Panel[3].name);
+ elementTextIncludes(StatisticsPanelStatusName, texts.Panel[3].items[0].title);
+ elementTextIncludes(StatisticsPanelStatusDescription, texts.Panel[3].items[0].subTitle);
+ elementTextIncludes(StatisticsPanelStatusPatterLabel, texts.Panel[3].items[0].label);
+ elementTextIncludes(StatisticsPanelIncludesApisName, texts.Panel[3].items[1].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(StatisticsPanelIncludesApisDescription, 'Enter the ID of the hosts you want to save data from, leave this empty to run the task on every host.') : elementTextIncludes(StatisticsPanelIncludesApisDescription, texts.Panel[3].items[1].subTitle);
+
+ elementTextIncludes(StatisticsPanelIncludesApisLabel, texts.Panel[3].items[1].label);
+ elementTextIncludes(StatisticsPanelIndexIntervalName, texts.Panel[3].items[2].title);
+ elementTextIncludes(StatisticsPanelIndexIntervalDescription, texts.Panel[3].items[2].subTitle);
+ elementTextIncludes(StatisticsPanelIndexIntervalLabel, texts.Panel[3].items[2].label);
+ elementTextIncludes(StatisticsPanelIndexNameName, texts.Panel[3].items[3].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(StatisticsPanelIndexNameDescription, 'Define the name of the index in which the documents will be saved.') : elementTextIncludes(StatisticsPanelIndexNameDescription, texts.Panel[3].items[3].subTitle);
+
+ elementTextIncludes(StatisticsPanelIndexNameLabel, texts.Panel[3].items[3].label);
+ elementTextIncludes(StatisticsPanelIndexCreationName, texts.Panel[3].items[4].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(StatisticsPanelIndexCreationDescription, 'Define the interval in which a new index will be created.') : elementTextIncludes(StatisticsPanelIndexCreationDescription, texts.Panel[3].items[4].subTitle);
+
+ elementTextIncludes(StatisticsPanelIndexCreationLabel, texts.Panel[3].items[4].label);
+ elementTextIncludes(StatisticsPanelIndexShardsName, texts.Panel[3].items[5].title);
+ elementTextIncludes(StatisticsPanelIndexShardsDescription, texts.Panel[3].items[5].subTitle);
+ elementTextIncludes(StatisticsPanelIndexShardsLabel, texts.Panel[3].items[5].label);
+ elementTextIncludes(StatisticsPanelIndexReplicasName, texts.Panel[3].items[6].title);
+ elementTextIncludes(StatisticsPanelIndexReplicasDescription, texts.Panel[3].items[6].subTitle);
+ elementTextIncludes(StatisticsPanelIndexReplicasLabel, texts.Panel[3].items[6].label);
+ elementTextIncludes(logoPanelTitle, texts.Panel[4].name);
+ elementTextIncludes(LogosCustomizationPanelLogoAppName, texts.Panel[4].items[0].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(LogosCustomizationPanelLogoAppDescription, 'Set the name of the app logo stored at /plugins/wazuh/public/assets/') : elementTextIncludes(LogosCustomizationPanelLogoAppDescription, texts.Panel[4].items[0].subTitle);
+
+
+ elementTextIncludes(LogosCustomizationPanelLogoAppPatterLabel, texts.Panel[4].items[0].label);
+ elementTextIncludes(LogosCustomizationPanelLogosSidebarName, texts.Panel[4].items[1].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(LogosCustomizationPanelLogosSidebarDescription, 'Set the name of the sidebar logo stored at /plugins/wazuh/public/assets') : elementTextIncludes(LogosCustomizationPanelLogosSidebarDescription, texts.Panel[4].items[1].subTitle);
+
+ elementTextIncludes(LogosCustomizationPanelLogosSidebarLabel, texts.Panel[4].items[1].label);
+ elementTextIncludes(LogosCustomizationPanelLogoHealthCheckName, texts.Panel[4].items[2].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(LogosCustomizationPanelLogoHealthCheckDescription, 'Set the name of the health-check logo stored at /plugins/wazuh/public/assets/') : elementTextIncludes(LogosCustomizationPanelLogoHealthCheckDescription, texts.Panel[4].items[2].subTitle);
+
+ elementTextIncludes(LogosCustomizationPanelLogoHealthCheckLabel, texts.Panel[4].items[2].label);
+ elementTextIncludes(LogosCustomizationPanelLogoReportName, texts.Panel[4].items[3].title);
+
+ (Cypress.env('type') == 'wzd') ? elementTextIncludes(LogosCustomizationPanelLogoReportDescription, 'Set the name of the reports logo (.png) stored at /plugins/wazuh/public/assets/') : elementTextIncludes(LogosCustomizationPanelLogoReportDescription, texts.Panel[4].items[3].subTitle);
+
+ elementTextIncludes(LogosCustomizationPanelLogoReportLabel, texts.Panel[4].items[3].label);
+})
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/settings/miscellaneous/run-health-check.when.js b/test/cypress/cypress/integration/step-definitions/settings/miscellaneous/run-health-check.when.js
new file mode 100644
index 0000000000..029a8ba3e0
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/miscellaneous/run-health-check.when.js
@@ -0,0 +1,8 @@
+import { clickElement, getSelector } from '../../../utils/driver';
+
+import { MISCELLANEOUS_PAGE as pageName} from '../../../utils/pages-constants';
+const runHealthChecksButton = getSelector('runHealthChecksButton', pageName);
+
+When('The user runs the health checks', () => {
+ clickElement(runHealthChecksButton);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/miscellaneous/validate-health-check-navigation.then.js b/test/cypress/cypress/integration/step-definitions/settings/miscellaneous/validate-health-check-navigation.then.js
new file mode 100644
index 0000000000..39372fab01
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/miscellaneous/validate-health-check-navigation.then.js
@@ -0,0 +1,6 @@
+import { validateURLIncludes } from '../../../utils/driver';
+import { HEALTH_CHECK_URL } from '../../../utils/health-check-constants';
+
+Then('The application navigates to the health checks page', () => {
+ validateURLIncludes(HEALTH_CHECK_URL);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/modules/activate-the-modules.when.js b/test/cypress/cypress/integration/step-definitions/settings/modules/activate-the-modules.when.js
new file mode 100644
index 0000000000..b3376014f6
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/modules/activate-the-modules.when.js
@@ -0,0 +1,9 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector } from '../../../utils/driver';
+import { MODULES_CARDS} from '../../../utils/pages-constants';
+
+When('The user {} the modules with {}', (status, moduleName) => {
+ elementIsVisible(getSelector(moduleName, MODULES_CARDS));
+ clickElement(getSelector(moduleName, MODULES_CARDS));
+ cy.wait(500)
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/modules/clean-the-modules.when.js b/test/cypress/cypress/integration/step-definitions/settings/modules/clean-the-modules.when.js
new file mode 100644
index 0000000000..0f25b20830
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/modules/clean-the-modules.when.js
@@ -0,0 +1,18 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getAttributeElement } from '../../../utils/driver';
+
+When('All modules are {}', (status) => {
+ //activates/deactivates
+ let activates = 0;
+ if (elementIsVisible('react-component button[aria-checked="true"]')) {
+ cy.get('react-component button[aria-checked="true"]').as('elementTrue').then(($el) => {
+ activates = $el.length;
+ if (activates != 0) {
+ cy.get('@elementTrue').each(($el) => {
+ elementIsVisible($el);
+ clickElement($el);
+ })
+ }
+ });
+ }
+});
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/step-definitions/settings/modules/validate-active-modules.then.js b/test/cypress/cypress/integration/step-definitions/settings/modules/validate-active-modules.then.js
new file mode 100644
index 0000000000..bebdff9be6
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/modules/validate-active-modules.then.js
@@ -0,0 +1,21 @@
+import { clickElement, elementIsVisible, getSelector } from '../../../utils/driver';
+import { WAZUH_MENU_PAGE as pageName, MODULES_CARDS } from '../../../utils/pages-constants';
+const modulesButton = getSelector('modulesButton', pageName);
+const modulesDirectoryLink = getSelector('modulesDirectoryLink', pageName);
+const wazuhMenuButton = getSelector('wazuhMenuButton', pageName);
+const wazuhMenuLeft = getSelector('wazuhMenuLeft', pageName);
+const wazuhMenuRight = getSelector('wazuhMenuRight', pageName);
+const wazuhMenuSettingRight = getSelector('wazuhMenuSettingRight', pageName);
+
+Then('The activated modules with {} are displayed on home page', (moduleName) => {
+ elementIsVisible(wazuhMenuButton);
+ clickElement(wazuhMenuButton);
+ elementIsVisible(wazuhMenuLeft);
+ elementIsVisible(wazuhMenuRight);
+ elementIsVisible(modulesButton);
+ clickElement(modulesButton);
+ elementIsVisible(wazuhMenuSettingRight);
+ elementIsVisible(modulesDirectoryLink);
+ clickElement(modulesDirectoryLink);
+ elementIsVisible(getSelector(moduleName, MODULES_CARDS));
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/modules/validate-deactivated-modules.then.js b/test/cypress/cypress/integration/step-definitions/settings/modules/validate-deactivated-modules.then.js
new file mode 100644
index 0000000000..d0695904e2
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/modules/validate-deactivated-modules.then.js
@@ -0,0 +1,23 @@
+import { clickElement, elementIsNotVisible, elementIsVisible, getSelector } from '../../../utils/driver';
+import { WAZUH_MENU_PAGE as pageName, MODULES_CARDS } from '../../../utils/pages-constants';
+const modulesButton = getSelector('modulesButton', pageName);
+const modulesDirectoryLink = getSelector('modulesDirectoryLink', pageName);
+const wazuhMenuButton = getSelector('wazuhMenuButton', pageName);
+const wazuhMenuLeft = getSelector('wazuhMenuLeft', pageName);
+const wazuhMenuRight = getSelector('wazuhMenuRight', pageName);
+const wazuhMenuSettingRight = getSelector('wazuhMenuSettingRight', pageName);
+
+Then('The deactivated modules with {} are not displayed on home page', (moduleName) => {
+ elementIsVisible(wazuhMenuButton);
+ clickElement(wazuhMenuButton);
+ elementIsVisible(wazuhMenuLeft);
+ elementIsVisible(wazuhMenuRight);
+ elementIsVisible(modulesButton);
+ clickElement(modulesButton);
+ cy.wait(1000)
+ elementIsVisible(wazuhMenuSettingRight);
+ elementIsVisible(modulesDirectoryLink);
+ clickElement(modulesDirectoryLink);
+ cy.get('react-component[name="OverviewWelcome"]', { timeout: 15000 });
+ elementIsNotVisible(getSelector(moduleName, MODULES_CARDS));
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/navigate-to-settings.when.js b/test/cypress/cypress/integration/step-definitions/settings/navigate-to-settings.when.js
new file mode 100644
index 0000000000..a01950a810
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/navigate-to-settings.when.js
@@ -0,0 +1,25 @@
+import { When } from 'cypress-cucumber-preprocessor/steps';
+import { clickElement, elementIsVisible, getSelector } from '../../utils/driver';
+import { WAZUH_MENU_PAGE as pageName, SETTINGS_MENU_LINKS } from '../../utils/pages-constants';
+const settingsButton = getSelector('settingsButton', pageName);
+const wazuhMenuButton = getSelector('wazuhMenuButton', pageName);
+const wazuhMenuLeft = getSelector('wazuhMenuLeft', pageName);
+const wazuhMenuRight = getSelector('wazuhMenuRight', pageName);
+const wazuhMenuSettingRight = getSelector('wazuhMenuSettingRight', pageName);
+
+When('The user navigates to {} settings', (menuOption) => {
+ elementIsVisible(wazuhMenuButton);
+ clickElement(wazuhMenuButton);
+ elementIsVisible(wazuhMenuLeft);
+ elementIsVisible(wazuhMenuRight);
+ elementIsVisible(settingsButton);
+ clickElement(settingsButton);
+ elementIsVisible(wazuhMenuSettingRight);
+ if (Cypress.env('type') == 'wzd') {
+ cy.wait(1000);
+ elementIsVisible(getSelector(menuOption, SETTINGS_MENU_LINKS)).click()
+ } else {
+ elementIsVisible(getSelector(menuOption, SETTINGS_MENU_LINKS));
+ clickElement(getSelector(menuOption, SETTINGS_MENU_LINKS));
+ };
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/sample-data/add-remove-sample-data.when.js b/test/cypress/cypress/integration/step-definitions/settings/sample-data/add-remove-sample-data.when.js
new file mode 100644
index 0000000000..209768e39d
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/sample-data/add-remove-sample-data.when.js
@@ -0,0 +1,39 @@
+import { clickElement, getSelector, forceClickElement, elementIsVisible } from '../../../utils/driver';
+import { SAMPLE_DATA } from '../../../utils/pages-constants';
+let toastLocator = '[data-test-subj="globalToastList"] div button';
+let toastLocatorTitle = '[data-test-subj="globalToastList"] div';
+
+When('All buttons have {} status', (status) => {
+ cy.wait(4000);
+ let label = 'Add data';
+ if (status == 'add'){ label = 'Remove data';
+ for (let i = 1; i <= 3; i++) {
+ elementIsVisible('div:nth-child(' + i + ') > div > div.euiCard__footer > div > div > button')
+ cy.get('div:nth-child(' + i + ') > div > div.euiCard__footer > div > div > button',{timeot:10000})
+ .then($button => {
+ if($button.find(':contains("' + label + '")').length){
+ return cy.get($button).click().wait(10000);
+ }
+ })
+ }}
+});
+
+When('The user {} sample data for', (status, types) => {
+ let titleStatus = 'added'
+ let buttonLabel = 'Remove data'
+ if (status != 'adds') { titleStatus = 'removed'; buttonLabel = 'Add data'; }
+ types.raw().forEach((sample) => {
+ cy.get(getSelector(sample, SAMPLE_DATA), { timeout: 15000 })
+ forceClickElement(getSelector(sample, SAMPLE_DATA));
+ cy.wait(500);
+ cy.get(getSelector(sample, SAMPLE_DATA), { timeout: 15000 }).should('have.text', buttonLabel)
+ cy.get(toastLocatorTitle, { timeout: 15000 })
+ .then(($) => {
+ const texts = $.map((i, el) => Cypress.$(el).text().replace('A new notification appears').replace('Date range for sample data is now-7 days ago'))
+ const paragraphs = texts.get()
+ let element = getSelector(sample + ' title', SAMPLE_DATA)
+ let titles = Cypress.$(element).text()
+ expect(paragraphs.toString()).to.contains(titles + ' alerts ' + titleStatus)
+ })
+ });
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/sample-data/validate-sample-data-added.then.js b/test/cypress/cypress/integration/step-definitions/settings/sample-data/validate-sample-data-added.then.js
new file mode 100644
index 0000000000..9b263498d1
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/sample-data/validate-sample-data-added.then.js
@@ -0,0 +1,16 @@
+import { elementIsVisible, getSelector } from '../../../utils/driver';
+import { SAMPLE_DATA_PAGE as pageName } from '../../../utils/pages-constants';
+const dataAddedSuccessfullyToast = getSelector('dataAddedSuccessfullyToast', pageName);
+
+Then('The add data success toasts are displayed', () => {
+ elementIsVisible(dataAddedSuccessfullyToast);
+
+ cy.get(dataAddedSuccessfullyToast)
+ .should('have.length', 3)
+ .each(($li, index, $lis) => {
+ return 'something else'
+ })
+ .then(($lis) => {
+ expect($lis).to.have.length(3)
+ })
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/sample-data/validate-sample-data-removed.then.js b/test/cypress/cypress/integration/step-definitions/settings/sample-data/validate-sample-data-removed.then.js
new file mode 100644
index 0000000000..c6e9fc6d45
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/sample-data/validate-sample-data-removed.then.js
@@ -0,0 +1,7 @@
+import { getSelector } from '../../../utils/driver';
+import { SAMPLE_DATA_PAGE as pageName} from '../../../utils/pages-constants';
+const dataAddedSuccessfullyToast = getSelector('dataAddedSuccessfullyToast', pageName);
+
+Then('The remove data success toasts are displayed', () => {
+ cy.get(dataAddedSuccessfullyToast).should('have.length', 0);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/wazuh-logs/backend-reload-logs.then.js b/test/cypress/cypress/integration/step-definitions/settings/wazuh-logs/backend-reload-logs.then.js
new file mode 100644
index 0000000000..984d90c8d7
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/wazuh-logs/backend-reload-logs.then.js
@@ -0,0 +1,6 @@
+Then('The backend response indicates that the logs are reloaded', () => {
+ cy.get('@apiCheck').should('not.be.null');
+ cy.wait('@apiCheck').then( (interceptedObject) => {
+ expect(interceptedObject.response.statusCode).to.equal(200);
+ });
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/wazuh-logs/reload-logs.when.js b/test/cypress/cypress/integration/step-definitions/settings/wazuh-logs/reload-logs.when.js
new file mode 100644
index 0000000000..19c0f47dc6
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/wazuh-logs/reload-logs.when.js
@@ -0,0 +1,10 @@
+import { clickElement, interceptAs, getSelector } from '../../../utils/driver';
+
+import { LOGS_PAGE as pageName} from '../../../utils/pages-constants';
+const reloadLogsLink = getSelector('reloadLogsLink', pageName);
+
+When('The user reloads the logs', () => {
+ interceptAs('GET', '/utils/logs', 'apiCheck');
+ clickElement(reloadLogsLink);
+ cy.wait(500);
+});
diff --git a/test/cypress/cypress/integration/step-definitions/settings/wazuh-logs/validate-logs-displayed.then.js b/test/cypress/cypress/integration/step-definitions/settings/wazuh-logs/validate-logs-displayed.then.js
new file mode 100644
index 0000000000..ee249a9082
--- /dev/null
+++ b/test/cypress/cypress/integration/step-definitions/settings/wazuh-logs/validate-logs-displayed.then.js
@@ -0,0 +1,12 @@
+import { elementIsVisible, elementTextIncludes, getSelector } from '../../../utils/driver';
+import { logsTitleText } from '../../../utils/logs-constants';
+
+import { LOGS_PAGE as pageName} from '../../../utils/pages-constants';
+const logsContainer = getSelector('logsContainer', pageName);
+const logsTitle = getSelector('logsTitle', pageName);
+
+Then("The Logs are displayed", () => {
+ elementIsVisible(logsTitle);
+ elementTextIncludes(logsTitle, logsTitleText);
+ elementIsVisible(logsContainer);
+});
diff --git a/test/cypress/cypress/integration/utils/driver.js b/test/cypress/cypress/integration/utils/driver.js
new file mode 100644
index 0000000000..d3b0b59f1d
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/driver.js
@@ -0,0 +1,168 @@
+///
+import { XPACK_PAGES_MAPPER } from "./mappers/xpack-pages-mapper";
+import { ODFE_PAGES_MAPPER } from "./mappers/odfe-pages-mapper";
+import { BASIC_PAGES_MAPPER } from "./mappers/basic-pages-mapper";
+import { WZD_PAGES_MAPPER } from "./mappers/wzd-pages-mapper";
+
+export const clickElement = (selector) => {
+ getElement(selector).should('not.be.disabled').click();
+ return this;
+};
+
+export const forceClickElement = (cssSelector) => {
+ cy.wait(1000);
+ getElement(cssSelector).click({ force: true })
+ return this;
+};
+
+export const clickElementByContains = (selector, label) => {
+ return cy.contains(selector,label).click();
+};
+
+export const forceCheckElement = (selector) => {
+ getElement(selector).check({ force: true })
+ return this;
+};
+
+export const forceEnter = (cssSelector) => {
+ cy.wait(1000);
+ getElement(cssSelector).type('{enter}')
+};
+
+export const forceClickElementByXpath = (xpathSelector) => {
+ cy.wait(1000);
+ getElementByXpath(xpathSelector).click({ force: true })
+ return this;
+};
+
+export const getAttributeElement = (selector) => {
+ return getElement(selector).invoke('attr', 'aria-checked').then(($element) => {
+ const value = $element
+ return value;
+ });
+};
+
+export const elementIsNotVisible = (selector) => {
+ return getElement(selector).should('not.exist');
+};
+
+export const elementIsVisible = (selector) => {
+ return getElement(selector).should('exist').should('be.visible');
+};
+
+export const elementTextIncludes = (selector, text) => {
+ getElement(selector).should('contain', text);
+};
+
+export const cleanAndfillField = (selector, text) => {
+ getElement(selector).clear().type(text);
+ return this;
+};
+
+export const fillField = (selector, text) => {
+ getElement(selector).type(text);
+ return this;
+};
+
+export const getElement = (selector) => {
+ return cy.get(selector, { timeout: 18000 });
+};
+
+export const getSelector = (name, page) => {
+ switch (Cypress.env('type')) {
+ case 'xpack':
+ return XPACK_PAGES_MAPPER[page][name];
+ case 'odfe':
+ return ODFE_PAGES_MAPPER[page][name];
+ case 'basic':
+ return BASIC_PAGES_MAPPER[page][name];
+ case 'wzd':
+ return WZD_PAGES_MAPPER[page][name];
+ default:
+ return '';
+ }
+};
+
+export const getAvailableElement = (selector) => {
+ return cy.get(selector).should('not.be.disabled');
+};
+
+export const interceptAs = (methodUsed, urlUsed, alias) => {
+ cy.intercept({
+ method: methodUsed,
+ url: urlUsed
+ }).as(alias);
+};
+
+export const navigate = (url) => {
+ cy.visit(url);
+};
+
+export const validateURLIncludes = (include) => {
+ cy.url().should('include', include);
+};
+
+
+// Function that's return the selector by xpath
+export const getElementByXpath = (xpathSelector) => {
+ return cy.xpath(xpathSelector);
+};
+
+export const clickElementByXpath = (xpathSelector) => {
+ getElementByXpath(xpathSelector).click();
+ return this;
+};
+
+export const xpathElementIsVisible = (xpathSelector) => {
+ return getElementByXpath(xpathSelector).should('exist').should('be.visible');
+};
+
+export const generateRandomName = () => {
+ const uniqueSeed = Date.now().toString();
+ const getUniqueId = () => Cypress._.uniqueId(uniqueSeed);
+ return 'Test-'+getUniqueId();
+};
+
+export const timestampToDate = (e) => {
+ let newDates = e.getDate() + "/" + (e.getMonth() + 1) + "/" + e.getFullYear() + " " + e.getHours() + ":" + e.getMinutes() + ":" + e.getSeconds();
+ return newDates;
+};
+
+export const checkInformationElement = (webLocator, optionsNames, optionLength) => {
+ cy.get(webLocator, { timeout: 2000 }).should("be.visible")
+ cy.get(webLocator)
+ .should(($) => {
+ const texts = $.map((i, el) => Cypress.$(el).text())
+ const paragraphs = texts.get()
+ expect(paragraphs, 'has ' + optionLength + ' paragraphs').to.have.length(optionLength)
+ expect(optionsNames, 'has expected [' + optionsNames + '] text in each paragraph [' + paragraphs + ']').to.contains(paragraphs)
+ })
+}
+
+export const xpathCheckInformationElement= (webLocator, optionsNames, optionLength) => {
+ cy.xpath(webLocator, { timeout: 2000 }).should("be.visible")
+ cy.xpath(webLocator)
+ .should(($) => {
+ const texts = $.map((i, el) => Cypress.$(el).text())
+ const paragraphs = texts.get()
+ expect(paragraphs, 'has ' + optionLength + ' paragraphs').to.have.length(optionLength)
+ expect(optionsNames, 'has expected [' + optionsNames + '] text in each paragraph [' + paragraphs + ']').to.contains(paragraphs)
+ })
+}
+
+
+export const getCookiesFromBrowser = (values) => {
+ return values.filter(item=>['wz-token', 'wz-user', 'wz-api', 'security_authentication'].includes(item.name))
+ .map(item=>{
+ return `${item.name}:${item.value}`
+ }).join(';');
+}
+
+export const retrieveInformation = (url,method,headers,bodyPost) => {
+ return cy.request({
+ method: method,
+ url: url,
+ headers: headers,
+ body: bodyPost
+ }).as('response');
+}
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/utils/health-check-constants.js b/test/cypress/cypress/integration/utils/health-check-constants.js
new file mode 100644
index 0000000000..4f2130535e
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/health-check-constants.js
@@ -0,0 +1 @@
+export const HEALTH_CHECK_URL = 'health-check';
diff --git a/test/cypress/cypress/integration/utils/login-constants.js b/test/cypress/cypress/integration/utils/login-constants.js
new file mode 100644
index 0000000000..9bb57b4a9a
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/login-constants.js
@@ -0,0 +1,19 @@
+import { loginXpack } from '../step-definitions/login/login-xpack';
+import { loginOdfe } from '../step-definitions/login/login-odfe';
+import { loginBasic } from '../step-definitions/login/login-basic';
+import { loginWzd } from '../step-definitions/login/login-wzd';
+
+export const LOGIN_TYPE = {
+ xpack: () => loginXpack(),
+ odfe: () => loginOdfe(),
+ basic: () => loginBasic(),
+ wzd: () => loginWzd()
+};
+
+export const ODFE_PASSWORD = 'admin';
+export const ODFE_USERNAME = 'admin';
+export const OVERVIEW_URL = '/overview/';
+export const XPACK_PASSWORD = 'elastic';
+export const XPACK_USERNAME = 'elastic';
+export const WZD_PASSWORD = 'SecretPassword';
+export const WZD_USERNAME = 'admin';
diff --git a/test/cypress/cypress/integration/utils/logs-constants.js b/test/cypress/cypress/integration/utils/logs-constants.js
new file mode 100644
index 0000000000..488326bd3d
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/logs-constants.js
@@ -0,0 +1 @@
+export const logsTitleText = 'App log messages';
diff --git a/test/cypress/cypress/integration/utils/mappers/basic-pages-mapper.js b/test/cypress/cypress/integration/utils/mappers/basic-pages-mapper.js
new file mode 100644
index 0000000000..41cfb879d8
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/basic-pages-mapper.js
@@ -0,0 +1,50 @@
+import { DEPLOY_NEW_AGENT_PAGE } from '../../pageobjects/basic/agents/deploy-new-agent.page';
+import { AGENTS_PAGE } from '../../pageobjects/basic/agents/agents.page';
+import { FILTERS_PAGE } from '../../pageobjects/basic/filters/filters.page';
+import { OVERVIEW_PAGE } from '../../pageobjects/basic/overview/overview.page';
+import { ABOUT_PAGE } from '../../pageobjects/basic/settings/about.page';
+import { API_CONFIGURATION_PAGE } from '../../pageobjects/basic/settings/api-configuration.page';
+import { CONFIGURATION_PAGE } from '../../pageobjects/basic/settings/configuration.page';
+import { LOGS_PAGE } from '../../pageobjects/basic/settings/logs.page';
+import { MISCELLANEOUS_PAGE } from '../../pageobjects/basic/settings/miscellaneous.page';
+import { MODULES_PAGE } from '../../pageobjects/basic/settings/modules.page';
+import { SAMPLE_DATA_PAGE } from '../../pageobjects/basic/settings/sample-data.page';
+import { DECODERS_PAGE } from '../../pageobjects/basic/wazuh-menu/decoders.page';
+import { RULES_PAGE } from '../../pageobjects/basic/wazuh-menu/rules.page';
+import { WAZUH_MENU_PAGE } from '../../pageobjects/basic/wazuh-menu/wazuh-menu.page';
+import { MODULES_DIRECTORY_PAGE } from '../../pageobjects/basic/modules-directory.page';
+import { REPORTING_PAGE } from '../../pageobjects/wzd/reporting/report.page';
+
+import { AGENT_MODULES } from './basic/agent-modules-mapper';
+import { BASIC_MODULES } from './basic/basic-modules-mapper';
+import { MODULES_CARDS, MODULES_SETTINGS } from './basic/modules-mapper';
+import { SAMPLE_DATA } from './basic/sample-data-mapper';
+import { SETTINGS_MENU_LINKS } from './basic/settings-mapper';
+import { GROUPS_PAGE } from '../../pageobjects/xpack/wazuh-menu/groups.page';
+
+export const BASIC_PAGES_MAPPER = {
+ DEPLOY_NEW_AGENT_PAGE,
+ AGENTS_PAGE,
+ FILTERS_PAGE,
+ OVERVIEW_PAGE,
+ ABOUT_PAGE,
+ API_CONFIGURATION_PAGE,
+ CONFIGURATION_PAGE,
+ LOGS_PAGE,
+ MISCELLANEOUS_PAGE,
+ MODULES_PAGE,
+ SAMPLE_DATA_PAGE,
+ DECODERS_PAGE,
+ RULES_PAGE,
+ WAZUH_MENU_PAGE,
+ MODULES_DIRECTORY_PAGE,
+ REPORTING_PAGE,
+
+ AGENT_MODULES,
+ BASIC_MODULES,
+ MODULES_CARDS,
+ MODULES_SETTINGS,
+ SAMPLE_DATA,
+ SETTINGS_MENU_LINKS,
+ GROUPS_PAGE
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/basic/agent-modules-mapper.js b/test/cypress/cypress/integration/utils/mappers/basic/agent-modules-mapper.js
new file mode 100644
index 0000000000..9d7aae9c3d
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/basic/agent-modules-mapper.js
@@ -0,0 +1,16 @@
+import {
+AGENTS_PAGE
+ } from '../../../pageobjects/basic/agents/agents.page';
+
+ export const AGENT_MODULES = {
+ 'Security Events': AGENTS_PAGE['agSecurityEventsLink'],
+ 'Integrity Monitoring': AGENTS_PAGE['agIntegrityMonitoringLink'],
+ 'SCA': AGENTS_PAGE['agSCALink'],
+ 'System Auditing': AGENTS_PAGE['agSystemAuditingLink'],
+ 'Vulnerabilities': AGENTS_PAGE['agVulnerabilitiesLink'],
+ 'Mitre & Attack': AGENTS_PAGE['agMitreAttackLink'],
+ 'Policy Monitoring': AGENTS_PAGE['agPolicyMonitoring'],
+ 'PCIDSS': AGENTS_PAGE['agPCIDSS'],
+ 'NIST': AGENTS_PAGE['agNIST'],
+ 'TSC': AGENTS_PAGE['agTSC']
+ }
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/utils/mappers/basic/basic-modules-mapper.js b/test/cypress/cypress/integration/utils/mappers/basic/basic-modules-mapper.js
new file mode 100644
index 0000000000..7b8c1927b0
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/basic/basic-modules-mapper.js
@@ -0,0 +1,18 @@
+import {
+ OVERVIEW_PAGE
+ } from "../../../pageobjects/basic/overview/overview.page";
+
+ export const BASIC_MODULES = {
+ 'Security Events': OVERVIEW_PAGE['securityEvents'],
+ 'Integrity Monitoring': OVERVIEW_PAGE['integrityMonitoring'],
+ 'System Auditing': OVERVIEW_PAGE['systemAuditing'],
+ 'Vulnerabilities': OVERVIEW_PAGE['vulnerabilities'],
+ 'Mitre & Attack': OVERVIEW_PAGE['mitre'],
+ 'GDPR': OVERVIEW_PAGE['gdpr'],
+ 'HIPAA': OVERVIEW_PAGE['hipaa'],
+ 'NIST': OVERVIEW_PAGE['nist'],
+ 'TSC': OVERVIEW_PAGE['tsc'],
+ 'PCIDSS': OVERVIEW_PAGE['pciDSS'],
+ 'Policy Monitoring': OVERVIEW_PAGE['policyMonitoring']
+ }
+
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/utils/mappers/basic/modules-mapper.js b/test/cypress/cypress/integration/utils/mappers/basic/modules-mapper.js
new file mode 100644
index 0000000000..bb21a9d4e5
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/basic/modules-mapper.js
@@ -0,0 +1,34 @@
+import {
+ MODULES_PAGE
+} from '../../../pageobjects/basic/settings/modules.page';
+import {
+ MODULES_DIRECTORY_PAGE
+} from '../../../pageobjects/basic/modules-directory.page';
+
+export const MODULES_CARDS = {
+ 'Amazon AWS': MODULES_PAGE['amazonAWSToggleButton'],
+ 'Google Cloud Platform': MODULES_PAGE['gCPToggleButton'],
+ GitHub: MODULES_PAGE['gitHubCardToggleButton'],
+ OpenSCAP: MODULES_PAGE['openSCAPToggleButton'],
+ 'CIS-CAT': MODULES_PAGE['cisCatToggleButton'],
+ VirusTotal: MODULES_PAGE['virusTotalToggleButton'],
+ Osquery: MODULES_PAGE['osqueryToggleButton'],
+ 'Docker listener': MODULES_PAGE['dockerListenerToggleButton'],
+ GDPR: MODULES_PAGE['gDPRToggleButton'],
+ HIPAA: MODULES_PAGE['hIPAAToggleButton'],
+ TSC: MODULES_PAGE['tSCToggleButton'],
+};
+
+export const MODULES_SETTINGS = {
+ 'Amazon AWS': MODULES_DIRECTORY_PAGE['amazonAWSCard'],
+ 'Google Cloud Platform': MODULES_DIRECTORY_PAGE['gCPCard'],
+ GitHub: MODULES_DIRECTORY_PAGE['gitHubCard'],
+ OpenSCAP: MODULES_DIRECTORY_PAGE['openSCAPCard'],
+ 'CIS-CAT': MODULES_DIRECTORY_PAGE['cisCatCard'],
+ VirusTotal: MODULES_DIRECTORY_PAGE['virusTotalCard'],
+ Osquery: MODULES_DIRECTORY_PAGE['osqueryCard'],
+ 'Docker listener': MODULES_DIRECTORY_PAGE['dockerListenerCard'],
+ GDPR: MODULES_DIRECTORY_PAGE['gDPRCard'],
+ HIPAA: MODULES_DIRECTORY_PAGE['hIPAACard'],
+ TSC: MODULES_DIRECTORY_PAGE['tSCCard'],
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/basic/sample-data-mapper.js b/test/cypress/cypress/integration/utils/mappers/basic/sample-data-mapper.js
new file mode 100644
index 0000000000..039b2d5edd
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/basic/sample-data-mapper.js
@@ -0,0 +1,12 @@
+import {
+ SAMPLE_DATA_PAGE
+} from '../../../pageobjects/basic/settings/sample-data.page';
+
+export const SAMPLE_DATA = {
+ 'security information': SAMPLE_DATA_PAGE['addSecurityInformationDataButton'],
+ 'security information title': SAMPLE_DATA_PAGE['securityInformationDataTitle'],
+ 'auditing and policy monitoring': SAMPLE_DATA_PAGE['addAuditingAndPolicyMonitoringDataButton'],
+ 'auditing and policy monitoring title': SAMPLE_DATA_PAGE['auditingAndPolicyMonitoringDataTitle'],
+ 'threat detection and response': SAMPLE_DATA_PAGE['addThreatDetectionAndResponseDataButton'],
+ 'threat detection and response title': SAMPLE_DATA_PAGE['threatDetectionAndResponseDataTitle'],
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/basic/settings-mapper.js b/test/cypress/cypress/integration/utils/mappers/basic/settings-mapper.js
new file mode 100644
index 0000000000..4b03c9c418
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/basic/settings-mapper.js
@@ -0,0 +1,13 @@
+import {
+ WAZUH_MENU_PAGE
+} from '../../../pageobjects/basic/wazuh-menu/wazuh-menu.page';
+
+export const SETTINGS_MENU_LINKS = {
+ 'API configuration': WAZUH_MENU_PAGE['settingsApiConfigurationLink'],
+ Modules: WAZUH_MENU_PAGE['settingsModulesLink'],
+ 'Sample data': WAZUH_MENU_PAGE['settingsSampleDataLink'],
+ Configuration: WAZUH_MENU_PAGE['settingsConfigurationLink'],
+ Logs: WAZUH_MENU_PAGE['settingsLogsLink'],
+ Miscellaneous: WAZUH_MENU_PAGE['settingsMiscellaneousLink'],
+ About: WAZUH_MENU_PAGE['settingsAboutLink'],
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/modules-mapper-report-data.js b/test/cypress/cypress/integration/utils/mappers/modules-mapper-report-data.js
new file mode 100644
index 0000000000..a3e8de6f13
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/modules-mapper-report-data.js
@@ -0,0 +1,10 @@
+export const REPORT_NAME = {
+ "Security Events":"general",
+ "Integrity Monitonring":"fim",
+ "System Auditing":"audit",
+ "Mitre & Attack":"mitre",
+ NIST:"nist",
+ TSC:"tsc",
+ "Policy Monitoring":"pm",
+ PCIDSS:"pci"
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/odfe-pages-mapper.js b/test/cypress/cypress/integration/utils/mappers/odfe-pages-mapper.js
new file mode 100644
index 0000000000..65527453fb
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/odfe-pages-mapper.js
@@ -0,0 +1,50 @@
+import { DEPLOY_NEW_AGENT_PAGE } from '../../pageobjects/odfe/agents/deploy-new-agent.page';
+import { AGENTS_PAGE } from '../../pageobjects/odfe/agents/agents.page';
+import { FILTERS_PAGE } from '../../pageobjects/odfe/filters/filters.page';
+import { OVERVIEW_PAGE } from '../../pageobjects/odfe/overview/overview.page';
+import { ABOUT_PAGE } from '../../pageobjects/odfe/settings/about.page';
+import { API_CONFIGURATION_PAGE } from '../../pageobjects/odfe/settings/api-configuration.page';
+import { CONFIGURATION_PAGE } from '../../pageobjects/odfe/settings/configuration.page';
+import { LOGS_PAGE } from '../../pageobjects/odfe/settings/logs.page';
+import { MISCELLANEOUS_PAGE } from '../../pageobjects/odfe/settings/miscellaneous.page';
+import { MODULES_PAGE } from '../../pageobjects/odfe/settings/modules.page';
+import { SAMPLE_DATA_PAGE } from '../../pageobjects/odfe/settings/sample-data.page';
+import { DECODERS_PAGE } from '../../pageobjects/odfe/wazuh-menu/decoders.page';
+import { RULES_PAGE } from '../../pageobjects/odfe/wazuh-menu/rules.page';
+import { WAZUH_MENU_PAGE } from '../../pageobjects/odfe/wazuh-menu/wazuh-menu.page';
+import { MODULES_DIRECTORY_PAGE } from '../../pageobjects/odfe/modules-directory.page';
+import { REPORTING_PAGE } from '../../pageobjects/wzd/reporting/report.page';
+
+import { AGENT_MODULES } from './odfe/agent-modules-mapper';
+import { BASIC_MODULES } from './odfe/basic-modules-mapper';
+import { MODULES_CARDS, MODULES_SETTINGS } from './odfe/modules-mapper';
+import { SAMPLE_DATA } from './odfe/sample-data-mapper';
+import { SETTINGS_MENU_LINKS } from './odfe/settings-mapper';
+import { GROUPS_PAGE } from '../../pageobjects/xpack/wazuh-menu/groups.page';
+
+export const ODFE_PAGES_MAPPER = {
+ DEPLOY_NEW_AGENT_PAGE,
+ AGENTS_PAGE,
+ FILTERS_PAGE,
+ OVERVIEW_PAGE,
+ ABOUT_PAGE,
+ API_CONFIGURATION_PAGE,
+ CONFIGURATION_PAGE,
+ LOGS_PAGE,
+ MISCELLANEOUS_PAGE,
+ MODULES_PAGE,
+ SAMPLE_DATA_PAGE,
+ DECODERS_PAGE,
+ RULES_PAGE,
+ WAZUH_MENU_PAGE,
+ MODULES_DIRECTORY_PAGE,
+ REPORTING_PAGE,
+
+ AGENT_MODULES,
+ BASIC_MODULES,
+ MODULES_CARDS,
+ MODULES_SETTINGS,
+ SAMPLE_DATA,
+ SETTINGS_MENU_LINKS,
+ GROUPS_PAGE
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/odfe/agent-modules-mapper.js b/test/cypress/cypress/integration/utils/mappers/odfe/agent-modules-mapper.js
new file mode 100644
index 0000000000..3120704531
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/odfe/agent-modules-mapper.js
@@ -0,0 +1,16 @@
+import {
+AGENTS_PAGE
+ } from '../../../pageobjects/odfe/agents/agents.page';
+
+ export const AGENT_MODULES = {
+ 'Security Events': AGENTS_PAGE['agSecurityEventsLink'],
+ 'Integrity Monitoring': AGENTS_PAGE['agIntegrityMonitoringLink'],
+ 'SCA': AGENTS_PAGE['agSCALink'],
+ 'System Auditing': AGENTS_PAGE['agSystemAuditingLink'],
+ 'Vulnerabilities': AGENTS_PAGE['agVulnerabilitiesLink'],
+ 'Mitre & Attack': AGENTS_PAGE['agMitreAttackLink'],
+ 'Policy Monitoring': AGENTS_PAGE['agPolicyMonitoring'],
+ 'PCIDSS': AGENTS_PAGE['agPCIDSS'],
+ 'NIST': AGENTS_PAGE['agNIST'],
+ 'TSC': AGENTS_PAGE['agTSC']
+ }
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/utils/mappers/odfe/basic-modules-mapper.js b/test/cypress/cypress/integration/utils/mappers/odfe/basic-modules-mapper.js
new file mode 100644
index 0000000000..cffb0d2b2e
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/odfe/basic-modules-mapper.js
@@ -0,0 +1,18 @@
+import {
+ OVERVIEW_PAGE
+ } from "../../../pageobjects/odfe/overview/overview.page";
+
+ export const BASIC_MODULES = {
+ 'Security Events': OVERVIEW_PAGE['securityEvents'],
+ 'Integrity Monitoring': OVERVIEW_PAGE['integrityMonitoring'],
+ 'System Auditing': OVERVIEW_PAGE['systemAuditing'],
+ 'Vulnerabilities': OVERVIEW_PAGE['vulnerabilities'],
+ 'Mitre & Attack': OVERVIEW_PAGE['mitre'],
+ 'GDPR': OVERVIEW_PAGE['gdpr'],
+ 'HIPAA': OVERVIEW_PAGE['hipaa'],
+ 'NIST': OVERVIEW_PAGE['nist'],
+ 'TSC': OVERVIEW_PAGE['tsc'],
+ 'PCIDSS': OVERVIEW_PAGE['pciDSS'],
+ 'Policy Monitoring': OVERVIEW_PAGE['policyMonitoring']
+ }
+
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/utils/mappers/odfe/modules-mapper.js b/test/cypress/cypress/integration/utils/mappers/odfe/modules-mapper.js
new file mode 100644
index 0000000000..0f13240bee
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/odfe/modules-mapper.js
@@ -0,0 +1,34 @@
+import {
+ MODULES_PAGE
+} from '../../../pageobjects/odfe/settings/modules.page';
+import {
+ MODULES_DIRECTORY_PAGE
+} from '../../../pageobjects/odfe/modules-directory.page';
+
+export const MODULES_CARDS = {
+ 'Amazon AWS': MODULES_PAGE['amazonAWSToggleButton'],
+ 'Google Cloud Platform': MODULES_PAGE['gCPToggleButton'],
+ GitHub: MODULES_PAGE['gitHubCardToggleButton'],
+ OpenSCAP: MODULES_PAGE['openSCAPToggleButton'],
+ 'CIS-CAT': MODULES_PAGE['cisCatToggleButton'],
+ VirusTotal: MODULES_PAGE['virusTotalToggleButton'],
+ Osquery: MODULES_PAGE['osqueryToggleButton'],
+ 'Docker listener': MODULES_PAGE['dockerListenerToggleButton'],
+ GDPR: MODULES_PAGE['gDPRToggleButton'],
+ HIPAA: MODULES_PAGE['hIPAAToggleButton'],
+ TSC: MODULES_PAGE['tSCToggleButton'],
+};
+
+export const MODULES_SETTINGS = {
+ 'Amazon AWS': MODULES_DIRECTORY_PAGE['amazonAWSCard'],
+ 'Google Cloud Platform': MODULES_DIRECTORY_PAGE['gCPCard'],
+ GitHub: MODULES_DIRECTORY_PAGE['gitHubCard'],
+ OpenSCAP: MODULES_DIRECTORY_PAGE['openSCAPCard'],
+ 'CIS-CAT': MODULES_DIRECTORY_PAGE['cisCatCard'],
+ VirusTotal: MODULES_DIRECTORY_PAGE['virusTotalCard'],
+ Osquery: MODULES_DIRECTORY_PAGE['osqueryCard'],
+ 'Docker listener': MODULES_DIRECTORY_PAGE['dockerListenerCard'],
+ GDPR: MODULES_DIRECTORY_PAGE['gDPRCard'],
+ HIPAA: MODULES_DIRECTORY_PAGE['hIPAACard'],
+ TSC: MODULES_DIRECTORY_PAGE['tSCCard'],
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/odfe/sample-data-mapper.js b/test/cypress/cypress/integration/utils/mappers/odfe/sample-data-mapper.js
new file mode 100644
index 0000000000..3511e3d5da
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/odfe/sample-data-mapper.js
@@ -0,0 +1,12 @@
+import {
+ SAMPLE_DATA_PAGE
+} from '../../../pageobjects/odfe/settings/sample-data.page';
+
+export const SAMPLE_DATA = {
+ 'security information': SAMPLE_DATA_PAGE['addSecurityInformationDataButton'],
+ 'security information title': SAMPLE_DATA_PAGE['securityInformationDataTitle'],
+ 'auditing and policy monitoring': SAMPLE_DATA_PAGE['addAuditingAndPolicyMonitoringDataButton'],
+ 'auditing and policy monitoring title': SAMPLE_DATA_PAGE['auditingAndPolicyMonitoringDataTitle'],
+ 'threat detection and response': SAMPLE_DATA_PAGE['addThreatDetectionAndResponseDataButton'],
+ 'threat detection and response title': SAMPLE_DATA_PAGE['threatDetectionAndResponseDataTitle'],
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/odfe/settings-mapper.js b/test/cypress/cypress/integration/utils/mappers/odfe/settings-mapper.js
new file mode 100644
index 0000000000..446ab1df40
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/odfe/settings-mapper.js
@@ -0,0 +1,13 @@
+import {
+ WAZUH_MENU_PAGE
+} from '../../../pageobjects/odfe/wazuh-menu/wazuh-menu.page';
+
+export const SETTINGS_MENU_LINKS = {
+ 'API configuration': WAZUH_MENU_PAGE['settingsApiConfigurationLink'],
+ Modules: WAZUH_MENU_PAGE['settingsModulesLink'],
+ 'Sample data': WAZUH_MENU_PAGE['settingsSampleDataLink'],
+ Configuration: WAZUH_MENU_PAGE['settingsConfigurationLink'],
+ Logs: WAZUH_MENU_PAGE['settingsLogsLink'],
+ Miscellaneous: WAZUH_MENU_PAGE['settingsMiscellaneousLink'],
+ About: WAZUH_MENU_PAGE['settingsAboutLink'],
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/wzd-pages-mapper.js b/test/cypress/cypress/integration/utils/mappers/wzd-pages-mapper.js
new file mode 100644
index 0000000000..0354641cba
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/wzd-pages-mapper.js
@@ -0,0 +1,49 @@
+import { DEPLOY_NEW_AGENT_PAGE } from '../../pageobjects/wzd/agents/deploy-new-agent.page';
+import { AGENTS_PAGE } from '../../pageobjects/wzd/agents/agents.page';
+import { FILTERS_PAGE } from '../../pageobjects/wzd/filters/filters.page';
+import { OVERVIEW_PAGE } from '../../pageobjects/wzd/overview/overview.page';
+import { ABOUT_PAGE } from '../../pageobjects/wzd/settings/about.page';
+import { API_CONFIGURATION_PAGE } from '../../pageobjects/wzd/settings/api-configuration.page';
+import { CONFIGURATION_PAGE } from '../../pageobjects/wzd/settings/configuration.page';
+import { LOGS_PAGE } from '../../pageobjects/wzd/settings/logs.page';
+import { MISCELLANEOUS_PAGE } from '../../pageobjects/wzd/settings/miscellaneous.page';
+import { MODULES_PAGE } from '../../pageobjects/wzd/settings/modules.page';
+import { SAMPLE_DATA_PAGE } from '../../pageobjects/wzd/settings/sample-data.page';
+import { DECODERS_PAGE } from '../../pageobjects/wzd/wazuh-menu/decoders.page';
+import { RULES_PAGE } from '../../pageobjects/wzd/wazuh-menu/rules.page';
+import { WAZUH_MENU_PAGE } from '../../pageobjects/wzd/wazuh-menu/wazuh-menu.page';
+import { MODULES_DIRECTORY_PAGE } from '../../pageobjects/wzd/modules-directory.page';
+import { REPORTING_PAGE } from '../../pageobjects/wzd/reporting/report.page';
+
+import { AGENT_MODULES } from './wzd/agent-modules-mapper';
+import { BASIC_MODULES } from './wzd/basic-modules-mapper';
+import { MODULES_CARDS, MODULES_SETTINGS } from './wzd/modules-mapper';
+import { SAMPLE_DATA } from './wzd/sample-data-mapper';
+import { SETTINGS_MENU_LINKS } from './wzd/settings-mapper';
+import { GROUPS_PAGE } from '../../pageobjects/xpack/wazuh-menu/groups.page';
+export const WZD_PAGES_MAPPER = {
+ DEPLOY_NEW_AGENT_PAGE,
+ AGENTS_PAGE,
+ FILTERS_PAGE,
+ OVERVIEW_PAGE,
+ ABOUT_PAGE,
+ API_CONFIGURATION_PAGE,
+ CONFIGURATION_PAGE,
+ LOGS_PAGE,
+ MISCELLANEOUS_PAGE,
+ MODULES_PAGE,
+ SAMPLE_DATA_PAGE,
+ DECODERS_PAGE,
+ RULES_PAGE,
+ WAZUH_MENU_PAGE,
+ MODULES_DIRECTORY_PAGE,
+ REPORTING_PAGE,
+
+ AGENT_MODULES,
+ BASIC_MODULES,
+ MODULES_CARDS,
+ MODULES_SETTINGS,
+ SAMPLE_DATA,
+ SETTINGS_MENU_LINKS,
+ GROUPS_PAGE
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/wzd/agent-modules-mapper.js b/test/cypress/cypress/integration/utils/mappers/wzd/agent-modules-mapper.js
new file mode 100644
index 0000000000..bc70e94407
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/wzd/agent-modules-mapper.js
@@ -0,0 +1,16 @@
+import {
+AGENTS_PAGE
+ } from '../../../pageobjects/wzd/agents/agents.page';
+
+ export const AGENT_MODULES = {
+ 'Security Events': AGENTS_PAGE['agSecurityEventsLink'],
+ 'Integrity Monitoring': AGENTS_PAGE['agIntegrityMonitoringLink'],
+ 'SCA': AGENTS_PAGE['agSCALink'],
+ 'System Auditing': AGENTS_PAGE['agSystemAuditingLink'],
+ 'Vulnerabilities': AGENTS_PAGE['agVulnerabilitiesLink'],
+ 'Mitre & Attack': AGENTS_PAGE['agMitreAttackLink'],
+ 'Policy Monitoring': AGENTS_PAGE['agPolicyMonitoring'],
+ 'PCIDSS': AGENTS_PAGE['agPCIDSS'],
+ 'NIST': AGENTS_PAGE['agNIST'],
+ 'TSC': AGENTS_PAGE['agTSC']
+ }
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/utils/mappers/wzd/basic-modules-mapper.js b/test/cypress/cypress/integration/utils/mappers/wzd/basic-modules-mapper.js
new file mode 100644
index 0000000000..6da280c4e4
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/wzd/basic-modules-mapper.js
@@ -0,0 +1,18 @@
+import {
+ OVERVIEW_PAGE
+ } from "../../../pageobjects/wzd/overview/overview.page";
+
+ export const BASIC_MODULES = {
+ 'Security Events': OVERVIEW_PAGE['securityEvents'],
+ 'Integrity Monitoring': OVERVIEW_PAGE['integrityMonitoring'],
+ 'System Auditing': OVERVIEW_PAGE['systemAuditing'],
+ 'Vulnerabilities': OVERVIEW_PAGE['vulnerabilities'],
+ 'Mitre & Attack': OVERVIEW_PAGE['mitre'],
+ 'GDPR': OVERVIEW_PAGE['gdpr'],
+ 'HIPAA': OVERVIEW_PAGE['hipaa'],
+ 'NIST': OVERVIEW_PAGE['nist'],
+ 'TSC': OVERVIEW_PAGE['tsc'],
+ 'PCIDSS': OVERVIEW_PAGE['pciDSS'],
+ 'Policy Monitoring': OVERVIEW_PAGE['policyMonitoring']
+ }
+
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/utils/mappers/wzd/modules-mapper.js b/test/cypress/cypress/integration/utils/mappers/wzd/modules-mapper.js
new file mode 100644
index 0000000000..22a70ed995
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/wzd/modules-mapper.js
@@ -0,0 +1,34 @@
+import {
+ MODULES_PAGE
+} from '../../../pageobjects/wzd/settings/modules.page';
+import {
+ MODULES_DIRECTORY_PAGE
+} from '../../../pageobjects/wzd/modules-directory.page';
+
+export const MODULES_CARDS = {
+ 'Amazon AWS': MODULES_PAGE['amazonAWSToggleButton'],
+ 'Google Cloud Platform': MODULES_PAGE['gCPToggleButton'],
+ GitHub: MODULES_PAGE['gitHubCardToggleButton'],
+ OpenSCAP: MODULES_PAGE['openSCAPToggleButton'],
+ 'CIS-CAT': MODULES_PAGE['cisCatToggleButton'],
+ VirusTotal: MODULES_PAGE['virusTotalToggleButton'],
+ Osquery: MODULES_PAGE['osqueryToggleButton'],
+ 'Docker listener': MODULES_PAGE['dockerListenerToggleButton'],
+ GDPR: MODULES_PAGE['gDPRToggleButton'],
+ HIPAA: MODULES_PAGE['hIPAAToggleButton'],
+ TSC: MODULES_PAGE['tSCToggleButton'],
+};
+
+export const MODULES_SETTINGS = {
+ 'Amazon AWS': MODULES_DIRECTORY_PAGE['amazonAWSCard'],
+ 'Google Cloud Platform': MODULES_DIRECTORY_PAGE['gCPCard'],
+ GitHub: MODULES_DIRECTORY_PAGE['gitHubCard'],
+ OpenSCAP: MODULES_DIRECTORY_PAGE['openSCAPCard'],
+ 'CIS-CAT': MODULES_DIRECTORY_PAGE['cisCatCard'],
+ VirusTotal: MODULES_DIRECTORY_PAGE['virusTotalCard'],
+ Osquery: MODULES_DIRECTORY_PAGE['osqueryCard'],
+ 'Docker listener': MODULES_DIRECTORY_PAGE['dockerListenerCard'],
+ GDPR: MODULES_DIRECTORY_PAGE['gDPRCard'],
+ HIPAA: MODULES_DIRECTORY_PAGE['hIPAACard'],
+ TSC: MODULES_DIRECTORY_PAGE['tSCCard'],
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/wzd/reporting-modules-mapper.js b/test/cypress/cypress/integration/utils/mappers/wzd/reporting-modules-mapper.js
new file mode 100644
index 0000000000..0960ea5362
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/wzd/reporting-modules-mapper.js
@@ -0,0 +1,7 @@
+import {
+ REPORTING_PAGE
+ } from '../../../pageobjects/wzd/reporting/report.page';
+
+export const REPORTING_PAGE_DATA = {
+ 'generateReportButton': REPORTING_PAGE['generateReportButton']
+}
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/utils/mappers/wzd/sample-data-mapper.js b/test/cypress/cypress/integration/utils/mappers/wzd/sample-data-mapper.js
new file mode 100644
index 0000000000..c098dff4c6
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/wzd/sample-data-mapper.js
@@ -0,0 +1,12 @@
+import {
+ SAMPLE_DATA_PAGE
+} from '../../../pageobjects/wzd/settings/sample-data.page';
+
+export const SAMPLE_DATA = {
+ 'security information': SAMPLE_DATA_PAGE['addSecurityInformationDataButton'],
+ 'security information title': SAMPLE_DATA_PAGE['securityInformationDataTitle'],
+ 'auditing and policy monitoring': SAMPLE_DATA_PAGE['addAuditingAndPolicyMonitoringDataButton'],
+ 'auditing and policy monitoring title': SAMPLE_DATA_PAGE['auditingAndPolicyMonitoringDataTitle'],
+ 'threat detection and response': SAMPLE_DATA_PAGE['addThreatDetectionAndResponseDataButton'],
+ 'threat detection and response title': SAMPLE_DATA_PAGE['threatDetectionAndResponseDataTitle'],
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/wzd/settings-mapper.js b/test/cypress/cypress/integration/utils/mappers/wzd/settings-mapper.js
new file mode 100644
index 0000000000..b20005e828
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/wzd/settings-mapper.js
@@ -0,0 +1,13 @@
+import {
+ WAZUH_MENU_PAGE
+} from '../../../pageobjects/wzd/wazuh-menu/wazuh-menu.page';
+
+export const SETTINGS_MENU_LINKS = {
+ 'API configuration': WAZUH_MENU_PAGE['settingsApiConfigurationLink'],
+ Modules: WAZUH_MENU_PAGE['settingsModulesLink'],
+ 'Sample data': WAZUH_MENU_PAGE['settingsSampleDataLink'],
+ Configuration: WAZUH_MENU_PAGE['settingsConfigurationLink'],
+ Logs: WAZUH_MENU_PAGE['settingsLogsLink'],
+ Miscellaneous: WAZUH_MENU_PAGE['settingsMiscellaneousLink'],
+ About: WAZUH_MENU_PAGE['settingsAboutLink'],
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/xpack-pages-mapper.js b/test/cypress/cypress/integration/utils/mappers/xpack-pages-mapper.js
new file mode 100644
index 0000000000..f7f1763a42
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/xpack-pages-mapper.js
@@ -0,0 +1,51 @@
+import { DEPLOY_NEW_AGENT_PAGE } from '../../pageobjects/xpack/agents/deploy-new-agent.page';
+import { AGENTS_PAGE } from '../../pageobjects/xpack/agents/agents.page';
+import { FILTERS_PAGE } from '../../pageobjects/xpack/filters/filters.page';
+import { OVERVIEW_PAGE } from '../../pageobjects/xpack/overview/overview.page';
+import { ABOUT_PAGE } from '../../pageobjects/xpack/settings/about.page';
+import { API_CONFIGURATION_PAGE } from '../../pageobjects/xpack/settings/api-configuration.page';
+import { CONFIGURATION_PAGE } from '../../pageobjects/xpack/settings/configuration.page';
+import { LOGS_PAGE } from '../../pageobjects/xpack/settings/logs.page';
+import { MISCELLANEOUS_PAGE } from '../../pageobjects/xpack/settings/miscellaneous.page';
+import { MODULES_PAGE } from '../../pageobjects/xpack/settings/modules.page';
+import { SAMPLE_DATA_PAGE } from '../../pageobjects/xpack/settings/sample-data.page';
+import { DECODERS_PAGE } from '../../pageobjects/xpack/wazuh-menu/decoders.page';
+import { RULES_PAGE } from '../../pageobjects/xpack/wazuh-menu/rules.page';
+import { WAZUH_MENU_PAGE } from '../../pageobjects/xpack/wazuh-menu/wazuh-menu.page';
+import { MODULES_DIRECTORY_PAGE } from '../../pageobjects/xpack/modules-directory.page';
+import { GROUPS_PAGE } from '../../pageobjects/xpack/wazuh-menu/groups.page';
+import { AGENT_MODULES } from './xpack/agent-modules-mapper';
+import { BASIC_MODULES } from './xpack/basic-modules-mapper';
+import { MODULES_CARDS, MODULES_SETTINGS } from './xpack/modules-mapper';
+import { SAMPLE_DATA } from './xpack/sample-data-mapper';
+import { SETTINGS_MENU_LINKS } from './xpack/settings-mapper';
+import { REPORTING_PAGE } from '../../pageobjects/wzd/reporting/report.page';
+
+
+export const XPACK_PAGES_MAPPER = {
+ DEPLOY_NEW_AGENT_PAGE,
+ AGENTS_PAGE,
+ FILTERS_PAGE,
+ OVERVIEW_PAGE,
+ ABOUT_PAGE,
+ API_CONFIGURATION_PAGE,
+ CONFIGURATION_PAGE,
+ LOGS_PAGE,
+ MISCELLANEOUS_PAGE,
+ MODULES_PAGE,
+ SAMPLE_DATA_PAGE,
+ DECODERS_PAGE,
+ RULES_PAGE,
+ WAZUH_MENU_PAGE,
+ MODULES_DIRECTORY_PAGE,
+ REPORTING_PAGE,
+
+
+ AGENT_MODULES,
+ BASIC_MODULES,
+ MODULES_CARDS,
+ MODULES_SETTINGS,
+ SAMPLE_DATA,
+ SETTINGS_MENU_LINKS,
+ GROUPS_PAGE
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/xpack/agent-modules-mapper.js b/test/cypress/cypress/integration/utils/mappers/xpack/agent-modules-mapper.js
new file mode 100644
index 0000000000..041b2a3ba5
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/xpack/agent-modules-mapper.js
@@ -0,0 +1,18 @@
+import {
+AGENTS_PAGE
+ } from '../../../pageobjects/xpack/agents/agents.page';
+
+ export const AGENT_MODULES = {
+ 'Security Events': AGENTS_PAGE['agSecurityEventsLink'],
+ 'Integrity Monitoring': AGENTS_PAGE['agIntegrityMonitoringLink'],
+ 'SCA': AGENTS_PAGE['agSCALink'],
+ 'System Auditing': AGENTS_PAGE['agSystemAuditingLink'],
+ 'Vulnerabilities': AGENTS_PAGE['agVulnerabilitiesLink'],
+ 'Mitre & Attack': AGENTS_PAGE['agMitreAttackLink'],
+ 'Policy Monitoring': AGENTS_PAGE['agPolicyMonitoring'],
+ 'PCIDSS': AGENTS_PAGE['agPCIDSS'],
+ 'GDPR': AGENTS_PAGE['agGDPR'],
+ 'HIPAA': AGENTS_PAGE['agHIPAA'],
+ 'NIST': AGENTS_PAGE['agNIST'],
+ 'TSC': AGENTS_PAGE['agTSC']
+ }
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/utils/mappers/xpack/basic-modules-mapper.js b/test/cypress/cypress/integration/utils/mappers/xpack/basic-modules-mapper.js
new file mode 100644
index 0000000000..21fcb51445
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/xpack/basic-modules-mapper.js
@@ -0,0 +1,18 @@
+import {
+ OVERVIEW_PAGE
+ } from "../../../pageobjects/xpack/overview/overview.page";
+
+ export const BASIC_MODULES = {
+ 'Security Events': OVERVIEW_PAGE['securityEvents'],
+ 'Integrity Monitoring': OVERVIEW_PAGE['integrityMonitoring'],
+ 'System Auditing': OVERVIEW_PAGE['systemAuditing'],
+ 'Vulnerabilities': OVERVIEW_PAGE['vulnerabilities'],
+ 'Mitre & Attack': OVERVIEW_PAGE['mitre'],
+ 'GDPR': OVERVIEW_PAGE['gdpr'],
+ 'HIPAA': OVERVIEW_PAGE['hipaa'],
+ 'NIST': OVERVIEW_PAGE['nist'],
+ 'TSC': OVERVIEW_PAGE['tsc'],
+ 'PCIDSS': OVERVIEW_PAGE['pciDSS'],
+ 'Policy Monitoring': OVERVIEW_PAGE['policyMonitoring']
+ }
+
\ No newline at end of file
diff --git a/test/cypress/cypress/integration/utils/mappers/xpack/modules-mapper.js b/test/cypress/cypress/integration/utils/mappers/xpack/modules-mapper.js
new file mode 100644
index 0000000000..3fe4616936
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/xpack/modules-mapper.js
@@ -0,0 +1,34 @@
+import {
+ MODULES_PAGE
+} from '../../../pageobjects/xpack/settings/modules.page';
+import {
+ MODULES_DIRECTORY_PAGE
+} from '../../../pageobjects/xpack/modules-directory.page';
+
+export const MODULES_CARDS = {
+ 'Amazon AWS': MODULES_PAGE['amazonAWSToggleButton'],
+ 'Google Cloud Platform': MODULES_PAGE['gCPToggleButton'],
+ GitHub: MODULES_PAGE['gitHubCardToggleButton'],
+ OpenSCAP: MODULES_PAGE['openSCAPToggleButton'],
+ 'CIS-CAT': MODULES_PAGE['cisCatToggleButton'],
+ VirusTotal: MODULES_PAGE['virusTotalToggleButton'],
+ Osquery: MODULES_PAGE['osqueryToggleButton'],
+ 'Docker listener': MODULES_PAGE['dockerListenerToggleButton'],
+ GDPR: MODULES_PAGE['gDPRToggleButton'],
+ HIPAA: MODULES_PAGE['hIPAAToggleButton'],
+ TSC: MODULES_PAGE['tSCToggleButton'],
+};
+
+export const MODULES_SETTINGS = {
+ 'Amazon AWS': MODULES_DIRECTORY_PAGE['amazonAWSCard'],
+ 'Google Cloud Platform': MODULES_DIRECTORY_PAGE['gCPCard'],
+ GitHub: MODULES_DIRECTORY_PAGE['gitHubCard'],
+ OpenSCAP: MODULES_DIRECTORY_PAGE['openSCAPCard'],
+ 'CIS-CAT': MODULES_DIRECTORY_PAGE['cisCatCard'],
+ VirusTotal: MODULES_DIRECTORY_PAGE['virusTotalCard'],
+ Osquery: MODULES_DIRECTORY_PAGE['osqueryCard'],
+ 'Docker listener': MODULES_DIRECTORY_PAGE['dockerListenerCard'],
+ GDPR: MODULES_DIRECTORY_PAGE['gDPRCard'],
+ HIPAA: MODULES_DIRECTORY_PAGE['hIPAACard'],
+ TSC: MODULES_DIRECTORY_PAGE['tSCCard'],
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/xpack/sample-data-mapper.js b/test/cypress/cypress/integration/utils/mappers/xpack/sample-data-mapper.js
new file mode 100644
index 0000000000..3486ee4678
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/xpack/sample-data-mapper.js
@@ -0,0 +1,12 @@
+import {
+ SAMPLE_DATA_PAGE
+} from '../../../pageobjects/xpack/settings/sample-data.page';
+
+export const SAMPLE_DATA = {
+ 'security information': SAMPLE_DATA_PAGE['addSecurityInformationDataButton'],
+ 'security information title': SAMPLE_DATA_PAGE['securityInformationDataTitle'],
+ 'auditing and policy monitoring': SAMPLE_DATA_PAGE['addAuditingAndPolicyMonitoringDataButton'],
+ 'auditing and policy monitoring title': SAMPLE_DATA_PAGE['auditingAndPolicyMonitoringDataTitle'],
+ 'threat detection and response': SAMPLE_DATA_PAGE['addThreatDetectionAndResponseDataButton'],
+ 'threat detection and response title': SAMPLE_DATA_PAGE['threatDetectionAndResponseDataTitle'],
+};
diff --git a/test/cypress/cypress/integration/utils/mappers/xpack/settings-mapper.js b/test/cypress/cypress/integration/utils/mappers/xpack/settings-mapper.js
new file mode 100644
index 0000000000..bff7e223ff
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/mappers/xpack/settings-mapper.js
@@ -0,0 +1,13 @@
+import {
+ WAZUH_MENU_PAGE
+} from '../../../pageobjects/xpack/wazuh-menu/wazuh-menu.page';
+
+export const SETTINGS_MENU_LINKS = {
+ 'API configuration': WAZUH_MENU_PAGE['settingsApiConfigurationLink'],
+ Modules: WAZUH_MENU_PAGE['settingsModulesLink'],
+ 'Sample data': WAZUH_MENU_PAGE['settingsSampleDataLink'],
+ Configuration: WAZUH_MENU_PAGE['settingsConfigurationLink'],
+ Logs: WAZUH_MENU_PAGE['settingsLogsLink'],
+ Miscellaneous: WAZUH_MENU_PAGE['settingsMiscellaneousLink'],
+ About: WAZUH_MENU_PAGE['settingsAboutLink'],
+};
diff --git a/test/cypress/cypress/integration/utils/pages-constants.js b/test/cypress/cypress/integration/utils/pages-constants.js
new file mode 100644
index 0000000000..0d30edf2d9
--- /dev/null
+++ b/test/cypress/cypress/integration/utils/pages-constants.js
@@ -0,0 +1,24 @@
+export const DEPLOY_NEW_AGENT_PAGE = 'DEPLOY_NEW_AGENT_PAGE';
+export const AGENTS_PAGE = 'AGENTS_PAGE';
+export const FILTERS_PAGE = 'FILTERS_PAGE';
+export const OVERVIEW_PAGE = 'OVERVIEW_PAGE';
+export const ABOUT_PAGE = 'ABOUT_PAGE';
+export const API_CONFIGURATION_PAGE = 'API_CONFIGURATION_PAGE';
+export const CONFIGURATION_PAGE = 'CONFIGURATION_PAGE';
+export const LOGS_PAGE = 'LOGS_PAGE';
+export const MISCELLANEOUS_PAGE = 'MISCELLANEOUS_PAGE';
+export const MODULES_PAGE = 'MODULES_PAGE';
+export const SAMPLE_DATA_PAGE = 'SAMPLE_DATA_PAGE';
+export const DECODERS_PAGE = 'DECODERS_PAGE';
+export const RULES_PAGE = 'RULES_PAGE';
+export const WAZUH_MENU_PAGE = 'WAZUH_MENU_PAGE';
+export const GROUPS_PAGE = 'GROUPS_PAGE';
+export const AGENT_MODULES = 'AGENT_MODULES';
+export const BASIC_MODULES = 'BASIC_MODULES';
+export const MODULES_CARDS = 'MODULES_CARDS';
+export const MODULES_SETTINGS = 'MODULES_SETTINGS';
+export const SAMPLE_DATA = 'SAMPLE_DATA';
+export const SETTINGS_MENU_LINKS = 'SETTINGS_MENU_LINKS';
+export const REPORTING_PAGE = 'REPORTING_PAGE';
+export const MODULES_DIRECTORY_PAGE = 'MODULES_DIRECTORY_PAGE';
+
diff --git a/test/cypress/cypress/plugins/index.js b/test/cypress/cypress/plugins/index.js
new file mode 100644
index 0000000000..43ce579193
--- /dev/null
+++ b/test/cypress/cypress/plugins/index.js
@@ -0,0 +1,26 @@
+///
+// ***********************************************************
+// This example plugins/index.js can be used to load plugins
+//
+// You can change the location of this file or turn off loading
+// the plugins file with the 'pluginsFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/plugins-guide
+// ***********************************************************
+
+// This function is called when a project is opened or re-opened (e.g. due to
+// the project's config changing)
+
+/**
+ * @type {function(*=): function(*=): Promise<*>}
+ */
+// eslint-disable-next-line no-unused-vars
+
+const cucumber = require('cypress-cucumber-preprocessor').default
+
+module.exports = (on, config) => {
+ // `on` is used to hook into various events Cypress emits
+ // `config` is the resolved Cypress config
+ on('file:preprocessor', cucumber());
+};
diff --git a/test/cypress/cypress/support/commands.js b/test/cypress/cypress/support/commands.js
new file mode 100644
index 0000000000..01d470cf7f
--- /dev/null
+++ b/test/cypress/cypress/support/commands.js
@@ -0,0 +1,32 @@
+// ***********************************************
+// This example commands.js shows you how to
+// create various custom commands and overwrite
+// existing commands.
+//
+// For more comprehensive examples of custom
+// commands please read more here:
+// https://on.cypress.io/custom-commands
+// ***********************************************
+//
+//
+// -- This is a parent command --
+// Cypress.Commands.add('login', (email, password) => { ... })
+//
+//
+// -- This is a child command --
+// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
+//
+//
+// -- This is a dual command --
+// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
+//
+//
+// -- This will overwrite an existing command --
+// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
+
+Cypress.Commands.add('setSessionStorage', (key, value) =>
+ cy.window({ log: true }).then((window) => {
+ window.sessionStorage.setItem(key, value)
+ })
+)
+
diff --git a/test/cypress/cypress/support/index.js b/test/cypress/cypress/support/index.js
new file mode 100644
index 0000000000..b8206dc351
--- /dev/null
+++ b/test/cypress/cypress/support/index.js
@@ -0,0 +1,82 @@
+// ***********************************************************
+// This example support/index.js is processed and
+// loaded automatically before your test files.
+//
+// This is a great place to put global configuration and
+// behavior that modifies Cypress.
+//
+// You can change the location of this file or turn off
+// automatically serving support files with the
+// 'supportFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/configuration
+// ***********************************************************
+
+// Import commands.js using ES2015 syntax:
+
+import { LOGIN_TYPE, OVERVIEW_URL } from '../integration/utils/login-constants';
+import {
+ navigate,
+ validateURLIncludes, getSelector
+} from '../integration/utils/driver';
+const loginMethod = Cypress.env('type')
+import './commands';
+require("cypress-xpath");
+const indexPageComp1 = 'react-component[name="StatsOverview"]';
+const indexPageComp2 = 'react-component[name="OverviewWelcome"]';
+import { MODULES_DIRECTORY_PAGE as pageName } from '../integration/utils/pages-constants';
+const userLoginCard = getSelector('userLoginCard', pageName);
+
+before(() => {
+
+ Cypress.on('uncaught:exception', (err, runnable) => {
+ return false;
+ });
+
+ const login = LOGIN_TYPE[loginMethod];
+
+ cy.log(`Parameter loginMethod is: ${loginMethod} and url from loginMethod is: ${Cypress.config('baseUrl')}`);
+
+ // if (Cypress.env('type') == 'odfe') {
+ // navigate("app/kibana?security_tenant=analysts#/visualize/edit/c501fa50-7e52-11e9-ae4e-b5d69947d32e?_g=()")
+ // }
+ // else if (Cypress.env('type') == 'wzd') {
+ // navigate("/");
+ // }
+ // else {
+ navigate("app/wazuh");
+ // }
+
+ login ? login() : cy.log(`Error! loginMethod: "${loginMethod}" is not recognized`);
+
+ cy.get(userLoginCard, { timeout: 18000 }).should('be.visible');
+
+ cy.wait(10000);
+
+ if (Cypress.env('type') != 'odfe') {
+ if (Cypress.env('type') != 'wzd') validateURLIncludes(OVERVIEW_URL);
+ } else {
+ navigate("app/wazuh");
+ };
+
+ cy.get('react-component[name="StatsOverview"]', { timeout: 18000 }).should('be.visible');
+ cy.get('react-component[name="OverviewWelcome"]', { timeout: 18000 }).should('be.visible');
+
+ cy.getCookies().then((cookies) => {
+ cy.log(`Save cookies in cookies.json: ${JSON.stringify(cookies)}`);
+ cy.writeFile('cookies.json', '[]');
+ cy.writeFile('cookies.json', JSON.stringify(cookies));
+ });
+})
+
+beforeEach(() => {
+ cy.readFile('cookies.json').then((cookies) => {
+ cookies.forEach((cookie) => {
+ cy.setCookie(cookie.name, cookie.value);
+ });
+ })
+ cy.setSessionStorage('healthCheck', 'executed');
+ if (Cypress.env('type') != 'wzd') navigate("/");
+}
+)
diff --git a/test/cypress/images/ubuntu-cypress/Dockerfile b/test/cypress/images/ubuntu-cypress/Dockerfile
new file mode 100755
index 0000000000..946de219a9
--- /dev/null
+++ b/test/cypress/images/ubuntu-cypress/Dockerfile
@@ -0,0 +1,33 @@
+FROM ubuntu:18.04
+
+ARG UBUNTU_CYPRESS_BRANCH
+
+ENV AUTOMATION_HOME=/home/automation
+ENV NVM_DIR=/home/automation/nvm
+ENV CYPRESS_DIR=/home/automation/wazuh-cypress
+
+# Install dependencies and download automation repository
+RUN apt-get update -y \
+ && apt-get install -y curl wget gnupg2 vim nano git libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libgconf-2-4 libnss3 libxss1 libasound2 libxtst6 xauth xvfb \
+ && apt-get update -y \
+ && mkdir -p $AUTOMATION_HOME \
+ && git clone --single-branch --depth 1 -b $UBUNTU_CYPRESS_BRANCH https://github.com/wazuh/wazuh-kibana-app.git $CYPRESS_DIR
+
+RUN wget -O /usr/src/google-chrome-stable_current_amd64.deb "https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb" \
+ && dpkg -i /usr/src/google-chrome-stable_current_amd64.deb ; \
+ apt-get install -f -y \
+ && rm -f /usr/src/google-chrome-stable_current_amd64.deb
+RUN google-chrome --version
+
+WORKDIR $AUTOMATION_HOME
+
+# Install nvm with node and npm
+RUN mkdir $NVM_DIR -p \
+ && curl https://raw.githubusercontent.com/creationix/nvm/v0.36.0/install.sh | bash \
+ && chmod u+x $NVM_DIR/nvm.sh \
+ && . $NVM_DIR/nvm.sh \
+ && cd $CYPRESS_DIR/test/cypress/cypress \
+ && nvm install $(cat .nvmrc) \
+ && npm install
+
+WORKDIR $CYPRESS_DIR/test/cypress/
diff --git a/test/cypress/images/wazuh_agent_ubuntu_sources_cmake/Dockerfile b/test/cypress/images/wazuh_agent_ubuntu_sources_cmake/Dockerfile
new file mode 100755
index 0000000000..35b26c5488
--- /dev/null
+++ b/test/cypress/images/wazuh_agent_ubuntu_sources_cmake/Dockerfile
@@ -0,0 +1,34 @@
+FROM ubuntu:18.04
+
+ARG WAZUH_VERSION
+
+# Copy preloaded vars file and entrypoint
+COPY --chown=root:root preloaded-vars.conf entrypoint.sh /scripts/
+
+# Install dependencies
+RUN apt-get update -y \
+ && apt-get -y install python git gnupg2 gcc make vim libc6-dev libc6-dev-mips64-cross curl policycoreutils automake autoconf libtool apt-transport-https lsb-release python-cryptography wget build-essential \
+ && wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null \
+ && echo "deb https://apt.kitware.com/ubuntu/ bionic main" | tee -a /etc/apt/sources.list.d/cmake.list \
+ && apt-get update -y \
+ && apt-get install cmake -y \
+ && curl -Ls https://github.com/wazuh/wazuh/archive/$WAZUH_VERSION.tar.gz | tar zx \
+ && rm -rf /var/lib/apt/lists/* \
+ && WAZUH_TMP_INSTALLER_DIRECTORY="/$(ls | grep wazuh)" \
+ && cp /scripts/preloaded-vars.conf $WAZUH_TMP_INSTALLER_DIRECTORY/etc/ \
+ && $WAZUH_TMP_INSTALLER_DIRECTORY/install.sh \
+ && rm -rf $WAZUH_TMP_INSTALLER_DIRECTORY
+
+WORKDIR /var/ossec
+
+ENTRYPOINT /scripts/entrypoint.sh
+
+### Variables ###
+
+## Arguments
+# WAZUH_VERSION = Define the Wazuh branch to install. [WAZUH_VERSION=v4.0.2]
+
+## Environment
+# JOIN_MANAGER - Manager IP/Domain. [JOIN_MANAGER=172.17.1.2]
+# JOIN_GROUPS - Groups to add the agent. [JOIN_GROUPS=default]
+# JOIN_PASSWORD - Password to register. [JOIN_PASSWORD=password]
\ No newline at end of file
diff --git a/test/cypress/images/wazuh_agent_ubuntu_sources_cmake/entrypoint.sh b/test/cypress/images/wazuh_agent_ubuntu_sources_cmake/entrypoint.sh
new file mode 100755
index 0000000000..33e7629b3b
--- /dev/null
+++ b/test/cypress/images/wazuh_agent_ubuntu_sources_cmake/entrypoint.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+# Register agent if client.keys is empty
+if [ ! -s /var/ossec/etc/client.keys ]; then
+ groups=${JOIN_GROUPS:-default}
+ password=""
+ if [ ! -z ${JOIN_PASSWORD} ]; then
+ password="-P ${JOIN_PASSWORD}"
+ fi
+ manager=${JOIN_MANAGER}
+ sed -i "s:MANAGER_IP:$JOIN_MANAGER:g" /var/ossec/etc/ossec.conf
+ /var/ossec/bin/agent-auth -m $manager -G $groups $password
+fi
+
+# Start the agent
+service wazuh-agent start
+status=$?
+if [ $status -ne 0 ]; then
+ echo "Failed to start agent: $status"
+ exit $status
+fi
+
+echo "Background jobs running, listening for changes"
+
+while sleep 60; do
+ service wazuh-agent status > /dev/null 2>&1
+ status=$?
+ if [ $status -ne 0 ]; then
+ echo "Looks like the agent died."
+ exit 1
+ fi
+done
\ No newline at end of file
diff --git a/test/cypress/images/wazuh_agent_ubuntu_sources_cmake/preloaded-vars.conf b/test/cypress/images/wazuh_agent_ubuntu_sources_cmake/preloaded-vars.conf
new file mode 100755
index 0000000000..89694c7c06
--- /dev/null
+++ b/test/cypress/images/wazuh_agent_ubuntu_sources_cmake/preloaded-vars.conf
@@ -0,0 +1,14 @@
+USER_LANGUAGE="en"
+USER_NO_STOP="y"
+USER_INSTALL_TYPE="agent"
+USER_DIR="/var/ossec"
+#USER_ENABLE_EMAIL="n"
+USER_ENABLE_SYSCHECK="y"
+USER_ENABLE_ROOTCHECK="y"
+USER_ENABLE_OPENSCAP="y"
+USER_WHITE_LIST="n"
+USER_ENABLE_SYSLOG="y"
+USER_ENABLE_AUTHD="y"
+USER_AUTO_START="y"
+USER_AGENT_SERVER_IP="MANAGER_IP"
+USER_CA_STORE="n"
\ No newline at end of file
diff --git a/test/cypress/images/wazuh_manager_filebeat_sources_cmake/Dockerfile b/test/cypress/images/wazuh_manager_filebeat_sources_cmake/Dockerfile
new file mode 100755
index 0000000000..fdd3e01e34
--- /dev/null
+++ b/test/cypress/images/wazuh_manager_filebeat_sources_cmake/Dockerfile
@@ -0,0 +1,47 @@
+FROM ubuntu:18.04
+
+ARG WAZUH_VERSION
+ARG FILEBEAT_VERSION
+ARG FILEBEAT_WAZUH_TEMPLATE_URL
+ARG FILEBEAT_WAZUH_MODULE_URL
+
+COPY --chown=root:root preloaded-vars.conf supervisord.conf /tmp/
+COPY --chown=root:root entrypoint.sh /scripts/entrypoint.sh
+
+RUN apt-get update -y \
+ && apt-get -y install supervisor python git gnupg2 gcc make vim wget build-essential \
+ libc6-dev libc6-dev-mips64-cross curl policycoreutils automake autoconf libtool apt-transport-https lsb-release python-cryptography \
+ && wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null \
+ && echo "deb https://apt.kitware.com/ubuntu/ bionic main" | tee -a /etc/apt/sources.list.d/cmake.list \
+ && apt-get update -y \
+ && apt-get install cmake -y \
+ && rm -rf /var/lib/apt/lists/* \
+ && mkdir -p /var/log/supervisor \
+ && mv /tmp/supervisord.conf /etc/supervisor/conf.d/ \
+ && curl -Ls https://github.com/wazuh/wazuh/archive/$WAZUH_VERSION.tar.gz | tar zx \
+ && WAZUH_TMP_INSTALLER_DIRECTORY="/$(ls | grep wazuh)" \
+ && cp /tmp/preloaded-vars.conf $WAZUH_TMP_INSTALLER_DIRECTORY/etc/ \
+ && $WAZUH_TMP_INSTALLER_DIRECTORY/install.sh \
+ && rm -rf $WAZUH_TMP_INSTALLER_DIRECTORY \
+ && curl -so /tmp/filebeat-installer.deb https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-oss-$FILEBEAT_VERSION-amd64.deb \
+ && dpkg -i /tmp/filebeat-installer.deb \
+ && curl -so /etc/filebeat/wazuh-template.json $FILEBEAT_WAZUH_TEMPLATE_URL \
+ && curl -s $FILEBEAT_WAZUH_MODULE_URL | tar -xvz -C /usr/share/filebeat/module
+
+ENTRYPOINT /scripts/entrypoint.sh
+
+WORKDIR /var/ossec
+
+EXPOSE 514
+EXPOSE 1514
+EXPOSE 1515
+EXPOSE 1516
+EXPOSE 55000
+
+### Variables ###
+
+## Arguments
+# WAZUH_VERSION - Define the Wazuh branch/tag to install. [WAZUH_VERSION=4.1.0]
+# FILEBEAT_VERSION - Filebeat Version
+# FILEBEAT_WAZUH_TEMPLATE_URL - Link with the Wazuh template. [FILEBEAT_WAZUH_TEMPLATE_URL=https://raw.githubusercontent.com/wazuh/wazuh/4.0/extensions/elasticsearch/7.x/wazuh-template.json]
+# FILEBEAT_WAZUH_MODULE_URL - Link with the Wazuh Filebeat module. [FILEBEAT_WAZUH_MODULE_URL=https://packages.wazuh.com/4.x/filebeat/wazuh-filebeat-0.1.tar.gz]
\ No newline at end of file
diff --git a/test/cypress/images/wazuh_manager_filebeat_sources_cmake/entrypoint.sh b/test/cypress/images/wazuh_manager_filebeat_sources_cmake/entrypoint.sh
new file mode 100755
index 0000000000..d716f59f5b
--- /dev/null
+++ b/test/cypress/images/wazuh_manager_filebeat_sources_cmake/entrypoint.sh
@@ -0,0 +1,43 @@
+#!/usr/bin/env bash
+
+WITNESS_FILE_PATH=/tmp/wazuh_configurated
+
+NODE_IP="${NODE_IP:-$1}"
+NODE_NAME="${NODE_NAME:-$2}"
+NODE_TYPE="${NODE_TYPE:-$3}"
+NODE_KEY="${NODE_KEY:-9d273b53510fef702b54a92e9cffc82e}"
+CLUSTER_NAME="${CLUSTER_NAME:-wazuh}"
+CLUSTER_DISABLED="${CLUSTER_DISABLED:-no}"
+
+if [ ! -f $WITNESS_FILE_PATH ]; then
+ # Set right permissions for test_config data
+ chown root:ossec /var/ossec/etc/ossec.conf
+ chown root:ossec /var/ossec/etc/client.keys
+ chown -R ossec:ossec /var/ossec/queue/agent-groups
+ chown -R ossec:ossec /var/ossec/etc/shared
+ chown root:ossec /var/ossec/etc/shared/ar.conf
+ chown -R ossecr:ossec /var/ossec/queue/agent-info
+
+ # Modify ossec.conf
+ sed -i "s: :$NODE_KEY :g" /var/ossec/etc/ossec.conf
+ sed -i "s:NODE_IP :$NODE_IP :g" /var/ossec/etc/ossec.conf
+ sed -i "s:wazuh :$CLUSTER_NAME :g" /var/ossec/etc/ossec.conf
+ sed -i -e "//,/<\/cluster>/ s|[a-z]\+ |$CLUSTER_DISABLED |g" /var/ossec/etc/ossec.conf
+ sed -i "s:node01 :$NODE_NAME :g" /var/ossec/etc/ossec.conf
+ sed -i "s:master :$NODE_TYPE :g" /var/ossec/etc/ossec.conf
+
+ # Create a witness file
+ touch $WITNESS_FILE_PATH
+fi
+
+chown root: /etc/filebeat/filebeat.yml
+chmod go-w /etc/filebeat/filebeat.yml
+
+service filebeat start
+
+sleep 1
+
+service wazuh-manager restart
+/var/ossec/bin/wazuh-apid restart
+
+/usr/bin/supervisord
\ No newline at end of file
diff --git a/test/cypress/images/wazuh_manager_filebeat_sources_cmake/filebeat.yml b/test/cypress/images/wazuh_manager_filebeat_sources_cmake/filebeat.yml
new file mode 100755
index 0000000000..1dcbf07af4
--- /dev/null
+++ b/test/cypress/images/wazuh_manager_filebeat_sources_cmake/filebeat.yml
@@ -0,0 +1,17 @@
+# Wazuh - Filebeat configuration file
+filebeat.modules:
+ - module: wazuh
+ alerts:
+ enabled: true
+ archives:
+ enabled: false
+
+setup.template.json.enabled: true
+setup.template.json.path: '/etc/filebeat/wazuh-template.json'
+setup.template.json.name: 'wazuh'
+setup.template.overwrite: true
+setup.ilm.enabled: false
+
+output.elasticsearch:
+ hosts: ['elasticsearch:9200']
+ protocol: http
\ No newline at end of file
diff --git a/test/cypress/images/wazuh_manager_filebeat_sources_cmake/preloaded-vars.conf b/test/cypress/images/wazuh_manager_filebeat_sources_cmake/preloaded-vars.conf
new file mode 100755
index 0000000000..b495ca4b4a
--- /dev/null
+++ b/test/cypress/images/wazuh_manager_filebeat_sources_cmake/preloaded-vars.conf
@@ -0,0 +1,12 @@
+USER_LANGUAGE="en"
+USER_NO_STOP="y"
+USER_INSTALL_TYPE="server"
+USER_DIR="/var/ossec"
+USER_ENABLE_EMAIL="n"
+USER_ENABLE_SYSCHECK="y"
+USER_ENABLE_ROOTCHECK="y"
+USER_ENABLE_OPENSCAP="y"
+USER_WHITE_LIST="n"
+USER_ENABLE_SYSLOG="y"
+USER_ENABLE_AUTHD="y"
+USER_AUTO_START="y"
\ No newline at end of file
diff --git a/test/cypress/images/wazuh_manager_filebeat_sources_cmake/supervisord.conf b/test/cypress/images/wazuh_manager_filebeat_sources_cmake/supervisord.conf
new file mode 100755
index 0000000000..775a27320a
--- /dev/null
+++ b/test/cypress/images/wazuh_manager_filebeat_sources_cmake/supervisord.conf
@@ -0,0 +1,4 @@
+[supervisord]
+logfile=/supervisord.log
+pidfile=/var/run/supervisord.pid
+nodaemon=true
\ No newline at end of file
diff --git a/test/cypress/package-lock.json b/test/cypress/package-lock.json
new file mode 100644
index 0000000000..629cf6d37a
--- /dev/null
+++ b/test/cypress/package-lock.json
@@ -0,0 +1,15742 @@
+{
+ "name": "wazuh-kibana-app-automation",
+ "version": "1.0.0",
+ "lockfileVersion": 2,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "wazuh-kibana-app-automation",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "cosmiconfig": "^4.0.0",
+ "mocha": "^9.2.2",
+ "prettier": "^2.3.0"
+ },
+ "devDependencies": {
+ "cypress": "^9.5.2",
+ "cypress-cucumber-preprocessor": "^4.0.3",
+ "cypress-xpath": "^1.6.2",
+ "eslint-plugin-cypress": "^2.11.3",
+ "mochawesome": "^7.1.3",
+ "mochawesome-merge": "^4.2.0"
+ },
+ "engines": {
+ "node": "17.3.0"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
+ "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.1.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
+ "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/highlight": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz",
+ "integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz",
+ "integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==",
+ "dev": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.1.0",
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.18.13",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-module-transforms": "^7.18.9",
+ "@babel/helpers": "^7.18.9",
+ "@babel/parser": "^7.18.13",
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.18.13",
+ "@babel/types": "^7.18.13",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.1",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz",
+ "integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.13",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "jsesc": "^2.5.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+ "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz",
+ "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz",
+ "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-explode-assignable-expression": "^7.18.6",
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz",
+ "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.18.8",
+ "@babel/helper-validator-option": "^7.18.6",
+ "browserslist": "^4.20.2",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.13.tgz",
+ "integrity": "sha512-hDvXp+QYxSRL+23mpAlSGxHMDyIGChm0/AwTfTAAK5Ufe40nCsyNdaYCGuK91phn/fVu9kqayImRDkvNAgdrsA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-member-expression-to-functions": "^7.18.9",
+ "@babel/helper-optimise-call-expression": "^7.18.6",
+ "@babel/helper-replace-supers": "^7.18.9",
+ "@babel/helper-split-export-declaration": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-regexp-features-plugin": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz",
+ "integrity": "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "regexpu-core": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-define-polyfill-provider": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.2.tgz",
+ "integrity": "sha512-r9QJJ+uDWrd+94BSPcP6/de67ygLtvVy6cK4luE6MOuDsZIdoaPBnfSpbO/+LTifjPckbKXRuI9BB/Z2/y3iTg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.17.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "debug": "^4.1.1",
+ "lodash.debounce": "^4.0.8",
+ "resolve": "^1.14.2",
+ "semver": "^6.1.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0-0"
+ }
+ },
+ "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
+ "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-explode-assignable-expression": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz",
+ "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz",
+ "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.18.6",
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
+ "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-member-expression-to-functions": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz",
+ "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
+ "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz",
+ "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-simple-access": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "@babel/template": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-optimise-call-expression": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz",
+ "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz",
+ "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-remap-async-to-generator": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz",
+ "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-wrap-function": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-replace-supers": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz",
+ "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-member-expression-to-functions": "^7.18.9",
+ "@babel/helper-optimise-call-expression": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz",
+ "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz",
+ "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
+ "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz",
+ "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
+ "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
+ "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-wrap-function": {
+ "version": "7.18.11",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.11.tgz",
+ "integrity": "sha512-oBUlbv+rjZLh2Ks9SKi4aL7eKaAXBWleHzU89mP0G6BMUlRxSckk9tSIkgDGydhgFxHuGSlBQZfnaD47oBEB7w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.18.11",
+ "@babel/types": "^7.18.10"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz",
+ "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "node_modules/@babel/highlight/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/highlight/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz",
+ "integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==",
+ "dev": true,
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz",
+ "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz",
+ "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9",
+ "@babel/plugin-proposal-optional-chaining": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.13.0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-async-generator-functions": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz",
+ "integrity": "sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-remap-async-to-generator": "^7.18.9",
+ "@babel/plugin-syntax-async-generators": "^7.8.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-class-properties": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz",
+ "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-class-static-block": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz",
+ "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.12.0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-dynamic-import": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz",
+ "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-export-namespace-from": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz",
+ "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-json-strings": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz",
+ "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-json-strings": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-logical-assignment-operators": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz",
+ "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz",
+ "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-numeric-separator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz",
+ "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz",
+ "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.18.8",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-transform-parameters": "^7.18.8"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-optional-catch-binding": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz",
+ "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-optional-chaining": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz",
+ "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-private-methods": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz",
+ "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-private-property-in-object": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz",
+ "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-unicode-property-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz",
+ "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-dynamic-import": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
+ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-export-namespace-from": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
+ "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-assertions": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz",
+ "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz",
+ "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-arrow-functions": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz",
+ "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-async-to-generator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz",
+ "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-remap-async-to-generator": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz",
+ "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoping": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz",
+ "integrity": "sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-classes": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz",
+ "integrity": "sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-optimise-call-expression": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-replace-supers": "^7.18.9",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-computed-properties": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz",
+ "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-destructuring": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz",
+ "integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-dotall-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz",
+ "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-duplicate-keys": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz",
+ "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz",
+ "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-for-of": {
+ "version": "7.18.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz",
+ "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-function-name": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz",
+ "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-literals": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz",
+ "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-member-expression-literals": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz",
+ "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-amd": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz",
+ "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz",
+ "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-simple-access": "^7.18.6",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-systemjs": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz",
+ "integrity": "sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-hoist-variables": "^7.18.6",
+ "@babel/helper-module-transforms": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-umd": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz",
+ "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz",
+ "integrity": "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-new-target": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz",
+ "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-object-super": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz",
+ "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-replace-supers": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-parameters": {
+ "version": "7.18.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz",
+ "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-property-literals": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz",
+ "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-display-name": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz",
+ "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.10.tgz",
+ "integrity": "sha512-gCy7Iikrpu3IZjYZolFE4M1Sm+nrh1/6za2Ewj77Z+XirT4TsbJcvOFOyF+fRPwU6AKKK136CZxx6L8AbSFG6A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-jsx": "^7.18.6",
+ "@babel/types": "^7.18.10"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-development": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz",
+ "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/plugin-transform-react-jsx": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-pure-annotations": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz",
+ "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-regenerator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz",
+ "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "regenerator-transform": "^0.15.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-reserved-words": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz",
+ "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-runtime": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.10.tgz",
+ "integrity": "sha512-q5mMeYAdfEbpBAgzl7tBre/la3LeCxmDO1+wMXRdPWbcoMjR3GiXlCLk7JBZVVye0bqTGNMbt0yYVXX1B1jEWQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "babel-plugin-polyfill-corejs2": "^0.3.2",
+ "babel-plugin-polyfill-corejs3": "^0.5.3",
+ "babel-plugin-polyfill-regenerator": "^0.4.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-runtime/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/plugin-transform-shorthand-properties": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz",
+ "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-spread": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz",
+ "integrity": "sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-sticky-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz",
+ "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-template-literals": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz",
+ "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typeof-symbol": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz",
+ "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-escapes": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz",
+ "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz",
+ "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-env": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.10.tgz",
+ "integrity": "sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.18.8",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-validator-option": "^7.18.6",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9",
+ "@babel/plugin-proposal-async-generator-functions": "^7.18.10",
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
+ "@babel/plugin-proposal-class-static-block": "^7.18.6",
+ "@babel/plugin-proposal-dynamic-import": "^7.18.6",
+ "@babel/plugin-proposal-export-namespace-from": "^7.18.9",
+ "@babel/plugin-proposal-json-strings": "^7.18.6",
+ "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
+ "@babel/plugin-proposal-numeric-separator": "^7.18.6",
+ "@babel/plugin-proposal-object-rest-spread": "^7.18.9",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.18.6",
+ "@babel/plugin-proposal-optional-chaining": "^7.18.9",
+ "@babel/plugin-proposal-private-methods": "^7.18.6",
+ "@babel/plugin-proposal-private-property-in-object": "^7.18.6",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.18.6",
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
+ "@babel/plugin-syntax-import-assertions": "^7.18.6",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5",
+ "@babel/plugin-transform-arrow-functions": "^7.18.6",
+ "@babel/plugin-transform-async-to-generator": "^7.18.6",
+ "@babel/plugin-transform-block-scoped-functions": "^7.18.6",
+ "@babel/plugin-transform-block-scoping": "^7.18.9",
+ "@babel/plugin-transform-classes": "^7.18.9",
+ "@babel/plugin-transform-computed-properties": "^7.18.9",
+ "@babel/plugin-transform-destructuring": "^7.18.9",
+ "@babel/plugin-transform-dotall-regex": "^7.18.6",
+ "@babel/plugin-transform-duplicate-keys": "^7.18.9",
+ "@babel/plugin-transform-exponentiation-operator": "^7.18.6",
+ "@babel/plugin-transform-for-of": "^7.18.8",
+ "@babel/plugin-transform-function-name": "^7.18.9",
+ "@babel/plugin-transform-literals": "^7.18.9",
+ "@babel/plugin-transform-member-expression-literals": "^7.18.6",
+ "@babel/plugin-transform-modules-amd": "^7.18.6",
+ "@babel/plugin-transform-modules-commonjs": "^7.18.6",
+ "@babel/plugin-transform-modules-systemjs": "^7.18.9",
+ "@babel/plugin-transform-modules-umd": "^7.18.6",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6",
+ "@babel/plugin-transform-new-target": "^7.18.6",
+ "@babel/plugin-transform-object-super": "^7.18.6",
+ "@babel/plugin-transform-parameters": "^7.18.8",
+ "@babel/plugin-transform-property-literals": "^7.18.6",
+ "@babel/plugin-transform-regenerator": "^7.18.6",
+ "@babel/plugin-transform-reserved-words": "^7.18.6",
+ "@babel/plugin-transform-shorthand-properties": "^7.18.6",
+ "@babel/plugin-transform-spread": "^7.18.9",
+ "@babel/plugin-transform-sticky-regex": "^7.18.6",
+ "@babel/plugin-transform-template-literals": "^7.18.9",
+ "@babel/plugin-transform-typeof-symbol": "^7.18.9",
+ "@babel/plugin-transform-unicode-escapes": "^7.18.10",
+ "@babel/plugin-transform-unicode-regex": "^7.18.6",
+ "@babel/preset-modules": "^0.1.5",
+ "@babel/types": "^7.18.10",
+ "babel-plugin-polyfill-corejs2": "^0.3.2",
+ "babel-plugin-polyfill-corejs3": "^0.5.3",
+ "babel-plugin-polyfill-regenerator": "^0.4.0",
+ "core-js-compat": "^3.22.1",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-env/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/preset-modules": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz",
+ "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
+ "@babel/plugin-transform-dotall-regex": "^7.4.4",
+ "@babel/types": "^7.4.4",
+ "esutils": "^2.0.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-react": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz",
+ "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-validator-option": "^7.18.6",
+ "@babel/plugin-transform-react-display-name": "^7.18.6",
+ "@babel/plugin-transform-react-jsx": "^7.18.6",
+ "@babel/plugin-transform-react-jsx-development": "^7.18.6",
+ "@babel/plugin-transform-react-pure-annotations": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz",
+ "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==",
+ "dev": true,
+ "dependencies": {
+ "regenerator-runtime": "^0.13.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
+ "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/parser": "^7.18.10",
+ "@babel/types": "^7.18.10"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz",
+ "integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.18.13",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-hoist-variables": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/parser": "^7.18.13",
+ "@babel/types": "^7.18.13",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz",
+ "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@colors/colors": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
+ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "node_modules/@cypress/browserify-preprocessor": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@cypress/browserify-preprocessor/-/browserify-preprocessor-3.0.2.tgz",
+ "integrity": "sha512-y6mlFR+IR2cqcm3HabSp7AEcX9QfF1EUL4eOaw/7xexdhmdQU8ez6piyRopZQob4BK8oKTsc9PkupsU2rzjqMA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.16.0",
+ "@babel/plugin-proposal-class-properties": "^7.16.0",
+ "@babel/plugin-proposal-object-rest-spread": "^7.16.0",
+ "@babel/plugin-transform-runtime": "^7.16.0",
+ "@babel/preset-env": "^7.16.0",
+ "@babel/preset-react": "^7.16.0",
+ "@babel/runtime": "^7.16.0",
+ "babel-plugin-add-module-exports": "^1.0.4",
+ "babelify": "^10.0.0",
+ "bluebird": "^3.7.2",
+ "browserify": "^16.2.3",
+ "coffeeify": "^3.0.1",
+ "coffeescript": "^1.12.7",
+ "debug": "^4.3.2",
+ "fs-extra": "^9.0.0",
+ "lodash.clonedeep": "^4.5.0",
+ "through2": "^2.0.0",
+ "watchify": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@cypress/request": {
+ "version": "2.88.10",
+ "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.10.tgz",
+ "integrity": "sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==",
+ "dev": true,
+ "dependencies": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "http-signature": "~1.3.6",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.5.0",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^8.3.2"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@cypress/xvfb": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz",
+ "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.1.0",
+ "lodash.once": "^4.1.1"
+ }
+ },
+ "node_modules/@cypress/xvfb/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.1.tgz",
+ "integrity": "sha512-OhSY22oQQdw3zgPOOwdoj01l/Dzl1Z+xyUP33tkSN+aqyEhymJCcPHyXt+ylW8FSe0TfRC2VG+ROQOapD0aZSQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.4.0",
+ "globals": "^13.15.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "13.17.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz",
+ "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
+ "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^1.2.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/gitignore-to-minimatch": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz",
+ "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==",
+ "dev": true,
+ "peer": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
+ "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.0",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz",
+ "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "14.18.26",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.26.tgz",
+ "integrity": "sha512-0b+utRBSYj8L7XAp0d+DX7lI4cSmowNaaTkk6/1SKzbKkG+doLuPusB9EOvzLJ8ahJSk03bTLIL6cWaEd4dBKA==",
+ "dev": true
+ },
+ "node_modules/@types/sinonjs__fake-timers": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz",
+ "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==",
+ "dev": true
+ },
+ "node_modules/@types/sizzle": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
+ "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
+ "dev": true
+ },
+ "node_modules/@types/yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@ungap/promise-all-settled": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
+ "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q=="
+ },
+ "node_modules/acorn": {
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
+ "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peer": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/acorn-node": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz",
+ "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^7.0.0",
+ "acorn-walk": "^7.0.0",
+ "xtend": "^4.0.2"
+ }
+ },
+ "node_modules/acorn-node/node_modules/acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-walk": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
+ "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/aggregate-error/node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+ "dev": true
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+ "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/arch": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz",
+ "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/asn1": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+ "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
+ "dev": true,
+ "dependencies": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "node_modules/asn1.js": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
+ "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "node_modules/asn1.js/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/assert": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
+ "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==",
+ "dev": true,
+ "dependencies": {
+ "object-assign": "^4.1.1",
+ "util": "0.10.3"
+ }
+ },
+ "node_modules/assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/assert/node_modules/inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==",
+ "dev": true
+ },
+ "node_modules/assert/node_modules/util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "2.0.1"
+ }
+ },
+ "node_modules/assertion-error": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/assertion-error-formatter": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error-formatter/-/assertion-error-formatter-2.0.1.tgz",
+ "integrity": "sha512-cjC3jUCh9spkroKue5PDSKH5RFQ/KNuZJhk3GwHYmB/8qqETxLOmMdLH+ohi/VukNzxDlMvIe7zScvLoOdhb6Q==",
+ "dev": true,
+ "dependencies": {
+ "diff": "^3.0.0",
+ "pad-right": "^0.2.2",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "node_modules/astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/async": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
+ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==",
+ "dev": true
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "dev": true
+ },
+ "node_modules/at-least-node": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
+ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/aws4": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-add-module-exports": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.4.tgz",
+ "integrity": "sha512-g+8yxHUZ60RcyaUpfNzy56OtWW+x9cyEe9j+CranqLiqbju2yf/Cy6ZtYK40EZxtrdHllzlVZgLmcOUCTlJ7Jg==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-dynamic-import-node": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
+ "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
+ "dev": true,
+ "dependencies": {
+ "object.assign": "^4.1.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs2": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.2.tgz",
+ "integrity": "sha512-LPnodUl3lS0/4wN3Rb+m+UK8s7lj2jcLRrjho4gLw+OJs+I4bvGXshINesY5xx/apM+biTnQ9reDI8yj+0M5+Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.17.7",
+ "@babel/helper-define-polyfill-provider": "^0.3.2",
+ "semver": "^6.1.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs3": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz",
+ "integrity": "sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.3.2",
+ "core-js-compat": "^3.21.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-regenerator": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.0.tgz",
+ "integrity": "sha512-RW1cnryiADFeHmfLS+WW/G431p1PsW5qdRdz0SDRi7TKcUgc7Oh/uXkT7MZ/+tGsT1BkczEAmD5XjUyJ5SWDTw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.3.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
+ "dev": true,
+ "dependencies": {
+ "core-js": "^2.4.0",
+ "regenerator-runtime": "^0.11.0"
+ }
+ },
+ "node_modules/babel-runtime/node_modules/regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+ "dev": true
+ },
+ "node_modules/babelify": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/babelify/-/babelify-10.0.0.tgz",
+ "integrity": "sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
+ "dev": true,
+ "dependencies": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "node_modules/becke-ch--regex--s0-0-v1--base--pl--lib": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/becke-ch--regex--s0-0-v1--base--pl--lib/-/becke-ch--regex--s0-0-v1--base--pl--lib-1.4.0.tgz",
+ "integrity": "sha512-FnWonOyaw7Vivg5nIkrUll9HSS5TjFbyuURAiDssuL6VxrBe3ERzudRxOcWRhZYlP89UArMDikz7SapRPQpmZQ==",
+ "dev": true
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/blob-util": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz",
+ "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==",
+ "dev": true
+ },
+ "node_modules/bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+ "dev": true
+ },
+ "node_modules/bn.js": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
+ "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==",
+ "dev": true
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==",
+ "dev": true
+ },
+ "node_modules/browser-pack": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz",
+ "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==",
+ "dev": true,
+ "dependencies": {
+ "combine-source-map": "~0.8.0",
+ "defined": "^1.0.0",
+ "JSONStream": "^1.0.3",
+ "safe-buffer": "^5.1.1",
+ "through2": "^2.0.0",
+ "umd": "^3.0.0"
+ },
+ "bin": {
+ "browser-pack": "bin/cmd.js"
+ }
+ },
+ "node_modules/browser-resolve": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz",
+ "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==",
+ "dev": true,
+ "dependencies": {
+ "resolve": "^1.17.0"
+ }
+ },
+ "node_modules/browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
+ },
+ "node_modules/browserify": {
+ "version": "16.5.2",
+ "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.5.2.tgz",
+ "integrity": "sha512-TkOR1cQGdmXU9zW4YukWzWVSJwrxmNdADFbqbE3HFgQWe5wqZmOawqZ7J/8MPCwk/W8yY7Y0h+7mOtcZxLP23g==",
+ "dev": true,
+ "dependencies": {
+ "assert": "^1.4.0",
+ "browser-pack": "^6.0.1",
+ "browser-resolve": "^2.0.0",
+ "browserify-zlib": "~0.2.0",
+ "buffer": "~5.2.1",
+ "cached-path-relative": "^1.0.0",
+ "concat-stream": "^1.6.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "~1.0.0",
+ "crypto-browserify": "^3.0.0",
+ "defined": "^1.0.0",
+ "deps-sort": "^2.0.0",
+ "domain-browser": "^1.2.0",
+ "duplexer2": "~0.1.2",
+ "events": "^2.0.0",
+ "glob": "^7.1.0",
+ "has": "^1.0.0",
+ "htmlescape": "^1.1.0",
+ "https-browserify": "^1.0.0",
+ "inherits": "~2.0.1",
+ "insert-module-globals": "^7.0.0",
+ "JSONStream": "^1.0.3",
+ "labeled-stream-splicer": "^2.0.0",
+ "mkdirp-classic": "^0.5.2",
+ "module-deps": "^6.2.3",
+ "os-browserify": "~0.3.0",
+ "parents": "^1.0.1",
+ "path-browserify": "~0.0.0",
+ "process": "~0.11.0",
+ "punycode": "^1.3.2",
+ "querystring-es3": "~0.2.0",
+ "read-only-stream": "^2.0.0",
+ "readable-stream": "^2.0.2",
+ "resolve": "^1.1.4",
+ "shasum": "^1.0.0",
+ "shell-quote": "^1.6.1",
+ "stream-browserify": "^2.0.0",
+ "stream-http": "^3.0.0",
+ "string_decoder": "^1.1.1",
+ "subarg": "^1.0.0",
+ "syntax-error": "^1.1.1",
+ "through2": "^2.0.0",
+ "timers-browserify": "^1.0.1",
+ "tty-browserify": "0.0.1",
+ "url": "~0.11.0",
+ "util": "~0.10.1",
+ "vm-browserify": "^1.0.0",
+ "xtend": "^4.0.0"
+ },
+ "bin": {
+ "browserify": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/browserify-aes": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+ "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+ "dev": true,
+ "dependencies": {
+ "buffer-xor": "^1.0.3",
+ "cipher-base": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.3",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/browserify-cipher": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+ "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+ "dev": true,
+ "dependencies": {
+ "browserify-aes": "^1.0.4",
+ "browserify-des": "^1.0.0",
+ "evp_bytestokey": "^1.0.0"
+ }
+ },
+ "node_modules/browserify-des": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+ "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+ "dev": true,
+ "dependencies": {
+ "cipher-base": "^1.0.1",
+ "des.js": "^1.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "node_modules/browserify-rsa": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz",
+ "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^5.0.0",
+ "randombytes": "^2.0.1"
+ }
+ },
+ "node_modules/browserify-sign": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz",
+ "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^5.1.1",
+ "browserify-rsa": "^4.0.1",
+ "create-hash": "^1.2.0",
+ "create-hmac": "^1.1.7",
+ "elliptic": "^6.5.3",
+ "inherits": "^2.0.4",
+ "parse-asn1": "^5.1.5",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ }
+ },
+ "node_modules/browserify-sign/node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/browserify-zlib": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+ "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+ "dev": true,
+ "dependencies": {
+ "pako": "~1.0.5"
+ }
+ },
+ "node_modules/browserify/node_modules/buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz",
+ "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==",
+ "dev": true,
+ "dependencies": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.21.3",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz",
+ "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001370",
+ "electron-to-chromium": "^1.4.202",
+ "node-releases": "^2.0.6",
+ "update-browserslist-db": "^1.0.5"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true
+ },
+ "node_modules/buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==",
+ "dev": true
+ },
+ "node_modules/builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==",
+ "dev": true
+ },
+ "node_modules/cached-path-relative": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.1.0.tgz",
+ "integrity": "sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==",
+ "dev": true
+ },
+ "node_modules/cachedir": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz",
+ "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001384",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001384.tgz",
+ "integrity": "sha512-BBWt57kqWbc0GYZXb47wTXpmAgqr5LSibPzNjk/AWMdmJMQhLqOl3c/Kd4OAU/tu4NLfYkMx8Tlq3RVBkOBolQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ }
+ ]
+ },
+ "node_modules/caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
+ "dev": true
+ },
+ "node_modules/chai": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
+ "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
+ "dev": true,
+ "dependencies": {
+ "assertion-error": "^1.1.0",
+ "check-error": "^1.0.2",
+ "deep-eql": "^3.0.1",
+ "get-func-name": "^2.0.0",
+ "loupe": "^2.3.1",
+ "pathval": "^1.1.1",
+ "type-detect": "^4.0.5"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chalk/node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/check-error": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+ "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/check-more-types": {
+ "version": "2.24.0",
+ "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz",
+ "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
+ "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
+ "dev": true,
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz",
+ "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==",
+ "dev": true
+ },
+ "node_modules/cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "dependencies": {
+ "restore-cursor": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cli-table": {
+ "version": "0.3.11",
+ "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz",
+ "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==",
+ "dev": true,
+ "dependencies": {
+ "colors": "1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.2.0"
+ }
+ },
+ "node_modules/cli-table/node_modules/colors": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
+ "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "node_modules/cli-table3": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz",
+ "integrity": "sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0"
+ },
+ "engines": {
+ "node": "10.* || >= 12.*"
+ },
+ "optionalDependencies": {
+ "@colors/colors": "1.5.0"
+ }
+ },
+ "node_modules/cli-truncate": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
+ "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
+ "dev": true,
+ "dependencies": {
+ "slice-ansi": "^3.0.0",
+ "string-width": "^4.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "node_modules/coffeeify": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/coffeeify/-/coffeeify-3.0.1.tgz",
+ "integrity": "sha512-Qjnr7UX6ldK1PHV7wCnv7AuCd4q19KTUtwJnu/6JRJB4rfm12zvcXtKdacUoePOKr1I4ka/ydKiwWpNAdsQb0g==",
+ "dev": true,
+ "dependencies": {
+ "convert-source-map": "^1.3.0",
+ "through2": "^2.0.0"
+ },
+ "peerDependencies": {
+ "coffeescript": ">1.9.2 <3"
+ }
+ },
+ "node_modules/coffeescript": {
+ "version": "1.12.7",
+ "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.12.7.tgz",
+ "integrity": "sha512-pLXHFxQMPklVoEekowk8b3erNynC+DVJzChxS/LCBBgR6/8AJkHivkm//zbowcfc7BTCAjryuhx6gPqPRfsFoA==",
+ "dev": true,
+ "bin": {
+ "cake": "bin/cake",
+ "coffee": "bin/coffee"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/colorette": {
+ "version": "2.0.19",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz",
+ "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==",
+ "dev": true
+ },
+ "node_modules/colors": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.1.90"
+ }
+ },
+ "node_modules/combine-source-map": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz",
+ "integrity": "sha512-UlxQ9Vw0b/Bt/KYwCFqdEwsQ1eL8d1gibiFb7lxQJFdvTgc2hIZi6ugsg+kyhzhPV+QEpUiEIwInIAIrgoEkrg==",
+ "dev": true,
+ "dependencies": {
+ "convert-source-map": "~1.1.0",
+ "inline-source-map": "~0.6.0",
+ "lodash.memoize": "~3.0.3",
+ "source-map": "~0.5.3"
+ }
+ },
+ "node_modules/combine-source-map/node_modules/convert-source-map": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz",
+ "integrity": "sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg==",
+ "dev": true
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/common-tags": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz",
+ "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ },
+ "node_modules/concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "dev": true,
+ "engines": [
+ "node >= 0.8"
+ ],
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "node_modules/console-browserify": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
+ "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==",
+ "dev": true
+ },
+ "node_modules/constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+ "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==",
+ "dev": true
+ },
+ "node_modules/convert-source-map": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
+ "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.1.1"
+ }
+ },
+ "node_modules/convert-source-map/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "node_modules/core-js": {
+ "version": "2.6.12",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
+ "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
+ "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
+ "dev": true,
+ "hasInstallScript": true
+ },
+ "node_modules/core-js-compat": {
+ "version": "3.25.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.0.tgz",
+ "integrity": "sha512-extKQM0g8/3GjFx9US12FAgx8KJawB7RCQ5y8ipYLbmfzEzmFRWdDjIlxDx82g7ygcNG85qMVUSRyABouELdow==",
+ "dev": true,
+ "dependencies": {
+ "browserslist": "^4.21.3",
+ "semver": "7.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "node_modules/core-js-compat/node_modules/semver": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
+ "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true
+ },
+ "node_modules/cosmiconfig": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz",
+ "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==",
+ "dependencies": {
+ "is-directory": "^0.3.1",
+ "js-yaml": "^3.9.0",
+ "parse-json": "^4.0.0",
+ "require-from-string": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/create-ecdh": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
+ "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.1.0",
+ "elliptic": "^6.5.3"
+ }
+ },
+ "node_modules/create-ecdh/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/create-hash": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+ "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+ "dev": true,
+ "dependencies": {
+ "cipher-base": "^1.0.1",
+ "inherits": "^2.0.1",
+ "md5.js": "^1.3.4",
+ "ripemd160": "^2.0.1",
+ "sha.js": "^2.4.0"
+ }
+ },
+ "node_modules/create-hmac": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+ "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+ "dev": true,
+ "dependencies": {
+ "cipher-base": "^1.0.3",
+ "create-hash": "^1.1.0",
+ "inherits": "^2.0.1",
+ "ripemd160": "^2.0.0",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/crypto-browserify": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+ "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+ "dev": true,
+ "dependencies": {
+ "browserify-cipher": "^1.0.0",
+ "browserify-sign": "^4.0.0",
+ "create-ecdh": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.0",
+ "diffie-hellman": "^5.0.0",
+ "inherits": "^2.0.1",
+ "pbkdf2": "^3.0.3",
+ "public-encrypt": "^4.0.0",
+ "randombytes": "^2.0.0",
+ "randomfill": "^1.0.3"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/cucumber": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/cucumber/-/cucumber-4.2.1.tgz",
+ "integrity": "sha512-3gQ0Vv4kSHsvXEFC6b1c+TfLRDzWD1/kU7e5vm8Kh8j35b95k6favan9/4ixcBNqd7UsU1T6FYcawC87+DlNKw==",
+ "deprecated": "Cucumber is publishing new releases under @cucumber/cucumber",
+ "dev": true,
+ "dependencies": {
+ "assertion-error-formatter": "^2.0.1",
+ "babel-runtime": "^6.11.6",
+ "bluebird": "^3.4.1",
+ "cli-table": "^0.3.1",
+ "colors": "^1.1.2",
+ "commander": "^2.9.0",
+ "cucumber-expressions": "^5.0.13",
+ "cucumber-tag-expressions": "^1.1.1",
+ "duration": "^0.2.0",
+ "escape-string-regexp": "^1.0.5",
+ "figures": "2.0.0",
+ "gherkin": "^5.0.0",
+ "glob": "^7.0.0",
+ "indent-string": "^3.1.0",
+ "is-generator": "^1.0.2",
+ "is-stream": "^1.1.0",
+ "knuth-shuffle-seeded": "^1.0.6",
+ "lodash": "^4.17.4",
+ "mz": "^2.4.0",
+ "progress": "^2.0.0",
+ "resolve": "^1.3.3",
+ "serialize-error": "^2.1.0",
+ "stack-chain": "^2.0.0",
+ "stacktrace-js": "^2.0.0",
+ "string-argv": "0.0.2",
+ "title-case": "^2.1.1",
+ "util-arity": "^1.0.2",
+ "verror": "^1.9.0"
+ },
+ "bin": {
+ "cucumber-js": "bin/cucumber-js"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/cucumber-expressions": {
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/cucumber-expressions/-/cucumber-expressions-6.6.2.tgz",
+ "integrity": "sha512-WcFSVBiWNLJbIcAAC3t/ACU46vaOKfe1UIF5H3qveoq+Y4XQm9j3YwHurQNufRKBBg8nCnpU7Ttsx7egjS3hwA==",
+ "deprecated": "This package is now published under @cucumber/cucumber-expressions",
+ "dev": true,
+ "dependencies": {
+ "becke-ch--regex--s0-0-v1--base--pl--lib": "^1.2.0"
+ }
+ },
+ "node_modules/cucumber-tag-expressions": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cucumber-tag-expressions/-/cucumber-tag-expressions-1.1.1.tgz",
+ "integrity": "sha512-V9jv81sR/HaJ87FoidrvHkviXId7KmBcUi7aQPfi+W3nRO30N6GqH6lcp8K+nyiT1DgemRJBPDDeBMS93xJqMQ==",
+ "dev": true
+ },
+ "node_modules/cucumber/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true
+ },
+ "node_modules/cucumber/node_modules/cucumber-expressions": {
+ "version": "5.0.18",
+ "resolved": "https://registry.npmjs.org/cucumber-expressions/-/cucumber-expressions-5.0.18.tgz",
+ "integrity": "sha512-cj9UKCEvsB7bN97THmowcZt8I3rYFbTAFBNeDpKmWW3vr43CLZeWBmbk7NlHijndLwPJ7+uiF72xWrRU+RLyZA==",
+ "deprecated": "This package is now published under @cucumber/cucumber-expressions",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "becke-ch--regex--s0-0-v1--base--pl--lib": "^1.2.0"
+ }
+ },
+ "node_modules/cucumber/node_modules/figures": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+ "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/cypress": {
+ "version": "9.7.0",
+ "resolved": "https://registry.npmjs.org/cypress/-/cypress-9.7.0.tgz",
+ "integrity": "sha512-+1EE1nuuuwIt/N1KXRR2iWHU+OiIt7H28jJDyyI4tiUftId/DrXYEwoDa5+kH2pki1zxnA0r6HrUGHV5eLbF5Q==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "@cypress/request": "^2.88.10",
+ "@cypress/xvfb": "^1.2.4",
+ "@types/node": "^14.14.31",
+ "@types/sinonjs__fake-timers": "8.1.1",
+ "@types/sizzle": "^2.3.2",
+ "arch": "^2.2.0",
+ "blob-util": "^2.0.2",
+ "bluebird": "^3.7.2",
+ "buffer": "^5.6.0",
+ "cachedir": "^2.3.0",
+ "chalk": "^4.1.0",
+ "check-more-types": "^2.24.0",
+ "cli-cursor": "^3.1.0",
+ "cli-table3": "~0.6.1",
+ "commander": "^5.1.0",
+ "common-tags": "^1.8.0",
+ "dayjs": "^1.10.4",
+ "debug": "^4.3.2",
+ "enquirer": "^2.3.6",
+ "eventemitter2": "^6.4.3",
+ "execa": "4.1.0",
+ "executable": "^4.1.1",
+ "extract-zip": "2.0.1",
+ "figures": "^3.2.0",
+ "fs-extra": "^9.1.0",
+ "getos": "^3.2.1",
+ "is-ci": "^3.0.0",
+ "is-installed-globally": "~0.4.0",
+ "lazy-ass": "^1.6.0",
+ "listr2": "^3.8.3",
+ "lodash": "^4.17.21",
+ "log-symbols": "^4.0.0",
+ "minimist": "^1.2.6",
+ "ospath": "^1.2.2",
+ "pretty-bytes": "^5.6.0",
+ "proxy-from-env": "1.0.0",
+ "request-progress": "^3.0.0",
+ "semver": "^7.3.2",
+ "supports-color": "^8.1.1",
+ "tmp": "~0.2.1",
+ "untildify": "^4.0.0",
+ "yauzl": "^2.10.0"
+ },
+ "bin": {
+ "cypress": "bin/cypress"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/cypress-cucumber-preprocessor": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/cypress-cucumber-preprocessor/-/cypress-cucumber-preprocessor-4.3.1.tgz",
+ "integrity": "sha512-BKUYXqoTeKzkPXohEczDtpAwRCY0ZPtIpfRwJut16yNLqdXQMV+aItwanxe3cbJTFlwg562NAjL4LMdiOhkAjg==",
+ "dev": true,
+ "dependencies": {
+ "@cypress/browserify-preprocessor": "^3.0.2",
+ "chai": "^4.2.0",
+ "chokidar": "3.5.2",
+ "cosmiconfig": "^4.0.0",
+ "cucumber": "^4.2.1",
+ "cucumber-expressions": "^6.0.1",
+ "cucumber-tag-expressions": "^1.1.1",
+ "dargs": "^7.0.0",
+ "debug": "^3.0.1",
+ "gherkin": "^5.1.0",
+ "glob": "^7.1.2",
+ "js-string-escape": "^1.0.1",
+ "minimist": "^1.2.5",
+ "through": "^2.3.8"
+ },
+ "bin": {
+ "cypress-tags": "cypress-tags.js"
+ }
+ },
+ "node_modules/cypress-cucumber-preprocessor/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/cypress-xpath": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/cypress-xpath/-/cypress-xpath-1.8.0.tgz",
+ "integrity": "sha512-a76JxNgkYwKCi8tJkY6DjLV8NQ2TBBFA4pIcq5nMDIGOee2DnIIbYbD0ucT7qxF2LSwOow/Ze49WhaTL4pRPmg==",
+ "dev": true
+ },
+ "node_modules/d": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
+ "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
+ "dev": true,
+ "dependencies": {
+ "es5-ext": "^0.10.50",
+ "type": "^1.0.1"
+ }
+ },
+ "node_modules/dargs": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz",
+ "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dash-ast": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz",
+ "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==",
+ "dev": true
+ },
+ "node_modules/dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
+ "dev": true,
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/dateformat": {
+ "version": "4.6.3",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz",
+ "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/dayjs": {
+ "version": "1.11.5",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz",
+ "integrity": "sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==",
+ "dev": true
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/deep-eql": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
+ "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+ "dev": true,
+ "dependencies": {
+ "type-detect": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/define-properties": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
+ "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
+ "dev": true,
+ "dependencies": {
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/defined": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
+ "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==",
+ "dev": true
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/deps-sort": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz",
+ "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==",
+ "dev": true,
+ "dependencies": {
+ "JSONStream": "^1.0.3",
+ "shasum-object": "^1.0.0",
+ "subarg": "^1.0.0",
+ "through2": "^2.0.0"
+ },
+ "bin": {
+ "deps-sort": "bin/cmd.js"
+ }
+ },
+ "node_modules/des.js": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
+ "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "node_modules/detective": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz",
+ "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==",
+ "dev": true,
+ "dependencies": {
+ "acorn-node": "^1.8.2",
+ "defined": "^1.0.0",
+ "minimist": "^1.2.6"
+ },
+ "bin": {
+ "detective": "bin/detective.js"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/diff": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/diffie-hellman": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+ "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.1.0",
+ "miller-rabin": "^4.0.0",
+ "randombytes": "^2.0.0"
+ }
+ },
+ "node_modules/diffie-hellman/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/domain-browser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4",
+ "npm": ">=1.2"
+ }
+ },
+ "node_modules/duplexer2": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
+ "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "node_modules/duration": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz",
+ "integrity": "sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg==",
+ "dev": true,
+ "dependencies": {
+ "d": "1",
+ "es5-ext": "~0.10.46"
+ }
+ },
+ "node_modules/ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
+ "dev": true,
+ "dependencies": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.233",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.233.tgz",
+ "integrity": "sha512-ejwIKXTg1wqbmkcRJh9Ur3hFGHFDZDw1POzdsVrB2WZjgRuRMHIQQKNpe64N/qh3ZtH2otEoRoS+s6arAAuAAw==",
+ "dev": true
+ },
+ "node_modules/elliptic": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
+ "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.11.9",
+ "brorand": "^1.1.0",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.1",
+ "inherits": "^2.0.4",
+ "minimalistic-assert": "^1.0.1",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "node_modules/elliptic/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/error-stack-parser": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
+ "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
+ "dev": true,
+ "dependencies": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz",
+ "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "function.prototype.name": "^1.1.5",
+ "get-intrinsic": "^1.1.1",
+ "get-symbol-description": "^1.0.0",
+ "has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.3",
+ "is-callable": "^1.2.4",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.12.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.2",
+ "regexp.prototype.flags": "^1.4.3",
+ "string.prototype.trimend": "^1.0.5",
+ "string.prototype.trimstart": "^1.0.5",
+ "unbox-primitive": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es5-ext": {
+ "version": "0.10.62",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
+ "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "es6-iterator": "^2.0.3",
+ "es6-symbol": "^3.1.3",
+ "next-tick": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/es6-iterator": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+ "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
+ "dev": true,
+ "dependencies": {
+ "d": "1",
+ "es5-ext": "^0.10.35",
+ "es6-symbol": "^3.1.1"
+ }
+ },
+ "node_modules/es6-symbol": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
+ "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
+ "dev": true,
+ "dependencies": {
+ "d": "^1.0.1",
+ "ext": "^1.1.2"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "dev": true
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.23.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.0.tgz",
+ "integrity": "sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@eslint/eslintrc": "^1.3.1",
+ "@humanwhocodes/config-array": "^0.10.4",
+ "@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.1.1",
+ "eslint-utils": "^3.0.0",
+ "eslint-visitor-keys": "^3.3.0",
+ "espree": "^9.4.0",
+ "esquery": "^1.4.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^6.0.1",
+ "globals": "^13.15.0",
+ "globby": "^11.1.0",
+ "grapheme-splitter": "^1.0.4",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "regexpp": "^3.2.0",
+ "strip-ansi": "^6.0.1",
+ "strip-json-comments": "^3.1.0",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-plugin-cypress": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.12.1.tgz",
+ "integrity": "sha512-c2W/uPADl5kospNDihgiLc7n87t5XhUbFDoTl6CfVkmG+kDAb5Ux10V9PoLPu9N+r7znpc+iQlcmAqT1A/89HA==",
+ "dev": true,
+ "dependencies": {
+ "globals": "^11.12.0"
+ },
+ "peerDependencies": {
+ "eslint": ">= 3.2.1"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
+ "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/eslint-utils": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+ "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^2.0.0"
+ },
+ "engines": {
+ "node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": ">=5"
+ }
+ },
+ "node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/eslint/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/eslint/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/eslint/node_modules/globals": {
+ "version": "13.17.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz",
+ "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint/node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/eslint/node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz",
+ "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "acorn": "^8.8.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+ "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eventemitter2": {
+ "version": "6.4.7",
+ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz",
+ "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==",
+ "dev": true
+ },
+ "node_modules/events": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz",
+ "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "node_modules/evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "dev": true,
+ "dependencies": {
+ "md5.js": "^1.3.4",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "node_modules/execa": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz",
+ "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "get-stream": "^5.0.0",
+ "human-signals": "^1.1.1",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.0",
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/execa/node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/executable": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz",
+ "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==",
+ "dev": true,
+ "dependencies": {
+ "pify": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ext": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz",
+ "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==",
+ "dev": true,
+ "dependencies": {
+ "type": "^2.5.0"
+ }
+ },
+ "node_modules/ext/node_modules/type": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz",
+ "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==",
+ "dev": true
+ },
+ "node_modules/extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "node_modules/extract-zip": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
+ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.1",
+ "get-stream": "^5.1.0",
+ "yauzl": "^2.10.0"
+ },
+ "bin": {
+ "extract-zip": "cli.js"
+ },
+ "engines": {
+ "node": ">= 10.17.0"
+ },
+ "optionalDependencies": {
+ "@types/yauzl": "^2.9.1"
+ }
+ },
+ "node_modules/extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
+ "dev": true,
+ "engines": [
+ "node >=0.6.0"
+ ]
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.2.11",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
+ "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/fast-safe-stringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
+ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
+ "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
+ "dev": true,
+ "dependencies": {
+ "pend": "~1.2.0"
+ }
+ },
+ "node_modules/figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "node_modules/forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "dev": true,
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 0.12"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "dependencies": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/fsu": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz",
+ "integrity": "sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==",
+ "dev": true
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
+ "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-assigned-identifiers": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz",
+ "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==",
+ "dev": true
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-func-name": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
+ "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
+ "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "dev": true,
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+ "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/getos": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz",
+ "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==",
+ "dev": true,
+ "dependencies": {
+ "async": "^3.2.0"
+ }
+ },
+ "node_modules/getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
+ "dev": true,
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "node_modules/gherkin": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/gherkin/-/gherkin-5.1.0.tgz",
+ "integrity": "sha512-axTCsxH0m0cixijLvo7s9591h5pMb8ifQxFDun5FnfFhVsUhxgdnH0H7TSK7q8I4ASUU18DJ/tmlnMegMuLUUQ==",
+ "deprecated": "This package is now published under @cucumber/gherkin",
+ "dev": true,
+ "bin": {
+ "gherkin-javascript": "bin/gherkin"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/global-dirs": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz",
+ "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==",
+ "dev": true,
+ "dependencies": {
+ "ini": "2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "node_modules/grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/growl": {
+ "version": "1.10.5",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
+ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
+ "engines": {
+ "node": ">=4.x"
+ }
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+ "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hash-base": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+ "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/hash-base/node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/hash.js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "bin": {
+ "he": "bin/he"
+ }
+ },
+ "node_modules/hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==",
+ "dev": true,
+ "dependencies": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "node_modules/htmlescape": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz",
+ "integrity": "sha512-eVcrzgbR4tim7c7soKQKtxa/kQM4TzjnlU83rcZ9bHU6t31ehfV7SktN6McWgwPWg+JYMA/O3qpGxBvFq1z2Jg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/http-signature": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz",
+ "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==",
+ "dev": true,
+ "dependencies": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^2.0.2",
+ "sshpk": "^1.14.1"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/https-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+ "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==",
+ "dev": true
+ },
+ "node_modules/human-signals": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
+ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.12.0"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
+ "integrity": "sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/ini": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz",
+ "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/inline-source-map": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz",
+ "integrity": "sha512-0mVWSSbNDvedDWIN4wxLsdPM4a7cIPcpyMxj3QZ406QRwQ6ePGB1YIHxVPjqpcUGbWQ5C+nHTwGNWAGvt7ggVA==",
+ "dev": true,
+ "dependencies": {
+ "source-map": "~0.5.3"
+ }
+ },
+ "node_modules/insert-module-globals": {
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz",
+ "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==",
+ "dev": true,
+ "dependencies": {
+ "acorn-node": "^1.5.2",
+ "combine-source-map": "^0.8.0",
+ "concat-stream": "^1.6.1",
+ "is-buffer": "^1.1.0",
+ "JSONStream": "^1.0.3",
+ "path-is-absolute": "^1.0.1",
+ "process": "~0.11.0",
+ "through2": "^2.0.0",
+ "undeclared-identifiers": "^1.1.2",
+ "xtend": "^4.0.0"
+ },
+ "bin": {
+ "insert-module-globals": "bin/cmd.js"
+ }
+ },
+ "node_modules/internal-slot": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
+ "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/is-arguments": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+ "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
+ },
+ "node_modules/is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
+ "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-ci": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz",
+ "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==",
+ "dev": true,
+ "dependencies": {
+ "ci-info": "^3.2.0"
+ },
+ "bin": {
+ "is-ci": "bin.js"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
+ "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
+ "dev": true,
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-directory": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
+ "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz",
+ "integrity": "sha512-G56jBpbJeg7ds83HW1LuShNs8J73Fv3CPz/bmROHOHlnKkN8sWb9ujiagjmxxMUywftgq48HlBZELKKqFLk0oA==",
+ "dev": true
+ },
+ "node_modules/is-generator-function": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
+ "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-installed-globally": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz",
+ "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==",
+ "dev": true,
+ "dependencies": {
+ "global-dirs": "^3.0.0",
+ "is-path-inside": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz",
+ "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "es-abstract": "^1.20.0",
+ "for-each": "^0.3.3",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
+ "dev": true
+ },
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "dev": true
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "node_modules/isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
+ "dev": true
+ },
+ "node_modules/js-string-escape": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz",
+ "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "node_modules/js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
+ "dev": true
+ },
+ "node_modules/jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
+ },
+ "node_modules/json-schema": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+ "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
+ "dev": true
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/json-stable-stringify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz",
+ "integrity": "sha512-nKtD/Qxm7tWdZqJoldEC7fF0S41v0mWbeaXG3637stOWfyGxTgWTYE2wtfKmjzpvxv2MA2xzxsXOIiwUpkX6Qw==",
+ "dev": true,
+ "dependencies": {
+ "jsonify": "~0.0.0"
+ }
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
+ "dev": true
+ },
+ "node_modules/json5": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
+ "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
+ "dev": true,
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jsonify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+ "integrity": "sha512-trvBk1ki43VZptdBI5rIlG4YOzyeH/WefQt5rj1grasPn4iiZWKet8nkgc4GlsAylaztn0qZfUYOiTsASJFdNA==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==",
+ "dev": true,
+ "engines": [
+ "node >= 0.2.0"
+ ]
+ },
+ "node_modules/JSONStream": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
+ "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+ "dev": true,
+ "dependencies": {
+ "jsonparse": "^1.2.0",
+ "through": ">=2.2.7 <3"
+ },
+ "bin": {
+ "JSONStream": "bin.js"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/jsprim": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz",
+ "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==",
+ "dev": true,
+ "engines": [
+ "node >=0.6.0"
+ ],
+ "dependencies": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.4.0",
+ "verror": "1.10.0"
+ }
+ },
+ "node_modules/jsprim/node_modules/core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
+ "dev": true
+ },
+ "node_modules/jsprim/node_modules/verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
+ "dev": true,
+ "engines": [
+ "node >=0.6.0"
+ ],
+ "dependencies": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ },
+ "node_modules/knuth-shuffle-seeded": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/knuth-shuffle-seeded/-/knuth-shuffle-seeded-1.0.6.tgz",
+ "integrity": "sha512-9pFH0SplrfyKyojCLxZfMcvkhf5hH0d+UwR9nTVJ/DDQJGuzcXjTwB7TP7sDfehSudlGGaOLblmEWqv04ERVWg==",
+ "dev": true,
+ "dependencies": {
+ "seed-random": "~2.2.0"
+ }
+ },
+ "node_modules/labeled-stream-splicer": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz",
+ "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "stream-splicer": "^2.0.0"
+ }
+ },
+ "node_modules/lazy-ass": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz",
+ "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==",
+ "dev": true,
+ "engines": {
+ "node": "> 0.8"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/listr2": {
+ "version": "3.14.0",
+ "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz",
+ "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==",
+ "dev": true,
+ "dependencies": {
+ "cli-truncate": "^2.1.0",
+ "colorette": "^2.0.16",
+ "log-update": "^4.0.0",
+ "p-map": "^4.0.0",
+ "rfdc": "^1.3.0",
+ "rxjs": "^7.5.1",
+ "through": "^2.3.8",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "enquirer": ">= 2.3.0 < 3"
+ },
+ "peerDependenciesMeta": {
+ "enquirer": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "node_modules/lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
+ "dev": true
+ },
+ "node_modules/lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+ "dev": true
+ },
+ "node_modules/lodash.isempty": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
+ "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==",
+ "dev": true
+ },
+ "node_modules/lodash.isfunction": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
+ "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==",
+ "dev": true
+ },
+ "node_modules/lodash.isobject": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz",
+ "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==",
+ "dev": true
+ },
+ "node_modules/lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+ "dev": true
+ },
+ "node_modules/lodash.memoize": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz",
+ "integrity": "sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==",
+ "dev": true
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
+ "dev": true
+ },
+ "node_modules/log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
+ "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-escapes": "^4.3.0",
+ "cli-cursor": "^3.1.0",
+ "slice-ansi": "^4.0.0",
+ "wrap-ansi": "^6.2.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update/node_modules/slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/log-update/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dev": true,
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/loupe": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz",
+ "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==",
+ "dev": true,
+ "dependencies": {
+ "get-func-name": "^2.0.0"
+ }
+ },
+ "node_modules/lower-case": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
+ "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==",
+ "dev": true
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/md5.js": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+ "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+ "dev": true,
+ "dependencies": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.0.0",
+ "brorand": "^1.0.1"
+ },
+ "bin": {
+ "miller-rabin": "bin/miller-rabin"
+ }
+ },
+ "node_modules/miller-rabin/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dev": true,
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "dev": true
+ },
+ "node_modules/minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==",
+ "dev": true
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
+ "dev": true
+ },
+ "node_modules/mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+ "dev": true
+ },
+ "node_modules/mocha": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
+ "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
+ "dependencies": {
+ "ansi-colors": "4.1.1",
+ "browser-stdout": "1.3.1",
+ "chokidar": "3.5.3",
+ "debug": "4.3.4",
+ "diff": "5.0.0",
+ "escape-string-regexp": "4.0.0",
+ "find-up": "5.0.0",
+ "glob": "7.2.0",
+ "he": "1.2.0",
+ "js-yaml": "4.1.0",
+ "log-symbols": "4.1.0",
+ "minimatch": "5.0.1",
+ "ms": "2.1.3",
+ "nanoid": "3.3.3",
+ "serialize-javascript": "6.0.0",
+ "strip-json-comments": "3.1.1",
+ "supports-color": "8.1.1",
+ "workerpool": "6.2.1",
+ "yargs": "16.2.0",
+ "yargs-parser": "20.2.4",
+ "yargs-unparser": "2.0.0"
+ },
+ "bin": {
+ "_mocha": "bin/_mocha",
+ "mocha": "bin/mocha.js"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mochajs"
+ }
+ },
+ "node_modules/mocha/node_modules/ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mocha/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
+ },
+ "node_modules/mocha/node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/mocha/node_modules/debug": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
+ "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/mocha/node_modules/debug/node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "node_modules/mocha/node_modules/diff": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/mocha/node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mocha/node_modules/glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/mocha/node_modules/glob/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/mocha/node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/mocha/node_modules/minimatch": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz",
+ "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mocha/node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/mochawesome": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/mochawesome/-/mochawesome-7.1.3.tgz",
+ "integrity": "sha512-Vkb3jR5GZ1cXohMQQ73H3cZz7RoxGjjUo0G5hu0jLaW+0FdUxUwg3Cj29bqQdh0rFcnyV06pWmqmi5eBPnEuNQ==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.2",
+ "diff": "^5.0.0",
+ "json-stringify-safe": "^5.0.1",
+ "lodash.isempty": "^4.4.0",
+ "lodash.isfunction": "^3.0.9",
+ "lodash.isobject": "^3.0.2",
+ "lodash.isstring": "^4.0.1",
+ "mochawesome-report-generator": "^6.2.0",
+ "strip-ansi": "^6.0.1",
+ "uuid": "^8.3.2"
+ },
+ "peerDependencies": {
+ "mocha": ">=7"
+ }
+ },
+ "node_modules/mochawesome-merge": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/mochawesome-merge/-/mochawesome-merge-4.2.1.tgz",
+ "integrity": "sha512-G7+LqIKgixShKG4FyWDn1PIrzpKEwCofrJip/VzdqghNGqZl4S5MNoXx5YDfk9KLe+pr4qGa1TOzCc/oVw/8Kw==",
+ "dev": true,
+ "dependencies": {
+ "fs-extra": "^7.0.1",
+ "glob": "^7.1.6",
+ "yargs": "^15.3.1"
+ },
+ "bin": {
+ "mochawesome-merge": "bin/mochawesome-merge.js"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/mochawesome-merge/node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mochawesome-merge/node_modules/cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "node_modules/mochawesome-merge/node_modules/decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/mochawesome-merge/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mochawesome-merge/node_modules/fs-extra": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=6 <7 || >=8"
+ }
+ },
+ "node_modules/mochawesome-merge/node_modules/jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
+ "dev": true,
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/mochawesome-merge/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mochawesome-merge/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/mochawesome-merge/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mochawesome-merge/node_modules/universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/mochawesome-merge/node_modules/wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mochawesome-merge/node_modules/y18n": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+ "dev": true
+ },
+ "node_modules/mochawesome-merge/node_modules/yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/mochawesome-merge/node_modules/yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mochawesome-report-generator": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-6.2.0.tgz",
+ "integrity": "sha512-Ghw8JhQFizF0Vjbtp9B0i//+BOkV5OWcQCPpbO0NGOoxV33o+gKDYU0Pr2pGxkIHnqZ+g5mYiXF7GMNgAcDpSg==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.2",
+ "dateformat": "^4.5.1",
+ "escape-html": "^1.0.3",
+ "fs-extra": "^10.0.0",
+ "fsu": "^1.1.1",
+ "lodash.isfunction": "^3.0.9",
+ "opener": "^1.5.2",
+ "prop-types": "^15.7.2",
+ "tcomb": "^3.2.17",
+ "tcomb-validation": "^3.3.0",
+ "validator": "^13.6.0",
+ "yargs": "^17.2.1"
+ },
+ "bin": {
+ "marge": "bin/cli.js"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+ "dev": true,
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/yargs": {
+ "version": "17.5.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
+ "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/mochawesome-report-generator/node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/mochawesome/node_modules/diff": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz",
+ "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/module-deps": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz",
+ "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==",
+ "dev": true,
+ "dependencies": {
+ "browser-resolve": "^2.0.0",
+ "cached-path-relative": "^1.0.2",
+ "concat-stream": "~1.6.0",
+ "defined": "^1.0.0",
+ "detective": "^5.2.0",
+ "duplexer2": "^0.1.2",
+ "inherits": "^2.0.1",
+ "JSONStream": "^1.0.3",
+ "parents": "^1.0.0",
+ "readable-stream": "^2.0.2",
+ "resolve": "^1.4.0",
+ "stream-combiner2": "^1.1.1",
+ "subarg": "^1.0.0",
+ "through2": "^2.0.0",
+ "xtend": "^4.0.0"
+ },
+ "bin": {
+ "module-deps": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "node_modules/mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "dev": true,
+ "dependencies": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
+ "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/next-tick": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
+ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==",
+ "dev": true
+ },
+ "node_modules/no-case": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
+ "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
+ "dev": true,
+ "dependencies": {
+ "lower-case": "^1.1.1"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
+ "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
+ "dev": true
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
+ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
+ "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/opener": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
+ "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
+ "dev": true,
+ "bin": {
+ "opener": "bin/opener-bin.js"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/os-browserify": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
+ "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==",
+ "dev": true
+ },
+ "node_modules/ospath": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz",
+ "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==",
+ "dev": true
+ },
+ "node_modules/outpipe": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/outpipe/-/outpipe-1.1.1.tgz",
+ "integrity": "sha512-BnNY/RwnDrkmQdUa9U+OfN/Y7AWmKuUPCCd+hbRclZnnANvYpO72zp/a6Q4n829hPbdqEac31XCcsvlEvb+rtA==",
+ "dev": true,
+ "dependencies": {
+ "shell-quote": "^1.4.2"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pad-right": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/pad-right/-/pad-right-0.2.2.tgz",
+ "integrity": "sha512-4cy8M95ioIGolCoMmm2cMntGR1lPLEbOMzOKu8bzjuJP6JpzEMQcDHmh7hHLYGgob+nKe1YHFMaG4V59HQa89g==",
+ "dev": true,
+ "dependencies": {
+ "repeat-string": "^1.5.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pako": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
+ "dev": true
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parents": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz",
+ "integrity": "sha512-mXKF3xkoUt5td2DoxpLmtOmZvko9VfFpwRwkKDHSNvgmpLAeBo18YDhcPbBzJq+QLCHMbGOfzia2cX4U+0v9Mg==",
+ "dev": true,
+ "dependencies": {
+ "path-platform": "~0.11.15"
+ }
+ },
+ "node_modules/parse-asn1": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz",
+ "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==",
+ "dev": true,
+ "dependencies": {
+ "asn1.js": "^5.2.0",
+ "browserify-aes": "^1.0.0",
+ "evp_bytestokey": "^1.0.0",
+ "pbkdf2": "^3.0.3",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+ "dependencies": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/path-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz",
+ "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==",
+ "dev": true
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/path-platform": {
+ "version": "0.11.15",
+ "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz",
+ "integrity": "sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pathval": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
+ "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/pbkdf2": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
+ "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==",
+ "dev": true,
+ "dependencies": {
+ "create-hash": "^1.1.2",
+ "create-hmac": "^1.1.4",
+ "ripemd160": "^2.0.1",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
+ "dev": true
+ },
+ "node_modules/performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
+ "dev": true
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
+ "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/pretty-bytes": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
+ "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "node_modules/progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dev": true,
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
+ "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==",
+ "dev": true
+ },
+ "node_modules/psl": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
+ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
+ "dev": true
+ },
+ "node_modules/public-encrypt": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+ "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
+ "dev": true,
+ "dependencies": {
+ "bn.js": "^4.1.0",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "parse-asn1": "^5.0.0",
+ "randombytes": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "node_modules/public-encrypt/node_modules/bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ },
+ "node_modules/pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==",
+ "dev": true
+ },
+ "node_modules/qs": {
+ "version": "6.5.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
+ "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==",
+ "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "node_modules/querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.x"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "peer": true
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/randomfill": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
+ "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+ "dev": true,
+ "dependencies": {
+ "randombytes": "^2.0.5",
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "dev": true
+ },
+ "node_modules/read-only-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz",
+ "integrity": "sha512-3ALe0bjBVZtkdWKIcThYpQCLbBMd/+Tbh2CDSrAIDO3UsZ4Xs+tnyjv2MjCOMMgBG+AsUOeuP1cgtY1INISc8w==",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dev": true,
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/readable-stream/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "node_modules/readable-stream/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/regenerate": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
+ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
+ "dev": true
+ },
+ "node_modules/regenerate-unicode-properties": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz",
+ "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==",
+ "dev": true,
+ "dependencies": {
+ "regenerate": "^1.4.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.13.9",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
+ "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
+ "dev": true
+ },
+ "node_modules/regenerator-transform": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz",
+ "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.8.4"
+ }
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
+ "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "functions-have-names": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
+ "node_modules/regexpu-core": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz",
+ "integrity": "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==",
+ "dev": true,
+ "dependencies": {
+ "regenerate": "^1.4.2",
+ "regenerate-unicode-properties": "^10.0.1",
+ "regjsgen": "^0.6.0",
+ "regjsparser": "^0.8.2",
+ "unicode-match-property-ecmascript": "^2.0.0",
+ "unicode-match-property-value-ecmascript": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regjsgen": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz",
+ "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==",
+ "dev": true
+ },
+ "node_modules/regjsparser": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz",
+ "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==",
+ "dev": true,
+ "dependencies": {
+ "jsesc": "~0.5.0"
+ },
+ "bin": {
+ "regjsparser": "bin/parser"
+ }
+ },
+ "node_modules/regjsparser/node_modules/jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ }
+ },
+ "node_modules/repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/request-progress": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz",
+ "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==",
+ "dev": true,
+ "dependencies": {
+ "throttleit": "^1.0.0"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "node_modules/resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "dependencies": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rfdc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
+ "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
+ "dev": true
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/ripemd160": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+ "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+ "dev": true,
+ "dependencies": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "peer": true,
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/rxjs": {
+ "version": "7.5.6",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz",
+ "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "node_modules/seed-random": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/seed-random/-/seed-random-2.2.0.tgz",
+ "integrity": "sha512-34EQV6AAHQGhoc0tn/96a9Fsi6v2xdqe/dMUwljGRaFOzR3EgRmECvD0O8vi8X+/uQ50LGHfkNu/Eue5TPKZkQ==",
+ "dev": true
+ },
+ "node_modules/semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/serialize-error": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz",
+ "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/serialize-javascript": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+ "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+ "dev": true
+ },
+ "node_modules/sha.js": {
+ "version": "2.4.11",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+ "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ },
+ "bin": {
+ "sha.js": "bin.js"
+ }
+ },
+ "node_modules/shasum": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz",
+ "integrity": "sha512-UTzHm/+AzKfO9RgPgRpDIuMSNie1ubXRaljjlhFMNGYoG7z+rm9AHLPMf70R7887xboDH9Q+5YQbWKObFHEAtw==",
+ "dev": true,
+ "dependencies": {
+ "json-stable-stringify": "~0.0.0",
+ "sha.js": "~2.4.4"
+ }
+ },
+ "node_modules/shasum-object": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz",
+ "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==",
+ "dev": true,
+ "dependencies": {
+ "fast-safe-stringify": "^2.0.7"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shell-quote": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz",
+ "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==",
+ "dev": true
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "node_modules/simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/slice-ansi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
+ "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
+ },
+ "node_modules/sshpk": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
+ "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
+ "dev": true,
+ "dependencies": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ },
+ "bin": {
+ "sshpk-conv": "bin/sshpk-conv",
+ "sshpk-sign": "bin/sshpk-sign",
+ "sshpk-verify": "bin/sshpk-verify"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stack-chain": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-2.0.0.tgz",
+ "integrity": "sha512-GGrHXePi305aW7XQweYZZwiRwR7Js3MWoK/EHzzB9ROdc75nCnjSJVi21rdAGxFl+yCx2L2qdfl5y7NO4lTyqg==",
+ "dev": true
+ },
+ "node_modules/stack-generator": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz",
+ "integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==",
+ "dev": true,
+ "dependencies": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/stackframe": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
+ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
+ "dev": true
+ },
+ "node_modules/stacktrace-gps": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz",
+ "integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==",
+ "dev": true,
+ "dependencies": {
+ "source-map": "0.5.6",
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/stacktrace-gps/node_modules/source-map": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+ "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/stacktrace-js": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz",
+ "integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==",
+ "dev": true,
+ "dependencies": {
+ "error-stack-parser": "^2.0.6",
+ "stack-generator": "^2.0.5",
+ "stacktrace-gps": "^3.0.4"
+ }
+ },
+ "node_modules/stream-browserify": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
+ "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "~2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "node_modules/stream-combiner2": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz",
+ "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==",
+ "dev": true,
+ "dependencies": {
+ "duplexer2": "~0.1.0",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "node_modules/stream-http": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz",
+ "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==",
+ "dev": true,
+ "dependencies": {
+ "builtin-status-codes": "^3.0.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.6.0",
+ "xtend": "^4.0.2"
+ }
+ },
+ "node_modules/stream-http/node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/stream-splicer": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz",
+ "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-argv": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.0.2.tgz",
+ "integrity": "sha512-p6/Mqq0utTQWUeGMi/m0uBtlLZEwXSY3+mXzeRRqw7fz5ezUb28Wr0R99NlfbWaMmL/jCyT9be4jpn7Yz8IO8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.6.19"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
+ "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
+ "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/subarg": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz",
+ "integrity": "sha512-RIrIdRY0X1xojthNcVtgT9sjpOGagEUKpZdgBUi054OEPFo282yg+zE+t1Rj3+RqKq2xStL7uUHhY+AjbC4BXg==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.1.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/syntax-error": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz",
+ "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==",
+ "dev": true,
+ "dependencies": {
+ "acorn-node": "^1.2.0"
+ }
+ },
+ "node_modules/tcomb": {
+ "version": "3.2.29",
+ "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz",
+ "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==",
+ "dev": true
+ },
+ "node_modules/tcomb-validation": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz",
+ "integrity": "sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==",
+ "dev": true,
+ "dependencies": {
+ "tcomb": "^3.0.0"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "dev": true,
+ "dependencies": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "node_modules/thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "dev": true,
+ "dependencies": {
+ "thenify": ">= 3.1.0 < 4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/throttleit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz",
+ "integrity": "sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==",
+ "dev": true
+ },
+ "node_modules/through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
+ "dev": true
+ },
+ "node_modules/through2": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": "~2.3.6",
+ "xtend": "~4.0.1"
+ }
+ },
+ "node_modules/timers-browserify": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz",
+ "integrity": "sha512-PIxwAupJZiYU4JmVZYwXp9FKsHMXb5h0ZEFyuXTAn8WLHOlcij+FEcbrvDsom1o5dr1YggEtFbECvGCW2sT53Q==",
+ "dev": true,
+ "dependencies": {
+ "process": "~0.11.0"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "node_modules/title-case": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz",
+ "integrity": "sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==",
+ "dev": true,
+ "dependencies": {
+ "no-case": "^2.2.0",
+ "upper-case": "^1.0.3"
+ }
+ },
+ "node_modules/tmp": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
+ "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
+ "dev": true,
+ "dependencies": {
+ "rimraf": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8.17.0"
+ }
+ },
+ "node_modules/to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/tough-cookie": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+ "dev": true,
+ "dependencies": {
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/tough-cookie/node_modules/punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
+ "dev": true
+ },
+ "node_modules/tty-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz",
+ "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==",
+ "dev": true
+ },
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
+ "dev": true
+ },
+ "node_modules/type": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
+ "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
+ "dev": true
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
+ "dev": true
+ },
+ "node_modules/umd": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz",
+ "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==",
+ "dev": true,
+ "bin": {
+ "umd": "bin/cli.js"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/undeclared-identifiers": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz",
+ "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==",
+ "dev": true,
+ "dependencies": {
+ "acorn-node": "^1.3.0",
+ "dash-ast": "^1.0.0",
+ "get-assigned-identifiers": "^1.2.0",
+ "simple-concat": "^1.0.0",
+ "xtend": "^4.0.1"
+ },
+ "bin": {
+ "undeclared-identifiers": "bin.js"
+ }
+ },
+ "node_modules/unicode-canonical-property-names-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
+ "dev": true,
+ "dependencies": {
+ "unicode-canonical-property-names-ecmascript": "^2.0.0",
+ "unicode-property-aliases-ecmascript": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-value-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-property-aliases-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/untildify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
+ "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
+ "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "browserslist-lint": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/upper-case": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
+ "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==",
+ "dev": true
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/uri-js/node_modules/punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ }
+ },
+ "node_modules/url/node_modules/punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==",
+ "dev": true
+ },
+ "node_modules/util": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
+ "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "2.0.3"
+ }
+ },
+ "node_modules/util-arity": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/util-arity/-/util-arity-1.1.0.tgz",
+ "integrity": "sha512-kkyIsXKwemfSy8ZEoaIz06ApApnWsk5hQO0vLjZS6UkBiGiW++Jsyb8vSBoc0WKlffGoGs5yYy/j5pp8zckrFA==",
+ "dev": true
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true
+ },
+ "node_modules/util/node_modules/inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
+ "dev": true
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "dev": true,
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/validator": {
+ "version": "13.7.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz",
+ "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/verror": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz",
+ "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==",
+ "dev": true,
+ "dependencies": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=0.6.0"
+ }
+ },
+ "node_modules/verror/node_modules/core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
+ "dev": true
+ },
+ "node_modules/vm-browserify": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
+ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
+ "dev": true
+ },
+ "node_modules/watchify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/watchify/-/watchify-4.0.0.tgz",
+ "integrity": "sha512-2Z04dxwoOeNxa11qzWumBTgSAohTC0+ScuY7XMenPnH+W2lhTcpEOJP4g2EIG/SWeLadPk47x++Yh+8BqPM/lA==",
+ "dev": true,
+ "dependencies": {
+ "anymatch": "^3.1.0",
+ "browserify": "^17.0.0",
+ "chokidar": "^3.4.0",
+ "defined": "^1.0.0",
+ "outpipe": "^1.1.0",
+ "through2": "^4.0.2",
+ "xtend": "^4.0.2"
+ },
+ "bin": {
+ "watchify": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ }
+ },
+ "node_modules/watchify/node_modules/browserify": {
+ "version": "17.0.0",
+ "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz",
+ "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==",
+ "dev": true,
+ "dependencies": {
+ "assert": "^1.4.0",
+ "browser-pack": "^6.0.1",
+ "browser-resolve": "^2.0.0",
+ "browserify-zlib": "~0.2.0",
+ "buffer": "~5.2.1",
+ "cached-path-relative": "^1.0.0",
+ "concat-stream": "^1.6.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "~1.0.0",
+ "crypto-browserify": "^3.0.0",
+ "defined": "^1.0.0",
+ "deps-sort": "^2.0.1",
+ "domain-browser": "^1.2.0",
+ "duplexer2": "~0.1.2",
+ "events": "^3.0.0",
+ "glob": "^7.1.0",
+ "has": "^1.0.0",
+ "htmlescape": "^1.1.0",
+ "https-browserify": "^1.0.0",
+ "inherits": "~2.0.1",
+ "insert-module-globals": "^7.2.1",
+ "JSONStream": "^1.0.3",
+ "labeled-stream-splicer": "^2.0.0",
+ "mkdirp-classic": "^0.5.2",
+ "module-deps": "^6.2.3",
+ "os-browserify": "~0.3.0",
+ "parents": "^1.0.1",
+ "path-browserify": "^1.0.0",
+ "process": "~0.11.0",
+ "punycode": "^1.3.2",
+ "querystring-es3": "~0.2.0",
+ "read-only-stream": "^2.0.0",
+ "readable-stream": "^2.0.2",
+ "resolve": "^1.1.4",
+ "shasum-object": "^1.0.0",
+ "shell-quote": "^1.6.1",
+ "stream-browserify": "^3.0.0",
+ "stream-http": "^3.0.0",
+ "string_decoder": "^1.1.1",
+ "subarg": "^1.0.0",
+ "syntax-error": "^1.1.1",
+ "through2": "^2.0.0",
+ "timers-browserify": "^1.0.1",
+ "tty-browserify": "0.0.1",
+ "url": "~0.11.0",
+ "util": "~0.12.0",
+ "vm-browserify": "^1.0.0",
+ "xtend": "^4.0.0"
+ },
+ "bin": {
+ "browserify": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/watchify/node_modules/browserify/node_modules/through2": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": "~2.3.6",
+ "xtend": "~4.0.1"
+ }
+ },
+ "node_modules/watchify/node_modules/buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz",
+ "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==",
+ "dev": true,
+ "dependencies": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4"
+ }
+ },
+ "node_modules/watchify/node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/watchify/node_modules/path-browserify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
+ "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
+ "dev": true
+ },
+ "node_modules/watchify/node_modules/stream-browserify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz",
+ "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "~2.0.4",
+ "readable-stream": "^3.5.0"
+ }
+ },
+ "node_modules/watchify/node_modules/stream-browserify/node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/watchify/node_modules/through2": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
+ "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": "3"
+ }
+ },
+ "node_modules/watchify/node_modules/through2/node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/watchify/node_modules/util": {
+ "version": "0.12.4",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz",
+ "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "is-arguments": "^1.0.4",
+ "is-generator-function": "^1.0.7",
+ "is-typed-array": "^1.1.3",
+ "safe-buffer": "^5.1.2",
+ "which-typed-array": "^1.1.2"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==",
+ "dev": true
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz",
+ "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "es-abstract": "^1.20.0",
+ "for-each": "^0.3.3",
+ "has-tostringtag": "^1.0.0",
+ "is-typed-array": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/workerpool": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz",
+ "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A=="
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "node_modules/yargs": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+ "dependencies": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "20.2.4",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+ "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yargs-unparser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+ "dependencies": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
+ "dev": true,
+ "dependencies": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ },
+ "dependencies": {
+ "@ampproject/remapping": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
+ "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/gen-mapping": "^0.1.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ },
+ "@babel/code-frame": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
+ "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==",
+ "dev": true,
+ "requires": {
+ "@babel/highlight": "^7.18.6"
+ }
+ },
+ "@babel/compat-data": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.13.tgz",
+ "integrity": "sha512-5yUzC5LqyTFp2HLmDoxGQelcdYgSpP9xsnMWBphAscOdFrHSAVbLNzWiy32sVNDqJRDiJK6klfDnAgu6PAGSHw==",
+ "dev": true
+ },
+ "@babel/core": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.13.tgz",
+ "integrity": "sha512-ZisbOvRRusFktksHSG6pjj1CSvkPkcZq/KHD45LAkVP/oiHJkNBZWfpvlLmX8OtHDG8IuzsFlVRWo08w7Qxn0A==",
+ "dev": true,
+ "requires": {
+ "@ampproject/remapping": "^2.1.0",
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.18.13",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-module-transforms": "^7.18.9",
+ "@babel/helpers": "^7.18.9",
+ "@babel/parser": "^7.18.13",
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.18.13",
+ "@babel/types": "^7.18.13",
+ "convert-source-map": "^1.7.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.1",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/generator": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.13.tgz",
+ "integrity": "sha512-CkPg8ySSPuHTYPJYo7IRALdqyjM9HCbt/3uOBEFbzyGVP6Mn8bwFPB0jX6982JVNBlYzM1nnPkfjuXSOPtQeEQ==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.13",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "jsesc": "^2.5.1"
+ },
+ "dependencies": {
+ "@jridgewell/gen-mapping": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz",
+ "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ }
+ }
+ }
+ },
+ "@babel/helper-annotate-as-pure": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz",
+ "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-builder-binary-assignment-operator-visitor": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz",
+ "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-explode-assignable-expression": "^7.18.6",
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helper-compilation-targets": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz",
+ "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.18.8",
+ "@babel/helper-validator-option": "^7.18.6",
+ "browserslist": "^4.20.2",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-create-class-features-plugin": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.13.tgz",
+ "integrity": "sha512-hDvXp+QYxSRL+23mpAlSGxHMDyIGChm0/AwTfTAAK5Ufe40nCsyNdaYCGuK91phn/fVu9kqayImRDkvNAgdrsA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-member-expression-to-functions": "^7.18.9",
+ "@babel/helper-optimise-call-expression": "^7.18.6",
+ "@babel/helper-replace-supers": "^7.18.9",
+ "@babel/helper-split-export-declaration": "^7.18.6"
+ }
+ },
+ "@babel/helper-create-regexp-features-plugin": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz",
+ "integrity": "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "regexpu-core": "^5.1.0"
+ }
+ },
+ "@babel/helper-define-polyfill-provider": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.2.tgz",
+ "integrity": "sha512-r9QJJ+uDWrd+94BSPcP6/de67ygLtvVy6cK4luE6MOuDsZIdoaPBnfSpbO/+LTifjPckbKXRuI9BB/Z2/y3iTg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-compilation-targets": "^7.17.7",
+ "@babel/helper-plugin-utils": "^7.16.7",
+ "debug": "^4.1.1",
+ "lodash.debounce": "^4.0.8",
+ "resolve": "^1.14.2",
+ "semver": "^6.1.2"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/helper-environment-visitor": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
+ "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==",
+ "dev": true
+ },
+ "@babel/helper-explode-assignable-expression": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz",
+ "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-function-name": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz",
+ "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.18.6",
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helper-hoist-variables": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz",
+ "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-member-expression-to-functions": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz",
+ "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helper-module-imports": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz",
+ "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-module-transforms": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz",
+ "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-simple-access": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "@babel/template": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helper-optimise-call-expression": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz",
+ "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-plugin-utils": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz",
+ "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==",
+ "dev": true
+ },
+ "@babel/helper-remap-async-to-generator": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz",
+ "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-wrap-function": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helper-replace-supers": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz",
+ "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-member-expression-to-functions": "^7.18.9",
+ "@babel/helper-optimise-call-expression": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helper-simple-access": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz",
+ "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz",
+ "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/helper-split-export-declaration": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
+ "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==",
+ "dev": true,
+ "requires": {
+ "@babel/types": "^7.18.6"
+ }
+ },
+ "@babel/helper-string-parser": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz",
+ "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==",
+ "dev": true
+ },
+ "@babel/helper-validator-identifier": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
+ "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==",
+ "dev": true
+ },
+ "@babel/helper-validator-option": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
+ "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
+ "dev": true
+ },
+ "@babel/helper-wrap-function": {
+ "version": "7.18.11",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.11.tgz",
+ "integrity": "sha512-oBUlbv+rjZLh2Ks9SKi4aL7eKaAXBWleHzU89mP0G6BMUlRxSckk9tSIkgDGydhgFxHuGSlBQZfnaD47oBEB7w==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/template": "^7.18.10",
+ "@babel/traverse": "^7.18.11",
+ "@babel/types": "^7.18.10"
+ }
+ },
+ "@babel/helpers": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz",
+ "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==",
+ "dev": true,
+ "requires": {
+ "@babel/template": "^7.18.6",
+ "@babel/traverse": "^7.18.9",
+ "@babel/types": "^7.18.9"
+ }
+ },
+ "@babel/highlight": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz",
+ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "chalk": "^2.0.0",
+ "js-tokens": "^4.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dev": true,
+ "requires": {
+ "color-convert": "^1.9.0"
+ }
+ },
+ "chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ }
+ },
+ "color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dev": true,
+ "requires": {
+ "color-name": "1.1.3"
+ }
+ },
+ "color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^3.0.0"
+ }
+ }
+ }
+ },
+ "@babel/parser": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.13.tgz",
+ "integrity": "sha512-dgXcIfMuQ0kgzLB2b9tRZs7TTFFaGM2AbtA4fJgUUYukzGH4jwsS7hzQHEGs67jdehpm22vkgKwvbU+aEflgwg==",
+ "dev": true
+ },
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz",
+ "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz",
+ "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9",
+ "@babel/plugin-proposal-optional-chaining": "^7.18.9"
+ }
+ },
+ "@babel/plugin-proposal-async-generator-functions": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz",
+ "integrity": "sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-remap-async-to-generator": "^7.18.9",
+ "@babel/plugin-syntax-async-generators": "^7.8.4"
+ }
+ },
+ "@babel/plugin-proposal-class-properties": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz",
+ "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-proposal-class-static-block": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz",
+ "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5"
+ }
+ },
+ "@babel/plugin-proposal-dynamic-import": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz",
+ "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-export-namespace-from": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz",
+ "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-json-strings": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz",
+ "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-json-strings": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-logical-assignment-operators": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz",
+ "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ }
+ },
+ "@babel/plugin-proposal-nullish-coalescing-operator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz",
+ "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-numeric-separator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz",
+ "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4"
+ }
+ },
+ "@babel/plugin-proposal-object-rest-spread": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz",
+ "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.18.8",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-transform-parameters": "^7.18.8"
+ }
+ },
+ "@babel/plugin-proposal-optional-catch-binding": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz",
+ "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-optional-chaining": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz",
+ "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3"
+ }
+ },
+ "@babel/plugin-proposal-private-methods": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz",
+ "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-proposal-private-property-in-object": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz",
+ "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
+ }
+ },
+ "@babel/plugin-proposal-unicode-property-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz",
+ "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ }
+ },
+ "@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-syntax-dynamic-import": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
+ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-export-namespace-from": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
+ "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.3"
+ }
+ },
+ "@babel/plugin-syntax-import-assertions": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz",
+ "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-jsx": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz",
+ "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ }
+ },
+ "@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ }
+ },
+ "@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ }
+ },
+ "@babel/plugin-transform-arrow-functions": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz",
+ "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-async-to-generator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz",
+ "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-remap-async-to-generator": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz",
+ "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-block-scoping": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz",
+ "integrity": "sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-classes": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz",
+ "integrity": "sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-optimise-call-expression": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-replace-supers": "^7.18.9",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "globals": "^11.1.0"
+ }
+ },
+ "@babel/plugin-transform-computed-properties": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz",
+ "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-destructuring": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.13.tgz",
+ "integrity": "sha512-TodpQ29XekIsex2A+YJPj5ax2plkGa8YYY6mFjCohk/IG9IY42Rtuj1FuDeemfg2ipxIFLzPeA83SIBnlhSIow==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-dotall-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz",
+ "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-duplicate-keys": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz",
+ "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz",
+ "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-for-of": {
+ "version": "7.18.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz",
+ "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-function-name": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz",
+ "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-literals": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz",
+ "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-member-expression-literals": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz",
+ "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-modules-amd": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz",
+ "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-transforms": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ }
+ },
+ "@babel/plugin-transform-modules-commonjs": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz",
+ "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-transforms": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-simple-access": "^7.18.6",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ }
+ },
+ "@babel/plugin-transform-modules-systemjs": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz",
+ "integrity": "sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-hoist-variables": "^7.18.6",
+ "@babel/helper-module-transforms": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "babel-plugin-dynamic-import-node": "^2.3.3"
+ }
+ },
+ "@babel/plugin-transform-modules-umd": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz",
+ "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-transforms": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz",
+ "integrity": "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-new-target": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz",
+ "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-object-super": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz",
+ "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-replace-supers": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-parameters": {
+ "version": "7.18.8",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz",
+ "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-property-literals": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz",
+ "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-react-display-name": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz",
+ "integrity": "sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-react-jsx": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.10.tgz",
+ "integrity": "sha512-gCy7Iikrpu3IZjYZolFE4M1Sm+nrh1/6za2Ewj77Z+XirT4TsbJcvOFOyF+fRPwU6AKKK136CZxx6L8AbSFG6A==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/plugin-syntax-jsx": "^7.18.6",
+ "@babel/types": "^7.18.10"
+ }
+ },
+ "@babel/plugin-transform-react-jsx-development": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz",
+ "integrity": "sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==",
+ "dev": true,
+ "requires": {
+ "@babel/plugin-transform-react-jsx": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-react-pure-annotations": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz",
+ "integrity": "sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-annotate-as-pure": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-regenerator": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz",
+ "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "regenerator-transform": "^0.15.0"
+ }
+ },
+ "@babel/plugin-transform-reserved-words": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz",
+ "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-runtime": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.10.tgz",
+ "integrity": "sha512-q5mMeYAdfEbpBAgzl7tBre/la3LeCxmDO1+wMXRdPWbcoMjR3GiXlCLk7JBZVVye0bqTGNMbt0yYVXX1B1jEWQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-module-imports": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "babel-plugin-polyfill-corejs2": "^0.3.2",
+ "babel-plugin-polyfill-corejs3": "^0.5.3",
+ "babel-plugin-polyfill-regenerator": "^0.4.0",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/plugin-transform-shorthand-properties": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz",
+ "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-spread": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz",
+ "integrity": "sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-sticky-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz",
+ "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/plugin-transform-template-literals": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz",
+ "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-typeof-symbol": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz",
+ "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-unicode-escapes": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz",
+ "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.9"
+ }
+ },
+ "@babel/plugin-transform-unicode-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz",
+ "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ }
+ },
+ "@babel/preset-env": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.10.tgz",
+ "integrity": "sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.18.8",
+ "@babel/helper-compilation-targets": "^7.18.9",
+ "@babel/helper-plugin-utils": "^7.18.9",
+ "@babel/helper-validator-option": "^7.18.6",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9",
+ "@babel/plugin-proposal-async-generator-functions": "^7.18.10",
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
+ "@babel/plugin-proposal-class-static-block": "^7.18.6",
+ "@babel/plugin-proposal-dynamic-import": "^7.18.6",
+ "@babel/plugin-proposal-export-namespace-from": "^7.18.9",
+ "@babel/plugin-proposal-json-strings": "^7.18.6",
+ "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9",
+ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
+ "@babel/plugin-proposal-numeric-separator": "^7.18.6",
+ "@babel/plugin-proposal-object-rest-spread": "^7.18.9",
+ "@babel/plugin-proposal-optional-catch-binding": "^7.18.6",
+ "@babel/plugin-proposal-optional-chaining": "^7.18.9",
+ "@babel/plugin-proposal-private-methods": "^7.18.6",
+ "@babel/plugin-proposal-private-property-in-object": "^7.18.6",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.18.6",
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-dynamic-import": "^7.8.3",
+ "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
+ "@babel/plugin-syntax-import-assertions": "^7.18.6",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5",
+ "@babel/plugin-transform-arrow-functions": "^7.18.6",
+ "@babel/plugin-transform-async-to-generator": "^7.18.6",
+ "@babel/plugin-transform-block-scoped-functions": "^7.18.6",
+ "@babel/plugin-transform-block-scoping": "^7.18.9",
+ "@babel/plugin-transform-classes": "^7.18.9",
+ "@babel/plugin-transform-computed-properties": "^7.18.9",
+ "@babel/plugin-transform-destructuring": "^7.18.9",
+ "@babel/plugin-transform-dotall-regex": "^7.18.6",
+ "@babel/plugin-transform-duplicate-keys": "^7.18.9",
+ "@babel/plugin-transform-exponentiation-operator": "^7.18.6",
+ "@babel/plugin-transform-for-of": "^7.18.8",
+ "@babel/plugin-transform-function-name": "^7.18.9",
+ "@babel/plugin-transform-literals": "^7.18.9",
+ "@babel/plugin-transform-member-expression-literals": "^7.18.6",
+ "@babel/plugin-transform-modules-amd": "^7.18.6",
+ "@babel/plugin-transform-modules-commonjs": "^7.18.6",
+ "@babel/plugin-transform-modules-systemjs": "^7.18.9",
+ "@babel/plugin-transform-modules-umd": "^7.18.6",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6",
+ "@babel/plugin-transform-new-target": "^7.18.6",
+ "@babel/plugin-transform-object-super": "^7.18.6",
+ "@babel/plugin-transform-parameters": "^7.18.8",
+ "@babel/plugin-transform-property-literals": "^7.18.6",
+ "@babel/plugin-transform-regenerator": "^7.18.6",
+ "@babel/plugin-transform-reserved-words": "^7.18.6",
+ "@babel/plugin-transform-shorthand-properties": "^7.18.6",
+ "@babel/plugin-transform-spread": "^7.18.9",
+ "@babel/plugin-transform-sticky-regex": "^7.18.6",
+ "@babel/plugin-transform-template-literals": "^7.18.9",
+ "@babel/plugin-transform-typeof-symbol": "^7.18.9",
+ "@babel/plugin-transform-unicode-escapes": "^7.18.10",
+ "@babel/plugin-transform-unicode-regex": "^7.18.6",
+ "@babel/preset-modules": "^0.1.5",
+ "@babel/types": "^7.18.10",
+ "babel-plugin-polyfill-corejs2": "^0.3.2",
+ "babel-plugin-polyfill-corejs3": "^0.5.3",
+ "babel-plugin-polyfill-regenerator": "^0.4.0",
+ "core-js-compat": "^3.22.1",
+ "semver": "^6.3.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "@babel/preset-modules": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz",
+ "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
+ "@babel/plugin-transform-dotall-regex": "^7.4.4",
+ "@babel/types": "^7.4.4",
+ "esutils": "^2.0.2"
+ }
+ },
+ "@babel/preset-react": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.18.6.tgz",
+ "integrity": "sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-plugin-utils": "^7.18.6",
+ "@babel/helper-validator-option": "^7.18.6",
+ "@babel/plugin-transform-react-display-name": "^7.18.6",
+ "@babel/plugin-transform-react-jsx": "^7.18.6",
+ "@babel/plugin-transform-react-jsx-development": "^7.18.6",
+ "@babel/plugin-transform-react-pure-annotations": "^7.18.6"
+ }
+ },
+ "@babel/runtime": {
+ "version": "7.18.9",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz",
+ "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==",
+ "dev": true,
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ },
+ "@babel/template": {
+ "version": "7.18.10",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz",
+ "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/parser": "^7.18.10",
+ "@babel/types": "^7.18.10"
+ }
+ },
+ "@babel/traverse": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.13.tgz",
+ "integrity": "sha512-N6kt9X1jRMLPxxxPYWi7tgvJRH/rtoU+dbKAPDM44RFHiMH8igdsaSBgFeskhSl/kLWLDUvIh1RXCrTmg0/zvA==",
+ "dev": true,
+ "requires": {
+ "@babel/code-frame": "^7.18.6",
+ "@babel/generator": "^7.18.13",
+ "@babel/helper-environment-visitor": "^7.18.9",
+ "@babel/helper-function-name": "^7.18.9",
+ "@babel/helper-hoist-variables": "^7.18.6",
+ "@babel/helper-split-export-declaration": "^7.18.6",
+ "@babel/parser": "^7.18.13",
+ "@babel/types": "^7.18.13",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ }
+ },
+ "@babel/types": {
+ "version": "7.18.13",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.13.tgz",
+ "integrity": "sha512-ePqfTihzW0W6XAU+aMw2ykilisStJfDnsejDCXRchCcMJ4O0+8DhPXf2YUbZ6wjBlsEmZwLK/sPweWtu8hcJYQ==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-string-parser": "^7.18.10",
+ "@babel/helper-validator-identifier": "^7.18.6",
+ "to-fast-properties": "^2.0.0"
+ }
+ },
+ "@colors/colors": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz",
+ "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==",
+ "dev": true,
+ "optional": true
+ },
+ "@cypress/browserify-preprocessor": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@cypress/browserify-preprocessor/-/browserify-preprocessor-3.0.2.tgz",
+ "integrity": "sha512-y6mlFR+IR2cqcm3HabSp7AEcX9QfF1EUL4eOaw/7xexdhmdQU8ez6piyRopZQob4BK8oKTsc9PkupsU2rzjqMA==",
+ "dev": true,
+ "requires": {
+ "@babel/core": "^7.16.0",
+ "@babel/plugin-proposal-class-properties": "^7.16.0",
+ "@babel/plugin-proposal-object-rest-spread": "^7.16.0",
+ "@babel/plugin-transform-runtime": "^7.16.0",
+ "@babel/preset-env": "^7.16.0",
+ "@babel/preset-react": "^7.16.0",
+ "@babel/runtime": "^7.16.0",
+ "babel-plugin-add-module-exports": "^1.0.4",
+ "babelify": "^10.0.0",
+ "bluebird": "^3.7.2",
+ "browserify": "^16.2.3",
+ "coffeeify": "^3.0.1",
+ "coffeescript": "^1.12.7",
+ "debug": "^4.3.2",
+ "fs-extra": "^9.0.0",
+ "lodash.clonedeep": "^4.5.0",
+ "through2": "^2.0.0",
+ "watchify": "^4.0.0"
+ }
+ },
+ "@cypress/request": {
+ "version": "2.88.10",
+ "resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.10.tgz",
+ "integrity": "sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==",
+ "dev": true,
+ "requires": {
+ "aws-sign2": "~0.7.0",
+ "aws4": "^1.8.0",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.6",
+ "extend": "~3.0.2",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.3.2",
+ "http-signature": "~1.3.6",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.19",
+ "performance-now": "^2.1.0",
+ "qs": "~6.5.2",
+ "safe-buffer": "^5.1.2",
+ "tough-cookie": "~2.5.0",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^8.3.2"
+ }
+ },
+ "@cypress/xvfb": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz",
+ "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==",
+ "dev": true,
+ "requires": {
+ "debug": "^3.1.0",
+ "lodash.once": "^4.1.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "@eslint/eslintrc": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.1.tgz",
+ "integrity": "sha512-OhSY22oQQdw3zgPOOwdoj01l/Dzl1Z+xyUP33tkSN+aqyEhymJCcPHyXt+ylW8FSe0TfRC2VG+ROQOapD0aZSQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.4.0",
+ "globals": "^13.15.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "dependencies": {
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "peer": true
+ },
+ "globals": {
+ "version": "13.17.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz",
+ "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "@humanwhocodes/config-array": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz",
+ "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@humanwhocodes/object-schema": "^1.2.1",
+ "debug": "^4.1.1",
+ "minimatch": "^3.0.4"
+ }
+ },
+ "@humanwhocodes/gitignore-to-minimatch": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz",
+ "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==",
+ "dev": true,
+ "peer": true
+ },
+ "@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "peer": true
+ },
+ "@humanwhocodes/object-schema": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
+ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
+ "dev": true,
+ "peer": true
+ },
+ "@jridgewell/gen-mapping": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
+ "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/set-array": "^1.0.0",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "@jridgewell/resolve-uri": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
+ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true
+ },
+ "@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "dev": true
+ },
+ "@jridgewell/sourcemap-codec": {
+ "version": "1.4.14",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
+ },
+ "@jridgewell/trace-mapping": {
+ "version": "0.3.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz",
+ "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==",
+ "dev": true,
+ "requires": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ }
+ },
+ "@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "peer": true
+ },
+ "@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ }
+ },
+ "@types/node": {
+ "version": "14.18.26",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.26.tgz",
+ "integrity": "sha512-0b+utRBSYj8L7XAp0d+DX7lI4cSmowNaaTkk6/1SKzbKkG+doLuPusB9EOvzLJ8ahJSk03bTLIL6cWaEd4dBKA==",
+ "dev": true
+ },
+ "@types/sinonjs__fake-timers": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz",
+ "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==",
+ "dev": true
+ },
+ "@types/sizzle": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
+ "integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
+ "dev": true
+ },
+ "@types/yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "@types/node": "*"
+ }
+ },
+ "@ungap/promise-all-settled": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
+ "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q=="
+ },
+ "acorn": {
+ "version": "8.8.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
+ "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==",
+ "dev": true,
+ "peer": true
+ },
+ "acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {}
+ },
+ "acorn-node": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz",
+ "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==",
+ "dev": true,
+ "requires": {
+ "acorn": "^7.0.0",
+ "acorn-walk": "^7.0.0",
+ "xtend": "^4.0.2"
+ },
+ "dependencies": {
+ "acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "dev": true
+ }
+ }
+ },
+ "acorn-walk": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
+ "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
+ "dev": true
+ },
+ "aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "dev": true,
+ "requires": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "dependencies": {
+ "indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true
+ }
+ }
+ },
+ "ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ }
+ },
+ "ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "dev": true
+ },
+ "ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "requires": {
+ "type-fest": "^0.21.3"
+ }
+ },
+ "ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
+ },
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+ "dev": true
+ },
+ "anymatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+ "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+ "requires": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ }
+ },
+ "arch": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz",
+ "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==",
+ "dev": true
+ },
+ "argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "requires": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "peer": true
+ },
+ "asn1": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
+ "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
+ "dev": true,
+ "requires": {
+ "safer-buffer": "~2.1.0"
+ }
+ },
+ "asn1.js": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz",
+ "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.0.0",
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0",
+ "safer-buffer": "^2.1.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ }
+ }
+ },
+ "assert": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
+ "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==",
+ "dev": true,
+ "requires": {
+ "object-assign": "^4.1.1",
+ "util": "0.10.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
+ "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==",
+ "dev": true
+ },
+ "util": {
+ "version": "0.10.3",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
+ "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.1"
+ }
+ }
+ }
+ },
+ "assert-plus": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
+ "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
+ "dev": true
+ },
+ "assertion-error": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+ "dev": true
+ },
+ "assertion-error-formatter": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/assertion-error-formatter/-/assertion-error-formatter-2.0.1.tgz",
+ "integrity": "sha512-cjC3jUCh9spkroKue5PDSKH5RFQ/KNuZJhk3GwHYmB/8qqETxLOmMdLH+ohi/VukNzxDlMvIe7zScvLoOdhb6Q==",
+ "dev": true,
+ "requires": {
+ "diff": "^3.0.0",
+ "pad-right": "^0.2.2",
+ "repeat-string": "^1.6.1"
+ }
+ },
+ "astral-regex": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+ "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+ "dev": true
+ },
+ "async": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz",
+ "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==",
+ "dev": true
+ },
+ "asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "dev": true
+ },
+ "at-least-node": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
+ "dev": true
+ },
+ "available-typed-arrays": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
+ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+ "dev": true
+ },
+ "aws-sign2": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
+ "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
+ "dev": true
+ },
+ "aws4": {
+ "version": "1.11.0",
+ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
+ "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
+ "dev": true
+ },
+ "babel-plugin-add-module-exports": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-1.0.4.tgz",
+ "integrity": "sha512-g+8yxHUZ60RcyaUpfNzy56OtWW+x9cyEe9j+CranqLiqbju2yf/Cy6ZtYK40EZxtrdHllzlVZgLmcOUCTlJ7Jg==",
+ "dev": true
+ },
+ "babel-plugin-dynamic-import-node": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
+ "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
+ "dev": true,
+ "requires": {
+ "object.assign": "^4.1.0"
+ }
+ },
+ "babel-plugin-polyfill-corejs2": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.2.tgz",
+ "integrity": "sha512-LPnodUl3lS0/4wN3Rb+m+UK8s7lj2jcLRrjho4gLw+OJs+I4bvGXshINesY5xx/apM+biTnQ9reDI8yj+0M5+Q==",
+ "dev": true,
+ "requires": {
+ "@babel/compat-data": "^7.17.7",
+ "@babel/helper-define-polyfill-provider": "^0.3.2",
+ "semver": "^6.1.1"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+ "dev": true
+ }
+ }
+ },
+ "babel-plugin-polyfill-corejs3": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz",
+ "integrity": "sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-define-polyfill-provider": "^0.3.2",
+ "core-js-compat": "^3.21.0"
+ }
+ },
+ "babel-plugin-polyfill-regenerator": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.0.tgz",
+ "integrity": "sha512-RW1cnryiADFeHmfLS+WW/G431p1PsW5qdRdz0SDRi7TKcUgc7Oh/uXkT7MZ/+tGsT1BkczEAmD5XjUyJ5SWDTw==",
+ "dev": true,
+ "requires": {
+ "@babel/helper-define-polyfill-provider": "^0.3.2"
+ }
+ },
+ "babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
+ "dev": true,
+ "requires": {
+ "core-js": "^2.4.0",
+ "regenerator-runtime": "^0.11.0"
+ },
+ "dependencies": {
+ "regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
+ "dev": true
+ }
+ }
+ },
+ "babelify": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/babelify/-/babelify-10.0.0.tgz",
+ "integrity": "sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg==",
+ "dev": true,
+ "requires": {}
+ },
+ "balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "dev": true
+ },
+ "bcrypt-pbkdf": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
+ "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
+ "dev": true,
+ "requires": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "becke-ch--regex--s0-0-v1--base--pl--lib": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/becke-ch--regex--s0-0-v1--base--pl--lib/-/becke-ch--regex--s0-0-v1--base--pl--lib-1.4.0.tgz",
+ "integrity": "sha512-FnWonOyaw7Vivg5nIkrUll9HSS5TjFbyuURAiDssuL6VxrBe3ERzudRxOcWRhZYlP89UArMDikz7SapRPQpmZQ==",
+ "dev": true
+ },
+ "binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
+ },
+ "blob-util": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz",
+ "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==",
+ "dev": true
+ },
+ "bluebird": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+ "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
+ "dev": true
+ },
+ "bn.js": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
+ "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==",
+ "dev": true
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "requires": {
+ "fill-range": "^7.0.1"
+ }
+ },
+ "brorand": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
+ "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==",
+ "dev": true
+ },
+ "browser-pack": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/browser-pack/-/browser-pack-6.1.0.tgz",
+ "integrity": "sha512-erYug8XoqzU3IfcU8fUgyHqyOXqIE4tUTTQ+7mqUjQlvnXkOO6OlT9c/ZoJVHYoAaqGxr09CN53G7XIsO4KtWA==",
+ "dev": true,
+ "requires": {
+ "combine-source-map": "~0.8.0",
+ "defined": "^1.0.0",
+ "JSONStream": "^1.0.3",
+ "safe-buffer": "^5.1.1",
+ "through2": "^2.0.0",
+ "umd": "^3.0.0"
+ }
+ },
+ "browser-resolve": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz",
+ "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==",
+ "dev": true,
+ "requires": {
+ "resolve": "^1.17.0"
+ }
+ },
+ "browser-stdout": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
+ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw=="
+ },
+ "browserify": {
+ "version": "16.5.2",
+ "resolved": "https://registry.npmjs.org/browserify/-/browserify-16.5.2.tgz",
+ "integrity": "sha512-TkOR1cQGdmXU9zW4YukWzWVSJwrxmNdADFbqbE3HFgQWe5wqZmOawqZ7J/8MPCwk/W8yY7Y0h+7mOtcZxLP23g==",
+ "dev": true,
+ "requires": {
+ "assert": "^1.4.0",
+ "browser-pack": "^6.0.1",
+ "browser-resolve": "^2.0.0",
+ "browserify-zlib": "~0.2.0",
+ "buffer": "~5.2.1",
+ "cached-path-relative": "^1.0.0",
+ "concat-stream": "^1.6.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "~1.0.0",
+ "crypto-browserify": "^3.0.0",
+ "defined": "^1.0.0",
+ "deps-sort": "^2.0.0",
+ "domain-browser": "^1.2.0",
+ "duplexer2": "~0.1.2",
+ "events": "^2.0.0",
+ "glob": "^7.1.0",
+ "has": "^1.0.0",
+ "htmlescape": "^1.1.0",
+ "https-browserify": "^1.0.0",
+ "inherits": "~2.0.1",
+ "insert-module-globals": "^7.0.0",
+ "JSONStream": "^1.0.3",
+ "labeled-stream-splicer": "^2.0.0",
+ "mkdirp-classic": "^0.5.2",
+ "module-deps": "^6.2.3",
+ "os-browserify": "~0.3.0",
+ "parents": "^1.0.1",
+ "path-browserify": "~0.0.0",
+ "process": "~0.11.0",
+ "punycode": "^1.3.2",
+ "querystring-es3": "~0.2.0",
+ "read-only-stream": "^2.0.0",
+ "readable-stream": "^2.0.2",
+ "resolve": "^1.1.4",
+ "shasum": "^1.0.0",
+ "shell-quote": "^1.6.1",
+ "stream-browserify": "^2.0.0",
+ "stream-http": "^3.0.0",
+ "string_decoder": "^1.1.1",
+ "subarg": "^1.0.0",
+ "syntax-error": "^1.1.1",
+ "through2": "^2.0.0",
+ "timers-browserify": "^1.0.1",
+ "tty-browserify": "0.0.1",
+ "url": "~0.11.0",
+ "util": "~0.10.1",
+ "vm-browserify": "^1.0.0",
+ "xtend": "^4.0.0"
+ },
+ "dependencies": {
+ "buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz",
+ "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4"
+ }
+ }
+ }
+ },
+ "browserify-aes": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
+ "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
+ "dev": true,
+ "requires": {
+ "buffer-xor": "^1.0.3",
+ "cipher-base": "^1.0.0",
+ "create-hash": "^1.1.0",
+ "evp_bytestokey": "^1.0.3",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "browserify-cipher": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
+ "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
+ "dev": true,
+ "requires": {
+ "browserify-aes": "^1.0.4",
+ "browserify-des": "^1.0.0",
+ "evp_bytestokey": "^1.0.0"
+ }
+ },
+ "browserify-des": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
+ "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "des.js": "^1.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "browserify-rsa": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz",
+ "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^5.0.0",
+ "randombytes": "^2.0.1"
+ }
+ },
+ "browserify-sign": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz",
+ "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^5.1.1",
+ "browserify-rsa": "^4.0.1",
+ "create-hash": "^1.2.0",
+ "create-hmac": "^1.1.7",
+ "elliptic": "^6.5.3",
+ "inherits": "^2.0.4",
+ "parse-asn1": "^5.1.5",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "browserify-zlib": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
+ "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
+ "dev": true,
+ "requires": {
+ "pako": "~1.0.5"
+ }
+ },
+ "browserslist": {
+ "version": "4.21.3",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz",
+ "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==",
+ "dev": true,
+ "requires": {
+ "caniuse-lite": "^1.0.30001370",
+ "electron-to-chromium": "^1.4.202",
+ "node-releases": "^2.0.6",
+ "update-browserslist-db": "^1.0.5"
+ }
+ },
+ "buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "buffer-crc32": {
+ "version": "0.2.13",
+ "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
+ "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
+ "dev": true
+ },
+ "buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "dev": true
+ },
+ "buffer-xor": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
+ "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==",
+ "dev": true
+ },
+ "builtin-status-codes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
+ "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==",
+ "dev": true
+ },
+ "cached-path-relative": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/cached-path-relative/-/cached-path-relative-1.1.0.tgz",
+ "integrity": "sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA==",
+ "dev": true
+ },
+ "cachedir": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz",
+ "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==",
+ "dev": true
+ },
+ "call-bind": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
+ "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "get-intrinsic": "^1.0.2"
+ }
+ },
+ "callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "peer": true
+ },
+ "camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="
+ },
+ "caniuse-lite": {
+ "version": "1.0.30001384",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001384.tgz",
+ "integrity": "sha512-BBWt57kqWbc0GYZXb47wTXpmAgqr5LSibPzNjk/AWMdmJMQhLqOl3c/Kd4OAU/tu4NLfYkMx8Tlq3RVBkOBolQ==",
+ "dev": true
+ },
+ "caseless": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
+ "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
+ "dev": true
+ },
+ "chai": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
+ "integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
+ "dev": true,
+ "requires": {
+ "assertion-error": "^1.1.0",
+ "check-error": "^1.0.2",
+ "deep-eql": "^3.0.1",
+ "get-func-name": "^2.0.0",
+ "loupe": "^2.3.1",
+ "pathval": "^1.1.1",
+ "type-detect": "^4.0.5"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "dependencies": {
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
+ "check-error": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
+ "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==",
+ "dev": true
+ },
+ "check-more-types": {
+ "version": "2.24.0",
+ "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz",
+ "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==",
+ "dev": true
+ },
+ "chokidar": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
+ "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
+ "dev": true,
+ "requires": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "fsevents": "~2.3.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ }
+ },
+ "ci-info": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.3.2.tgz",
+ "integrity": "sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==",
+ "dev": true
+ },
+ "cipher-base": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
+ "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "dev": true
+ },
+ "cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+ "dev": true,
+ "requires": {
+ "restore-cursor": "^3.1.0"
+ }
+ },
+ "cli-table": {
+ "version": "0.3.11",
+ "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz",
+ "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==",
+ "dev": true,
+ "requires": {
+ "colors": "1.0.3"
+ },
+ "dependencies": {
+ "colors": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
+ "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==",
+ "dev": true
+ }
+ }
+ },
+ "cli-table3": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.2.tgz",
+ "integrity": "sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==",
+ "dev": true,
+ "requires": {
+ "@colors/colors": "1.5.0",
+ "string-width": "^4.2.0"
+ }
+ },
+ "cli-truncate": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
+ "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
+ "dev": true,
+ "requires": {
+ "slice-ansi": "^3.0.0",
+ "string-width": "^4.2.0"
+ }
+ },
+ "cliui": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "coffeeify": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/coffeeify/-/coffeeify-3.0.1.tgz",
+ "integrity": "sha512-Qjnr7UX6ldK1PHV7wCnv7AuCd4q19KTUtwJnu/6JRJB4rfm12zvcXtKdacUoePOKr1I4ka/ydKiwWpNAdsQb0g==",
+ "dev": true,
+ "requires": {
+ "convert-source-map": "^1.3.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "coffeescript": {
+ "version": "1.12.7",
+ "resolved": "https://registry.npmjs.org/coffeescript/-/coffeescript-1.12.7.tgz",
+ "integrity": "sha512-pLXHFxQMPklVoEekowk8b3erNynC+DVJzChxS/LCBBgR6/8AJkHivkm//zbowcfc7BTCAjryuhx6gPqPRfsFoA==",
+ "dev": true
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "colorette": {
+ "version": "2.0.19",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz",
+ "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==",
+ "dev": true
+ },
+ "colors": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
+ "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
+ "dev": true
+ },
+ "combine-source-map": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/combine-source-map/-/combine-source-map-0.8.0.tgz",
+ "integrity": "sha512-UlxQ9Vw0b/Bt/KYwCFqdEwsQ1eL8d1gibiFb7lxQJFdvTgc2hIZi6ugsg+kyhzhPV+QEpUiEIwInIAIrgoEkrg==",
+ "dev": true,
+ "requires": {
+ "convert-source-map": "~1.1.0",
+ "inline-source-map": "~0.6.0",
+ "lodash.memoize": "~3.0.3",
+ "source-map": "~0.5.3"
+ },
+ "dependencies": {
+ "convert-source-map": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.1.3.tgz",
+ "integrity": "sha512-Y8L5rp6jo+g9VEPgvqNfEopjTR4OTYct8lXlS8iVQdmnjDvbdbzYe9rjtFCB9egC86JoNCU61WRY+ScjkZpnIg==",
+ "dev": true
+ }
+ }
+ },
+ "combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dev": true,
+ "requires": {
+ "delayed-stream": "~1.0.0"
+ }
+ },
+ "commander": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz",
+ "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==",
+ "dev": true
+ },
+ "common-tags": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz",
+ "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==",
+ "dev": true
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ },
+ "concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "dev": true,
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "console-browserify": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
+ "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==",
+ "dev": true
+ },
+ "constants-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
+ "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==",
+ "dev": true
+ },
+ "convert-source-map": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
+ "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.1"
+ },
+ "dependencies": {
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ }
+ }
+ },
+ "core-js": {
+ "version": "2.6.12",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
+ "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
+ "dev": true
+ },
+ "core-js-compat": {
+ "version": "3.25.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.25.0.tgz",
+ "integrity": "sha512-extKQM0g8/3GjFx9US12FAgx8KJawB7RCQ5y8ipYLbmfzEzmFRWdDjIlxDx82g7ygcNG85qMVUSRyABouELdow==",
+ "dev": true,
+ "requires": {
+ "browserslist": "^4.21.3",
+ "semver": "7.0.0"
+ },
+ "dependencies": {
+ "semver": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
+ "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
+ "dev": true
+ }
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true
+ },
+ "cosmiconfig": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-4.0.0.tgz",
+ "integrity": "sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ==",
+ "requires": {
+ "is-directory": "^0.3.1",
+ "js-yaml": "^3.9.0",
+ "parse-json": "^4.0.0",
+ "require-from-string": "^2.0.1"
+ }
+ },
+ "create-ecdh": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
+ "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "elliptic": "^6.5.3"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ }
+ }
+ },
+ "create-hash": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
+ "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.1",
+ "inherits": "^2.0.1",
+ "md5.js": "^1.3.4",
+ "ripemd160": "^2.0.1",
+ "sha.js": "^2.4.0"
+ }
+ },
+ "create-hmac": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
+ "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
+ "dev": true,
+ "requires": {
+ "cipher-base": "^1.0.3",
+ "create-hash": "^1.1.0",
+ "inherits": "^2.0.1",
+ "ripemd160": "^2.0.0",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "cross-spawn": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
+ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ }
+ },
+ "crypto-browserify": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
+ "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+ "dev": true,
+ "requires": {
+ "browserify-cipher": "^1.0.0",
+ "browserify-sign": "^4.0.0",
+ "create-ecdh": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "create-hmac": "^1.1.0",
+ "diffie-hellman": "^5.0.0",
+ "inherits": "^2.0.1",
+ "pbkdf2": "^3.0.3",
+ "public-encrypt": "^4.0.0",
+ "randombytes": "^2.0.0",
+ "randomfill": "^1.0.3"
+ }
+ },
+ "cucumber": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/cucumber/-/cucumber-4.2.1.tgz",
+ "integrity": "sha512-3gQ0Vv4kSHsvXEFC6b1c+TfLRDzWD1/kU7e5vm8Kh8j35b95k6favan9/4ixcBNqd7UsU1T6FYcawC87+DlNKw==",
+ "dev": true,
+ "requires": {
+ "assertion-error-formatter": "^2.0.1",
+ "babel-runtime": "^6.11.6",
+ "bluebird": "^3.4.1",
+ "cli-table": "^0.3.1",
+ "colors": "^1.1.2",
+ "commander": "^2.9.0",
+ "cucumber-expressions": "^5.0.13",
+ "cucumber-tag-expressions": "^1.1.1",
+ "duration": "^0.2.0",
+ "escape-string-regexp": "^1.0.5",
+ "figures": "2.0.0",
+ "gherkin": "^5.0.0",
+ "glob": "^7.0.0",
+ "indent-string": "^3.1.0",
+ "is-generator": "^1.0.2",
+ "is-stream": "^1.1.0",
+ "knuth-shuffle-seeded": "^1.0.6",
+ "lodash": "^4.17.4",
+ "mz": "^2.4.0",
+ "progress": "^2.0.0",
+ "resolve": "^1.3.3",
+ "serialize-error": "^2.1.0",
+ "stack-chain": "^2.0.0",
+ "stacktrace-js": "^2.0.0",
+ "string-argv": "0.0.2",
+ "title-case": "^2.1.1",
+ "util-arity": "^1.0.2",
+ "verror": "^1.9.0"
+ },
+ "dependencies": {
+ "commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true
+ },
+ "cucumber-expressions": {
+ "version": "5.0.18",
+ "resolved": "https://registry.npmjs.org/cucumber-expressions/-/cucumber-expressions-5.0.18.tgz",
+ "integrity": "sha512-cj9UKCEvsB7bN97THmowcZt8I3rYFbTAFBNeDpKmWW3vr43CLZeWBmbk7NlHijndLwPJ7+uiF72xWrRU+RLyZA==",
+ "dev": true,
+ "requires": {
+ "becke-ch--regex--s0-0-v1--base--pl--lib": "^1.2.0"
+ }
+ },
+ "figures": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+ "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ }
+ }
+ },
+ "cucumber-expressions": {
+ "version": "6.6.2",
+ "resolved": "https://registry.npmjs.org/cucumber-expressions/-/cucumber-expressions-6.6.2.tgz",
+ "integrity": "sha512-WcFSVBiWNLJbIcAAC3t/ACU46vaOKfe1UIF5H3qveoq+Y4XQm9j3YwHurQNufRKBBg8nCnpU7Ttsx7egjS3hwA==",
+ "dev": true,
+ "requires": {
+ "becke-ch--regex--s0-0-v1--base--pl--lib": "^1.2.0"
+ }
+ },
+ "cucumber-tag-expressions": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/cucumber-tag-expressions/-/cucumber-tag-expressions-1.1.1.tgz",
+ "integrity": "sha512-V9jv81sR/HaJ87FoidrvHkviXId7KmBcUi7aQPfi+W3nRO30N6GqH6lcp8K+nyiT1DgemRJBPDDeBMS93xJqMQ==",
+ "dev": true
+ },
+ "cypress": {
+ "version": "9.7.0",
+ "resolved": "https://registry.npmjs.org/cypress/-/cypress-9.7.0.tgz",
+ "integrity": "sha512-+1EE1nuuuwIt/N1KXRR2iWHU+OiIt7H28jJDyyI4tiUftId/DrXYEwoDa5+kH2pki1zxnA0r6HrUGHV5eLbF5Q==",
+ "dev": true,
+ "requires": {
+ "@cypress/request": "^2.88.10",
+ "@cypress/xvfb": "^1.2.4",
+ "@types/node": "^14.14.31",
+ "@types/sinonjs__fake-timers": "8.1.1",
+ "@types/sizzle": "^2.3.2",
+ "arch": "^2.2.0",
+ "blob-util": "^2.0.2",
+ "bluebird": "^3.7.2",
+ "buffer": "^5.6.0",
+ "cachedir": "^2.3.0",
+ "chalk": "^4.1.0",
+ "check-more-types": "^2.24.0",
+ "cli-cursor": "^3.1.0",
+ "cli-table3": "~0.6.1",
+ "commander": "^5.1.0",
+ "common-tags": "^1.8.0",
+ "dayjs": "^1.10.4",
+ "debug": "^4.3.2",
+ "enquirer": "^2.3.6",
+ "eventemitter2": "^6.4.3",
+ "execa": "4.1.0",
+ "executable": "^4.1.1",
+ "extract-zip": "2.0.1",
+ "figures": "^3.2.0",
+ "fs-extra": "^9.1.0",
+ "getos": "^3.2.1",
+ "is-ci": "^3.0.0",
+ "is-installed-globally": "~0.4.0",
+ "lazy-ass": "^1.6.0",
+ "listr2": "^3.8.3",
+ "lodash": "^4.17.21",
+ "log-symbols": "^4.0.0",
+ "minimist": "^1.2.6",
+ "ospath": "^1.2.2",
+ "pretty-bytes": "^5.6.0",
+ "proxy-from-env": "1.0.0",
+ "request-progress": "^3.0.0",
+ "semver": "^7.3.2",
+ "supports-color": "^8.1.1",
+ "tmp": "~0.2.1",
+ "untildify": "^4.0.0",
+ "yauzl": "^2.10.0"
+ }
+ },
+ "cypress-cucumber-preprocessor": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/cypress-cucumber-preprocessor/-/cypress-cucumber-preprocessor-4.3.1.tgz",
+ "integrity": "sha512-BKUYXqoTeKzkPXohEczDtpAwRCY0ZPtIpfRwJut16yNLqdXQMV+aItwanxe3cbJTFlwg562NAjL4LMdiOhkAjg==",
+ "dev": true,
+ "requires": {
+ "@cypress/browserify-preprocessor": "^3.0.2",
+ "chai": "^4.2.0",
+ "chokidar": "3.5.2",
+ "cosmiconfig": "^4.0.0",
+ "cucumber": "^4.2.1",
+ "cucumber-expressions": "^6.0.1",
+ "cucumber-tag-expressions": "^1.1.1",
+ "dargs": "^7.0.0",
+ "debug": "^3.0.1",
+ "gherkin": "^5.1.0",
+ "glob": "^7.1.2",
+ "js-string-escape": "^1.0.1",
+ "minimist": "^1.2.5",
+ "through": "^2.3.8"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "cypress-xpath": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/cypress-xpath/-/cypress-xpath-1.8.0.tgz",
+ "integrity": "sha512-a76JxNgkYwKCi8tJkY6DjLV8NQ2TBBFA4pIcq5nMDIGOee2DnIIbYbD0ucT7qxF2LSwOow/Ze49WhaTL4pRPmg==",
+ "dev": true
+ },
+ "d": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
+ "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
+ "dev": true,
+ "requires": {
+ "es5-ext": "^0.10.50",
+ "type": "^1.0.1"
+ }
+ },
+ "dargs": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz",
+ "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==",
+ "dev": true
+ },
+ "dash-ast": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz",
+ "integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA==",
+ "dev": true
+ },
+ "dashdash": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
+ "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "dateformat": {
+ "version": "4.6.3",
+ "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz",
+ "integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==",
+ "dev": true
+ },
+ "dayjs": {
+ "version": "1.11.5",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.5.tgz",
+ "integrity": "sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==",
+ "dev": true
+ },
+ "debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
+ "requires": {
+ "ms": "2.1.2"
+ }
+ },
+ "decamelize": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
+ "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ=="
+ },
+ "deep-eql": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
+ "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
+ "dev": true,
+ "requires": {
+ "type-detect": "^4.0.0"
+ }
+ },
+ "deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "peer": true
+ },
+ "define-properties": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz",
+ "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==",
+ "dev": true,
+ "requires": {
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ }
+ },
+ "defined": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
+ "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==",
+ "dev": true
+ },
+ "delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "dev": true
+ },
+ "deps-sort": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/deps-sort/-/deps-sort-2.0.1.tgz",
+ "integrity": "sha512-1orqXQr5po+3KI6kQb9A4jnXT1PBwggGl2d7Sq2xsnOeI9GPcE/tGcF9UiSZtZBM7MukY4cAh7MemS6tZYipfw==",
+ "dev": true,
+ "requires": {
+ "JSONStream": "^1.0.3",
+ "shasum-object": "^1.0.0",
+ "subarg": "^1.0.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "des.js": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
+ "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "detective": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz",
+ "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==",
+ "dev": true,
+ "requires": {
+ "acorn-node": "^1.8.2",
+ "defined": "^1.0.0",
+ "minimist": "^1.2.6"
+ }
+ },
+ "diff": {
+ "version": "3.5.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
+ "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
+ "dev": true
+ },
+ "diffie-hellman": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
+ "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "miller-rabin": "^4.0.0",
+ "randombytes": "^2.0.0"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ }
+ }
+ },
+ "dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "path-type": "^4.0.0"
+ }
+ },
+ "doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "domain-browser": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
+ "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+ "dev": true
+ },
+ "duplexer2": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
+ "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "duration": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz",
+ "integrity": "sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg==",
+ "dev": true,
+ "requires": {
+ "d": "1",
+ "es5-ext": "~0.10.46"
+ }
+ },
+ "ecc-jsbn": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
+ "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
+ "dev": true,
+ "requires": {
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.1.0"
+ }
+ },
+ "electron-to-chromium": {
+ "version": "1.4.233",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.233.tgz",
+ "integrity": "sha512-ejwIKXTg1wqbmkcRJh9Ur3hFGHFDZDw1POzdsVrB2WZjgRuRMHIQQKNpe64N/qh3ZtH2otEoRoS+s6arAAuAAw==",
+ "dev": true
+ },
+ "elliptic": {
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
+ "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.11.9",
+ "brorand": "^1.1.0",
+ "hash.js": "^1.0.0",
+ "hmac-drbg": "^1.0.1",
+ "inherits": "^2.0.4",
+ "minimalistic-assert": "^1.0.1",
+ "minimalistic-crypto-utils": "^1.0.1"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ }
+ }
+ },
+ "emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dev": true,
+ "requires": {
+ "once": "^1.4.0"
+ }
+ },
+ "enquirer": {
+ "version": "2.3.6",
+ "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
+ "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==",
+ "dev": true,
+ "requires": {
+ "ansi-colors": "^4.1.1"
+ }
+ },
+ "error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "requires": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "error-stack-parser": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
+ "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
+ "dev": true,
+ "requires": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "es-abstract": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz",
+ "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "es-to-primitive": "^1.2.1",
+ "function-bind": "^1.1.1",
+ "function.prototype.name": "^1.1.5",
+ "get-intrinsic": "^1.1.1",
+ "get-symbol-description": "^1.0.0",
+ "has": "^1.0.3",
+ "has-property-descriptors": "^1.0.0",
+ "has-symbols": "^1.0.3",
+ "internal-slot": "^1.0.3",
+ "is-callable": "^1.2.4",
+ "is-negative-zero": "^2.0.2",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.2",
+ "is-string": "^1.0.7",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.12.0",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.2",
+ "regexp.prototype.flags": "^1.4.3",
+ "string.prototype.trimend": "^1.0.5",
+ "string.prototype.trimstart": "^1.0.5",
+ "unbox-primitive": "^1.0.2"
+ }
+ },
+ "es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ }
+ },
+ "es5-ext": {
+ "version": "0.10.62",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz",
+ "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==",
+ "dev": true,
+ "requires": {
+ "es6-iterator": "^2.0.3",
+ "es6-symbol": "^3.1.3",
+ "next-tick": "^1.1.0"
+ }
+ },
+ "es6-iterator": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+ "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
+ "dev": true,
+ "requires": {
+ "d": "1",
+ "es5-ext": "^0.10.35",
+ "es6-symbol": "^3.1.1"
+ }
+ },
+ "es6-symbol": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
+ "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
+ "dev": true,
+ "requires": {
+ "d": "^1.0.1",
+ "ext": "^1.1.2"
+ }
+ },
+ "escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
+ },
+ "escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "dev": true
+ },
+ "escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "dev": true
+ },
+ "eslint": {
+ "version": "8.23.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.0.tgz",
+ "integrity": "sha512-pBG/XOn0MsJcKcTRLr27S5HpzQo4kLr+HjLQIyK4EiCsijDl/TB+h5uEuJU6bQ8Edvwz1XWOjpaP2qgnXGpTcA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@eslint/eslintrc": "^1.3.1",
+ "@humanwhocodes/config-array": "^0.10.4",
+ "@humanwhocodes/gitignore-to-minimatch": "^1.0.2",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "ajv": "^6.10.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.1.1",
+ "eslint-utils": "^3.0.0",
+ "eslint-visitor-keys": "^3.3.0",
+ "espree": "^9.4.0",
+ "esquery": "^1.4.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "functional-red-black-tree": "^1.0.1",
+ "glob-parent": "^6.0.1",
+ "globals": "^13.15.0",
+ "globby": "^11.1.0",
+ "grapheme-splitter": "^1.0.4",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.0.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.1",
+ "regexpp": "^3.2.0",
+ "strip-ansi": "^6.0.1",
+ "strip-json-comments": "^3.1.0",
+ "text-table": "^0.2.0"
+ },
+ "dependencies": {
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "peer": true
+ },
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "peer": true
+ },
+ "glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "is-glob": "^4.0.3"
+ }
+ },
+ "globals": {
+ "version": "13.17.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz",
+ "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "type-fest": "^0.20.2"
+ }
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "eslint-plugin-cypress": {
+ "version": "2.12.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-cypress/-/eslint-plugin-cypress-2.12.1.tgz",
+ "integrity": "sha512-c2W/uPADl5kospNDihgiLc7n87t5XhUbFDoTl6CfVkmG+kDAb5Ux10V9PoLPu9N+r7znpc+iQlcmAqT1A/89HA==",
+ "dev": true,
+ "requires": {
+ "globals": "^11.12.0"
+ }
+ },
+ "eslint-scope": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz",
+ "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ }
+ },
+ "eslint-utils": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+ "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "eslint-visitor-keys": "^2.0.0"
+ },
+ "dependencies": {
+ "eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "eslint-visitor-keys": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz",
+ "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
+ "dev": true,
+ "peer": true
+ },
+ "espree": {
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.0.tgz",
+ "integrity": "sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "acorn": "^8.8.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.3.0"
+ }
+ },
+ "esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
+ },
+ "esquery": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
+ "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "estraverse": "^5.1.0"
+ }
+ },
+ "esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "estraverse": "^5.2.0"
+ }
+ },
+ "estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "peer": true
+ },
+ "esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true
+ },
+ "eventemitter2": {
+ "version": "6.4.7",
+ "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz",
+ "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==",
+ "dev": true
+ },
+ "events": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-2.1.0.tgz",
+ "integrity": "sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg==",
+ "dev": true
+ },
+ "evp_bytestokey": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
+ "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
+ "dev": true,
+ "requires": {
+ "md5.js": "^1.3.4",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "execa": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz",
+ "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==",
+ "dev": true,
+ "requires": {
+ "cross-spawn": "^7.0.0",
+ "get-stream": "^5.0.0",
+ "human-signals": "^1.1.1",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.0",
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2",
+ "strip-final-newline": "^2.0.0"
+ },
+ "dependencies": {
+ "is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true
+ }
+ }
+ },
+ "executable": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz",
+ "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==",
+ "dev": true,
+ "requires": {
+ "pify": "^2.2.0"
+ }
+ },
+ "ext": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz",
+ "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==",
+ "dev": true,
+ "requires": {
+ "type": "^2.5.0"
+ },
+ "dependencies": {
+ "type": {
+ "version": "2.7.2",
+ "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz",
+ "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==",
+ "dev": true
+ }
+ }
+ },
+ "extend": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
+ "dev": true
+ },
+ "extract-zip": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz",
+ "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==",
+ "dev": true,
+ "requires": {
+ "@types/yauzl": "^2.9.1",
+ "debug": "^4.1.1",
+ "get-stream": "^5.1.0",
+ "yauzl": "^2.10.0"
+ }
+ },
+ "extsprintf": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
+ "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
+ "dev": true
+ },
+ "fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "peer": true
+ },
+ "fast-glob": {
+ "version": "3.2.11",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
+ "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ }
+ },
+ "fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "peer": true
+ },
+ "fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "peer": true
+ },
+ "fast-safe-stringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
+ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
+ "dev": true
+ },
+ "fastq": {
+ "version": "1.13.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
+ "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "fd-slicer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
+ "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
+ "dev": true,
+ "requires": {
+ "pend": "~1.2.0"
+ }
+ },
+ "figures": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+ "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "dev": true,
+ "requires": {
+ "escape-string-regexp": "^1.0.5"
+ }
+ },
+ "file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "flat-cache": "^3.0.4"
+ }
+ },
+ "fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "requires": {
+ "to-regex-range": "^5.0.1"
+ }
+ },
+ "find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "requires": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ=="
+ },
+ "flat-cache": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
+ "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "flatted": "^3.1.0",
+ "rimraf": "^3.0.2"
+ }
+ },
+ "flatted": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz",
+ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==",
+ "dev": true,
+ "peer": true
+ },
+ "for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "dev": true,
+ "requires": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "forever-agent": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
+ "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
+ "dev": true
+ },
+ "form-data": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
+ "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
+ "dev": true,
+ "requires": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.6",
+ "mime-types": "^2.1.12"
+ }
+ },
+ "fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "requires": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+ },
+ "fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "optional": true
+ },
+ "fsu": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/fsu/-/fsu-1.1.1.tgz",
+ "integrity": "sha512-xQVsnjJ/5pQtcKh+KjUoZGzVWn4uNkchxTF6Lwjr4Gf7nQr8fmUfhKJ62zE77+xQg9xnxi5KUps7XGs+VC986A==",
+ "dev": true
+ },
+ "function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+ "dev": true
+ },
+ "function.prototype.name": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz",
+ "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.19.0",
+ "functions-have-names": "^1.2.2"
+ }
+ },
+ "functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
+ "dev": true,
+ "peer": true
+ },
+ "functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true
+ },
+ "gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true
+ },
+ "get-assigned-identifiers": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz",
+ "integrity": "sha512-mBBwmeGTrxEMO4pMaaf/uUEFHnYtwr8FTe8Y/mer4rcV/bye0qGm6pw1bGZFGStxC5O76c5ZAVBGnqHmOaJpdQ==",
+ "dev": true
+ },
+ "get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
+ },
+ "get-func-name": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
+ "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==",
+ "dev": true
+ },
+ "get-intrinsic": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz",
+ "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1",
+ "has": "^1.0.3",
+ "has-symbols": "^1.0.3"
+ }
+ },
+ "get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "dev": true,
+ "requires": {
+ "pump": "^3.0.0"
+ }
+ },
+ "get-symbol-description": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
+ "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ }
+ },
+ "getos": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz",
+ "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==",
+ "dev": true,
+ "requires": {
+ "async": "^3.2.0"
+ }
+ },
+ "getpass": {
+ "version": "0.1.7",
+ "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
+ "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "gherkin": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/gherkin/-/gherkin-5.1.0.tgz",
+ "integrity": "sha512-axTCsxH0m0cixijLvo7s9591h5pMb8ifQxFDun5FnfFhVsUhxgdnH0H7TSK7q8I4ASUU18DJ/tmlnMegMuLUUQ==",
+ "dev": true
+ },
+ "glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "requires": {
+ "is-glob": "^4.0.1"
+ }
+ },
+ "global-dirs": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.0.tgz",
+ "integrity": "sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA==",
+ "dev": true,
+ "requires": {
+ "ini": "2.0.0"
+ }
+ },
+ "globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true
+ },
+ "globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ }
+ },
+ "graceful-fs": {
+ "version": "4.2.10",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
+ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "dev": true
+ },
+ "grapheme-splitter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz",
+ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==",
+ "dev": true,
+ "peer": true
+ },
+ "growl": {
+ "version": "1.10.5",
+ "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
+ "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA=="
+ },
+ "has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dev": true,
+ "requires": {
+ "function-bind": "^1.1.1"
+ }
+ },
+ "has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+ },
+ "has-property-descriptors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz",
+ "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==",
+ "dev": true,
+ "requires": {
+ "get-intrinsic": "^1.1.1"
+ }
+ },
+ "has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true
+ },
+ "has-tostringtag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
+ "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "hash-base": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz",
+ "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.6.0",
+ "safe-buffer": "^5.2.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "hash.js": {
+ "version": "1.1.7",
+ "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
+ "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "minimalistic-assert": "^1.0.1"
+ }
+ },
+ "he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
+ },
+ "hmac-drbg": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
+ "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==",
+ "dev": true,
+ "requires": {
+ "hash.js": "^1.0.3",
+ "minimalistic-assert": "^1.0.0",
+ "minimalistic-crypto-utils": "^1.0.1"
+ }
+ },
+ "htmlescape": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/htmlescape/-/htmlescape-1.1.1.tgz",
+ "integrity": "sha512-eVcrzgbR4tim7c7soKQKtxa/kQM4TzjnlU83rcZ9bHU6t31ehfV7SktN6McWgwPWg+JYMA/O3qpGxBvFq1z2Jg==",
+ "dev": true
+ },
+ "http-signature": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.3.6.tgz",
+ "integrity": "sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "jsprim": "^2.0.2",
+ "sshpk": "^1.14.1"
+ }
+ },
+ "https-browserify": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
+ "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==",
+ "dev": true
+ },
+ "human-signals": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
+ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
+ "dev": true
+ },
+ "ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "dev": true
+ },
+ "ignore": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz",
+ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==",
+ "dev": true,
+ "peer": true
+ },
+ "import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ }
+ },
+ "imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "peer": true
+ },
+ "indent-string": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
+ "integrity": "sha512-BYqTHXTGUIvg7t1r4sJNKcbDZkL92nkXA8YtRpbjFHRHGDL/NtUeiBJMeE60kIFN/Mg8ESaWQvftaYMGJzQZCQ==",
+ "dev": true
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "ini": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz",
+ "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==",
+ "dev": true
+ },
+ "inline-source-map": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/inline-source-map/-/inline-source-map-0.6.2.tgz",
+ "integrity": "sha512-0mVWSSbNDvedDWIN4wxLsdPM4a7cIPcpyMxj3QZ406QRwQ6ePGB1YIHxVPjqpcUGbWQ5C+nHTwGNWAGvt7ggVA==",
+ "dev": true,
+ "requires": {
+ "source-map": "~0.5.3"
+ }
+ },
+ "insert-module-globals": {
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/insert-module-globals/-/insert-module-globals-7.2.1.tgz",
+ "integrity": "sha512-ufS5Qq9RZN+Bu899eA9QCAYThY+gGW7oRkmb0vC93Vlyu/CFGcH0OYPEjVkDXA5FEbTt1+VWzdoOD3Ny9N+8tg==",
+ "dev": true,
+ "requires": {
+ "acorn-node": "^1.5.2",
+ "combine-source-map": "^0.8.0",
+ "concat-stream": "^1.6.1",
+ "is-buffer": "^1.1.0",
+ "JSONStream": "^1.0.3",
+ "path-is-absolute": "^1.0.1",
+ "process": "~0.11.0",
+ "through2": "^2.0.0",
+ "undeclared-identifiers": "^1.1.2",
+ "xtend": "^4.0.0"
+ }
+ },
+ "internal-slot": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
+ "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
+ "dev": true,
+ "requires": {
+ "get-intrinsic": "^1.1.0",
+ "has": "^1.0.3",
+ "side-channel": "^1.0.4"
+ }
+ },
+ "is-arguments": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
+ "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
+ },
+ "is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "requires": {
+ "has-bigints": "^1.0.1"
+ }
+ },
+ "is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "requires": {
+ "binary-extensions": "^2.0.0"
+ }
+ },
+ "is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+ "dev": true
+ },
+ "is-callable": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
+ "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
+ "dev": true
+ },
+ "is-ci": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz",
+ "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==",
+ "dev": true,
+ "requires": {
+ "ci-info": "^3.2.0"
+ }
+ },
+ "is-core-module": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz",
+ "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==",
+ "dev": true,
+ "requires": {
+ "has": "^1.0.3"
+ }
+ },
+ "is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-directory": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
+ "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw=="
+ },
+ "is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
+ },
+ "is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
+ },
+ "is-generator": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-generator/-/is-generator-1.0.3.tgz",
+ "integrity": "sha512-G56jBpbJeg7ds83HW1LuShNs8J73Fv3CPz/bmROHOHlnKkN8sWb9ujiagjmxxMUywftgq48HlBZELKKqFLk0oA==",
+ "dev": true
+ },
+ "is-generator-function": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
+ "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "requires": {
+ "is-extglob": "^2.1.1"
+ }
+ },
+ "is-installed-globally": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz",
+ "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==",
+ "dev": true,
+ "requires": {
+ "global-dirs": "^3.0.0",
+ "is-path-inside": "^3.0.2"
+ }
+ },
+ "is-negative-zero": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "dev": true
+ },
+ "is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
+ },
+ "is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true
+ },
+ "is-plain-obj": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
+ "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA=="
+ },
+ "is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-shared-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
+ "is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+ "dev": true
+ },
+ "is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "requires": {
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "requires": {
+ "has-symbols": "^1.0.2"
+ }
+ },
+ "is-typed-array": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.9.tgz",
+ "integrity": "sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==",
+ "dev": true,
+ "requires": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "es-abstract": "^1.20.0",
+ "for-each": "^0.3.3",
+ "has-tostringtag": "^1.0.0"
+ }
+ },
+ "is-typedarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
+ "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
+ "dev": true
+ },
+ "is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="
+ },
+ "is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2"
+ }
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "dev": true
+ },
+ "isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "isstream": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
+ "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
+ "dev": true
+ },
+ "js-string-escape": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz",
+ "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==",
+ "dev": true
+ },
+ "js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true
+ },
+ "js-yaml": {
+ "version": "3.14.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
+ "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "requires": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ }
+ },
+ "jsbn": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
+ "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
+ "dev": true
+ },
+ "jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true
+ },
+ "json-parse-better-errors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
+ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw=="
+ },
+ "json-schema": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
+ "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
+ "dev": true
+ },
+ "json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "peer": true
+ },
+ "json-stable-stringify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-0.0.1.tgz",
+ "integrity": "sha512-nKtD/Qxm7tWdZqJoldEC7fF0S41v0mWbeaXG3637stOWfyGxTgWTYE2wtfKmjzpvxv2MA2xzxsXOIiwUpkX6Qw==",
+ "dev": true,
+ "requires": {
+ "jsonify": "~0.0.0"
+ }
+ },
+ "json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "peer": true
+ },
+ "json-stringify-safe": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
+ "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
+ "dev": true
+ },
+ "json5": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
+ "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
+ "dev": true
+ },
+ "jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6",
+ "universalify": "^2.0.0"
+ }
+ },
+ "jsonify": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz",
+ "integrity": "sha512-trvBk1ki43VZptdBI5rIlG4YOzyeH/WefQt5rj1grasPn4iiZWKet8nkgc4GlsAylaztn0qZfUYOiTsASJFdNA==",
+ "dev": true
+ },
+ "jsonparse": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+ "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==",
+ "dev": true
+ },
+ "JSONStream": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
+ "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+ "dev": true,
+ "requires": {
+ "jsonparse": "^1.2.0",
+ "through": ">=2.2.7 <3"
+ }
+ },
+ "jsprim": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz",
+ "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==",
+ "dev": true,
+ "requires": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.3.0",
+ "json-schema": "0.4.0",
+ "verror": "1.10.0"
+ },
+ "dependencies": {
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
+ "dev": true
+ },
+ "verror": {
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
+ "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ }
+ }
+ }
+ },
+ "knuth-shuffle-seeded": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/knuth-shuffle-seeded/-/knuth-shuffle-seeded-1.0.6.tgz",
+ "integrity": "sha512-9pFH0SplrfyKyojCLxZfMcvkhf5hH0d+UwR9nTVJ/DDQJGuzcXjTwB7TP7sDfehSudlGGaOLblmEWqv04ERVWg==",
+ "dev": true,
+ "requires": {
+ "seed-random": "~2.2.0"
+ }
+ },
+ "labeled-stream-splicer": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.2.tgz",
+ "integrity": "sha512-Ca4LSXFFZUjPScRaqOcFxneA0VpKZr4MMYCljyQr4LIewTLb3Y0IUTIsnBBsVubIeEfxeSZpSjSsRM8APEQaAw==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "stream-splicer": "^2.0.0"
+ }
+ },
+ "lazy-ass": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz",
+ "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==",
+ "dev": true
+ },
+ "levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ }
+ },
+ "listr2": {
+ "version": "3.14.0",
+ "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz",
+ "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==",
+ "dev": true,
+ "requires": {
+ "cli-truncate": "^2.1.0",
+ "colorette": "^2.0.16",
+ "log-update": "^4.0.0",
+ "p-map": "^4.0.0",
+ "rfdc": "^1.3.0",
+ "rxjs": "^7.5.1",
+ "through": "^2.3.8",
+ "wrap-ansi": "^7.0.0"
+ }
+ },
+ "locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "requires": {
+ "p-locate": "^5.0.0"
+ }
+ },
+ "lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "dev": true
+ },
+ "lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
+ "dev": true
+ },
+ "lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+ "dev": true
+ },
+ "lodash.isempty": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz",
+ "integrity": "sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==",
+ "dev": true
+ },
+ "lodash.isfunction": {
+ "version": "3.0.9",
+ "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz",
+ "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==",
+ "dev": true
+ },
+ "lodash.isobject": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-3.0.2.tgz",
+ "integrity": "sha512-3/Qptq2vr7WeJbB4KHUSKlq8Pl7ASXi3UG6CMbBm8WRtXi8+GHm7mKaU3urfpSEzWe2wCIChs6/sdocUsTKJiA==",
+ "dev": true
+ },
+ "lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+ "dev": true
+ },
+ "lodash.memoize": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-3.0.4.tgz",
+ "integrity": "sha512-eDn9kqrAmVUC1wmZvlQ6Uhde44n+tXpqPrN8olQJbttgh0oKclk+SF54P47VEGE9CEiMeRwAP8BaM7UHvBkz2A==",
+ "dev": true
+ },
+ "lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "peer": true
+ },
+ "lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
+ "dev": true
+ },
+ "log-symbols": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+ "requires": {
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
+ }
+ },
+ "log-update": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
+ "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
+ "dev": true,
+ "requires": {
+ "ansi-escapes": "^4.3.0",
+ "cli-cursor": "^3.1.0",
+ "slice-ansi": "^4.0.0",
+ "wrap-ansi": "^6.2.0"
+ },
+ "dependencies": {
+ "slice-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+ "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ }
+ },
+ "wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ }
+ }
+ },
+ "loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dev": true,
+ "requires": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ }
+ },
+ "loupe": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.4.tgz",
+ "integrity": "sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ==",
+ "dev": true,
+ "requires": {
+ "get-func-name": "^2.0.0"
+ }
+ },
+ "lower-case": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
+ "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==",
+ "dev": true
+ },
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dev": true,
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "md5.js": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
+ "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
+ "dev": true,
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ }
+ },
+ "merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
+ },
+ "merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "peer": true
+ },
+ "micromatch": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
+ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "braces": "^3.0.2",
+ "picomatch": "^2.3.1"
+ }
+ },
+ "miller-rabin": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
+ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.0.0",
+ "brorand": "^1.0.1"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ }
+ }
+ },
+ "mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "dev": true
+ },
+ "mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dev": true,
+ "requires": {
+ "mime-db": "1.52.0"
+ }
+ },
+ "mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true
+ },
+ "minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "dev": true
+ },
+ "minimalistic-crypto-utils": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
+ "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==",
+ "dev": true
+ },
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz",
+ "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==",
+ "dev": true
+ },
+ "mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+ "dev": true
+ },
+ "mocha": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/mocha/-/mocha-9.2.2.tgz",
+ "integrity": "sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g==",
+ "requires": {
+ "@ungap/promise-all-settled": "1.1.2",
+ "ansi-colors": "4.1.1",
+ "browser-stdout": "1.3.1",
+ "chokidar": "3.5.3",
+ "debug": "4.3.3",
+ "diff": "5.0.0",
+ "escape-string-regexp": "4.0.0",
+ "find-up": "5.0.0",
+ "glob": "7.2.0",
+ "growl": "1.10.5",
+ "he": "1.2.0",
+ "js-yaml": "4.1.0",
+ "log-symbols": "4.1.0",
+ "minimatch": "4.2.1",
+ "ms": "2.1.3",
+ "nanoid": "3.3.1",
+ "serialize-javascript": "6.0.0",
+ "strip-json-comments": "3.1.1",
+ "supports-color": "8.1.1",
+ "which": "2.0.2",
+ "workerpool": "6.2.0",
+ "yargs": "16.2.0",
+ "yargs-parser": "20.2.4",
+ "yargs-unparser": "2.0.0"
+ },
+ "dependencies": {
+ "ansi-colors": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
+ "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA=="
+ },
+ "argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
+ },
+ "chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "requires": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "fsevents": "~2.3.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ }
+ },
+ "debug": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
+ "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+ "requires": {
+ "ms": "2.1.2"
+ },
+ "dependencies": {
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ }
+ }
+ },
+ "diff": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
+ "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w=="
+ },
+ "escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
+ },
+ "glob": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
+ "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "dependencies": {
+ "minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ }
+ }
+ },
+ "js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "requires": {
+ "argparse": "^2.0.1"
+ }
+ },
+ "minimatch": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.1.tgz",
+ "integrity": "sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ }
+ }
+ },
+ "mochawesome": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/mochawesome/-/mochawesome-7.1.3.tgz",
+ "integrity": "sha512-Vkb3jR5GZ1cXohMQQ73H3cZz7RoxGjjUo0G5hu0jLaW+0FdUxUwg3Cj29bqQdh0rFcnyV06pWmqmi5eBPnEuNQ==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.1.2",
+ "diff": "^5.0.0",
+ "json-stringify-safe": "^5.0.1",
+ "lodash.isempty": "^4.4.0",
+ "lodash.isfunction": "^3.0.9",
+ "lodash.isobject": "^3.0.2",
+ "lodash.isstring": "^4.0.1",
+ "mochawesome-report-generator": "^6.2.0",
+ "strip-ansi": "^6.0.1",
+ "uuid": "^8.3.2"
+ },
+ "dependencies": {
+ "diff": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz",
+ "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==",
+ "dev": true
+ }
+ }
+ },
+ "mochawesome-merge": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/mochawesome-merge/-/mochawesome-merge-4.2.1.tgz",
+ "integrity": "sha512-G7+LqIKgixShKG4FyWDn1PIrzpKEwCofrJip/VzdqghNGqZl4S5MNoXx5YDfk9KLe+pr4qGa1TOzCc/oVw/8Kw==",
+ "dev": true,
+ "requires": {
+ "fs-extra": "^7.0.1",
+ "glob": "^7.1.6",
+ "yargs": "^15.3.1"
+ },
+ "dependencies": {
+ "camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true
+ },
+ "cliui": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
+ "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "dev": true,
+ "requires": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.0",
+ "wrap-ansi": "^6.2.0"
+ }
+ },
+ "decamelize": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
+ "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
+ "dev": true
+ },
+ "find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "requires": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ }
+ },
+ "fs-extra": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
+ "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.2",
+ "jsonfile": "^4.0.0",
+ "universalify": "^0.1.0"
+ }
+ },
+ "jsonfile": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
+ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "requires": {
+ "p-locate": "^4.1.0"
+ }
+ },
+ "p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "requires": {
+ "p-try": "^2.0.0"
+ }
+ },
+ "p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "requires": {
+ "p-limit": "^2.2.0"
+ }
+ },
+ "universalify": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
+ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
+ "dev": true
+ },
+ "wrap-ansi": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+ "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "y18n": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "15.4.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
+ "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
+ "dev": true,
+ "requires": {
+ "cliui": "^6.0.0",
+ "decamelize": "^1.2.0",
+ "find-up": "^4.1.0",
+ "get-caller-file": "^2.0.1",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^2.0.0",
+ "set-blocking": "^2.0.0",
+ "string-width": "^4.2.0",
+ "which-module": "^2.0.0",
+ "y18n": "^4.0.0",
+ "yargs-parser": "^18.1.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "18.1.3",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
+ "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
+ "dev": true,
+ "requires": {
+ "camelcase": "^5.0.0",
+ "decamelize": "^1.2.0"
+ }
+ }
+ }
+ },
+ "mochawesome-report-generator": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/mochawesome-report-generator/-/mochawesome-report-generator-6.2.0.tgz",
+ "integrity": "sha512-Ghw8JhQFizF0Vjbtp9B0i//+BOkV5OWcQCPpbO0NGOoxV33o+gKDYU0Pr2pGxkIHnqZ+g5mYiXF7GMNgAcDpSg==",
+ "dev": true,
+ "requires": {
+ "chalk": "^4.1.2",
+ "dateformat": "^4.5.1",
+ "escape-html": "^1.0.3",
+ "fs-extra": "^10.0.0",
+ "fsu": "^1.1.1",
+ "lodash.isfunction": "^3.0.9",
+ "opener": "^1.5.2",
+ "prop-types": "^15.7.2",
+ "tcomb": "^3.2.17",
+ "tcomb-validation": "^3.3.0",
+ "validator": "^13.6.0",
+ "yargs": "^17.2.1"
+ },
+ "dependencies": {
+ "fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+ "dev": true,
+ "requires": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ }
+ },
+ "yargs": {
+ "version": "17.5.1",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz",
+ "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==",
+ "dev": true,
+ "requires": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.0.0"
+ }
+ },
+ "yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true
+ }
+ }
+ },
+ "module-deps": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/module-deps/-/module-deps-6.2.3.tgz",
+ "integrity": "sha512-fg7OZaQBcL4/L+AK5f4iVqf9OMbCclXfy/znXRxTVhJSeW5AIlS9AwheYwDaXM3lVW7OBeaeUEY3gbaC6cLlSA==",
+ "dev": true,
+ "requires": {
+ "browser-resolve": "^2.0.0",
+ "cached-path-relative": "^1.0.2",
+ "concat-stream": "~1.6.0",
+ "defined": "^1.0.0",
+ "detective": "^5.2.0",
+ "duplexer2": "^0.1.2",
+ "inherits": "^2.0.1",
+ "JSONStream": "^1.0.3",
+ "parents": "^1.0.0",
+ "readable-stream": "^2.0.2",
+ "resolve": "^1.4.0",
+ "stream-combiner2": "^1.1.1",
+ "subarg": "^1.0.0",
+ "through2": "^2.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "dev": true
+ },
+ "mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "dev": true,
+ "requires": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
+ "nanoid": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.1.tgz",
+ "integrity": "sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw=="
+ },
+ "natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "peer": true
+ },
+ "next-tick": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
+ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==",
+ "dev": true
+ },
+ "no-case": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
+ "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
+ "dev": true,
+ "requires": {
+ "lower-case": "^1.1.1"
+ }
+ },
+ "node-releases": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
+ "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
+ "dev": true
+ },
+ "normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
+ },
+ "npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "requires": {
+ "path-key": "^3.0.0"
+ }
+ },
+ "object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "dev": true
+ },
+ "object-inspect": {
+ "version": "1.12.2",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
+ "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==",
+ "dev": true
+ },
+ "object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true
+ },
+ "object.assign": {
+ "version": "4.1.4",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
+ "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ }
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "requires": {
+ "mimic-fn": "^2.1.0"
+ }
+ },
+ "opener": {
+ "version": "1.5.2",
+ "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
+ "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
+ "dev": true
+ },
+ "optionator": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
+ "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.3"
+ }
+ },
+ "os-browserify": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
+ "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==",
+ "dev": true
+ },
+ "ospath": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz",
+ "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==",
+ "dev": true
+ },
+ "outpipe": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/outpipe/-/outpipe-1.1.1.tgz",
+ "integrity": "sha512-BnNY/RwnDrkmQdUa9U+OfN/Y7AWmKuUPCCd+hbRclZnnANvYpO72zp/a6Q4n829hPbdqEac31XCcsvlEvb+rtA==",
+ "dev": true,
+ "requires": {
+ "shell-quote": "^1.4.2"
+ }
+ },
+ "p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "requires": {
+ "yocto-queue": "^0.1.0"
+ }
+ },
+ "p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "requires": {
+ "p-limit": "^3.0.2"
+ }
+ },
+ "p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "dev": true,
+ "requires": {
+ "aggregate-error": "^3.0.0"
+ }
+ },
+ "p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true
+ },
+ "pad-right": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/pad-right/-/pad-right-0.2.2.tgz",
+ "integrity": "sha512-4cy8M95ioIGolCoMmm2cMntGR1lPLEbOMzOKu8bzjuJP6JpzEMQcDHmh7hHLYGgob+nKe1YHFMaG4V59HQa89g==",
+ "dev": true,
+ "requires": {
+ "repeat-string": "^1.5.2"
+ }
+ },
+ "pako": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
+ "dev": true
+ },
+ "parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "callsites": "^3.0.0"
+ }
+ },
+ "parents": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parents/-/parents-1.0.1.tgz",
+ "integrity": "sha512-mXKF3xkoUt5td2DoxpLmtOmZvko9VfFpwRwkKDHSNvgmpLAeBo18YDhcPbBzJq+QLCHMbGOfzia2cX4U+0v9Mg==",
+ "dev": true,
+ "requires": {
+ "path-platform": "~0.11.15"
+ }
+ },
+ "parse-asn1": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz",
+ "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==",
+ "dev": true,
+ "requires": {
+ "asn1.js": "^5.2.0",
+ "browserify-aes": "^1.0.0",
+ "evp_bytestokey": "^1.0.0",
+ "pbkdf2": "^3.0.3",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "parse-json": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
+ "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
+ "requires": {
+ "error-ex": "^1.3.1",
+ "json-parse-better-errors": "^1.0.1"
+ }
+ },
+ "path-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz",
+ "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==",
+ "dev": true
+ },
+ "path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
+ },
+ "path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true
+ },
+ "path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "path-platform": {
+ "version": "0.11.15",
+ "resolved": "https://registry.npmjs.org/path-platform/-/path-platform-0.11.15.tgz",
+ "integrity": "sha512-Y30dB6rab1A/nfEKsZxmr01nUotHX0c/ZiIAsCTatEe1CmS5Pm5He7fZ195bPT7RdquoaL8lLxFCMQi/bS7IJg==",
+ "dev": true
+ },
+ "path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "peer": true
+ },
+ "pathval": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
+ "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
+ "dev": true
+ },
+ "pbkdf2": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
+ "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==",
+ "dev": true,
+ "requires": {
+ "create-hash": "^1.1.2",
+ "create-hmac": "^1.1.4",
+ "ripemd160": "^2.0.1",
+ "safe-buffer": "^5.0.1",
+ "sha.js": "^2.4.8"
+ }
+ },
+ "pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
+ "dev": true
+ },
+ "performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
+ "dev": true
+ },
+ "picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
+ "dev": true
+ },
+ "picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
+ },
+ "pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "dev": true
+ },
+ "prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "peer": true
+ },
+ "prettier": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
+ "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g=="
+ },
+ "pretty-bytes": {
+ "version": "5.6.0",
+ "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz",
+ "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
+ "dev": true
+ },
+ "process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "dev": true
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "dev": true
+ },
+ "prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dev": true,
+ "requires": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "proxy-from-env": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
+ "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==",
+ "dev": true
+ },
+ "psl": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
+ "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==",
+ "dev": true
+ },
+ "public-encrypt": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
+ "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
+ "dev": true,
+ "requires": {
+ "bn.js": "^4.1.0",
+ "browserify-rsa": "^4.0.0",
+ "create-hash": "^1.1.0",
+ "parse-asn1": "^5.0.0",
+ "randombytes": "^2.0.1",
+ "safe-buffer": "^5.1.2"
+ },
+ "dependencies": {
+ "bn.js": {
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
+ "dev": true
+ }
+ }
+ },
+ "pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dev": true,
+ "requires": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "punycode": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
+ "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==",
+ "dev": true
+ },
+ "qs": {
+ "version": "6.5.3",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
+ "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
+ "dev": true
+ },
+ "querystring": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
+ "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==",
+ "dev": true
+ },
+ "querystring-es3": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+ "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==",
+ "dev": true
+ },
+ "queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "peer": true
+ },
+ "randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "requires": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "randomfill": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
+ "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
+ "dev": true,
+ "requires": {
+ "randombytes": "^2.0.5",
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
+ "dev": true
+ },
+ "read-only-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz",
+ "integrity": "sha512-3ALe0bjBVZtkdWKIcThYpQCLbBMd/+Tbh2CDSrAIDO3UsZ4Xs+tnyjv2MjCOMMgBG+AsUOeuP1cgtY1INISc8w==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dev": true,
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ },
+ "dependencies": {
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ }
+ }
+ },
+ "readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "requires": {
+ "picomatch": "^2.2.1"
+ }
+ },
+ "regenerate": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
+ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
+ "dev": true
+ },
+ "regenerate-unicode-properties": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz",
+ "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==",
+ "dev": true,
+ "requires": {
+ "regenerate": "^1.4.2"
+ }
+ },
+ "regenerator-runtime": {
+ "version": "0.13.9",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
+ "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==",
+ "dev": true
+ },
+ "regenerator-transform": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz",
+ "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==",
+ "dev": true,
+ "requires": {
+ "@babel/runtime": "^7.8.4"
+ }
+ },
+ "regexp.prototype.flags": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz",
+ "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.3",
+ "functions-have-names": "^1.2.2"
+ }
+ },
+ "regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true,
+ "peer": true
+ },
+ "regexpu-core": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz",
+ "integrity": "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==",
+ "dev": true,
+ "requires": {
+ "regenerate": "^1.4.2",
+ "regenerate-unicode-properties": "^10.0.1",
+ "regjsgen": "^0.6.0",
+ "regjsparser": "^0.8.2",
+ "unicode-match-property-ecmascript": "^2.0.0",
+ "unicode-match-property-value-ecmascript": "^2.0.0"
+ }
+ },
+ "regjsgen": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz",
+ "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==",
+ "dev": true
+ },
+ "regjsparser": {
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz",
+ "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==",
+ "dev": true,
+ "requires": {
+ "jsesc": "~0.5.0"
+ },
+ "dependencies": {
+ "jsesc": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
+ "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
+ "dev": true
+ }
+ }
+ },
+ "repeat-string": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
+ "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
+ "dev": true
+ },
+ "request-progress": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz",
+ "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==",
+ "dev": true,
+ "requires": {
+ "throttleit": "^1.0.0"
+ }
+ },
+ "require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="
+ },
+ "require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="
+ },
+ "require-main-filename": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
+ "dev": true
+ },
+ "resolve": {
+ "version": "1.22.1",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+ "dev": true,
+ "requires": {
+ "is-core-module": "^2.9.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ }
+ },
+ "resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "peer": true
+ },
+ "restore-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+ "dev": true,
+ "requires": {
+ "onetime": "^5.1.0",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "peer": true
+ },
+ "rfdc": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
+ "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
+ "dev": true
+ },
+ "rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "dev": true,
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "ripemd160": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
+ "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
+ "dev": true,
+ "requires": {
+ "hash-base": "^3.0.0",
+ "inherits": "^2.0.1"
+ }
+ },
+ "run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "rxjs": {
+ "version": "7.5.6",
+ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.5.6.tgz",
+ "integrity": "sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==",
+ "dev": true,
+ "requires": {
+ "tslib": "^2.1.0"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
+ },
+ "safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "seed-random": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/seed-random/-/seed-random-2.2.0.tgz",
+ "integrity": "sha512-34EQV6AAHQGhoc0tn/96a9Fsi6v2xdqe/dMUwljGRaFOzR3EgRmECvD0O8vi8X+/uQ50LGHfkNu/Eue5TPKZkQ==",
+ "dev": true
+ },
+ "semver": {
+ "version": "7.3.7",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz",
+ "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==",
+ "dev": true,
+ "requires": {
+ "lru-cache": "^6.0.0"
+ }
+ },
+ "serialize-error": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz",
+ "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==",
+ "dev": true
+ },
+ "serialize-javascript": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
+ "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
+ "requires": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+ "dev": true
+ },
+ "sha.js": {
+ "version": "2.4.11",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
+ "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "shasum": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/shasum/-/shasum-1.0.2.tgz",
+ "integrity": "sha512-UTzHm/+AzKfO9RgPgRpDIuMSNie1ubXRaljjlhFMNGYoG7z+rm9AHLPMf70R7887xboDH9Q+5YQbWKObFHEAtw==",
+ "dev": true,
+ "requires": {
+ "json-stable-stringify": "~0.0.0",
+ "sha.js": "~2.4.4"
+ }
+ },
+ "shasum-object": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shasum-object/-/shasum-object-1.0.0.tgz",
+ "integrity": "sha512-Iqo5rp/3xVi6M4YheapzZhhGPVs0yZwHj7wvwQ1B9z8H6zk+FEnI7y3Teq7qwnekfEhu8WmG2z0z4iWZaxLWVg==",
+ "dev": true,
+ "requires": {
+ "fast-safe-stringify": "^2.0.7"
+ }
+ },
+ "shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "requires": {
+ "shebang-regex": "^3.0.0"
+ }
+ },
+ "shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true
+ },
+ "shell-quote": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz",
+ "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==",
+ "dev": true
+ },
+ "side-channel": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
+ "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.0",
+ "get-intrinsic": "^1.0.2",
+ "object-inspect": "^1.9.0"
+ }
+ },
+ "signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "dev": true
+ },
+ "slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "peer": true
+ },
+ "slice-ansi": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
+ "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
+ "dev": true,
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "astral-regex": "^2.0.0",
+ "is-fullwidth-code-point": "^3.0.0"
+ }
+ },
+ "source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "dev": true
+ },
+ "sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
+ },
+ "sshpk": {
+ "version": "1.17.0",
+ "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz",
+ "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==",
+ "dev": true,
+ "requires": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "bcrypt-pbkdf": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "ecc-jsbn": "~0.1.1",
+ "getpass": "^0.1.1",
+ "jsbn": "~0.1.0",
+ "safer-buffer": "^2.0.2",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "stack-chain": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/stack-chain/-/stack-chain-2.0.0.tgz",
+ "integrity": "sha512-GGrHXePi305aW7XQweYZZwiRwR7Js3MWoK/EHzzB9ROdc75nCnjSJVi21rdAGxFl+yCx2L2qdfl5y7NO4lTyqg==",
+ "dev": true
+ },
+ "stack-generator": {
+ "version": "2.0.10",
+ "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz",
+ "integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==",
+ "dev": true,
+ "requires": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "stackframe": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
+ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
+ "dev": true
+ },
+ "stacktrace-gps": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz",
+ "integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==",
+ "dev": true,
+ "requires": {
+ "source-map": "0.5.6",
+ "stackframe": "^1.3.4"
+ },
+ "dependencies": {
+ "source-map": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz",
+ "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==",
+ "dev": true
+ }
+ }
+ },
+ "stacktrace-js": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz",
+ "integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==",
+ "dev": true,
+ "requires": {
+ "error-stack-parser": "^2.0.6",
+ "stack-generator": "^2.0.5",
+ "stacktrace-gps": "^3.0.4"
+ }
+ },
+ "stream-browserify": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
+ "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==",
+ "dev": true,
+ "requires": {
+ "inherits": "~2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "stream-combiner2": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz",
+ "integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==",
+ "dev": true,
+ "requires": {
+ "duplexer2": "~0.1.0",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "stream-http": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz",
+ "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==",
+ "dev": true,
+ "requires": {
+ "builtin-status-codes": "^3.0.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.6.0",
+ "xtend": "^4.0.2"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "stream-splicer": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/stream-splicer/-/stream-splicer-2.0.1.tgz",
+ "integrity": "sha512-Xizh4/NPuYSyAXyT7g8IvdJ9HJpxIGL9PjyhtywCZvvP0OPIdqyrr4dMikeuvY8xahpdKEBlBTySe583totajg==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "string-argv": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.0.2.tgz",
+ "integrity": "sha512-p6/Mqq0utTQWUeGMi/m0uBtlLZEwXSY3+mXzeRRqw7fz5ezUb28Wr0R99NlfbWaMmL/jCyT9be4jpn7Yz8IO8w==",
+ "dev": true
+ },
+ "string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "requires": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "string.prototype.trimend": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz",
+ "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ }
+ },
+ "string.prototype.trimstart": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz",
+ "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.1.4",
+ "es-abstract": "^1.19.5"
+ }
+ },
+ "strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "requires": {
+ "ansi-regex": "^5.0.1"
+ }
+ },
+ "strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true
+ },
+ "strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="
+ },
+ "subarg": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz",
+ "integrity": "sha512-RIrIdRY0X1xojthNcVtgT9sjpOGagEUKpZdgBUi054OEPFo282yg+zE+t1Rj3+RqKq2xStL7uUHhY+AjbC4BXg==",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.1.0"
+ }
+ },
+ "supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ },
+ "supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true
+ },
+ "syntax-error": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/syntax-error/-/syntax-error-1.4.0.tgz",
+ "integrity": "sha512-YPPlu67mdnHGTup2A8ff7BC2Pjq0e0Yp/IyTFN03zWO0RcK07uLcbi7C2KpGR2FvWbaB0+bfE27a+sBKebSo7w==",
+ "dev": true,
+ "requires": {
+ "acorn-node": "^1.2.0"
+ }
+ },
+ "tcomb": {
+ "version": "3.2.29",
+ "resolved": "https://registry.npmjs.org/tcomb/-/tcomb-3.2.29.tgz",
+ "integrity": "sha512-di2Hd1DB2Zfw6StGv861JoAF5h/uQVu/QJp2g8KVbtfKnoHdBQl5M32YWq6mnSYBQ1vFFrns5B1haWJL7rKaOQ==",
+ "dev": true
+ },
+ "tcomb-validation": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/tcomb-validation/-/tcomb-validation-3.4.1.tgz",
+ "integrity": "sha512-urVVMQOma4RXwiVCa2nM2eqrAomHROHvWPuj6UkDGz/eb5kcy0x6P0dVt6kzpUZtYMNoAqJLWmz1BPtxrtjtrA==",
+ "dev": true,
+ "requires": {
+ "tcomb": "^3.0.0"
+ }
+ },
+ "text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true,
+ "peer": true
+ },
+ "thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "dev": true,
+ "requires": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "dev": true,
+ "requires": {
+ "thenify": ">= 3.1.0 < 4"
+ }
+ },
+ "throttleit": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz",
+ "integrity": "sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==",
+ "dev": true
+ },
+ "through": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
+ "dev": true
+ },
+ "through2": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "~2.3.6",
+ "xtend": "~4.0.1"
+ }
+ },
+ "timers-browserify": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-1.4.2.tgz",
+ "integrity": "sha512-PIxwAupJZiYU4JmVZYwXp9FKsHMXb5h0ZEFyuXTAn8WLHOlcij+FEcbrvDsom1o5dr1YggEtFbECvGCW2sT53Q==",
+ "dev": true,
+ "requires": {
+ "process": "~0.11.0"
+ }
+ },
+ "title-case": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/title-case/-/title-case-2.1.1.tgz",
+ "integrity": "sha512-EkJoZ2O3zdCz3zJsYCsxyq2OC5hrxR9mfdd5I+w8h/tmFfeOxJ+vvkxsKxdmN0WtS9zLdHEgfgVOiMVgv+Po4Q==",
+ "dev": true,
+ "requires": {
+ "no-case": "^2.2.0",
+ "upper-case": "^1.0.3"
+ }
+ },
+ "tmp": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
+ "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
+ "dev": true,
+ "requires": {
+ "rimraf": "^3.0.0"
+ }
+ },
+ "to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+ "dev": true
+ },
+ "to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "requires": {
+ "is-number": "^7.0.0"
+ }
+ },
+ "tough-cookie": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
+ "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
+ "dev": true,
+ "requires": {
+ "psl": "^1.1.28",
+ "punycode": "^2.1.1"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true
+ }
+ }
+ },
+ "tslib": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
+ "dev": true
+ },
+ "tty-browserify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz",
+ "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==",
+ "dev": true
+ },
+ "tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "dev": true,
+ "requires": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "tweetnacl": {
+ "version": "0.14.5",
+ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
+ "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
+ "dev": true
+ },
+ "type": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
+ "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
+ "dev": true
+ },
+ "type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "prelude-ls": "^1.2.1"
+ }
+ },
+ "type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true
+ },
+ "type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
+ "dev": true
+ },
+ "umd": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/umd/-/umd-3.0.3.tgz",
+ "integrity": "sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow==",
+ "dev": true
+ },
+ "unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ }
+ },
+ "undeclared-identifiers": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/undeclared-identifiers/-/undeclared-identifiers-1.1.3.tgz",
+ "integrity": "sha512-pJOW4nxjlmfwKApE4zvxLScM/njmwj/DiUBv7EabwE4O8kRUy+HIwxQtZLBPll/jx1LJyBcqNfB3/cpv9EZwOw==",
+ "dev": true,
+ "requires": {
+ "acorn-node": "^1.3.0",
+ "dash-ast": "^1.0.0",
+ "get-assigned-identifiers": "^1.2.0",
+ "simple-concat": "^1.0.0",
+ "xtend": "^4.0.1"
+ }
+ },
+ "unicode-canonical-property-names-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==",
+ "dev": true
+ },
+ "unicode-match-property-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
+ "dev": true,
+ "requires": {
+ "unicode-canonical-property-names-ecmascript": "^2.0.0",
+ "unicode-property-aliases-ecmascript": "^2.0.0"
+ }
+ },
+ "unicode-match-property-value-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==",
+ "dev": true
+ },
+ "unicode-property-aliases-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==",
+ "dev": true
+ },
+ "universalify": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
+ "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
+ "dev": true
+ },
+ "untildify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz",
+ "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==",
+ "dev": true
+ },
+ "update-browserslist-db": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
+ "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==",
+ "dev": true,
+ "requires": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ }
+ },
+ "upper-case": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
+ "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==",
+ "dev": true
+ },
+ "uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "peer": true,
+ "requires": {
+ "punycode": "^2.1.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
+ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
+ "dev": true,
+ "peer": true
+ }
+ }
+ },
+ "url": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
+ "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==",
+ "dev": true,
+ "requires": {
+ "punycode": "1.3.2",
+ "querystring": "0.2.0"
+ },
+ "dependencies": {
+ "punycode": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
+ "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==",
+ "dev": true
+ }
+ }
+ },
+ "util": {
+ "version": "0.10.4",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
+ "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
+ "dev": true,
+ "requires": {
+ "inherits": "2.0.3"
+ },
+ "dependencies": {
+ "inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
+ "dev": true
+ }
+ }
+ },
+ "util-arity": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/util-arity/-/util-arity-1.1.0.tgz",
+ "integrity": "sha512-kkyIsXKwemfSy8ZEoaIz06ApApnWsk5hQO0vLjZS6UkBiGiW++Jsyb8vSBoc0WKlffGoGs5yYy/j5pp8zckrFA==",
+ "dev": true
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true
+ },
+ "uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "dev": true
+ },
+ "validator": {
+ "version": "13.7.0",
+ "resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz",
+ "integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw==",
+ "dev": true
+ },
+ "verror": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz",
+ "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==",
+ "dev": true,
+ "requires": {
+ "assert-plus": "^1.0.0",
+ "core-util-is": "1.0.2",
+ "extsprintf": "^1.2.0"
+ },
+ "dependencies": {
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
+ "dev": true
+ }
+ }
+ },
+ "vm-browserify": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
+ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
+ "dev": true
+ },
+ "watchify": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/watchify/-/watchify-4.0.0.tgz",
+ "integrity": "sha512-2Z04dxwoOeNxa11qzWumBTgSAohTC0+ScuY7XMenPnH+W2lhTcpEOJP4g2EIG/SWeLadPk47x++Yh+8BqPM/lA==",
+ "dev": true,
+ "requires": {
+ "anymatch": "^3.1.0",
+ "browserify": "^17.0.0",
+ "chokidar": "^3.4.0",
+ "defined": "^1.0.0",
+ "outpipe": "^1.1.0",
+ "through2": "^4.0.2",
+ "xtend": "^4.0.2"
+ },
+ "dependencies": {
+ "browserify": {
+ "version": "17.0.0",
+ "resolved": "https://registry.npmjs.org/browserify/-/browserify-17.0.0.tgz",
+ "integrity": "sha512-SaHqzhku9v/j6XsQMRxPyBrSP3gnwmE27gLJYZgMT2GeK3J0+0toN+MnuNYDfHwVGQfLiMZ7KSNSIXHemy905w==",
+ "dev": true,
+ "requires": {
+ "assert": "^1.4.0",
+ "browser-pack": "^6.0.1",
+ "browser-resolve": "^2.0.0",
+ "browserify-zlib": "~0.2.0",
+ "buffer": "~5.2.1",
+ "cached-path-relative": "^1.0.0",
+ "concat-stream": "^1.6.0",
+ "console-browserify": "^1.1.0",
+ "constants-browserify": "~1.0.0",
+ "crypto-browserify": "^3.0.0",
+ "defined": "^1.0.0",
+ "deps-sort": "^2.0.1",
+ "domain-browser": "^1.2.0",
+ "duplexer2": "~0.1.2",
+ "events": "^3.0.0",
+ "glob": "^7.1.0",
+ "has": "^1.0.0",
+ "htmlescape": "^1.1.0",
+ "https-browserify": "^1.0.0",
+ "inherits": "~2.0.1",
+ "insert-module-globals": "^7.2.1",
+ "JSONStream": "^1.0.3",
+ "labeled-stream-splicer": "^2.0.0",
+ "mkdirp-classic": "^0.5.2",
+ "module-deps": "^6.2.3",
+ "os-browserify": "~0.3.0",
+ "parents": "^1.0.1",
+ "path-browserify": "^1.0.0",
+ "process": "~0.11.0",
+ "punycode": "^1.3.2",
+ "querystring-es3": "~0.2.0",
+ "read-only-stream": "^2.0.0",
+ "readable-stream": "^2.0.2",
+ "resolve": "^1.1.4",
+ "shasum-object": "^1.0.0",
+ "shell-quote": "^1.6.1",
+ "stream-browserify": "^3.0.0",
+ "stream-http": "^3.0.0",
+ "string_decoder": "^1.1.1",
+ "subarg": "^1.0.0",
+ "syntax-error": "^1.1.1",
+ "through2": "^2.0.0",
+ "timers-browserify": "^1.0.1",
+ "tty-browserify": "0.0.1",
+ "url": "~0.11.0",
+ "util": "~0.12.0",
+ "vm-browserify": "^1.0.0",
+ "xtend": "^4.0.0"
+ },
+ "dependencies": {
+ "through2": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
+ "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "~2.3.6",
+ "xtend": "~4.0.1"
+ }
+ }
+ }
+ },
+ "buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.2.1.tgz",
+ "integrity": "sha512-c+Ko0loDaFfuPWiL02ls9Xd3GO3cPVmUobQ6t3rXNUk304u6hGq+8N/kFi+QEIKhzK3uwolVhLzszmfLmMLnqg==",
+ "dev": true,
+ "requires": {
+ "base64-js": "^1.0.2",
+ "ieee754": "^1.1.4"
+ }
+ },
+ "events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "dev": true
+ },
+ "path-browserify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz",
+ "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
+ "dev": true
+ },
+ "stream-browserify": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz",
+ "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==",
+ "dev": true,
+ "requires": {
+ "inherits": "~2.0.4",
+ "readable-stream": "^3.5.0"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "through2": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
+ "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
+ "dev": true,
+ "requires": {
+ "readable-stream": "3"
+ },
+ "dependencies": {
+ "readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ }
+ }
+ }
+ },
+ "util": {
+ "version": "0.12.4",
+ "resolved": "https://registry.npmjs.org/util/-/util-0.12.4.tgz",
+ "integrity": "sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw==",
+ "dev": true,
+ "requires": {
+ "inherits": "^2.0.3",
+ "is-arguments": "^1.0.4",
+ "is-generator-function": "^1.0.7",
+ "is-typed-array": "^1.1.3",
+ "safe-buffer": "^5.1.2",
+ "which-typed-array": "^1.1.2"
+ }
+ }
+ }
+ },
+ "which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "requires": {
+ "isexe": "^2.0.0"
+ }
+ },
+ "which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "requires": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ }
+ },
+ "which-module": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
+ "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==",
+ "dev": true
+ },
+ "which-typed-array": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.8.tgz",
+ "integrity": "sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==",
+ "dev": true,
+ "requires": {
+ "available-typed-arrays": "^1.0.5",
+ "call-bind": "^1.0.2",
+ "es-abstract": "^1.20.0",
+ "for-each": "^0.3.3",
+ "has-tostringtag": "^1.0.0",
+ "is-typed-array": "^1.1.9"
+ }
+ },
+ "word-wrap": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
+ "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "dev": true,
+ "peer": true
+ },
+ "workerpool": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.0.tgz",
+ "integrity": "sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A=="
+ },
+ "wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "requires": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ }
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "dev": true
+ },
+ "y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "dev": true
+ },
+ "yargs": {
+ "version": "16.2.0",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
+ "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
+ "requires": {
+ "cliui": "^7.0.2",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.0",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^20.2.2"
+ }
+ },
+ "yargs-parser": {
+ "version": "20.2.4",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
+ "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA=="
+ },
+ "yargs-unparser": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
+ "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
+ "requires": {
+ "camelcase": "^6.0.0",
+ "decamelize": "^4.0.0",
+ "flat": "^5.0.2",
+ "is-plain-obj": "^2.1.0"
+ }
+ },
+ "yauzl": {
+ "version": "2.10.0",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
+ "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
+ "dev": true,
+ "requires": {
+ "buffer-crc32": "~0.2.3",
+ "fd-slicer": "~1.1.0"
+ }
+ },
+ "yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
+ }
+ }
+}
diff --git a/test/cypress/package.json b/test/cypress/package.json
new file mode 100644
index 0000000000..7f153c5667
--- /dev/null
+++ b/test/cypress/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "wazuh-kibana-app-automation",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "start": "npx cypress open ",
+ "start:xpack": "npx cypress open --config baseUrl=https://localhost:5601/ --env type=xpack",
+ "start:basic": "npx cypress open --config baseUrl=http://localhost:5601/ --env type=basic",
+ "start:odfe": "npx cypress open --config baseUrl=http://localhost:5601/ --env type=odfe",
+ "start:wzd": "npx cypress open --config baseUrl=https://localhost:5601/ --env type=wzd",
+ "cy:install": "npx cypress install --force",
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "cypress:run-headless": "cypress run --headless --browser chrome",
+ "cypress:run-headless:github-actions:xpack": "cypress-tags run -e TAGS=\"@actions\" --headless --browser chrome --config baseUrl=https://kibana:5601/ --env type=xpack -e TAGS=\"@actions\"",
+ "cypress:run-headless:github-actions:basic": "cypress-tags run -e TAGS=\"@actions\" --headless --browser chrome --config baseUrl=http://kibana:5601/ --env type=basic -e TAGS=\"@actions\"",
+ "cypress:run-headless:github-actions:odfe": "cypress-tags run -e TAGS=\"@actions\" --headless --browser chrome --config baseUrl=http://kibana:5601/ --env type=odfe -e TAGS=\"@actions\"",
+ "cypress:run-headless:github-actions:wzd": "cypress-tags run -e TAGS=\"@actions\" --headless --browser chrome --config baseUrl=https://wazuh.dashboard:5601/ --env type=wzd -e TAGS=\"@actions\"",
+ "cypress:run-headless:xpack": "cypress run --headless --browser chrome --config baseUrl=https://localhost:5601/ --env type=xpack",
+ "cypress:run-headless:basic": "cypress run --headless --browser chrome --config baseUrl=http://localhost:5601/ --env type=basic",
+ "cypress:run-headless:odfe": "cypress run --headless --browser chrome --config baseUrl=http://localhost:5601/ --env type=odfe",
+ "cypress:run-headless:wzd": "cypress run --headless --browser chrome --config baseUrl=https://localhost:5601/ --env type=wzd",
+ "cypress:run": "cypress run --headed --browser chrome",
+ "merge": "mochawesome-merge cypress/report/mochawesome-report/*.json > cypress/report/output.json",
+ "generate_mochawesome_report": "marge cypress/report/output.json --reportDir ./cypress/report --inline",
+ "cypress:report": "mochawesome-merge cypress/report/mochawesome-report/*.json > cypress/report/output.json && marge cypress/report/output.json --reportDir ./cypress/report --inline",
+ "delete:reports": "rm -r cypress/report/* || true"
+ },
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "cosmiconfig": "^4.0.0",
+ "mocha": "^10.1.0",
+ "prettier": "^2.3.0"
+ },
+ "devDependencies": {
+ "cypress": "^9.5.2",
+ "cypress-cucumber-preprocessor": "^4.0.3",
+ "cypress-real-events": "^1.7.1",
+ "cypress-xpath": "^1.6.2",
+ "eslint-plugin-cypress": "^2.11.3",
+ "mochawesome": "^7.1.3",
+ "mochawesome-merge": "^4.2.0"
+ },
+ "cypress-cucumber-preprocessor": {
+ "nonGlobalStepDefinitions": false,
+ "step_definitions": "cypress/integration/step-definitions/**/"
+ },
+ "engines": {
+ "node": "17.3.0"
+ }
+}
diff --git a/test/functional/apps/overview/_integrity_monitoring.ts b/test/functional/apps/overview/_integrity_monitoring.ts
index 588e83dd4e..2b4369e70d 100644
--- a/test/functional/apps/overview/_integrity_monitoring.ts
+++ b/test/functional/apps/overview/_integrity_monitoring.ts
@@ -10,10 +10,10 @@
* Find more information about this on the LICENSE file.
*/
-import expect from '@kbn/expect';
+import expect from '@osd/expect';
import { FtrProviderContext } from '../../../../../../test/functional/ftr_provider_context';
import { SearchParams } from 'elasticsearch';
-import { WAZUH_ALERTS_PATTERN } from '../../../../common/constants';
+import { getSettingDefaultValue } from '../../../../common/services/settings';
export default function({getService, getPageObjects, }: FtrProviderContext) {
const areaChart = getService('areaChart');
@@ -33,7 +33,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
let es_index: string;
before(async () => {
await PageObjects.wazuhCommon.OpenIntegrityMonitoring();
- es_index = WAZUH_ALERTS_PATTERN;
+ es_index = getSettingDefaultValue('pattern');
});
beforeEach(async () => {
@@ -255,7 +255,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
};
const esValues: object[] = await esTableViz.getData(query, fields, ['-Count', 'Level', '-Rule ID', ]);
-
+
expect(arrayHelper.compareObjects(values, esValues))
.to.be.ok();
});
@@ -336,7 +336,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
term: {
"rule.groups": "syscheck"
}
- },
+ },
{
"term": {
"rule.level": 7
@@ -360,7 +360,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
expect(JSON.stringify(esValues))
.to.be.equal(JSON.stringify(values));
await filterBar.removeAllFilters();
-
+
});
it('should Top 5 agents values are correct when add the filter rule.level: 7', async () => {
@@ -381,7 +381,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
term: {
"rule.groups": "syscheck"
}
- },
+ },
{
"term": {
"rule.level": 7
@@ -425,7 +425,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
term: {
"rule.groups": "syscheck"
}
- },
+ },
{
"term": {
"rule.level": 7
@@ -469,7 +469,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
term: {
"rule.groups": "syscheck"
}
- },
+ },
{
"term": {
"rule.level": 7
@@ -513,7 +513,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
term: {
"rule.groups": "syscheck"
}
- },
+ },
{
"term": {
"rule.level": 7
@@ -564,7 +564,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
term: {
"rule.groups": "syscheck"
}
- },
+ },
{
"term": {
"rule.level": 7
@@ -626,7 +626,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
term: {
"rule.groups": "syscheck"
}
- },
+ },
{
"term": {
"rule.level": 7
@@ -687,7 +687,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
term: {
"rule.groups": "syscheck"
}
- },
+ },
{
"term": {
"rule.level": 7
@@ -712,7 +712,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
.to.be.equal(JSON.stringify(values));
await queryBar.setQuery('');
await queryBar.submitQuery();
-
+
});
it('should Top 5 agents values are correct when add to the query bar rule.level: 7', async () => {
@@ -734,7 +734,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
term: {
"rule.groups": "syscheck"
}
- },
+ },
{
"term": {
"rule.level": 7
@@ -780,7 +780,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
term: {
"rule.groups": "syscheck"
}
- },
+ },
{
"term": {
"rule.level": 7
@@ -826,7 +826,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
term: {
"rule.groups": "syscheck"
}
- },
+ },
{
"term": {
"rule.level": 7
@@ -872,7 +872,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
term: {
"rule.groups": "syscheck"
}
- },
+ },
{
"term": {
"rule.level": 7
@@ -925,7 +925,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
term: {
"rule.groups": "syscheck"
}
- },
+ },
{
"term": {
"rule.level": 7
@@ -989,7 +989,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
term: {
"rule.groups": "syscheck"
}
- },
+ },
{
"term": {
"rule.level": 7
@@ -1027,7 +1027,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
await queryBar.setQuery('');
await queryBar.submitQuery();
});
-
+
//#endregion
});
-}
\ No newline at end of file
+}
diff --git a/test/functional/apps/overview/_security_events.ts b/test/functional/apps/overview/_security_events.ts
index 50bf599f05..a1af191957 100644
--- a/test/functional/apps/overview/_security_events.ts
+++ b/test/functional/apps/overview/_security_events.ts
@@ -10,10 +10,10 @@
* Find more information about this on the LICENSE file.
*/
-import expect from '@kbn/expect';
+import expect from '@osd/expect';
import { FtrProviderContext } from '../../../../../../test/functional/ftr_provider_context';
import { SearchParams } from 'elasticsearch';
-import { WAZUH_ALERTS_PATTERN } from '../../../../common/constants';
+import { getSettingDefaultValue } from '../../../../common/services/settings';
export default function({getService, getPageObjects, }: FtrProviderContext) {
const areaChart = getService('areaChart');
@@ -34,7 +34,7 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
let es_index: string;
before(async () => {
await PageObjects.wazuhCommon.OpenSecurityEvents();
- es_index = WAZUH_ALERTS_PATTERN;
+ es_index = getSettingDefaultValue('pattern');
});
beforeEach(async () => {
@@ -867,4 +867,4 @@ export default function({getService, getPageObjects, }: FtrProviderContext) {
//#endregion
});
-}
\ No newline at end of file
+}
diff --git a/test/functional/config.js b/test/functional/config.js
index f9fdd170b7..fab4babd16 100644
--- a/test/functional/config.js
+++ b/test/functional/config.js
@@ -1,5 +1,5 @@
import { resolve } from 'path';
-import { resolveKibanaPath } from '@kbn/plugin-helpers';
+import { resolveKibanaPath } from '@osd/plugin-helpers';
import { pageObjects } from './page_objects';
import { services } from './services';
diff --git a/test/functional/page_objects/api_page.js b/test/functional/page_objects/api_page.js
index 2f7773086d..fd20b7e3e6 100644
--- a/test/functional/page_objects/api_page.js
+++ b/test/functional/page_objects/api_page.js
@@ -1,4 +1,4 @@
-import expect from '@kbn/expect';
+import expect from '@osd/expect';
export function ApiProvider({ getService, getPageObjects }) {
const browser = getService('browser');
diff --git a/test/jest/config.js b/test/jest/config.js
index f619786815..a95d24efef 100644
--- a/test/jest/config.js
+++ b/test/jest/config.js
@@ -13,20 +13,22 @@ export default {
`${kbnDir}/node_modules`
],
collectCoverageFrom: [
- "**/*.{js,jsx,ts,tsx}",
- "./!**/node_modules/**",
+ '**/*.{js,jsx,ts,tsx}',
+ './!**/node_modules/**',
],
moduleNameMapper: {
'^ui/(.*)': `${kbnDir}/src/ui/public/$1`,
+ // eslint-disable-next-line max-len
'\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': `${kbnDir}/src/dev/jest/mocks/file_mock.js`,
'\\.(css|less|scss)$': `${kbnDir}/src/dev/jest/mocks/style_mock.js`,
+ 'axios': 'axios/dist/node/axios.cjs',
},
setupFiles: [
`${kbnDir}/src/dev/jest/setup/babel_polyfill.js`,
`${kbnDir}/src/dev/jest/setup/enzyme.js`,
],
collectCoverage: true,
- coverageDirectory: `./target/test-coverage`,
+ coverageDirectory: './target/test-coverage',
coverageReporters: [
'html',
'text-summary',
@@ -62,6 +64,7 @@ export default {
snapshotSerializers: [
`${kbnDir}/node_modules/enzyme-to-json/serializer`,
],
+ testEnvironment: 'jest-environment-jsdom',
reporters: [
'default',
`${kbnDir}/src/dev/jest/junit_reporter.js`,
diff --git a/test/server/wazuh-elastic.js b/test/server/wazuh-elastic.js
index 2143f211c4..ba2da2d854 100644
--- a/test/server/wazuh-elastic.js
+++ b/test/server/wazuh-elastic.js
@@ -1,6 +1,6 @@
const chai = require('chai');
const needle = require('needle');
-const { WAZUH_ALERTS_PATTERN, PLUGIN_PLATFORM_REQUEST_HEADERS } = require('../../common/constants');
+const { PLUGIN_PLATFORM_REQUEST_HEADERS } = require('../../common/constants');
const kibanaServer = process.env.KIBANA_IP || 'localhost';
@@ -15,7 +15,7 @@ describe('wazuh-elastic', () => {
it('GET /elastic/known-fields/{pattern}', async () => {
const res = await needle(
'get',
- `${kibanaServer}:5601/elastic/known-fields/${WAZUH_ALERTS_PATTERN}`,
+ `${kibanaServer}:5601/elastic/known-fields/${getSettingDefaultValue('pattern')}`,
{},
headers
);
@@ -23,7 +23,7 @@ describe('wazuh-elastic', () => {
res.body.output.should.be.a('object');
//res.body.output._index.should.be.eql('.kibana');
res.body.output._type.should.be.eql('doc');
- res.body.output._id.should.be.eql(`index-pattern:${WAZUH_ALERTS_PATTERN}`);
+ res.body.output._id.should.be.eql(`index-pattern:${getSettingDefaultValue('pattern')}`);
});
});
@@ -31,7 +31,7 @@ describe('wazuh-elastic', () => {
it('GET /elastic/visualizations/{tab}/{pattern}', async () => {
const res = await needle(
'get',
- `${kibanaServer}:5601/elastic/visualizations/overview-general/${WAZUH_ALERTS_PATTERN}`,
+ `${kibanaServer}:5601/elastic/visualizations/overview-general/${getSettingDefaultValue('pattern')}`,
{},
headers
);
@@ -46,7 +46,7 @@ describe('wazuh-elastic', () => {
it('POST /elastic/visualizations/{tab}/{pattern}', async () => {
const res = await needle(
'post',
- `${kibanaServer}:5601/elastic/visualizations/cluster-monitoring/${WAZUH_ALERTS_PATTERN}`,
+ `${kibanaServer}:5601/elastic/visualizations/cluster-monitoring/${getSettingDefaultValue('pattern')}`,
{ nodes: { items: [], name: 'node01' } },
headers
);
@@ -63,25 +63,13 @@ describe('wazuh-elastic', () => {
it('GET /elastic/template/{pattern}', async () => {
const res = await needle(
'get',
- `${kibanaServer}:5601/elastic/template/${WAZUH_ALERTS_PATTERN}`,
+ `${kibanaServer}:5601/elastic/template/${getSettingDefaultValue('pattern')}`,
{},
headers
);
res.body.statusCode.should.be.eql(200);
res.body.status.should.be.eql(true);
- res.body.data.should.be.eql(`Template found for ${WAZUH_ALERTS_PATTERN}`);
- });
-
- it('GET /elastic/index-patterns/{pattern}', async () => {
- const res = await needle(
- 'get',
- `${kibanaServer}:5601/elastic/index-patterns/${WAZUH_ALERTS_PATTERN}`,
- {},
- headers
- );
- res.body.statusCode.should.be.eql(200);
- res.body.status.should.be.eql(true);
- res.body.data.should.be.eql('Index pattern found');
+ res.body.data.should.be.eql(`Template found for ${getSettingDefaultValue('pattern')}`);
});
});
});