Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed a problem updating the API host registry #6995

Merged
merged 8 commits into from
Sep 19, 2024
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ All notable changes to the Wazuh app project will be documented in this file.

### Added

- Add feature to filter by field in the events table rows [#6977](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6991)
- Support for Wazuh 4.9.1
- Add feature to filter by field in the events table rows [#6977](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6991)

### Fixed

Expand All @@ -20,6 +20,7 @@ All notable changes to the Wazuh app project will be documented in this file.
- Fixed missing link to Vulnerabilities detection and Office 365 in the agent menu of `Endpoints Summary` [#6983](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6983)
- Fixed missing options depending on agent operating system in the agent configuration report [#6983](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6983)
- Fixed an style that affected the Discover plugin [#6989](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6989)
- Fixed a problem updating the API host registry in the GET /api/check-stored-api [#6995](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6995)

### Changed

Expand Down
118 changes: 24 additions & 94 deletions plugins/main/server/controllers/wazuh-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,9 @@ export class WazuhApiCtrl {
}
}
}
let token;
if (context.wazuh_core.manageHosts.isEnabledAuthWithRunAs(idHost)) {
token = await context.wazuh.api.client.asCurrentUser.authenticate(
idHost,
);
} else {
token = await context.wazuh.api.client.asInternalUser.authenticate(
idHost,
);
}
const token = await context.wazuh.api.client.asCurrentUser.authenticate(
idHost,
);

let textSecure = '';
if (context.wazuh.server.info.protocol === 'https') {
Expand Down Expand Up @@ -162,94 +155,31 @@ export class WazuhApiCtrl {
}

// If we have a valid response from the Wazuh API
if (
responseManagerInfo.status === HTTP_STATUS_CODES.OK &&
responseManagerInfo.data
) {
// Clear and update cluster information before being sent back to frontend
delete api.cluster_info;
const responseAgents =
await context.wazuh.api.client.asInternalUser.request(
'GET',
`/agents`,
{ params: { agents_list: '000' } },
{ apiHostID: id },
try {
const { status, manager, node, cluster } =
await context.wazuh_core.manageHosts.getRegistryDataByHost(
apiHostData,
{
throwError: true,
},
);

if (responseAgents.status === HTTP_STATUS_CODES.OK) {
const managerName =
responseAgents.data.data.affected_items[0].manager;
api.cluster_info = { status, manager, node, cluster };

const responseClusterStatus =
await context.wazuh.api.client.asInternalUser.request(
'GET',
`/cluster/status`,
{},
{ apiHostID: id },
);
if (responseClusterStatus.status === HTTP_STATUS_CODES.OK) {
if (responseClusterStatus.data.data.enabled === 'yes') {
const responseClusterLocalInfo =
await context.wazuh.api.client.asInternalUser.request(
'GET',
`/cluster/local/info`,
{},
{ apiHostID: id },
);
if (responseClusterLocalInfo.status === HTTP_STATUS_CODES.OK) {
const clusterEnabled =
responseClusterStatus.data.data.enabled === 'yes';
api.cluster_info = {
status: clusterEnabled ? 'enabled' : 'disabled',
manager: managerName,
node: responseClusterLocalInfo.data.data.affected_items[0]
.node,
cluster: clusterEnabled
? responseClusterLocalInfo.data.data.affected_items[0]
.cluster
: 'Disabled',
};
}
} else {
// Cluster mode is not active
api.cluster_info = {
status: 'disabled',
manager: managerName,
cluster: 'Disabled',
};
}
} else {
// Cluster mode is not active
api.cluster_info = {
status: 'disabled',
manager: managerName,
cluster: 'Disabled',
};
}

if (api.cluster_info) {
// Update cluster information in the wazuh-registry.json
await context.wazuh_core.manageHosts.updateRegistryByHost(
id,
api.cluster_info,
);

return response.ok({
body: {
statusCode: HTTP_STATUS_CODES.OK,
data: api,
idChanged: request.body.idChanged || null,
},
});
}
}
return response.ok({
body: {
statusCode: HTTP_STATUS_CODES.OK,
data: api,
idChanged: request.body.idChanged || null,
},
});
} catch (error) {
// If we have an invalid response from the Wazuh API
throw new Error(
responseManagerInfo.data.detail ||
`${api.url}:${api.port} is unreachable`,
);
}

// If we have an invalid response from the Wazuh API
throw new Error(
responseManagerInfo.data.detail ||
`${api.url}:${api.port} is unreachable`,
);
} catch (error) {
if (error.code === 'EPROTO') {
return response.ok({
Expand Down
1 change: 1 addition & 0 deletions plugins/main/server/routes/wazuh-api-http-status.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const context = {
cacheAPIUserAllowRunAs: {
set: jest.fn(),
API_USER_STATUS_RUN_AS: {
UNABLE_TO_CHECK: -1,
ALL_DISABLED: 0,
USER_NOT_ALLOWED: 1,
HOST_DISABLED: 2,
Expand Down
21 changes: 3 additions & 18 deletions plugins/wazuh-core/common/api-user-status-run-as.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,8 @@
/**
* @example
* HOST = set in configuration
* USER = set in user interface
*
* ALL_DISABLED
* binary 00 = decimal 0 ---> USER 0 y HOST 0
*
* USER_NOT_ALLOWED
* binary 01 = decimal 1 ---> USER 0 y HOST 1
*
* HOST_DISABLED
* binary 10 = decimal 2 ---> USER 1 y HOST 0
*
* ENABLED
* binary 11 = decimal 3 ---> USER 1 y HOST 1
*/
export enum API_USER_STATUS_RUN_AS {
UNABLE_TO_CHECK = -1 /* Initial value or could not check the user can
use the run_as */,
ALL_DISABLED = 0, // Wazuh HOST and USER API user configured with run_as=false or undefined
USER_NOT_ALLOWED = 1, // Wazuh HOST API user configured with run_as=true in configuration but it has not run_as in Wazuh API
HOST_DISABLED = 2, // Wazuh HOST API user configured with run_as=false in configuration but it has not run_as in Wazuh API
HOST_DISABLED = 2, // Wazuh HOST API user configured with run_as=false in configuration but it has run_as in Wazuh API
ENABLED = 3, // Wazuh API user configured with run_as=true and allow run_as
}
73 changes: 57 additions & 16 deletions plugins/wazuh-core/server/services/manage-hosts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { HTTP_STATUS_CODES } from '../../common/constants';

interface IAPIHost {
id: string;
url: string;
username: string;
password: string;
port: number;
Expand All @@ -31,6 +32,13 @@ interface IAPIHostRegistry {
allow_run_as: API_USER_STATUS_RUN_AS;
}

interface GetRegistryDataByHostOptions {
/* this option lets to throw the error when trying to fetch the required data
of the API host that is used by the checkStoredAPI of /api/check-stored-api
endpoint */
throwError: boolean;
}

/**
* This service manages the API connections.
* Get API hosts configuration
Expand Down Expand Up @@ -141,6 +149,7 @@ export class ManageHosts {
*/
private async getRegistryDataByHost(
host: IAPIHost,
options: GetRegistryDataByHostOptions,
): Promise<IAPIHostRegistry> {
const apiHostID = host.id;
this.logger.debug(`Getting registry data from host [${apiHostID}]`);
Expand All @@ -150,7 +159,7 @@ export class ManageHosts {
node = null,
status = 'disabled',
cluster = 'Disabled',
allow_run_as = API_USER_STATUS_RUN_AS.ALL_DISABLED;
allow_run_as = API_USER_STATUS_RUN_AS.UNABLE_TO_CHECK;

try {
const responseAgents = await this.serverAPIClient.asInternalUser.request(
Expand All @@ -165,21 +174,24 @@ export class ManageHosts {
}

// Get allow_run_as
if (!host.run_as) {
allow_run_as = API_USER_STATUS_RUN_AS.HOST_DISABLED;
} else {
const responseAllowRunAs =
await this.serverAPIClient.asInternalUser.request(
'GET',
'/security/users/me',
{},
{ apiHostID },
);
if (this.isServerAPIClientResponseOk(responseAllowRunAs)) {
allow_run_as = responseAllowRunAs.data.data.affected_items[0]
.allow_run_as
const responseAllowRunAs =
await this.serverAPIClient.asInternalUser.request(
'GET',
'/security/users/me',
{},
{ apiHostID },
);
if (this.isServerAPIClientResponseOk(responseAllowRunAs)) {
const allow_run_as_response =
responseAllowRunAs.data.data.affected_items[0].allow_run_as;
if (host.run_as) {
allow_run_as = allow_run_as_response
? API_USER_STATUS_RUN_AS.ENABLED
: API_USER_STATUS_RUN_AS.USER_NOT_ALLOWED;
} else {
allow_run_as = allow_run_as_response
? API_USER_STATUS_RUN_AS.HOST_DISABLED
: API_USER_STATUS_RUN_AS.ALL_DISABLED;
}
}

Expand All @@ -191,7 +203,10 @@ export class ManageHosts {
{ apiHostID },
);

if (this.isServerAPIClientResponseOk(responseClusterStatus) && responseClusterStatus.data?.data?.enabled === 'yes') {
if (
this.isServerAPIClientResponseOk(responseClusterStatus) &&
responseClusterStatus.data?.data?.enabled === 'yes'
) {
status = 'enabled';

const responseClusterLocal =
Expand All @@ -207,7 +222,11 @@ export class ManageHosts {
cluster = responseClusterLocal.data.data.affected_items[0].cluster;
}
}
} catch (error) {}
} catch (error) {
if (options?.throwError) {
throw error;
}
}

const data = {
manager,
Expand Down Expand Up @@ -283,11 +302,33 @@ export class ManageHosts {
`API host with ID [${apiId}] was not found in the registry. This could be caused by a problem getting and storing the registry data or the API host was removed.`,
);
}
if (registryHost.allow_run_as === API_USER_STATUS_RUN_AS.UNABLE_TO_CHECK) {
throw new Error(
`API host with host ID [${apiId}] could not check the ability to use the run as. Ensure the API host is accesible and the internal user has the minimal permissions to check this capability.`,
);
}
if (registryHost.allow_run_as === API_USER_STATUS_RUN_AS.USER_NOT_ALLOWED) {
throw new Error(
`API host with host ID [${apiId}] misconfigured. The configurated API user is not allowed to use [run_as]. Allow it in the API user configuration or set [run_as] host setting with [false] value.`,
);
}

/* The allowed values to compare should be:
API_USER_STATUS_RUN_AS.ENABLED: use run_as
API_USER_STATUS_RUN_AS.HOST_DISABLED: not use run_as
API_USER_STATUS_RUN_AS.ALL_DISABLED: not use run_as
*/
if (
![
API_USER_STATUS_RUN_AS.ENABLED,
API_USER_STATUS_RUN_AS.HOST_DISABLED,
API_USER_STATUS_RUN_AS.ALL_DISABLED,
].includes(registryHost.allow_run_as)
) {
throw new Error(
`API host with host ID [${apiId}] has an unexpected value [${registryHost.allow_run_as}] stored in the registry. This could be caused by a problem getting and storing the registry data.`,
);
}
return registryHost.allow_run_as === API_USER_STATUS_RUN_AS.ENABLED;
}
}
Loading
Loading