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

Bugfix/cluster delay error #2651

Merged
merged 8 commits into from
Nov 30, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ All notable changes to the Wazuh app project will be documented in this file.

### Fixed

- Manager restart in rule editor does not work with Wazuh cluster enabled [#2640](https://github.com/wazuh/wazuh-kibana-app/issues/2640)
- Restore the tables in the agents' reports [#2628](https://github.com/wazuh/wazuh-kibana-app/issues/2628)
- [RBAC] Issues detected when using RBAC [#2579](https://github.com/wazuh/wazuh-kibana-app/issues/2579)
- Changes done via a worker's API are overwritten [#2626](https://github.com/wazuh/wazuh-kibana-app/issues/2626)

### Fixed

- [BUGFIX] Default user field for current platform [#2633](https://github.com/wazuh/wazuh-kibana-app/pull/2633)

## Wazuh v4.0.1 - Kibana v7.9.1, v7.9.3 - Revision 4009
Expand Down
3 changes: 1 addition & 2 deletions public/components/common/restart-cluster-manager-callout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,8 @@ class WzRestartClusterManagerCallout extends Component<IWzRestartClusterManagerC
try{
this.setState({ warningRestarting: true, warningRestartModalVisible: false});
const data = await restartClusterOrManager(this.props.updateWazuhNotReadyYet);
// this.setState({ warningRestarting: false });
this.props.onRestarted();
this.showToast('success', `${data.restarted === 'cluster' ? 'Restarting cluster, it will take up to 30 seconds.': 'Manager was restarted'}`)
this.showToast('success', `${data.restarted === 'cluster' ? 'Cluster was restarted': 'Manager was restarted'}`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the possible values of data.restarted are cluster or manager change the string template to:

`${data.restarted} was restarted`

}catch(error){
this.setState({ warningRestarting: false });
this.props.updateWazuhNotReadyYet(false);
Expand Down
2 changes: 1 addition & 1 deletion public/components/common/welcome/overview-welcome.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export class OverviewWelcome extends Component {
<EuiFlexGroup >
<EuiFlexItem >
<EuiCallOut style={{height:"65%"}} title="No agents were added to this manager. " color="warning" iconType="alert">
<EuiButtonEmpty style={{margin: "-58px 286px"}} alignItems='right' color="warning" href='#/agents-preview?'>Add agent</EuiButtonEmpty>
<EuiButtonEmpty style={{margin: "-58px 286px"}} href='#/agents-preview?'>Add agent</EuiButtonEmpty>
</EuiCallOut>
</EuiFlexItem >
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import { WzRequest } from '../../../../../../react-services/wz-request';
import { delay } from './utils';
import { replaceIllegalXML } from './xml';
import { toastNotifications } from 'ui/notify';

/**
* Get configuration for an agent/manager of request sections
Expand Down Expand Up @@ -181,7 +182,7 @@ export const checkDaemons = async () => {
* @param {number} [tries=10] Tries
* @return {Promise}
*/
export const makePing = async (updateWazuhNotReadyYet, tries = 15) => {
export const makePing = async (updateWazuhNotReadyYet, tries = 30) => {
try {
let isValid = false;
while (tries--) {
Expand Down Expand Up @@ -313,7 +314,9 @@ export const restartCluster = async () => {
throw new Error(str);
}
// this.performClusterRestart(); // TODO: convert AngularJS to React
await WzRequest.apiReq('PUT', `/cluster/restart`, {});
await WzRequest.apiReq('PUT', `/cluster/restart`, {
delay: 15000
});
// this.$rootScope.$broadcast('removeRestarting', {}); TODO: isRestarting: false?
return {
data: {
Expand Down Expand Up @@ -343,7 +346,7 @@ export const restartNode = async node => {
}
const result = await WzRequest.apiReq(
'PUT',
`/cluster/restart`, {}
`/cluster/restart`, {delay: 15000}
);

return result;
Expand Down Expand Up @@ -506,7 +509,7 @@ export const checkCurrentSecurityPlatform = async () => {
'/elastic/security/current-platform',
{}
);
const platform = (result.data || {}).platform || 'elastic';
const platform = (result.data || {}).platform || 'elastic';

return platform;
} catch (error) {
Expand All @@ -522,12 +525,17 @@ export const restartClusterOrManager = async (updateWazuhNotReadyYet) => {
const clusterStatus = (((await clusterReq()) || {}).data || {}).data || {};
const isCluster =
clusterStatus.enabled === 'yes' && clusterStatus.running === 'yes';

toastNotifications.add({
color:'success',
title:isCluster ?'Restarting cluster, it will take up to 30 seconds.': 'Manager was restarted',
toastLifeTimeMs: 3000
});
isCluster ? await restartCluster() : await restartManager();
// Dispatch a Redux action
updateWazuhNotReadyYet(
`Restarting ${isCluster ? 'Cluster' : 'Manager'}, please wait.`
);
await delay(15000);
await makePing(updateWazuhNotReadyYet);
return { restarted: isCluster ? 'cluster' : 'manager'}
}catch (error){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ export default class StatusHandler {
const str = data.details.join();
throw new Error(str);
}
await WzRequest.apiReq('PUT', `/cluster/restart`, { });
await WzRequest.apiReq('PUT', `/cluster/restart`, { delay: 15000 });
return { data: { data: 'Restarting cluster' } };
} catch (error) {
return Promise.reject(error);
Expand Down
2 changes: 1 addition & 1 deletion public/services/config-handler.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class ConfigHandler {

async performClusterRestart() {
try {
await WzRequest.apiReq('PUT', `/cluster/restart`, {});
await WzRequest.apiReq('PUT', `/cluster/restart`, { delay: 15000 });
this.$rootScope.$broadcast('removeRestarting', {});
} catch (error) {
this.$rootScope.$broadcast('removeRestarting', {});
Expand Down
93 changes: 45 additions & 48 deletions server/controllers/wazuh-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,34 +61,34 @@ export class WazuhApiCtrl {
return undefined;
}

getApiIdFromCookie(cookie){
if(!cookie) return false;
getApiIdFromCookie(cookie) {
if (!cookie) return false;
const getWzApi = /.*wz-api=([^;]+)/;
const wzApi = cookie.match(getWzApi)
if(wzApi && wzApi.length && wzApi[1]) return wzApi[1];
if (wzApi && wzApi.length && wzApi[1]) return wzApi[1];
return false;
}

getTokenFromCookie(cookie){
if(!cookie) return false;
getTokenFromCookie(cookie) {
if (!cookie) return false;
const getWzToken = /.*wz-token=([^;]+)/;
const wzToken = cookie.match(getWzToken)
if(wzToken && wzToken.length && wzToken[1]) return wzToken[1];
if (wzToken && wzToken.length && wzToken[1]) return wzToken[1];
return false;
}

getUserFromCookie(cookie){
if(!cookie) return false;
getUserFromCookie(cookie) {
if (!cookie) return false;
const getWzUser = /.*wz-user=([^;]+)/;
const wzUser = cookie.match(getWzUser)
if(wzUser && wzUser.length && wzUser[1]) return wzUser[1];
if (wzUser && wzUser.length && wzUser[1]) return wzUser[1];
return false;
}

getUserFromAuthContext(authContext){
if(this.PLATFORM === WAZUH_SECURITY_PLUGIN_XPACK_SECURITY)
getUserFromAuthContext(authContext) {
if (this.PLATFORM === WAZUH_SECURITY_PLUGIN_XPACK_SECURITY)
return authContext.username;
if(this.PLATFORM === WAZUH_SECURITY_PLUGIN_OPEN_DISTRO_FOR_ELASTICSEARCH)
if (this.PLATFORM === WAZUH_SECURITY_PLUGIN_OPEN_DISTRO_FOR_ELASTICSEARCH)
return authContext.user_name;
}

Expand All @@ -98,33 +98,33 @@ export class WazuhApiCtrl {
const { idHost } = req.payload;
const authContext = await this.securityObj.getCurrentUser(req);
const username = this.getUserFromAuthContext(authContext);
if(!force && req.headers.cookie && username === this.getUserFromCookie(req.headers.cookie) && idHost === this.getApiIdFromCookie(req.headers.cookie)){
if (!force && req.headers.cookie && username === this.getUserFromCookie(req.headers.cookie) && idHost === this.getApiIdFromCookie(req.headers.cookie)) {
const wzToken = this.getTokenFromCookie(req.headers.cookie);
if(wzToken){
try{ // if the current token is not a valid jwt token we ask for a new one
const decodedToken = jwtDecode(wzToken);
const expirationTime = (decodedToken.exp - (Date.now() / 1000));
if(wzToken && expirationTime > 0) {
return {token: wzToken}
if (wzToken) {
try { // if the current token is not a valid jwt token we ask for a new one
const decodedToken = jwtDecode(wzToken);
const expirationTime = (decodedToken.exp - (Date.now() / 1000));
if (wzToken && expirationTime > 0) {
return { token: wzToken }
}
}catch(error){
} catch (error) {
log('wazuh-api:getToken', error.message || error);
}
}
}
}
let token;
if(await APIUserAllowRunAs.canUse(idHost)){
if (await APIUserAllowRunAs.canUse(idHost)) {
token = await this.apiInterceptor.authenticateApi(idHost, authContext)
}else{
} else {
token = await this.apiInterceptor.authenticateApi(idHost)
};
const response = reply.response({token});
response.state('wz-token', token, {isSecure: false, path: '/'});
response.state('wz-user', username, {isSecure: false, path: '/'});
response.state('wz-api', idHost, {isSecure: false, path: '/'});
const response = reply.response({ token });
response.state('wz-token', token, { isSecure: false, path: '/' });
response.state('wz-user', username, { isSecure: false, path: '/' });
response.state('wz-api', idHost, { isSecure: false, path: '/' });

return { token };
} catch (error){
} catch (error) {
const errorMessage = ((error.response || {}).data || {}).detail || error.message || error;
log('wazuh-api:getToken', errorMessage);
return ErrorResponse(
Expand Down Expand Up @@ -181,7 +181,7 @@ export class WazuhApiCtrl {
'get',
`${api.url}:${api.port}/agents`,
{ params: { agents_list: '000' } },
{ idHost: id}
{ idHost: id }
);

if (responseAgents.status === 200) {
Expand All @@ -191,7 +191,7 @@ export class WazuhApiCtrl {
'get',
`${api.url}:${api.port}/cluster/status`,
{},
{ idHost: id }
{ idHost: id }
);
if (responseClusterStatus.status === 200) {
if (responseClusterStatus.data.data.enabled === 'yes') {
Expand Down Expand Up @@ -354,7 +354,7 @@ export class WazuhApiCtrl {
apiAvailable.password = Buffer.from(req.payload.password, 'base64').toString('ascii');
}
const options = { idHost: req.payload.id };
if(req.payload.forceRefresh){
if (req.payload.forceRefresh) {
options["forceRefresh"] = req.payload.forceRefresh;
}

Expand Down Expand Up @@ -401,14 +401,14 @@ export class WazuhApiCtrl {

// Check the run_as for the API user and update it
let apiUserAllowRunAs = API_USER_STATUS_RUN_AS.DISABLED;
if(apiAvailable.run_as){
if (apiAvailable.run_as) {
const responseApiUserAllowRunAs = await this.apiInterceptor.request(
'GET',
`${apiAvailable.url}:${apiAvailable.port}/security/users/me`,
{},
{ idHost: req.payload.id }
);
if(responseApiUserAllowRunAs.status === 200) {
if (responseApiUserAllowRunAs.status === 200) {
apiUserAllowRunAs = responseApiUserAllowRunAs.data.data.affected_items[0].allow_run_as ? API_USER_STATUS_RUN_AS.ENABLED : API_USER_STATUS_RUN_AS.NOT_ALLOWED;
}
}
Expand Down Expand Up @@ -453,15 +453,15 @@ export class WazuhApiCtrl {
} catch (error) {
log('wazuh-api:checkAPI', error.message || error);

if(error && error.response && error.response.status === 401){
if (error && error.response && error.response.status === 401) {
return ErrorResponse(
`Unathorized. Please check API credentials. ${error.response.data.message}`,
401,
401,
reply
);
}
if(error && error.response && error.response.data && error.response.data.detail){
if (error && error.response && error.response.data && error.response.data.detail) {
return ErrorResponse(
error.response.data.detail,
error.response.status || 500,
Expand Down Expand Up @@ -975,16 +975,13 @@ export class WazuhApiCtrl {
}
const delay = (data || {}).delay || 0;
let fullUrl = getPath(api) + path;

if (delay) {
const current = new Date();
this.queue.addJob({
startAt: new Date(current.getTime() + delay),
type: 'request',
method,
fullUrl,
data,
options,
});
const del = data.delay;
delete data.delay;
setTimeout(() => {
this.makeRequest(method, path, data, id, reply, token).then(console.log).catch(console.log);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should log here, maybe.

}, del)
return { error: 0, message: 'Success' };
}

Expand Down Expand Up @@ -1055,7 +1052,7 @@ export class WazuhApiCtrl {
? { message: responseBody.detail, code: responseError }
: new Error('Unexpected error fetching data from the Wazuh API');
} catch (error) {
if(error && error.response && error.response.status === 401){
if (error && error.response && error.response.status === 401) {
return ErrorResponse(
error.message || error,
error.code ? `Wazuh API error: ${error.code}` : 3013,
Expand Down Expand Up @@ -1144,8 +1141,8 @@ export class WazuhApiCtrl {
*/
requestApi(req, reply) {
const token = this.getTokenFromCookie(req.headers.cookie);
const idApi = this. getApiIdFromCookie(req.headers.cookie);
if(idApi !== req.payload.id){ // if the current token belongs to a different API id, we relogin to obtain a new token
const idApi = this.getApiIdFromCookie(req.headers.cookie);
if (idApi !== req.payload.id) { // if the current token belongs to a different API id, we relogin to obtain a new token
return ErrorResponse(
'status code 401',
401,
Expand Down Expand Up @@ -1242,7 +1239,7 @@ export class WazuhApiCtrl {
);

const isList = req.payload.path.includes('/lists') && req.payload.filters && req.payload.filters.length && req.payload.filters.find(filter => filter._isCDBList);

const totalItems = (((output || {}).data || {}).data || {}).total_affected_items;

if (totalItems && !isList) {
Expand Down