This commit is contained in:
Adri Valle 2019-10-09 12:18:50 +02:00
parent 5f34eff198
commit 7a44233a2c
38 changed files with 717 additions and 484 deletions

View File

@ -15,7 +15,7 @@ import { Initialize } from './server/initialize';
import { WazuhElasticRouter } from './server/routes/wazuh-elastic';
import { Monitoring } from './server/monitoring';
import { WazuhApiRoutes } from './server/routes/wazuh-api';
import { WazuhHostsRoutes } from './server/routes/wazuh-hosts'
import { WazuhHostsRoutes } from './server/routes/wazuh-hosts';
import { WazuhReportingRoutes } from './server/routes/wazuh-reporting';
import { WazuhUtilsRoutes } from './server/routes/wazuh-utils';
import { IndexPatternCronJob } from './server/index-pattern-cron-job';

View File

@ -93,11 +93,7 @@ app.run(function($rootScope, $route, $location, appState, $window) {
appState.setNavigation({
reloaded: false,
discoverPrevious: false,
discoverSections: [
'/overview/',
'/agents',
'/wazuh-dev'
]
discoverSections: ['/overview/', '/agents', '/wazuh-dev']
});
$rootScope.$on('$routeChangeSuccess', () => {

View File

@ -45,4 +45,4 @@ app
.value('BasicTable', BasicTable)
.value('Tabs', Tabs)
.value('EuiSwitch', EuiSwitch)
.value('EuiSpacer',EuiSpacer);
.value('EuiSpacer', EuiSpacer);

View File

@ -297,11 +297,14 @@ export class AgentsPreviewController {
*/
async needsPassword() {
try {
const result = await this.apiReq.request('GET', '/agents/000/config/auth/auth', {});
const result = await this.apiReq.request(
'GET',
'/agents/000/config/auth/auth',
{}
);
const auth = ((result.data || {}).data || {}).auth || {};
const usePassword = auth.use_password === 'yes';
return usePassword;
} catch (error) {
return false;
}
@ -314,7 +317,9 @@ export class AgentsPreviewController {
try {
const result = await this.genericReq.request('GET', '/elastic/apis');
const entries = result.data || [];
const host = entries.filter(e => {return e._id == this.api});
const host = entries.filter(e => {
return e._id == this.api;
});
const url = host[0]._source.url;
const numToClean = url.startsWith('https://') ? 8 : 7;
return url.substr(numToClean);

View File

@ -53,11 +53,11 @@ export class RegisterAgent extends Component {
serverAddress: apiAddress,
needsPassword: needsPassword,
wazuhVersion: wazuhVersion
})
});
} catch (error) {
this.setState({
wazuhVersion: version
})
});
}
}
@ -79,11 +79,10 @@ export class RegisterAgent extends Component {
*/
cleanSteps(steps) {
if (this.state.needsPassword) return steps;
steps.splice(2,1);
steps.splice(2, 1);
return steps;
}
render() {
const rpmButton = (
<EuiButtonToggle
@ -145,10 +144,38 @@ export class RegisterAgent extends Component {
zIndex: '100'
};
const customTexts = {
rpmText: `sudo WAZUH_MANAGER_IP='${this.state.serverAddress}'${this.state.needsPassword ? ` WAZUH_PASSWORD='${this.state.wazuhPassword}' ` : ' '}yum install https://packages.wazuh.com/3.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.x86_64.rpm`,
debText: `curl -so wazuh-agent.deb https://packages.wazuh.com/3.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_amd64.deb && sudo WAZUH_MANAGER_IP='${this.state.serverAddress}'${this.state.needsPassword ? ` WAZUH_PASSWORD='${this.state.wazuhPassword}' ` : ' '} dpkg -i ./wazuh-agent.deb`,
macosText: `curl -so wazuh-agent.pkg https://packages.wazuh.com/3.x/osx/wazuh-agent-${this.state.wazuhVersion}-1.pkg && sudo launchctl setenv WAZUH_MANAGER_IP '${this.state.serverAddress}'${this.state.needsPassword ? ` setenv WAZUH_PASSWORD '${this.state.wazuhPassword}' ` : ' '} && sudo installer -pkg ./wazuh-agent.pkg -target /`,
winText: `Invoke-WebRequest -Uri https://packages.wazuh.com/3.x/windows/wazuh-agent-${this.state.wazuhVersion}-1.msi -OutFile wazuh-agent.msi; wazuh-agent.msi /q ADDRESS='${this.state.serverAddress}' AUTHD_SERVER='${this.state.serverAddress}'${this.state.needsPassword ? ` PASSWORD='${this.state.wazuhPassword}' ` : ' '}`
rpmText: `sudo WAZUH_MANAGER_IP='${this.state.serverAddress}'${
this.state.needsPassword
? ` WAZUH_PASSWORD='${this.state.wazuhPassword}' `
: ' '
}yum install https://packages.wazuh.com/3.x/yum/wazuh-agent-${
this.state.wazuhVersion
}-1.x86_64.rpm`,
debText: `curl -so wazuh-agent.deb https://packages.wazuh.com/3.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${
this.state.wazuhVersion
}-1_amd64.deb && sudo WAZUH_MANAGER_IP='${this.state.serverAddress}'${
this.state.needsPassword
? ` WAZUH_PASSWORD='${this.state.wazuhPassword}' `
: ' '
} dpkg -i ./wazuh-agent.deb`,
macosText: `curl -so wazuh-agent.pkg https://packages.wazuh.com/3.x/osx/wazuh-agent-${
this.state.wazuhVersion
}-1.pkg && sudo launchctl setenv WAZUH_MANAGER_IP '${
this.state.serverAddress
}'${
this.state.needsPassword
? ` setenv WAZUH_PASSWORD '${this.state.wazuhPassword}' `
: ' '
} && sudo installer -pkg ./wazuh-agent.pkg -target /`,
winText: `Invoke-WebRequest -Uri https://packages.wazuh.com/3.x/windows/wazuh-agent-${
this.state.wazuhVersion
}-1.msi -OutFile wazuh-agent.msi; wazuh-agent.msi /q ADDRESS='${
this.state.serverAddress
}' AUTHD_SERVER='${this.state.serverAddress}'${
this.state.needsPassword
? ` PASSWORD='${this.state.wazuhPassword}' `
: ' '
}`
};
const field = `${this.state.selectedOS}Text`;
@ -217,7 +244,7 @@ export class RegisterAgent extends Component {
return (
<div>
<EuiPage restrictWidth="1000px" style={{background: "transparent"}} >
<EuiPage restrictWidth="1000px" style={{ background: 'transparent' }}>
<EuiPageBody>
<EuiFlexGroup>
<EuiFlexItem>

View File

@ -12,7 +12,15 @@
*/
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { EuiCodeEditor, EuiCallOut, EuiSpacer, EuiPanel, EuiFlexItem, EuiButton, EuiFlexGroup } from '@elastic/eui';
import {
EuiCodeEditor,
EuiCallOut,
EuiSpacer,
EuiPanel,
EuiFlexItem,
EuiButton,
EuiFlexGroup
} from '@elastic/eui';
import { DynamicHeight } from '../../../utils/dynamic-height';
export class TestConfiguration extends Component {
@ -27,10 +35,9 @@ export class TestConfiguration extends Component {
}
onChange = value => {
this.setState({ configuration : value });
this.setState({ configuration: value });
};
validate = async () => {
this.setState({
validating: true
@ -43,29 +50,27 @@ export class TestConfiguration extends Component {
};
dynamicHeight = () =>
DynamicHeight.dynamicHeightStatic(
'.euiCodeEditorWrapper',
this.state.result ? 110 : 110
);
DynamicHeight.dynamicHeightStatic(
'.euiCodeEditorWrapper',
this.state.result ? 110 : 110
);
render() {
this.dynamicHeight();
return (
<div>
<Fragment>
<EuiSpacer size="m" />
<EuiPanel paddingSize="l">
{this.state.result && (
<div>
<EuiCallOut
title="The configuration is valid!"
color="success"
iconType="check"
>
</EuiCallOut>
<EuiSpacer size="m" />
</div>
{this.state.result && (
<div>
<EuiCallOut
title="The configuration is valid!"
color="success"
iconType="check"
></EuiCallOut>
<EuiSpacer size="m" />
</div>
)}
<EuiCodeEditor
theme="XML"
@ -83,10 +88,9 @@ export class TestConfiguration extends Component {
</EuiPanel>
<EuiSpacer size="m" />
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}></EuiFlexItem>
<EuiFlexItem grow={false}>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
<EuiButton
isLoading={this.state.validating}
isDisabled={this.state.validating || !this.state.configuration}
fill
@ -98,7 +102,7 @@ export class TestConfiguration extends Component {
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</Fragment>
</Fragment>
</div>
);
}

View File

@ -10,7 +10,7 @@
*
* Find more information about this on the LICENSE file.
*/
import React, { Component,Fragment } from 'react';
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import {
EuiCard,

View File

@ -64,7 +64,10 @@ export class CdbListsController {
`${this.currentList.path}/${this.currentList.name}`
);
let list = stringToObj(data.data.data);
list = Object.keys(list).length === 1 && !Object.keys(list)[0].trim() ? {} : list
list =
Object.keys(list).length === 1 && !Object.keys(list)[0].trim()
? {}
: list;
this.currentList.list = list;
this.viewingDetail = true;
this.$scope.$emit('setCurrentList', { currentList: this.currentList });
@ -167,7 +170,7 @@ export class CdbListsController {
/**
* Refresh the list of cdb lists
*/
refresh(){
refresh() {
this.search();
}

View File

@ -47,7 +47,7 @@ export class UploadFiles extends Component {
onButtonClick() {
this.setState({
isPopoverOpen: !this.state.isPopoverOpen,
isPopoverOpen: !this.state.isPopoverOpen
});
}
@ -89,7 +89,7 @@ export class UploadFiles extends Component {
}
}, 100);
}
} catch (error) { }
} catch (error) {}
}
/**
@ -103,34 +103,39 @@ export class UploadFiles extends Component {
}
/**
* Renders the result of a file upload
*/
* Renders the result of a file upload
*/
renderResult(result) {
return (
<Fragment>
{!result.uploaded &&
<EuiCallOut size="s" title={result.file} color="danger" iconType="alert">
<EuiText
className='list-element-bad'
size='s'
>{result.error}
{(!result.uploaded && (
<EuiCallOut
size="s"
title={result.file}
color="danger"
iconType="alert"
>
<EuiText className="list-element-bad" size="s">
{result.error}
</EuiText>
</EuiCallOut>
||
<EuiCallOut size="s" title={result.file} color="success" iconType="check">
<EuiText
className='list-element-ok'
size='s'
> File upload successfully
)) || (
<EuiCallOut
size="s"
title={result.file}
color="success"
iconType="check"
>
<EuiText className="list-element-ok" size="s">
{' '}
File upload successfully
</EuiText>
</EuiCallOut>
}
)}
</Fragment>
);
}
/**
* Checks the size of the files in order to check if anyone is bigger that the size allowed
*/
@ -176,7 +181,6 @@ export class UploadFiles extends Component {
);
}
/**
* Renders the errors when trying to upload files
*/
@ -184,32 +188,28 @@ export class UploadFiles extends Component {
return (
<Fragment>
<EuiListGroup flush={true} className="list-of-files-fail">
{this.state.uploadErrors.map((error, idx) => { // We first show the files that were successfully uploaded
{this.state.uploadErrors.map((error, idx) => {
// We first show the files that were successfully uploaded
if (error.uploaded) {
return (
<EuiFlexItem
key={idx}
id={error.index}>
<EuiFlexItem key={idx} id={error.index}>
{this.renderResult(error)}
<EuiSpacer size="s" />
</EuiFlexItem>
)
);
}
})
}
})}
{this.state.uploadErrors.map((error, idx) => {
if (!error.uploaded) { // When all successfully uploaded files are shown, then we show the failed files
if (!error.uploaded) {
// When all successfully uploaded files are shown, then we show the failed files
return (
<EuiFlexItem
key={idx}
id={error.index}>
<EuiFlexItem key={idx} id={error.index}>
{this.renderResult(error)}
<EuiSpacer size="s" />
</EuiFlexItem>
)
);
}
})
}
})}
</EuiListGroup>
</Fragment>
);
@ -237,45 +237,49 @@ export class UploadFiles extends Component {
<EuiTitle size="m">
<h1>{`Upload ${this.props.msg}`}</h1>
</EuiTitle>
<EuiFlexItem>{!this.state.uploadErrors &&
<EuiFilePicker
id="filePicker"
multiple
compressed={false}
initialPromptText={`Select or drag and drop your ${this.props.msg} files here`}
className="no-max-width"
onChange={files => {
this.onChange(files);
}}
/>
}</EuiFlexItem>
<EuiFlexItem>
{!this.state.uploadErrors && (
<EuiFilePicker
id="filePicker"
multiple
compressed={false}
initialPromptText={`Select or drag and drop your ${this.props.msg} files here`}
className="no-max-width"
onChange={files => {
this.onChange(files);
}}
/>
)}
</EuiFlexItem>
{this.state.files.length > 0 &&
this.state.files.length < 6 &&
!this.checkOverSize() > 0 &&
this.checkValidFileExtensions() > 0 && (
<Fragment>
<EuiFlexItem>{!this.state.uploadErrors &&
this.renderFiles() ||
this.renderErrors()
}</EuiFlexItem>
<EuiFlexItem grow={false}>{!this.state.uploadErrors &&
<EuiButton
className="upload-files-button"
fill
iconType="sortUp"
onClick={() => this.startUpload()}
>
Upload
</EuiButton>
||
<EuiButtonEmpty
className="upload-files-button"
onClick={() => this.closePopover()}
>
Close
</EuiButtonEmpty>
}</EuiFlexItem>
<EuiFlexItem>
{(!this.state.uploadErrors && this.renderFiles()) ||
this.renderErrors()}
</EuiFlexItem>
<EuiFlexItem grow={false}>
{(!this.state.uploadErrors && (
<EuiButton
className="upload-files-button"
fill
iconType="sortUp"
onClick={() => this.startUpload()}
>
Upload
</EuiButton>
)) || (
<EuiButtonEmpty
className="upload-files-button"
onClick={() => this.closePopover()}
>
Close
</EuiButtonEmpty>
)}
</EuiFlexItem>
</Fragment>
)}

View File

@ -159,7 +159,7 @@ export function GroupsController(
$scope.groupsSelectedTab = 'agents';
$scope.groupsTabsProps.selectedTab = 'agents';
return $scope.loadGroup(parameters.group);
});;
});
$scope.$on('wazuhShowGroupFile', (ev, parameters) => {
ev.stopPropagation();

View File

@ -454,20 +454,30 @@ export class ManagementController {
this.errors = false;
this.results = [];
if (path === 'etc/rules') {
this.upload = this.rulesetHandler.sendRuleConfiguration
this.upload = this.rulesetHandler.sendRuleConfiguration;
} else if (path === 'etc/decoders') {
this.upload = this.rulesetHandler.sendDecoderConfiguration
this.upload = this.rulesetHandler.sendDecoderConfiguration;
} else {
this.upload = this.rulesetHandler.sendCdbList
this.upload = this.rulesetHandler.sendCdbList;
}
for (let idx in files) {
const { file, content } = files[idx];
try {
await this.upload(file, content, true); // True does not overwrite the file
this.results.push({index: idx, uploaded: true, file: file, error: 0});
await this.upload(file, content, true); // True does not overwrite the file
this.results.push({
index: idx,
uploaded: true,
file: file,
error: 0
});
} catch (error) {
this.errors = true
this.results.push({index: idx, uploaded: false, file: file, error: error});
this.errors = true;
this.results.push({
index: idx,
uploaded: false,
file: file,
error: error
});
}
}
if (this.errors) throw this.results;
@ -478,4 +488,4 @@ export class ManagementController {
this.errorHandler.handle('Files cannot be uploaded');
}
}
}
}

View File

@ -140,7 +140,7 @@ export class HealthCheck {
async checkApiConnection() {
try {
const currentApi = JSON.parse(this.appState.getCurrentAPI() || '{}');
if (this.checks.api && currentApi && currentApi.id) {
if (this.checks.api && currentApi && currentApi.id) {
const data = await this.testAPI.checkStored(currentApi.id);
if (((data || {}).data || {}).idChanged) {
@ -217,7 +217,7 @@ export class HealthCheck {
async load() {
try {
const configuration = this.wazuhConfig.getConfig();
this.appState.setPatternSelector(configuration['ip.selector']);
this.checks.pattern = configuration['checks.pattern'];

View File

@ -35,9 +35,8 @@ export class AddApi extends Component {
};
}
componentDidMount() {
this.setState({enableClose: this.props.enableClose});
this.setState({ enableClose: this.props.enableClose });
this.checkErrorsAtInit();
}
@ -50,7 +49,9 @@ export class AddApi extends Component {
this.setState({
status: error.type || 'danger',
blockClose: true,
message: (error.data || error).message || 'Wazuh API not reachable, please review your configuration',
message:
(error.data || error).message ||
'Wazuh API not reachable, please review your configuration',
fetchingData: false
});
}
@ -65,7 +66,7 @@ export class AddApi extends Component {
this.setState({
status: 'incomplete',
fetchingData: true,
blockClose: false,
blockClose: false
});
await this.props.checkForNewApis();
@ -76,13 +77,18 @@ export class AddApi extends Component {
closedEnabled: true
});
} catch (error) {
const close = (error.data && error.data.code && error.data.code === 2001) ? false : (error.closedEnabled || false);
const close =
error.data && error.data.code && error.data.code === 2001
? false
: error.closedEnabled || false;
this.setState({
status: error.type || 'danger',
closedEnabled: close,
blockClose: !close,
enableClose: false,
message: (error.data || error).message || 'Wazuh API not reachable, please review your configuration',
message:
(error.data || error).message ||
'Wazuh API not reachable, please review your configuration',
fetchingData: false
});
}
@ -98,14 +104,16 @@ export class AddApi extends Component {
const checkConnectionChildren = (
<div>
{(this.state.status === 'warning' || this.state.status === 'danger') && (
{(this.state.status === 'warning' ||
this.state.status === 'danger') && (
<EuiCallOut
color={this.state.status}
iconType="help"
title={this.state.message}
/>
)}
{(this.state.status === 'warning' || this.state.status === 'danger') && <EuiSpacer />}
{(this.state.status === 'warning' ||
this.state.status === 'danger') && <EuiSpacer />}
<EuiText>
Check that the Kibana server can reach the configured Wazuh API(s).
</EuiText>
@ -116,13 +124,12 @@ export class AddApi extends Component {
>
Check connection
</EuiButton>
{((this.state.closedEnabled || this.state.enableClose) && !this.state.blockClose) && (
<EuiButtonEmpty
onClick={() => this.props.closeAddApi()}
>
Close
</EuiButtonEmpty>
)}
{(this.state.closedEnabled || this.state.enableClose) &&
!this.state.blockClose && (
<EuiButtonEmpty onClick={() => this.props.closeAddApi()}>
Close
</EuiButtonEmpty>
)}
</div>
);
@ -170,7 +177,7 @@ export class AddApi extends Component {
</EuiFlexItem>
<EuiFlexItem />
<EuiFlexItem grow={false}>
{(this.state.enableClose && !this.state.blockClose) && (
{this.state.enableClose && !this.state.blockClose && (
<EuiButtonEmpty
size="s"
onClick={() => this.props.closeAddApi()}

View File

@ -41,7 +41,6 @@ export class ApiIsDown extends Component {
};
}
componentDidMount() {
this.setState({
apiEntries: [...this.props.apiEntries]
@ -68,7 +67,7 @@ export class ApiIsDown extends Component {
try {
const data = await this.props.testApi(entry);
const clusterInfo = data.data || {};
const id = entries[idx].id;;
const id = entries[idx].id;
entries[idx].status = 'online';
entries[idx].cluster_info = clusterInfo;
//Updates the cluster info in the registry
@ -76,7 +75,8 @@ export class ApiIsDown extends Component {
} catch (error) {
numErr = numErr + 1;
const code = ((error || {}).data || {}).code;
const downReason = ((error || {}).data || {}).message || 'Wazuh is not reachable';
const downReason =
((error || {}).data || {}).message || 'Wazuh is not reachable';
const status = code === 3099 ? 'down' : 'unknown';
entries[idx].status = { status, downReason };
}
@ -91,7 +91,12 @@ export class ApiIsDown extends Component {
refreshingEntries: false
});
} catch (error) {
if (error && error.data && error.data.message && error.data.code === 2001) {
if (
error &&
error.data &&
error.data.message &&
error.data.code === 2001
) {
this.setState({ error: error.data.message, status: 'danger' });
}
}
@ -122,16 +127,14 @@ hosts:
</EuiButton>
{this.state.status !== 'danger' &&
this.state.status !== 'incomplete' && (
<EuiButtonEmpty
onClick={() => this.props.closeApiIsDown()}
>
<EuiButtonEmpty onClick={() => this.props.closeApiIsDown()}>
Close
</EuiButtonEmpty>
</EuiButtonEmpty>
)}
<EuiSpacer />
<EuiText>Already configured Wazuh API(s)</EuiText>
<EuiSpacer />
{!this.state.error && (
{(!this.state.error && (
<EuiBasicTable
loading={this.state.refreshingEntries}
items={this.state.apiEntries}
@ -150,33 +153,50 @@ hosts:
<span>
<EuiHealth color="warning">Warning</EuiHealth>
<EuiToolTip position="top" content={item.downReason}>
<EuiButtonIcon color="primary" style={{ marginTop: '-12px' }} iconType="questionInCircle" onClick={() => this.props.copyToClipBoard(item.downReason)}/>
<EuiButtonIcon
color="primary"
style={{ marginTop: '-12px' }}
iconType="questionInCircle"
onClick={() =>
this.props.copyToClipBoard(item.downReason)
}
/>
</EuiToolTip>
</span>
) : (
<span>
<EuiHealth color="danger">Offline</EuiHealth>
<EuiToolTip position="top" content={item.downReason}>
<EuiButtonIcon color="primary" style={{ marginTop: '-12px' }} iconType="questionInCircle" onClick={() => this.props.copyToClipBoard(item.downReason)}/>
</EuiToolTip>
</span >
);
<span>
<EuiHealth color="danger">Offline</EuiHealth>
<EuiToolTip position="top" content={item.downReason}>
<EuiButtonIcon
color="primary"
style={{ marginTop: '-12px' }}
iconType="questionInCircle"
onClick={() =>
this.props.copyToClipBoard(item.downReason)
}
/>
</EuiToolTip>
</span>
);
} else {
return (<span><EuiLoadingSpinner size="s" /><span>&nbsp;&nbsp;Checking</span></span>);
return (
<span>
<EuiLoadingSpinner size="s" />
<span>&nbsp;&nbsp;Checking</span>
</span>
);
}
}
}
]}
/>
) || (
<EuiCallOut
color='danger'
iconType="cross"
title={this.state.error}
/>
)}
)) || (
<EuiCallOut
color="danger"
iconType="cross"
title={this.state.error}
/>
)}
</div>
);

View File

@ -42,10 +42,9 @@ export class ApiTable extends Component {
});
}
/**
* Refresh the API entries
*/
* Refresh the API entries
*/
async refresh() {
try {
let status = 'complete';
@ -62,7 +61,7 @@ export class ApiTable extends Component {
try {
const data = await this.props.testApi(entry);
const clusterInfo = data.data || {};
const id = entries[idx].id;;
const id = entries[idx].id;
entries[idx].status = 'online';
entries[idx].cluster_info = clusterInfo;
//Updates the cluster info in the registry
@ -70,7 +69,8 @@ export class ApiTable extends Component {
} catch (error) {
numErr = numErr + 1;
const code = ((error || {}).data || {}).code;
const downReason = ((error || {}).data || {}).message || 'Wazuh is not reachable';
const downReason =
((error || {}).data || {}).message || 'Wazuh is not reachable';
const status = code === 3099 ? 'down' : 'unknown';
entries[idx].status = { status, downReason };
}
@ -84,7 +84,12 @@ export class ApiTable extends Component {
refreshingEntries: false
});
} catch (error) {
if (error && error.data && error.data.message && error.data.code === 2001) {
if (
error &&
error.data &&
error.data.message &&
error.data.code === 2001
) {
this.props.showAddApiWithInitialError(error);
}
}
@ -92,7 +97,7 @@ export class ApiTable extends Component {
/**
* Checks the API connectivity
* @param {Object} api
* @param {Object} api
*/
async checkApi(api) {
try {
@ -103,7 +108,8 @@ export class ApiTable extends Component {
entries[idx].status = 'online';
} catch (error) {
const code = ((error || {}).data || {}).code;
const downReason = ((error || {}).data || {}).message || 'Wazuh is not reachable';
const downReason =
((error || {}).data || {}).message || 'Wazuh is not reachable';
const status = code === 3099 ? 'down' : 'unknown';
entries[idx].status = { status, downReason };
}
@ -122,37 +128,37 @@ export class ApiTable extends Component {
field: 'id',
name: 'ID',
align: 'left',
sortable: true,
sortable: true
},
{
field: 'cluster_info.cluster',
name: 'Cluster',
align: 'left',
sortable: true,
sortable: true
},
{
field: 'cluster_info.manager',
name: 'Manager',
align: 'left',
sortable: true,
sortable: true
},
{
field: 'url',
name: 'Host',
align: 'left',
sortable: true,
sortable: true
},
{
field: 'port',
name: 'Port',
align: 'left',
sortable: true,
sortable: true
},
{
field: 'user',
name: 'User',
align: 'left',
sortable: true,
sortable: true
},
{
field: 'status',
@ -167,22 +173,35 @@ export class ApiTable extends Component {
<span>
<EuiHealth color="warning">Warning</EuiHealth>
<EuiToolTip position="top" content={item.downReason}>
<EuiButtonIcon color="primary" style={{ marginTop: '-12px' }} iconType="questionInCircle" onClick={() => this.props.copyToClipBoard(item.downReason)}/>
<EuiButtonIcon
color="primary"
style={{ marginTop: '-12px' }}
iconType="questionInCircle"
onClick={() => this.props.copyToClipBoard(item.downReason)}
/>
</EuiToolTip>
</span>
) : (
<span>
<EuiHealth color="danger">Offline</EuiHealth>
<EuiToolTip position="top" content={item.downReason}>
<EuiButtonIcon color="primary" style={{ marginTop: '-12px' }} iconType="questionInCircle" onClick={() => this.props.copyToClipBoard(item.downReason)}/>
</EuiToolTip>
</span >
);
<span>
<EuiHealth color="danger">Offline</EuiHealth>
<EuiToolTip position="top" content={item.downReason}>
<EuiButtonIcon
color="primary"
style={{ marginTop: '-12px' }}
iconType="questionInCircle"
onClick={() => this.props.copyToClipBoard(item.downReason)}
/>
</EuiToolTip>
</span>
);
} else {
return (<span><EuiLoadingSpinner size="s" /><span>&nbsp;&nbsp;Checking</span></span>);
return (
<span>
<EuiLoadingSpinner size="s" />
<span>&nbsp;&nbsp;Checking</span>
</span>
);
}
}
},
{
@ -225,7 +244,7 @@ export class ApiTable extends Component {
const search = {
box: {
incremental: this.state.incremental,
schema: true,
schema: true
}
};
@ -247,7 +266,7 @@ export class ApiTable extends Component {
onClick={() => this.props.showAddApi()}
>
Add new
</EuiButtonEmpty>
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonEmpty
@ -261,7 +280,8 @@ export class ApiTable extends Component {
<EuiFlexGroup>
<EuiFlexItem>
<EuiText color="subdued" style={{ paddingBottom: '15px' }}>
From here you can see how to set up your Wazuh host, establish as default, and check their connection and status.
From here you can see how to set up your Wazuh host, establish as
default, and check their connection and status.
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>

View File

@ -83,7 +83,8 @@ export class SettingsController {
await this.getSettings();
const down = await this.checkApisStatus();
//Checks if all the API entries are down
this.apiIsDown = (down >= this.apiEntries.length && this.apiEntries.length > 0);
this.apiIsDown =
down >= this.apiEntries.length && this.apiEntries.length > 0;
const location = this.$location.search();
if (location && location.tab) {
@ -93,7 +94,7 @@ export class SettingsController {
await this.getAppInfo();
} catch (error) {
this.errorHandler.handle('Cannot initialize Settings')
this.errorHandler.handle('Cannot initialize Settings');
}
}
@ -110,8 +111,10 @@ export class SettingsController {
showAddApi: () => this.showAddApi(),
getHosts: () => this.getHosts(),
testApi: entry => this.testAPI.check(entry),
showAddApiWithInitialError: error => this.showAddApiWithInitialError(error),
updateClusterInfoInRegistry: (id, clusterInfo) => this.updateClusterInfoInRegistry(id, clusterInfo),
showAddApiWithInitialError: error =>
this.showAddApiWithInitialError(error),
updateClusterInfoInRegistry: (id, clusterInfo) =>
this.updateClusterInfoInRegistry(id, clusterInfo),
showApiIsDown: () => this.showApiIsDown(),
copyToClipBoard: msg => this.copyToClipBoard(msg)
};
@ -119,16 +122,17 @@ export class SettingsController {
this.addApiProps = {
checkForNewApis: () => this.checkForNewApis(),
closeAddApi: () => this.closeAddApi()
}
};
this.apiIsDownProps = {
apiEntries: this.apiEntries,
testApi: entry => this.testAPI.check(entry),
closeApiIsDown: () => this.closeApiIsDown(),
getHosts: () => this.getHosts(),
updateClusterInfoInRegistry: (id, clusterInfo) => this.updateClusterInfoInRegistry(id, clusterInfo),
updateClusterInfoInRegistry: (id, clusterInfo) =>
this.updateClusterInfoInRegistry(id, clusterInfo),
copyToClipBoard: msg => this.copyToClipBoard(msg)
}
};
this.settingsTabsProps = {
clickAction: tab => {
@ -144,7 +148,7 @@ export class SettingsController {
{ id: 'logs', name: 'Logs' },
{ id: 'about', name: 'About' }
]
}
};
}
/**
@ -162,17 +166,19 @@ export class SettingsController {
// Get current API index
getCurrentAPIIndex() {
if (this.apiEntries.length) {
const idx = this.apiEntries.map(entry => entry.id).indexOf(this.currentDefault);
const idx = this.apiEntries
.map(entry => entry.id)
.indexOf(this.currentDefault);
this.currentApiEntryIndex = idx;
}
}
/**
* Returns the index of the API in the entries array
* @param {Object} api
*/
* Returns the index of the API in the entries array
* @param {Object} api
*/
getApiIndex(api) {
return this.apiEntries.map(entry => entry.id).indexOf(api.id)
return this.apiEntries.map(entry => entry.id).indexOf(api.id);
}
/**
@ -187,14 +193,15 @@ export class SettingsController {
this.apiEntries[idx].status = 'online';
} catch (error) {
const code = ((error || {}).data || {}).code;
const downReason = ((error || {}).data || {}).message || 'Wazuh is not reachable';
const downReason =
((error || {}).data || {}).message || 'Wazuh is not reachable';
const status = code === 3099 ? 'down' : 'unknown';
this.apiEntries[idx].status = { status, downReason };
numError = numError + 1;
}
};
}
return numError;
} catch (error) { }
} catch (error) {}
}
// Set default API
@ -206,7 +213,7 @@ export class SettingsController {
const { cluster_info, id } = api;
const { manager, cluster, status } = cluster_info;
// Check the connection before set as default
// Check the connection before set as default
this.appState.setClusterInfo(cluster_info);
const clusterEnabled = status === 'disabled';
this.appState.setCurrentAPI(
@ -277,7 +284,7 @@ export class SettingsController {
if (currentApi && !this.appState.getExtensions(this.currentDefault)) {
const { id, extensions } = this.apiEntries[this.currentApiEntryIndex];
const apiExtensions = extensions || {}
const apiExtensions = extensions || {};
this.appState.setExtensions(id, apiExtensions);
}
@ -286,13 +293,15 @@ export class SettingsController {
this.errorHandler.handle('Error getting API entries', 'Settings');
}
// Every time that the API entries are required in the settings the registry will be checked in order to remove orphan host entries
await this.genericReq.request('POST', '/hosts/remove-orphan-entries', { entries: this.apiEntries });
await this.genericReq.request('POST', '/hosts/remove-orphan-entries', {
entries: this.apiEntries
});
return;
}
/**
* @param {String} id
* @param {Object} clusterInfo
* @param {String} id
* @param {Object} clusterInfo
*/
async updateClusterInfoInRegistry(id, clusterInfo) {
try {
@ -309,9 +318,7 @@ export class SettingsController {
async checkManager(item, isIndex, silent = false) {
try {
// Get the index of the API in the entries
const index = isIndex
? item
: this.getApiIndex(item);
const index = isIndex ? item : this.getApiIndex(item);
// Get the Api information
const api = this.apiEntries[index];
@ -329,7 +336,7 @@ export class SettingsController {
const data = await this.testAPI.check(tmpData);
tmpData.cluster_info = data.data;
const { cluster_info } = tmpData;
// Updates the cluster-information in the registry
// Updates the cluster-information in the registry
await this.updateClusterInfoInRegistry(id, cluster_info);
this.$scope.$emit('updateAPI', { cluster_info });
this.apiEntries[index].cluster_info = cluster_info;
@ -403,7 +410,10 @@ export class SettingsController {
}
this.getCurrentAPIIndex();
if ((this.currentApiEntryIndex || this.currentApiEntryIndex === 0) && this.currentApiEntryIndex >= 0) {
if (
(this.currentApiEntryIndex || this.currentApiEntryIndex === 0) &&
this.currentApiEntryIndex >= 0
) {
await this.checkManager(this.currentApiEntryIndex, true, true);
}
this.$scope.$applyAsync();
@ -499,14 +509,28 @@ export class SettingsController {
this.addApiProps.errorsAtInit = false;
const hosts = await this.getHosts();
//Tries to check if there are new APIs entries in the wazuh.yml also, checks if some of them have connection
if (!hosts.length) throw { message: 'There were not found any API entry in the wazuh.yml', type: 'warning', closedEnabled: false };
if (!hosts.length)
throw {
message: 'There were not found any API entry in the wazuh.yml',
type: 'warning',
closedEnabled: false
};
const notRecheable = await this.checkApisStatus();
if (notRecheable) {
if (notRecheable >= hosts.length) {
this.apiIsDown = true;
throw { message: 'Wazuh API not recheable, please review your configuration', type: 'danger', closedEnabled: true };
throw {
message:
'Wazuh API not recheable, please review your configuration',
type: 'danger',
closedEnabled: true
};
}
throw { message: 'Some API entries are not reachable', type: 'warning', closedEnabled: true };
throw {
message: 'Some API entries are not reachable',
type: 'warning',
closedEnabled: true
};
}
return;
} catch (error) {
@ -551,8 +575,8 @@ export class SettingsController {
}
/**
* Shows the add API component
*/
* Shows the add API component
*/
showApiIsDown() {
this.apiIsDown = true;
this.$scope.$applyAsync();
@ -584,7 +608,8 @@ export class SettingsController {
this.apiEntries = await this.getHosts();
const down = await this.checkApisStatus();
//Checks if all the API entries are down
this.apiIsDown = (down >= this.apiEntries.length && this.apiEntries.length > 0);
this.apiIsDown =
down >= this.apiEntries.length && this.apiEntries.length > 0;
this.$scope.$applyAsync();
return this.apiEntries;
} catch (error) {
@ -595,7 +620,7 @@ export class SettingsController {
/**
* Copy to the clickboard the string passed
* @param {String} msg
* @param {String} msg
*/
copyToClipBoard(msg) {
const el = document.createElement('textarea');

View File

@ -814,7 +814,7 @@ function discoverController(
const isClusterMonitoring = $scope.tabView === 'cluster-monitoring';
// Wazuh. Should we fetch "_source" and "hits" ?
const noHits = (isPanels || isClusterMonitoring);
const noHits = isPanels || isClusterMonitoring;
// Wazuh. The very first time, the copies are null, just create them
if (!defaultSearchSource || !noHitsSearchSource) {

View File

@ -34,7 +34,7 @@ export class ApiTester {
headers: { 'Content-Type': 'application/json' },
timeout: timeout || 20000
};
const payload = {id: data};
const payload = { id: data };
const result = await this.$http.post(
chrome.addBasePath('/api/check-stored-api'),
payload,

View File

@ -23,7 +23,8 @@ export function apiCount($q, genericReq, $location, appState) {
genericReq
.request('GET', '/hosts/apis')
.then(async data => {
if (!data || !data.data || !data.data.length) throw new Error('No API entries found');
if (!data || !data.data || !data.data.length)
throw new Error('No API entries found');
if (!appState.getCurrentAPI()) {
await tryToSetDefault(data.data, appState);
}
@ -58,4 +59,4 @@ function tryToSetDefault(apis, appState) {
} catch (error) {
return Promise.reject(error);
}
}
}

View File

@ -29,7 +29,7 @@ export function settingsWizard(
const checkResponse = data => {
let fromWazuhHosts = false;
if (parseInt(data.data.error) === 2) {
console.log('default akaaakaa')
console.log('default akaaakaa');
!disableErrors &&
errorHandler.handle(
'Please set up Wazuh API credentials.',
@ -105,7 +105,10 @@ export function settingsWizard(
try {
currentApi = JSON.parse(appState.getCurrentAPI()).id;
} catch (error) {
console.log('Error parsing JSON (settingsWizards.callCheckStored 1)', error);
console.log(
'Error parsing JSON (settingsWizards.callCheckStored 1)',
error
);
}
if (currentApi && !appState.getExtensions(currentApi)) {
const extensions = {
@ -152,7 +155,7 @@ export function settingsWizard(
}
}
})
.catch((error) => {
.catch(error => {
appState.removeCurrentAPI();
setUpCredentials(
'Wazuh App: Please set up Wazuh API credentials.',
@ -190,9 +193,7 @@ export function settingsWizard(
name: api.cluster_info.manager,
id: id
});
appState.setCurrentAPI(
defaultApi
);
appState.setCurrentAPI(defaultApi);
callCheckStored();
return defaultApi;
}
@ -207,7 +208,7 @@ export function settingsWizard(
} catch (error) {
return Promise.reject(error);
}
}
};
const currentParams = $location.search();
const targetedAgent =
@ -282,7 +283,7 @@ export function settingsWizard(
}
}
})
.catch((error) => {
.catch(error => {
setUpCredentials('Wazuh App: Please set up Wazuh API credentials.');
});
}

View File

@ -73,7 +73,8 @@ export class RulesetHandler {
try {
const result = await this.apiReq.request(
'POST',
`/manager/files?path=etc/rules/${rule.file || rule}&overwrite=${!overwrite}`,
`/manager/files?path=etc/rules/${rule.file ||
rule}&overwrite=${!overwrite}`,
{ content, origin: 'xmleditor' }
);
return result;
@ -85,9 +86,8 @@ export class RulesetHandler {
try {
const result = await this.apiReq.request(
'POST',
`/manager/files?path=etc/decoders/${
decoder.file || decoder
}&overwrite=${!overwrite}`,
`/manager/files?path=etc/decoders/${decoder.file ||
decoder}&overwrite=${!overwrite}`,
{ content, origin: 'xmleditor' }
);
return result;

View File

@ -11,33 +11,31 @@
*/
export class StringsTools {
constructor () {}
/**
* Set the first letter to upper case
*
* @param {*} str
* @returns capitalized str
* @memberof StringsTools
*/
capitalize (str) {
return str[0].toUpperCase() + str.slice(1);
}
/**
* Remove all white spaces from str
*
* @param {*} str
* @returns striped str
* @memberof StringsTools
*/
strip (str) {
return str.replace(/\s+/g, '');
}
toUpperCamelCase (str) {
const capitalizeStrs = str.split(' ').map((s) => this.capitalize(s));
return capitalizeStrs.join('');
}
}
constructor() {}
/**
* Set the first letter to upper case
*
* @param {*} str
* @returns capitalized str
* @memberof StringsTools
*/
capitalize(str) {
return str[0].toUpperCase() + str.slice(1);
}
/**
* Remove all white spaces from str
*
* @param {*} str
* @returns striped str
* @memberof StringsTools
*/
strip(str) {
return str.replace(/\s+/g, '');
}
toUpperCamelCase(str) {
const capitalizeStrs = str.split(' ').map(s => this.capitalize(s));
return capitalizeStrs.join('');
}
}

View File

@ -44,9 +44,11 @@ export function ErrorResponse(
message.includes('EAI_AGAIN')) &&
code === 3005
) {
filteredMessage = 'Wazuh API is not reachable. Please check your url and port.';
filteredMessage =
'Wazuh API is not reachable. Please check your url and port.';
} else if (isString && message.includes('ECONNREFUSED') && code === 3005) {
filteredMessage = 'Wazuh API is not reachable. Please check your url and port.';
filteredMessage =
'Wazuh API is not reachable. Please check your url and port.';
} else if (
isString &&
message.toLowerCase().includes('not found') &&

View File

@ -14,9 +14,4 @@ import { WazuhApiCtrl } from './wazuh-api';
import { WazuhReportingCtrl } from './wazuh-reporting';
import { WazuhUtilsCtrl } from './wazuh-utils';
export {
WazuhElasticCtrl,
WazuhApiCtrl,
WazuhReportingCtrl,
WazuhUtilsCtrl
};
export { WazuhElasticCtrl, WazuhApiCtrl, WazuhReportingCtrl, WazuhUtilsCtrl };

View File

@ -54,9 +54,9 @@ export class WazuhApiCtrl {
async checkStoredAPI(req, reply) {
try {
// Get config from wazuh.yml
const id = req.payload.id || req.payload
const id = req.payload.id || req.payload;
const api = await this.manageHosts.getHostById(id);
// Check Manage Hosts
if (!Object.keys(api).length) {
throw new Error('Could not find Wazuh API entry on wazuh.yml');
@ -77,7 +77,12 @@ export class WazuhApiCtrl {
// Look for socket-related errors
if (this.checkResponseIsDown(response)) {
return ErrorResponse(`ERROR3099 - ${response.body.message || 'Wazuh not ready yet'}`, 3099, 500, reply);
return ErrorResponse(
`ERROR3099 - ${response.body.message || 'Wazuh not ready yet'}`,
3099,
500,
reply
);
}
// Store error and data fields from the Wazuh API into different variables
@ -142,7 +147,7 @@ export class WazuhApiCtrl {
try {
const id = Object.keys(api)[0];
const host = api[id];
const options = ApiHelper.buildOptionsObject(host);
const options = ApiHelper.buildOptionsObject(host);
const response = await needle(
'get',
`${host.url}:${host.port}/version`,
@ -151,7 +156,13 @@ export class WazuhApiCtrl {
);
if (this.checkResponseIsDown(response)) {
return ErrorResponse(`ERROR3099 - ${response.body.message || 'Wazuh not ready yet'}`, 3099, 500, reply);
return ErrorResponse(
`ERROR3099 - ${response.body.message ||
'Wazuh not ready yet'}`,
3099,
500,
reply
);
}
if (
@ -245,7 +256,12 @@ export class WazuhApiCtrl {
const responseIsDown = this.checkResponseIsDown(response);
if (responseIsDown) {
return ErrorResponse(`ERROR3099 - ${response.body.message || 'Wazuh not ready yet'}`, 3099, 500, reply);
return ErrorResponse(
`ERROR3099 - ${response.body.message || 'Wazuh not ready yet'}`,
3099,
500,
reply
);
}
// Check wrong credentials
@ -344,7 +360,7 @@ export class WazuhApiCtrl {
if (!req.headers.id) {
return pciRequirementsFile;
}
const apiId = req.headers.id;
const api = await this.manageHosts.getHostById(apiId);
@ -360,7 +376,7 @@ export class WazuhApiCtrl {
400,
reply
);
}
}
const response = await needle(
'get',
@ -465,7 +481,7 @@ export class WazuhApiCtrl {
400,
reply
);
}
}
const response = await needle(
'get',
@ -561,7 +577,7 @@ export class WazuhApiCtrl {
400,
reply
);
}
}
const response = await needle(
'get',
@ -623,7 +639,7 @@ export class WazuhApiCtrl {
if (!req.headers.id) {
return nistRequirementsFile;
}
const apiId = req.headers.id;
const api = await this.manageHosts.getHostById(apiId);
@ -639,7 +655,7 @@ export class WazuhApiCtrl {
400,
reply
);
}
}
const response = await needle(
'get',
@ -787,7 +803,7 @@ export class WazuhApiCtrl {
404,
reply
);
}
}
if (!data) {
data = {};
@ -845,7 +861,12 @@ export class WazuhApiCtrl {
'wazuh-api:makeRequest',
'Wazuh API is online but Wazuh is not ready yet'
);
return ErrorResponse(`ERROR3099 - ${response.body.message || 'Wazuh not ready yet'}`, 3099, 500, reply);
return ErrorResponse(
`ERROR3099 - ${response.body.message || 'Wazuh not ready yet'}`,
3099,
500,
reply
);
}
}
}
@ -877,14 +898,24 @@ export class WazuhApiCtrl {
const responseIsDown = this.checkResponseIsDown(response);
if (responseIsDown) {
return ErrorResponse(`ERROR3099 - ${response.body.message || 'Wazuh not ready yet'}`, 3099, 500, reply);
return ErrorResponse(
`ERROR3099 - ${response.body.message || 'Wazuh not ready yet'}`,
3099,
500,
reply
);
}
const responseBody = (response || {}).body || {};
let responseData = responseBody.data;
if (!responseData) {
responseData = typeof responseData === 'string' && path.includes('/files') && method === 'GET' ? ' ' : false
response.body.data = responseData
responseData =
typeof responseData === 'string' &&
path.includes('/files') &&
method === 'GET'
? ' '
: false;
response.body.data = responseData;
}
const responseError = responseBody.error || false;
@ -931,7 +962,7 @@ export class WazuhApiCtrl {
if (!Object.keys(api).length) {
//Can not get credentials from wazuh-hosts
throw new Error('Could not get host credentials');
}
}
if (!method.match(/^(?:GET|PUT|POST|DELETE)$/)) {
log('wazuh-api:makeRequest', 'Request method is not valid.');
@ -996,9 +1027,9 @@ export class WazuhApiCtrl {
log('wazuh-api:makeRequest', 'Request method is not valid.');
//Method is not a valid HTTP request method
return ErrorResponse('Request method is not valid.', 3015, 400, reply);
}else if (!req.payload.path) {
} else if (!req.payload.path) {
return ErrorResponse('Missing param: path', 3016, 400, reply);
}else if (!req.payload.path.match(/^\/.+/)) {
} else if (!req.payload.path.match(/^\/.+/)) {
log('wazuh-api:makeRequest', 'Request path is not valid.');
//Path doesn't start with '/'
return ErrorResponse('Request path is not valid.', 3015, 400, reply);
@ -1078,9 +1109,7 @@ export class WazuhApiCtrl {
? req.payload.filters
: [];
const config = await this.manageHosts.getHostById(
req.payload.id
);
const config = await this.manageHosts.getHostById(req.payload.id);
let tmpPath = req.payload.path;
@ -1140,10 +1169,7 @@ export class WazuhApiCtrl {
if (isAgents || isAgentsOfGroup) {
if (isFiles) {
fields = [
'filename',
'hash'
];
fields = ['filename', 'hash'];
} else {
fields = [
'id',
@ -1227,9 +1253,7 @@ export class WazuhApiCtrl {
if (!req.params || !req.params.api)
throw new Error('Field api is required');
const config = await this.manageHosts.getHostById(
req.params.api
);
const config = await this.manageHosts.getHostById(req.params.api);
const headers = ApiHelper.buildOptionsObject(config);
@ -1323,7 +1347,9 @@ export class WazuhApiCtrl {
*/
getTimeStamp(req, reply) {
try {
const source = JSON.parse(fs.readFileSync(this.updateRegistry.file, 'utf8'));
const source = JSON.parse(
fs.readFileSync(this.updateRegistry.file, 'utf8')
);
if (source.installationDate && source.lastRestart) {
log(
'wazuh-api:getTimeStamp',
@ -1356,7 +1382,9 @@ export class WazuhApiCtrl {
*/
async getSetupInfo(req, reply) {
try {
const source = JSON.parse(fs.readFileSync(this.updateRegistry.file, 'utf8'));
const source = JSON.parse(
fs.readFileSync(this.updateRegistry.file, 'utf8')
);
return !Object.values(source).length
? { statusCode: 200, data: '' }
: { statusCode: 200, data: source };

View File

@ -35,22 +35,24 @@ export class WazuhHostsCtrl {
return result;
} catch (error) {
log('wazuh-hosts:getHostsEntries', error.message || error);
const errorResponse = reply ? ErrorResponse(error.message || error, 2001, 500, reply) : error;
const errorResponse = reply
? ErrorResponse(error.message || error, 2001, 500, reply)
: error;
return errorResponse;
}
}
/**
* Joins the hosts with the related information in the registry
* @param {Object} hosts
* @param {Object} registry
* @param {Object} hosts
* @param {Object} registry
*/
joinHostRegistry(hosts, registry, removePassword = true) {
try {
const joined = [];
hosts.forEach(h => {
const id = Object.keys(h)[0];
const api = Object.assign(h[id], {id: id});
const api = Object.assign(h[id], { id: id });
const host = Object.assign(api, registry[id]);
if (removePassword) delete host.password;
joined.push(host);
@ -61,11 +63,11 @@ export class WazuhHostsCtrl {
}
}
/**
* This update an API hostname
* @param {Object} req
* @param {Object} reply
* Status response or ErrorResponse
*/
* This update an API hostname
* @param {Object} req
* @param {Object} reply
* Status response or ErrorResponse
*/
async updateClusterInfo(req, reply) {
try {
const id = req.params.id;
@ -79,7 +81,8 @@ export class WazuhHostsCtrl {
} catch (error) {
log('wazuh-hosts:updateClusterInfo', error.message || error);
return ErrorResponse(
`Could not update data in wazuh-registry.json due to ${error.message || error}`,
`Could not update data in wazuh-registry.json due to ${error.message ||
error}`,
2012,
500,
reply
@ -95,13 +98,15 @@ export class WazuhHostsCtrl {
async removeOrphanEntries(req, reply) {
try {
log('wazuh-hosts:cleanRegistry', 'Cleaning registry', 'debug');
if (!req.payload && !req.payload.entries) throw new Error('No entries given to check');
await this.updateRegistry.removeOrphanEntries(req.payload.entries)
if (!req.payload && !req.payload.entries)
throw new Error('No entries given to check');
await this.updateRegistry.removeOrphanEntries(req.payload.entries);
return { statusCode: 200, message: 'ok' };
} catch (error) {
log('wazuh-hosts:cleanRegistry', error.message || error);
return ErrorResponse(
`Could not clean entries in the wazuh-registry.json due to ${error.message || error}`,
`Could not clean entries in the wazuh-registry.json due to ${error.message ||
error}`,
2013,
500,
reply

View File

@ -43,7 +43,7 @@ export function Initialize(server) {
: 'wazuh-alerts-3.x-*';
global.XPACK_RBAC_ENABLED =
configurationFile &&
typeof configurationFile['xpack.rbac.enabled'] !== 'undefined'
typeof configurationFile['xpack.rbac.enabled'] !== 'undefined'
? configurationFile['xpack.rbac.enabled']
: true;
} catch (e) {
@ -110,7 +110,6 @@ export function Initialize(server) {
}
};
/**
* Checks if the .wazuh index exist in order to migrate to wazuh.yml
*/
@ -123,11 +122,15 @@ export function Initialize(server) {
if (result) {
try {
const data = await wzWrapper.getWazuhAPIEntries();
const apiEntries = (((data || {}).hits || {}).hits || []);
await manageHosts.migrateFromIndex(apiEntries)
log('initialize:checkWazuhIndex', 'Index .wazuh will be removed and its content will be migrated to wazuh.yml', 'debug');
const apiEntries = ((data || {}).hits || {}).hits || [];
await manageHosts.migrateFromIndex(apiEntries);
log(
'initialize:checkWazuhIndex',
'Index .wazuh will be removed and its content will be migrated to wazuh.yml',
'debug'
);
// Check if all APIs entries were migrated properly and delete it from the .wazuh index
await checkProperlyMigrate();
await checkProperlyMigrate();
await wzWrapper.deleteIndexByName('.wazuh');
} catch (error) {
throw new Error(error);
@ -147,7 +150,7 @@ export function Initialize(server) {
let apisIndex = await wzWrapper.getWazuhAPIEntries();
const hosts = await manageHosts.getHosts();
apisIndex = (apisIndex.hits || {}).hits || [];
const apisIndexKeys = apisIndex.map(api => {
return api._id;
});
@ -157,19 +160,24 @@ export function Initialize(server) {
// Get into an array the API entries that were not migrated, if the length is 0 then all the API entries were properly migrated.
const rest = apisIndexKeys.filter(k => {
return !hostsKeys.includes(k)
return !hostsKeys.includes(k);
});
if (rest.length) {
throw new Error(`Cannot migrate all API entries, missed entries: (${rest.toString()})`)
throw new Error(
`Cannot migrate all API entries, missed entries: (${rest.toString()})`
);
}
log('initialize:checkProperlyMigrate', 'The API entries migration was successful', 'debug');
log(
'initialize:checkProperlyMigrate',
'The API entries migration was successful',
'debug'
);
} catch (error) {
log('initialize:checkProperlyMigrate', `${error}`, 'error');
return Promise.reject(error);
}
}
};
/**
* Checks if the .wazuh-version exists, in this case it will be deleted and the wazuh-registry.json will be created
@ -289,7 +297,7 @@ export function Initialize(server) {
return Promise.reject(
new Error(
`Error creating ${
wzWrapper.WZ_KIBANA_INDEX
wzWrapper.WZ_KIBANA_INDEX
} index due to ${error.message || error}`
)
);
@ -310,7 +318,7 @@ export function Initialize(server) {
return Promise.reject(
new Error(
`Error creating template for ${
wzWrapper.WZ_KIBANA_INDEX
wzWrapper.WZ_KIBANA_INDEX
} due to ${error.message || error}`
)
);

View File

@ -22,11 +22,10 @@ export class ManageHosts {
this.updateRegistry = new UpdateRegistry();
}
/**
* Composes the host structure
* @param {Object} host
* @param {String} id
* @param {Object} host
* @param {String} id
*/
composeHost(host, id) {
try {
@ -44,12 +43,12 @@ export class ManageHosts {
/**
* Regex to build the host
* @param {Object} host
* @param {Object} host
*/
composeRegex(host) {
try {
const hostId = Object.keys(host)[0];
const reg = `\\s*-\\s*${hostId}\\s*:\\s*\\n*\\s*url\\s*:\\s*\\S*\\s*\\n*\\s*port\\s*:\\s*\\S*\\s*\\n*\\s*user\\s*:\\s*\\S*\\s*\\n*\\s*password\\s*:\\s*\\S*`
const reg = `\\s*-\\s*${hostId}\\s*:\\s*\\n*\\s*url\\s*:\\s*\\S*\\s*\\n*\\s*port\\s*:\\s*\\S*\\s*\\n*\\s*user\\s*:\\s*\\S*\\s*\\n*\\s*password\\s*:\\s*\\S*`;
log('manage-hosts:composeRegex', 'Composing regex', 'debug');
return new RegExp(`${reg}`, 'gm');
} catch (error) {
@ -102,7 +101,9 @@ export class ManageHosts {
async getCurrentHostsIds() {
try {
const hosts = await this.getHosts();
const ids = hosts.map(h => { return Object.keys(h)[0] })
const ids = hosts.map(h => {
return Object.keys(h)[0];
});
log('manage-hosts:getCurrentHostsIds', 'Getting hosts ids', 'debug');
return ids;
} catch (error) {
@ -113,15 +114,17 @@ export class ManageHosts {
/**
* Get host by id
* @param {String} id
* @param {String} id
*/
async getHostById(id) {
try {
log('manage-hosts:getHostById', `Getting host ${id}`, 'debug');
const hosts = await this.getHosts();
const host = hosts.filter(h => { return Object.keys(h)[0] == id });
const host = hosts.filter(h => {
return Object.keys(h)[0] == id;
});
const key = Object.keys(host[0])[0];
const result = Object.assign(host[0][key], {id: key}) || {};
const result = Object.assign(host[0][key], { id: key }) || {};
return result;
} catch (error) {
log('manage-hosts:getHostById', error.message || error);
@ -131,18 +134,15 @@ export class ManageHosts {
/**
* Decodes the API password
* @param {String} password
* @param {String} password
*/
decodeApiPassword(password) {
return Buffer.from(
password,
'base64'
).toString('ascii');
return Buffer.from(password, 'base64').toString('ascii');
}
/**
* Iterate the array with the API entries in given from the .wazuh index in order to create a valid array
* @param {Object} apiEntries
* @param {Object} apiEntries
*/
transformIndexedApis(apiEntries) {
const entries = [];
@ -161,7 +161,11 @@ export class ManageHosts {
};
entries.push(api);
});
log('manage-hosts:transformIndexedApis', 'Transforming index API schedule to wazuh.yml', 'debug');
log(
'manage-hosts:transformIndexedApis',
'Transforming index API schedule to wazuh.yml',
'debug'
);
} catch (error) {
log('manage-hosts:transformIndexedApis', error.message || error);
throw error;
@ -169,11 +173,10 @@ export class ManageHosts {
return entries;
}
/**
* Calls transformIndexedApis() to get the entries to migrate and after that calls addSeveralHosts()
* @param {Object} apiEntries
*/
* Calls transformIndexedApis() to get the entries to migrate and after that calls addSeveralHosts()
* @param {Object} apiEntries
*/
async migrateFromIndex(apiEntries) {
try {
const apis = this.transformIndexedApis(apiEntries);
@ -186,13 +189,19 @@ export class ManageHosts {
/**
* Receives an array of hosts and checks if any host is already in the wazuh.yml, in this case is removed from the received array and returns the resulting array
* @param {Array} hosts
* @param {Array} hosts
*/
async cleanExistingHosts(hosts) {
try {
const currentHosts = await this.getCurrentHostsIds();
const cleanHosts = hosts.filter(h => { return !currentHosts.includes(h.id) });
log('manage-hosts:cleanExistingHosts', 'Preventing add existings hosts', 'debug');
const cleanHosts = hosts.filter(h => {
return !currentHosts.includes(h.id);
});
log(
'manage-hosts:cleanExistingHosts',
'Preventing add existings hosts',
'debug'
);
return cleanHosts;
} catch (error) {
log('manage-hosts:cleanExistingHosts', error.message || error);
@ -204,23 +213,24 @@ export class ManageHosts {
* Throws an error is the wazuh.yml is busy
*/
checkBusy() {
if (this.busy) throw new Error('Another process is writting the configuration file');
if (this.busy)
throw new Error('Another process is writting the configuration file');
}
/**
* Recursive function used to add several APIs entries
* @param {Array} hosts
* @param {Array} hosts
*/
async addSeveralHosts(hosts) {
try {
log('manage-hosts:addSeveralHosts', 'Adding several', 'debug');
const hostsToAdd = await this.cleanExistingHosts(hosts);
if (!hostsToAdd.length) return 'There are not APIs entries to migrate'
if (!hostsToAdd.length) return 'There are not APIs entries to migrate';
for (let idx in hostsToAdd) {
const entry = hostsToAdd[idx];
await this.addHost(entry);
}
return 'All APIs entries were migrated to the wazuh.yml'
return 'All APIs entries were migrated to the wazuh.yml';
} catch (error) {
log('manage-hosts:addSeveralHosts', error.message || error);
return Promise.reject(error);
@ -229,7 +239,7 @@ export class ManageHosts {
/**
* Add a single host
* @param {Obeject} host
* @param {Obeject} host
*/
async addHost(host) {
const id = host.id || new Date().getTime();
@ -237,23 +247,35 @@ export class ManageHosts {
let data = await fs.readFileSync(this.file, { encoding: 'utf-8' });
try {
this.checkBusy();
const hosts = await this.getHosts() || [];
const hosts = (await this.getHosts()) || [];
this.busy = true;
if (!hosts.length) {
const hostsExists = await this.checkIfHostsKeyExists();
const result = !hostsExists ? `${data}\nhosts:\n${compose}\n` : `${data}\n${compose}\n`;
const result = !hostsExists
? `${data}\nhosts:\n${compose}\n`
: `${data}\n${compose}\n`;
await fs.writeFileSync(this.file, result, 'utf8');
} else {
const lastHost = (hosts || []).pop();
if (lastHost) {
const lastHostObject = this.composeHost(lastHost[Object.keys(lastHost)[0]], Object.keys(lastHost)[0]);
const lastHostObject = this.composeHost(
lastHost[Object.keys(lastHost)[0]],
Object.keys(lastHost)[0]
);
const regex = this.composeRegex(lastHost);
const replace = data.replace(regex, `\n${lastHostObject}\n${compose}\n`)
const replace = data.replace(
regex,
`\n${lastHostObject}\n${compose}\n`
);
await fs.writeFileSync(this.file, replace, 'utf8');
}
}
this.busy = false;
this.updateRegistry.migrateToRegistry(id, host.cluster_info, host.extensions);
this.updateRegistry.migrateToRegistry(
id,
host.cluster_info,
host.extensions
);
log('manage-hosts:addHost', `Host ${id} was properly added`, 'debug');
return id;
} catch (error) {
@ -271,29 +293,36 @@ export class ManageHosts {
let data = await fs.readFileSync(this.file, { encoding: 'utf-8' });
try {
this.checkBusy();
const hosts = await this.getHosts() || [];
const hosts = (await this.getHosts()) || [];
this.busy = true;
if (!hosts.length) {
throw new Error('There are not configured hosts.');
} else {
const hostsNumber = hosts.length;
const target = (hosts || []).find((element) => {
const target = (hosts || []).find(element => {
return Object.keys(element)[0] === req.params.id;
});
if (!target) {
throw new Error(`Host ${req.params.id} not found.`);
}
const regex = this.composeRegex(target);
const result = data.replace(regex, ``)
const result = data.replace(regex, ``);
await fs.writeFileSync(this.file, result, 'utf8');
if (hostsNumber === 1) {
data = await fs.readFileSync(this.file, { encoding: 'utf-8' });
const clearHosts = data.replace(new RegExp(`hosts:\\s*[\\n\\r]`, 'gm'), '')
const clearHosts = data.replace(
new RegExp(`hosts:\\s*[\\n\\r]`, 'gm'),
''
);
await fs.writeFileSync(this.file, clearHosts, 'utf8');
}
}
this.busy = false;
log('manage-hosts:deleteHost', `Host ${req.params.id} was properly deleted`, 'debug');
log(
'manage-hosts:deleteHost',
`Host ${req.params.id} was properly deleted`,
'debug'
);
return true;
} catch (error) {
this.busy = false;
@ -304,19 +333,19 @@ export class ManageHosts {
/**
* Updates the hosts information
* @param {String} id
* @param {Object} host
* @param {String} id
* @param {Object} host
*/
async updateHost(id, host) {
let data = await fs.readFileSync(this.file, { encoding: 'utf-8' });
try {
this.checkBusy();
const hosts = await this.getHosts() || [];
const hosts = (await this.getHosts()) || [];
this.busy = true;
if (!hosts.length) {
throw new Error('There are not configured hosts.');
} else {
const target = (hosts || []).find((element) => {
const target = (hosts || []).find(element => {
return Object.keys(element)[0] === id;
});
if (!target) {
@ -327,7 +356,11 @@ export class ManageHosts {
await fs.writeFileSync(this.file, result, 'utf8');
}
this.busy = false;
log('manage-hosts:updateHost', `Host ${id} was properly updated`, 'debug');
log(
'manage-hosts:updateHost',
`Host ${id} was properly updated`,
'debug'
);
return true;
} catch (error) {
this.busy = false;

View File

@ -71,7 +71,11 @@ export class UpdateConfigurationFile {
const { key, value } = (input || {}).payload || {};
this.updateLine(key, value, typeof configuration[key] !== 'undefined');
this.busy = false;
log('update-configuration:updateConfiguration', 'Updating configuration', 'debug');
log(
'update-configuration:updateConfiguration',
'Updating configuration',
'debug'
);
return { needRestart: needRestartFields.includes(key) };
} catch (error) {
log('update-configuration:updateConfiguration', error.message || error);

View File

@ -19,13 +19,16 @@ export class UpdateRegistry {
this.file = path.join(__dirname, '../../server/wazuh-registry.json');
}
/**
* Reads the Wazuh registry content
*/
async readContent() {
try {
log('update-registry:readContent', 'Reading wazuh-registry.json content', 'debug');
log(
'update-registry:readContent',
'Reading wazuh-registry.json content',
'debug'
);
const content = await fs.readFileSync(this.file, { encoding: 'utf-8' });
return JSON.parse(content);
} catch (error) {
@ -49,9 +52,9 @@ export class UpdateRegistry {
}
/**
* Returns the cluster information associated to an API id
* @param {String} id
*/
* Returns the cluster information associated to an API id
* @param {String} id
*/
async getHostById(id) {
try {
if (!id) throw new Error('API id is missing');
@ -65,11 +68,15 @@ export class UpdateRegistry {
/**
* Writes the wazuh-registry.json
* @param {Object} content
* @param {Object} content
*/
async writeContent(content) {
try {
log('update-registry:writeContent', 'Writting wazuh-registry.json content', 'debug');
log(
'update-registry:writeContent',
'Writting wazuh-registry.json content',
'debug'
);
if (this.busy) {
throw new Error('Another process is updating the registry file');
}
@ -78,14 +85,14 @@ export class UpdateRegistry {
this.busy = false;
} catch (error) {
log('update-registry:writeContent', error.message || error);
return Promise.reject(error)
return Promise.reject(error);
}
}
/**
* Checks if the host exist in order to update the data, otherwise creates it
* @param {String} id
* @param {Object} hosts
* @param {String} id
* @param {Object} hosts
*/
checkHost(id, hosts) {
try {
@ -98,18 +105,23 @@ export class UpdateRegistry {
/**
* Migrates the cluster information and extensions associated to an API id
* @param {String} id
* @param {Object} clusterInfo
* @param {Object} clusterExtensions
* @param {String} id
* @param {Object} clusterInfo
* @param {Object} clusterExtensions
*/
async migrateToRegistry(id, clusterInfo, clusterExtensions) {
try {
const content = await this.readContent();
if (!Object.keys(content).includes('hosts')) Object.assign(content, {hosts: {}});
const info = { cluster_info: clusterInfo, extensions: clusterExtensions};
if (!Object.keys(content).includes('hosts'))
Object.assign(content, { hosts: {} });
const info = { cluster_info: clusterInfo, extensions: clusterExtensions };
content.hosts[id] = info;
await this.writeContent(content);
log('update-registry:migrateToRegistry', `API ${id} was properly migrated`, 'debug');
log(
'update-registry:migrateToRegistry',
`API ${id} was properly migrated`,
'debug'
);
return info;
} catch (error) {
log('update-registry:migrateToRegistry', error.message || error);
@ -117,10 +129,10 @@ export class UpdateRegistry {
}
}
/**
/**
* Updates the cluster-information or manager-information in the registry
* @param {String} id
* @param {Object} clusterInfo
* @param {String} id
* @param {Object} clusterInfo
*/
async updateClusterInfo(id, clusterInfo) {
try {
@ -129,7 +141,11 @@ export class UpdateRegistry {
if (!content.hosts[id]) content.hosts[id] = {};
content.hosts[id].cluster_info = clusterInfo;
await this.writeContent(content);
log('update-registry:updateClusterInfo', `API ${id} information was properly updated`, 'debug');
log(
'update-registry:updateClusterInfo',
`API ${id} information was properly updated`,
'debug'
);
return id;
} catch (error) {
log('update-registry:updateClusterInfo', error.message || error);
@ -137,17 +153,21 @@ export class UpdateRegistry {
}
}
/**
/**
* Updates the cluster-information or manager-information in the registry
* @param {String} id
* @param {Object} clusterInfo
* @param {String} id
* @param {Object} clusterInfo
*/
async updateAPIExtensions(id, extensions) {
try {
const content = await this.readContent();
content.hosts[id].extensions = extensions;
await this.writeContent(content);
log('update-registry:updateAPIExtensions', `API ${id} extensions were properly updated`, 'debug');
log(
'update-registry:updateAPIExtensions',
`API ${id} extensions were properly updated`,
'debug'
);
return id;
} catch (error) {
log('update-registry:updateAPIHostname', error.message || error);
@ -157,7 +177,7 @@ export class UpdateRegistry {
/**
* Remove the given ids from the registry host entries
* @param {Array} ids
* @param {Array} ids
*/
async removeHostEntries(ids) {
try {
@ -177,11 +197,19 @@ export class UpdateRegistry {
*/
async removeOrphanEntries(hosts) {
try {
log('update-registry:removeOrphanEntries', 'Checking orphan registry entries', 'debug');
log(
'update-registry:removeOrphanEntries',
'Checking orphan registry entries',
'debug'
);
const entries = await this.getHosts();
const hostsKeys = hosts.map(h => {return h.id});
const hostsKeys = hosts.map(h => {
return h.id;
});
const entriesKeys = Object.keys(entries);
const diff = entriesKeys.filter(e => {return !hostsKeys.includes(e)});
const diff = entriesKeys.filter(e => {
return !hostsKeys.includes(e);
});
await this.removeHostEntries(diff);
} catch (error) {
log('update-registry:removeOrphanEntries', error.message || error);
@ -189,4 +217,3 @@ export class UpdateRegistry {
}
}
}

View File

@ -249,7 +249,7 @@ export class Monitoring {
user: element.user,
password: element.password,
url: element.url,
port: element.port,
port: element.port
};
log(
'monitoring:loadCredentials',

View File

@ -32,7 +32,6 @@ export function WazuhHostsRoutes(server) {
}
});
// Checks the orphan hosts in the registry in order to delete them
server.route({
method: 'POST',

View File

@ -4,13 +4,13 @@ import { resolveKibanaPath } from '@kbn/plugin-helpers';
import { pageObjects } from './page_objects';
import { services } from './services';
export default async function ({ readConfigFile }) {
const kibanaConfig = await readConfigFile(resolveKibanaPath('test/functional/config.js'));
export default async function({ readConfigFile }) {
const kibanaConfig = await readConfigFile(
resolveKibanaPath('test/functional/config.js')
);
return {
testFiles: [
require.resolve('./apps/overview'),
],
testFiles: [require.resolve('./apps/overview')],
services: {
...kibanaConfig.get('services'),
@ -19,22 +19,22 @@ export default async function ({ readConfigFile }) {
pageObjects: {
...kibanaConfig.get('pageObjects'),
...pageObjects,
...pageObjects
},
apps: {
...kibanaConfig.get('apps'),
wazuh: {
pathname: '/app/wazuh',
pathname: '/app/wazuh'
}
},
esArchiver: {
directory: resolve(__dirname, './es_archives'),
directory: resolve(__dirname, './es_archives')
},
screenshots: {
directory: resolve(__dirname, './tmp/screenshots'),
directory: resolve(__dirname, './tmp/screenshots')
},
servers: kibanaConfig.get('servers'),
@ -47,7 +47,7 @@ export default async function ({ readConfigFile }) {
...kibanaConfig.get('kbnTestServer.serverArgs'),
'--oss',
`--plugin-path=${resolve(__dirname, '../../')}`
],
},
]
}
};
}
}

View File

@ -8,26 +8,26 @@ export function ApiProvider({ getService, getPageObjects }) {
const testSubjects = getService('testSubjects');
const toasts = getService('toasts');
/**
* The Api Page class provides functions to automate the process
* The Api Page class provides functions to automate the process
* of testing the API configuration
*
* @class ApiPage
*/
class ApiPage {
/**
* Complete the form to create a new Api connection.
*
* @param {string} [type='apiConfig'] Set the form type
* - apiConfig: For new API form
* - apiTableEdit: For edit API form
* @memberof ApiPage
*/
async completeApiForm (type='apiConfig') {
if (!(type == 'apiConfig' || type == 'apiTableEdit')){
throw new Error(`Invalid type: ${type}; use 'apiConfig' or 'apiTableEdit'`);
/**
* Complete the form to create a new Api connection.
*
* @param {string} [type='apiConfig'] Set the form type
* - apiConfig: For new API form
* - apiTableEdit: For edit API form
* @memberof ApiPage
*/
async completeApiForm(type = 'apiConfig') {
if (!(type == 'apiConfig' || type == 'apiTableEdit')) {
throw new Error(
`Invalid type: ${type}; use 'apiConfig' or 'apiTableEdit'`
);
}
await testSubjects.setValue(`${type}Username`, 'foo');
log.debug('insert the user');
@ -48,7 +48,7 @@ export function ApiProvider({ getService, getPageObjects }) {
* @param {string} tab testSubjects value
* @memberof ApiPage
*/
async checkTabDisabled (tab) {
async checkTabDisabled(tab) {
await testSubjects.click(tab);
await PageObjects.common.sleep(1500);
expect(await browser.getCurrentUrl()).to.contain('tab=api');
@ -60,7 +60,7 @@ export function ApiProvider({ getService, getPageObjects }) {
*
* @memberof ApiPage
*/
async checkIfAllTabsAreDisables () {
async checkIfAllTabsAreDisables() {
await this.checkTabDisabled('wzMenuOverview');
await this.checkTabDisabled('wzMenuManagement');
await this.checkTabDisabled('wzMenuAgents');
@ -69,13 +69,13 @@ export function ApiProvider({ getService, getPageObjects }) {
}
/**
* Press all refresh buttons of the API list and
* Press all refresh buttons of the API list and
* the response in the toasts
*
* @param {array} buttonList list of button WebElementWrapper
* @memberof ApiPage
*/
async pressAllCheckConnectionButtons (buttonList) {
async pressAllCheckConnectionButtons(buttonList) {
for (const key in buttonList) {
if (buttonList.hasOwnProperty(key)) {
const checkButton = buttonList[key];
@ -83,7 +83,9 @@ export function ApiProvider({ getService, getPageObjects }) {
await PageObjects.common.sleep(1000);
await checkButton.click();
await PageObjects.common.sleep(2000);
expect(await toasts.findMessageInToasts('Settings. Connection success')).to.be.ok();
expect(
await toasts.findMessageInToasts('Settings. Connection success')
).to.be.ok();
await PageObjects.common.clearAllToasts();
}
}
@ -95,13 +97,17 @@ export function ApiProvider({ getService, getPageObjects }) {
* @param {array} apiButtonList list of button WebElementWrapper
* @memberof ApiPage
*/
async editAllApis (apiButtonList) {
async editAllApis(apiButtonList) {
for (const apiButton of apiButtonList) {
await apiButton.moveMouseTo();
await PageObjects.common.sleep(1000);
await apiButton.click();
await this.completeApiForm('apiTableEdit');
expect(await toasts.findMessageInToasts('Settings. The API was updated successfully')).to.be.ok();
expect(
await toasts.findMessageInToasts(
'Settings. The API was updated successfully'
)
).to.be.ok();
await PageObjects.common.clearAllToasts();
}
}
@ -111,14 +117,20 @@ export function ApiProvider({ getService, getPageObjects }) {
*
* @memberof ApiPage
*/
async deleteAllApis () {
const deleteApiButtonList = await testSubjects.findAll('apiTableTrashButton');
async deleteAllApis() {
const deleteApiButtonList = await testSubjects.findAll(
'apiTableTrashButton'
);
for (const deleteButton of deleteApiButtonList) {
await deleteButton.moveMouseTo();
await PageObjects.common.sleep(1000);
await deleteButton.click();
await PageObjects.common.sleep(1500);
expect(await toasts.findMessageInToasts('Settings. The API was removed successfully')).to.be.ok();
expect(
await toasts.findMessageInToasts(
'Settings. The API was removed successfully'
)
).to.be.ok();
await PageObjects.common.clearAllToasts();
}
}
@ -128,7 +140,7 @@ export function ApiProvider({ getService, getPageObjects }) {
*
* @memberof ApiPage
*/
async navigateToApiSetting () {
async navigateToApiSetting() {
await testSubjects.click('wzMenuSettings');
await testSubjects.click('settingMenuApi');
}
@ -138,14 +150,14 @@ export function ApiProvider({ getService, getPageObjects }) {
*
* @memberof ApiPage
*/
async insertNewApi () {
async insertNewApi() {
const fromUrl = await browser.getCurrentUrl();
await this.navigateToApiSetting();
await testSubjects.click('apiTableAddButton');
await this.completeApiForm();
await find.clickByCssSelector('[test-api-default="false"]');
await browser.get(fromUrl);
await PageObjects.common.waitUntilUrlIncludes('tab=welcome');
await PageObjects.common.waitUntilUrlIncludes('tab=welcome');
}
/**
@ -153,7 +165,7 @@ export function ApiProvider({ getService, getPageObjects }) {
*
* @memberof ApiPage
*/
async deleteNewApi () {
async deleteNewApi() {
const fromUrl = await browser.getCurrentUrl();
await this.navigateToApiSetting();
await PageObjects.common.sleep(500);
@ -163,23 +175,24 @@ export function ApiProvider({ getService, getPageObjects }) {
}
/**
* Remove the API marked as default
* Remove the API marked as default
*
* @returns
* @memberof ApiPage
*/
async clickTrashDefaultApi () {
async clickTrashDefaultApi() {
const rows = await find.allByCssSelector('table>tbody>tr');
for (const row of rows) {
try {
await row.findByCssSelector('[test-api-default="true"]')
const trashButton = await row.findByCssSelector('[data-test-subj="apiTableTrashButton"]')
await row.findByCssSelector('[test-api-default="true"]');
const trashButton = await row.findByCssSelector(
'[data-test-subj="apiTableTrashButton"]'
);
await trashButton.click();
return;
} catch (error) {}
}
}
}
return new ApiPage;
}
return new ApiPage();
}

View File

@ -2,6 +2,6 @@ import { ApiProvider } from './api_page';
import { WazuhCommonProvider } from './wazuh_common_page';
export const pageObjects = {
api: ApiProvider,
wazuhCommon: WazuhCommonProvider,
}
api: ApiProvider,
wazuhCommon: WazuhCommonProvider
};

View File

@ -22,13 +22,12 @@ export function WazuhCommonProvider({ getService, getPageObjects }) {
* @class WazuhCommonPage
*/
class WazuhCommonPage {
/**
* Navigate to `Security events` without the timestamp parameter in the URL
*
* @memberof WazuhCommonPage
*/
async OpenSecurityEvents () {
async OpenSecurityEvents() {
log.debug('Open Security events');
await PageObjects.common.navigateToApp('settings');
await appsMenu.clickLink('Wazuh');
@ -41,7 +40,7 @@ export function WazuhCommonProvider({ getService, getPageObjects }) {
*
* @memberof WazuhCommonPage
*/
async OpenIntegrityMonitoring () {
async OpenIntegrityMonitoring() {
log.debug('Open Security events');
await PageObjects.common.navigateToApp('settings');
await appsMenu.clickLink('Wazuh');
@ -49,19 +48,20 @@ export function WazuhCommonProvider({ getService, getPageObjects }) {
await testSubjects.click('overviewWelcomeFim');
}
/**
* Select `today` in the commonly used times
*
* @memberof WazuhCommonPage
*/
async setTodayRange () {
async setTodayRange() {
log.debug('Set today in the time range picker');
await PageObjects.timePicker.setCommonlyUsedTime('superDatePickerCommonlyUsed_Today');
await PageObjects.timePicker.setCommonlyUsedTime(
'superDatePickerCommonlyUsed_Today'
);
await PageObjects.common.sleep(3000);
await testSubjects.click('querySubmitButton');
await PageObjects.common.sleep(3000);
}
}
return new WazuhCommonPage;
}
return new WazuhCommonPage();
}

View File

@ -8,16 +8,15 @@ export function ExtensionPopoverProvider({ getService, getPageObjects }) {
* @class ExtensionPopover
*/
class ExtensionPopover {
/**
* Check if the view has PopOvers
*
* @returns {bool}
* @memberof ExtensionPopover
*/
async availablePopovers () {
async availablePopovers() {
const currentUrl = await browser.getCurrentUrl();
if(currentUrl.includes('tab=welcome')){
if (currentUrl.includes('tab=welcome')) {
return true;
}
throw new Error('The current view has not popovers');
@ -31,24 +30,23 @@ export function ExtensionPopoverProvider({ getService, getPageObjects }) {
* @returns {bool} extension status
* @memberof ExtensionPopover
*/
async checkedPopover (key, popOver) {
async checkedPopover(key, popOver) {
await this.availablePopovers();
if (await testSubjects.exists(popOver)){
if (await testSubjects.exists(popOver)) {
await testSubjects.click(popOver);
} else {
throw new Error(`Error to locate ${popOver}`);
throw new Error(`Error to locate ${popOver}`);
}
if (await testSubjects.exists(key, { allowHidden: true })){
if (await testSubjects.exists(key, { allowHidden: true })) {
await testSubjects.click(key);
const result = await testSubjects.getProperty(key, 'checked');
return result;
} else {
throw new Error(`Error to locate ${key}`);
throw new Error(`Error to locate ${key}`);
}
}
}
return new ExtensionPopover();
}
}

View File

@ -15,5 +15,5 @@ export const services = {
esAreaChart: EsAreaChartProvider,
esPieChart: EsPieChartProvider,
esTableViz: EsTableVizProvider,
arrayHelper: ArrayHelperProvider,
}
arrayHelper: ArrayHelperProvider
};