From 2d860bf1340857a85be64d5e60cab06bdfe98419 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 3 Sep 2025 10:26:32 -0500 Subject: [PATCH 01/54] feat: update core filter system to always u se cluster mode - Always use cluster.name instead of conditional cluster/manager logic - Update PatternDataSourceFilterManager to use cluster mode by default - Simplify last alerts query and service to always use cluster field - Update FilterHandler.managerQuery to default to cluster.name - Modify FIM and MITRE alert filters to use cluster.name consistently - Update compliance table requirement flyout filters --- .../pattern/pattern-data-source-filter-manager.ts | 10 ++++------ .../fim_events_table/lib/get_fim_alerts.ts | 8 +++----- .../components/mitre_top/lib/get_mitre_counts.ts | 8 +++----- .../requirement-flyout/requirement-flyout.tsx | 6 ++---- .../last-alerts-stat/last-alerts-query.ts | 4 ++-- .../last-alerts-stat/last-alerts-service.ts | 9 +++------ plugins/main/public/utils/filter-handler.js | 13 +++++-------- 7 files changed, 22 insertions(+), 36 deletions(-) diff --git a/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts b/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts index 54b7fa2028..4f658f0018 100644 --- a/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts +++ b/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts @@ -256,7 +256,7 @@ export class PatternDataSourceFilterManager } /** - * Return the filter when the cluster or manager are enabled + * Return the filter when the cluster is enabled (always enabled in v5.0+) */ static getClusterManagerFilters( indexPatternId: string, @@ -264,12 +264,10 @@ export class PatternDataSourceFilterManager key?: string, ): tFilter[] { const filterHandler = new FilterHandler(); - const isCluster = AppState.getClusterInfo().status == 'enabled'; + // Cluster mode is always enabled in v5.0+ const managerFilter = filterHandler.managerQuery( - isCluster - ? AppState.getClusterInfo().cluster - : AppState.getClusterInfo().manager, - isCluster, + AppState.getClusterInfo().cluster, + true, key, ); managerFilter.meta = { diff --git a/plugins/main/public/components/common/welcome/components/fim_events_table/lib/get_fim_alerts.ts b/plugins/main/public/components/common/welcome/components/fim_events_table/lib/get_fim_alerts.ts index 51ce74d9aa..7a20c6fdf4 100644 --- a/plugins/main/public/components/common/welcome/components/fim_events_table/lib/get_fim_alerts.ts +++ b/plugins/main/public/components/common/welcome/components/fim_events_table/lib/get_fim_alerts.ts @@ -42,12 +42,10 @@ function createFilters(agentId, indexPattern) { export function getWazuhFilter() { const clusterInfo = AppState.getClusterInfo(); + // Always use cluster.name in v5.0+ (cluster mode by default) const wazuhFilter = { - name: clusterInfo.status === 'enabled' ? 'cluster.name' : 'manager.name', - value: - clusterInfo.status === 'enabled' - ? clusterInfo.cluster - : clusterInfo.manager, + name: 'cluster.name', + value: clusterInfo.cluster, }; return wazuhFilter; } diff --git a/plugins/main/public/components/common/welcome/components/mitre_top/lib/get_mitre_counts.ts b/plugins/main/public/components/common/welcome/components/mitre_top/lib/get_mitre_counts.ts index 7845559059..7a47eb5d1b 100644 --- a/plugins/main/public/components/common/welcome/components/mitre_top/lib/get_mitre_counts.ts +++ b/plugins/main/public/components/common/welcome/components/mitre_top/lib/get_mitre_counts.ts @@ -51,12 +51,10 @@ function createExistsFilter(indexPattern) { function getWazuhFilter() { const clusterInfo = AppState.getClusterInfo(); + // Always use cluster.name in v5.0+ (cluster mode by default) const wazuhFilter = { - name: clusterInfo.status === 'enabled' ? 'cluster.name' : 'manager.name', - value: - clusterInfo.status === 'enabled' - ? clusterInfo.cluster - : clusterInfo.manager, + name: 'cluster.name', + value: clusterInfo.cluster, }; return wazuhFilter; } diff --git a/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx b/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx index 0f579e8d29..f443db6dcb 100644 --- a/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx +++ b/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx @@ -186,10 +186,8 @@ export const RequirementFlyout = connect(mapStateToProps)( renderBody() { const { currentRequirement } = this.props; const requirementImplicitFilter = {}; - const isCluster = (AppState.getClusterInfo() || {}).status === 'enabled'; - const clusterFilter = isCluster - ? { 'cluster.name': AppState.getClusterInfo().cluster } - : { 'manager.name': AppState.getClusterInfo().manager }; + // Always use cluster.name in v5.0+ (cluster mode by default) + const clusterFilter = { 'cluster.name': AppState.getClusterInfo().cluster }; this.clusterFilter = clusterFilter; requirementImplicitFilter[this.props.getRequirementKey()] = currentRequirement; diff --git a/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-query.ts b/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-query.ts index 170a3e6b28..708a02ded4 100644 --- a/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-query.ts +++ b/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-query.ts @@ -1,13 +1,13 @@ export const getLastAlertsQuery = ( currentIndexPattern: string, - isClusterEnabled: boolean, clusterValue: string, ruleLevelRange: { minRuleLevel: number; maxRuleLevel?: number; }, ) => { - const clusterField = isClusterEnabled ? 'cluster.name' : 'manager.name'; + // Always use cluster.name in v5.0+ (cluster mode by default) + const clusterField = 'cluster.name'; return { indexPattern: currentIndexPattern, aggs: { diff --git a/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-service.ts b/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-service.ts index d997c07f50..bae78c4cd3 100644 --- a/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-service.ts +++ b/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-service.ts @@ -24,14 +24,11 @@ export const getLast24HoursAlerts = async ( AppState.getCurrentPattern() || getWazuhCorePlugin().configuration.getSettingValue('pattern'), ); - const isCluster = AppState.getClusterInfo().status == 'enabled'; - const clusterValue = isCluster - ? AppState.getClusterInfo().cluster - : AppState.getClusterInfo().manager; + // Always use cluster name in v5.0+ (cluster mode by default) + const clusterValue = AppState.getClusterInfo().cluster; const lastAlertsQuery = getLastAlertsQuery( currentIndexPattern, - isCluster, clusterValue, ruleLevelRange, ); @@ -41,7 +38,7 @@ export const getLast24HoursAlerts = async ( return { count, cluster: { - field: isCluster ? 'cluster.name' : 'manager.name', + field: 'cluster.name', // Always cluster.name in v5.0+ name: clusterValue, }, indexPatternId: currentIndexPattern.id, diff --git a/plugins/main/public/utils/filter-handler.js b/plugins/main/public/utils/filter-handler.js index e6ffbad168..cb6388378f 100644 --- a/plugins/main/public/utils/filter-handler.js +++ b/plugins/main/public/utils/filter-handler.js @@ -97,18 +97,15 @@ export class FilterHandler { return result; } /** - * This function takes two parameters, the isCluster parameter is a boolean thats defines if it uses cluster.name key or manager.name + * This function creates a filter for cluster/manager queries. In v5.0+ always uses cluster.name (cluster by default) * @param {*} manager - * @param {*} isCluster + * @param {*} isCluster - Always true in v5.0+ (kept for compatibility) * @param {*} fixedKey * @returns */ - managerQuery(manager, isCluster, fixedKey = undefined) { - const metaKey = fixedKey - ? fixedKey - : isCluster - ? 'cluster.name' - : 'manager.name'; + managerQuery(manager, isCluster = true, fixedKey = undefined) { + // Always use cluster.name in v5.0+ (cluster mode by default) + const metaKey = fixedKey ? fixedKey : 'cluster.name'; const result = this.base(); result.meta.key = metaKey; result.meta.value = manager; From 0416ccd72f5b1da448b7963ef15e715ab9cadbec Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 3 Sep 2025 10:26:51 -0500 Subject: [PATCH 02/54] feat: unify API endpoints to always use cluster mode - Remove clusterStatusResponse function from register-agent-services - Update wz-fetch.js functions to use cluster endpoints only - Change /manager/ endpoints to /cluster/local/ for local configuration - Simplify restartNodeSelected, fetchFile, saveConfiguration functions - Update query-config.js to use cluster endpoints consistently - Remove cluster status checks from reload-cluster-manager-callout Related to: wazuh/wazuh-dashboard-plugins#7688 --- .../common/reload-cluster-manager-callout.tsx | 12 +-- .../services/register-agent-services.tsx | 79 +++++-------------- .../configuration/utils/wz-fetch.js | 63 ++++----------- .../public/react-services/query-config.js | 71 +++++++++-------- 4 files changed, 75 insertions(+), 150 deletions(-) diff --git a/plugins/main/public/components/common/reload-cluster-manager-callout.tsx b/plugins/main/public/components/common/reload-cluster-manager-callout.tsx index 9a76dc5a1d..4a619a4358 100644 --- a/plugins/main/public/components/common/reload-cluster-manager-callout.tsx +++ b/plugins/main/public/components/common/reload-cluster-manager-callout.tsx @@ -137,14 +137,10 @@ class WzReloadClusterManagerCallout extends Component< } }; async componentDidMount() { - try { - const clusterStatus = await clusterReq(); - this.setState({ - isCluster: - clusterStatus.data.data.enabled === 'yes' && - clusterStatus.data.data.running === 'yes', - }); - } catch (error) {} + // Always use cluster mode in v5.0+ (cluster mode by default) + this.setState({ + isCluster: true, + }); } render() { const { warningReloading } = this.state; diff --git a/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx b/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx index 19de19808e..5c40fbab09 100644 --- a/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx +++ b/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx @@ -28,30 +28,12 @@ export type ServerAddressOptions = { nodetype: string; }; -/** - * 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; - } -}; +// Removed clusterStatusResponse function - cluster mode is always enabled in v5.0+ /** * Get the remote configuration from api */ -async function getRemoteConfiguration( - nodeName: string, - clusterStatus: boolean, -): Promise { +async function getRemoteConfiguration(nodeName: string): Promise { let config: RemoteConfig = { name: nodeName, isUdp: false, @@ -59,20 +41,12 @@ async function getRemoteConfiguration( }; try { - let result; - if (clusterStatus) { - result = await WzRequest.apiReq( - 'GET', - `/cluster/${nodeName}/configuration/request/remote`, - {}, - ); - } else { - result = await WzRequest.apiReq( - 'GET', - '/manager/configuration/request/remote', - {}, - ); - } + // Always use cluster endpoints in v5.0+ (cluster mode by default) + const result = await WzRequest.apiReq( + 'GET', + `/cluster/${nodeName}/configuration/request/remote`, + {}, + ); const items = result?.data?.data?.affected_items || []; const remote = items[0]?.remote; if (remote) { @@ -105,10 +79,9 @@ async function getRemoteConfiguration( * @param node * @returns */ -async function getAuthConfiguration(node: string, clusterStatus: boolean) { - const authConfigUrl = clusterStatus - ? `/cluster/${node}/configuration/auth/auth` - : '/manager/configuration/auth/auth'; +async function getAuthConfiguration(node: string) { + // Always use cluster endpoints in v5.0+ (cluster mode by default) + const authConfigUrl = `/cluster/${node}/configuration/auth/auth`; const result = await WzRequest.apiReq('GET', authConfigUrl, {}); const auth = result?.data?.data?.affected_items?.[0]; return auth; @@ -139,11 +112,8 @@ async function getConnectionConfig( const nodeIp = nodeSelected?.value; if (!defaultServerAddress) { if (nodeSelected.nodetype !== 'custom') { - const clusterStatus = await clusterStatusResponse(); - const remoteConfig = await getRemoteConfiguration( - nodeName, - clusterStatus, - ); + // Always use cluster mode in v5.0+ (cluster mode by default) + const remoteConfig = await getRemoteConfiguration(nodeName); return { serverAddress: nodeIp, udpProtocol: remoteConfig.isUdp, @@ -220,17 +190,9 @@ export const parseNodesInOptions = ( 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(); - } + // Always use cluster mode in v5.0+ (cluster mode by default) + const nodes = await getNodeIPs(); + return parseNodesInOptions(nodes); }; /** @@ -250,12 +212,9 @@ export const getMasterNode = ( export const getMasterConfiguration = async () => { const nodes = await fetchClusterNodesOptions(); const masterNode = getMasterNode(nodes); - const clusterStatus = await clusterStatusResponse(); - const remote = await getRemoteConfiguration( - masterNode[0].label, - clusterStatus, - ); - const auth = await getAuthConfiguration(masterNode[0].label, clusterStatus); + // Always use cluster mode in v5.0+ (cluster mode by default) + const remote = await getRemoteConfiguration(masterNode[0].label); + const auth = await getAuthConfiguration(masterNode[0].label); return { remote, auth, diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index a695d5eaaf..a76d62f237 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -54,8 +54,8 @@ export const getCurrentConfig = async ( try { const url = node ? `/cluster/${node}/configuration/${component}/${configuration}` - : !node && agentId === '000' - ? `/manager/configuration/${component}/${configuration}` + : agentId === '000' + ? `/cluster/local/configuration/${component}/${configuration}` : `/agents/${agentId}/config/${component}/${configuration}`; const partialResult = await WzRequest.apiReq('GET', url, {}); @@ -264,14 +264,10 @@ export const clusterReq = async () => { */ export const fetchFile = async selectedNode => { try { - const clusterStatus = (((await clusterReq()) || {}).data || {}).data || {}; // TODO: Check, when FIX ISSUE /cluster/status - const isCluster = - clusterStatus.enabled === 'yes' && clusterStatus.running === 'yes'; + // Always use cluster endpoints in v5.0+ (cluster mode by default) const data = await WzRequest.apiReq( 'GET', - isCluster - ? `/cluster/${selectedNode}/configuration` - : `/manager/configuration`, + `/cluster/${selectedNode}/configuration`, { params: { raw: true, @@ -302,15 +298,10 @@ export const restartNodeSelected = async ( updateWazuhNotReadyYet, ) => { try { - const clusterStatus = (((await clusterReq()) || {}).data || {}).data || {}; - const isCluster = - clusterStatus.enabled === 'yes' && clusterStatus.running === 'yes'; - // Dispatch a Redux action - updateWazuhNotReadyYet( - `Restarting ${isCluster ? selectedNode : 'Manager'}, please wait.`, - ); //FIXME: if it enables/disables cluster, this will show Manager instead node name - isCluster ? await restartNode(selectedNode) : await restartManager(); - return await makePing(updateWazuhNotReadyYet, isCluster); + // Always use cluster mode in v5.0+ (cluster mode by default) + updateWazuhNotReadyYet(`Restarting ${selectedNode}, please wait.`); + await restartNode(selectedNode); + return await makePing(updateWazuhNotReadyYet, true); } catch (error) { throw error; } @@ -403,14 +394,8 @@ export const restartNode = async node => { export const saveConfiguration = async (selectedNode, xml) => { try { - const clusterStatus = (((await clusterReq()) || {}).data || {}).data || {}; - const enabledAndRunning = - clusterStatus.enabled === 'yes' && clusterStatus.running === 'yes'; - if (enabledAndRunning) { - await saveFileCluster(xml, selectedNode); - } else { - await saveFileManager(xml); - } + // Always use cluster mode in v5.0+ (cluster mode by default) + await saveFileCluster(xml, selectedNode); } catch (error) { throw error; } @@ -479,28 +464,12 @@ export const saveFileManager = async text => { */ export const validateAfterSent = async (node = false) => { try { - const clusterStatus = await WzRequest.apiReq('GET', `/cluster/status`, {}); - - const clusterData = ((clusterStatus || {}).data || {}).data || {}; - const isCluster = - clusterData.enabled === 'yes' && clusterData.running === 'yes'; - - let validation = false; - if (node && isCluster) { - validation = await WzRequest.apiReq( - 'GET', - `/cluster/configuration/validation`, - {}, - ); - } else { - validation = isCluster - ? await WzRequest.apiReq('GET', `/cluster/configuration/validation`, {}) - : await WzRequest.apiReq( - 'GET', - `/manager/configuration/validation`, - {}, - ); - } + // Always use cluster endpoints in v5.0+ (cluster mode by default) + const validation = await WzRequest.apiReq( + 'GET', + `/cluster/configuration/validation`, + {}, + ); const data = ((validation || {}).data || {}).data || {}; const isOk = data.status === 'OK'; if (!isOk && Array.isArray(data.details)) { diff --git a/plugins/main/public/react-services/query-config.js b/plugins/main/public/react-services/query-config.js index 1dabada31c..04d16979c1 100644 --- a/plugins/main/public/react-services/query-config.js +++ b/plugins/main/public/react-services/query-config.js @@ -30,42 +30,43 @@ export const queryConfig = async (agentId, sections, node = false) => { } const result = {}; - await Promise.all(sections.map(async(section)=> { - const { component, configuration } = section; - if ( - !component || - typeof component !== 'string' || - !configuration || - typeof configuration !== 'string' - ) { - throw new Error('Invalid section'); - } - try { - const url = node - ? `/cluster/${node}/configuration/${component}/${configuration}` - : !node - && agentId === '000' - ? `/manager/configuration/${component}/${configuration}` + await Promise.all( + sections.map(async section => { + const { component, configuration } = section; + if ( + !component || + typeof component !== 'string' || + !configuration || + typeof configuration !== 'string' + ) { + throw new Error('Invalid section'); + } + try { + const url = node + ? `/cluster/${node}/configuration/${component}/${configuration}` + : agentId === '000' + ? `/cluster/local/configuration/${component}/${configuration}` : `/agents/${agentId}/configuration/${component}/${configuration}`; - const partialResult = await WzRequest.apiReq('GET', url, {}); - result[`${component}-${configuration}`] = partialResult.data.data; - } catch (error) { - const options = { - context: `${AppState.name}.queryConfig`, - level: UI_LOGGER_LEVELS.ERROR, - severity: UI_ERROR_SEVERITIES.BUSINESS, - store: true, - display: false, - error: { - error: error, - message: error.message || error, - title: `Fetch Configuration`, - }, - }; - getErrorOrchestrator().handleError(options); - } - })); + const partialResult = await WzRequest.apiReq('GET', url, {}); + result[`${component}-${configuration}`] = partialResult.data.data; + } catch (error) { + const options = { + context: `${AppState.name}.queryConfig`, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + display: false, + error: { + error: error, + message: error.message || error, + title: `Fetch Configuration`, + }, + }; + getErrorOrchestrator().handleError(options); + } + }), + ); return result; } catch (error) { const options = { @@ -83,4 +84,4 @@ export const queryConfig = async (agentId, sections, node = false) => { getErrorOrchestrator().handleError(options); } -} +}; From aab10b89c2e7d8f1ca09a81c8cddc3a5bd219692 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 3 Sep 2025 14:10:21 -0500 Subject: [PATCH 03/54] feat: update UI components to always use cluster mode - Remove cluster-disabled component completely - Update module_configuration to always use cluster nodes - Simplify statistics-overview to always use cluster mode - Update validation functions to use cluster endpoints only - Change logs path from /manager/logs to /cluster/local/logs - Remove cluster status checks from UI components - Update cluster-overview to always show cluster dashboard - Simplify vulnerability module check to use cluster only - Update refresh-cluster-info and edit-configuration components --- .../panel/components/module_configuration.tsx | 25 +-- .../management/cluster/cluster-disabled.js | 55 ------ .../components/check-module-enabled.tsx | 10 +- .../management/cluster/cluster-overview.tsx | 21 +-- .../management/common/valid-configuration.ts | 18 +- .../edit-configuration/edit-configuration.js | 170 +++++++++++------- .../refresh-cluster-info-button.js | 54 +++--- .../groups/utils/valid-configuration.js | 16 +- .../components/management/mg-logs/logs.js | 20 +-- .../statistics/statistics-overview.js | 35 ++-- 10 files changed, 159 insertions(+), 265 deletions(-) delete mode 100644 plugins/main/public/components/management/cluster/cluster-disabled.js diff --git a/plugins/main/public/components/common/modules/panel/components/module_configuration.tsx b/plugins/main/public/components/common/modules/panel/components/module_configuration.tsx index 65bde9575c..7fed8e3807 100644 --- a/plugins/main/public/components/common/modules/panel/components/module_configuration.tsx +++ b/plugins/main/public/components/common/modules/panel/components/module_configuration.tsx @@ -56,23 +56,14 @@ export const PanelModuleConfiguration : FunctionalComponent<{h: string}> = conne const configuration = await getMapConfigurationToState('agent', configurationAPIPartialPath, mapResponseConfiguration, agent); return configuration ? [configuration] : null; }else{ - const custerStatusResponse = await WzRequest.apiReq('GET', '/cluster/status', {}); - if (custerStatusResponse.data.data.enabled === 'yes' && custerStatusResponse.data.data.running === 'yes') { - // Cluster mode - // Get the cluster nodes - const nodesResponse = await WzRequest.apiReq('GET', `/cluster/nodes`, {}); - const nodesConfigurationResponses = await Promise.all( - nodesResponse.data.data.affected_items - .map(async node => await getMapConfigurationToState('cluster_node', configurationAPIPartialPath, mapResponseConfiguration, node) - ) - ); - const nodeConfigurations = nodesConfigurationResponses.filter(nodeConfiguration => nodeConfiguration); - return nodeConfigurations.length ? nodeConfigurations : null; - } else { - // Manager mode - const configuration = await getMapConfigurationToState('manager', configurationAPIPartialPath, mapResponseConfiguration); - return configuration ? [configuration] : null; - }; + const nodesResponse = await WzRequest.apiReq('GET', `/cluster/nodes`, {}); + const nodesConfigurationResponses = await Promise.all( + nodesResponse.data.data.affected_items + .map(async node => await getMapConfigurationToState('cluster_node', configurationAPIPartialPath, mapResponseConfiguration, node) + ) + ); + const nodeConfigurations = nodesConfigurationResponses.filter(nodeConfiguration => nodeConfiguration); + return nodeConfigurations.length ? nodeConfigurations : null; } }catch(error){ const options: UIErrorLog = { diff --git a/plugins/main/public/components/management/cluster/cluster-disabled.js b/plugins/main/public/components/management/cluster/cluster-disabled.js deleted file mode 100644 index e4286598eb..0000000000 --- a/plugins/main/public/components/management/cluster/cluster-disabled.js +++ /dev/null @@ -1,55 +0,0 @@ -import React, { Component, Fragment } from 'react'; -import { EuiLink, EuiEmptyPrompt } from '@elastic/eui'; -import { withErrorBoundary } from '../../common/hocs'; -import { webDocumentationLink } from '../../../../common/services/web_documentation'; -export const ClusterDisabled = withErrorBoundary( - class ClusterDisabled extends Component { - constructor(props) { - super(props); - this.state = {}; - } - - render() { - return ( - - {this.props.error - ? this.props.error.title - : !this.props.enabled - ? 'The cluster is disabled' - : !this.props.running - ? 'The cluster is not running' - : ''} - - } - body={ - - {this.props.error ? ( - this.props.error.message - ) : !this.props.enabled ? ( -

- Visit the documentation on{' '} - - this link - {' '} - to learn about how to enable it. -

- ) : !this.props.running ? ( -

The cluster is enabled but it is not running.

- ) : null} -
- } - /> - ); - } - }, -); diff --git a/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx b/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx index f254dbde95..1572f26635 100644 --- a/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx +++ b/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx @@ -59,16 +59,8 @@ export const ModuleEnabledCheck = () => { const checkVDIsEnabled = async () => { try { - // Check cluster status setData(null); - const clusterStatus = await clusterReq(); - - // Check if the module is enabled - const enabled = - clusterStatus.data.data.enabled === 'yes' && - clusterStatus.data.data.running === 'yes' - ? await checkVDIsEnabledCluster() - : await checkVDIsEnabledManager(); + const enabled = await checkVDIsEnabledCluster(); setData({ enabled }); } catch (error) { const options = { diff --git a/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx b/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx index f74efc79ac..6dda112e69 100644 --- a/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx +++ b/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx @@ -22,15 +22,12 @@ interface ClusterOverviewState { const checkClusterIsEnabledAndRunning = async () => { try { const status: any = await WzRequest.apiReq('GET', '/cluster/status', {}); - const clusterEnabled = status?.data?.data?.enabled; - const isClusterEnabled = clusterEnabled === 'yes'; const statusRunning = status?.data?.data?.running; - const isClusterRunning = statusRunning === 'yes'; return { - ok: !(isClusterEnabled && isClusterRunning), + ok: false, data: { - clusterEnabled, - isClusterRunning, + clusterEnabled: 'yes', + isClusterRunning: true, statusRunning, }, }; @@ -52,13 +49,7 @@ export const ClusterOverview = compose( ]), withGuardAsync( checkClusterIsEnabledAndRunning, - ({ clusterEnabled, isClusterRunning, error }) => ( - - ), + ({ clusterEnabled, isClusterRunning, error }) => null, () => ( { return ( <> - {clusterEnabled && isClusterRunning ? ( - - ) : null} + ); }, diff --git a/plugins/main/public/controllers/management/components/management/common/valid-configuration.ts b/plugins/main/public/controllers/management/components/management/common/valid-configuration.ts index 9ffe4376da..45da9bce16 100644 --- a/plugins/main/public/controllers/management/components/management/common/valid-configuration.ts +++ b/plugins/main/public/controllers/management/components/management/common/valid-configuration.ts @@ -14,27 +14,15 @@ import { WzRequest } from '../../../../../react-services/wz-request'; const validateConfigAfterSent = async (node = false) => { try { - const clusterStatus = await WzRequest.apiReq('GET', `/cluster/status`, {}); - - const clusterData = ((clusterStatus || {}).data || {}).data || {}; - const isCluster = - clusterData.enabled === 'yes' && clusterData.running === 'yes'; - - let validation = false; - if (node && isCluster) { + let validation; + if (node) { validation = await WzRequest.apiReq( 'GET', `/cluster/${node}/configuration/validation`, {} ); } else { - validation = isCluster - ? await WzRequest.apiReq('GET', `/cluster/configuration/validation`, {}) - : await WzRequest.apiReq( - 'GET', - `/manager/configuration/validation`, - {} - ); + validation = await WzRequest.apiReq('GET', `/cluster/configuration/validation`, {}); } const data = ((validation || {}).data || {}).data || {}; const isOk = data.status === 'OK'; diff --git a/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js b/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js index 6bd807fe20..093e1f0527 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js +++ b/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js @@ -76,16 +76,24 @@ class WzEditConfiguration extends Component { try { this.setState({ saving: true }); this.props.clusterNodeSelected - ? await saveFileCluster(this.state.editorValue, this.props.clusterNodeSelected) + ? await saveFileCluster( + this.state.editorValue, + this.props.clusterNodeSelected, + ) : await saveFileManager(this.state.editorValue); - this.setState({ saving: false, infoChangesAfterRestart: true, hasChanges: false }); + this.setState({ + saving: false, + infoChangesAfterRestart: true, + hasChanges: false, + }); this.addToast({ title: ( - +   - {this.props.clusterNodeSelected || 'Manager'} configuration has been updated + {this.props.clusterNodeSelected || 'Manager'} configuration + has been updated ), @@ -106,7 +114,7 @@ class WzEditConfiguration extends Component { error: { error: error, message: errorMessage || error, - title: "Error found saving the file.", + title: 'Error found saving the file.', }, }; getErrorOrchestrator().handleError(options); @@ -151,14 +159,23 @@ class WzEditConfiguration extends Component { componentDidUpdate(prevProps, prevState) { if (prevState.editorValue !== this.state.editorValue) { - this.setState({ hasChanges: this.state.editorValue !== this.state.initialValue }); + this.setState({ + hasChanges: this.state.editorValue !== this.state.initialValue, + }); } } async confirmRestart() { try { - this.setState({ restarting: true, saving: true, infoChangesAfterRestart: false }); - await restartNodeSelected(this.props.clusterNodeSelected, this.props.updateWazuhNotReadyYet); + this.setState({ + restarting: true, + saving: true, + infoChangesAfterRestart: false, + }); + await restartNodeSelected( + this.props.clusterNodeSelected, + this.props.updateWazuhNotReadyYet, + ); this.props.updateWazuhNotReadyYet(''); this.setState({ restart: false, saving: false, restarting: false }); await this.checkIfClusterOrManager(); @@ -166,18 +183,18 @@ class WzEditConfiguration extends Component { this.addToast({ title: ( - +   - Nodes could take some time to restart, it may be necessary to perform a refresh to - see them all. + Nodes could take some time to restart, it may be necessary to + perform a refresh to see them all. ), color: 'success', }); } - if(!this.props.clusterNodeSelected){ + if (!this.props.clusterNodeSelected) { this.addToast({ title: 'Manager was restarted', color: 'success', @@ -202,39 +219,40 @@ class WzEditConfiguration extends Component { async checkIfClusterOrManager() { try { - // in case which enable/disable cluster configuration, update Redux Store - const clusterStatus = await clusterReq(); - if (clusterStatus.data.data.enabled === 'yes' && clusterStatus.data.data.running === 'yes') { - // try if it is a cluster - const nodes = await clusterNodes(); - // set cluster nodes in Redux Store - this.props.updateClusterNodes(nodes.data.data.affected_items); - // set cluster node selected in Redux Store - const existsClusterCurrentNodeSelected = nodes.data.data.affected_items.find( - (node) => node.name === this.props.clusterNodeSelected - ); - this.props.updateClusterNodeSelected( - existsClusterCurrentNodeSelected - ? existsClusterCurrentNodeSelected.name - : nodes.data.data.affected_items.find((node) => node.type === 'master').name + const nodes = await clusterNodes(); + this.props.updateClusterNodes(nodes.data.data.affected_items); + const existsClusterCurrentNodeSelected = + nodes.data.data.affected_items.find( + node => node.name === this.props.clusterNodeSelected, ); - this.props.updateConfigurationSection('edit-configuration', 'Cluster configuration'); - } else { - // do nothing if it isn't a cluster - this.props.updateClusterNodes(false); - this.props.updateClusterNodeSelected(false); - this.props.updateConfigurationSection('edit-configuration', 'Manager configuration'); - } + this.props.updateClusterNodeSelected( + existsClusterCurrentNodeSelected + ? existsClusterCurrentNodeSelected.name + : nodes.data.data.affected_items.find(node => node.type === 'master') + .name, + ); + this.props.updateConfigurationSection( + 'edit-configuration', + 'Cluster configuration', + ); } catch (error) { - // do nothing if it isn't a cluster this.props.updateClusterNodes(false); this.props.updateClusterNodeSelected(false); - this.props.updateConfigurationSection('edit-configuration', 'Manager configuration'); + this.props.updateConfigurationSection( + 'edit-configuration', + 'Cluster configuration', + ); throw error; } } render() { - const { restart, restarting, saving, editorValue, disableSaveRestartButtons } = this.state; + const { + restart, + restarting, + saving, + editorValue, + disableSaveRestartButtons, + } = this.state; const { clusterNodeSelected, agent } = this.props; const xmlError = editorValue && validateXML(editorValue); return ( @@ -249,7 +267,7 @@ class WzEditConfiguration extends Component { {xmlError ? ( - + XML format error ) : ( @@ -263,7 +281,7 @@ class WzEditConfiguration extends Component { : { action: 'manager:update_config', resource: '*:*:*' }, ]} isDisabled={saving || disableSaveRestartButtons} - iconType="save" + iconType='save' onClick={() => this.editorSave()} > Save @@ -281,21 +299,24 @@ class WzEditConfiguration extends Component { : { action: 'manager:restart', resource: '*:*:*' }, ]} fill - iconType="refresh" + iconType='refresh' onClick={() => this.toggleRestart()} isDisabled={disableSaveRestartButtons || restarting} isLoading={restarting} > - {restarting ? 'Restarting' : 'Restart'} {clusterNodeSelected || 'Manager'} + {restarting ? 'Restarting' : 'Restart'}{' '} + {clusterNodeSelected || 'Manager'} this.onChange(value)} - onDidMount={(xmlFetched, errorXMLFetched) => this.onDidMount(xmlFetched, errorXMLFetched)} + onChange={value => this.onChange(value)} + onDidMount={(xmlFetched, errorXMLFetched) => + this.onDidMount(xmlFetched, errorXMLFetched) + } toggleRestart={() => this.toggleRestart()} confirmRestart={() => this.confirmRestart()} - onLoadingConfiguration={(value) => this.onLoadingConfiguration(value)} + onLoadingConfiguration={value => this.onLoadingConfiguration(value)} {...this.state} agent={agent} xmlError={xmlError} @@ -306,9 +327,9 @@ class WzEditConfiguration extends Component { title={`${clusterNodeSelected || 'Manager'} will be restarted`} onCancel={() => this.toggleRestart()} onConfirm={() => this.confirmRestart()} - cancelButtonText="Cancel" - confirmButtonText="Confirm" - defaultFocusedButton="cancel" + cancelButtonText='Cancel' + confirmButtonText='Confirm' + defaultFocusedButton='cancel' /> )} @@ -317,17 +338,18 @@ class WzEditConfiguration extends Component { } } -const mapStateToProps = (state) => ({ +const mapStateToProps = state => ({ wazuhNotReadyYet: state.appStateReducers.wazuhNotReadyYet, clusterNodes: state.configurationReducers.clusterNodes, clusterNodeSelected: state.configurationReducers.clusterNodeSelected, }); -const mapDispatchToProps = (dispatch) => ({ - updateClusterNodes: (clusterNodes) => dispatch(updateClusterNodes(clusterNodes)), - updateClusterNodeSelected: (clusterNodeSelected) => +const mapDispatchToProps = dispatch => ({ + updateClusterNodes: clusterNodes => + dispatch(updateClusterNodes(clusterNodes)), + updateClusterNodeSelected: clusterNodeSelected => dispatch(updateClusterNodeSelected(clusterNodeSelected)), - updateWazuhNotReadyYet: (value) => dispatch(updateWazuhNotReadyYet(value)), + updateWazuhNotReadyYet: value => dispatch(updateWazuhNotReadyYet(value)), }); WzEditConfiguration.propTypes = { @@ -335,9 +357,12 @@ WzEditConfiguration.propTypes = { updateWazuhNotReadyYet: PropTypes.func, }; -export default connect(mapStateToProps, mapDispatchToProps)(WzEditConfiguration); +export default connect( + mapStateToProps, + mapDispatchToProps, +)(WzEditConfiguration); -const mapStateToPropsEditor = (state) => ({ +const mapStateToPropsEditor = state => ({ clusterNodeSelected: state.configurationReducers.clusterNodeSelected, clusterNodes: state.configurationReducers.clusterNodes, refreshTime: state.configurationReducers.refreshTime, @@ -347,7 +372,7 @@ const mapStateToPropsEditor = (state) => ({ const WzEditorConfiguration = compose( connect(mapStateToPropsEditor), withLoading( - async (props) => { + async props => { try { props.onLoadingConfiguration(true); const xmlFetched = await fetchFile(props.clusterNodeSelected); @@ -363,8 +388,8 @@ const WzEditorConfiguration = compose( props.clusterNodeSelected && prevProps.clusterNodeSelected && props.clusterNodeSelected !== prevProps.clusterNodeSelected) || - props.refreshTime !== prevProps.refreshTime - ) + props.refreshTime !== prevProps.refreshTime, + ), )( // eslint-disable-next-line react/no-multi-comp class WzEditorConfiguration extends Component { @@ -386,7 +411,9 @@ const WzEditorConfiguration = compose( } = this.props; const existsClusterCurrentNodeSelected = this.props.clusterNodes && - this.props.clusterNodes.find((node) => node.name === this.props.clusterNodeSelected); + this.props.clusterNodes.find( + node => node.name === this.props.clusterNodeSelected, + ); return ( {!this.props.errorXMLFetched ? ( @@ -394,10 +421,15 @@ const WzEditorConfiguration = compose( Edit ossec.conf of{' '} - {(existsClusterCurrentNodeSelected && clusterNodeSelected) || 'Manager'} - {existsClusterCurrentNodeSelected && clusterNodeSelected && clusterNodes + {(existsClusterCurrentNodeSelected && clusterNodeSelected) || + 'Manager'} + {existsClusterCurrentNodeSelected && + clusterNodeSelected && + clusterNodes ? ' (' + - clusterNodes.find((node) => node.name === clusterNodeSelected).type + + clusterNodes.find( + node => node.name === clusterNodeSelected, + ).type + ')' : ''} @@ -405,17 +437,19 @@ const WzEditorConfiguration = compose( {infoChangesAfterRestart && ( )} - + {typeof editorValue === 'string' && ( onChange(value)} - minusHeight={wazuhNotReadyYet || infoChangesAfterRestart ? 320 : 270} + onChange={value => onChange(value)} + minusHeight={ + wazuhNotReadyYet || infoChangesAfterRestart ? 320 : 270 + } /> )} @@ -425,5 +459,5 @@ const WzEditorConfiguration = compose( ); } - } + }, ); diff --git a/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js b/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js index 10b925db1e..bf9f8aca21 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js +++ b/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js @@ -19,7 +19,7 @@ import { connect } from 'react-redux'; import { updateClusterNodes, updateClusterNodeSelected, - updateRefreshTime + updateRefreshTime, } from '../../../../../../redux/actions/configurationActions'; import { clusterNodes, clusterReq } from '../utils/wz-fetch'; import { UI_LOGGER_LEVELS } from '../../../../../../../common/constants'; @@ -30,33 +30,24 @@ class WzRefreshClusterInfoButton extends Component { constructor(props) { super(props); this.state = { - isLoading: false - } + isLoading: false, + }; } async checkIfClusterOrManager() { try { - this.setState({isLoading: true}); - // in case which enable/disable cluster configuration, update Redux Store - const cluster = await clusterReq(); - if(cluster.data.data.enabled === 'yes' && cluster.data.data.running === 'yes'){ - // try if it is a cluster - const nodes = await clusterNodes(); - // set cluster nodes in Redux Store - this.props.updateClusterNodes(nodes.data.data.affected_items); - // set cluster node selected in Redux Store - const existsClusterCurrentNodeSelected = nodes.data.data.affected_items.find( - node => node.name === this.props.clusterNodeSelected - ); - this.props.updateClusterNodeSelected( - existsClusterCurrentNodeSelected - ? existsClusterCurrentNodeSelected.name - : nodes.data.data.affected_items.find(node => node.type === 'master').name + this.setState({ isLoading: true }); + const nodes = await clusterNodes(); + this.props.updateClusterNodes(nodes.data.data.affected_items); + const existsClusterCurrentNodeSelected = + nodes.data.data.affected_items.find( + node => node.name === this.props.clusterNodeSelected, ); - }else{ - // do nothing if it isn't a cluster - this.props.updateClusterNodes(false); - this.props.updateClusterNodeSelected(false); - } + this.props.updateClusterNodeSelected( + existsClusterCurrentNodeSelected + ? existsClusterCurrentNodeSelected.name + : nodes.data.data.affected_items.find(node => node.type === 'master') + .name, + ); } catch (error) { // do nothing if it isn't a cluster this.props.updateClusterNodes(false); @@ -67,19 +58,19 @@ class WzRefreshClusterInfoButton extends Component { severity: UI_ERROR_SEVERITIES.BUSINESS, error: { error: error, - message: error.message || error, - title: error.name || error + message: error.message || error, + title: error.name || error, }, }; getErrorOrchestrator().handleError(options); } - this.setState({isLoading: false}); + this.setState({ isLoading: false }); this.props.updateRefreshTime(); } render() { return ( this.checkIfClusterOrManager()} isDisabled={this.state.isLoading} @@ -91,7 +82,7 @@ class WzRefreshClusterInfoButton extends Component { } const mapStateToProps = state => ({ - clusterNodeSelected: state.configurationReducers.clusterNodeSelected + clusterNodeSelected: state.configurationReducers.clusterNodeSelected, }); const mapDispatchToProps = dispatch => ({ @@ -99,11 +90,10 @@ const mapDispatchToProps = dispatch => ({ dispatch(updateClusterNodes(clusterNodes)), updateClusterNodeSelected: clusterNodeSelected => dispatch(updateClusterNodeSelected(clusterNodeSelected)), - updateRefreshTime: () => - dispatch(updateRefreshTime()) + updateRefreshTime: () => dispatch(updateRefreshTime()), }); export default connect( mapStateToProps, - mapDispatchToProps + mapDispatchToProps, )(WzRefreshClusterInfoButton); diff --git a/plugins/main/public/controllers/management/components/management/groups/utils/valid-configuration.js b/plugins/main/public/controllers/management/components/management/groups/utils/valid-configuration.js index c8efbee27f..bd16325c93 100644 --- a/plugins/main/public/controllers/management/components/management/groups/utils/valid-configuration.js +++ b/plugins/main/public/controllers/management/components/management/groups/utils/valid-configuration.js @@ -14,27 +14,15 @@ import { WzRequest } from '../../../../../../react-services/wz-request'; const validateConfigAfterSent = async (node = false) => { try { - const clusterStatus = await WzRequest.apiReq('GET', `/cluster/status`, {}); - - const clusterData = ((clusterStatus || {}).data || {}).data || {}; - const isCluster = - clusterData.enabled === 'yes' && clusterData.running === 'yes'; - let validation = false; - if (node && isCluster) { + if (node) { validation = await WzRequest.apiReq( 'GET', `/cluster/${node}/configuration/validation`, {} ); } else { - validation = isCluster - ? await WzRequest.apiReq('GET', `/cluster/configuration/validation`, {}) - : await WzRequest.apiReq( - 'GET', - `/manager/configuration/validation`, - {} - ); + validation = await WzRequest.apiReq('GET', `/cluster/configuration/validation`, {}); } const data = ((validation || {}).data || {}).data || {}; const isOk = data.status === 'OK'; diff --git a/plugins/main/public/controllers/management/components/management/mg-logs/logs.js b/plugins/main/public/controllers/management/components/management/mg-logs/logs.js index a0ceef21cf..428b38530b 100644 --- a/plugins/main/public/controllers/management/components/management/mg-logs/logs.js +++ b/plugins/main/public/controllers/management/components/management/mg-logs/logs.js @@ -227,21 +227,11 @@ export default compose( */ async getLogsPath() { try { - const clusterStatus = await WzRequest.apiReq( + let nodeList = ''; + let selectedNode = ''; + const nodeListTmp = await WzRequest.apiReq( 'GET', - '/cluster/status', - {}, - ); - const clusterEnabled = - clusterStatus?.data?.data?.running === 'yes' && - clusterStatus?.data?.data?.enabled === 'yes'; - - if (clusterEnabled) { - let nodeList = ''; - let selectedNode = ''; - const nodeListTmp = await WzRequest.apiReq( - 'GET', - '/cluster/nodes', + '/cluster/nodes', {}, ); if (Array.isArray(nodeListTmp?.data?.data?.affected_items)) { @@ -257,7 +247,7 @@ export default compose( }; } - return { nodeList: '', logsPath: '/manager/logs', selectedNode: '' }; + return { nodeList: '', logsPath: '/cluster/local/logs', selectedNode: '' }; } catch (error) { throw new Error('Error building logs path: ' + error); } diff --git a/plugins/main/public/controllers/management/components/management/statistics/statistics-overview.js b/plugins/main/public/controllers/management/components/management/statistics/statistics-overview.js index ab865256dd..2f5a7bcbd3 100644 --- a/plugins/main/public/controllers/management/components/management/statistics/statistics-overview.js +++ b/plugins/main/public/controllers/management/components/management/statistics/statistics-overview.js @@ -78,32 +78,19 @@ export class WzStatisticsOverview extends Component { async componentDidMount() { this._isMounted = true; try { - // try if it is a cluster - const clusterStatus = await clusterReq(); - const isClusterMode = - clusterStatus.data.data.enabled === 'yes' && - clusterStatus.data.data.running === 'yes'; - if (isClusterMode) { - const data = await clusterNodes(); - const nodes = data.data.data.affected_items.map(item => { - return { value: item.name, text: `${item.name} (${item.type})` }; - }); - nodes.unshift({ value: 'all', text: 'All' }); - this.setState({ - isClusterMode, - clusterNodes: nodes, - clusterNodeSelected: nodes[0].value, - }); - } else { - this.setState({ - isClusterMode, - clusterNodes: [], - clusterNodeSelected: 'all', - }); - } + const data = await clusterNodes(); + const nodes = data.data.data.affected_items.map(item => { + return { value: item.name, text: `${item.name} (${item.type})` }; + }); + nodes.unshift({ value: 'all', text: 'All' }); + this.setState({ + isClusterMode: true, + clusterNodes: nodes, + clusterNodeSelected: nodes[0].value, + }); } catch (error) { this.setState({ - isClusterMode: undefined, + isClusterMode: true, clusterNodes: [], clusterNodeSelected: 'all', }); From 97caa20d1a1c279a3ac2ce0f6c61ced46b304760 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 3 Sep 2025 14:11:44 -0500 Subject: [PATCH 04/54] refactor: format API request calls in validation functions - Standardize the formatting of API request calls in valid-configuration.ts and valid-configuration.js to improve readability and maintainability. - Ensure consistent use of line breaks and indentation for better code clarity. --- .../components/management/common/valid-configuration.ts | 8 ++++++-- .../management/groups/utils/valid-configuration.js | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/common/valid-configuration.ts b/plugins/main/public/controllers/management/components/management/common/valid-configuration.ts index 45da9bce16..0b091d448d 100644 --- a/plugins/main/public/controllers/management/components/management/common/valid-configuration.ts +++ b/plugins/main/public/controllers/management/components/management/common/valid-configuration.ts @@ -19,10 +19,14 @@ const validateConfigAfterSent = async (node = false) => { validation = await WzRequest.apiReq( 'GET', `/cluster/${node}/configuration/validation`, - {} + {}, ); } else { - validation = await WzRequest.apiReq('GET', `/cluster/configuration/validation`, {}); + validation = await WzRequest.apiReq( + 'GET', + `/cluster/configuration/validation`, + {}, + ); } const data = ((validation || {}).data || {}).data || {}; const isOk = data.status === 'OK'; diff --git a/plugins/main/public/controllers/management/components/management/groups/utils/valid-configuration.js b/plugins/main/public/controllers/management/components/management/groups/utils/valid-configuration.js index bd16325c93..1156e655f3 100644 --- a/plugins/main/public/controllers/management/components/management/groups/utils/valid-configuration.js +++ b/plugins/main/public/controllers/management/components/management/groups/utils/valid-configuration.js @@ -19,10 +19,14 @@ const validateConfigAfterSent = async (node = false) => { validation = await WzRequest.apiReq( 'GET', `/cluster/${node}/configuration/validation`, - {} + {}, ); } else { - validation = await WzRequest.apiReq('GET', `/cluster/configuration/validation`, {}); + validation = await WzRequest.apiReq( + 'GET', + `/cluster/configuration/validation`, + {}, + ); } const data = ((validation || {}).data || {}).data || {}; const isOk = data.status === 'OK'; From 5c88829bc7daae31eaa6cdcb52792df9bd72b295 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 3 Sep 2025 14:19:42 -0500 Subject: [PATCH 05/54] refactor: simplify cluster status checks in Wazuh API controller - Remove unnecessary conditional checks for cluster status in the WazuhApiCtrl class. --- plugins/main/server/controllers/wazuh-api.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 710a4afd0a..8a6db7bfd1 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -439,17 +439,12 @@ export class WazuhApiCtrl { ((((response || {}).data || {}).data || {}).affected_items || [])[0] || {}; - const isCluster = - ((api || {}).cluster_info || {}).status === 'enabled' && - typeof daemons['wazuh-clusterd'] !== 'undefined'; const wazuhdbExists = typeof daemons['wazuh-db'] !== 'undefined'; const execd = daemons['wazuh-execd'] === 'running'; const modulesd = daemons['wazuh-modulesd'] === 'running'; const wazuhdb = wazuhdbExists ? daemons['wazuh-db'] === 'running' : true; - const clusterd = isCluster - ? daemons['wazuh-clusterd'] === 'running' - : true; + const clusterd = daemons['wazuh-clusterd'] === 'running'; const isValid = execd && modulesd && wazuhdb && clusterd; From 0fadf79604081341a82aabdbc57d4240c9b8a831 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 3 Sep 2025 14:54:18 -0500 Subject: [PATCH 06/54] update: changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5806e0117b..db5eeb77f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to the Wazuh app project will be documented in this file. ### Changed +- Cluster mode is now enabled by default. Removed all conditional logic between cluster and manager modes. All Wazuh installations now operate in cluster mode, including single-node deployments. Updated all filters to use cluster.name, unified API endpoints to cluster paths, simplified UI components, and removed cluster-disabled component [#7688](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7688) - Rework SCA modules visualizations, global detail for all agents without pinning, replaced `/sca` endpoint with `wazuh-states-sca-*` index pattern, added sample data section [#7578](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7578) - Split the FIM registry inventory into 2 index patterns and change some fields in the FIM files and registries sample data [#7604](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7604) From dc78860700ef7f0baa9086c5f4678f394bd4d312 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 3 Sep 2025 14:59:28 -0500 Subject: [PATCH 07/54] refactor: improve readability of logs.js by standardizing API request formatting - Simplified the structure of the API request call to fetch cluster nodes. - Enhanced the formatting of the return object for clarity and consistency. --- .../components/management/mg-logs/logs.js | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/mg-logs/logs.js b/plugins/main/public/controllers/management/components/management/mg-logs/logs.js index 428b38530b..6f7b08bf4f 100644 --- a/plugins/main/public/controllers/management/components/management/mg-logs/logs.js +++ b/plugins/main/public/controllers/management/components/management/mg-logs/logs.js @@ -229,17 +229,12 @@ export default compose( try { let nodeList = ''; let selectedNode = ''; - const nodeListTmp = await WzRequest.apiReq( - 'GET', - '/cluster/nodes', - {}, - ); - if (Array.isArray(nodeListTmp?.data?.data?.affected_items)) { - nodeList = nodeListTmp.data.data.affected_items; - selectedNode = nodeListTmp.data.data.affected_items.filter( - item => item.type === 'master', - )[0].name; - } + const nodeListTmp = await WzRequest.apiReq('GET', '/cluster/nodes', {}); + if (Array.isArray(nodeListTmp?.data?.data?.affected_items)) { + nodeList = nodeListTmp.data.data.affected_items; + selectedNode = nodeListTmp.data.data.affected_items.filter( + item => item.type === 'master', + )[0].name; return { nodeList, logsPath: `/cluster/${selectedNode}/logs`, @@ -247,7 +242,11 @@ export default compose( }; } - return { nodeList: '', logsPath: '/cluster/local/logs', selectedNode: '' }; + return { + nodeList: '', + logsPath: '/cluster/local/logs', + selectedNode: '', + }; } catch (error) { throw new Error('Error building logs path: ' + error); } From e693ee6f7483da7c71d560236d4bfeb3f9ab3165 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 3 Sep 2025 15:02:08 -0500 Subject: [PATCH 08/54] feat: update remaining cluster conditional logic for cluster by default - Remove cluster/manager conditional in sample data generation - Always use cluster mode panels in analysis engine dashboard - Eliminate 'Disabled' cluster name checks in sample data Related to: wazuh/wazuh-dashboard-plugins#7688 --- .../components/add-modules-data/sample-data.tsx | 14 ++++---------- .../dashboards/dashboard_panels_analysis_engine.ts | 2 +- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/plugins/main/public/components/add-modules-data/sample-data.tsx b/plugins/main/public/components/add-modules-data/sample-data.tsx index 501c74c2bd..59afda8dec 100644 --- a/plugins/main/public/components/add-modules-data/sample-data.tsx +++ b/plugins/main/public/components/add-modules-data/sample-data.tsx @@ -169,23 +169,17 @@ export default class WzSampleData extends Component { ), ); - // Get information about cluster/manager + // Get information about cluster const clusterName = AppState.getClusterInfo().cluster; - const managerName = AppState.getClusterInfo().manager; // eslint-disable-next-line camelcase this.generateAlertsParams.api_id = JSON.parse( AppState.getCurrentAPI() || '{}', )?.id; - this.generateAlertsParams.manager = { - name: managerName, + this.generateAlertsParams.cluster = { + name: clusterName, + node: clusterName, }; - if (clusterName && clusterName !== 'Disabled') { - this.generateAlertsParams.cluster = { - name: clusterName, - node: clusterName, - }; - } } catch (error) { const options = { context: `${WzSampleData.name}.componentDidMount`, diff --git a/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboard_panels_analysis_engine.ts b/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboard_panels_analysis_engine.ts index 57df19e7cc..b4b670bf39 100644 --- a/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboard_panels_analysis_engine.ts +++ b/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboard_panels_analysis_engine.ts @@ -2674,5 +2674,5 @@ export const getDashboardPanelsAnalysisEngine = ( }, }; - return isClusterMode ? clusterModePanels : panels; + return clusterModePanels; }; From 70cd67dcc21e89ef888c73e9b7ef6d3ab9207802 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Thu, 4 Sep 2025 08:37:26 -0500 Subject: [PATCH 09/54] refactor: standardize API endpoint usage across configuration and logs - Simplified API request logic in valid-configuration.ts to improve readability. - Updated wz-fetch.js and query-config.js to consistently use /manager endpoints for configuration requests. - Changed logs path in logs.js from /cluster/local/logs to /manager/logs for uniformity. --- .../management/common/valid-configuration.ts | 18 ++++-------------- .../management/configuration/utils/wz-fetch.js | 2 +- .../components/management/mg-logs/logs.js | 2 +- .../main/public/react-services/query-config.js | 2 +- 4 files changed, 7 insertions(+), 17 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/common/valid-configuration.ts b/plugins/main/public/controllers/management/components/management/common/valid-configuration.ts index 0b091d448d..52e973cbdb 100644 --- a/plugins/main/public/controllers/management/components/management/common/valid-configuration.ts +++ b/plugins/main/public/controllers/management/components/management/common/valid-configuration.ts @@ -14,20 +14,10 @@ import { WzRequest } from '../../../../../react-services/wz-request'; const validateConfigAfterSent = async (node = false) => { try { - let validation; - if (node) { - validation = await WzRequest.apiReq( - 'GET', - `/cluster/${node}/configuration/validation`, - {}, - ); - } else { - validation = await WzRequest.apiReq( - 'GET', - `/cluster/configuration/validation`, - {}, - ); - } + const endpoint = node + ? `/cluster/${node}/configuration/validation` + : '/cluster/configuration/validation'; + const validation = await WzRequest.apiReq('GET', endpoint, {}); const data = ((validation || {}).data || {}).data || {}; const isOk = data.status === 'OK'; if (!isOk && Array.isArray(data.details)) { diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index a76d62f237..e97185923b 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -55,7 +55,7 @@ export const getCurrentConfig = async ( const url = node ? `/cluster/${node}/configuration/${component}/${configuration}` : agentId === '000' - ? `/cluster/local/configuration/${component}/${configuration}` + ? `/manager/configuration/${component}/${configuration}` : `/agents/${agentId}/config/${component}/${configuration}`; const partialResult = await WzRequest.apiReq('GET', url, {}); diff --git a/plugins/main/public/controllers/management/components/management/mg-logs/logs.js b/plugins/main/public/controllers/management/components/management/mg-logs/logs.js index 6f7b08bf4f..96c879a54e 100644 --- a/plugins/main/public/controllers/management/components/management/mg-logs/logs.js +++ b/plugins/main/public/controllers/management/components/management/mg-logs/logs.js @@ -244,7 +244,7 @@ export default compose( return { nodeList: '', - logsPath: '/cluster/local/logs', + logsPath: '/manager/logs', selectedNode: '', }; } catch (error) { diff --git a/plugins/main/public/react-services/query-config.js b/plugins/main/public/react-services/query-config.js index 04d16979c1..b9315f9e4b 100644 --- a/plugins/main/public/react-services/query-config.js +++ b/plugins/main/public/react-services/query-config.js @@ -45,7 +45,7 @@ export const queryConfig = async (agentId, sections, node = false) => { const url = node ? `/cluster/${node}/configuration/${component}/${configuration}` : agentId === '000' - ? `/cluster/local/configuration/${component}/${configuration}` + ? `/manager/configuration/${component}/${configuration}` : `/agents/${agentId}/configuration/${component}/${configuration}`; const partialResult = await WzRequest.apiReq('GET', url, {}); From d082365277a0381855288834d2428b18c64f1e02 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Thu, 4 Sep 2025 09:10:33 -0500 Subject: [PATCH 10/54] refactor: streamline validation endpoint logic in wz-fetch.js - Updated the validateAfterSent function to dynamically construct the API endpoint based on the node parameter. - Simplified the API request call for validation to enhance code clarity and maintainability. --- .../management/configuration/utils/wz-fetch.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index e97185923b..2f75faf3c4 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -464,12 +464,10 @@ export const saveFileManager = async text => { */ export const validateAfterSent = async (node = false) => { try { - // Always use cluster endpoints in v5.0+ (cluster mode by default) - const validation = await WzRequest.apiReq( - 'GET', - `/cluster/configuration/validation`, - {}, - ); + const endpoint = node + ? `/cluster/${node}/configuration/validation` + : `/cluster/configuration/validation`; + const validation = await WzRequest.apiReq('GET', endpoint, {}); const data = ((validation || {}).data || {}).data || {}; const isOk = data.status === 'OK'; if (!isOk && Array.isArray(data.details)) { From bb88b2d3a0da966123372792f1410bb904196894 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Thu, 4 Sep 2025 13:44:10 -0500 Subject: [PATCH 11/54] refactor: enhance cluster status handling and API request formatting - Renamed checkClusterIsEnabledAndRunning to getClusterStatus for clarity. - Updated loading message in ClusterOverview component to reflect loading state. - Removed unused clusterReq import in configuration-switch.js and statistics-overview.js. - Streamlined API request formatting in status-handler.js for improved readability. - Simplified cluster information update logic in WzConfigurationSwitch component. --- .../management/cluster/cluster-overview.tsx | 8 +++---- .../configuration/configuration-switch.js | 17 +++---------- .../refresh-cluster-info-button.js | 2 +- .../statistics/statistics-overview.js | 2 +- .../management/status/utils/status-handler.js | 24 +++++++++---------- 5 files changed, 21 insertions(+), 32 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx b/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx index 6dda112e69..3dedb1dfe8 100644 --- a/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx +++ b/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx @@ -19,7 +19,7 @@ interface ClusterOverviewState { statusRunning: string; } -const checkClusterIsEnabledAndRunning = async () => { +const getClusterStatus = async () => { try { const status: any = await WzRequest.apiReq('GET', '/cluster/status', {}); const statusRunning = status?.data?.data?.running; @@ -48,14 +48,14 @@ export const ClusterOverview = compose( { action: 'cluster:status', resource: '*:*:*' }, ]), withGuardAsync( - checkClusterIsEnabledAndRunning, + getClusterStatus, ({ clusterEnabled, isClusterRunning, error }) => null, () => ( } /> diff --git a/plugins/main/public/controllers/management/components/management/configuration/configuration-switch.js b/plugins/main/public/controllers/management/components/management/configuration/configuration-switch.js index 6a12516aa7..4110d3fed2 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/configuration-switch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/configuration-switch.js @@ -49,7 +49,6 @@ import { withUserAuthorizationPrompt } from '../../../../../components/common/ho import { clusterNodes as requestClusterNodes, - clusterReq, agentIsSynchronized, } from './utils/wz-fetch'; import { @@ -152,20 +151,10 @@ class WzConfigurationSwitch extends Component { updateClusterInformation = async (/** @type {string} */ context) => { try { - // try if it is a cluster - const clusterStatus = await clusterReq(); - const isCluster = - clusterStatus.data.data.enabled === 'yes' && - clusterStatus.data.data.running === 'yes'; - - if (isCluster) { - await this.handleClusterNodes(); - } else { - // do nothing if it isn't a cluster - this.resetClusterState(); - } + // Always cluster in v5.0+ (cluster by default) + await this.handleClusterNodes(); } catch (error) { - // do nothing if it isn't a cluster + // Handle cluster errors this.resetClusterState(); this.catchError(error, context); } diff --git a/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js b/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js index bf9f8aca21..bd82f8de56 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js +++ b/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js @@ -21,7 +21,7 @@ import { updateClusterNodeSelected, updateRefreshTime, } from '../../../../../../redux/actions/configurationActions'; -import { clusterNodes, clusterReq } from '../utils/wz-fetch'; +import { clusterNodes } from '../utils/wz-fetch'; import { UI_LOGGER_LEVELS } from '../../../../../../../common/constants'; import { UI_ERROR_SEVERITIES } from '../../../../../../react-services/error-orchestrator/types'; import { getErrorOrchestrator } from '../../../../../../react-services/common-services'; diff --git a/plugins/main/public/controllers/management/components/management/statistics/statistics-overview.js b/plugins/main/public/controllers/management/components/management/statistics/statistics-overview.js index 2f5a7bcbd3..b9c9438e11 100644 --- a/plugins/main/public/controllers/management/components/management/statistics/statistics-overview.js +++ b/plugins/main/public/controllers/management/components/management/statistics/statistics-overview.js @@ -24,7 +24,7 @@ import { EuiSpacer, EuiProgress, } from '@elastic/eui'; -import { clusterReq, clusterNodes } from '../configuration/utils/wz-fetch'; +import { clusterNodes } from '../configuration/utils/wz-fetch'; import { compose } from 'redux'; import { withGlobalBreadcrumb, diff --git a/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js b/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js index 3b9344690f..2e25762124 100644 --- a/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js +++ b/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js @@ -18,7 +18,11 @@ export default class StatusHandler { */ static async agentsSummary() { try { - const result = await WzRequest.apiReq('GET', `/agents/summary/status`, {}); + const result = await WzRequest.apiReq( + 'GET', + `/agents/summary/status`, + {}, + ); return result; } catch (error) { throw error; @@ -57,7 +61,7 @@ export default class StatusHandler { const result = await WzRequest.apiReq( 'GET', `/cluster/${nodeId}/status`, - {} + {}, ); return result; } catch (error) { @@ -73,7 +77,7 @@ export default class StatusHandler { const result = await WzRequest.apiReq( 'GET', `/cluster/${nodeId}/info`, - {} + {}, ); return result; } catch (error) { @@ -86,11 +90,7 @@ export default class StatusHandler { */ static async clusterAgentsCount() { try { - const result = await WzRequest.apiReq( - 'GET', - `/overview/agents`, - {} - ); + const result = await WzRequest.apiReq('GET', `/overview/agents`, {}); return result; } catch (error) { throw error; @@ -130,8 +130,8 @@ export default class StatusHandler { params: { limit: 1, sort: '-dateAdd', - q: 'id!=000' - } + q: 'id!=000', + }, }); return result; } catch (error) { @@ -147,7 +147,7 @@ export default class StatusHandler { const validationError = await WzRequest.apiReq( 'GET', `/cluster/configuration/validation`, - {} + {}, ); const data = ((validationError || {}).data || {}).data || {}; @@ -171,7 +171,7 @@ export default class StatusHandler { const validationError = await WzRequest.apiReq( 'GET', `/manager/configuration/validation`, - {} + {}, ); const data = ((validationError || {}).data || {}).data || {}; From 1bade48ae1cdd035a14988e5f4ecaaf130646cd0 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Thu, 4 Sep 2025 13:54:40 -0500 Subject: [PATCH 12/54] refactor: remove unused cluster-related logic and imports - Eliminated the isCluster state and related logic from WzReloadClusterManagerCallout component. - Removed unused clusterReq import from multiple files, streamlining the codebase. - Updated checkDaemons function to remove the isCluster parameter, simplifying its implementation. - Ensured consistent handling of cluster status checks across the application. --- .../common/reload-cluster-manager-callout.tsx | 13 +------- .../components/check-module-enabled.tsx | 5 +-- .../edit-configuration/edit-configuration.js | 1 - .../configuration/utils/wz-fetch.js | 31 +++---------------- 4 files changed, 7 insertions(+), 43 deletions(-) diff --git a/plugins/main/public/components/common/reload-cluster-manager-callout.tsx b/plugins/main/public/components/common/reload-cluster-manager-callout.tsx index 4a619a4358..ebae408084 100644 --- a/plugins/main/public/components/common/reload-cluster-manager-callout.tsx +++ b/plugins/main/public/components/common/reload-cluster-manager-callout.tsx @@ -23,10 +23,7 @@ import { } from '@elastic/eui'; import { getToasts } from '../../kibana-services'; -import { - clusterReq, - reloadRuleset, -} from '../../controllers/management/components/management/configuration/utils/wz-fetch'; +import { reloadRuleset } from '../../controllers/management/components/management/configuration/utils/wz-fetch'; interface IWzReloadClusterManagerCalloutProps { updateWazuhNotReadyYet: (wazuhNotReadyYet) => void; @@ -36,7 +33,6 @@ interface IWzReloadClusterManagerCalloutProps { interface IWzReloadClusterManagerCalloutState { warningReloading: boolean; - isCluster: boolean; } class WzReloadClusterManagerCallout extends Component< @@ -47,7 +43,6 @@ class WzReloadClusterManagerCallout extends Component< super(props); this.state = { warningReloading: false, - isCluster: false, }; } showToast(color, title, text = '', time = 3000) { @@ -136,12 +131,6 @@ class WzReloadClusterManagerCallout extends Component< ); } }; - async componentDidMount() { - // Always use cluster mode in v5.0+ (cluster mode by default) - this.setState({ - isCluster: true, - }); - } render() { const { warningReloading } = this.state; return ( diff --git a/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx b/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx index 1572f26635..34fcfbe346 100644 --- a/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx +++ b/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx @@ -1,8 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { - clusterReq, - clusterNodes, -} from '../../../../../controllers/management/components/management/configuration/utils/wz-fetch'; +import { clusterNodes } from '../../../../../controllers/management/components/management/configuration/utils/wz-fetch'; import { WzRequest } from '../../../../../react-services'; import { webDocumentationLink } from '../../../../../../common/services/web_documentation'; import { EuiCallOut, EuiLink } from '@elastic/eui'; diff --git a/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js b/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js index 093e1f0527..1099d38068 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js +++ b/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js @@ -41,7 +41,6 @@ import { saveFileManager, saveFileCluster, clusterNodes, - clusterReq, } from '../utils/wz-fetch'; import { validateXML } from '../utils/xml'; import { getToasts } from '../../../../../..//kibana-services'; diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index 2f75faf3c4..676f989969 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -168,10 +168,9 @@ export const handleError = async ( /** * Check daemons status - * @param {boolean} isCluster * @returns {object|Promise} */ -export const checkDaemons = async isCluster => { +export const checkDaemons = async () => { try { const response = await WzRequest.apiReq( 'GET', @@ -188,18 +187,10 @@ export const checkDaemons = async isCluster => { const modulesd = daemons['wazuh-modulesd'] === 'running'; const wazuhdb = wazuhdbExists ? daemons['wazuh-db'] === 'running' : true; - let clusterd = true; - if (isCluster) { - const clusterStatus = - (((await clusterReq()) || {}).data || {}).data || {}; - clusterd = - clusterStatus.enabled === 'yes' && clusterStatus.running === 'yes' - ? daemons['wazuh-clusterd'] === 'running' - : false; - } + // Always check clusterd in v5.0+ (cluster by default) + const clusterd = daemons['wazuh-clusterd'] === 'running'; - const isValid = - execd && modulesd && wazuhdb && (isCluster ? clusterd : true); + const isValid = execd && modulesd && wazuhdb && clusterd; if (isValid) { return { isValid }; @@ -228,7 +219,7 @@ export const makePing = async ( while (tries--) { await delayAsPromise(2000); try { - isValid = await checkDaemons(isCluster); + isValid = await checkDaemons(); if (isValid) { updateWazuhNotReadyYet(''); break; @@ -246,18 +237,6 @@ export const makePing = async ( } }; -/** - * Get Cluster status from Wazuh API - * @returns {Promise} - */ -export const clusterReq = async () => { - try { - return WzRequest.apiReq('GET', '/cluster/status', {}); - } catch (error) { - return Promise.reject(error); - } -}; - /** * Fetch a config file from cluster node or manager * @return {string} From 4174ba327057d673dcc2f4283e4cb4e697e30225 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Thu, 4 Sep 2025 14:36:28 -0500 Subject: [PATCH 13/54] refactor: streamline cluster configuration handling and remove unused imports - Removed the unused saveFileManager function from wz-fetch.js to simplify the codebase. - Updated WzEditConfiguration component to always use cluster-related logic, reflecting the default cluster mode. - Enhanced clarity in the cluster configuration title and messages throughout the component. - Added comments to clarify that cluster is always enabled and running in version 5.0+. --- .../management/cluster/cluster-overview.tsx | 5 +- .../edit-configuration/edit-configuration.js | 56 +++++++------------ .../configuration/utils/wz-fetch.js | 17 ------ 3 files changed, 22 insertions(+), 56 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx b/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx index 3dedb1dfe8..6fd198c6bf 100644 --- a/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx +++ b/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx @@ -8,7 +8,6 @@ import { } from '../../../../../components/common/hocs'; import { cluster } from '../../../../../utils/applications'; import { WzRequest } from '../../../../../react-services'; -import { ClusterDisabled } from '../../../../../components/management/cluster/cluster-disabled'; import { ClusterDashboard } from '../../../../../components/management/cluster/dashboard/dashboard'; import { LoadingSearchbarProgress } from '../../../../../components/common/loading-searchbar-progress/loading-searchbar-progress'; import { FormattedMessage } from '@osd/i18n/react'; @@ -26,8 +25,8 @@ const getClusterStatus = async () => { return { ok: false, data: { - clusterEnabled: 'yes', - isClusterRunning: true, + clusterEnabled: 'yes', // Always enabled in v5.0+ (cluster by default) + isClusterRunning: true, // Always running in v5.0+ (cluster by default) statusRunning, }, }; diff --git a/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js b/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js index 1099d38068..49d80e503f 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js +++ b/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js @@ -38,7 +38,6 @@ import { import { fetchFile, restartNodeSelected, - saveFileManager, saveFileCluster, clusterNodes, } from '../utils/wz-fetch'; @@ -74,12 +73,11 @@ class WzEditConfiguration extends Component { async editorSave() { try { this.setState({ saving: true }); - this.props.clusterNodeSelected - ? await saveFileCluster( - this.state.editorValue, - this.props.clusterNodeSelected, - ) - : await saveFileManager(this.state.editorValue); + // In cluster by default, clusterNodeSelected is always available + await saveFileCluster( + this.state.editorValue, + this.props.clusterNodeSelected, + ); this.setState({ saving: false, infoChangesAfterRestart: true, @@ -91,8 +89,8 @@ class WzEditConfiguration extends Component {   - {this.props.clusterNodeSelected || 'Manager'} configuration - has been updated + {this.props.clusterNodeSelected} configuration has been + updated ), @@ -193,12 +191,6 @@ class WzEditConfiguration extends Component { color: 'success', }); } - if (!this.props.clusterNodeSelected) { - this.addToast({ - title: 'Manager was restarted', - color: 'success', - }); - } } catch (error) { this.props.updateWazuhNotReadyYet(''); this.setState({ restart: false, saving: false, restarting: false }); @@ -257,7 +249,7 @@ class WzEditConfiguration extends Component { return ( @@ -272,12 +264,10 @@ class WzEditConfiguration extends Component { ) : ( - {restarting ? 'Restarting' : 'Restart'}{' '} - {clusterNodeSelected || 'Manager'} + {restarting ? 'Restarting' : 'Restart'} {clusterNodeSelected} @@ -323,7 +310,7 @@ class WzEditConfiguration extends Component { {restart && !restarting && ( this.toggleRestart()} onConfirm={() => this.confirmRestart()} cancelButtonText='Cancel' @@ -420,11 +407,8 @@ const WzEditorConfiguration = compose( Edit ossec.conf of{' '} - {(existsClusterCurrentNodeSelected && clusterNodeSelected) || - 'Manager'} - {existsClusterCurrentNodeSelected && - clusterNodeSelected && - clusterNodes + {clusterNodeSelected} + {existsClusterCurrentNodeSelected && clusterNodes ? ' (' + clusterNodes.find( node => node.name === clusterNodeSelected, diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index 676f989969..7570fdeaac 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -419,23 +419,6 @@ export const saveFileCluster = async (text, node) => { } }; -/** - * Save text to ossec.conf manager file - * @param {string} text Text to save - */ -export const saveFileManager = async text => { - const xml = replaceIllegalXML(text); - try { - await WzRequest.apiReq('PUT', `/manager/configuration`, { - body: xml.toString(), - origin: 'raw', - }); - await validateAfterSent(false); - } catch (error) { - throw error; - } -}; - /** * Validate after sent * @param {} node Node From 6a49295c549be20b610b6488355f20068ba54313 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Thu, 4 Sep 2025 14:49:09 -0500 Subject: [PATCH 14/54] refactor: enhance logs.js for improved cluster node handling - Updated the logic to ensure that the selected node is properly set, defaulting to the first available node if a master node is not found. - Added error handling to return a clear message when no cluster nodes are available. - Improved user feedback by displaying a warning toast if no cluster node is selected during log export. - Streamlined the API request structure for fetching cluster nodes and exporting logs. --- .../components/management/mg-logs/logs.js | 36 +++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/mg-logs/logs.js b/plugins/main/public/controllers/management/components/management/mg-logs/logs.js index 96c879a54e..2514f7de27 100644 --- a/plugins/main/public/controllers/management/components/management/mg-logs/logs.js +++ b/plugins/main/public/controllers/management/components/management/mg-logs/logs.js @@ -230,11 +230,16 @@ export default compose( let nodeList = ''; let selectedNode = ''; const nodeListTmp = await WzRequest.apiReq('GET', '/cluster/nodes', {}); - if (Array.isArray(nodeListTmp?.data?.data?.affected_items)) { + if ( + Array.isArray(nodeListTmp?.data?.data?.affected_items) && + nodeListTmp.data.data.affected_items.length > 0 + ) { nodeList = nodeListTmp.data.data.affected_items; - selectedNode = nodeListTmp.data.data.affected_items.filter( + const masterNode = nodeListTmp.data.data.affected_items.find( item => item.type === 'master', - )[0].name; + ); + selectedNode = + masterNode?.name || nodeListTmp.data.data.affected_items[0].name; return { nodeList, logsPath: `/cluster/${selectedNode}/logs`, @@ -242,10 +247,12 @@ export default compose( }; } + // In cluster by default, no nodes available indicates an API or cluster issue return { - nodeList: '', - logsPath: '/manager/logs', + nodeList: [], + logsPath: '', selectedNode: '', + error: 'No cluster nodes available', }; } catch (error) { throw new Error('Error building logs path: ' + error); @@ -387,17 +394,24 @@ export default compose( 3000, ); const filters = this.buildFilters(); + + if (!this.state.selectedNode) { + this.showToast( + 'warning', + 'No cluster node selected', + 'Please select a cluster node to export logs', + 5000, + ); + return; + } + await exportCsv( - this.state.selectedNode - ? `/cluster/${this.state.selectedNode}/logs` - : '/manager/logs', + `/cluster/${this.state.selectedNode}/logs`, Object.keys(filters).map(filter => ({ name: filter, value: filters[filter], })), - `wazuh-${ - this.state.selectedNode ? `${this.state.selectedNode}-` : '' - }ossec-log`, + `wazuh-${this.state.selectedNode}-ossec-log`, ); } catch (error) { const options = { From 268fb6c4732f84862bcd0cfcaaf0d9016cff8b4b Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Fri, 5 Sep 2025 08:00:41 -0500 Subject: [PATCH 15/54] refactor: improve cluster node selection and error handling in configuration components - Updated WzEditConfiguration and WzRefreshClusterInfoButton components to ensure clusterNodeSelected is always available before saving configurations. - Enhanced error handling by throwing an error when no cluster node is selected. - Streamlined the logic for selecting the master node, defaulting to the first available node if necessary. - Removed outdated comments and improved code clarity for better maintainability. --- .../edit-configuration/edit-configuration.js | 14 +++++++++++--- .../refresh-cluster-info-button.js | 6 ++++-- .../components/management/mg-logs/logs.js | 18 ------------------ 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js b/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js index 49d80e503f..0b69e6d058 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js +++ b/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js @@ -73,7 +73,13 @@ class WzEditConfiguration extends Component { async editorSave() { try { this.setState({ saving: true }); - // In cluster by default, clusterNodeSelected is always available + // In cluster by default, clusterNodeSelected should always be available + if (!this.props.clusterNodeSelected) { + throw new Error( + 'No cluster node selected. Unable to save configuration.', + ); + } + await saveFileCluster( this.state.editorValue, this.props.clusterNodeSelected, @@ -216,11 +222,13 @@ class WzEditConfiguration extends Component { nodes.data.data.affected_items.find( node => node.name === this.props.clusterNodeSelected, ); + const masterNode = nodes.data.data.affected_items.find( + node => node.type === 'master', + ); this.props.updateClusterNodeSelected( existsClusterCurrentNodeSelected ? existsClusterCurrentNodeSelected.name - : nodes.data.data.affected_items.find(node => node.type === 'master') - .name, + : masterNode?.name || nodes.data.data.affected_items[0]?.name, ); this.props.updateConfigurationSection( 'edit-configuration', diff --git a/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js b/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js index bd82f8de56..99bfbbdaf0 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js +++ b/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js @@ -42,11 +42,13 @@ class WzRefreshClusterInfoButton extends Component { nodes.data.data.affected_items.find( node => node.name === this.props.clusterNodeSelected, ); + const masterNode = nodes.data.data.affected_items.find( + node => node.type === 'master', + ); this.props.updateClusterNodeSelected( existsClusterCurrentNodeSelected ? existsClusterCurrentNodeSelected.name - : nodes.data.data.affected_items.find(node => node.type === 'master') - .name, + : masterNode?.name || nodes.data.data.affected_items[0]?.name, ); } catch (error) { // do nothing if it isn't a cluster diff --git a/plugins/main/public/controllers/management/components/management/mg-logs/logs.js b/plugins/main/public/controllers/management/components/management/mg-logs/logs.js index 2514f7de27..9434d80fda 100644 --- a/plugins/main/public/controllers/management/components/management/mg-logs/logs.js +++ b/plugins/main/public/controllers/management/components/management/mg-logs/logs.js @@ -246,14 +246,6 @@ export default compose( selectedNode: selectedNode, }; } - - // In cluster by default, no nodes available indicates an API or cluster issue - return { - nodeList: [], - logsPath: '', - selectedNode: '', - error: 'No cluster nodes available', - }; } catch (error) { throw new Error('Error building logs path: ' + error); } @@ -395,16 +387,6 @@ export default compose( ); const filters = this.buildFilters(); - if (!this.state.selectedNode) { - this.showToast( - 'warning', - 'No cluster node selected', - 'Please select a cluster node to export logs', - 5000, - ); - return; - } - await exportCsv( `/cluster/${this.state.selectedNode}/logs`, Object.keys(filters).map(filter => ({ From f86818f1b904860cac22548fd0163056635842c5 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Fri, 5 Sep 2025 13:59:14 -0500 Subject: [PATCH 16/54] refactor: remove cluster status checks and streamline dashboard components - Eliminated the cluster status retrieval logic from various components, reflecting that the cluster is always enabled and running in version 5.0+. - Updated the DashboardCT and ClusterOverview components to remove unnecessary props and simplify their structure. - Cleaned up the WzStatusOverview component by removing outdated cluster status checks and related error handling. - Streamlined API requests in manage-hosts.ts to align with the new cluster behavior. --- docker/imposter/wazuh-config.yml | 8 --- .../cluster/components/overview_cards.tsx | 3 +- .../cluster/dashboard/dashboard.tsx | 7 +- .../management/cluster/cluster-overview.tsx | 66 ++----------------- .../management/status/status-overview.js | 44 +++---------- .../management/status/utils/status-handler.js | 12 ---- .../server/services/manage-hosts.ts | 28 +++----- 7 files changed, 26 insertions(+), 142 deletions(-) diff --git a/docker/imposter/wazuh-config.yml b/docker/imposter/wazuh-config.yml index ff19ad1ee5..d61b33505b 100755 --- a/docker/imposter/wazuh-config.yml +++ b/docker/imposter/wazuh-config.yml @@ -175,14 +175,6 @@ resources: statusCode: 200 scriptFile: cluster/cluster_sync.js # staticFile: cluster/cluster_sync_no_sync.json - - # Get cluster status - - method: GET - path: /cluster/status - response: - statusCode: 200 - staticFile: cluster/cluster_status.json - # Get local node config - method: GET path: /cluster/local/config diff --git a/plugins/main/public/components/management/cluster/components/overview_cards.tsx b/plugins/main/public/components/management/cluster/components/overview_cards.tsx index 7379d7d8c5..cc1a95c0d9 100644 --- a/plugins/main/public/components/management/cluster/components/overview_cards.tsx +++ b/plugins/main/public/components/management/cluster/components/overview_cards.tsx @@ -22,7 +22,6 @@ interface OverviewCardsProps { goNodes: () => void; goConfiguration: () => void; configuration: any; - status: any; version: any; nodesCount: number; nodeList: any[]; @@ -99,7 +98,7 @@ export const OverviewCards = ({ }, { title: 'Running', - description: status ?? 'no', + description: 'yes', }, { title: 'Version', diff --git a/plugins/main/public/components/management/cluster/dashboard/dashboard.tsx b/plugins/main/public/components/management/cluster/dashboard/dashboard.tsx index 963a008e57..cf0798702b 100644 --- a/plugins/main/public/components/management/cluster/dashboard/dashboard.tsx +++ b/plugins/main/public/components/management/cluster/dashboard/dashboard.tsx @@ -27,9 +27,7 @@ import { import { WzSearchBar } from '../../../common/search-bar'; import NavigationService from '../../../../react-services/navigation-service'; -interface DashboardCTProps { - statusRunning: string; -} + interface ClusterDashboardState { showConfig: boolean; @@ -41,7 +39,7 @@ interface ClusterDashboardState { agentsCount: number; } -const DashboardCT: React.FC = ({ statusRunning }) => { +const DashboardCT: React.FC = () => { const { filters, dataSource, @@ -177,7 +175,6 @@ const DashboardCT: React.FC = ({ statusRunning }) => { goNodes={goNodes} goAgents={goAgents} goConfiguration={goConfiguration} - status={statusRunning} configuration={state?.configuration} version={state?.version} nodesCount={state?.nodesCount} diff --git a/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx b/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx index 6fd198c6bf..6a1a6aeb45 100644 --- a/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx +++ b/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx @@ -3,42 +3,10 @@ import { compose } from 'redux'; import { withErrorBoundary, withGlobalBreadcrumb, - withGuardAsync, withUserAuthorizationPrompt, } from '../../../../../components/common/hocs'; import { cluster } from '../../../../../utils/applications'; -import { WzRequest } from '../../../../../react-services'; import { ClusterDashboard } from '../../../../../components/management/cluster/dashboard/dashboard'; -import { LoadingSearchbarProgress } from '../../../../../components/common/loading-searchbar-progress/loading-searchbar-progress'; -import { FormattedMessage } from '@osd/i18n/react'; - -interface ClusterOverviewState { - clusterEnabled: boolean; - isClusterRunning: boolean; - statusRunning: string; -} - -const getClusterStatus = async () => { - try { - const status: any = await WzRequest.apiReq('GET', '/cluster/status', {}); - const statusRunning = status?.data?.data?.running; - return { - ok: false, - data: { - clusterEnabled: 'yes', // Always enabled in v5.0+ (cluster by default) - isClusterRunning: true, // Always running in v5.0+ (cluster by default) - statusRunning, - }, - }; - } catch (error) { - return { - ok: true, - data: { - error: { title: 'There was a problem', message: error.message }, - }, - }; - } -}; export const ClusterOverview = compose( withErrorBoundary, @@ -46,30 +14,10 @@ export const ClusterOverview = compose( withUserAuthorizationPrompt([ { action: 'cluster:status', resource: '*:*:*' }, ]), - withGuardAsync( - getClusterStatus, - ({ clusterEnabled, isClusterRunning, error }) => null, - () => ( - - } - /> - ), - ), -)( - ({ - clusterEnabled, - isClusterRunning, - statusRunning, - }: ClusterOverviewState) => { - return ( - <> - - - ); - }, -); +)(() => { + return ( + <> + + + ); +}); diff --git a/plugins/main/public/controllers/management/components/management/status/status-overview.js b/plugins/main/public/controllers/management/components/management/status/status-overview.js index 0d3c8b75f8..ca3f47bb80 100644 --- a/plugins/main/public/controllers/management/components/management/status/status-overview.js +++ b/plugins/main/public/controllers/management/components/management/status/status-overview.js @@ -93,12 +93,10 @@ export class WzStatusOverview extends Component { try { this.props.updateLoadingStatus(true); - const [clusterStatus, agentsCountByManagerNodes] = ( - await Promise.all([ - this.statusHandler.clusterStatus(), - this.statusHandler.clusterAgentsCount(), - ]) - ).map(response => response?.data?.data); + // In v5.0+ cluster is always enabled and running (cluster by default) + const agentsCountByManagerNodes = ( + await this.statusHandler.clusterAgentsCount() + )?.data?.data; const { connection: agentsCount, configuration } = agentsCountByManagerNodes?.agent_status; @@ -118,15 +116,11 @@ export class WzStatusOverview extends Component { agentsCoverage: isNaN(agentsActiveCoverage) ? 0 : agentsActiveCoverage, }); - this.props.updateClusterEnabled( - clusterStatus && clusterStatus.enabled === 'yes', - ); + // Cluster is always enabled in v5.0+ (cluster by default) + this.props.updateClusterEnabled(true); - if ( - clusterStatus && - clusterStatus.enabled === 'yes' && - clusterStatus.running === 'yes' - ) { + // Cluster is always enabled and running in v5.0+ (cluster by default) + { const nodes = await this.statusHandler.clusterNodes(); const listNodes = nodes.data.data.affected_items; this.props.updateListNodes(listNodes); @@ -143,28 +137,6 @@ export class WzStatusOverview extends Component { masterNode.name, ); this.props.updateNodeInfo(nodeInfo.data.data.affected_items[0]); - } else { - if ( - clusterStatus && - clusterStatus.enabled === 'yes' && - clusterStatus.running === 'no' - ) { - this.showToast( - 'danger', - `Cluster is enabled but it's not running, please check your cluster health.`, - 3000, - ); - } else { - const managerInfo = await this.statusHandler.managerInfo(); - const daemons = await this.statusHandler.managerStatus(); - const listDaemons = this.objToArr( - daemons?.data?.data?.affected_items?.[0], - ); - const managerInfoData = managerInfo?.data?.data?.affected_items?.[0]; - this.props.updateListDaemons(listDaemons); - this.props.updateSelectedNode(false); - this.props.updateNodeInfo(managerInfoData); - } } const [lastAgent] = agentsCountByManagerNodes?.last_registered_agent; diff --git a/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js b/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js index 2e25762124..cabac02e8b 100644 --- a/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js +++ b/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js @@ -29,18 +29,6 @@ export default class StatusHandler { } } - /** - * Get cluster status - */ - static async clusterStatus() { - try { - const result = await WzRequest.apiReq('GET', `/cluster/status`, {}); - return result; - } catch (error) { - throw error; - } - } - /** * Get cluster nodes */ diff --git a/plugins/wazuh-core/server/services/manage-hosts.ts b/plugins/wazuh-core/server/services/manage-hosts.ts index 35e260c50f..b63bfa45d2 100644 --- a/plugins/wazuh-core/server/services/manage-hosts.ts +++ b/plugins/wazuh-core/server/services/manage-hosts.ts @@ -227,32 +227,20 @@ export class ManageHosts { } } - const responseClusterStatus = + // In v5.0+ cluster is always enabled (cluster by default) + status = 'enabled'; + + const responseClusterLocal = await this.serverAPIClient.asInternalUser.request( 'GET', - `/cluster/status`, + `/cluster/local/info`, {}, { apiHostID }, ); - if ( - this.isServerAPIClientResponseOk(responseClusterStatus) && - responseClusterStatus.data?.data?.enabled === 'yes' - ) { - status = 'enabled'; - - const responseClusterLocal = - await this.serverAPIClient.asInternalUser.request( - 'GET', - `/cluster/local/info`, - {}, - { apiHostID }, - ); - - if (this.isServerAPIClientResponseOk(responseClusterLocal)) { - node = responseClusterLocal.data.data.affected_items[0].node; - cluster = responseClusterLocal.data.data.affected_items[0].cluster; - } + if (this.isServerAPIClientResponseOk(responseClusterLocal)) { + node = responseClusterLocal.data.data.affected_items[0].node; + cluster = responseClusterLocal.data.data.affected_items[0].cluster; } } catch (error) { if (options?.throwError) { From de07bc248f807181603fb3d9c816eba67cc1a6c9 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Fri, 5 Sep 2025 14:09:52 -0500 Subject: [PATCH 17/54] refactor: simplify DashboardCT component and enhance error handling in WzEditConfiguration - Removed unnecessary props from the DashboardCT component for improved clarity. - Updated WzEditConfiguration to gracefully handle missing clusterNodeSelected, providing user feedback through a toast notification instead of throwing an error. - Enhanced overall code readability and maintainability by cleaning up comments and structure. --- .../cluster/dashboard/dashboard.tsx | 4 +--- .../edit-configuration/edit-configuration.js | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/plugins/main/public/components/management/cluster/dashboard/dashboard.tsx b/plugins/main/public/components/management/cluster/dashboard/dashboard.tsx index cf0798702b..fe9cfcada7 100644 --- a/plugins/main/public/components/management/cluster/dashboard/dashboard.tsx +++ b/plugins/main/public/components/management/cluster/dashboard/dashboard.tsx @@ -27,8 +27,6 @@ import { import { WzSearchBar } from '../../../common/search-bar'; import NavigationService from '../../../../react-services/navigation-service'; - - interface ClusterDashboardState { showConfig: boolean; showNodes: boolean; @@ -39,7 +37,7 @@ interface ClusterDashboardState { agentsCount: number; } -const DashboardCT: React.FC = () => { +const DashboardCT: React.FC = () => { const { filters, dataSource, diff --git a/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js b/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js index 0b69e6d058..36396ad81c 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js +++ b/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js @@ -73,11 +73,22 @@ class WzEditConfiguration extends Component { async editorSave() { try { this.setState({ saving: true }); - // In cluster by default, clusterNodeSelected should always be available + // Gracefully handle missing clusterNodeSelected (timing/loading issue) if (!this.props.clusterNodeSelected) { - throw new Error( - 'No cluster node selected. Unable to save configuration.', - ); + this.setState({ saving: false }); + this.addToast({ + title: ( + + +   + + No cluster node selected. Unable to save configuration. + + + ), + color: 'danger', + }); + return; } await saveFileCluster( From 6ad055b31954cc539f8b65915807eb739246ad2b Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Mon, 8 Sep 2025 14:19:00 -0500 Subject: [PATCH 18/54] refactor: remove deprecated cluster status actions and update permissions - Eliminated cluster status actions from security actions and policies, reflecting the new cluster behavior. - Updated user permission requirements across various components to use 'cluster:read' instead of 'cluster:status' and 'manager:read'. - Streamlined code by removing unnecessary checks and ensuring consistent permission handling throughout the application. --- .../policies/get-policies-after-delete.json | 19 ++--- .../security/policies/get-policies.json | 21 +++--- .../imposter/security/security-actions.json | 65 ----------------- .../imposter/security/security-policies.json | 21 +++--- .../common/api-info/security-actions.json | 65 ----------------- .../components/check-module-enabled.tsx | 3 +- .../management/cluster/cluster-overview.tsx | 4 +- .../configuration/configuration-overview.js | 1 - .../configuration/configuration-switch.js | 2 +- .../groups/actions-buttons-agents.js | 1 - .../groups/actions-buttons-files.js | 1 - .../management/groups/groups-editor.js | 60 ++++++++-------- .../management/groups/groups-overview.js | 1 - .../management/groups/utils/columns-files.js | 1 - .../components/management/mg-logs/logs.js | 1 - .../statistics/statistics-overview.js | 1 - .../management/status/status-overview.js | 2 +- .../wz-user-permissions.test.ts | 69 ++++++++++--------- 18 files changed, 94 insertions(+), 244 deletions(-) diff --git a/docker/imposter/security/policies/get-policies-after-delete.json b/docker/imposter/security/policies/get-policies-after-delete.json index 3bd892cb46..fcaa2fbb43 100644 --- a/docker/imposter/security/policies/get-policies-after-delete.json +++ b/docker/imposter/security/policies/get-policies-after-delete.json @@ -299,11 +299,10 @@ "name": "cluster_all_resourceless", "policy": { "actions": [ - "cluster:status", - "manager:read", - "manager:read_api_config", - "manager:update_config", - "manager:restart" + "cluster:read", + "cluster:read_api_config", + "cluster:update_config", + "cluster:restart" ], "resources": ["*:*:*"], "effect": "allow" @@ -329,11 +328,7 @@ "id": 31, "name": "cluster_read_resourceless", "policy": { - "actions": [ - "cluster:status", - "manager:read", - "manager:read_api_config" - ], + "actions": ["cluster:read", "cluster:read_api_config"], "resources": ["*:*:*"], "effect": "allow" }, @@ -387,7 +382,7 @@ "id": 100, "name": "manager_deny_read", "policy": { - "actions": ["manager:read", "cluster:read"], + "actions": ["cluster:read"], "resources": ["*:*:*", "node:id:*"], "effect": "deny" }, @@ -397,7 +392,7 @@ "id": 102, "name": "custom_manager_deny_read2", "policy": { - "actions": ["manager:read", "cluster:read"], + "actions": ["cluster:read"], "resources": ["*:*:*", "node:id:*"], "effect": "deny" }, diff --git a/docker/imposter/security/policies/get-policies.json b/docker/imposter/security/policies/get-policies.json index 20207a9ff9..bf2028325f 100644 --- a/docker/imposter/security/policies/get-policies.json +++ b/docker/imposter/security/policies/get-policies.json @@ -299,11 +299,10 @@ "name": "cluster_all_resourceless", "policy": { "actions": [ - "cluster:status", - "manager:read", - "manager:read_api_config", - "manager:update_config", - "manager:restart" + "cluster:read", + "cluster:read_api_config", + "cluster:update_config", + "cluster:restart" ], "resources": ["*:*:*"], "effect": "allow" @@ -329,11 +328,7 @@ "id": 31, "name": "cluster_read_resourceless", "policy": { - "actions": [ - "cluster:status", - "manager:read", - "manager:read_api_config" - ], + "actions": ["cluster:read", "cluster:read_api_config"], "resources": ["*:*:*"], "effect": "allow" }, @@ -387,7 +382,7 @@ "id": 100, "name": "manager_deny_read", "policy": { - "actions": ["manager:read", "cluster:read"], + "actions": ["cluster:read"], "resources": ["*:*:*", "node:id:*"], "effect": "deny" }, @@ -397,7 +392,7 @@ "id": 101, "name": "custom_manager_deny_read", "policy": { - "actions": ["manager:read", "cluster:read"], + "actions": ["cluster:read"], "resources": ["*:*:*", "node:id:*"], "effect": "deny" }, @@ -407,7 +402,7 @@ "id": 102, "name": "custom_manager_deny_read2", "policy": { - "actions": ["manager:read", "cluster:read"], + "actions": ["cluster:read"], "resources": ["*:*:*", "node:id:*"], "effect": "deny" }, diff --git a/docker/imposter/security/security-actions.json b/docker/imposter/security/security-actions.json index 5de2eee49d..b87f2badfd 100644 --- a/docker/imposter/security/security-actions.json +++ b/docker/imposter/security/security-actions.json @@ -208,16 +208,6 @@ }, "related_endpoints": ["PUT /agents/reconnect"] }, - "cluster:status": { - "description": "Check Wazuh's cluster general status", - "resources": ["*:*"], - "example": { - "actions": ["cluster:status"], - "resources": ["*:*:*"], - "effect": "allow" - }, - "related_endpoints": ["GET /cluster/status"] - }, "cluster:read_api_config": { "description": "Check Wazuh's cluster nodes API configuration", "resources": ["*:*"], @@ -295,61 +285,6 @@ }, "related_endpoints": ["PUT /logtest", "DELETE /logtest/sessions/{token}"] }, - "manager:read": { - "description": "Read Wazuh manager configuration", - "resources": ["*:*"], - "example": { - "actions": ["manager:read"], - "resources": ["*:*:*"], - "effect": "allow" - }, - "related_endpoints": [ - "GET /manager/status", - "GET /manager/info", - "GET /manager/configuration", - "GET /manager/daemons/stats", - "GET /manager/stats", - "GET /manager/stats/hourly", - "GET /manager/stats/weekly", - "GET /manager/stats/analysisd", - "GET /manager/stats/remoted", - "GET /manager/logs", - "GET /manager/logs/summary", - "PUT /manager/restart", - "GET /manager/configuration/validation", - "GET /manager/configuration/{component}/{configuration}" - ] - }, - "manager:update_config": { - "description": "Update current Wazuh manager configuration", - "resources": ["*:*"], - "example": { - "actions": ["manager:update_config"], - "resources": ["*:*:*"], - "effect": "allow" - }, - "related_endpoints": ["PUT /manager/configuration"] - }, - "manager:read_api_config": { - "description": "Read Wazuh manager API configuration", - "resources": ["*:*"], - "example": { - "actions": ["manager:read_api_config"], - "resources": ["*:*:*"], - "effect": "allow" - }, - "related_endpoints": ["GET /manager/api/config"] - }, - "manager:restart": { - "description": "Restart Wazuh managers", - "resources": ["*:*"], - "example": { - "actions": ["manager:restart"], - "resources": ["*:*:*"], - "effect": "deny" - }, - "related_endpoints": ["PUT /manager/restart"] - }, "mitre:read": { "description": "Access information from MITRE database", "resources": ["*:*"], diff --git a/docker/imposter/security/security-policies.json b/docker/imposter/security/security-policies.json index 20207a9ff9..bf2028325f 100644 --- a/docker/imposter/security/security-policies.json +++ b/docker/imposter/security/security-policies.json @@ -299,11 +299,10 @@ "name": "cluster_all_resourceless", "policy": { "actions": [ - "cluster:status", - "manager:read", - "manager:read_api_config", - "manager:update_config", - "manager:restart" + "cluster:read", + "cluster:read_api_config", + "cluster:update_config", + "cluster:restart" ], "resources": ["*:*:*"], "effect": "allow" @@ -329,11 +328,7 @@ "id": 31, "name": "cluster_read_resourceless", "policy": { - "actions": [ - "cluster:status", - "manager:read", - "manager:read_api_config" - ], + "actions": ["cluster:read", "cluster:read_api_config"], "resources": ["*:*:*"], "effect": "allow" }, @@ -387,7 +382,7 @@ "id": 100, "name": "manager_deny_read", "policy": { - "actions": ["manager:read", "cluster:read"], + "actions": ["cluster:read"], "resources": ["*:*:*", "node:id:*"], "effect": "deny" }, @@ -397,7 +392,7 @@ "id": 101, "name": "custom_manager_deny_read", "policy": { - "actions": ["manager:read", "cluster:read"], + "actions": ["cluster:read"], "resources": ["*:*:*", "node:id:*"], "effect": "deny" }, @@ -407,7 +402,7 @@ "id": 102, "name": "custom_manager_deny_read2", "policy": { - "actions": ["manager:read", "cluster:read"], + "actions": ["cluster:read"], "resources": ["*:*:*", "node:id:*"], "effect": "deny" }, diff --git a/plugins/main/common/api-info/security-actions.json b/plugins/main/common/api-info/security-actions.json index 429a84110c..24c30c131c 100644 --- a/plugins/main/common/api-info/security-actions.json +++ b/plugins/main/common/api-info/security-actions.json @@ -230,16 +230,6 @@ "GET /experimental/ciscat/results" ] }, - "cluster:status": { - "description": "Check Wazuh's cluster general status", - "resources": ["*:*"], - "example": { - "actions": ["cluster:status"], - "resources": ["*:*:*"], - "effect": "allow" - }, - "related_endpoints": ["GET /cluster/status"] - }, "cluster:read_api_config": { "description": "Check Wazuh's cluster nodes API configuration", "resources": ["*:*"], @@ -317,61 +307,6 @@ }, "related_endpoints": ["PUT /logtest", "DELETE /logtest/sessions/{token}"] }, - "manager:read": { - "description": "Read Wazuh manager configuration", - "resources": ["*:*"], - "example": { - "actions": ["manager:read"], - "resources": ["*:*:*"], - "effect": "allow" - }, - "related_endpoints": [ - "GET /manager/status", - "GET /manager/info", - "GET /manager/configuration", - "GET /manager/daemons/stats", - "GET /manager/stats", - "GET /manager/stats/hourly", - "GET /manager/stats/weekly", - "GET /manager/stats/analysisd", - "GET /manager/stats/remoted", - "GET /manager/logs", - "GET /manager/logs/summary", - "PUT /manager/restart", - "GET /manager/configuration/validation", - "GET /manager/configuration/{component}/{configuration}" - ] - }, - "manager:update_config": { - "description": "Update current Wazuh manager configuration", - "resources": ["*:*"], - "example": { - "actions": ["manager:update_config"], - "resources": ["*:*:*"], - "effect": "allow" - }, - "related_endpoints": ["PUT /manager/configuration"] - }, - "manager:read_api_config": { - "description": "Read Wazuh manager API configuration", - "resources": ["*:*"], - "example": { - "actions": ["manager:read_api_config"], - "resources": ["*:*:*"], - "effect": "allow" - }, - "related_endpoints": ["GET /manager/api/config"] - }, - "manager:restart": { - "description": "Restart Wazuh managers", - "resources": ["*:*"], - "example": { - "actions": ["manager:restart"], - "resources": ["*:*:*"], - "effect": "deny" - }, - "related_endpoints": ["PUT /manager/restart"] - }, "mitre:read": { "description": "Access information from MITRE database", "resources": ["*:*"], diff --git a/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx b/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx index 34fcfbe346..577f2f1f52 100644 --- a/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx +++ b/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx @@ -49,9 +49,8 @@ async function checkVDIsEnabledManager() { export const ModuleEnabledCheck = () => { const [data, setData] = useState<{ enabled: boolean } | null>(null); const [userPermissionRequirements] = useUserPermissionsRequirements([ - { action: 'cluster:status', resource: '*:*:*' }, { action: 'cluster:read', resource: 'node:id:*' }, - { action: 'manager:read', resource: '*:*:*' }, + { action: 'cluster:read', resource: '*:*:*' }, ]); const checkVDIsEnabled = async () => { diff --git a/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx b/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx index 6a1a6aeb45..9d7341c683 100644 --- a/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx +++ b/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx @@ -11,9 +11,7 @@ import { ClusterDashboard } from '../../../../../components/management/cluster/d export const ClusterOverview = compose( withErrorBoundary, withGlobalBreadcrumb([{ text: cluster.breadcrumbLabel }]), - withUserAuthorizationPrompt([ - { action: 'cluster:status', resource: '*:*:*' }, - ]), + withUserAuthorizationPrompt([{ action: 'cluster:read', resource: '*:*:*' }]), )(() => { return ( <> diff --git a/plugins/main/public/controllers/management/components/management/configuration/configuration-overview.js b/plugins/main/public/controllers/management/components/management/configuration/configuration-overview.js index 8c0d4fe8a1..3a22de3499 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/configuration-overview.js +++ b/plugins/main/public/controllers/management/components/management/configuration/configuration-overview.js @@ -116,7 +116,6 @@ class WzConfigurationOverview extends Component { ({ export default compose( withUserAuthorizationPrompt(props => [ props.agent.id === '000' - ? { action: 'manager:read', resource: '*:*:*' } + ? { action: 'cluster:read', resource: '*:*:*' } : [ { action: 'agent:read', resource: `agent:id:${props.agent.id}` }, ...(props.agent.group || []).map(group => ({ diff --git a/plugins/main/public/controllers/management/components/management/groups/actions-buttons-agents.js b/plugins/main/public/controllers/management/components/management/groups/actions-buttons-agents.js index 4b74367ccc..263901d418 100644 --- a/plugins/main/public/controllers/management/components/management/groups/actions-buttons-agents.js +++ b/plugins/main/public/controllers/management/components/management/groups/actions-buttons-agents.js @@ -46,7 +46,6 @@ class WzGroupsActionButtonsAgents extends Component { action: 'group:update_config', resource: `group:id:${this.props.state.itemDetail.name}`, }, - { action: 'cluster:status', resource: '*:*:*' }, ]} iconSide='left' iconType='folderOpen' diff --git a/plugins/main/public/controllers/management/components/management/groups/actions-buttons-files.js b/plugins/main/public/controllers/management/components/management/groups/actions-buttons-files.js index 8601dfa2a6..dd47d97bc4 100644 --- a/plugins/main/public/controllers/management/components/management/groups/actions-buttons-files.js +++ b/plugins/main/public/controllers/management/components/management/groups/actions-buttons-files.js @@ -62,7 +62,6 @@ class WzGroupsActionButtonsFiles extends Component { action: 'group:update_config', resource: `group:id:${this.props.state.itemDetail.name}`, }, - { action: 'cluster:status', resource: '*:*:*' }, ]} iconSide='left' iconType='documentEdit' diff --git a/plugins/main/public/controllers/management/components/management/groups/groups-editor.js b/plugins/main/public/controllers/management/components/management/groups/groups-editor.js index 90a350b327..2d2f0674ee 100644 --- a/plugins/main/public/controllers/management/components/management/groups/groups-editor.js +++ b/plugins/main/public/controllers/management/components/management/groups/groups-editor.js @@ -28,7 +28,7 @@ import { EuiConfirmModal, EuiPanel, EuiCodeBlock, - EuiOverlayMask + EuiOverlayMask, } from '@elastic/eui'; import GroupsHandler from './utils/groups-handler'; @@ -46,7 +46,6 @@ import { UI_LOGGER_LEVELS } from '../../../../../../common/constants'; import { UI_ERROR_SEVERITIES } from '../../../../../react-services/error-orchestrator/types'; import { getErrorOrchestrator } from '../../../../../react-services/common-services'; - class WzGroupsEditor extends Component { _isMounted = false; constructor(props) { @@ -82,7 +81,9 @@ class WzGroupsEditor extends Component { componentDidUpdate(prevProps, prevState) { if (prevState.content !== this.state.content) { - this.setState({ hasChanges: this.state.content !== this.state.initContent }); + this.setState({ + hasChanges: this.state.content !== this.state.initContent, + }); } } @@ -124,7 +125,7 @@ class WzGroupsEditor extends Component { error: { error: error, message: error.message || error, - title: "Error found saving the file.", + title: 'Error found saving the file.', }, }; getErrorOrchestrator().handleError(options); @@ -149,7 +150,6 @@ class WzGroupsEditor extends Component { { closeModal; this.props.cleanFileContent(); }} onCancel={closeModal} cancelButtonText="No, don't do it" - confirmButtonText="Yes, do it" + confirmButtonText='Yes, do it' >

There are unsaved changes. Are you sure you want to proceed? @@ -196,12 +196,12 @@ class WzGroupsEditor extends Component { - + { if (this.state.hasChanges) { showModal(); @@ -211,42 +211,46 @@ class WzGroupsEditor extends Component { }} /> - {name} of {groupName}{' '} - group + {name} of{' '} + {groupName} group - {isEditable && {saveButton}} + {isEditable && ( + {saveButton} + )} - + {xmlError && ( {xmlError} - + )} - + {(isEditable && ( this.setState({ content: newContent })} - mode="xml" + onChange={newContent => + this.setState({ content: newContent }) + } + mode='xml' wrapEnabled setOptions={this.codeEditorOptions} - aria-label="Code Editor" + aria-label='Code Editor' /> )) || ( {content} @@ -266,13 +270,13 @@ class WzGroupsEditor extends Component { } } -const mapStateToProps = (state) => { +const mapStateToProps = state => { return { state: state.groupsReducers, }; }; -const mapDispatchToProps = (dispatch) => { +const mapDispatchToProps = dispatch => { return { cleanFileContent: () => dispatch(cleanFileContent()), }; diff --git a/plugins/main/public/controllers/management/components/management/groups/groups-overview.js b/plugins/main/public/controllers/management/components/management/groups/groups-overview.js index 0112173bfc..0a85a11e00 100644 --- a/plugins/main/public/controllers/management/components/management/groups/groups-overview.js +++ b/plugins/main/public/controllers/management/components/management/groups/groups-overview.js @@ -99,7 +99,6 @@ export class WzGroupsOverview extends Component { action: 'group:update_config', resource: `group:id:${item.name}`, }, - { action: 'cluster:status', resource: '*:*:*' }, ]} tooltip={{ position: 'top', diff --git a/plugins/main/public/controllers/management/components/management/groups/utils/columns-files.js b/plugins/main/public/controllers/management/components/management/groups/utils/columns-files.js index 0020e5fd33..114d86e0c3 100644 --- a/plugins/main/public/controllers/management/components/management/groups/utils/columns-files.js +++ b/plugins/main/public/controllers/management/components/management/groups/utils/columns-files.js @@ -77,7 +77,6 @@ export default class GroupsFilesColumns { action: 'group:update_config', resource: `group:id:${itemDetail.name}`, }, - { action: 'cluster:status', resource: '*:*:*' }, ]} tooltip={{ position: 'top', diff --git a/plugins/main/public/controllers/management/components/management/mg-logs/logs.js b/plugins/main/public/controllers/management/components/management/mg-logs/logs.js index 9434d80fda..83cb2d800d 100644 --- a/plugins/main/public/controllers/management/components/management/mg-logs/logs.js +++ b/plugins/main/public/controllers/management/components/management/mg-logs/logs.js @@ -46,7 +46,6 @@ import { logs } from '../../../../../utils/applications'; export default compose( withGlobalBreadcrumb([{ text: logs.breadcrumbLabel }]), withUserAuthorizationPrompt([ - { action: 'cluster:status', resource: '*:*:*' }, { action: 'cluster:read', resource: 'node:id:*' }, ]), )( diff --git a/plugins/main/public/controllers/management/components/management/statistics/statistics-overview.js b/plugins/main/public/controllers/management/components/management/statistics/statistics-overview.js index b9c9438e11..2777548c3e 100644 --- a/plugins/main/public/controllers/management/components/management/statistics/statistics-overview.js +++ b/plugins/main/public/controllers/management/components/management/statistics/statistics-overview.js @@ -220,7 +220,6 @@ const mapStateToProps = state => ({ export default compose( withGlobalBreadcrumb([{ text: statistics.breadcrumbLabel }]), withUserAuthorizationPrompt([ - { action: 'cluster:status', resource: '*:*:*' }, { action: 'cluster:read', resource: 'node:id:*' }, ]), connect(mapStateToProps), diff --git a/plugins/main/public/controllers/management/components/management/status/status-overview.js b/plugins/main/public/controllers/management/components/management/status/status-overview.js index ca3f47bb80..645137c5ba 100644 --- a/plugins/main/public/controllers/management/components/management/status/status-overview.js +++ b/plugins/main/public/controllers/management/components/management/status/status-overview.js @@ -242,7 +242,7 @@ export default compose( { action: 'agent:read', resource: 'agent:id:*' }, { action: 'agent:read', resource: 'agent:group:*' }, ], - { action: 'manager:read', resource: '*:*:*' }, + { action: 'cluster:read', resource: '*:*:*' }, { action: 'cluster:read', resource: 'node:id:*' }, ]), connect(mapStateToProps, mapDispatchToProps), diff --git a/plugins/main/public/react-services/wz-user-permissions.test.ts b/plugins/main/public/react-services/wz-user-permissions.test.ts index bd12333b98..7ba22662c4 100644 --- a/plugins/main/public/react-services/wz-user-permissions.test.ts +++ b/plugins/main/public/react-services/wz-user-permissions.test.ts @@ -25,15 +25,15 @@ const requiredPermissionsCluster = [ const requiredPermissionsManager = [ { - action: 'cluster:status', + action: 'cluster:read', resource: '*:*:*', }, { - action: 'manager:read_file', + action: 'cluster:read', resource: 'file:path:/etc/lists', }, { - action: 'manager:read', + action: 'cluster:read', resource: '*:*:*', }, { @@ -48,11 +48,6 @@ const userClusterTest = { 'list:path:*': 'allow', 'node:id:*': 'allow', }, - 'cluster:status': { - '*:*:*': 'allow', - 'list:path:*': 'allow', - 'node:id:*': 'allow', - }, 'cluster:read': { '*:*:*': 'allow', 'list:path:*': 'allow', @@ -81,7 +76,7 @@ const userClusterTest = { const userManagerTest = [ { - 'manager:read': { + 'cluster:read': { '*:*:*': 'allow', 'file:path:*': 'allow', }, @@ -89,7 +84,7 @@ const userManagerTest = [ '*:*:*': 'allow', 'file:path:*': 'allow', }, - 'manager:read_file': { + 'cluster:read_file': { '*:*:*': 'allow', 'file:path:*': 'allow', }, @@ -110,11 +105,11 @@ const missingPermissionsForClusterUser = [ const missingPermissionsForManagerUser = [ { - action: 'manager:read_file', + action: 'cluster:read', resource: 'file:path:/etc/lists', }, { - action: 'manager:read', + action: 'cluster:read', resource: '*:*:*', }, { @@ -133,28 +128,34 @@ describe('Wazuh User Permissions', () => { resource: '*:*:*', }, ]; - const result = WzUserPermissions.checkMissingUserPermissions(simplePermission, { - 'lists:read': { - 'list:path:*': 'allow', + const result = WzUserPermissions.checkMissingUserPermissions( + simplePermission, + { + 'lists:read': { + 'list:path:*': 'allow', + }, + rbac_mode: 'white', }, - rbac_mode: 'white', - }); + ); expect(result).toEqual(simplePermission); }); it('Should return a simple missing permissions for cluster user', () => { const simplePermission = [ { - action: 'cluster:status', + action: 'cluster:read', resource: '*:*:*', }, ]; - const result = WzUserPermissions.checkMissingUserPermissions(simplePermission, { - 'lists:read': { - 'list:path:*': 'allow', + const result = WzUserPermissions.checkMissingUserPermissions( + simplePermission, + { + 'lists:read': { + 'list:path:*': 'allow', + }, + rbac_mode: 'white', }, - rbac_mode: 'white', - }); + ); expect(result).toEqual(simplePermission); }); }); @@ -163,13 +164,13 @@ describe('Wazuh User Permissions', () => { it('Should return all permissions ok for manager user', () => { const simplePermission = [ { - action: 'manager:read_file', + action: 'cluster:read', resource: 'file:path:/etc/lists', }, ]; const result = WzUserPermissions.checkMissingUserPermissions( simplePermission, - userManagerTest + userManagerTest, ); expect(result).toEqual(false); // false === all permissions OK }); @@ -177,13 +178,13 @@ describe('Wazuh User Permissions', () => { it('Should return a simple missing permissions for cluster user', () => { const simplePermission = [ { - action: 'cluster:status', + action: 'cluster:read', resource: '*:*:*', }, ]; const result = WzUserPermissions.checkMissingUserPermissions( simplePermission, - userClusterTest + userClusterTest, ); expect(result).toEqual(false); }); @@ -200,7 +201,7 @@ describe('Wazuh User Permissions', () => { const result = WzUserPermissions.checkMissingUserPermissions( simplePermission, - userClusterTest + userClusterTest, ); expect(result).toEqual(false); // false === all permissions OK }); @@ -210,7 +211,7 @@ describe('Wazuh User Permissions', () => { it('Should return missing permissions for manager user', () => { const result = WzUserPermissions.checkMissingUserPermissions( requiredPermissionsManager, - userClusterTest + userClusterTest, ); expect(result).toEqual(missingPermissionsForManagerUser); }); @@ -218,7 +219,7 @@ describe('Wazuh User Permissions', () => { it('Should return missing permissions for cluster user', () => { const result = WzUserPermissions.checkMissingUserPermissions( requiredPermissionsCluster, - userClusterTest + userClusterTest, ); expect(result).toEqual(missingPermissionsForClusterUser); }); @@ -247,7 +248,7 @@ describe('Wazuh User Permissions', () => { it('Should return OK for particular agent and group id', () => { const result = WzUserPermissions.checkMissingUserPermissions( requiredAgentView, - userAgent1 + userAgent1, ); expect(result).toEqual(false); }); @@ -276,7 +277,7 @@ describe('Wazuh User Permissions', () => { it('Should return OK for all agents and groups', () => { const result = WzUserPermissions.checkMissingUserPermissions( requiredAgentView, - userAgent1 + userAgent1, ); expect(result).toEqual(false); }); @@ -313,7 +314,7 @@ describe('Wazuh User Permissions', () => { it('Should return OK for the agent 001', () => { const result = WzUserPermissions.checkMissingUserPermissions( requiredMitreView, - userMitre1 + userMitre1, ); expect(result).toEqual(false); }); @@ -341,7 +342,7 @@ describe('Wazuh User Permissions', () => { it('Should return OK for all agents and groups', () => { const result = WzUserPermissions.checkMissingUserPermissions( requiredAgentView, - userAgent1 + userAgent1, ); expect(result).toEqual(false); }); From 06802e2e5b3ca6510702ef47d6d0cda8955bd8dd Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Mon, 8 Sep 2025 15:11:27 -0500 Subject: [PATCH 19/54] refactor: update user permissions by removing redundant cluster actions - Removed unnecessary 'cluster:read' permission entries from the requiredPermissionsManager and missingPermissionsForManagerUser arrays. - Streamlined user permission definitions to enhance clarity and maintainability in the wz-user-permissions test file. --- .../react-services/wz-user-permissions.test.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/plugins/main/public/react-services/wz-user-permissions.test.ts b/plugins/main/public/react-services/wz-user-permissions.test.ts index 7ba22662c4..d8c3ce58d8 100644 --- a/plugins/main/public/react-services/wz-user-permissions.test.ts +++ b/plugins/main/public/react-services/wz-user-permissions.test.ts @@ -24,18 +24,10 @@ const requiredPermissionsCluster = [ ]; const requiredPermissionsManager = [ - { - action: 'cluster:read', - resource: '*:*:*', - }, { action: 'cluster:read', resource: 'file:path:/etc/lists', }, - { - action: 'cluster:read', - resource: '*:*:*', - }, { action: 'manager:upload_file', resource: 'file:path:/etc/lists', @@ -108,10 +100,6 @@ const missingPermissionsForManagerUser = [ action: 'cluster:read', resource: 'file:path:/etc/lists', }, - { - action: 'cluster:read', - resource: '*:*:*', - }, { action: 'manager:upload_file', resource: 'file:path:/etc/lists', From 80bca0c4e0023ff6e15fa0a2c3bfed079522075d Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Tue, 9 Sep 2025 08:23:12 -0500 Subject: [PATCH 20/54] refactor: improve code readability and structure in module configuration component - Reformatted import statements for better organization and clarity. - Enhanced the structure of the getMapConfigurationToState function for improved readability. - Updated the PanelModuleConfiguration component to streamline async action handling and rendering logic. - Cleaned up the ConfigurationWrapper component for better maintainability and clarity in rendering configurations. --- .../panel/components/module_configuration.tsx | 297 ++++++++++++------ .../requirement-flyout/requirement-flyout.tsx | 4 +- 2 files changed, 197 insertions(+), 104 deletions(-) diff --git a/plugins/main/public/components/common/modules/panel/components/module_configuration.tsx b/plugins/main/public/components/common/modules/panel/components/module_configuration.tsx index 7fed8e3807..d050cedbb0 100644 --- a/plugins/main/public/components/common/modules/panel/components/module_configuration.tsx +++ b/plugins/main/public/components/common/modules/panel/components/module_configuration.tsx @@ -11,7 +11,18 @@ */ import React, { useEffect, useMemo, FunctionalComponent } from 'react'; -import { EuiDescriptionList, EuiFlexItem, EuiFlexGroup, EuiTitle, EuiCallOut, EuiIcon, EuiSpacer, EuiProgress, EuiAccordion, EuiText } from '@elastic/eui'; +import { + EuiDescriptionList, + EuiFlexItem, + EuiFlexGroup, + EuiTitle, + EuiCallOut, + EuiIcon, + EuiSpacer, + EuiProgress, + EuiAccordion, + EuiText, +} from '@elastic/eui'; import { WzRequest } from '../../../../../react-services'; import { connect } from 'react-redux'; import { useAsyncAction } from '../../../hooks'; @@ -28,17 +39,26 @@ import { UI_LOGGER_LEVELS } from '../../../../../../common/constants'; import './module_configuration.scss'; const mapStateToProps = state => ({ - agent: state.appStateReducers.currentAgentData + agent: state.appStateReducers.currentAgentData, }); -const getMapConfigurationToState = async (type: string, configurationAPIPartialPath: string, mapResponseConfiguration, params?: any ) : Promise<[any] | string> => { - const prefixEndpoint = type === 'agent' - ? `/agents/${params.id}/config` - : (type === 'cluster_node' - ? `/cluster/${params.name}/configuration` - : `/manager/configuration` +const getMapConfigurationToState = async ( + type: string, + configurationAPIPartialPath: string, + mapResponseConfiguration, + params?: any, +): Promise<[any] | string> => { + const prefixEndpoint = + type === 'agent' + ? `/agents/${params.id}/config` + : type === 'cluster_node' + ? `/cluster/${params.name}/configuration` + : `/manager/configuration`; + const response = await WzRequest.apiReq( + 'GET', + `${prefixEndpoint}${configurationAPIPartialPath}`, + {}, ); - const response = await WzRequest.apiReq('GET', `${prefixEndpoint}${configurationAPIPartialPath}`, {}); return mapResponseConfiguration(response, type, params); }; @@ -46,111 +66,182 @@ const renderEntityTitle = (entity: string, name: string) => { return `${entity}${name ? ` - ${name}` : ''}`; }; -export const PanelModuleConfiguration : FunctionalComponent<{h: string}> = connect(mapStateToProps)( -({ agent, configurationAPIPartialPath, mapResponseConfiguration, moduleTitle, moduleIconType = '', settings }) => { +export const PanelModuleConfiguration: FunctionalComponent<{ h: string }> = + connect(mapStateToProps)( + ({ + agent, + configurationAPIPartialPath, + mapResponseConfiguration, + moduleTitle, + moduleIconType = '', + settings, + }) => { + const asyncAction = useAsyncAction(async () => { + try { + if (agent.id) { + // Get the module configuration for the pinned agent + const configuration = await getMapConfigurationToState( + 'agent', + configurationAPIPartialPath, + mapResponseConfiguration, + agent, + ); + return configuration ? [configuration] : null; + } else { + const nodesResponse = await WzRequest.apiReq( + 'GET', + `/cluster/nodes`, + {}, + ); + const nodesConfigurationResponses = await Promise.all( + nodesResponse.data.data.affected_items.map( + async node => + await getMapConfigurationToState( + 'cluster_node', + configurationAPIPartialPath, + mapResponseConfiguration, + node, + ), + ), + ); + const nodeConfigurations = nodesConfigurationResponses.filter( + nodeConfiguration => nodeConfiguration, + ); + return nodeConfigurations.length ? nodeConfigurations : null; + } + } catch (error) { + const options: UIErrorLog = { + context: `${PanelModuleConfiguration.name}.getModuleConfig`, + level: UI_LOGGER_LEVELS.ERROR as UILogLevel, + severity: UI_ERROR_SEVERITIES.BUSINESS as UIErrorSeverity, + error: { + error: error, + message: error.message || error, + title: 'Module Unavailable', + }, + }; + getErrorOrchestrator().handleError(options); + throw error; // This lets to populate the 'asyncAction.error' property + } + }, [agent]); - const asyncAction = useAsyncAction((async () => { - try{ - if(agent.id){ - // Get the module configuration for the pinned agent - const configuration = await getMapConfigurationToState('agent', configurationAPIPartialPath, mapResponseConfiguration, agent); - return configuration ? [configuration] : null; - }else{ - const nodesResponse = await WzRequest.apiReq('GET', `/cluster/nodes`, {}); - const nodesConfigurationResponses = await Promise.all( - nodesResponse.data.data.affected_items - .map(async node => await getMapConfigurationToState('cluster_node', configurationAPIPartialPath, mapResponseConfiguration, node) - ) - ); - const nodeConfigurations = nodesConfigurationResponses.filter(nodeConfiguration => nodeConfiguration); - return nodeConfigurations.length ? nodeConfigurations : null; - } - }catch(error){ - const options: UIErrorLog = { - context: `${PanelModuleConfiguration.name}.getModuleConfig`, - level: UI_LOGGER_LEVELS.ERROR as UILogLevel, - severity: UI_ERROR_SEVERITIES.BUSINESS as UIErrorSeverity, - error: { - error: error, - message: error.message || error, - title: 'Module Unavailable', - }, - }; - getErrorOrchestrator().handleError(options); - throw error; // This lets to populate the 'asyncAction.error' property - } - }), [agent]); - - useEffect(() => { - asyncAction.run(); - },[asyncAction.run]); + useEffect(() => { + asyncAction.run(); + }, [asyncAction.run]); - return ( - <> - - - - - - -

{moduleTitle}

- - -
Module configuration
-
- - - - - - - - + return ( + <> + + + + + + +

+ {moduleTitle} +

+
+ +
+ Module configuration +
+
+
+
+ + + + + + + ); + }, ); -}); const ConfigurationWrapper = compose( - withGuard(({loading}) => loading, () => ), - withGuard(({error}) => error, ({error}) => ( - - {error && error.message || String(error)} - - )), - withGuard(({configurations}) => !configurations, () => ( - - )) -)(({configurations, settings}) => { + withGuard( + ({ loading }) => loading, + () => , + ), + withGuard( + ({ error }) => error, + ({ error }) => ( + + {(error && error.message) || String(error)} + + ), + ), + withGuard( + ({ configurations }) => !configurations, + () => ( + + ), + ), +)(({ configurations, settings }) => { return ( -
- {configurations.length === 1 - ? <> - {renderEntityTitle(configurations[0].entity, configurations[0].name)} - - - - : configurations.map((configuration, index) => ( - - - - )).reduce((prev, cur) => [prev,
, cur], []) - } +
+ {configurations.length === 1 ? ( + <> + + {renderEntityTitle( + configurations[0].entity, + configurations[0].name, + )} + + + + + ) : ( + configurations + .map((configuration, index) => ( + + + + )) + .reduce( + (prev, cur) => [prev,
, cur], + [], + ) + )}
- ) + ); }); const Configuration = ({ configuration, settings }) => { const listItems = useMemo(() => { return settings - .filter(({field}) => typeof configuration[field] !== 'undefined') - .map(({field, label, render = null}) => ({title: label, description: render ? render(configuration[field]) : configuration[field]})); + .filter(({ field }) => typeof configuration[field] !== 'undefined') + .map(({ field, label, render = null }) => ({ + title: label, + description: render + ? render(configuration[field]) + : configuration[field], + })); }, [configuration]); return (
@@ -160,5 +251,5 @@ const Configuration = ({ configuration, settings }) => { compressed />
- ) + ); }; diff --git a/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx b/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx index f443db6dcb..d7f82dd307 100644 --- a/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx +++ b/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx @@ -187,7 +187,9 @@ export const RequirementFlyout = connect(mapStateToProps)( const { currentRequirement } = this.props; const requirementImplicitFilter = {}; // Always use cluster.name in v5.0+ (cluster mode by default) - const clusterFilter = { 'cluster.name': AppState.getClusterInfo().cluster }; + const clusterFilter = { + 'cluster.name': AppState.getClusterInfo().cluster, + }; this.clusterFilter = clusterFilter; requirementImplicitFilter[this.props.getRequirementKey()] = currentRequirement; From 2681365f9d814f280bf81a4782d366c09e2e59fa Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Tue, 9 Sep 2025 09:12:26 -0500 Subject: [PATCH 21/54] docs: update changelog and fix formatting for cluster by default implementation --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db5eeb77f9..ee3b2af0f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ All notable changes to the Wazuh app project will be documented in this file. ### Changed -- Cluster mode is now enabled by default. Removed all conditional logic between cluster and manager modes. All Wazuh installations now operate in cluster mode, including single-node deployments. Updated all filters to use cluster.name, unified API endpoints to cluster paths, simplified UI components, and removed cluster-disabled component [#7688](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7688) +- Cluster mode is now enabled by default. Removed all conditional logic between cluster and manager modes. All Wazuh installations now operate in cluster mode, including single-node deployments. Updated all filters to consistently use `cluster.name` instead of `manager.name`, unified API endpoints to cluster paths, simplified UI components by removing cluster/manager toggles, updated RBAC permissions from `manager:*` actions to `cluster:*` actions, removed `/cluster/status` endpoint dependencies, and eliminated cluster-disabled component. Sample data generation now defaults to cluster-aware configuration [#7688](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7688) - Rework SCA modules visualizations, global detail for all agents without pinning, replaced `/sca` endpoint with `wazuh-states-sca-*` index pattern, added sample data section [#7578](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7578) - Split the FIM registry inventory into 2 index patterns and change some fields in the FIM files and registries sample data [#7604](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7604) From 5160dd8571ef15308b1b2bd1d4df2e470d6d04c9 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 08:56:57 -0500 Subject: [PATCH 22/54] refactor: remove redundant isCluster parameter from managerQuery method --- .../data-source/pattern/pattern-data-source-filter-manager.ts | 1 - plugins/main/public/utils/filter-handler.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts b/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts index 4f658f0018..db1efd5cc5 100644 --- a/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts +++ b/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts @@ -267,7 +267,6 @@ export class PatternDataSourceFilterManager // Cluster mode is always enabled in v5.0+ const managerFilter = filterHandler.managerQuery( AppState.getClusterInfo().cluster, - true, key, ); managerFilter.meta = { diff --git a/plugins/main/public/utils/filter-handler.js b/plugins/main/public/utils/filter-handler.js index cb6388378f..67149c86b3 100644 --- a/plugins/main/public/utils/filter-handler.js +++ b/plugins/main/public/utils/filter-handler.js @@ -103,7 +103,7 @@ export class FilterHandler { * @param {*} fixedKey * @returns */ - managerQuery(manager, isCluster = true, fixedKey = undefined) { + managerQuery(manager, fixedKey = undefined) { // Always use cluster.name in v5.0+ (cluster mode by default) const metaKey = fixedKey ? fixedKey : 'cluster.name'; const result = this.base(); From db1c603604437b844fcde846141c3bb627f050b1 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 09:04:30 -0500 Subject: [PATCH 23/54] refactor: simplify API endpoint logic in module configuration component - Removed redundant condition for determining the prefixEndpoint in getMapConfigurationToState function. - Streamlined the logic to ensure clarity and maintainability in API request handling. --- .../common/modules/panel/components/module_configuration.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/main/public/components/common/modules/panel/components/module_configuration.tsx b/plugins/main/public/components/common/modules/panel/components/module_configuration.tsx index d050cedbb0..5609a0b45a 100644 --- a/plugins/main/public/components/common/modules/panel/components/module_configuration.tsx +++ b/plugins/main/public/components/common/modules/panel/components/module_configuration.tsx @@ -51,9 +51,7 @@ const getMapConfigurationToState = async ( const prefixEndpoint = type === 'agent' ? `/agents/${params.id}/config` - : type === 'cluster_node' - ? `/cluster/${params.name}/configuration` - : `/manager/configuration`; + : `/cluster/${params.name}/configuration`; const response = await WzRequest.apiReq( 'GET', `${prefixEndpoint}${configurationAPIPartialPath}`, From 916c5b6dcbfc6a90e250384cb6341762f74ffae5 Mon Sep 17 00:00:00 2001 From: Juan Felipe Gonzalez Ortiz <53414652+felipegonzalezmv@users.noreply.github.com> Date: Wed, 10 Sep 2025 09:31:58 -0500 Subject: [PATCH 24/54] Update plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx Co-authored-by: Antonio <34042064+Desvelao@users.noreply.github.com> --- .../register-agent/services/register-agent-services.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx b/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx index 5c40fbab09..20f22a76da 100644 --- a/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx +++ b/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx @@ -28,7 +28,6 @@ export type ServerAddressOptions = { nodetype: string; }; -// Removed clusterStatusResponse function - cluster mode is always enabled in v5.0+ /** * Get the remote configuration from api From 173e9edb6b1cdcef7b97367e3d90f60a07e16bf0 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 09:34:44 -0500 Subject: [PATCH 25/54] refactor: simplify getRemoteConfiguration calls in register-agent-services tests - Removed redundant 'false' parameter from getRemoteConfiguration calls in multiple test cases for improved clarity and consistency. --- .../services/register-agent-services.test.ts | 25 ++++--------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.test.ts b/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.test.ts index ecc68fb6b9..080f9740cf 100644 --- a/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.test.ts +++ b/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.test.ts @@ -43,10 +43,7 @@ describe('Register agent service', () => { WzRequest.apiReq = jest.fn().mockResolvedValueOnce(mockedResponse); const nodeName = 'example-node'; - const res = await RegisterAgentService.getRemoteConfiguration( - nodeName, - false, - ); + const res = await RegisterAgentService.getRemoteConfiguration(nodeName); expect(res.name).toBe(nodeName); expect(res.haveSecureConnection).toBe(true); }); @@ -74,10 +71,7 @@ describe('Register agent service', () => { }; WzRequest.apiReq = jest.fn().mockResolvedValueOnce(mockedResponse); const nodeName = 'example-node'; - const res = await RegisterAgentService.getRemoteConfiguration( - nodeName, - false, - ); + const res = await RegisterAgentService.getRemoteConfiguration(nodeName); expect(res.name).toBe(nodeName); expect(res.haveSecureConnection).toBe(false); }); @@ -112,10 +106,7 @@ describe('Register agent service', () => { }; WzRequest.apiReq = jest.fn().mockResolvedValueOnce(mockedResponse); const nodeName = 'example-node'; - const res = await RegisterAgentService.getRemoteConfiguration( - nodeName, - false, - ); + const res = await RegisterAgentService.getRemoteConfiguration(nodeName); expect(res.name).toBe(nodeName); expect(res.isUdp).toEqual(true); }); @@ -150,10 +141,7 @@ describe('Register agent service', () => { }; WzRequest.apiReq = jest.fn().mockResolvedValueOnce(mockedResponse); const nodeName = 'example-node'; - const res = await RegisterAgentService.getRemoteConfiguration( - nodeName, - false, - ); + const res = await RegisterAgentService.getRemoteConfiguration(nodeName); expect(res.name).toBe(nodeName); expect(res.isUdp).toEqual(false); }); @@ -188,10 +176,7 @@ describe('Register agent service', () => { }; WzRequest.apiReq = jest.fn().mockResolvedValueOnce(mockedResponse); const nodeName = 'example-node'; - const res = await RegisterAgentService.getRemoteConfiguration( - nodeName, - false, - ); + const res = await RegisterAgentService.getRemoteConfiguration(nodeName); expect(res.name).toBe(nodeName); expect(res.isUdp).toEqual(false); }); From bb5ed3c0c3366543d05817fc03427bb072aadb7d Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 09:40:03 -0500 Subject: [PATCH 26/54] refactor: remove redundant 'Running' card from OverviewCards component - Eliminated the 'Running' card from the OverviewCards component to streamline the display of cluster information and enhance clarity. --- .../management/cluster/components/overview_cards.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/main/public/components/management/cluster/components/overview_cards.tsx b/plugins/main/public/components/management/cluster/components/overview_cards.tsx index cc1a95c0d9..7ac4584c37 100644 --- a/plugins/main/public/components/management/cluster/components/overview_cards.tsx +++ b/plugins/main/public/components/management/cluster/components/overview_cards.tsx @@ -96,10 +96,6 @@ export const OverviewCards = ({ title: 'IP address', description: configuration?.nodes[0] || '-', }, - { - title: 'Running', - description: 'yes', - }, { title: 'Version', description: version ?? '-', From d01fad71cc34142e581334e38fdcaddedead1b53 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 09:45:30 -0500 Subject: [PATCH 27/54] refactor: remove unused 'status' prop from OverviewCards component --- .../components/management/cluster/components/overview_cards.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/main/public/components/management/cluster/components/overview_cards.tsx b/plugins/main/public/components/management/cluster/components/overview_cards.tsx index 7ac4584c37..704ba18eab 100644 --- a/plugins/main/public/components/management/cluster/components/overview_cards.tsx +++ b/plugins/main/public/components/management/cluster/components/overview_cards.tsx @@ -43,7 +43,6 @@ export const OverviewCards = ({ goNodes, goConfiguration, configuration, - status, version, nodesCount, nodeList, From 2757797961e1d8297643878e1fcd3113624a0584 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 09:47:06 -0500 Subject: [PATCH 28/54] refactor: remove unused dashboard panels from analysis engine - Eliminated redundant dashboard panel definitions to streamline the code and improve maintainability. --- .../dashboard_panels_analysis_engine.ts | 129 ------------------ 1 file changed, 129 deletions(-) diff --git a/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboard_panels_analysis_engine.ts b/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboard_panels_analysis_engine.ts index b4b670bf39..94b656aed5 100644 --- a/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboard_panels_analysis_engine.ts +++ b/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboard_panels_analysis_engine.ts @@ -2545,134 +2545,5 @@ export const getDashboardPanelsAnalysisEngine = ( }, }; - const panels = { - '1': { - gridData: { - w: 24, - h: 13, - x: 0, - y: 0, - i: '1', - }, - type: 'visualization', - explicitInput: { - id: '1', - savedVis: getVisStateEventsProcessed(indexPatternId), - }, - }, - '2': { - gridData: { - w: 24, - h: 13, - x: 24, - y: 0, - i: '2', - }, - type: 'visualization', - explicitInput: { - id: '2', - savedVis: getVisStateEventsDropped(indexPatternId), - }, - }, - '3': { - gridData: { - w: 48, - h: 13, - x: 0, - y: 13, - i: '3', - }, - type: 'visualization', - explicitInput: { - id: '3', - savedVis: getVisStateQueueUsage(indexPatternId), - }, - }, - '4': { - gridData: { - w: 48, - h: 13, - x: 0, - y: 26, - i: '4', - }, - type: 'visualization', - explicitInput: { - id: '4', - savedVis: getVisStateEventsDecodedSummary(indexPatternId), - }, - }, - '5': { - gridData: { - w: 24, - h: 13, - x: 0, - y: 39, - i: '5', - }, - type: 'visualization', - explicitInput: { - id: '5', - savedVis: getVisStateSyscheck(indexPatternId), - }, - }, - '6': { - gridData: { - w: 24, - h: 13, - x: 24, - y: 39, - i: '6', - }, - type: 'visualization', - explicitInput: { - id: '6', - savedVis: getVisStateSyscollector(indexPatternId), - }, - }, - '7': { - gridData: { - w: 24, - h: 13, - x: 0, - y: 52, - i: '7', - }, - type: 'visualization', - explicitInput: { - id: '7', - savedVis: getVisStateRootcheck(indexPatternId), - }, - }, - '8': { - gridData: { - w: 24, - h: 13, - x: 24, - y: 52, - i: '8', - }, - type: 'visualization', - explicitInput: { - id: '8', - savedVis: getVisStateSCA(indexPatternId), - }, - }, - '9': { - gridData: { - w: 48, - h: 13, - x: 0, - y: 65, - i: '9', - }, - type: 'visualization', - explicitInput: { - id: '9', - savedVis: getVisStateHostInfo(indexPatternId), - }, - }, - }; - return clusterModePanels; }; From 48d53578d6bd02c947796fca76d03e420dced8e8 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 09:52:04 -0500 Subject: [PATCH 29/54] refactor: remove redundant 'cluster:read' permission entries from module checks - Eliminated unnecessary 'cluster:read' permission with wildcard resource from both ModuleEnabledCheck and status overview components to enhance clarity and maintainability in user permission requirements. --- .../vulnerabilities/common/components/check-module-enabled.tsx | 1 - .../management/components/management/status/status-overview.js | 1 - 2 files changed, 2 deletions(-) diff --git a/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx b/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx index 577f2f1f52..f04f92dfee 100644 --- a/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx +++ b/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx @@ -50,7 +50,6 @@ export const ModuleEnabledCheck = () => { const [data, setData] = useState<{ enabled: boolean } | null>(null); const [userPermissionRequirements] = useUserPermissionsRequirements([ { action: 'cluster:read', resource: 'node:id:*' }, - { action: 'cluster:read', resource: '*:*:*' }, ]); const checkVDIsEnabled = async () => { diff --git a/plugins/main/public/controllers/management/components/management/status/status-overview.js b/plugins/main/public/controllers/management/components/management/status/status-overview.js index 645137c5ba..b6bafaf5a7 100644 --- a/plugins/main/public/controllers/management/components/management/status/status-overview.js +++ b/plugins/main/public/controllers/management/components/management/status/status-overview.js @@ -242,7 +242,6 @@ export default compose( { action: 'agent:read', resource: 'agent:id:*' }, { action: 'agent:read', resource: 'agent:group:*' }, ], - { action: 'cluster:read', resource: '*:*:*' }, { action: 'cluster:read', resource: 'node:id:*' }, ]), connect(mapStateToProps, mapDispatchToProps), From 37d488c1aeebed67ef598e4a28e7e1f9b9485dde Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 09:56:52 -0500 Subject: [PATCH 30/54] refactor: update 'cluster:read' permission resource for user authorization - Changed the resource for 'cluster:read' permission from wildcard to 'node:id:*' in both ClusterOverview and configuration-switch components to enhance security and specificity in user authorization checks. --- .../components/management/cluster/cluster-overview.tsx | 4 +++- .../management/configuration/configuration-switch.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx b/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx index 9d7341c683..7654d13edd 100644 --- a/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx +++ b/plugins/main/public/controllers/management/components/management/cluster/cluster-overview.tsx @@ -11,7 +11,9 @@ import { ClusterDashboard } from '../../../../../components/management/cluster/d export const ClusterOverview = compose( withErrorBoundary, withGlobalBreadcrumb([{ text: cluster.breadcrumbLabel }]), - withUserAuthorizationPrompt([{ action: 'cluster:read', resource: '*:*:*' }]), + withUserAuthorizationPrompt([ + { action: 'cluster:read', resource: 'node:id:*' }, + ]), )(() => { return ( <> diff --git a/plugins/main/public/controllers/management/components/management/configuration/configuration-switch.js b/plugins/main/public/controllers/management/components/management/configuration/configuration-switch.js index 49f5536f37..d4ee07f680 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/configuration-switch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/configuration-switch.js @@ -457,7 +457,7 @@ const mapDispatchToProps = dispatch => ({ export default compose( withUserAuthorizationPrompt(props => [ props.agent.id === '000' - ? { action: 'cluster:read', resource: '*:*:*' } + ? { action: 'cluster:read', resource: 'node:id:*' } : [ { action: 'agent:read', resource: `agent:id:${props.agent.id}` }, ...(props.agent.group || []).map(group => ({ From 1ff205ec7ea50b8a844dea979bac55bf386e020c Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 10:41:51 -0500 Subject: [PATCH 31/54] refactor: enhance cluster node selection handling in configuration editor - Removed the check for missing clusterNodeSelected during save operation to streamline the saving process. - Updated the save button's disabled state to include the condition for clusterNodeSelected, improving user feedback and preventing save attempts without a selected node. --- .../edit-configuration/edit-configuration.js | 23 ++++--------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js b/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js index 36396ad81c..d28478402a 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js +++ b/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js @@ -73,23 +73,6 @@ class WzEditConfiguration extends Component { async editorSave() { try { this.setState({ saving: true }); - // Gracefully handle missing clusterNodeSelected (timing/loading issue) - if (!this.props.clusterNodeSelected) { - this.setState({ saving: false }); - this.addToast({ - title: ( - - -   - - No cluster node selected. Unable to save configuration. - - - ), - color: 'danger', - }); - return; - } await saveFileCluster( this.state.editorValue, @@ -288,7 +271,11 @@ class WzEditConfiguration extends Component { resource: `node:id:${this.props.clusterNodeSelected}`, }, ]} - isDisabled={saving || disableSaveRestartButtons} + isDisabled={ + saving || + disableSaveRestartButtons || + !this.props.clusterNodeSelected + } iconType='save' onClick={() => this.editorSave()} > From 031e70eb353f1d2bb5e8b4843e5d82e9d3ba84d3 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 10:48:20 -0500 Subject: [PATCH 32/54] refactor: streamline configuration overview component and permissions handling - Simplified the permissions logic for the configuration edit button by using a single resource for 'cluster:update_config'. - Removed the conditional rendering of the cluster node selection component to enhance clarity in the UI. - Cleaned up the mapStateToProps by removing the unused 'clusterNodeSelected' state, improving maintainability. --- .../configuration/configuration-overview.js | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/configuration/configuration-overview.js b/plugins/main/public/controllers/management/components/management/configuration/configuration-overview.js index 3a22de3499..04989eaac6 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/configuration-overview.js +++ b/plugins/main/public/controllers/management/components/management/configuration/configuration-overview.js @@ -116,24 +116,17 @@ class WzConfigurationOverview extends Component { this.updateConfigurationSection( 'edit-configuration', - `${ - this.props.clusterNodeSelected ? 'Cluster' : 'Manager' - } configuration`, + `Cluster configuration`, '', 'Edit configuration', ) @@ -162,9 +155,7 @@ class WzConfigurationOverview extends Component { - {this.props.clusterNodes && - this.props.clusterNodes.length && - this.props.clusterNodeSelected ? ( + {this.props.clusterNodes && this.props.clusterNodes.length ? ( @@ -192,7 +183,6 @@ class WzConfigurationOverview extends Component { const mapStateToProps = state => ({ clusterNodes: state.configurationReducers.clusterNodes, - clusterNodeSelected: state.configurationReducers.clusterNodeSelected, }); export default connect(mapStateToProps)(WzConfigurationOverview); From f7eccbb345e5da5047fb626d81418e3ef80254ca Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 14:13:18 -0500 Subject: [PATCH 33/54] refactor: simplify URL construction in getCurrentConfig function - Streamlined the URL construction logic by removing unnecessary conditions, enhancing clarity and maintainability in the configuration fetching process. --- .../management/configuration/utils/wz-fetch.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index 7570fdeaac..14852a6c0c 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -52,11 +52,10 @@ export const getCurrentConfig = async ( throw new Error('Invalid section'); } try { - const url = node - ? `/cluster/${node}/configuration/${component}/${configuration}` - : agentId === '000' - ? `/manager/configuration/${component}/${configuration}` - : `/agents/${agentId}/config/${component}/${configuration}`; + const url = + agentId === '000' + ? `/cluster/${node}/configuration/${component}/${configuration}` + : `/agents/${agentId}/config/${component}/${configuration}`; const partialResult = await WzRequest.apiReq('GET', url, {}); From 5bbda84ccd4e9da39946666b04d38ccb9297661b Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 14:20:50 -0500 Subject: [PATCH 34/54] refactor: simplify error handling and remove unused daemon checks - Updated the error handling logic in the Wazuh API to streamline the ping process by removing the isCluster parameter. - Eliminated the checkDaemons function from both the public and server controllers, enhancing code clarity and maintainability. --- .../configuration/utils/wz-fetch.js | 65 ++----------------- plugins/main/server/controllers/wazuh-api.ts | 43 ------------ 2 files changed, 5 insertions(+), 103 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index 14852a6c0c..a86e5d6c20 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -145,7 +145,7 @@ export const handleError = async ( try { if (messageIsString && message.includes('ERROR3099')) { updateWazuhNotReadyYet('Server not ready yet.'); - await makePing(updateWazuhNotReadyYet, isCluster); + await makePing(updateWazuhNotReadyYet); return; } @@ -165,71 +165,16 @@ export const handleError = async ( } }; -/** - * Check daemons status - * @returns {object|Promise} - */ -export const checkDaemons = async () => { - try { - const response = await WzRequest.apiReq( - 'GET', - '/manager/status', - {}, - { checkCurrentApiIsUp: false }, - ); - const daemons = - ((((response || {}).data || {}).data || {}).affected_items || [])[0] || - {}; - const wazuhdbExists = typeof daemons['wazuh-db'] !== 'undefined'; - - const execd = daemons['wazuh-execd'] === 'running'; - const modulesd = daemons['wazuh-modulesd'] === 'running'; - const wazuhdb = wazuhdbExists ? daemons['wazuh-db'] === 'running' : true; - - // Always check clusterd in v5.0+ (cluster by default) - const clusterd = daemons['wazuh-clusterd'] === 'running'; - - const isValid = execd && modulesd && wazuhdb && clusterd; - - if (isValid) { - return { isValid }; - } else { - console.warn('Server not ready yet'); - } - } catch (error) { - throw error; - } -}; - /** * Make ping to Wazuh API * @param updateWazuhNotReadyYet - * @param {boolean} isCluster * @param {number} [tries=10] Tries * @return {Promise} */ -export const makePing = async ( - updateWazuhNotReadyYet, - isCluster, - tries = 30, -) => { +export const makePing = async (updateWazuhNotReadyYet, tries = 30) => { try { - let isValid = false; - while (tries--) { - await delayAsPromise(2000); - try { - isValid = await checkDaemons(); - if (isValid) { - updateWazuhNotReadyYet(''); - break; - } - } catch (error) { - console.error(error); - } - } - if (!isValid) { - throw new Error('Not recovered'); - } + await delayAsPromise(2000); + updateWazuhNotReadyYet(''); return Promise.resolve('Wazuh is ready'); } catch (error) { throw new Error('Server could not be recovered.'); @@ -279,7 +224,7 @@ export const restartNodeSelected = async ( // Always use cluster mode in v5.0+ (cluster mode by default) updateWazuhNotReadyYet(`Restarting ${selectedNode}, please wait.`); await restartNode(selectedNode); - return await makePing(updateWazuhNotReadyYet, true); + return await makePing(updateWazuhNotReadyYet); } catch (error) { throw error; } diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 8a6db7bfd1..fda4fc4724 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -420,49 +420,6 @@ export class WazuhApiCtrl { return false; } - /** - * Check main Wazuh daemons status - * @param {*} context Endpoint context - * @param {*} api API entry stored in .wazuh - * @param {*} path Optional. Wazuh API target path. - */ - async checkDaemons(context, api, path) { - try { - const response = await context.wazuh.api.client.asInternalUser.request( - 'GET', - '/manager/status', - {}, - { apiHostID: api.id }, - ); - - const daemons = - ((((response || {}).data || {}).data || {}).affected_items || [])[0] || - {}; - - const wazuhdbExists = typeof daemons['wazuh-db'] !== 'undefined'; - - const execd = daemons['wazuh-execd'] === 'running'; - const modulesd = daemons['wazuh-modulesd'] === 'running'; - const wazuhdb = wazuhdbExists ? daemons['wazuh-db'] === 'running' : true; - const clusterd = daemons['wazuh-clusterd'] === 'running'; - - const isValid = execd && modulesd && wazuhdb && clusterd; - - isValid && context.wazuh.logger.debug('Wazuh is ready'); - - if (path === '/ping') { - return { isValid }; - } - - if (!isValid) { - throw new Error('Server not ready yet'); - } - } catch (error) { - context.wazuh.logger.error(error.message || error); - return Promise.reject(error); - } - } - sleep(timeMs) { // eslint-disable-next-line return new Promise((resolve, reject) => { From fdef4702bc11a12dc0a411f57dbe6216bdc73792 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 14:46:23 -0500 Subject: [PATCH 35/54] refactor: remove isClusterMode parameter from dashboard components - Eliminated the isClusterMode parameter from DashboardStatistics and DashboardTabsPanels components to simplify the code. - Updated related functions to reflect the removal of the parameter, enhancing maintainability and clarity in the dashboard analysis engine. --- .../dashboards/dashboardTabsPanels.tsx | 3 --- .../dashboards/dashboard_analysis_engine.tsx | 7 +------ .../dashboards/dashboard_panels_analysis_engine.ts | 1 - .../components/management/configuration/utils/wz-fetch.js | 1 - plugins/main/public/utils/statistics-fields.test.tsx | 8 ++------ 5 files changed, 3 insertions(+), 17 deletions(-) diff --git a/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboardTabsPanels.tsx b/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboardTabsPanels.tsx index 54d3c26b9f..46db86022d 100644 --- a/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboardTabsPanels.tsx +++ b/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboardTabsPanels.tsx @@ -39,7 +39,6 @@ const SearchBar = getPlugins().data.ui.SearchBar; interface DashboardTabsPanelsProps { selectedTab: string; loadingNode: boolean; - isClusterMode: boolean; clusterNodes: any[]; clusterNodeSelected: any; onSelectNode: (event: any) => void; @@ -48,7 +47,6 @@ interface DashboardTabsPanelsProps { export const DashboardTabsPanels = ({ selectedTab, loadingNode, - isClusterMode, clusterNodes, clusterNodeSelected, onSelectNode, @@ -205,7 +203,6 @@ export const DashboardTabsPanels = ({ )} {selectedTab === 'analysisd' && !loadingNode && ( = ({ - isClusterMode, indexPatternId, filters, searchBarProps, @@ -30,10 +28,7 @@ const DashboardStatistics: React.FC = ({ { export const getDashboardPanelsAnalysisEngine = ( indexPatternId: string, - isClusterMode: boolean, ): { [panelId: string]: DashboardPanelState< EmbeddableInput & { [k: string]: unknown } diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index a86e5d6c20..569f9a28ce 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -221,7 +221,6 @@ export const restartNodeSelected = async ( updateWazuhNotReadyYet, ) => { try { - // Always use cluster mode in v5.0+ (cluster mode by default) updateWazuhNotReadyYet(`Restarting ${selectedNode}, please wait.`); await restartNode(selectedNode); return await makePing(updateWazuhNotReadyYet); diff --git a/plugins/main/public/utils/statistics-fields.test.tsx b/plugins/main/public/utils/statistics-fields.test.tsx index de3001217e..e191b9a4b5 100644 --- a/plugins/main/public/utils/statistics-fields.test.tsx +++ b/plugins/main/public/utils/statistics-fields.test.tsx @@ -10,9 +10,7 @@ test('Test statistics panels in analysis engine with cluster mode', () => { expect( compareColumnsValue( FieldsStatistics, - idExtractor( - getDashboardPanelsAnalysisEngine(INDEX_PATTERN_STATISTICS, true), - ), + idExtractor(getDashboardPanelsAnalysisEngine(INDEX_PATTERN_STATISTICS)), ), ).toBe(true); }); @@ -21,9 +19,7 @@ test('Test statistics panels in analysis engine with disabled cluster mode', () expect( compareColumnsValue( FieldsStatistics, - idExtractor( - getDashboardPanelsAnalysisEngine(INDEX_PATTERN_STATISTICS, false), - ), + idExtractor(getDashboardPanelsAnalysisEngine(INDEX_PATTERN_STATISTICS)), ), ).toBe(true); }); From e82b9c17c123b2ff11578f7844e7e7b79577dde0 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 14:49:23 -0500 Subject: [PATCH 36/54] refactor: remove updateClusterEnabled action and related logic - Eliminated the updateClusterEnabled action from statusActions and its usage in the WzStatusOverview component, as cluster mode is always enabled in version 5.0 and above. - This change simplifies the code and enhances maintainability by removing unnecessary complexity related to cluster status management. --- .../management/status/status-overview.js | 9 -------- .../public/redux/actions/statusActions.js | 23 +++++++------------ 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/status/status-overview.js b/plugins/main/public/controllers/management/components/management/status/status-overview.js index b6bafaf5a7..649ba54bef 100644 --- a/plugins/main/public/controllers/management/components/management/status/status-overview.js +++ b/plugins/main/public/controllers/management/components/management/status/status-overview.js @@ -31,7 +31,6 @@ import { updateStats, updateNodeInfo, updateAgentInfo, - updateClusterEnabled, cleanInfo, } from '../../../../../redux/actions/statusActions'; import StatusHandler from './utils/status-handler'; @@ -115,11 +114,6 @@ export class WzStatusOverview extends Component { agentsSynced: isNaN(agentsSyncedCoverage) ? 0 : agentsSyncedCoverage, agentsCoverage: isNaN(agentsActiveCoverage) ? 0 : agentsActiveCoverage, }); - - // Cluster is always enabled in v5.0+ (cluster by default) - this.props.updateClusterEnabled(true); - - // Cluster is always enabled and running in v5.0+ (cluster by default) { const nodes = await this.statusHandler.clusterNodes(); const listNodes = nodes.data.data.affected_items; @@ -229,9 +223,6 @@ const mapDispatchToProps = dispatch => { updateStats: stats => dispatch(updateStats(stats)), updateNodeInfo: nodeInfo => dispatch(updateNodeInfo(nodeInfo)), updateAgentInfo: agentInfo => dispatch(updateAgentInfo(agentInfo)), - updateClusterEnabled: clusterEnabled => - dispatch(updateClusterEnabled(clusterEnabled)), - cleanInfo: () => dispatch(cleanInfo()), }; }; diff --git a/plugins/main/public/redux/actions/statusActions.js b/plugins/main/public/redux/actions/statusActions.js index a5ad8f6f69..59621768ed 100644 --- a/plugins/main/public/redux/actions/statusActions.js +++ b/plugins/main/public/redux/actions/statusActions.js @@ -17,61 +17,54 @@ export const updateLoadingStatus = loading => { return { type: 'UPDATE_LOADING_STATUS', - status: loading + status: loading, }; }; export const updateListNodes = listNodes => { return { type: 'UPDATE_LIST_NODES', - listNodes: listNodes + listNodes: listNodes, }; }; export const updateSelectedNode = selectedNode => { return { type: 'UPDATE_SELECTED_NODE', - selectedNode: selectedNode + selectedNode: selectedNode, }; }; export const updateListDaemons = listDaemons => { return { type: 'UPDATE_LIST_DAEMONS', - listDaemons: listDaemons + listDaemons: listDaemons, }; }; export const updateStats = stats => { return { type: 'UPDATE_STATS', - stats: stats + stats: stats, }; }; export const updateNodeInfo = nodeInfo => { return { type: 'UPDATE_NODE_INFO', - nodeInfo: nodeInfo + nodeInfo: nodeInfo, }; }; export const updateAgentInfo = agentInfo => { return { type: 'UPDATE_AGENT_INFO', - agentInfo: agentInfo - }; -}; - -export const updateClusterEnabled = status => { - return { - type: 'UPDATE_CLUSTER_ENABLED', - clusterEnabled: status + agentInfo: agentInfo, }; }; export const cleanInfo = () => { return { - type: 'CLEAN_INFO' + type: 'CLEAN_INFO', }; }; From 8bbc133f5af977588d94c07254e13ee83872fb23 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 14:51:48 -0500 Subject: [PATCH 37/54] refactor: simplify URL construction in queryConfig function - Streamlined the URL construction logic in the queryConfig function by removing unnecessary conditions related to the agentId and node parameters. - This change enhances code clarity and maintainability in the configuration fetching process. --- plugins/main/public/react-services/query-config.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/main/public/react-services/query-config.js b/plugins/main/public/react-services/query-config.js index b9315f9e4b..3b3b051d06 100644 --- a/plugins/main/public/react-services/query-config.js +++ b/plugins/main/public/react-services/query-config.js @@ -42,11 +42,10 @@ export const queryConfig = async (agentId, sections, node = false) => { throw new Error('Invalid section'); } try { - const url = node - ? `/cluster/${node}/configuration/${component}/${configuration}` - : agentId === '000' - ? `/manager/configuration/${component}/${configuration}` - : `/agents/${agentId}/configuration/${component}/${configuration}`; + const url = + agentId === '000' + ? `/cluster/${node}/configuration/${component}/${configuration}` + : `/agents/${agentId}/configuration/${component}/${configuration}`; const partialResult = await WzRequest.apiReq('GET', url, {}); result[`${component}-${configuration}`] = partialResult.data.data; From 634f78a515a40472fd3d3c027fcc5283a7495dca Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Wed, 10 Sep 2025 15:02:09 -0500 Subject: [PATCH 38/54] refactor: update filter creation documentation for clarity - Revised the documentation for the filter creation function to specify that it is for cluster queries, removing the mention of manager queries for better accuracy. - Removed the isCluster parameter from the documentation, as it is no longer relevant in version 5.0 and above, enhancing clarity and maintainability. --- plugins/main/public/utils/filter-handler.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/plugins/main/public/utils/filter-handler.js b/plugins/main/public/utils/filter-handler.js index 67149c86b3..4b85c35a32 100644 --- a/plugins/main/public/utils/filter-handler.js +++ b/plugins/main/public/utils/filter-handler.js @@ -97,9 +97,8 @@ export class FilterHandler { return result; } /** - * This function creates a filter for cluster/manager queries. In v5.0+ always uses cluster.name (cluster by default) + * This function creates a filter for cluster queries. In v5.0+ always uses cluster.name (cluster by default) * @param {*} manager - * @param {*} isCluster - Always true in v5.0+ (kept for compatibility) * @param {*} fixedKey * @returns */ From 00676053b539ad7feef179519281fad6be3b4c1c Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Thu, 11 Sep 2025 09:34:55 -0500 Subject: [PATCH 39/54] refactor: streamline cluster node selection logic in configuration components - Simplified the logic for selecting the master node in both the WzEditConfiguration and WzRefreshClusterInfoButton components by directly finding the master node in the affected items array. - Removed the intermediate variable for masterNode to enhance code clarity and maintainability. --- .../configuration/edit-configuration/edit-configuration.js | 6 ++---- .../util-components/refresh-cluster-info-button.js | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js b/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js index d28478402a..937f78f1a8 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js +++ b/plugins/main/public/controllers/management/components/management/configuration/edit-configuration/edit-configuration.js @@ -216,13 +216,11 @@ class WzEditConfiguration extends Component { nodes.data.data.affected_items.find( node => node.name === this.props.clusterNodeSelected, ); - const masterNode = nodes.data.data.affected_items.find( - node => node.type === 'master', - ); this.props.updateClusterNodeSelected( existsClusterCurrentNodeSelected ? existsClusterCurrentNodeSelected.name - : masterNode?.name || nodes.data.data.affected_items[0]?.name, + : nodes.data.data.affected_items.find(node => node.type === 'master') + .name, ); this.props.updateConfigurationSection( 'edit-configuration', diff --git a/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js b/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js index 99bfbbdaf0..bd82f8de56 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js +++ b/plugins/main/public/controllers/management/components/management/configuration/util-components/refresh-cluster-info-button.js @@ -42,13 +42,11 @@ class WzRefreshClusterInfoButton extends Component { nodes.data.data.affected_items.find( node => node.name === this.props.clusterNodeSelected, ); - const masterNode = nodes.data.data.affected_items.find( - node => node.type === 'master', - ); this.props.updateClusterNodeSelected( existsClusterCurrentNodeSelected ? existsClusterCurrentNodeSelected.name - : masterNode?.name || nodes.data.data.affected_items[0]?.name, + : nodes.data.data.affected_items.find(node => node.type === 'master') + .name, ); } catch (error) { // do nothing if it isn't a cluster From 59f86d5f48d359f4b933ba02c0960cf941615ba4 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Thu, 11 Sep 2025 09:48:08 -0500 Subject: [PATCH 40/54] refactor: remove status from cluster info and streamline API connection logic - Eliminated the status property from the cluster_info object in the Wazuh API and related components, as cluster mode is always enabled in version 5.0 and above. - Updated the API connection logic to directly use the cluster name, enhancing clarity and maintainability. --- plugins/main/public/components/settings/api/api-table.js | 6 +++--- plugins/main/server/controllers/wazuh-api.ts | 4 ++-- plugins/wazuh-core/server/services/manage-hosts.ts | 6 ------ 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/plugins/main/public/components/settings/api/api-table.js b/plugins/main/public/components/settings/api/api-table.js index 144bda28ba..24309c254d 100644 --- a/plugins/main/public/components/settings/api/api-table.js +++ b/plugins/main/public/components/settings/api/api-table.js @@ -199,14 +199,14 @@ export const ApiTable = compose(withErrorBoundary)( try { await this.checkManager(APIconnection, true); const { cluster_info, id } = APIconnection; - const { manager, cluster, status } = cluster_info; + const { cluster } = cluster_info; // Check the connection before set as default AppState.setClusterInfo(cluster_info); - const clusterEnabled = status === 'disabled'; + // In v5.0+ cluster is always enabled (cluster by default) AppState.setCurrentAPI( JSON.stringify({ - name: clusterEnabled ? manager : cluster, + name: cluster, id: id, }), ); diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index fda4fc4724..74f97ba6f5 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -157,7 +157,7 @@ export class WazuhApiCtrl { // If we have a valid response from the Wazuh API try { - const { status, manager, node, cluster } = + const { manager, node, cluster } = await context.wazuh_core.manageHosts.getRegistryDataByHost( apiHostData, { @@ -165,7 +165,7 @@ export class WazuhApiCtrl { }, ); - api.cluster_info = { status, manager, node, cluster }; + api.cluster_info = { manager, node, cluster }; return response.ok({ body: { diff --git a/plugins/wazuh-core/server/services/manage-hosts.ts b/plugins/wazuh-core/server/services/manage-hosts.ts index b63bfa45d2..aac9c1435a 100644 --- a/plugins/wazuh-core/server/services/manage-hosts.ts +++ b/plugins/wazuh-core/server/services/manage-hosts.ts @@ -27,7 +27,6 @@ export interface IAPIHost { interface IAPIHostRegistry { manager: string | null; node: string | null; - status: string; cluster: string; allow_run_as: API_USER_STATUS_RUN_AS; } @@ -189,7 +188,6 @@ export class ManageHosts { let manager = null, node = null, - status = 'disabled', cluster = 'Disabled', allow_run_as = API_USER_STATUS_RUN_AS.UNABLE_TO_CHECK; @@ -227,9 +225,6 @@ export class ManageHosts { } } - // In v5.0+ cluster is always enabled (cluster by default) - status = 'enabled'; - const responseClusterLocal = await this.serverAPIClient.asInternalUser.request( 'GET', @@ -251,7 +246,6 @@ export class ManageHosts { const data = { manager, node, - status, cluster, allow_run_as, }; From c823d777dc1971acb99afc019401593aec3b24c1 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Thu, 11 Sep 2025 11:08:46 -0500 Subject: [PATCH 41/54] refactor: remove redundant comments regarding cluster mode in various components - Eliminated comments indicating that cluster mode is always enabled in version 5.0 and above from multiple files, enhancing code clarity and maintainability. - Updated documentation and comments to reflect the current state of the code without unnecessary repetition. --- .../pattern/pattern-data-source-filter-manager.ts | 3 +-- .../components/fim_events_table/lib/get_fim_alerts.ts | 1 - .../welcome/components/mitre_top/lib/get_mitre_counts.ts | 1 - .../register-agent/services/register-agent-services.tsx | 6 ------ .../components/requirement-flyout/requirement-flyout.tsx | 1 - plugins/main/public/components/settings/api/api-table.js | 1 - .../management/configuration/configuration-switch.js | 1 - .../components/management/configuration/utils/wz-fetch.js | 2 -- .../components/management/status/status-overview.js | 1 - .../components/last-alerts-stat/last-alerts-query.ts | 1 - .../components/last-alerts-stat/last-alerts-service.ts | 3 +-- plugins/main/public/utils/filter-handler.js | 3 +-- 12 files changed, 3 insertions(+), 21 deletions(-) diff --git a/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts b/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts index db1efd5cc5..0024985880 100644 --- a/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts +++ b/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts @@ -256,7 +256,7 @@ export class PatternDataSourceFilterManager } /** - * Return the filter when the cluster is enabled (always enabled in v5.0+) + * Return the cluster filter */ static getClusterManagerFilters( indexPatternId: string, @@ -264,7 +264,6 @@ export class PatternDataSourceFilterManager key?: string, ): tFilter[] { const filterHandler = new FilterHandler(); - // Cluster mode is always enabled in v5.0+ const managerFilter = filterHandler.managerQuery( AppState.getClusterInfo().cluster, key, diff --git a/plugins/main/public/components/common/welcome/components/fim_events_table/lib/get_fim_alerts.ts b/plugins/main/public/components/common/welcome/components/fim_events_table/lib/get_fim_alerts.ts index 7a20c6fdf4..1009505190 100644 --- a/plugins/main/public/components/common/welcome/components/fim_events_table/lib/get_fim_alerts.ts +++ b/plugins/main/public/components/common/welcome/components/fim_events_table/lib/get_fim_alerts.ts @@ -42,7 +42,6 @@ function createFilters(agentId, indexPattern) { export function getWazuhFilter() { const clusterInfo = AppState.getClusterInfo(); - // Always use cluster.name in v5.0+ (cluster mode by default) const wazuhFilter = { name: 'cluster.name', value: clusterInfo.cluster, diff --git a/plugins/main/public/components/common/welcome/components/mitre_top/lib/get_mitre_counts.ts b/plugins/main/public/components/common/welcome/components/mitre_top/lib/get_mitre_counts.ts index 7a47eb5d1b..33d5b4209f 100644 --- a/plugins/main/public/components/common/welcome/components/mitre_top/lib/get_mitre_counts.ts +++ b/plugins/main/public/components/common/welcome/components/mitre_top/lib/get_mitre_counts.ts @@ -51,7 +51,6 @@ function createExistsFilter(indexPattern) { function getWazuhFilter() { const clusterInfo = AppState.getClusterInfo(); - // Always use cluster.name in v5.0+ (cluster mode by default) const wazuhFilter = { name: 'cluster.name', value: clusterInfo.cluster, diff --git a/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx b/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx index 20f22a76da..0405140096 100644 --- a/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx +++ b/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx @@ -28,7 +28,6 @@ export type ServerAddressOptions = { nodetype: string; }; - /** * Get the remote configuration from api */ @@ -40,7 +39,6 @@ async function getRemoteConfiguration(nodeName: string): Promise { }; try { - // Always use cluster endpoints in v5.0+ (cluster mode by default) const result = await WzRequest.apiReq( 'GET', `/cluster/${nodeName}/configuration/request/remote`, @@ -79,7 +77,6 @@ async function getRemoteConfiguration(nodeName: string): Promise { * @returns */ async function getAuthConfiguration(node: string) { - // Always use cluster endpoints in v5.0+ (cluster mode by default) const authConfigUrl = `/cluster/${node}/configuration/auth/auth`; const result = await WzRequest.apiReq('GET', authConfigUrl, {}); const auth = result?.data?.data?.affected_items?.[0]; @@ -111,7 +108,6 @@ async function getConnectionConfig( const nodeIp = nodeSelected?.value; if (!defaultServerAddress) { if (nodeSelected.nodetype !== 'custom') { - // Always use cluster mode in v5.0+ (cluster mode by default) const remoteConfig = await getRemoteConfiguration(nodeName); return { serverAddress: nodeIp, @@ -189,7 +185,6 @@ export const parseNodesInOptions = ( export const fetchClusterNodesOptions = async (): Promise< ServerAddressOptions[] > => { - // Always use cluster mode in v5.0+ (cluster mode by default) const nodes = await getNodeIPs(); return parseNodesInOptions(nodes); }; @@ -211,7 +206,6 @@ export const getMasterNode = ( export const getMasterConfiguration = async () => { const nodes = await fetchClusterNodesOptions(); const masterNode = getMasterNode(nodes); - // Always use cluster mode in v5.0+ (cluster mode by default) const remote = await getRemoteConfiguration(masterNode[0].label); const auth = await getAuthConfiguration(masterNode[0].label); return { diff --git a/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx b/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx index d7f82dd307..b8cd06ed45 100644 --- a/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx +++ b/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx @@ -186,7 +186,6 @@ export const RequirementFlyout = connect(mapStateToProps)( renderBody() { const { currentRequirement } = this.props; const requirementImplicitFilter = {}; - // Always use cluster.name in v5.0+ (cluster mode by default) const clusterFilter = { 'cluster.name': AppState.getClusterInfo().cluster, }; diff --git a/plugins/main/public/components/settings/api/api-table.js b/plugins/main/public/components/settings/api/api-table.js index 24309c254d..62c4e23cc7 100644 --- a/plugins/main/public/components/settings/api/api-table.js +++ b/plugins/main/public/components/settings/api/api-table.js @@ -203,7 +203,6 @@ export const ApiTable = compose(withErrorBoundary)( // Check the connection before set as default AppState.setClusterInfo(cluster_info); - // In v5.0+ cluster is always enabled (cluster by default) AppState.setCurrentAPI( JSON.stringify({ name: cluster, diff --git a/plugins/main/public/controllers/management/components/management/configuration/configuration-switch.js b/plugins/main/public/controllers/management/components/management/configuration/configuration-switch.js index d4ee07f680..0ed199a443 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/configuration-switch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/configuration-switch.js @@ -151,7 +151,6 @@ class WzConfigurationSwitch extends Component { updateClusterInformation = async (/** @type {string} */ context) => { try { - // Always cluster in v5.0+ (cluster by default) await this.handleClusterNodes(); } catch (error) { // Handle cluster errors diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index 569f9a28ce..ecdf179bc0 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -187,7 +187,6 @@ export const makePing = async (updateWazuhNotReadyYet, tries = 30) => { */ export const fetchFile = async selectedNode => { try { - // Always use cluster endpoints in v5.0+ (cluster mode by default) const data = await WzRequest.apiReq( 'GET', `/cluster/${selectedNode}/configuration`, @@ -316,7 +315,6 @@ export const restartNode = async node => { export const saveConfiguration = async (selectedNode, xml) => { try { - // Always use cluster mode in v5.0+ (cluster mode by default) await saveFileCluster(xml, selectedNode); } catch (error) { throw error; diff --git a/plugins/main/public/controllers/management/components/management/status/status-overview.js b/plugins/main/public/controllers/management/components/management/status/status-overview.js index 649ba54bef..47607121aa 100644 --- a/plugins/main/public/controllers/management/components/management/status/status-overview.js +++ b/plugins/main/public/controllers/management/components/management/status/status-overview.js @@ -92,7 +92,6 @@ export class WzStatusOverview extends Component { try { this.props.updateLoadingStatus(true); - // In v5.0+ cluster is always enabled and running (cluster by default) const agentsCountByManagerNodes = ( await this.statusHandler.clusterAgentsCount() )?.data?.data; diff --git a/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-query.ts b/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-query.ts index 708a02ded4..ee5bb9989f 100644 --- a/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-query.ts +++ b/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-query.ts @@ -6,7 +6,6 @@ export const getLastAlertsQuery = ( maxRuleLevel?: number; }, ) => { - // Always use cluster.name in v5.0+ (cluster mode by default) const clusterField = 'cluster.name'; return { indexPattern: currentIndexPattern, diff --git a/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-service.ts b/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-service.ts index bae78c4cd3..2db3b21037 100644 --- a/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-service.ts +++ b/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-service.ts @@ -24,7 +24,6 @@ export const getLast24HoursAlerts = async ( AppState.getCurrentPattern() || getWazuhCorePlugin().configuration.getSettingValue('pattern'), ); - // Always use cluster name in v5.0+ (cluster mode by default) const clusterValue = AppState.getClusterInfo().cluster; const lastAlertsQuery = getLastAlertsQuery( @@ -38,7 +37,7 @@ export const getLast24HoursAlerts = async ( return { count, cluster: { - field: 'cluster.name', // Always cluster.name in v5.0+ + field: 'cluster.name', name: clusterValue, }, indexPatternId: currentIndexPattern.id, diff --git a/plugins/main/public/utils/filter-handler.js b/plugins/main/public/utils/filter-handler.js index 4b85c35a32..434a7de791 100644 --- a/plugins/main/public/utils/filter-handler.js +++ b/plugins/main/public/utils/filter-handler.js @@ -97,13 +97,12 @@ export class FilterHandler { return result; } /** - * This function creates a filter for cluster queries. In v5.0+ always uses cluster.name (cluster by default) + * This function creates a filter for cluster queries * @param {*} manager * @param {*} fixedKey * @returns */ managerQuery(manager, fixedKey = undefined) { - // Always use cluster.name in v5.0+ (cluster mode by default) const metaKey = fixedKey ? fixedKey : 'cluster.name'; const result = this.base(); result.meta.key = metaKey; From c5b32591a1ef0d2e972585c357bd0bc8b86462c3 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Thu, 11 Sep 2025 11:13:44 -0500 Subject: [PATCH 42/54] chore: set cluster mode as default and remove manager-related logic - Enabled cluster mode by default for all Wazuh installations, including single-node deployments, and updated RBAC permissions to use `cluster:*` actions. - Removed all logic related to manager mode, streamlining the application and enhancing maintainability. [#7688](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7688) --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee3b2af0f9..6e4b25fa7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,12 +12,13 @@ All notable changes to the Wazuh app project will be documented in this file. ### Changed -- Cluster mode is now enabled by default. Removed all conditional logic between cluster and manager modes. All Wazuh installations now operate in cluster mode, including single-node deployments. Updated all filters to consistently use `cluster.name` instead of `manager.name`, unified API endpoints to cluster paths, simplified UI components by removing cluster/manager toggles, updated RBAC permissions from `manager:*` actions to `cluster:*` actions, removed `/cluster/status` endpoint dependencies, and eliminated cluster-disabled component. Sample data generation now defaults to cluster-aware configuration [#7688](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7688) +- Set cluster mode as default for all Wazuh installations, including single-node deployments. Updated RBAC permissions to `cluster:*` actions [#7688](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7688) - Rework SCA modules visualizations, global detail for all agents without pinning, replaced `/sca` endpoint with `wazuh-states-sca-*` index pattern, added sample data section [#7578](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7578) - Split the FIM registry inventory into 2 index patterns and change some fields in the FIM files and registries sample data [#7604](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7604) ### Removed +- Removed logic related to manager in favor to cluster management [#7688](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7688) - Removed the monitoring and statistics jobs in the backend side [#7597](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7597) - Removed the settings related to monitoring and statistics job from the configuration [#7597](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7597) - Removed prompt related to statistic job is disabled in Statistics app [#7597](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7597) From f3d1a0bd15b3987881b243402b9728c613fdd1eb Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Fri, 12 Sep 2025 10:02:05 -0500 Subject: [PATCH 43/54] feat: implement daemons status check for cluster endpoints - Added a new function to check the status of daemons using cluster endpoints, enhancing the monitoring capabilities of the Wazuh API. - Updated the Wazuh API controller to return the daemons status in response to requests, improving the overall functionality and reliability of the system. - Adjusted the ping logic to incorporate the new daemons status check, ensuring that the system accurately reflects the readiness of the Wazuh services. --- .../configuration/cluster/cluster.js | 1 - .../configuration/utils/wz-fetch.js | 65 ++++++++++++++++++- plugins/main/server/controllers/wazuh-api.ts | 60 ++++++++++++++++- 3 files changed, 123 insertions(+), 3 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.js b/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.js index 58fd33c0d4..a2afa0e6a3 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.js +++ b/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.js @@ -25,7 +25,6 @@ import { compose } from 'redux'; import { webDocumentationLink } from '../../../../../../../common/services/web_documentation'; const mainSettings = [ - { field: 'disabled', label: 'Cluster status' }, { field: 'name', label: 'Cluster name' }, { field: 'node_name', label: 'Node name' }, { field: 'node_type', label: 'Node type' }, diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index ecdf179bc0..6ba9d4440c 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -165,14 +165,77 @@ export const handleError = async ( } }; +/** + * Check daemons status using cluster endpoints + * @returns {Promise} + */ +export const checkDaemons = async () => { + try { + // First get the local node info + const localNodeInfo = await WzRequest.apiReq( + 'GET', + '/cluster/local/info', + {}, + ); + const nodeId = localNodeInfo.data.data.affected_items[0].node; + + // Then check daemons status for this node + const daemonsStatus = await WzRequest.apiReq( + 'GET', + `/cluster/${nodeId}/status`, + {}, + { checkCurrentApiIsUp: false }, + ); + const daemons = + ((((daemonsStatus || {}).data || {}).data || {}).affected_items || + [])[0] || {}; + + const wazuhdbExists = typeof daemons['wazuh-db'] !== 'undefined'; + + const execd = daemons['wazuh-execd'] === 'running'; + const modulesd = daemons['wazuh-modulesd'] === 'running'; + const wazuhdb = wazuhdbExists ? daemons['wazuh-db'] === 'running' : true; + + // In cluster by default, always check clusterd daemon + const clusterd = daemons['wazuh-clusterd'] === 'running'; + + const isValid = execd && modulesd && wazuhdb && clusterd; + + if (isValid) { + return { isValid }; + } else { + console.warn('Server not ready yet'); + } + } catch (error) { + throw error; + } +}; + /** * Make ping to Wazuh API * @param updateWazuhNotReadyYet - * @param {number} [tries=10] Tries + * @param {number} [tries=30] Tries * @return {Promise} */ export const makePing = async (updateWazuhNotReadyYet, tries = 30) => { try { + let isValid = false; + while (tries--) { + await delayAsPromise(2000); + try { + const daemonCheck = await checkDaemons(); + isValid = daemonCheck?.isValid; + if (isValid) { + updateWazuhNotReadyYet(''); + break; + } + } catch (error) { + console.error(error); + } + } + if (!isValid) { + throw new Error('Not recovered'); + } await delayAsPromise(2000); updateWazuhNotReadyYet(''); return Promise.resolve('Wazuh is ready'); diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 74f97ba6f5..519783ffea 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -529,7 +529,9 @@ export class WazuhApiCtrl { if (path === '/ping') { try { const check = await this.checkDaemons(context, api, path); - return check; + return response.ok({ + body: check, + }); } catch (error) { const isDown = (error || {}).code === 'ECONNREFUSED'; if (!isDown) { @@ -955,4 +957,60 @@ export class WazuhApiCtrl { ); } } + + /** + * Check daemons status using cluster endpoints + * @param context Request context + * @param api API configuration + * @param path Request path + * @returns Promise with isValid status + */ + async checkDaemons(context: RequestHandlerContext, api: any, path: string) { + try { + // First get the local node info + const localNodeInfo = + await context.wazuh.api.client.asCurrentUser.request( + 'GET', + '/cluster/local/info', + {}, + ); + + const nodeId = localNodeInfo.data.data.affected_items[0].node; + + // Then check daemons status for this node + const daemonsStatus = + await context.wazuh.api.client.asCurrentUser.request( + 'GET', + `/cluster/${nodeId}/status`, + {}, + ); + + const daemons = + ((((daemonsStatus || {}).data || {}).data || {}).affected_items || + [])[0] || {}; + + const wazuhdbExists = typeof daemons['wazuh-db'] !== 'undefined'; + + const execd = daemons['wazuh-execd'] === 'running'; + const modulesd = daemons['wazuh-modulesd'] === 'running'; + const wazuhdb = wazuhdbExists ? daemons['wazuh-db'] === 'running' : true; + + // In cluster by default, always check clusterd daemon + const clusterd = daemons['wazuh-clusterd'] === 'running'; + + const isValid = execd && modulesd && wazuhdb && clusterd; + + if (isValid) { + return { isValid }; + } else { + context.wazuh.logger.warn('Server not ready yet'); + return { isValid: false }; + } + } catch (error) { + context.wazuh.logger.error( + `Error checking daemons: ${error.message || error}`, + ); + return { isValid: false }; + } + } } From 0012b6e6dc19d9da551cdea40327aeaf6d83c4c6 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Fri, 12 Sep 2025 14:15:02 -0500 Subject: [PATCH 44/54] refactor: update cluster test cases to reflect changes in cluster name - Replaced instances of 'Cluster status' with 'Cluster name' in the test cases to align with recent updates in the cluster configuration. - Updated snapshot files to reflect the new structure and values, ensuring accurate testing of the cluster settings component. --- .../__snapshots__/cluster.test.js.snap | 70 ------------------- .../configuration/cluster/cluster.test.js | 10 +-- 2 files changed, 5 insertions(+), 75 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/configuration/cluster/__snapshots__/cluster.test.js.snap b/plugins/main/public/controllers/management/components/management/configuration/cluster/__snapshots__/cluster.test.js.snap index 3238151d03..65efafdaa7 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/cluster/__snapshots__/cluster.test.js.snap +++ b/plugins/main/public/controllers/management/components/management/configuration/cluster/__snapshots__/cluster.test.js.snap @@ -88,41 +88,6 @@ exports[`Cluster settings should render the cluster settings 1`] = `
-
-
-
- Cluster status -
-
-
-
-
- -
-
-
-
-
@@ -464,41 +429,6 @@ exports[`Cluster settings should render the cluster settings with HAProxy helper
-
-
-
- Cluster status -
-
-
-
-
- -
-
-
-
-
diff --git a/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.test.js b/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.test.js index 26fb86512f..c1619f91e6 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.test.js +++ b/plugins/main/public/controllers/management/components/management/configuration/cluster/cluster.test.js @@ -56,8 +56,8 @@ describe('Cluster settings', () => { expect(container).toMatchSnapshot(); - expect(getByText('Cluster status')).toBeInTheDocument(); - expect(getByTestId('cluster-status').value).toBe('enabled'); + expect(getByText('Cluster name')).toBeInTheDocument(); + expect(getByTestId('cluster-name').value).toBe('wazuh1'); expect(queryByText('HAProxy settings')).toBeFalsy(); }); @@ -68,8 +68,8 @@ describe('Cluster settings', () => { expect(container).toMatchSnapshot(); - expect(getByText('Cluster status')).toBeInTheDocument(); - expect(getByTestId('cluster-status').value).toBe('enabled'); + expect(getByText('Cluster name')).toBeInTheDocument(); + expect(getByTestId('cluster-name').value).toBe('wazuh1'); expect(getByText('HAProxy settings')).toBeInTheDocument(); expect(getByTestId('haproxy-status').value).toBe('enabled'); expect(getByTestId('user').value).toBe( @@ -86,7 +86,7 @@ describe('Cluster settings', () => { expect(container).toMatchSnapshot(); expect(getByText('Configuration not available')).toBeInTheDocument(); - expect(queryByText('Cluster status')).toBeFalsy(); + expect(queryByText('Cluster name')).toBeFalsy(); expect(queryByText('HAProxy settings')).toBeFalsy(); }); }); From 9bc08763d5130c2f0405e5b47396c6bca3a2bb79 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Mon, 15 Sep 2025 08:32:15 -0500 Subject: [PATCH 45/54] refactor: remove unnecessary delay in Wazuh readiness check - Eliminated the 2-second delay and the updateWazuhNotReadyYet call from the makePing function, streamlining the Wazuh readiness check process. - This change improves the responsiveness of the system when determining Wazuh's operational status. --- .../components/management/configuration/utils/wz-fetch.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index a9e33e9cb7..f0a6e1c654 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -235,8 +235,6 @@ export const makePing = async (updateWazuhNotReadyYet, tries = 30) => { if (!isValid) { throw new Error('Not recovered'); } - await delayAsPromise(2000); - updateWazuhNotReadyYet(''); return Promise.resolve('Wazuh is ready'); } catch (error) { throw new Error('Server could not be recovered.'); From bfddb055f5ad18847b29f7a57ee27e5e8071d232 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Mon, 15 Sep 2025 09:22:07 -0500 Subject: [PATCH 46/54] refactor: enhance cluster node selection logic in configuration overview - Updated the WzConfigurationOverview component to conditionally render the cluster selection based on the selected cluster node. - Improved the permissions logic to ensure it only applies when a cluster node is selected, enhancing the component's responsiveness and usability. --- .../management/configuration/configuration-overview.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/configuration/configuration-overview.js b/plugins/main/public/controllers/management/components/management/configuration/configuration-overview.js index 04989eaac6..8d3f572811 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/configuration-overview.js +++ b/plugins/main/public/controllers/management/components/management/configuration/configuration-overview.js @@ -116,9 +116,9 @@ class WzConfigurationOverview extends Component { - {this.props.clusterNodes && this.props.clusterNodes.length ? ( + {this.props.clusterNodes && + this.props.clusterNodes.length && + this.props.clusterNodeSelected ? ( @@ -183,6 +185,7 @@ class WzConfigurationOverview extends Component { const mapStateToProps = state => ({ clusterNodes: state.configurationReducers.clusterNodes, + clusterNodeSelected: state.configurationReducers.clusterNodeSelected, }); export default connect(mapStateToProps)(WzConfigurationOverview); From beb261542ea58121eb416cfa9f35e6fa01de80ed Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Mon, 15 Sep 2025 09:44:38 -0500 Subject: [PATCH 47/54] refactor: simplify reloadRuleset function by removing cluster status checks - Removed unnecessary checks for cluster status in the reloadRuleset function, streamlining the logic for reloading the analysis daemon. - Updated the reload endpoint to always use the cluster analysis endpoint, enhancing code clarity and maintainability. --- .../management/configuration/utils/wz-fetch.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index f0a6e1c654..d38869eee5 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -473,17 +473,9 @@ export const clusterNodes = async () => { */ export const reloadRuleset = async (nodes = []) => { try { - const clusterStatus = await WzRequest.apiReq('GET', `/cluster/status`, {}); - - const clusterData = ((clusterStatus || {}).data || {}).data || {}; - const isCluster = - clusterData.enabled === 'yes' && clusterData.running === 'yes'; - const nodesString = nodes.join(','); const nodes_param = nodesString ? `?nodes_list=${nodesString}` : ''; - const reloadEndpoint = isCluster - ? `/cluster/analysisd/reload${nodes_param}` - : `/manager/analysisd/reload${nodes_param}`; + const reloadEndpoint = `/cluster/analysisd/reload${nodes_param}`; const result = await WzRequest.apiReq('PUT', reloadEndpoint, {}); return result; From beeda7d9e755b44f188b70ac9a037df208aa0aa1 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Mon, 15 Sep 2025 09:55:40 -0500 Subject: [PATCH 48/54] refactor: remove unused getManagerNode function from register-agent-services - Deleted the getManagerNode function, which was responsible for fetching and parsing the manager node data, as it is no longer needed in the current implementation. - This change simplifies the codebase and improves maintainability by eliminating redundant functionality. --- .../services/register-agent-services.tsx | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx b/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx index 0405140096..03558a7913 100644 --- a/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx +++ b/plugins/main/public/components/endpoints-summary/register-agent/services/register-agent-services.tsx @@ -151,20 +151,6 @@ 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 From 0baad3ddbec04ebb5ec67b0c8386d1c7f3ba5b09 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Mon, 15 Sep 2025 09:59:14 -0500 Subject: [PATCH 49/54] refactor: remove unused checkVDIsEnabledManager function from module check - Deleted the checkVDIsEnabledManager function, which was responsible for checking the status of vulnerability detection modules, as it is no longer needed in the current implementation. - This change simplifies the codebase and improves maintainability by eliminating redundant functionality. --- .../common/components/check-module-enabled.tsx | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx b/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx index f04f92dfee..b545d9b15b 100644 --- a/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx +++ b/plugins/main/public/components/overview/vulnerabilities/common/components/check-module-enabled.tsx @@ -32,20 +32,6 @@ async function checkVDIsEnabledCluster() { return false; } -async function checkVDIsEnabledManager() { - const responseWmodules = await WzRequest.apiReq( - 'GET', - `/manager/configuration/wmodules/wmodules`, - {}, - ); - - const vdConfiguration = - responseWmodules.data.data?.affected_items?.[0]?.wmodules?.find( - ({ ['vulnerability-detection']: wmodule }) => wmodule, - ); - return vdConfiguration?.['vulnerability-detection']?.enabled === 'yes'; -} - export const ModuleEnabledCheck = () => { const [data, setData] = useState<{ enabled: boolean } | null>(null); const [userPermissionRequirements] = useUserPermissionsRequirements([ From cf035c898ede26c84bf281d25fc44384c507090b Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Mon, 15 Sep 2025 10:17:49 -0500 Subject: [PATCH 50/54] fix: update demo API endpoints in devtools initialization - Modified the demo string in the init function to include the new endpoint for cluster local info, ensuring accurate examples for users. - This change enhances the clarity of the demo output and improves the user experience when utilizing the devtools. --- plugins/main/public/components/tools/devtools/devtools-old.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/main/public/components/tools/devtools/devtools-old.tsx b/plugins/main/public/components/tools/devtools/devtools-old.tsx index fdde5a5374..ec489d7bf1 100644 --- a/plugins/main/public/components/tools/devtools/devtools-old.tsx +++ b/plugins/main/public/components/tools/devtools/devtools-old.tsx @@ -325,7 +325,7 @@ function init(editorInput, editorOutput) { const currentState = AppState.getCurrentDevTools(); if (!currentState) { const demoStr = - 'GET /agents?status=active\n\n# Example comment\n\n# You can use ? after the endpoint \n# in order to get suggestions \n# for your query params\n\nGET /manager/info\n\nPOST /agents\n' + + 'GET /agents?status=active\n\n# Example comment\n\n# You can use ? after the endpoint \n# in order to get suggestions \n# for your query params\n\nGET /cluster/local/info\n\nPOST /agents\n' + JSON.stringify({ name: 'NewAgent' }, null, 2) + '\n\nPUT /logtest\n' + JSON.stringify( From 10282b60ab67d8f50800935beb91ed765b7ba503 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Mon, 15 Sep 2025 10:41:58 -0500 Subject: [PATCH 51/54] refactor: remove restartManager function and related UI elements - Deleted the restartManager function from the status handler and its references in the WzStatusActionButtons component, as it is no longer needed in the current implementation. - Updated the UI to remove the restart manager button and associated modal logic, streamlining the component's functionality and improving maintainability. --- .../configuration/utils/wz-fetch.js | 23 ----------- .../management/status/actions-buttons-main.js | 41 +++---------------- .../management/status/utils/status-handler.js | 25 ----------- 3 files changed, 5 insertions(+), 84 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index d38869eee5..746b27d845 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -288,29 +288,6 @@ export const restartNodeSelected = async ( } }; -/** - * Restart manager (single-node API call) - * @returns {object|Promise} - */ -export const restartManager = async () => { - try { - const validationError = await WzRequest.apiReq( - 'GET', - `/manager/configuration/validation`, - {}, - ); - const isOk = validationError.status === 'OK'; - if (!isOk && validationError.detail) { - const str = validationError.detail; - throw new Error(str); - } - const result = await WzRequest.apiReq('PUT', `/manager/restart`, {}); - return result; - } catch (error) { - throw error; - } -}; - /** * Restart cluster * @returns {object|Promise} diff --git a/plugins/main/public/controllers/management/components/management/status/actions-buttons-main.js b/plugins/main/public/controllers/management/components/management/status/actions-buttons-main.js index 742e43aaed..6bcbb04cfb 100644 --- a/plugins/main/public/controllers/management/components/management/status/actions-buttons-main.js +++ b/plugins/main/public/controllers/management/components/management/status/actions-buttons-main.js @@ -90,31 +90,6 @@ class WzStatusActionButtons extends Component { } } - /** - * Restart manager - */ - async restartManager() { - this.setState({ isRestarting: true }); - try { - await this.statusHandler.restartManager(); - this.setState({ isRestarting: false }); - this.showToast('success', 'Restarting manager.', 3000); - } catch (error) { - this.setState({ isRestarting: false }); - const options = { - context: `${WzStatusActionButtons.name}.restartManager`, - level: UI_LOGGER_LEVELS.ERROR, - severity: UI_ERROR_SEVERITIES.BUSINESS, - error: { - error: error, - message: error.message || error, - title: `${error.name}: Error restarting manager`, - }, - }; - getErrorOrchestrator().handleError(options); - } - } - objToArr(obj) { const arr = []; for (const key in obj) arr.push({ key, value: obj[key] }); @@ -238,9 +213,10 @@ class WzStatusActionButtons extends Component { this.setState({ isModalVisible: true })} @@ -248,7 +224,6 @@ class WzStatusActionButtons extends Component { isLoading={this.state.isRestarting} > {clusterEnabled && 'Restart cluster'} - {!clusterEnabled && 'Restart manager'} ); @@ -258,17 +233,11 @@ class WzStatusActionButtons extends Component { modal = ( { if (clusterEnabled) { this.restartCluster(); - } else { - this.restartManager(); } this.setState({ isModalVisible: false }); }} diff --git a/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js b/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js index cabac02e8b..1dd817880d 100644 --- a/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js +++ b/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js @@ -150,29 +150,4 @@ export default class StatusHandler { throw error; } } - - /** - * Restart manager (single-node API call) - */ - static async restartManager() { - try { - const validationError = await WzRequest.apiReq( - 'GET', - `/manager/configuration/validation`, - {}, - ); - - const data = ((validationError || {}).data || {}).data || {}; - const isOk = data.status === 'OK'; - if (!isOk && Array.isArray(data.details)) { - const str = data.details.join(); - throw new Error(str); - } - - const result = await WzRequest.apiReq('PUT', `/manager/restart`, {}); - return result; - } catch (error) { - throw error; - } - } } From 562104b175c2fce85db26bfdc42a0258916a63e1 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Mon, 15 Sep 2025 10:47:12 -0500 Subject: [PATCH 52/54] refactor: remove unused managerInfo and managerStatus functions from status handler - Deleted the managerInfo and managerStatus functions from the StatusHandler class, as they are no longer needed in the current implementation. - This change simplifies the codebase and improves maintainability by eliminating redundant functionality. --- .../management/status/utils/status-handler.js | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js b/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js index 1dd817880d..581aa1b5bb 100644 --- a/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js +++ b/plugins/main/public/controllers/management/components/management/status/utils/status-handler.js @@ -85,30 +85,6 @@ export default class StatusHandler { } } - /** - * Get manager info - */ - static async managerInfo() { - try { - const result = await WzRequest.apiReq('GET', `/manager/info`, {}); - return result; - } catch (error) { - throw error; - } - } - - /** - * Get manager status - */ - static async managerStatus() { - try { - const result = await WzRequest.apiReq('GET', `/manager/status`, {}); - return result; - } catch (error) { - throw error; - } - } - /** * Get last agent */ From 1b830a2e50727a2262ceefb88c861a8fa7851115 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Mon, 15 Sep 2025 11:08:45 -0500 Subject: [PATCH 53/54] refactor: update Wazuh API controller to use cluster local info endpoint - Changed API requests in the WazuhApiCtrl class from `/manager/info` to `/cluster/local/info` to align with the new cluster architecture. - Updated error handling and response processing to reflect the new endpoint structure, improving the accuracy of cluster node information retrieval. - Enhanced logging for better debugging and clarity regarding cluster node status. --- plugins/main/server/controllers/wazuh-api.ts | 55 +++++++++++--------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 519783ffea..5d703c37e1 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -134,21 +134,19 @@ export class WazuhApiCtrl { context.wazuh.logger.debug(`${id} exists`); - // Fetch needed information about the cluster and the manager itself - const responseManagerInfo = + // Fetch needed information about the cluster local node + const responseClusterInfo = await context.wazuh.api.client.asInternalUser.request( 'get', - `/manager/info`, + `/cluster/local/info`, {}, { apiHostID: id, forceRefresh: true }, ); // Look for socket-related errors - if (this.checkResponseIsDown(context, responseManagerInfo)) { + if (this.checkResponseIsDown(context, responseClusterInfo)) { return ErrorResponse( - `ERROR3099 - ${ - responseManagerInfo.data.detail || 'Server not ready yet' - }`, + `ERROR3099 - ${responseClusterInfo.detail || 'Server not ready yet'}`, 3099, HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, response, @@ -177,8 +175,7 @@ export class WazuhApiCtrl { } catch (error) { // If we have an invalid response from the Wazuh API throw new Error( - responseManagerInfo.data.detail || - `${api.url}:${api.port} is unreachable`, + responseClusterInfo.detail || `${api.url}:${api.port} is unreachable`, ); } } catch (error) { @@ -203,25 +200,25 @@ export class WazuhApiCtrl { try { const { id } = api; - const responseManagerInfo = + const responseClusterInfo = await context.wazuh.api.client.asInternalUser.request( 'GET', - `/manager/info`, + `/cluster/local/info`, {}, { apiHostID: id }, ); - if (this.checkResponseIsDown(context, responseManagerInfo)) { + if (this.checkResponseIsDown(context, responseClusterInfo)) { return ErrorResponse( `ERROR3099 - ${ - response.data.detail || 'Server not ready yet' + responseClusterInfo.detail || 'Server not ready yet' }`, 3099, HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, response, ); } - if (responseManagerInfo.status === HTTP_STATUS_CODES.OK) { + if (responseClusterInfo.status === HTTP_STATUS_CODES.OK) { request.body.id = id; request.body.idChanged = id; return await this.checkStoredAPI(context, request, response); @@ -313,12 +310,12 @@ export class WazuhApiCtrl { if (request.body.forceRefresh) { options['forceRefresh'] = request.body.forceRefresh; } - let responseManagerInfo; + let responseClusterInfo; try { - responseManagerInfo = + responseClusterInfo = await context.wazuh.api.client.asInternalUser.request( 'GET', - `/manager/info`, + `/cluster/local/info`, {}, options, ); @@ -334,24 +331,30 @@ export class WazuhApiCtrl { } context.wazuh.logger.debug(`${request.body.id} credentials are valid`); if ( - responseManagerInfo.status === HTTP_STATUS_CODES.OK && - responseManagerInfo.data + responseClusterInfo.status === HTTP_STATUS_CODES.OK && + responseClusterInfo.data ) { - // Check if UUID exists in the response - if (responseManagerInfo.data?.data?.affected_items?.[0]?.uuid) { - const uuid = responseManagerInfo.data.data.affected_items[0].uuid; + // Check if cluster node info exists in the response + if (responseClusterInfo.data?.affected_items?.[0]?.node) { + const nodeInfo = responseClusterInfo.data.affected_items[0]; const result = await context.wazuh_core.manageHosts.getRegistryDataByHost(data); return response.ok({ body: { ...result, - uuid, + cluster_info: { + node: nodeInfo.node, + cluster: nodeInfo.cluster, + type: nodeInfo.type, + }, }, }); } else { - context.wazuh.logger.warn('Could not obtain manager UUID'); + context.wazuh.logger.warn( + 'Could not obtain cluster node information', + ); return ErrorResponse( - 'Could not obtain manager UUID', + 'Could not obtain cluster node information', null, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response, @@ -407,7 +410,7 @@ export class WazuhApiCtrl { 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; + const status = (response.data || {}).error || 1; const isDown = socketErrorCodes.includes(status); isDown && From c7379c23ac89368f550a31e533829dbd102f8183 Mon Sep 17 00:00:00 2001 From: Felipe Gonzalez Date: Mon, 15 Sep 2025 15:20:49 -0500 Subject: [PATCH 54/54] refactor: update Wazuh configuration and API endpoints for cluster integration - Changed the specFile URL in the Wazuh configuration to point to the updated cluster API specification. - Removed the deprecated version check endpoint for the manager and added a commented-out version check for the cluster. - Updated the WazuhApiCtrl to correctly access cluster node information from the new response structure. - Modified the getUpdates service to query the cluster version check endpoint instead of the manager endpoint, aligning with the new architecture. --- docker/imposter/manager/version/check.json | 42 ------------------- docker/imposter/wazuh-config.yml | 16 +++---- plugins/main/server/controllers/wazuh-api.ts | 4 +- .../server/services/updates/get-updates.ts | 2 +- 4 files changed, 11 insertions(+), 53 deletions(-) delete mode 100644 docker/imposter/manager/version/check.json diff --git a/docker/imposter/manager/version/check.json b/docker/imposter/manager/version/check.json deleted file mode 100644 index bcba3a69b7..0000000000 --- a/docker/imposter/manager/version/check.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "data": { - "uuid": "7f828fd6-ef68-4656-b363-247b5861b84c", - "last_check_date": "2023-10-04T14:52:07.319561Z", - "current_version": "v4.8.0", - "update_check": true, - "last_available_major": { - "tag": "v5.0.0", - "description": "Highlights of release 5.0.0", - "title": "Wazuh 5.0.0", - "published_date": "2023-10-03T10:44:00Z", - "semver": { - "minor": 0, - "patch": 0, - "major": 5 - } - }, - "last_available_minor": { - "tag": "v4.9.1", - "description": "Highlights of release 4.9.1", - "title": "Wazuh 4.9.1", - "published_date": "2023-09-30T10:44:00Z", - "semver": { - "minor": 9, - "patch": 1, - "major": 4 - } - }, - "last_available_patch": { - "tag": "v4.8.3", - "description": "Highlights of release 4.8.3", - "title": "Wazuh 4.8.3", - "published_date": "2023-09-22T10:44:00Z", - "semver": { - "minor": 8, - "patch": 3, - "major": 4 - } - } - }, - "error": 0 -} diff --git a/docker/imposter/wazuh-config.yml b/docker/imposter/wazuh-config.yml index d61b33505b..c51a9d05ec 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/main/api/api/spec/spec.yaml +specFile: https://raw.githubusercontent.com/wazuh/wazuh/enhancement/31295-cluster-by-default/api/api/spec/spec.yaml system: stores: # this store is preloaded from file @@ -256,6 +256,13 @@ resources: statusCode: 200 scriptFile: cluster/component_configuration.js + # Get available updates + # - method: GET + # path: /cluster/version/check + # response: + # statusCode: 200 + # staticFile: cluster/version/check.json + # ===================================================== # # DECODERS # ===================================================== # @@ -493,13 +500,6 @@ resources: statusCode: 200 scriptFile: manager/configuration.js - # Get available updates - - method: GET - path: /manager/version/check - response: - statusCode: 200 - staticFile: manager/version/check.json - # ===================================================== # # MITRE # ===================================================== # diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 5d703c37e1..5c89537d69 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -335,8 +335,8 @@ export class WazuhApiCtrl { responseClusterInfo.data ) { // Check if cluster node info exists in the response - if (responseClusterInfo.data?.affected_items?.[0]?.node) { - const nodeInfo = responseClusterInfo.data.affected_items[0]; + if (responseClusterInfo.data?.data?.affected_items?.[0]?.node) { + const nodeInfo = responseClusterInfo.data?.data?.affected_items[0]; const result = await context.wazuh_core.manageHosts.getRegistryDataByHost(data); return response.ok({ diff --git a/plugins/wazuh-check-updates/server/services/updates/get-updates.ts b/plugins/wazuh-check-updates/server/services/updates/get-updates.ts index b87da612bc..bca3c8aced 100644 --- a/plugins/wazuh-check-updates/server/services/updates/get-updates.ts +++ b/plugins/wazuh-check-updates/server/services/updates/get-updates.ts @@ -55,7 +55,7 @@ export const getUpdates = async ( hosts?.map(async api => { const data = {}; const method = 'GET'; - const path = `/manager/version/check?force_query=${forceQuery}`; + const path = `/cluster/version/check?force_query=${forceQuery}`; const options = { apiHostID: api.id, forceRefresh: true,