Bump 7.2 into 7.3

This commit is contained in:
JuanCarlos 2019-08-07 10:31:59 +02:00
parent f1006686e8
commit 320825de99
No known key found for this signature in database
GPG Key ID: B1C4FB733616273A
97 changed files with 4032 additions and 6913 deletions

1
.yarnignore Normal file
View File

@ -0,0 +1 @@
plugins/wazuh/server/wazuh-version.json

View File

@ -39,6 +39,8 @@
# Values must to be true or false.
#extensions.pci : true
#extensions.gdpr : true
#extensions.hipaa : true
#extensions.nist : true
#extensions.audit : true
#extensions.oscap : false
#extensions.ciscat : false
@ -57,11 +59,9 @@
#
# ------------------------------ Advanced indices ------------------------------
#
# Configure .wazuh and .wazuh-version indices shards and replicas.
# Configure .wazuh indices shards and replicas.
#wazuh.shards : 1
#wazuh.replicas : 0
#wazuh-version.shards : 1
#wazuh-version.replicas: 0
#
# --------------------------- Index pattern selector ---------------------------
#

View File

@ -1,8 +1,8 @@
{
"name": "wazuh",
"version": "3.9.4",
"revision": "0528",
"code": "0528-0",
"version": "3.10.0",
"revision": "05269",
"code": "0529-0",
"kibana": {
"version": "7.3.0"
},

View File

@ -23,6 +23,7 @@ import {
} from '@elastic/eui';
import { BasicTable } from '../directives/wz-table-eui/components/table';
import { Tabs } from '../directives/wz-tabs-eui/components/tabs';
const app = uiModules.get('app/wazuh', ['react']);
@ -35,4 +36,5 @@ app
.value('EuiBasicTable', EuiBasicTable)
.value('EuiHealth', EuiHealth)
.value('EuiCallOut', EuiCallOut)
.value('BasicTable', BasicTable);
.value('BasicTable', BasicTable)
.value('Tabs', Tabs);

View File

@ -92,10 +92,12 @@ export class AgentsPreviewController {
this.$scope.$on('wazuhFetched', (ev, parameters) => {
ev.stopPropagation();
this.$scope.showNoAgents =
!parameters.items.length > 0 && !parameters.filters.length;
});
this.registerAgentsProps = {
addNewAgent: flag => this.addNewAgent(flag)
};
this.init = false;
//Load
this.load();
@ -201,6 +203,9 @@ export class AgentsPreviewController {
this.osPlatforms = unique.osPlatforms;
this.lastAgent = unique.lastAgent;
this.summary = unique.summary;
if (!this.lastAgent || !this.lastAgent.id) {
this.addNewAgent(true);
}
if (agentsTop.data.data === '') {
this.mostActiveAgent.name = this.appState.getClusterInfo().manager;
@ -225,8 +230,8 @@ export class AgentsPreviewController {
return;
}
registerNewAgent(flag) {
this.$scope.registerNewAgent = flag;
addNewAgent(flag) {
this.addingNewAgent = flag;
}
reloadList() {
@ -245,6 +250,7 @@ export class AgentsPreviewController {
} catch (error) {
this.errorHandler.handle('Error refreshing agents stats');
}
this.$scope.$broadcast('reloadSearchFilterBar', {});
}
openRegistrationDocs() {

View File

@ -14,6 +14,7 @@ import { generateMetric } from '../../utils/generate-metric';
import { TabNames } from '../../utils/tab-names';
import * as FileSaver from '../../services/file-saver';
import { TabDescription } from '../../../server/reporting/tab-description';
import { UnsupportedComponents } from '../../utils/components-os-support';
import {
metricsGeneral,
metricsAudit,
@ -165,7 +166,7 @@ export class AgentsController {
this.$scope.hostMonitoringTabs = ['general', 'fim', 'syscollector'];
this.$scope.systemAuditTabs = ['pm', 'sca', 'audit', 'oscap', 'ciscat'];
this.$scope.securityTabs = ['vuls', 'virustotal', 'osquery', 'docker'];
this.$scope.complianceTabs = ['pci', 'gdpr'];
this.$scope.complianceTabs = ['pci', 'gdpr', 'hipaa', 'nist'];
/**
* This check if given array of items contais a single given item
@ -214,6 +215,9 @@ export class AgentsController {
this.$scope.startVis2Png = () => this.startVis2Png();
this.$scope.shouldShowComponent = component =>
this.shouldShowComponent(component);
this.$scope.$on('$destroy', () => {
this.visFactoryService.clearAll();
});
@ -225,6 +229,14 @@ export class AgentsController {
this.$location.path('/manager/groups');
};
this.$scope.exportConfiguration = enabledComponents => {
this.reportingService.startConfigReport(
this.$scope.agent,
'agentConfig',
enabledComponents
);
};
this.$scope.restartAgent = async agent => {
this.$scope.restartingAgent = true;
try {
@ -437,14 +449,6 @@ export class AgentsController {
};
this.$scope.expand = i => this.expand(i);
this.$scope.welcomeCardsProps = {
switchTab: tab => this.switchTab(tab),
extensions: this.$scope.extensions,
api: this.appState.getCurrentAPI(),
setExtensions: (api, extensions) =>
this.appState.setExtensions(api, extensions)
};
}
/**
* Create metric for given object
@ -562,7 +566,7 @@ export class AgentsController {
this.$scope.agent.status =
(((agentInfo || {}).data || {}).data || {}).status ||
this.$scope.agent.status;
} catch (error) {} // eslint-disable-line
} catch (error) { } // eslint-disable-line
}
try {
@ -579,6 +583,18 @@ export class AgentsController {
this.$scope.selectedGdprIndex = 0;
}
if (tab === 'hipaa') {
const hipaaTabs = await this.commonData.getHIPAA();
this.$scope.hipaaTabs = hipaaTabs;
this.$scope.selectedHipaaIndex = 0;
}
if (tab === 'nist') {
const nistTabs = await this.commonData.getNIST();
this.$scope.nistTabs = nistTabs;
this.$scope.selectedNistIndex = 0;
}
if (tab === 'sca') {
try {
this.$scope.loadSca = true;
@ -598,7 +614,7 @@ export class AgentsController {
if (tab === 'syscollector')
try {
await this.loadSyscollector(this.$scope.agent.id);
} catch (error) {} // eslint-disable-line
} catch (error) { } // eslint-disable-line
if (tab === 'configuration') {
this.$scope.switchConfigurationTab('welcome');
} else {
@ -730,12 +746,13 @@ export class AgentsController {
if (agentInfo && this.$scope.agent.os) {
this.$scope.agentOS =
this.$scope.agent.os.name + ' ' + this.$scope.agent.os.version;
this.$scope.agent.isLinuxOS = this.$scope.agent.os.uname.includes(
'Linux'
);
const isLinux = this.$scope.agent.os.uname.includes('Linux');
this.$scope.agent.agentPlatform = isLinux
? 'linux'
: this.$scope.agent.os.platform;
} else {
this.$scope.agentOS = '-';
this.$scope.agent.isLinuxOS = false;
this.$scope.agent.agentPlatform = false;
}
await this.$scope.switchTab(this.$scope.tab, true);
@ -748,6 +765,7 @@ export class AgentsController {
this.$scope.agent.group && !this.$scope.agent.group.includes(item)
);
this.loadWelcomeCardsProps();
this.$scope.load = false;
this.$scope.$applyAsync();
return;
@ -767,11 +785,48 @@ export class AgentsController {
this.$location.path('/agents-preview');
}
}
this.$scope.load = false;
this.$scope.$applyAsync();
return;
}
shouldShowComponent(component) {
return !(
UnsupportedComponents[this.$scope.agent.agentPlatform] ||
UnsupportedComponents['other']
).includes(component);
}
cleanExtensions(extensions) {
const result = {};
for (const extension in extensions) {
if (
!(
UnsupportedComponents[this.$scope.agent.agentPlatform] ||
UnsupportedComponents['other']
).includes(extension)
) {
result[extension] = extensions[extension];
}
}
return result;
}
/**
* Get available welcome cards after getting the agent
*/
loadWelcomeCardsProps() {
this.$scope.welcomeCardsProps = {
switchTab: tab => this.switchTab(tab),
extensions: this.cleanExtensions(this.$scope.extensions),
agent: this.$scope.agent,
api: this.appState.getCurrentAPI(),
setExtensions: (api, extensions) =>
this.appState.setExtensions(api, extensions)
};
}
switchGroupEdit() {
this.$scope.editGroup = !!!this.$scope.editGroup;
this.$scope.$applyAsync();

View File

@ -0,0 +1,159 @@
import React, { Component } from 'react';
import {
EuiPopover,
EuiButton,
EuiCheckboxGroup,
EuiSpacer,
EuiButtonEmpty
} from '@elastic/eui';
import PropTypes from 'prop-types';
import { UnsupportedComponents } from '../../../utils/components-os-support';
export class ExportConfiguration extends Component {
constructor(props) {
super(props);
this.state = {
buttonDisabled: false,
isPopoverOpen: false
};
const agentOptions = [
'Global configuration',
'Communication',
'Anti-flooding settings',
'Labels',
'Policy monitoring',
{ name: 'oscap', desc: 'OpenSCAP' },
'CIS-CAT',
'Osquery',
'Inventory data',
'Active response',
'Commands',
{ name: 'docker', desc: 'Docker listener' },
'Log collection',
'Integrity monitoring'
];
const groupOptions = ['Configurations', 'Agents in group'];
this.options = [];
const list = this.props.type === 'agent' ? agentOptions : groupOptions;
list.forEach((x, idx) => {
if (
typeof x === 'string' ||
(x.name &&
!(
UnsupportedComponents[this.props.agentPlatform] ||
UnsupportedComponents['other']
).includes(x.name))
) {
this.options.push({ id: `${idx}`, label: x.desc || x });
}
});
let initialChecks = {};
this.options.forEach(x => {
initialChecks[x.id] = true;
});
this.state.checkboxIdToSelectedMap = initialChecks;
}
selectAll(flag) {
let newCheckboxIdToSelectedMap = {};
for (let i = 0; i < this.options.length; i++) {
newCheckboxIdToSelectedMap[`${this.options[i].id}`] = flag;
}
this.setState({
checkboxIdToSelectedMap: newCheckboxIdToSelectedMap,
buttonDisabled: !flag
});
}
exportClick() {
this.setState({
isPopoverOpen: !this.state.isPopoverOpen
});
}
closePopover() {
this.setState({
isPopoverOpen: false
});
}
onChange = optionId => {
const newCheckboxIdToSelectedMap = {
...this.state.checkboxIdToSelectedMap,
...{
[optionId]: !this.state.checkboxIdToSelectedMap[optionId]
}
};
let result = false;
for (let i = 0; i < this.options.length; i++) {
if (newCheckboxIdToSelectedMap[`${this.options[i].id}`] === true) {
result = true;
}
}
this.setState({
checkboxIdToSelectedMap: newCheckboxIdToSelectedMap,
buttonDisabled: !result
});
};
render() {
const button = (
<EuiButton
iconType="importAction"
iconSide="left"
size="s"
onClick={this.exportClick.bind(this)}
>
PDF
</EuiButton>
);
return (
<EuiPopover
id="trapFocus"
ownFocus
button={button}
isOpen={this.state.isPopoverOpen}
closePopover={this.closePopover.bind(this)}
anchorPosition="downRight"
>
<EuiCheckboxGroup
options={this.options}
idToSelectedMap={this.state.checkboxIdToSelectedMap}
onChange={this.onChange}
compressed
/>
<EuiSpacer size="s" />
<EuiButtonEmpty size="xs" onClick={() => this.selectAll(true)}>
Select all
</EuiButtonEmpty>
<EuiSpacer size="s" />
<EuiButtonEmpty size="xs" onClick={() => this.selectAll(false)}>
Unselect all
</EuiButtonEmpty>
<EuiSpacer size="m" />
<EuiButton
isDisabled={this.state.buttonDisabled}
onClick={() => {
this.closePopover();
this.props.exportConfiguration(this.state.checkboxIdToSelectedMap);
}}
fill
>
Generate PDF report
</EuiButton>
</EuiPopover>
);
}
}
ExportConfiguration.propTypes = {
exportConfiguration: PropTypes.func,
type: PropTypes.string,
agentPlatform: PropTypes.string
};

View File

@ -0,0 +1,191 @@
import React, { Component, Fragment } from 'react';
import {
EuiSteps,
EuiFlexGroup,
EuiFlexItem,
EuiPanel,
EuiButtonToggle,
EuiFieldText,
EuiText,
EuiCodeBlock,
EuiTitle,
EuiButtonIcon,
EuiButtonEmpty,
EuiCopy,
EuiPage,
EuiPageBody
} from '@elastic/eui';
import { RegisterGuideDefs } from './register-guide-defs';
import PropTypes from 'prop-types';
export class RegisterAgent extends Component {
constructor(props) {
super(props);
this.state = {
status: 'incomplete',
selectedOS: '',
serverAddress: ''
};
}
selectOS(os) {
this.setState({ selectedOS: os });
}
setServerAddress(event) {
this.setState({ serverAddress: event.target.value });
}
render() {
const rpmButton = (
<EuiButtonToggle
label="Red Hat / CentOS"
onChange={() => this.selectOS('rpm')}
fill={this.state.selectedOS === 'rpm'}
/>
);
const debButton = (
<EuiButtonToggle
label="Debian / Ubuntu"
onChange={() => this.selectOS('deb')}
fill={this.state.selectedOS === 'deb'}
/>
);
const windowsButton = (
<EuiButtonToggle
label="Windows"
onChange={() => this.selectOS('win')}
fill={this.state.selectedOS === 'win'}
/>
);
const macOSButton = (
<EuiButtonToggle
label="MacOS"
onChange={() => this.selectOS('macos')}
fill={this.state.selectedOS === 'macos'}
/>
);
const ipInput = (
<EuiFieldText
placeholder="Server address..."
value={this.state.serverAddress}
onChange={event => this.setServerAddress(event)}
/>
);
const copyButton = {
position: 'relative',
float: 'right',
zIndex: '1000',
right: '8px',
top: '16px'
};
const codeBlock = {
zIndex: '100'
};
const customTexts = {
rpmText: `WAZUH_MANAGER_IP='${this.state.serverAddress}' yum install wazuh-agent`,
debText: `WAZUH_MANAGER_IP='${this.state.serverAddress}' apt-get install wazuh-agent`,
macosText: `launchctl setenv WAZUH_MANAGER_IP '${this.state.serverAddress}' && installer -pkg wazuh-agent-.pkg -target /`,
winText: `wazuh-agent-3.9.1-1.msi /q ADDRESS='${this.state.serverAddress}' AUTHD_SERVER='${this.state.serverAddress}'`
};
const field = `${this.state.selectedOS}Text`;
const text = customTexts[field];
const guide = (
<div>
{this.state.selectedOS && (
<EuiText>
<div style={copyButton}>
<EuiCopy textToCopy={text}>
{copy => (
<EuiButtonIcon
onClick={copy}
iconType="copy"
aria-label="Copy"
/>
)}
</EuiCopy>
</div>
<EuiCodeBlock style={codeBlock} language="js">
{text}
</EuiCodeBlock>
</EuiText>
)}
</div>
);
const steps = [
{
title: 'Choose your OS',
children: (
<Fragment>
{rpmButton} {debButton} {windowsButton} {macOSButton}
</Fragment>
)
},
{
title: 'Wazuh server address',
children: <Fragment>{ipInput}</Fragment>
},
{
title: 'Complete the installation',
children: (
<div>
<Fragment>
<div>{guide}</div>
</Fragment>
</div>
)
}
];
return (
<div>
<EuiPage restrictWidth="1000px">
<EuiPageBody>
<EuiFlexGroup>
<EuiFlexItem>
<EuiTitle>
<h2>Add a new agent</h2>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonEmpty
size="s"
onClick={() => this.props.addNewAgent(false)}
iconType="cross"
>
close
</EuiButtonEmpty>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup>
<EuiFlexItem>
<EuiPanel>
<EuiFlexItem>
<EuiSteps steps={steps} />
</EuiFlexItem>
</EuiPanel>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageBody>
</EuiPage>
</div>
);
}
}
RegisterAgent.propTypes = {
addNewAgent: PropTypes.func
};

View File

@ -0,0 +1,20 @@
/*
* Wazuh app - Wazuh Register Agents Component steps texts
* Copyright (C) 2015-2019 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
export const RegisterGuideDefs = {
rpmText1:
'rpm --import http://packages.wazuh.com/key/GPG-KEY-WAZUH\ncat > /etc/yum.repos.d/wazuh.repo <<EOF\n[wazuh_repo]\ngpgcheck=1\ngpgkey=https://packages.wazuh.com/key/GPG-KEY-WAZUH\nenabled=1\nname=Wazuh repository\nbaseurl=https://packages.wazuh.com/3.x/yum/\nprotect=1\nEOF',
debText1: 'apt-get install curl apt-transport-https lsb-release',
debText2:
'curl -s https://packages.wazuh.com/key/GPG-KEY-WAZUH | apt-key add -',
debText3:
'echo "deb https://packages.wazuh.com/3.x/apt/ stable main" | tee /etc/apt/sources.list.d/wazuh.list\napt-get update'
};

View File

@ -16,6 +16,8 @@ import {
} from '@elastic/eui';
import { TabDescription } from '../../../../server/reporting/tab-description';
import { UnsupportedComponents } from '../../../utils/components-os-support';
export class WelcomeScreen extends Component {
constructor(props) {
super(props);
@ -64,17 +66,19 @@ export class WelcomeScreen extends Component {
}
buildPopover(popoverName, extensions) {
const switches = extensions.map(extension => {
return (
<EuiFormRow key={extension}>
<EuiSwitch
label={`${TabDescription[extension].title} extension`}
checked={this.state.extensions[extension]}
onChange={() => this.toggleExtension(extension)}
/>
</EuiFormRow>
);
});
const switches = extensions
.filter(extension => this.props.extensions[extension] !== undefined)
.map(extension => {
return (
<EuiFormRow key={extension}>
<EuiSwitch
label={`${TabDescription[extension].title} extension`}
checked={this.state.extensions[extension]}
onChange={() => this.toggleExtension(extension)}
/>
</EuiFormRow>
);
});
return (
<EuiPopover
@ -149,8 +153,33 @@ export class WelcomeScreen extends Component {
])}
</EuiFlexItem>
</EuiFlexGroup>
{(
UnsupportedComponents[this.props.agent.agentPlatform] ||
UnsupportedComponents['other']
).includes('vuls') &&
!this.props.extensions.virustotal &&
!this.props.extensions.osquery &&
!this.props.extensions.docker && (
<EuiFlexGroup>
<EuiFlexItem>
<EuiCallOut
title={
<p>
Click the <EuiIcon type="eye" /> icon to show thread
detection and response extensions.
</p>
}
color="success"
iconType="help"
/>
</EuiFlexItem>
</EuiFlexGroup>
)}
<EuiFlexGrid columns={2}>
{this.buildTabCard('vuls', 'securityApp')}
{!(
UnsupportedComponents[this.props.agent.agentPlatform] ||
UnsupportedComponents['other']
).includes('vuls') && this.buildTabCard('vuls', 'securityApp')}
{this.props.extensions.virustotal &&
this.buildTabCard('virustotal', 'savedObjectsApp')}
{this.props.extensions.osquery &&
@ -202,6 +231,7 @@ export class WelcomeScreen extends Component {
WelcomeScreen.propTypes = {
extensions: PropTypes.object,
agent: PropTypes.object,
setExtensions: PropTypes.func,
switchTab: PropTypes.func,
api: PropTypes.string

View File

@ -12,6 +12,8 @@
import { uiModules } from 'ui/modules';
import { AgentsPreviewController } from './agents-preview';
import { AgentsController } from './agents';
import { RegisterAgent } from './components/register-agent';
import { ExportConfiguration } from './components/export-configuration';
import { WelcomeScreen } from './components/welcome';
import { Stats } from './components/stats';
@ -20,5 +22,7 @@ const app = uiModules.get('app/wazuh', []);
app
.controller('agentsController', AgentsController)
.controller('agentsPreviewController', AgentsPreviewController)
.value('RegisterAgent', RegisterAgent)
.value('ExportConfiguration', ExportConfiguration)
.value('WelcomeScreenAgent', WelcomeScreen)
.value('StatsAgent', Stats);

View File

@ -15,6 +15,8 @@ import { ExcludedIntelliSenseTriggerKeys } from '../../../util/excluded-devtools
import queryString from 'querystring-browser';
import $ from 'jquery';
import * as FileSaver from '../../services/file-saver';
import chrome from 'ui/chrome';
export class DevToolsController {
/**
* Constructor
@ -45,6 +47,7 @@ export class DevToolsController {
this.linesWithClass = [];
this.widgets = [];
this.multipleKeyPressed = [];
this.IS_DARK_THEME = chrome.getUiSettingsClient().get('theme:darkMode');
}
/**
@ -76,7 +79,7 @@ export class DevToolsController {
lineNumbers: true,
matchBrackets: true,
mode: { name: 'javascript', json: true },
theme: 'ttcn',
theme: this.IS_DARK_THEME ? 'lesser-dark' : 'ttcn',
foldGutter: true,
styleSelectedText: true,
gutters: ['CodeMirror-foldgutter']
@ -119,7 +122,7 @@ export class DevToolsController {
readOnly: true,
lineWrapping: true,
styleActiveLine: true,
theme: 'ttcn',
theme: this.IS_DARK_THEME ? 'lesser-dark' : 'ttcn',
foldGutter: true,
gutters: ['CodeMirror-foldgutter']
}

View File

@ -109,13 +109,13 @@ export class FilesController {
isOverwrite: !!this.overwriteError
};
(isNewFile && this.$scope.type === 'rules') ||
(!isNewFile && this.$scope.currentFile.type === 'rule')
(!isNewFile && this.$scope.currentFile.type === 'rule')
? (objParam.rule = isNewFile
? this.selectedItem
: this.$scope.currentFile)
? this.selectedItem
: this.$scope.currentFile)
: (objParam.decoder = isNewFile
? this.selectedItem
: this.$scope.currentFile);
? this.selectedItem
: this.$scope.currentFile);
this.$scope.$broadcast('saveXmlFile', objParam);
this.$scope.$applyAsync();
}
@ -170,13 +170,13 @@ export class FilesController {
this.$scope.fetchedXML =
this.$scope.type === 'rules'
? await this.rulesetHandler.getRuleConfiguration(
this.$scope.currentFile.file,
readonly
)
this.$scope.currentFile.file,
readonly
)
: await this.rulesetHandler.getDecoderConfiguration(
this.$scope.currentFile.file,
readonly
);
this.$scope.currentFile.file,
readonly
);
this.$scope.$applyAsync();
if (!readonly) {
this.$scope.$broadcast('fetchedFile', { data: this.$scope.fetchedXML });

View File

@ -22,7 +22,8 @@ export function GroupsController(
shareAgent,
groupHandler,
wzTableFilter,
wazuhConfig
wazuhConfig,
reportingService
) {
$scope.addingGroup = false;
$scope.$on('groupsIsReloaded', () => {
@ -238,6 +239,14 @@ export function GroupsController(
$scope.$applyAsync();
};
$scope.exportConfiguration = enabledComponents => {
reportingService.startConfigReport(
$scope.currentGroup,
'groupConfig',
enabledComponents
);
};
/**
* This show us a group file, for a given group and file
*/

View File

@ -150,6 +150,27 @@ export class ManagementController {
this.welcomeCardsProps = {
switchTab: (tab, setNav) => this.switchTab(tab, setNav)
};
this.rulesetTabsProps = {
clickAction: tab => this.setRulesTab(tab),
selectedTab: this.rulesetTab,
tabs: [
{ id: 'rules', name: 'Rules' },
{ id: 'decoders', name: 'Decoders' },
{ id: 'cdblists', name: 'Lists' }
]
};
this.managementTabsProps = {
clickAction: tab => this.switchTab(tab, true),
selectedTab: this.tab,
tabs: [
{ id: 'status', name: 'Status' },
{ id: 'logs', name: 'Logs' },
{ id: 'monitoring', name: 'Cluster' },
{ id: 'reporting', name: 'Reporting' }
]
};
}
/**

View File

@ -80,6 +80,33 @@ export function RulesController(
);
$scope.appliedFilters.push(filter);
$scope.$broadcast('wazuhFilter', { filter });
} else if (
term &&
term.startsWith('hipaa:') &&
term.split('hipaa:')[1].trim()
) {
$scope.custom_search = '';
const filter = { name: 'hipaa', value: term.split('hipaa:')[1].trim() };
$scope.appliedFilters = $scope.appliedFilters.filter(
item => item.name !== 'hipaa'
);
$scope.appliedFilters.push(filter);
$scope.$broadcast('wazuhFilter', { filter });
} else if (
term &&
term.startsWith('nist-800-53:') &&
term.split('nist-800-53:')[1].trim()
) {
$scope.custom_search = '';
const filter = {
name: 'nist-800-53',
value: term.split('nist-800-53:')[1].trim()
};
$scope.appliedFilters = $scope.appliedFilters.filter(
item => item.name !== 'nist-800-53'
);
$scope.appliedFilters.push(filter);
$scope.$broadcast('wazuhFilter', { filter });
} else if (
term &&
term.startsWith('file:') &&

View File

@ -172,7 +172,7 @@ export class HealthCheck {
const apiVersion = versionData.data.data;
const setupData = await this.genericReq.request(
'GET',
'/elastic/setup'
'/api/setup'
);
if (!setupData.data.data['app-version'] || !apiVersion) {
this.errorHandler.handle(

View File

@ -11,8 +11,9 @@
*/
import chrome from 'ui/chrome';
export class ReportingController {
constructor(errorHandler, genericReq, $window, timeService) {
constructor($scope, errorHandler, genericReq, $window, timeService) {
// Services
this.$scope = $scope;
this.$window = $window;
this.errorHandler = errorHandler;
this.genericReq = genericReq;
@ -84,6 +85,7 @@ export class ReportingController {
this.errorHandler.handle(error.message || error);
}
this.loading = false;
this.$scope.$applyAsync();
return this.items;
}
}

View File

@ -117,7 +117,7 @@ export class OverviewController {
this.hostMonitoringTabs = ['general', 'fim', 'aws'];
this.systemAuditTabs = ['pm', 'audit', 'oscap', 'ciscat', 'sca'];
this.securityTabs = ['vuls', 'virustotal', 'osquery', 'docker'];
this.complianceTabs = ['pci', 'gdpr'];
this.complianceTabs = ['pci', 'gdpr', 'hipaa', 'nist'];
this.wodlesConfiguration = null;
@ -256,6 +256,18 @@ export class OverviewController {
this.selectedGdprIndex = 0;
}
if (newTab === 'hipaa') {
const hipaaTabs = await this.commonData.getHIPAA();
this.hipaaTabs = hipaaTabs;
this.selectedHipaaIndex = 0;
}
if (newTab === 'nist') {
const nistTabs = await this.commonData.getNIST();
this.nistTabs = nistTabs;
this.selectedNistIndex = 0;
}
if (newTab !== 'welcome') this.tabHistory.push(newTab);
if (this.tabHistory.length > 2)

View File

@ -386,6 +386,8 @@ export class SettingsController {
tmpData.extensions.audit = config['extensions.audit'];
tmpData.extensions.pci = config['extensions.pci'];
tmpData.extensions.gdpr = config['extensions.gdpr'];
tmpData.extensions.hipaa = config['extensions.hipaa'];
tmpData.extensions.nist = config['extensions.nist'];
tmpData.extensions.oscap = config['extensions.oscap'];
tmpData.extensions.ciscat = config['extensions.ciscat'];
tmpData.extensions.aws = config['extensions.aws'];
@ -674,7 +676,7 @@ export class SettingsController {
*/
async getAppInfo() {
try {
const data = await this.genericReq.request('GET', '/elastic/setup');
const data = await this.genericReq.request('GET', '/api/setup');
this.appInfo = {};
this.appInfo['app-version'] = data.data.data['app-version'];
this.appInfo['installationDate'] = data.data.data['installationDate'];

View File

@ -29,8 +29,6 @@ import './wz-multiple-selector/wz-multiple-selector';
import './wz-multiple-selector/wz-multiple-selector.less';
import './wz-list-manage/wz-list-manage';
import './wz-kbn-switch/wz-kbn-switch';
import './wz-register-agents/wz-register-agents';
import './wz-register-agents/wz-register-agents.less';
import './wz-add-filter-chip/wz-add-filter-chip';
import './wz-add-filter-chip/wz-add-filter-chip.less';
import './wz-src/wz-src';

View File

@ -30,6 +30,7 @@
.chips-dropdown .dropdown-menu{
display: block !important;
right: 0;
}
.ui-select-choices-row-inner {

View File

@ -13,6 +13,7 @@
import template from './wz-config-viewer.html';
import { uiModules } from 'ui/modules';
import CodeMirror from '../../utils/codemirror/lib/codemirror';
import chrome from 'ui/chrome';
const app = uiModules.get('app/wazuh', []);
@ -32,6 +33,7 @@ class WzConfigViewer {
controller($scope, $document, $window) {
const window = $window;
const IS_DARK_THEME = chrome.getUiSettingsClient().get('theme:darkMode');
const setJsonBox = () => {
$scope.jsonCodeBox = CodeMirror.fromTextArea(
$document[0].getElementById('viewer_json_box'),
@ -42,7 +44,7 @@ class WzConfigViewer {
matchBrackets: true,
mode: { name: 'javascript', json: true },
readOnly: true,
theme: 'ttcn',
theme: IS_DARK_THEME ? 'lesser-dark' : 'ttcn',
foldGutter: true,
styleSelectedText: true,
gutters: ['CodeMirror-foldgutter']
@ -60,7 +62,7 @@ class WzConfigViewer {
matchBrackets: true,
mode: 'text/xml',
readOnly: true,
theme: 'ttcn',
theme: IS_DARK_THEME ? 'lesser-dark' : 'ttcn',
foldGutter: true,
styleSelectedText: true,
gutters: ['CodeMirror-foldgutter']

View File

@ -1,221 +0,0 @@
<div class="tutorial">
<md-nav-bar class="wz-nav-bar nav-bar-white-bg tutorial-nav-bar" md-selected-nav-item="registerObj.selectedSystemTab"
nav-bar-aria-label="System" class="wz-margin-bottom-25">
<md-nav-item class="wz-nav-item" md-nav-click="setSystem('linux')" name="linux"><i class="fa fa-linux"></i>
Linux</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="setSystem('windows')" name="windows"><i class="fa fa-windows"></i>
Windows</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="setSystem('osx')" name="osx"><i class="fa fa-apple"></i>
OSX</md-nav-item>
</md-nav-bar>
<!-- Linux -->
<div ng-if="registerObj.selectedSystem === 0">
<div class="tutorial-step" ng-class="{'active' : registerObj.currentStep === 0, 'completed' : registerObj.currentStep > 0 }">
<div layout="row" class="tutorial-header">
<div class="step-number">
<p>1</p>
</div>
<h3 class="step-title">{{registerObj.systems[0].steps[0].title}}</h3>
</div>
<div class="tutorial-body">
<div layout="row">
<div class="wz-padding-right-16">
<label class="euiFormLabel">Agent name</label>
<div class="euiFormControlLayout wz-margin-top-4">
<div class="euiFormControlLayout__childrenWrapper">
<input type="text" class="euiFieldText" aria-label="default columns" ng-model="registerObj.systems[0].steps[0].agentName">
</div>
</div>
</div>
<div class="wz-padding-right-16">
<label class="euiFormLabel">Agent IP</label>
<div class="euiFormControlLayout wz-margin-top-4">
<div class="euiFormControlLayout__childrenWrapper">
<input type="text" class="euiFieldText" aria-label="default columns" ng-model="registerObj.systems[0].steps[0].agentIP">
</div>
</div>
</div>
<md-button ng-disabled="!registerObj.systems[0].steps[0].agentName || !registerObj.systems[0].steps[0].agentIP || addingAgent"
class="wz-button btn height-40" ng-click="addAgent()"><i class="fa fa-plus" ng-class="addingAgent ? 'fa-spin fa-spinner' : ''"></i>
Add agent
</md-button>
</div>
</div>
</div>
<div class="tutorial-step" ng-class="{'active' : registerObj.currentStep === 1, 'completed' : registerObj.currentStep > 1, 'disabled' : registerObj.currentStep < 1 }">
<div layout="row" class="tutorial-header">
<div class="step-number">
<p>2</p>
</div>
<h3 class="step-title">{{registerObj.systems[0].steps[1].title}}</h3>
</div>
<div class="tutorial-body">
<p class="tutorial-exit">Please execute the following command:</p>
<div class="wz-code-viewer">{{registerObj.systems[0].steps[1].code}}</div>
<md-button class="wz-button btn height-40 next-btn" ng-click="nextStep()"><i class="fa fa-success"></i>
Next
</md-button>
</div>
</div>
<div class="tutorial-step" ng-class="{'active' : registerObj.currentStep === 2, 'completed' : registerObj.currentStep > 2, 'disabled' : registerObj.currentStep < 2 }">
<div layout="row" class="tutorial-header">
<div class="step-number">
<p>3</p>
</div>
<h3 class="step-title">{{registerObj.systems[0].steps[2].title}}</h3>
</div>
<div class="tutorial-body">
<div class="wz-margin-bottom-10">
<label class="euiFormLabel">Manager IP</label>
<div class="euiFormControlLayout wz-margin-top-4">
<div class="euiFormControlLayout__childrenWrapper">
<input type="text" class="euiFieldText" aria-label="default columns" ng-model="registerObj.systems[0].steps[2].managerIp">
</div>
</div>
</div>
<p class="tutorial-exit" ng-show="registerObj.systems[0].steps[2].managerIp">Please execute the
following
command:</p>
<div ng-show="registerObj.systems[0].steps[2].managerIp" class="wz-code-viewer">
sed -i 's/MANAGER_IP/{{registerObj.systems[0].steps[2].managerIp}}/g' /var/ossec/etc/ossec.conf
</div>
<md-button ng-show="registerObj.systems[0].steps[2].managerIp" class="wz-button btn height-40 next-btn"
ng-click="nextStep()"><i class="fa fa-success"></i> Next
</md-button>
</div>
</div>
<div class="tutorial-step" ng-class="{'active' : registerObj.currentStep === 3, 'completed' : registerObj.currentStep > 3, 'disabled' : registerObj.currentStep < 3 }">
<div layout="row" class="tutorial-header">
<div class="step-number">
<p>4</p>
</div>
<h3 class="step-title">{{registerObj.systems[0].steps[3].title}}</h3>
</div>
<div class="tutorial-body">
<md-button class="wz-button wz-no-margin height-40" ng-click="restartAgent()"><i class="fa fa-refresh"
ng-class="restartingAgent ? 'fa-spin fa-spinner' : ''"></i>
Restart agent
</md-button>
</div>
</div>
</div>
<!-- Windows -->
<div ng-if="registerObj.selectedSystem === 1">
<div class="tutorial-step" ng-class="{'active' : registerObj.currentStep === 0, 'completed' : registerObj.currentStep > 0, 'disabled' : registerObj.currentStep < 0 }">
<div layout="row" class="tutorial-header">
<div class="step-number">
<p>1</p>
</div>
<h3 class="step-title">{{registerObj.systems[1].steps[0].title}}</h3>
</div>
<div class="tutorial-body">
<div layout="row" class="wz-margin-bottom-10">
<div class="wz-padding-right-16">
<label class="euiFormLabel">Agent name</label>
<div class="euiFormControlLayout wz-margin-top-4">
<div class="euiFormControlLayout__childrenWrapper">
<input type="text" class="euiFieldText" aria-label="default columns" ng-model="registerObj.systems[1].steps[0].agentName">
</div>
</div>
</div>
<div class="wz-padding-right-16">
<label class="euiFormLabel">Manager IP</label>
<div class="euiFormControlLayout wz-margin-top-4">
<div class="euiFormControlLayout__childrenWrapper">
<input type="text" class="euiFieldText" aria-label="default columns" ng-model="registerObj.systems[1].steps[0].managerIP">
</div>
</div>
</div>
<div class="wz-padding-right-16">
<label class="euiFormLabel">Authd service IP</label>
<div class="euiFormControlLayout wz-margin-top-4">
<div class="euiFormControlLayout__childrenWrapper">
<input type="text" class="euiFieldText" aria-label="default columns" ng-model="registerObj.systems[1].steps[0].authdIP">
</div>
</div>
</div>
</div>
<p class="tutorial-exit" ng-show="registerObj.systems[1].steps[0].agentName && registerObj.systems[1].steps[0].managerIP &&
registerObj.systems[1].steps[0].authdIP">Please
execute the following command:</p>
<div ng-show="registerObj.systems[1].steps[0].agentName && registerObj.systems[1].steps[0].managerIP &&
registerObj.systems[1].steps[0].authdIP"
class="wz-code-viewer">
wazuh-agent-3.8.2-1.msi /q ADDRESS="{{registerObj.systems[1].steps[0].managerIP}}"
AUTHD_SERVER="{{registerObj.systems[1].steps[0].authdIP}}"
AGENT_NAME="{{registerObj.systems[1].steps[0].agentName}}"
</div>
<md-button ng-show="registerObj.systems[1].steps[0].agentName && registerObj.systems[1].steps[0].managerIP &&
registerObj.systems[1].steps[0].authdIP"
class="wz-button btn height-40 next-btn" ng-click="nextStep()"><i class="fa fa-success"></i>
Next
</md-button>
</div>
</div>
</div>
<!-- OSX -->
<div ng-if="registerObj.selectedSystem === 2">
<div class="tutorial-step" ng-class="{'active' : registerObj.currentStep === 0, 'completed' : registerObj.currentStep > 0, 'disabled' : registerObj.currentStep < 0 }">
<div layout="row" class="tutorial-header">
<div class="step-number">
<p>1</p>
</div>
<h3 class="step-title">{{registerObj.systems[2].steps[0].title}}</h3>
</div>
<div class="tutorial-body">
<div class="wz-margin-bottom-10">
<label class="euiFormLabel">Manager IP</label>
<div class="euiFormControlLayout wz-margin-top-4">
<div class="euiFormControlLayout__childrenWrapper">
<input type="text" class="euiFieldText" aria-label="default columns" ng-model="registerObj.systems[2].steps[0].managerIp">
</div>
</div>
</div>
<p class="tutorial-exit" ng-show="registerObj.systems[2].steps[0].managerIp">Please execute the
following
command:</p>
<div ng-show="registerObj.systems[2].steps[0].managerIp" class="wz-code-viewer">
/Library/Ossec/bin/agent-auth -m {{registerObj.systems[2].steps[0].managerIp}}
</div>
<md-button ng-show="registerObj.systems[2].steps[0].managerIp" class="wz-button btn height-40 next-btn"
ng-click="nextStep()"><i class="fa fa-success"></i> Next
</md-button>
</div>
</div>
<div class="tutorial-step" ng-class="{'active' : registerObj.currentStep === 1, 'completed' : registerObj.currentStep > 1, 'disabled' : registerObj.currentStep < 1 }">
<div layout="row" class="tutorial-header">
<div class="step-number">
<p>2</p>
</div>
<h3 class="step-title">{{registerObj.systems[2].steps[1].title}}</h3>
</div>
<div class="tutorial-body">
<p class="tutorial-exit">Please execute the following command:</p>
<div class="wz-code-viewer">sed -i '' -e 's/MANAGER_IP/{{registerObj.systems[2].steps[0].managerIp}}/g'
/Library/Ossec/etc/ossec.conf</div>
<md-button class="wz-button btn height-40 next-btn" ng-click="nextStep()"><i class="fa fa-success"></i>
Next
</md-button>
</div>
</div>
<div class="tutorial-step" ng-class="{'active' : registerObj.currentStep === 2, 'completed' : registerObj.currentStep > 2, 'disabled' : registerObj.currentStep < 2 }">
<div layout="row" class="tutorial-header">
<div class="step-number">
<p>3</p>
</div>
<h3 class="step-title">{{registerObj.systems[2].steps[2].title}}</h3>
</div>
<div class="tutorial-body">
<p class="tutorial-exit">Please execute the following command:</p>
<div class="wz-code-viewer">
{{registerObj.systems[2].steps[2].code}}
</div>
<md-button class="wz-button btn height-40 next-btn" ng-click="nextStep()"><i class="fa fa-success"></i>
Next
</md-button>
</div>
</div>
</div>
</div>

View File

@ -1,112 +0,0 @@
/*
* Wazuh app - Wazuh register agents stylesheet
* Copyright (C) 2015-2019 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
/* -------------------------------------------------------------------------- */
/* ------------------ Wazuh register agents stylesheet ---------------------- */
/* -------------------------------------------------------------------------- */
.tutorial{
margin: 0 12%;
}
.registerNewAgent .tutorial{
margin: 0 !important;
}
.tutorial-nav-bar .md-nav-bar{
margin-bottom: 25px;
}
.tutorial-nav-bar .md-nav-bar ._md-nav-button{
padding: 15px 20px!important;
}
.tutorial-step{
margin-bottom: 15px;
}
.tutorial .tutorial-step:not(:last-child){
border-bottom: 2px dashed #e9e9e9;
}
.tutorial-header {
padding-bottom: 15px;
}
.tutorial-body {
padding: 0px 0px 15px 40px;
}
.tutorial-body button{
width: 150px;
}
.tutorial-body .layout-row button, .next-btn{
margin: 18px 0 0 0!important;
}
.tutorial-step.disabled .tutorial-body, .tutorial-step.completed .tutorial-body{
display: none;
}
.step-number{
width: 30px;
height: 30px;
border-radius: 50%;
color: white;
line-height: 30px;
font-size: 20px;
text-align: center;
}
.tutorial-step.active .step-number{
background: #007ba4;
}
.tutorial-step.disabled .step-number{
background: #c6c6c6;
}
.tutorial-step.completed .step-number{
background: #70ba56;
}
.step-title{
font-size: 17px;
line-height: 30px;
padding-left: 8px;
}
.tutorial-step.active .step-title{
color: #005571;
}
.tutorial-step.disabled .step-title{
color: #c6c6c6;
}
.tutorial-step.completed .step-title{
color: #70ba56;
}
.tutorial .wz-code-viewer{
text-align: left;
font-size: 12px!important;
padding: 5px;
height: auto;
}
.tutorial-exit{
font-family: monospace;
text-align: left;
padding: 8px 0 5px 0;
font-size: 12px;
}

View File

@ -0,0 +1,54 @@
import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { EuiTabs, EuiTab } from '@elastic/eui';
export class Tabs extends Component {
constructor(props) {
super(props);
this.tabs = [];
this.props.tabs.forEach(tab => {
this.tabs.push({
id: tab.id,
name: tab.name
});
});
this.state = {
selectedTabId: this.props.selectedTab
};
}
onSelectedTabChanged = id => {
this.setState({
selectedTabId: id
});
this.props.clickAction(id);
};
renderTabs() {
return this.tabs.map((tab, index) => (
<EuiTab
onClick={() => this.onSelectedTabChanged(tab.id)}
isSelected={tab.id === this.state.selectedTabId}
key={index}
>
{tab.name}
</EuiTab>
));
}
render() {
return (
<Fragment>
<EuiTabs>{this.renderTabs()}</EuiTabs>
</Fragment>
);
}
}
Tabs.propTypes = {
tabs: PropTypes.array,
selectedTab: PropTypes.string,
clickAction: PropTypes.func
};

View File

@ -434,6 +434,11 @@ app.directive('wzTagFilter', function() {
}
});
$('#wz-search-filter-bar-input').attr('autocomplete', 'off');
$scope.$on('reloadSearchFilterBar', () => {
buildQuery($scope.groupedTagList);
$scope.$applyAsync();
});
load();
},
template

View File

@ -13,6 +13,7 @@
import template from './wz-xml-file-editor.html';
import CodeMirror from '../../utils/codemirror/lib/codemirror';
import { uiModules } from 'ui/modules';
import chrome from 'ui/chrome';
const app = uiModules.get('app/wazuh', []);
@ -41,6 +42,7 @@ app.directive('wzXmlFileEditor', function() {
$window
) {
const window = $window;
const IS_DARK_THEME = chrome.getUiSettingsClient().get('theme:darkMode');
$scope.targetNameShown = $scope.targetName;
$scope.configError = false;
/**
@ -328,7 +330,7 @@ app.directive('wzXmlFileEditor', function() {
matchClosing: true,
matchBrackets: true,
mode: 'text/xml',
theme: 'ttcn',
theme: IS_DARK_THEME ? 'lesser-dark' : 'ttcn',
foldGutter: true,
styleSelectedText: true,
gutters: ['CodeMirror-foldgutter']

View File

@ -26,6 +26,8 @@ export class TabVisualizations {
audit: 9,
gdpr: 6,
pci: 6,
hipaa: 6,
nist: 6,
virustotal: 6,
configuration: 0,
osquery: 5,
@ -43,6 +45,8 @@ export class TabVisualizations {
audit: 6,
pci: 5,
gdpr: 5,
hipaa: 5,
nist: 5,
aws: 8,
virustotal: 7,
osquery: 5,

View File

@ -109,6 +109,19 @@ export class VisualizeDataLoader {
);
}
const valueAxes = (visParams || {}).valueAxes || false;
const hasSeries = ((this.visData || {}).series || []).length;
if (valueAxes && hasSeries) {
if (visParams.type !== 'area') {
visParams.valueAxes.forEach((axis: { scale: { max: number; }; }, idx: string | number) => {
const maxValue = Math.max.apply(Math, this.visData.series[idx].values.map((x: { y: any; }) => { return x.y; }));
const lengthMaxValue = maxValue.toString().length;
const addTo = parseInt('1' + '0'.repeat(lengthMaxValue - 1));
axis.scale.max = maxValue + (addTo / 2);
});
}
}
return {
as: 'visualization',
value: {

View File

@ -257,9 +257,9 @@
box-shadow: none !important;
}
.btn-as-i:hover {
.btn-as-i:hover, .btn-as-i:focus {
background: none !important;
color: #006bb4;
color: #006bb4!important;
}
/* Custom reporting button styles */
@ -535,7 +535,7 @@ md-sidenav {
.wz-md-card:not(.wz-metric-color) {
box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.1) !important;
border: 1px solid #d3dae6 !important;
border: 1px solid #d3dae6;
overflow: hidden;
}
@ -992,6 +992,17 @@ discover-app-w .container-fluid {
background: #fff;
}
.registerAgent{
min-height: calc(~'100vh - 100px');
background: #fafbfd;
padding-top: 25px;
}
.refresh-report-button {
padding: 10px;
text-align: right;
}
.monitoring-discover form{
display: none;
}

View File

@ -696,233 +696,7 @@
margin-left: 0%;
}
}
.table {
width: 100%;
max-width: 100%;
margin-bottom: 20px;
font-size: 14px;
}
.table thead {
font-size: 12px;
}
.table > thead > tr > th,
.table > tbody > tr > th,
.table > tfoot > tr > th,
.table > thead > tr > td,
.table > tbody > tr > td,
.table > tfoot > tr > td {
padding: 8px;
line-height: 1.42857143;
vertical-align: top;
border-top: 1px solid #D3DAE6;
}
.table > thead > tr > th {
vertical-align: bottom;
border-bottom: 1px solid #D3DAE6;
}
.table > caption + thead > tr:first-child > th,
.table > colgroup + thead > tr:first-child > th,
.table > thead:first-child > tr:first-child > th,
.table > caption + thead > tr:first-child > td,
.table > colgroup + thead > tr:first-child > td,
.table > thead:first-child > tr:first-child > td {
border-top: 0;
}
.table > tbody + tbody {
border-top: 2px solid #D3DAE6;
}
.table .table {
background-color: #FFF;
}
.table-condensed > thead > tr > th,
.table-condensed > tbody > tr > th,
.table-condensed > tfoot > tr > th,
.table-condensed > thead > tr > td,
.table-condensed > tbody > tr > td,
.table-condensed > tfoot > tr > td {
padding: 5px;
font-size: 12px;
}
.table-bordered {
border: 1px solid #D3DAE6;
}
.table-bordered > thead > tr > th,
.table-bordered > tbody > tr > th,
.table-bordered > tfoot > tr > th,
.table-bordered > thead > tr > td,
.table-bordered > tbody > tr > td,
.table-bordered > tfoot > tr > td {
border: 1px solid #D3DAE6;
}
.table-bordered > thead > tr > th,
.table-bordered > thead > tr > td {
border-bottom-width: 2px;
}
table col[class*="col-"] {
position: static;
float: none;
display: table-column;
}
table td[class*="col-"],
table th[class*="col-"] {
position: static;
float: none;
display: table-cell;
}
.table > thead > tr > td.active,
.table > tbody > tr > td.active,
.table > tfoot > tr > td.active,
.table > thead > tr > th.active,
.table > tbody > tr > th.active,
.table > tfoot > tr > th.active,
.table > thead > tr.active > td,
.table > tbody > tr.active > td,
.table > tfoot > tr.active > td,
.table > thead > tr.active > th,
.table > tbody > tr.active > th,
.table > tfoot > tr.active > th {
background-color: #D3DAE6;
}
.table-hover > tbody > tr > td.active:hover,
.table-hover > tbody > tr > th.active:hover,
.table-hover > tbody > tr.active:hover > td,
.table-hover > tbody > tr:hover > .active,
.table-hover > tbody > tr.active:hover > th {
background-color: #c3ccdd;
}
.table > thead > tr > td.success,
.table > tbody > tr > td.success,
.table > tfoot > tr > td.success,
.table > thead > tr > th.success,
.table > tbody > tr > th.success,
.table > tfoot > tr > th.success,
.table > thead > tr.success > td,
.table > tbody > tr.success > td,
.table > tfoot > tr.success > td,
.table > thead > tr.success > th,
.table > tbody > tr.success > th,
.table > tfoot > tr.success > th {
background-color: #017D73;
}
.table-hover > tbody > tr > td.success:hover,
.table-hover > tbody > tr > th.success:hover,
.table-hover > tbody > tr.success:hover > td,
.table-hover > tbody > tr:hover > .success,
.table-hover > tbody > tr.success:hover > th {
background-color: #01645c;
}
.table > thead > tr > td.info,
.table > tbody > tr > td.info,
.table > tfoot > tr > td.info,
.table > thead > tr > th.info,
.table > tbody > tr > th.info,
.table > tfoot > tr > th.info,
.table > thead > tr.info > td,
.table > tbody > tr.info > td,
.table > tfoot > tr.info > td,
.table > thead > tr.info > th,
.table > tbody > tr.info > th,
.table > tfoot > tr.info > th {
background-color: #006BB4;
}
.table-hover > tbody > tr > td.info:hover,
.table-hover > tbody > tr > th.info:hover,
.table-hover > tbody > tr.info:hover > td,
.table-hover > tbody > tr:hover > .info,
.table-hover > tbody > tr.info:hover > th {
background-color: #005c9b;
}
.table > thead > tr > td.warning,
.table > tbody > tr > td.warning,
.table > tfoot > tr > td.warning,
.table > thead > tr > th.warning,
.table > tbody > tr > th.warning,
.table > tfoot > tr > th.warning,
.table > thead > tr.warning > td,
.table > tbody > tr.warning > td,
.table > tfoot > tr.warning > td,
.table > thead > tr.warning > th,
.table > tbody > tr.warning > th,
.table > tfoot > tr.warning > th {
background-color: #F5A700;
}
.table-hover > tbody > tr > td.warning:hover,
.table-hover > tbody > tr > th.warning:hover,
.table-hover > tbody > tr.warning:hover > td,
.table-hover > tbody > tr:hover > .warning,
.table-hover > tbody > tr.warning:hover > th {
background-color: #dc9600;
}
.table > thead > tr > td.danger,
.table > tbody > tr > td.danger,
.table > tfoot > tr > td.danger,
.table > thead > tr > th.danger,
.table > tbody > tr > th.danger,
.table > tfoot > tr > th.danger,
.table > thead > tr.danger > td,
.table > tbody > tr.danger > td,
.table > tfoot > tr.danger > td,
.table > thead > tr.danger > th,
.table > tbody > tr.danger > th,
.table > tfoot > tr.danger > th {
background-color: #BD271E;
}
.table-hover > tbody > tr > td.danger:hover,
.table-hover > tbody > tr > th.danger:hover,
.table-hover > tbody > tr.danger:hover > td,
.table-hover > tbody > tr:hover > .danger,
.table-hover > tbody > tr.danger:hover > th {
background-color: #a7221b;
}
.table-responsive {
overflow-x: auto;
min-height: 0.01%;
}
@media screen and (max-width: 767px) {
.table-responsive {
width: 100%;
margin-bottom: 15px;
overflow-y: hidden;
-ms-overflow-style: -ms-autohiding-scrollbar;
border: 1px solid #D3DAE6;
}
.table-responsive > .table {
margin-bottom: 0;
}
.table-responsive > .table > thead > tr > th,
.table-responsive > .table > tbody > tr > th,
.table-responsive > .table > tfoot > tr > th,
.table-responsive > .table > thead > tr > td,
.table-responsive > .table > tbody > tr > td,
.table-responsive > .table > tfoot > tr > td {
white-space: nowrap;
}
.table-responsive > .table-bordered {
border: 0;
}
.table-responsive > .table-bordered > thead > tr > th:first-child,
.table-responsive > .table-bordered > tbody > tr > th:first-child,
.table-responsive > .table-bordered > tfoot > tr > th:first-child,
.table-responsive > .table-bordered > thead > tr > td:first-child,
.table-responsive > .table-bordered > tbody > tr > td:first-child,
.table-responsive > .table-bordered > tfoot > tr > td:first-child {
border-left: 0;
}
.table-responsive > .table-bordered > thead > tr > th:last-child,
.table-responsive > .table-bordered > tbody > tr > th:last-child,
.table-responsive > .table-bordered > tfoot > tr > th:last-child,
.table-responsive > .table-bordered > thead > tr > td:last-child,
.table-responsive > .table-bordered > tbody > tr > td:last-child,
.table-responsive > .table-bordered > tfoot > tr > td:last-child {
border-right: 0;
}
.table-responsive > .table-bordered > tbody > tr:last-child > th,
.table-responsive > .table-bordered > tfoot > tr:last-child > th,
.table-responsive > .table-bordered > tbody > tr:last-child > td,
.table-responsive > .table-bordered > tfoot > tr:last-child > td {
border-bottom: 0;
}
}
.form-control {
display: block;
width: 100%;

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,9 @@ html {
background: white !important;
}
#kibana-body{
min-height: calc(~'100vh - 1px') !important;
}
/* Margins */
.wz-margin-right-8 {
@ -417,11 +420,6 @@ md-dialog.modalTheme .md-button {
background-color: #0079a5 !important;
}
.euiButton--primary.euiButton--fill {
background-color: #0079a5 !important;
border-color: #0079a5 !important;
}
.columns-bar {
margin-top: -17px;
margin-left: -16px;

View File

@ -23,7 +23,6 @@ import './typography.less';
import './ui_framework.css';
import './jquery-ui.css';
//import './dark_theme/wz_theme_dark.css';
import chrome from 'ui/chrome';
const IS_DARK_THEME = chrome.getUiSettingsClient().get('theme:darkMode');
/* eslint-disable no-undef */
@ -32,15 +31,5 @@ if (IS_DARK_THEME) {
newSS.rel = 'stylesheet';
newSS.href = '../plugins/wazuh/less/dark_theme/wz_theme_dark.css';
document.getElementsByTagName('head')[0].appendChild(newSS);
newSS = document.createElement('link');
newSS.rel = 'stylesheet';
newSS.href = '../plugins/wazuh/less/dark_theme/bootstrap_light.css';
document.getElementsByTagName('head')[0].appendChild(newSS);
newSS = document.createElement('link');
newSS.rel = 'stylesheet';
newSS.href = '../plugins/wazuh/less/dark_theme/kui_light.css';
document.getElementsByTagName('head')[0].appendChild(newSS);
}
/* eslint-enable no-undef */

View File

@ -128,6 +128,8 @@ export class CommonData {
audit: { group: 'audit' },
pci: { group: 'pci_dss' },
gdpr: { group: 'gdpr' },
hipaa: { group: 'hipaa' },
nist: { group: 'nist' },
aws: { group: 'amazon' },
virustotal: { group: 'virustotal' },
osquery: { group: 'osquery' },
@ -153,6 +155,12 @@ export class CommonData {
} else if (tab === 'gdpr') {
this.removeDuplicateExists('rule.gdpr');
filters.push(filterHandler.gdprQuery());
} else if (tab === 'hipaa') {
this.removeDuplicateExists('rule.hipaa');
filters.push(filterHandler.hipaaQuery());
} else if (tab === 'nist') {
this.removeDuplicateExists('rule.nist_800_53');
filters.push(filterHandler.nistQuery());
} else {
this.removeDuplicateRuleGroups(tabFilters[tab].group);
filters.push(filterHandler.ruleGroupQuery(tabFilters[tab].group));
@ -208,6 +216,40 @@ export class CommonData {
}
}
/**
* GET HIPAA
*/
async getHIPAA() {
try {
const hipaaTabs = [];
const data = await this.genericReq.request('GET', '/api/hipaa/all');
if (!data.data) return [];
for (const key in data.data) {
hipaaTabs.push({ title: key, content: data.data[key] });
}
return hipaaTabs;
} catch (error) {
return Promise.reject(error);
}
}
/**
* GET NIST 800-53
*/
async getNIST() {
try {
const nistTabs = [];
const data = await this.genericReq.request('GET', '/api/nist/all');
if (!data.data) return [];
for (const key in data.data) {
nistTabs.push({ title: key, content: data.data[key] });
}
return nistTabs;
} catch (error) {
return Promise.reject(error);
}
}
/**
* Assign given filter
* @param {Object} filterHandler

View File

@ -113,4 +113,51 @@ export class ReportingService {
this.errorHandler.handle(error.message || error);
}
}
async startConfigReport(obj, type, components) {
try {
this.$rootScope.reportBusy = true;
this.$rootScope.reportStatus = 'Generating PDF document...';
this.$rootScope.$applyAsync();
const docType =
type === 'agentConfig'
? `wazuh-agent-${obj.id}`
: `wazuh-group-${obj.name}`;
const name = `${docType}-configuration-${(Date.now() / 1000) | 0}.pdf`;
const browserTimezone = moment.tz.guess(true);
const data = {
array: [],
name,
filters: [
type === 'agentConfig' ? { agent: obj.id } : { group: obj.name }
],
time: '',
searchBar: '',
tables: [],
tab: type,
browserTimezone,
components
};
await this.genericReq.request('POST', '/reports', data);
this.$rootScope.reportBusy = false;
this.$rootScope.reportStatus = false;
this.$rootScope.$applyAsync();
this.errorHandler.info(
'Success. Go to Wazuh > Management > Reporting',
'Reporting'
);
return;
} catch (error) {
this.$rootScope.reportBusy = false;
this.$rootScope.reportStatus = false;
this.errorHandler.handle(error.message || error);
this.$rootScope.$applyAsync();
}
}
}

View File

@ -11,13 +11,13 @@
*/
export async function checkTimestamp(appState, genericReq, $location, wzMisc) {
try {
const data = await genericReq.request('GET', '/elastic/timestamp');
const data = await genericReq.request('GET', '/api/timestamp');
const current = appState.getCreatedAt();
if (data && data.data) {
if (!current) appState.setCreatedAt(data.data.lastRestart);
wzMisc.setLastRestart(data.data.lastRestart);
} else {
wzMisc.setBlankScr('Your .wazuh-version index is empty or corrupt.');
wzMisc.setBlankScr('Your wazuh-version registry is empty or corrupt.');
$location.search('tab', null);
$location.path('/blank-screen');
}

View File

@ -20,6 +20,8 @@ export async function getWzConfig($q, genericReq, wazuhConfig) {
'checks.setup': true,
'extensions.pci': true,
'extensions.gdpr': true,
'extensions.hipaa': true,
'extensions.nist': true,
'extensions.audit': true,
'extensions.oscap': false,
'extensions.ciscat': false,
@ -30,8 +32,6 @@ export async function getWzConfig($q, genericReq, wazuhConfig) {
timeout: 20000,
'wazuh.shards': 1,
'wazuh.replicas': 0,
'wazuh-version.shards': 1,
'wazuh-version.replicas': 0,
'ip.selector': true,
'ip.ignore': [],
'xpack.rbac.enabled': true,

View File

@ -114,6 +114,8 @@ export function settingsWizard(
audit: config['extensions.audit'],
pci: config['extensions.pci'],
gdpr: config['extensions.gdpr'],
hipaa: config['extensions.hipaa'],
nist: config['extensions.nist'],
oscap: config['extensions.oscap'],
ciscat: config['extensions.ciscat'],
aws: config['extensions.aws'],

View File

@ -22,123 +22,133 @@
</div>
<div ng-if="!ctrl.init && !ctrl.loading && !ctrl.errorInit" layout="column" layout-align="start space-around">
<div class="md-padding euiFlexGroup--wrap layout-row">
<div class="layout-column md-padding">
<span class="wz-headline-title">
<react-component name="EuiIcon" props="{type:'node'}" /> Status
</span>
<md-divider class="wz-margin-top-10"></md-divider>
<canvas id="bar" ng-if="ctrl.lastAgent && ctrl.lastAgent.id" class="wz-margin-top-16 chart chart-doughnut"
chart-data="[ctrl.summary.agentsCountActive,ctrl.summary.agentsCountDisconnected,ctrl.summary.agentsCountNeverConnected]"
chart-labels="['Active','Disconnected', 'Never connected']" chart-colors="['#57C17B', '#BC52BC', '#9E3533']"
chart-options="{cutoutPercentage: 75, legend: {display: true,position: 'right',},responsive: false, maintainAspectRatio: false}" />
<div layout="row" class="wz-margin-top-16 layout-align-center-center" ng-if="!ctrl.lastAgent || !ctrl.lastAgent.id">
There are no agents yet.
</div>
<div layout="row" class="wz-margin-top-16 layout-align-center-center" ng-if="!ctrl.lastAgent || !ctrl.lastAgent.id">
<button class="kuiButton kuiButton--success" ng-click="ctrl.openRegistrationDocs()">
<react-component name="EuiIcon" props="{type: 'help'}" /> How to
</button>
</div>
</div>
<div flex class="layout-column md-padding">
<span class="wz-headline-title">
<react-component name="EuiIcon" props="{type:'visHeatmap'}" /> Details
</span>
<md-divider class="wz-margin-top-10"></md-divider>
<div class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow euiFlexGroup--responsive wz-margin-top-4">
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<div class="euiStat">
<div class="euiText euiText--small euiStat__description">
<p>Active</p>
</div>
<p class="euiTitle euiTitle--small euiStat__title">{{ctrl.summary.agentsCountActive}}</p>
</div>
</div>
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<div class="euiStat">
<div class="euiText euiText--small euiStat__description">
<p>Disconnected</p>
</div>
<p class="euiTitle euiTitle--small euiStat__title">{{ctrl.summary.agentsCountDisconnected}}</p>
</div>
</div>
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<div class="euiStat">
<div class="euiText euiText--small euiStat__description">
<p>Never connected</p>
</div>
<p class="euiTitle euiTitle--small euiStat__title">{{ctrl.summary.agentsCountNeverConnected}}</p>
</div>
</div>
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<div class="euiStat">
<div class="euiText euiText--small euiStat__description">
<p>Agents coverage</p>
</div>
<p class="euiTitle euiTitle--small euiStat__title">{{(ctrl.summary.agentsCoverity | number:2)}}%</p>
</div>
</div>
</div>
<div class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow euiFlexGroup--responsive">
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<div class="euiStat">
<div class="euiText euiText--small euiStat__description">
<p>Last registered agent</p>
</div>
<p ng-if="ctrl.lastAgent && ctrl.lastAgent.id && ctrl.lastAgent.id !== '000'" ng-click="ctrl.showAgent(ctrl.lastAgent)"
class="euiTitle euiTitle--small euiStat__title wz-text-link cursor-pointer">
{{ctrl.lastAgent.name}}</p>
<p ng-if="!ctrl.lastAgent || !ctrl.lastAgent.id" class="euiTitle euiTitle--small euiStat__title">
-</p>
</div>
</div>
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<div class="euiStat">
<div class="euiText euiText--small euiStat__description">
<p>Most active agent</p>
</div>
<p ng-if="ctrl.lastAgent && ctrl.lastAgent.id && ctrl.mostActiveAgent.id !== '000'" ng-click="ctrl.showAgent(ctrl.mostActiveAgent)"
class="euiTitle euiTitle--small euiStat__title wz-text-link cursor-pointer">
{{ctrl.mostActiveAgent.name}}</p>
<p ng-if="!ctrl.lastAgent || !ctrl.lastAgent.id" class="euiTitle euiTitle--small euiStat__title">
-</p>
</div>
</div>
</div>
</div>
<div class="registerAgent" ng-show="ctrl.addingNewAgent">
<react-component name="RegisterAgent" props="ctrl.registerAgentsProps" />
</div>
<div layout="row" class="md-padding">
<wz-tag-filter flex path="'/agents'" query-fn="ctrl.query(q, search)" fields-model="ctrl.searchBarModel">
</wz-tag-filter>
<md-button class="agents-prev-btn btn btn-info" style="height: 48px;margin: 0px 0 0 8px!important;" ng-click="ctrl.reloadList()">
<react-component name="EuiIcon" props="{type:'refresh'}" /> Refresh</md-button>
</div>
<div layout="row">
<md-card flex class="wz-md-card _md flex md-margin-h">
<md-card-content>
<div layout="row">
<wz-table custom-columns="true" flex path="'/agents'" keys="[{value: 'id', width: '75px'},'name','ip','status','group','os.name','os.version','version', {value: 'dateAdd', offset: true}, {value: 'lastKeepAlive', offset: true}]"
allow-click="true" row-sizes="[17,15,13]"></wz-table>
<div ng-show="!ctrl.addingNewAgent">
<div class="md-padding euiFlexGroup--wrap layout-row">
<div class="layout-column md-padding">
<span class="wz-headline-title">
<react-component name="EuiIcon" props="{type:'node'}" /> Status
</span>
<md-divider class="wz-margin-top-10"></md-divider>
<canvas id="bar" ng-if="ctrl.lastAgent && ctrl.lastAgent.id" class="wz-margin-top-16 chart chart-doughnut"
chart-data="[ctrl.summary.agentsCountActive,ctrl.summary.agentsCountDisconnected,ctrl.summary.agentsCountNeverConnected]"
chart-labels="['Active','Disconnected', 'Never connected']" chart-colors="['#57C17B', '#BC52BC', '#9E3533']"
chart-options="{cutoutPercentage: 75, legend: {display: true,position: 'right',},responsive: false, maintainAspectRatio: false}" />
<div layout="row" class="wz-margin-top-16 layout-align-center-center" ng-if="!ctrl.lastAgent || !ctrl.lastAgent.id">
There are no agents yet.
</div>
<div layout="row" layout-align="end center">
<button type="button" ng-click="ctrl.downloadCsv()" class="euiButtonEmpty euiButtonEmpty--primary euiButtonEmpty--small">
<span class="euiButtonEmpty__content">
<react-component name="EuiIcon" props="{type:'importAction'}" />
<span class="euiButtonEmpty__text">Formatted</span>
</span>
<div layout="row" class="wz-margin-top-16 layout-align-center-center" ng-if="!ctrl.lastAgent || !ctrl.lastAgent.id">
<button class="kuiButton kuiButton--success" ng-click="ctrl.openRegistrationDocs()">
<react-component name="EuiIcon" props="{type: 'help'}" /> How to
</button>
</div>
</md-card-content>
</md-card>
</div>
<div flex class="layout-column md-padding">
<span class="wz-headline-title">
<react-component name="EuiIcon" props="{type:'visHeatmap'}" /> Details
</span>
<md-divider class="wz-margin-top-10"></md-divider>
<div class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow euiFlexGroup--responsive wz-margin-top-4">
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<div class="euiStat">
<div class="euiText euiText--small euiStat__description">
<p>Active</p>
</div>
<p class="euiTitle euiTitle--small euiStat__title">{{ctrl.summary.agentsCountActive}}</p>
</div>
</div>
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<div class="euiStat">
<div class="euiText euiText--small euiStat__description">
<p>Disconnected</p>
</div>
<p class="euiTitle euiTitle--small euiStat__title">{{ctrl.summary.agentsCountDisconnected}}</p>
</div>
</div>
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<div class="euiStat">
<div class="euiText euiText--small euiStat__description">
<p>Never connected</p>
</div>
<p class="euiTitle euiTitle--small euiStat__title">{{ctrl.summary.agentsCountNeverConnected}}</p>
</div>
</div>
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<div class="euiStat">
<div class="euiText euiText--small euiStat__description">
<p>Agents coverage</p>
</div>
<p class="euiTitle euiTitle--small euiStat__title">{{(ctrl.summary.agentsCoverity |
number:2)}}%</p>
</div>
</div>
</div>
<div class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow euiFlexGroup--responsive">
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<div class="euiStat">
<div class="euiText euiText--small euiStat__description">
<p>Last registered agent</p>
</div>
<p ng-if="ctrl.lastAgent && ctrl.lastAgent.id && ctrl.lastAgent.id !== '000'" ng-click="ctrl.showAgent(ctrl.lastAgent)"
class="euiTitle euiTitle--small euiStat__title wz-text-link cursor-pointer">
{{ctrl.lastAgent.name}}</p>
<p ng-if="!ctrl.lastAgent || !ctrl.lastAgent.id" class="euiTitle euiTitle--small euiStat__title">
-</p>
</div>
</div>
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<div class="euiStat">
<div class="euiText euiText--small euiStat__description">
<p>Most active agent</p>
</div>
<p ng-if="ctrl.lastAgent && ctrl.lastAgent.id && ctrl.mostActiveAgent.id !== '000'"
ng-click="ctrl.showAgent(ctrl.mostActiveAgent)" class="euiTitle euiTitle--small euiStat__title wz-text-link cursor-pointer">
{{ctrl.mostActiveAgent.name}}</p>
<p ng-if="!ctrl.lastAgent || !ctrl.lastAgent.id" class="euiTitle euiTitle--small euiStat__title">
-</p>
</div>
</div>
</div>
</div>
</div>
<div layout="row" class="md-padding">
<wz-tag-filter flex path="'/agents'" query-fn="ctrl.query(q, search)" fields-model="ctrl.searchBarModel">
</wz-tag-filter>
<md-button class="agents-prev-btn btn btn-info" style="height: 48px;margin: 0px 0 0 8px!important;"
ng-click="ctrl.reloadList()">
<react-component name="EuiIcon" props="{type:'refresh'}" /> Refresh</md-button>
</div>
<div layout="row">
<md-card flex class="wz-md-card _md flex md-margin-h">
<md-card-actions ng-if="adminMode" layout="row" layout-align="end center" class="wz-card-actions wz-card-actions-top">
<a ng-click="ctrl.addNewAgent(true)">
<react-component name="EuiIcon" props="{type:'plusInCircle'}" /> Add new agent </a>
<span flex></span>
</md-card-actions>
<md-card-content>
<div layout="row">
<wz-table custom-columns="true" flex path="'/agents'" keys="[{value: 'id', width: '75px'},'name','ip','status','group','os.name','os.version','version', {value: 'dateAdd', offset: true}, {value: 'lastKeepAlive', offset: true}]"
allow-click="true" row-sizes="[17,15,13]"></wz-table>
</div>
<div layout="row" layout-align="end center">
<button type="button" ng-click="ctrl.downloadCsv()" class="euiButtonEmpty euiButtonEmpty--primary euiButtonEmpty--small">
<span class="euiButtonEmpty__content">
<react-component name="EuiIcon" props="{type:'importAction'}" />
<span class="euiButtonEmpty__text">Formatted</span>
</span>
</button>
</div>
</md-card-content>
</md-card>
</div>
</div>
</div>

View File

@ -0,0 +1,104 @@
<md-content flex layout="column" ng-if="tab === 'hipaa' && tabView === 'panels'" ng-class="{'no-opacity': resultState !== 'ready' || !rendered}"
layout-align="start">
<!-- View: Panels -->
<div layout="row" layout-align="center stretch">
<md-card flex class="wz-md-card">
<md-tabs md-selected="selectedHipaaIndex" class="wz-md-tab" md-border-bottom md-dynamic-height id="hipaaReq_tab">
<md-tab ng-repeat="tab in hipaaTabs" ng-disabled="tab.disabled" label="{{tab.title}}">
<div class="md-padding">
<span class="wz-headline-title">HIPAA Requirement: {{tab.title}}</span>
<md-divider class="wz-margin-top-10"></md-divider>
<div layout="row" class="wz-padding-top-10 wz-line-height">
<div ng-bind-html="tab.content"></div>
</div>
</div>
</md-tab>
</md-tabs>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-300">
<md-card flex class="wz-md-card" ng-class="{'fullscreen': expandArray[0]}">
<md-card-actions layout="row" layout-align="end center" class="wz-card-actions-vis" ng-dblclick="expand(0)">
<span class="wz-headline-title">Top 5 rule groups</span>
<span flex></span>
<span class="cursor-pointer" ng-click="expand(0)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Agents-HIPAA-Groups" vis-id="'Wazuh-App-Agents-HIPAA-Groups'"></kbn-vis>
</md-card-content>
</md-card>
<md-card flex class="wz-md-card" ng-class="{'fullscreen': expandArray[1]}">
<md-card-actions layout="row" layout-align="end center" class="wz-card-actions-vis" ng-dblclick="expand(1)">
<span class="wz-headline-title">Top 5 rules</span>
<span flex></span>
<span class="cursor-pointer" ng-click="expand(1)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Agents-HIPAA-Rule" vis-id="'Wazuh-App-Agents-HIPAA-Rule'"></kbn-vis>
</md-card-content>
</md-card>
<md-card flex class="wz-md-card" ng-class="{'fullscreen': expandArray[2]}">
<md-card-actions layout="row" layout-align="end center" class="wz-card-actions-vis" ng-dblclick="expand(2)">
<span class="wz-headline-title">Top 5 HIPAA requirements</span>
<span flex></span>
<span class="cursor-pointer" ng-click="expand(2)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Agents-HIPAA-Requirement" vis-id="'Wazuh-App-Agents-HIPAA-Requirement'"></kbn-vis>
</md-card-content>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-300">
<md-card flex="70" class="wz-md-card" ng-class="{'fullscreen': expandArray[3]}">
<md-card-actions layout="row" layout-align="end center" class="wz-card-actions-vis" ng-dblclick="expand(3)">
<span class="wz-headline-title">HIPAA Requirements</span>
<span flex></span>
<span class="cursor-pointer" ng-click="expand(3)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Agents-HIPAA-Requirements" vis-id="'Wazuh-App-Agents-HIPAA-Requirements'">
</kbn-vis>
</md-card-content>
</md-card>
<md-card flex class="wz-md-card" ng-class="{'fullscreen': expandArray[4]}">
<md-card-actions layout="row" layout-align="end center" class="wz-card-actions-vis" ng-dblclick="expand(4)">
<span class="wz-headline-title">Rule level distribution</span>
<span flex></span>
<span class="cursor-pointer" ng-click="expand(4)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Agents-HIPAA-Rule-level-distribution" vis-id="'Wazuh-App-Agents-HIPAA-Rule-level-distribution'"></kbn-vis>
</md-card-content>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-570">
<md-card class="wz-md-card" flex ng-class="{'fullscreen': expandArray[5]}">
<md-card-actions layout="row" layout-align="end center" class="wz-card-actions-vis" ng-dblclick="expand(5)">
<span class="wz-headline-title">Alerts summary</span>
<span flex></span>
<span class="cursor-pointer" ng-click="expand(5)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis vis-id="'Wazuh-App-Agents-HIPAA-Last-alerts'"></kbn-vis>
</md-card-content>
</md-card>
</div>
</md-content>

View File

@ -0,0 +1,104 @@
<md-content flex layout="column" ng-if="tab === 'nist' && tabView === 'panels'" ng-class="{'no-opacity': resultState !== 'ready' || !rendered}"
layout-align="start">
<!-- View: Panels -->
<div layout="row" layout-align="center stretch">
<md-card flex class="wz-md-card">
<md-tabs md-selected="selectedNistIndex" class="wz-md-tab" md-border-bottom md-dynamic-height id="nistReq_tab">
<md-tab ng-repeat="tab in nistTabs" ng-disabled="tab.disabled" label="{{tab.title}}">
<div class="md-padding">
<span class="wz-headline-title">NIST-800-53 Requirement: {{tab.title}}</span>
<md-divider class="wz-margin-top-10"></md-divider>
<div layout="row" class="wz-padding-top-10 wz-line-height">
<div ng-bind-html="tab.content"></div>
</div>
</div>
</md-tab>
</md-tabs>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-300">
<md-card flex class="wz-md-card" ng-class="{'fullscreen': expandArray[0]}">
<md-card-actions layout="row" layout-align="end center" class="wz-card-actions-vis" ng-dblclick="expand(0)">
<span class="wz-headline-title">Top 5 rule groups</span>
<span flex></span>
<span class="cursor-pointer" ng-click="expand(0)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Agents-NIST-Groups" vis-id="'Wazuh-App-Agents-NIST-Groups'"></kbn-vis>
</md-card-content>
</md-card>
<md-card flex class="wz-md-card" ng-class="{'fullscreen': expandArray[1]}">
<md-card-actions layout="row" layout-align="end center" class="wz-card-actions-vis" ng-dblclick="expand(1)">
<span class="wz-headline-title">Top 5 rules</span>
<span flex></span>
<span class="cursor-pointer" ng-click="expand(1)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Agents-NIST-Rule" vis-id="'Wazuh-App-Agents-NIST-Rule'"></kbn-vis>
</md-card-content>
</md-card>
<md-card flex class="wz-md-card" ng-class="{'fullscreen': expandArray[2]}">
<md-card-actions layout="row" layout-align="end center" class="wz-card-actions-vis" ng-dblclick="expand(2)">
<span class="wz-headline-title">Top 5 NIST-800-53 requirements</span>
<span flex></span>
<span class="cursor-pointer" ng-click="expand(2)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Agents-NIST-Requirement" vis-id="'Wazuh-App-Agents-NIST-Requirement'"></kbn-vis>
</md-card-content>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-300">
<md-card flex="70" class="wz-md-card" ng-class="{'fullscreen': expandArray[3]}">
<md-card-actions layout="row" layout-align="end center" class="wz-card-actions-vis" ng-dblclick="expand(3)">
<span class="wz-headline-title">NIST-800-53 Requirements</span>
<span flex></span>
<span class="cursor-pointer" ng-click="expand(3)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Agents-NIST-Requirements" vis-id="'Wazuh-App-Agents-NIST-Requirements'">
</kbn-vis>
</md-card-content>
</md-card>
<md-card flex class="wz-md-card" ng-class="{'fullscreen': expandArray[4]}">
<md-card-actions layout="row" layout-align="end center" class="wz-card-actions-vis" ng-dblclick="expand(4)">
<span class="wz-headline-title">Rule level distribution</span>
<span flex></span>
<span class="cursor-pointer" ng-click="expand(4)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Agents-NIST-Rule-level-distribution" vis-id="'Wazuh-App-Agents-NIST-Rule-level-distribution'"></kbn-vis>
</md-card-content>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-570">
<md-card class="wz-md-card" flex ng-class="{'fullscreen': expandArray[5]}">
<md-card-actions layout="row" layout-align="end center" class="wz-card-actions-vis" ng-dblclick="expand(5)">
<span class="wz-headline-title">Alerts summary</span>
<span flex></span>
<span class="cursor-pointer" ng-click="expand(5)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis vis-id="'Wazuh-App-Agents-NIST-Last-alerts'"></kbn-vis>
</md-card-content>
</md-card>
</div>
</md-content>

View File

@ -7,20 +7,18 @@
not fetch data for this agent. <span ng-if="emptyAgent">Reason: {{emptyAgent}}</span></span>
</div>
<div layout="row" layout-padding ng-if="emptyAgent">
<span class="cursor-pointer" ng-click="getAgent()"><i class="fa fa-fw fa-refresh"
aria-hidden="true"></i>
<span class="cursor-pointer" ng-click="getAgent()"><i class="fa fa-fw fa-refresh" aria-hidden="true"></i>
Try again</span>
</div>
</md-card-content>
</md-card>
</div>
</div>
<div layout="column" class="" layout-align="start stretch" ng-if="tab === 'welcome'" ng-show="!load && agent">
<div layout="column" layout-align="start stretch" ng-if="tab === 'welcome'" ng-show="!load && agent">
<div layout="row" class="wz-margin-left-16 wz-margin-right-16 wz-margin-top-8">
<span flex></span>
<button class="kuiButton kuiButton--secondary small wz-no-margin" ng-click="goDiscover()"><i
class="fa fa-compass"></i>
<button class="kuiButton kuiButton--secondary small wz-no-margin" ng-click="goDiscover()"><i class="fa fa-compass"></i>
Discover
</button>
</div>
@ -36,7 +34,7 @@
}" />
</div>
<div layout="row" layout-padding>
<div layout="row" layout-padding ng-if="welcomeCardsProps">
<react-component name="WelcomeScreenAgent" props="welcomeCardsProps" />
</div>
</div>

View File

@ -135,12 +135,16 @@
<!-- End Security navigation bar -->
<!-- Compliance navigation bar -->
<md-nav-bar ng-if="inArray(tab, complianceTabs) && extensions.pci && extensions.gdpr" class="wz-nav-bar"
<md-nav-bar ng-if="inArray(tab, complianceTabs) && (extensions.pci || extensions.gdpr || extensions.hipaa || extensions.nist)" class="wz-nav-bar"
ng-show="tab !== 'welcome'" md-selected-nav-item="tab" nav-bar-aria-label="Compliance navigation links">
<md-nav-item ng-show="extensions.pci" class="wz-nav-item" md-nav-click="switchTab('pci')" name="pci">{{
tabNames['pci'] }}</md-nav-item>
<md-nav-item ng-show="extensions.gdpr" class="wz-nav-item" md-nav-click="switchTab('gdpr')" name="gdpr">{{
tabNames['gdpr'] }}</md-nav-item>
<md-nav-item ng-show="extensions.hipaa" class="wz-nav-item" md-nav-click="switchTab('hipaa')" name="hipaa">{{
tabNames['hipaa'] }}</md-nav-item>
<md-nav-item ng-show="extensions.nist" class="wz-nav-item" md-nav-click="switchTab('nist')" name="nist">{{
tabNames['nist'] }}</md-nav-item>
</md-nav-bar>
<!-- End Compliance navigation bar -->

View File

@ -9,6 +9,8 @@ include ./agents-audit.html
include ./agents-ciscat.html
include ./agents-pci.html
include ./agents-gdpr.html
include ./agents-hipaa.html
include ./agents-nist.html
include ./agents-virustotal.html
include ./agents-syscollector.html
include ./agents-osquery.html

View File

@ -32,7 +32,7 @@
<md-nav-item class="wz-nav-item" md-nav-click="switchConfigurationSubTab('fim-monitored')" name="fim-monitored">Monitored</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="switchConfigurationSubTab('fim-ignored')" name="fim-ignored">Ignored</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="switchConfigurationSubTab('fim-nodiff')" name="fim-nodiff">No diff</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="switchConfigurationSubTab('fim-whodata')" ng-if="!agent || agent.isLinuxOS" name="fim-whodata">Who-data</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="switchConfigurationSubTab('fim-whodata')" ng-if="!agent || agent.agentPlatform === 'linux'" name="fim-whodata">Who-data</md-nav-item>
</md-nav-bar>
<!-- End Integrity monitoring navigation bar -->

View File

@ -13,65 +13,58 @@
<div flex layout="row">
<div flex layout="column">
<md-card flex class="wz-md-card _md flex">
<md-card-actions ng-if="mctrl.adminMode || adminMode" ng-show="!agent || agent.id === '000'"
layout="row" class="wz-card-actions wz-card-actions-top layout-align-start-center">
<a ng-click="mctrl.setConfigTab('editconfiguration', true)">
<md-card-actions layout="row" class="wz-card-actions wz-card-actions-top layout-align-end-center"
ng-hide="agent && agent.id !== '000' && agent.status !== 'Active'">
<a ng-if="mctrl.adminMode || adminMode" ng-show="!agent || agent.id === '000'" ng-click="mctrl.setConfigTab('editconfiguration', true)">
<react-component name="EuiIcon" props="{type:'pencil', color:'primary'}" /> Edit configuration
</a>
<react-component ng-show="agent && agent.id !== '000' && agent.status === 'Active'" name="ExportConfiguration"
ng-hide="reportBusy && reportStatus" props="{exportConfiguration, type: 'agent', agentPlatform: agent.agentPlatform}" />
<react-component ng-show="reportBusy && reportStatus" name="EuiLoadingSpinner" props="{size:'m'}" />
</md-card-actions>
<md-card-content>
<span class="font-size-16 wz-text-bold">Main configurations</span>
<md-divider class="wz-margin-top-10"></md-divider>
<table ng-if="!agent || agent.id === '000'"
class="table table-striped table-condensed table-layout-fixed table-hover table-vertical-align-middle">
<table ng-if="!agent || agent.id === '000'" class="table table-striped table-condensed table-layout-fixed table-hover table-vertical-align-middle">
<thead class="wz-text-bold">
<th class="wz-text-left col-lg-2">Name</th>
<th class="wz-text-left">Description</th>
</thead>
<tbody>
<tr class="cursor-pointer"
ng-click="switchConfigTab('global-configuration', [{component:'analysis',configuration:'global'},{component:'mail',configuration:'global'},{component:'request',configuration:'remote'},{component:'com',configuration:'logging'}])">
<tr class="cursor-pointer" ng-click="switchConfigTab('global-configuration', [{component:'analysis',configuration:'global'},{component:'mail',configuration:'global'},{component:'request',configuration:'remote'},{component:'com',configuration:'logging'}])">
<td>Global configuration</td>
<td>Global and remote settings</td>
</tr>
<tr class="cursor-pointer"
ng-click="switchConfigTab('cluster', [{component:'com',configuration:'cluster'}])">
<tr class="cursor-pointer" ng-click="switchConfigTab('cluster', [{component:'com',configuration:'cluster'}])">
<td>Cluster</td>
<td>Master node configuration</td>
</tr>
<tr class="cursor-pointer"
ng-click="switchConfigTab('registration-service', [{component:'auth',configuration:'auth'}])">
<tr class="cursor-pointer" ng-click="switchConfigTab('registration-service', [{component:'auth',configuration:'auth'}])">
<td>Registration service</td>
<td>Automatic agent registration service</td>
</tr>
</tbody>
</table>
<table ng-if="agent && agent.id !== '000'"
class="table table-striped table-condensed table-layout-fixed table-hover table-vertical-align-middle">
<table ng-if="agent && agent.id !== '000'" class="table table-striped table-condensed table-layout-fixed table-hover table-vertical-align-middle">
<thead class="wz-text-bold">
<th class="wz-text-left col-lg-2">Name</th>
<th class="wz-text-left">Description</th>
</thead>
<tbody>
<tr class="cursor-pointer"
ng-click="switchConfigTab('global-configuration', [{component:'com',configuration:'logging'}])">
<tr class="cursor-pointer" ng-click="switchConfigTab('global-configuration', [{component:'com',configuration:'logging'}])">
<td>Global configuration</td>
<td>Logging settings that apply to the agent</td>
</tr>
<tr class="cursor-pointer"
ng-click="switchConfigTab('client', [{component:'agent',configuration:'client'}])">
<tr class="cursor-pointer" ng-click="switchConfigTab('client', [{component:'agent',configuration:'client'}])">
<td>Communication</td>
<td>Settings related to the connection with the manager</td>
</tr>
<tr class="cursor-pointer"
ng-click="switchConfigTab('client-buffer', [{component:'agent',configuration:'buffer'}])">
<tr class="cursor-pointer" ng-click="switchConfigTab('client-buffer', [{component:'agent',configuration:'buffer'}])">
<td>Anti-flooding settings</td>
<td>Agent bucket parameters to avoid event flooding</td>
</tr>
<tr class="cursor-pointer"
ng-click="switchConfigTab('alerts',[{component:'agent',configuration:'labels'}])">
<tr class="cursor-pointer" ng-click="switchConfigTab('alerts',[{component:'agent',configuration:'labels'}])">
<td>Labels</td>
<td>User-defined information about the agent included in alerts</td>
</tr>
@ -81,20 +74,17 @@
<span ng-if="!agent || agent.id === '000'" class="font-size-16 wz-text-bold">Alerts and output
management</span>
<md-divider ng-if="!agent || agent.id === '000'" class="wz-margin-top-10"></md-divider>
<table ng-if="!agent || agent.id === '000'"
class="table table-striped table-condensed table-layout-fixed table-hover table-vertical-align-middle">
<table ng-if="!agent || agent.id === '000'" class="table table-striped table-condensed table-layout-fixed table-hover table-vertical-align-middle">
<thead class="wz-text-bold">
<th class="wz-text-left col-lg-2">Name</th>
<th class="wz-text-left">Description</th>
</thead>
<tbody>
<tr class="cursor-pointer"
ng-click="switchConfigTab('alerts',[{component:'analysis',configuration:'alerts'},{component:'analysis',configuration:'labels'},{component:'mail',configuration:'alerts'},{component:'monitor',configuration:'reports'}, {component:'csyslog',configuration:'csyslog'}])">
<tr class="cursor-pointer" ng-click="switchConfigTab('alerts',[{component:'analysis',configuration:'alerts'},{component:'analysis',configuration:'labels'},{component:'mail',configuration:'alerts'},{component:'monitor',configuration:'reports'}, {component:'csyslog',configuration:'csyslog'}])">
<td>Alerts</td>
<td>Settings related to the alerts and their format</td>
</tr>
<tr class="cursor-pointer"
ng-click="switchConfigTab('integrations',[{component:'integrator',configuration:'integration'}])">
<tr class="cursor-pointer" ng-click="switchConfigTab('integrations',[{component:'integrator',configuration:'integration'}])">
<td>Integrations</td>
<td>Slack, VirusTotal and PagerDuty integrations with external APIs</td>
</tr>
@ -103,20 +93,18 @@
<span class="font-size-16 wz-text-bold">Auditing and policy monitoring</span>
<md-divider class="wz-margin-top-10"></md-divider>
<table
class="table table-striped table-condensed table-layout-fixed table-hover table-vertical-align-middle">
<table class="table table-striped table-condensed table-layout-fixed table-hover table-vertical-align-middle">
<thead class="wz-text-bold">
<th class="wz-text-left col-lg-2">Name</th>
<th class="wz-text-left">Description</th>
</thead>
<tbody>
<tr class="cursor-pointer"
ng-click="switchConfigTab('policy-monitoring', [{component:'syscheck',configuration:'rootcheck'}, {component:'wmodules',configuration:'wmodules'}])">
<tr class="cursor-pointer" ng-click="switchConfigTab('policy-monitoring', [{component:'syscheck',configuration:'rootcheck'}, {component:'wmodules',configuration:'wmodules'}])">
<td>Policy monitoring</td>
<td>Configuration to ensure compliance with security policies, standards and hardening
guides</td>
</tr>
<tr class="cursor-pointer" ng-click="switchWodle('open-scap')">
<tr class="cursor-pointer" ng-click="switchWodle('open-scap')" ng-if="shouldShowComponent('oscap')">
<td>OpenSCAP</td>
<td>Configuration assessment and automation of compliance monitoring using SCAP checks
</td>
@ -131,15 +119,13 @@
<span class="font-size-16 wz-text-bold">System threats and incident response</span>
<md-divider class="wz-margin-top-10"></md-divider>
<table
class="table table-striped table-condensed table-layout-fixed table-hover table-vertical-align-middle">
<table class="table table-striped table-condensed table-layout-fixed table-hover table-vertical-align-middle">
<thead class="wz-text-bold">
<th class="wz-text-left col-lg-2">Name</th>
<th class="wz-text-left">Description</th>
</thead>
<tbody>
<tr class="cursor-pointer" ng-if="!agent || agent.id === '000'"
ng-click="switchWodle('vulnerability-detector')">
<tr class="cursor-pointer" ng-if="!agent || agent.id === '000'" ng-click="switchWodle('vulnerability-detector')">
<td>Vulnerabilities</td>
<td>Discover what applications are affected by well-known vulnerabilities</td>
</tr>
@ -153,14 +139,12 @@
<td>Gather relevant information about system OS, hardware, networking and packages
</td>
</tr>
<tr class="cursor-pointer" ng-if="!agent || agent.id === '000'"
ng-click="switchConfigTab('active-response',[{component:'analysis',configuration:'command'},{component:'analysis',configuration:'active_response'}])">
<tr class="cursor-pointer" ng-if="!agent || agent.id === '000'" ng-click="switchConfigTab('active-response',[{component:'analysis',configuration:'command'},{component:'analysis',configuration:'active_response'}])">
<td>Active response</td>
<td>Active threat addressing by inmmediate response
</td>
</tr>
<tr class="cursor-pointer" ng-if="agent && agent.id !== '000'"
ng-click="switchConfigTab('active-response',[{component:'com',configuration:'active-response'}])">
<tr class="cursor-pointer" ng-if="agent && agent.id !== '000'" ng-click="switchConfigTab('active-response',[{component:'com',configuration:'active-response'}])">
<td>Active response</td>
<td>Active threat addressing by inmmediate response
</td>
@ -170,7 +154,7 @@
<td>Configuration options of the Command wodle
</td>
</tr>
<tr class="cursor-pointer" ng-click="switchWodle('docker-listener')">
<tr class="cursor-pointer" ng-click="switchWodle('docker-listener')" ng-if="shouldShowComponent('docker')">
<td>Docker listener</td>
<td>Monitor and collect the activity from Docker containers such as creation, running,
starting, stopping or pausing events
@ -181,26 +165,22 @@
<span class="font-size-16 wz-text-bold">Log data analysis</span>
<md-divider class="wz-margin-top-10"></md-divider>
<table
class="table table-striped table-condensed table-layout-fixed table-hover table-vertical-align-middle">
<table class="table table-striped table-condensed table-layout-fixed table-hover table-vertical-align-middle">
<thead class="wz-text-bold">
<th class="wz-text-left col-lg-2">Name</th>
<th class="wz-text-left">Description</th>
</thead>
<tbody>
<tr class="cursor-pointer"
ng-click="switchConfigTab('log-collection',[{component:'logcollector',configuration:'localfile'},{component:'logcollector',configuration:'socket'}])">
<tr class="cursor-pointer" ng-click="switchConfigTab('log-collection',[{component:'logcollector',configuration:'localfile'},{component:'logcollector',configuration:'socket'}])">
<td>Log collection</td>
<td>Log analysis from text files, Windows events or syslog outputs</td>
</tr>
<tr class="cursor-pointer"
ng-click="switchConfigTab('integrity-monitoring',[{component:'syscheck',configuration:'syscheck'}])">
<tr class="cursor-pointer" ng-click="switchConfigTab('integrity-monitoring',[{component:'syscheck',configuration:'syscheck'}])">
<td>Integrity monitoring</td>
<td>Identify changes in content, permissions, ownership, and attributes of files
</td>
</tr>
<tr class="cursor-pointer" ng-if="!agent || agent.id === '000'"
ng-click="switchConfigTab('agentless',[{component:'agentless',configuration:'agentless'}])">
<tr class="cursor-pointer" ng-if="!agent || agent.id === '000'" ng-click="switchConfigTab('agentless',[{component:'agentless',configuration:'agentless'}])">
<td>Agentless</td>
<td>Run integrity checks on devices such as routers, firewalls and switches
</td>
@ -211,8 +191,7 @@
<span ng-if="!agent || agent.id === '000'" class="font-size-16 wz-text-bold">Cloud security
monitoring</span>
<md-divider ng-if="!agent || agent.id === '000'" class="wz-margin-top-10"></md-divider>
<table ng-if="!agent || agent.id === '000'"
class="table table-striped table-condensed table-layout-fixed table-hover table-vertical-align-middle">
<table ng-if="!agent || agent.id === '000'" class="table table-striped table-condensed table-layout-fixed table-hover table-vertical-align-middle">
<thead class="wz-text-bold">
<th class="wz-text-left col-lg-2">Name</th>
<th class="wz-text-left">Description</th>
@ -234,14 +213,11 @@
</span>
<md-list ng-if="showHelp">
<md-subheader>More info about this section</md-subheader>
<md-list-item target="_blank" class="wz-text-link"
ng-href="https://documentation.wazuh.com/current/user-manual/manager/index.html">Wazuh
<md-list-item target="_blank" class="wz-text-link" ng-href="https://documentation.wazuh.com/current/user-manual/manager/index.html">Wazuh
administration documentation</md-list-item>
<md-list-item target="_blank" class="wz-text-link"
ng-href="https://documentation.wazuh.com/current/user-manual/capabilities/index.html">Wazuh
<md-list-item target="_blank" class="wz-text-link" ng-href="https://documentation.wazuh.com/current/user-manual/capabilities/index.html">Wazuh
capabilities documentation</md-list-item>
<md-list-item target="_blank" class="wz-text-link"
ng-href="https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/index.html">Local
<md-list-item target="_blank" class="wz-text-link" ng-href="https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/index.html">Local
configuration reference</md-list-item>
</md-list>
</md-sidenav>

View File

@ -142,6 +142,10 @@
<div ng-if='!addingAgents'>
<!-- Group agents table -->
<md-card flex class="wz-md-card _md flex md-margin-h wz-margin-top-16" ng-if="lookingGroup && groupsSelectedTab==='agents' && currentGroup">
<md-card-actions layout="row" class="wz-card-actions wz-card-actions-top layout-align-end-center">
<react-component name="ExportConfiguration" ng-hide="reportBusy && reportStatus" props="{exportConfiguration, type: 'group'}" />
<react-component ng-show="reportBusy && reportStatus" name="EuiLoadingSpinner" props="{size:'m'}" />
</md-card-actions>
<div layout="row" ng-show="failedErrors" class="extraHeader">
<md-list>
<md-list-item class="error-enum-configuration" ng-repeat="group in failedErrors">
@ -174,6 +178,10 @@
<!-- Group files table -->
<md-card flex class="wz-md-card _md flex md-margin-h wz-margin-top-16" ng-if="lookingGroup && groupsSelectedTab==='files' && !fileViewer && currentGroup">
<md-card-actions layout="row" class="wz-card-actions wz-card-actions-top layout-align-end-center">
<react-component name="ExportConfiguration" ng-hide="reportBusy && reportStatus" props="{exportConfiguration, type: 'group'}" />
<react-component ng-show="reportBusy && reportStatus" name="EuiLoadingSpinner" props="{size:'m'}" />
</md-card-actions>
<md-card-content>
<div layout="row">
<wz-table custom-columns="true" flex path="'/agents/groups/' + currentGroup.name + '/files'"

View File

@ -67,14 +67,7 @@
</div>
</div>
<md-nav-bar ng-if="!mctrl.load && mctrl.inArray(mctrl.tab, mctrl.statusReportsTabs) && mctrl.tab !== 'monitoring'"
class="wz-nav-bar" ng-show="mctrl.tab !== 'welcome'" md-selected-nav-item="mctrl.tab"
nav-bar-aria-label="Status and reports navigation links">
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.switchTab('status', true)" name="status">Status
</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.switchTab('logs', true)" name="logs">Logs</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.switchTab('monitoring', true)" name="monitoring">Cluster
</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.switchTab('reporting', true)" name="reporting">Reporting
</md-nav-item>
</md-nav-bar>
<div ng-if="!mctrl.load && mctrl.inArray(mctrl.tab, mctrl.statusReportsTabs) && mctrl.tab !== 'monitoring' && mctrl.tab !== 'welcome'"
class="md-padding-h" ng-show="mctrl.tab !== 'welcome'" >
<react-component name="Tabs" props="mctrl.managementTabsProps" />
</div>

View File

@ -14,15 +14,9 @@
<!-- End cluster disabled breadcrumbs -->
<!-- Status and reports navigation bar -->
<md-nav-bar class="wz-nav-bar" ng-show="mctrl.tab !== 'welcome'" md-selected-nav-item="mctrl.tab"
nav-bar-aria-label="Status and reports navigation links">
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.switchTab('status')" name="status">Status</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.switchTab('logs')" name="logs">Logs</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.switchTab('monitoring')" name="monitoring">Cluster
</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.switchTab('reporting')" name="reporting">Reporting
</md-nav-item>
</md-nav-bar>
<div ng-show="mctrl.tab !== 'welcome'" class="md-padding-h">
<react-component name="Tabs" props="mctrl.managementTabsProps" />
</div>
<!-- End status and reports navigation bar -->
<!-- Cluster disabled section -->
@ -110,15 +104,9 @@
<!-- End navigation section -->
<!-- Status and reports navigation bar -->
<md-nav-bar ng-if="!loading" class="wz-nav-bar" ng-show="mctrl.tab !== 'welcome'"
md-selected-nav-item="mctrl.tab" nav-bar-aria-label="Status and reports navigation links">
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.switchTab('status')" name="status">Status</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.switchTab('logs')" name="logs">Logs</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.switchTab('monitoring')" name="monitoring">Cluster
</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.switchTab('reporting')" name="reporting">Reporting
</md-nav-item>
</md-nav-bar>
<div ng-if="!loading" ng-show="mctrl.tab !== 'welcome'" class="md-padding-h">
<react-component name="Tabs" props="mctrl.managementTabsProps" />
</div>
<!-- End status and reports navigation bar -->
<!-- Discover search bar section -->

View File

@ -1,30 +1,8 @@
<div layout="column" layout-align="start stretch" ng-controller="reportingController as ctrl" ng-if="mctrl.tab === 'reporting'">
<div ng-if="ctrl.loading" class="md-padding wz-margin-top-16">
<react-component name="EuiProgress" props="{size: 'xs', color: 'primary'}" />
</div>
<div layout="row" layout-padding ng-if="!ctrl.loading && ctrl.reportingTableProps">
<react-component name="ReportingTable" props="ctrl.reportingTableProps" />
</div>
<!--
<div layout="row" class="wz-margin-top-16" layout-align="start start"
ng-show="!ctrl.loading && (!ctrl.pagedItems || !ctrl.pagedItems.length)">
<md-card flex class="wz-md-card" flex>
<md-card-content class="wz-text-center">
<i class="fa fa-fw fa-info-circle" aria-hidden="true"></i> <span class="wz-headline-title">No reports
available</span>
<md-divider class="wz-margin-top-10"></md-divider>
<div layout="column" class="wz-padding-top-10">
<p>There are no reports yet. Go to the Overview or Agents tabs and click on the <i
class="fa fa-fw fa-print" aria-hidden="true"></i> icon to create one.</p>
</div>
</md-card-content>
</md-card>
</div>
-->
</div>

View File

@ -3,8 +3,7 @@
<div layout="row" layout-align="start center" ng-show="!editingFile">
<!-- Back button -->
<md-button class="md-icon-button" style="margin: 5px!important;" aria-label="Back to rules list" tooltip="Back"
tooltip-placement="bottom" ng-click="closeDetailView(true)"><i class="fa fa-fw fa-arrow-left"
aria-hidden="true"></i></md-button>
tooltip-placement="bottom" ng-click="closeDetailView(true)"><i class="fa fa-fw fa-arrow-left" aria-hidden="true"></i></md-button>
<!-- Rule title -->
<div>
<h1 class="font-size-18" ng-bind-html="colorRuleArg(currentRule.description)"></h1>
@ -16,8 +15,7 @@
<div layout="row" ng-show="!editingFile" class="wz-padding-left-8 wz-padding-right-8">
<md-card flex class="wz-metric-color wz-md-card">
<md-card-content layout="row" class="wz-padding-metric">
<div flex="15" ng-if="currentRule.id" class="wz-text-truncatable">ID: <span
class="wz-text-bold">{{currentRule.id}}</span></div>
<div flex="15" ng-if="currentRule.id" class="wz-text-truncatable">ID: <span class="wz-text-bold">{{currentRule.id}}</span></div>
<div flex="15" ng-if="currentRule.level || currentRule.level == 0" class="wz-text-truncatable">Level:
<span class="wz-text-bold wz-text-link" ng-click="addDetailFilter('level', currentRule.level)"
tooltip="Filter by this level" tooltip-placement="bottom">{{currentRule.level}}</span></div>
@ -33,8 +31,7 @@
</div>
<!-- End Rule information ribbon -->
<div layout="row" class="md-padding"
ng-if="!editingFile && currentRule.file && currentRule.path === 'etc/rules' && adminMode">
<div layout="row" class="md-padding" ng-if="!editingFile && currentRule.file && currentRule.path === 'etc/rules' && adminMode">
<button ng-click='editRulesConfig(currentRule)' class="height-35 kuiButton kuiButton--secondary">
<react-component name="EuiIcon" props="{type:'pencil'}" />
Edit {{ currentRule.file }}
@ -54,20 +51,17 @@
<div layout="row" class="wz-margin-top-10">
<div class="euiFlexItem">
<dl class="euiDescriptionList euiDescriptionList--row"
ng-repeat="(key, value) in currentRule.details">
<dl class="euiDescriptionList euiDescriptionList--row" ng-repeat="(key, value) in currentRule.details">
<dt class="euiDescriptionList__title">{{key}}</dt>
<dd class="euiDescriptionList__description">
<div ng-if='!isArray(value)' class="wz-word-break">
<span ng-if="!isObject(value)" class="wz-text-right color-grey">{{value}}</span>
<span ng-if="isObject(value)" class="color-grey">
<span ng-repeat="(key, value) in value">{{key}}: {{value}} <span
ng-if="!$last">|</span>
<span ng-repeat="(key, value) in value">{{key}}: {{value}} <span ng-if="!$last">|</span>
</span>
</span>
</div>
<span ng-if="isArray(value)" ng-repeat="v in value track by $index"
class="wz-text-right color-grey">
<span ng-if="isArray(value)" ng-repeat="v in value track by $index" class="wz-text-right color-grey">
{{v}}{{$last ? '' : ',&nbsp;'}}
</span>
</dd>
@ -98,20 +92,19 @@
</md-card-content>
</md-card>
<md-card flex class="wz-md-card" ng-if="currentRule.pci.length || currentRule.gdpr.length">
<md-card flex class="wz-md-card" ng-if="currentRule.pci.length || currentRule.gdpr.length || currentRule.hipaa.length ||currentRule.nist.length">
<md-card-content>
<span class="wz-margin-top-10 wz-headline-title">
<react-component name="EuiIcon" props="{type:'controlsHorizontal'}" /> Compliance
</span>
<md-divider class="wz-margin-top-10"></md-divider>
<div layout="row" class="wz-margin-top-10" ng-if="currentRule.pci.length">
<div class="euiFlexItem">
<dl class="euiDescriptionList euiDescriptionList--row">
<dt class="euiDescriptionList__title">PCI DSS</dt>
<dd class="euiDescriptionList__description" ng-repeat="item in currentRule.pci">
<span class="wz-text-link" tooltip="Filter by this requirement"
tooltip-placement="bottom" ng-click="addDetailFilter('pci', item)">
<span class="wz-text-link" tooltip="Filter by this requirement" tooltip-placement="bottom"
ng-click="addDetailFilter('pci', item)">
{{item}}
</span>
</dd>
@ -123,8 +116,34 @@
<dl class="euiDescriptionList euiDescriptionList--row">
<dt class="euiDescriptionList__title">GDPR</dt>
<dd class="euiDescriptionList__description" ng-repeat="item in currentRule.gdpr">
<span class="wz-text-link" tooltip="Filter by this requirement"
tooltip-placement="bottom" ng-click="addDetailFilter('gdpr', item)">
<span class="wz-text-link" tooltip="Filter by this requirement" tooltip-placement="bottom"
ng-click="addDetailFilter('gdpr', item)">
{{item}}
</span>
</dd>
</dl>
</div>
</div>
<div layout="row" class="wz-margin-top-10" ng-if="currentRule.hipaa.length">
<div class="euiFlexItem">
<dl class="euiDescriptionList euiDescriptionList--row">
<dt class="euiDescriptionList__title">HIPAA</dt>
<dd class="euiDescriptionList__description" ng-repeat="item in currentRule.hipaa">
<span class="wz-text-link" tooltip="Filter by this requirement" tooltip-placement="bottom"
ng-click="addDetailFilter('hipaa', item)">
{{item}}
</span>
</dd>
</dl>
</div>
</div>
<div layout="row" class="wz-margin-top-10" ng-if="currentRule['nist-800-53'].length">
<div class="euiFlexItem">
<dl class="euiDescriptionList euiDescriptionList--row">
<dt class="euiDescriptionList__title">NIST-800-53</dt>
<dd class="euiDescriptionList__description" ng-repeat="item in currentRule['nist-800-53']">
<span class="wz-text-link" tooltip="Filter by this requirement" tooltip-placement="bottom"
ng-click="addDetailFilter('nist-800-53', item)">
{{item}}
</span>
</dd>
@ -145,9 +164,8 @@
<div layout="row" ng-if="currentRule">
<md-card flex class="wz-md-card _md flex md-margin-h">
<md-card-content>
<wz-table custom-columns="true" flex path="'/rules'"
implicit-filter="[{ name:'file',value: currentRule.file}]"
keys="[{value: 'id', width: '75px'},{value:'file',size:2},{value:'description',size:2},{value:'groups',nosortable:true,size:2},{value:'pci',nosortable:true,size:2},{value:'gdpr',nosortable:true},'level']"
<wz-table custom-columns="true" flex path="'/rules'" implicit-filter="[{ name:'file',value: currentRule.file}]"
keys="[{value: 'id', width: '75px'},{value:'file',size:2},{value:'description',size:2},{value:'groups',nosortable:true,size:2},{value:'pci',nosortable:true,size:2},{value:'gdpr',nosortable:true},{value:'hipaa',nosortable:true},{value:'nist-800-53',nosortable:true},'level']"
allow-click="true">
</wz-table>
</md-card-content>
@ -164,22 +182,18 @@
<div layout="column" layout-align="start" ng-show="editingFile">
<div layout="row">
<span ng-click='closeEditingFile()' class='btn btn-info'>Close</span>
<button ng-disabled='xmlHasErrors || doingSaving' ng-click='doSaveConfig()'
class='btn wz-button pull-right wz-margin-left-8'>
<span ng-show='!xmlHasErrors'><i aria-hidden='true' class='fa fa-fw fa-save'
ng-class="doingSaving ? 'fa-spin fa-spinner' : ''"></i>Save
<button ng-disabled='xmlHasErrors || doingSaving' ng-click='doSaveConfig()' class='btn wz-button pull-right wz-margin-left-8'>
<span ng-show='!xmlHasErrors'><i aria-hidden='true' class='fa fa-fw fa-save' ng-class="doingSaving ? 'fa-spin fa-spinner' : ''"></i>Save
file</span>
<span ng-show='xmlHasErrors' class='btn-danger'><i aria-hidden='true'
class='fa fa-fw fa-exclamation-triangle'></i>
<span ng-show='xmlHasErrors' class='btn-danger'><i aria-hidden='true' class='fa fa-fw fa-exclamation-triangle'></i>
XML format error</span>
</button>
<button ng-show="restartBtn" class="btn wz-button" type="button" ng-disabled="doingSaving"
ng-click="restart(); toggleRestartMsg()">Restart
<button ng-show="restartBtn" class="btn wz-button" type="button" ng-disabled="doingSaving" ng-click="restart(); toggleRestartMsg()">Restart
now</button>
</div>
<div class="wz-padding-top-14" ng-if="fetchedXML">
<wz-xml-file-editor file-name='rules' data="fetchedXML" target-name="currentRule.file"
valid-fn='xmlIsValid(valid)' saving-param='toggleSaveConfig()' close-fn='closeEditingFile(reload)'>
<wz-xml-file-editor file-name='rules' data="fetchedXML" target-name="currentRule.file" valid-fn='xmlIsValid(valid)'
saving-param='toggleSaveConfig()' close-fn='closeEditingFile(reload)'>
</wz-xml-file-editor>
</div>
</div>

View File

@ -5,7 +5,7 @@
<input placeholder="Filter rules..." ng-model="custom_search" type="text" class="euiFieldSearch euiFieldSearch--fullWidth euiFlexItem height-35 ng-empty ng-pristine ng-touched ng-valid"
aria-invalid="false" wz-enter="search(custom_search)" id="search-input-rules">
<wz-add-filter-chip id-input="search-input-rules" options="[{label: 'File', value: 'file'}, {label: 'Path', value: 'path', hide: mctrl.showingLocalRules}, {label: 'Level', value: 'level'},
{label: 'Group', value: 'group'}, {label: 'PCI control', value: 'pci'}, {label: 'GDPR', value: 'gdpr'}]" />
{label: 'Group', value: 'group'}, {label: 'PCI control', value: 'pci'}, {label: 'GDPR', value: 'gdpr'}, {label: 'HIPAA', value: 'hipaa'}, {label: 'NIST-800-53', value: 'nist-800-53'}]" />
<div class="euiFormControlLayoutIcons wz-margin-left-16">
<span class="euiFormControlLayoutCustomIcon">
<react-component name="EuiIcon" props="{type:'search', className:'euiFormControlLayoutCustomIcon__icon'}" />
@ -51,6 +51,16 @@
<i class="fa fa-fw fa-times cursor-pointer" aria-hidden="true" ng-click="removeFilter('gdpr')"></i>
</span>
</md-chip>
<md-chip class="wz-chip" ng-show="includesFilter('hipaa')">
<span>HIPAA: {{getFilter('hipaa')}}
<i class="fa fa-fw fa-times cursor-pointer" aria-hidden="true" ng-click="removeFilter('hipaa')"></i>
</span>
</md-chip>
<md-chip class="wz-chip" ng-show="includesFilter('nist-800-53')">
<span>NIST-800-53: {{getFilter('nist-800-53')}}
<i class="fa fa-fw fa-times cursor-pointer" aria-hidden="true" ng-click="removeFilter('nist-800-53')"></i>
</span>
</md-chip>
</md-chips>
<div layout="row" ng-if="!editingFile" class="wz-margin-top-16">
@ -63,11 +73,11 @@
switch-text="Custom rules" switch-change="switchLocalRules()"></wz-kbn-switch>
</md-card-actions>
<md-card-content class="wz-padding-bottom-0">
<wz-table custom-columns="true" flex ng-if="mctrl.showingLocalRules" path="'/rules'" keys="[{value: 'id', width: '85px'},{value:'description', width: 'auto'},{value:'groups',nosortable:true, width: '250px'},{value:'pci',nosortable:true, width: '170px'},{value:'gdpr',nosortable:true,width: '170px'}, {value: 'level', width: '100px'}, {value:'file',width: '200px'}, {value:'path', width: 'auto'}]"
<wz-table custom-columns="true" flex ng-if="mctrl.showingLocalRules" path="'/rules'" keys="[{value: 'id', width: '85px'},{value:'description', width: 'auto'},{value:'groups',nosortable:true, width: '250px'},{value:'pci',nosortable:true, width: '170px'},{value:'gdpr',nosortable:true,width: '170px'}, {value:'hipaa',nosortable:true,width: '170px'}, {value:'nist-800-53',nosortable:true,width: '170px'}, {value: 'level', width: '100px'}, {value:'file',width: '200px'}, {value:'path', width: 'auto'}]"
implicit-filter="appliedFilters" allow-click="true" row-sizes="[16,14,12]">
</wz-table>
<wz-table custom-columns="true" ng-if="!mctrl.showingLocalRules" implicit-filter="appliedFilters" flex
path="'/rules'" keys="[{value: 'id', width: '85px'},{value:'description', width: 'auto'},{value:'groups',nosortable:true, width: '250px'},{value:'pci',nosortable:true, width: '170px'},{value:'gdpr',nosortable:true,width: '170px'}, {value: 'level', width: '100px'}, {value:'file',width: '200px'}, {value:'path', width: 'auto'}]"
path="'/rules'" keys="[{value: 'id', width: '85px'},{value:'description', width: 'auto'},{value:'groups',nosortable:true, width: '250px'},{value:'pci',nosortable:true, width: '170px'},{value:'gdpr',nosortable:true,width: '170px'}, {value:'hipaa',nosortable:true,width: '170px'}, {value:'nist-800-53',nosortable:true,width: '170px'}, {value: 'level', width: '100px'}, {value:'file',width: '200px'}, {value:'path', width: 'auto'}]"
allow-click="true" row-sizes="[16,14,12]">
</wz-table>
</md-card-content>

View File

@ -1,9 +1,4 @@
<div flex="auto" layout="column" ng-if="mctrl.globalRuleSet == 'ruleset'">
<div>
<!-- End group actions -->
<md-nav-bar class="wz-nav-bar nav-bar-white-bg " md-selected-nav-item="mctrl.globalRulesetTab">
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.setRulesTab('rules')" name="rules">Rules</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.setRulesTab('decoders')" name="decoders">Decoders</md-nav-item>
<md-nav-item class="wz-nav-item" md-nav-click="mctrl.setRulesTab('cdblists')" name="cdblists">Lists</md-nav-item>
</md-nav-bar>
</div>
<div class="md-padding-h">
<react-component name="Tabs" props="mctrl.rulesetTabsProps" />
</div>

View File

@ -0,0 +1,107 @@
<md-content flex layout="column" ng-if="octrl.tab === 'hipaa' && octrl.tabView === 'panels'" ng-class="{'no-opacity': resultState !== 'ready' || !rendered}"
layout-align="start">
<div layout="row" layout-align="center stretch">
<md-card flex class="wz-md-card">
<md-tabs md-selected="selectedPciIndex" class="wz-md-tab" md-border-bottom md-dynamic-height id="hipaaReq_tab">
<md-tab ng-repeat="tab in octrl.hipaaTabs" ng-disabled="tab.disabled" label="{{tab.title}}">
<div class="md-padding">
<span class="wz-headline-title">HIPAA Requirement: {{tab.title}}</span>
<md-divider class="wz-margin-top-10"></md-divider>
<div layout="row" class="wz-padding-top-10 wz-line-height">
<div ng-bind-html="tab.content"></div>
</div>
</div>
</md-tab>
</md-tabs>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-400">
<md-card flex="70" class="wz-md-card" ng-class="{'fullscreen': octrl.expandArray[0]}">
<md-card-actions layout="row" class="wz-card-actions-vis" ng-dblclick="octrl.expand(0)">
<span class="wz-headline-title">HIPAA requirements</span>
<span flex></span>
<span class="cursor-pointer" ng-click="octrl.expand(0)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Overview-HIPAA-requirements" vis-id="'Wazuh-App-Overview-HIPAA-requirements'"></kbn-vis>
</md-card-content>
</md-card>
<md-card flex="30" class="wz-md-card" ng-class="{'fullscreen': octrl.expandArray[1]}">
<md-card-actions layout="row" class="wz-card-actions-vis" ng-dblclick="octrl.expand(1)">
<span class="wz-headline-title">Top 10 agents by alerts number</span>
<span flex></span>
<span class="cursor-pointer" ng-click="octrl.expand(1)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Overview-HIPAA-Agents" vis-id="'Wazuh-App-Overview-HIPAA-Agents'"></kbn-vis>
</md-card-content>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-300">
<md-card flex class="wz-md-card" ng-class="{'fullscreen': octrl.expandArray[2]}">
<md-card-actions layout="row" class="wz-card-actions-vis" ng-dblclick="octrl.expand(2)">
<span class="wz-headline-title">Top requirements over time</span>
<span flex></span>
<span class="cursor-pointer" ng-click="octrl.expand(2)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Overview-HIPAA-Requirements-over-time" vis-id="'Wazuh-App-Overview-HIPAA-Requirements-over-time'"></kbn-vis>
</md-card-content>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-530">
<md-card flex class="wz-md-card" ng-class="{'fullscreen': octrl.expandArray[3]}">
<md-card-actions layout="row" class="wz-card-actions-vis" ng-dblclick="octrl.expand(3)">
<span class="wz-headline-title">Last alerts</span>
<span flex></span>
<span class="cursor-pointer" ng-click="octrl.expand(3)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Overview-HIPAA-Requirements-Agents-heatmap" vis-id="'Wazuh-App-Overview-HIPAA-Requirements-Agents-heatmap'">
</kbn-vis>
</md-card-content>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-255">
<md-card flex class="wz-md-card" ng-class="{'fullscreen': octrl.expandArray[4]}">
<md-card-actions layout="row" class="wz-card-actions-vis" ng-dblclick="octrl.expand(4)">
<span class="wz-headline-title">Requirements by agent</span>
<span flex></span>
<span class="cursor-pointer" ng-click="octrl.expand(4)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Overview-HIPAA-Requirements-by-agent" vis-id="'Wazuh-App-Overview-HIPAA-Requirements-by-agent'"></kbn-vis>
</md-card-content>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-570">
<md-card flex class="wz-md-card" ng-class="{'fullscreen': octrl.expandArray[5]}">
<md-card-actions layout="row" class="wz-card-actions-vis" ng-dblclick="octrl.expand(5)">
<span class="wz-headline-title">Alerts summary</span>
<span flex></span>
<span class="cursor-pointer" ng-click="octrl.expand(5)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis vis-id="'Wazuh-App-Overview-HIPAA-Alerts-summary'"></kbn-vis>
</md-card-content>
</md-card>
</div>
</md-content>

View File

@ -0,0 +1,107 @@
<md-content flex layout="column" ng-if="octrl.tab === 'nist' && octrl.tabView === 'panels'" ng-class="{'no-opacity': resultState !== 'ready' || !rendered}"
layout-align="start">
<div layout="row" layout-align="center stretch">
<md-card flex class="wz-md-card">
<md-tabs md-selected="selectedPciIndex" class="wz-md-tab" md-border-bottom md-dynamic-height id="nistReq_tab">
<md-tab ng-repeat="tab in octrl.nistTabs" ng-disabled="tab.disabled" label="{{tab.title}}">
<div class="md-padding">
<span class="wz-headline-title">NIST 800-53 Requirement: {{tab.title}}</span>
<md-divider class="wz-margin-top-10"></md-divider>
<div layout="row" class="wz-padding-top-10 wz-line-height">
<div ng-bind-html="tab.content"></div>
</div>
</div>
</md-tab>
</md-tabs>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-400">
<md-card flex="70" class="wz-md-card" ng-class="{'fullscreen': octrl.expandArray[0]}">
<md-card-actions layout="row" class="wz-card-actions-vis" ng-dblclick="octrl.expand(0)">
<span class="wz-headline-title">NIST 800-53 requirements</span>
<span flex></span>
<span class="cursor-pointer" ng-click="octrl.expand(0)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Overview-NIST-requirements" vis-id="'Wazuh-App-Overview-NIST-requirements'"></kbn-vis>
</md-card-content>
</md-card>
<md-card flex="30" class="wz-md-card" ng-class="{'fullscreen': octrl.expandArray[1]}">
<md-card-actions layout="row" class="wz-card-actions-vis" ng-dblclick="octrl.expand(1)">
<span class="wz-headline-title">Top 10 agents by alerts number</span>
<span flex></span>
<span class="cursor-pointer" ng-click="octrl.expand(1)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Overview-NIST-Agents" vis-id="'Wazuh-App-Overview-NIST-Agents'"></kbn-vis>
</md-card-content>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-300">
<md-card flex class="wz-md-card" ng-class="{'fullscreen': octrl.expandArray[2]}">
<md-card-actions layout="row" class="wz-card-actions-vis" ng-dblclick="octrl.expand(2)">
<span class="wz-headline-title">Top requirements over time</span>
<span flex></span>
<span class="cursor-pointer" ng-click="octrl.expand(2)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Overview-NIST-Requirements-over-time" vis-id="'Wazuh-App-Overview-NIST-Requirements-over-time'"></kbn-vis>
</md-card-content>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-530">
<md-card flex class="wz-md-card" ng-class="{'fullscreen': octrl.expandArray[3]}">
<md-card-actions layout="row" class="wz-card-actions-vis" ng-dblclick="octrl.expand(3)">
<span class="wz-headline-title">Last alerts</span>
<span flex></span>
<span class="cursor-pointer" ng-click="octrl.expand(3)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Overview-NIST-Requirements-Agents-heatmap" vis-id="'Wazuh-App-Overview-NIST-Requirements-Agents-heatmap'">
</kbn-vis>
</md-card-content>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-255">
<md-card flex class="wz-md-card" ng-class="{'fullscreen': octrl.expandArray[4]}">
<md-card-actions layout="row" class="wz-card-actions-vis" ng-dblclick="octrl.expand(4)">
<span class="wz-headline-title">Requirements by agent</span>
<span flex></span>
<span class="cursor-pointer" ng-click="octrl.expand(4)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis id="Wazuh-App-Overview-NIST-Requirements-by-agent" vis-id="'Wazuh-App-Overview-NIST-Requirements-by-agent'"></kbn-vis>
</md-card-content>
</md-card>
</div>
<div layout="row" layout-align="center stretch" class="height-570">
<md-card flex class="wz-md-card" ng-class="{'fullscreen': octrl.expandArray[5]}">
<md-card-actions layout="row" class="wz-card-actions-vis" ng-dblclick="octrl.expand(5)">
<span class="wz-headline-title">Alerts summary</span>
<span flex></span>
<span class="cursor-pointer" ng-click="octrl.expand(5)">
<react-component name="EuiIcon" props="{type:'expand'}" />
</span>
</md-card-actions>
<md-card-content class="wazuh-column">
<kbn-vis vis-id="'Wazuh-App-Overview-NIST-Alerts-summary'"></kbn-vis>
</md-card-content>
</md-card>
</div>
</md-content>

View File

@ -1,4 +1,4 @@
<div class="" layout="column" layout-align="start stretch" ng-if="octrl.tab === 'welcome'">
<div layout="column" layout-align="start stretch" ng-if="octrl.tab === 'welcome'">
<div layout="row" layout-padding>
<react-component name="StatsOverview" flex props="{

View File

@ -97,13 +97,17 @@
<!-- End Security navigation bar -->
<!-- Compliance navigation bar -->
<md-nav-bar ng-if="octrl.inArray(octrl.tab, octrl.complianceTabs) && octrl.extensions.pci && octrl.extensions.gdpr"
<md-nav-bar ng-if="octrl.inArray(octrl.tab, octrl.complianceTabs) && (octrl.extensions.pci || octrl.extensions.gdpr || octrl.extensions.hipaa || octrl.extensions.nist)"
class="wz-nav-bar" ng-show="octrl.tab !== 'welcome'" md-selected-nav-item="octrl.tab"
nav-bar-aria-label="Compliance navigation links">
<md-nav-item ng-show="octrl.extensions.pci" class="wz-nav-item" md-nav-click="octrl.switchTab('pci',true)"
name="pci">{{ octrl.tabNames['pci'] }}</md-nav-item>
<md-nav-item ng-show="octrl.extensions.gdpr" class="wz-nav-item" md-nav-click="octrl.switchTab('gdpr',true)"
name="gdpr">{{ octrl.tabNames['gdpr'] }}</md-nav-item>
<md-nav-item ng-show="octrl.extensions.gdpr" class="wz-nav-item" md-nav-click="octrl.switchTab('hipaa',true)"
name="hipaa">{{ octrl.tabNames['hipaa'] }}</md-nav-item>
<md-nav-item ng-show="octrl.extensions.gdpr" class="wz-nav-item" md-nav-click="octrl.switchTab('nist',true)"
name="nist">{{ octrl.tabNames['nist'] }}</md-nav-item>
</md-nav-bar>
<!-- End Compliance navigation bar -->

View File

@ -9,6 +9,8 @@ include ./overview-audit.html
include ./overview-ciscat.html
include ./overview-pci.html
include ./overview-gdpr.html
include ./overview-hipaa.html
include ./overview-nist.html
include ./overview-aws.html
include ./overview-virustotal.html
include ./overview-osquery.html

View File

@ -4,6 +4,7 @@
import './codemirror.css';
import './foldgutter.css';
import './ttcn.css';
import './lesser-dark.css';
import './javascript.js';
import './xml.js';
import './formatting.js';

View File

@ -0,0 +1,131 @@
/*
http://lesscss.org/ dark theme
Ported to CodeMirror by Peter Kroon
*/
.cm-s-lesser-dark {
line-height: 1.3em;
}
.cm-s-lesser-dark.CodeMirror {
background: #25262E;
color: #ebefe7;
text-shadow: 0 -1px 1px #262626;
}
.cm-s-lesser-dark div.CodeMirror-selected {
background: #002835;
} /* 33322B*/
.cm-s-lesser-dark .CodeMirror-line::selection,
.cm-s-lesser-dark .CodeMirror-line > span::selection,
.cm-s-lesser-dark .CodeMirror-line > span > span::selection {
background: #002835;
}
.cm-s-lesser-dark .CodeMirror-line::-moz-selection,
.cm-s-lesser-dark .CodeMirror-line > span::-moz-selection,
.cm-s-lesser-dark .CodeMirror-line > span > span::-moz-selection {
background: #002835;
}
.cm-s-lesser-dark .CodeMirror-cursor {
border-left: 1px solid white;
}
.cm-s-lesser-dark pre {
padding: 0 8px;
} /*editable code holder*/
.cm-s-lesser-dark.CodeMirror span.CodeMirror-matchingbracket {
color: #7efc7e;
} /*65FC65*/
.cm-s-lesser-dark .CodeMirror-gutters {
background: #1D1E24;
border-right: 1px solid #343741;
}
.cm-s-lesser-dark .CodeMirror-guttermarker {
color: #599eff;
}
.cm-s-lesser-dark .CodeMirror-guttermarker-subtle {
color: #777;
}
.cm-s-lesser-dark .CodeMirror-linenumber {
color: #777;
}
.cm-s-lesser-dark span.cm-header {
color: #a0a;
}
.cm-s-lesser-dark span.cm-quote {
color: #090;
}
.cm-s-lesser-dark span.cm-keyword {
color: #599eff;
}
.cm-s-lesser-dark span.cm-atom {
color: #c2b470;
}
.cm-s-lesser-dark span.cm-number {
color: #66c27d;
}
.cm-s-lesser-dark span.cm-def {
color: #c8dad9;
}
.cm-s-lesser-dark span.cm-variable {
color: #4dc0ba;
}
.cm-s-lesser-dark span.cm-variable:first-child {
color: #f094c1;
}
.cm-s-lesser-dark span.cm-variable-2 {
color: #669199;
}
.cm-s-lesser-dark span.cm-variable-3,
.cm-s-lesser-dark span.cm-type {
color: #c8dad9;
}
.cm-s-lesser-dark span.cm-property {
color: #92a75c;
}
.cm-s-lesser-dark span.cm-operator {
color: #92a75c;
}
.cm-s-lesser-dark span.cm-comment {
color: #666;
}
.cm-s-lesser-dark span.cm-string {
color: #7cbad1;
}
.cm-s-lesser-dark span.cm-string-2 {
color: #f50;
}
.cm-s-lesser-dark span.cm-meta {
color: #738c73;
}
.cm-s-lesser-dark span.cm-qualifier {
color: #555;
}
.cm-s-lesser-dark span.cm-builtin {
color: #ff9e59;
}
.cm-s-lesser-dark span.cm-bracket {
color: #ebefe7;
}
.cm-s-lesser-dark span.cm-tag {
color: #669199;
}
.cm-s-lesser-dark span.cm-attribute {
color: #81a4d5;
}
.cm-s-lesser-dark span.cm-hr {
color: #999;
}
.cm-s-lesser-dark span.cm-link {
color: #7070e6;
}
.cm-s-lesser-dark span.cm-error {
color: #95b8a6;
}
.cm-s-lesser-dark .CodeMirror-activeline-background {
background: #3c3a3a;
}
.cm-s-lesser-dark .CodeMirror-matchingbracket {
outline: 1px solid grey;
color: #c8dad9 !important;
}

View File

@ -0,0 +1,18 @@
/*
* Wazuh app - Components compatibility operative system
* Copyright (C) 2015-2019 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
export const UnsupportedComponents = {
linux: [],
windows: ['audit', 'oscap', 'vuls', 'docker'],
darwin: ['audit', 'oscap', 'vuls', 'docker'],
other: ['audit', 'oscap', 'vuls', 'docker']
};

View File

@ -26,10 +26,6 @@ export const configEquivalences = {
'wazuh.shards': 'Define the number of shards to use for the .wazuh index.',
'wazuh.replicas':
'Define the number of replicas to use for the .wazuh index.',
'wazuh-version.shards':
'Define the number of shards to use for the .wazuh-version index.',
'wazuh-version.replicas':
'Define the number of replicas to use for the .wazuh-version index.',
'ip.selector':
'Defines if the user is allowed to change the selected index pattern directly from the top menu bar.',
'ip.ignore':

View File

@ -140,4 +140,28 @@ export class FilterHandler {
delete result.query;
return result;
}
hipaaQuery() {
const result = this.base();
result.meta.type = 'exists';
result.meta.value = 'exists';
result.meta.key = 'rule.hipaa';
result.exists = {
field: 'rule.hipaa'
};
delete result.query;
return result;
}
nistQuery() {
const result = this.base();
result.meta.type = 'exists';
result.meta.value = 'exists';
result.meta.key = 'rule.nist_800_53';
result.exists = {
field: 'rule.nist_800_53'
};
delete result.query;
return result;
}
}

View File

@ -21,6 +21,8 @@ export const TabNames = {
ciscat: 'CIS-CAT',
pci: 'PCI DSS',
gdpr: 'GDPR',
hipaa: 'HIPAA',
nist: 'NIST 800-53',
aws: 'Amazon AWS',
virustotal: 'VirusTotal',
configuration: 'Configuration',

View File

@ -14,6 +14,8 @@
import needle from 'needle';
import { pciRequirementsFile } from '../integration-files/pci-requirements';
import { gdprRequirementsFile } from '../integration-files/gdpr-requirements';
import { hipaaRequirementsFile } from '../integration-files/hipaa-requirements';
import { nistRequirementsFile } from '../integration-files/nist-requirements';
import { ElasticWrapper } from '../lib/elastic-wrapper';
import { getPath } from '../../util/get-path';
import { Monitoring } from '../monitoring';
@ -28,6 +30,8 @@ import { apiRequestList } from '../../util/api-request-list';
import * as ApiHelper from '../lib/api-helper';
import { Queue } from '../jobs/queue';
import querystring from 'querystring';
import fs from 'fs';
import path from 'path';
export class WazuhApiCtrl {
/**
* Constructor
@ -37,6 +41,7 @@ export class WazuhApiCtrl {
this.queue = Queue;
this.wzWrapper = new ElasticWrapper(server);
this.monitoringInstance = new Monitoring(server, true);
this.wazuhVersion = path.join(__dirname, '../wazuh-version.json');
}
/**
@ -540,6 +545,170 @@ export class WazuhApiCtrl {
return isDown;
}
/**
* This get PCI requirements
* @param {Object} req
* @param {Object} reply
* @returns {Array<Object>} requirements or ErrorResponse
*/
async getHipaaRequirement(req, reply) {
try {
let hipaa_description = '';
if (req.params.requirement === 'all') {
if (!req.headers.id) {
return hipaaRequirementsFile;
}
let api = await this.wzWrapper.getWazuhConfigurationById(
req.headers.id
);
if (api.error_code > 1) {
log(
'wazuh-api:getHipaaRequirement',
'Elasticsearch unexpected error or cannot connect'
);
// Can not connect to elasticsearch
return ErrorResponse(
'Elasticsearch unexpected error or cannot connect',
3007,
400,
reply
);
} else if (api.error_code > 0) {
log('wazuh-api:getHipaaRequirement', 'Credentials do not exist');
// Credentials not found
return ErrorResponse('Credentials do not exist', 3008, 400, reply);
}
const response = await needle(
'get',
`${api.url}:${api.port}/rules/hipaa`,
{},
ApiHelper.buildOptionsObject(api)
);
if ((((response || {}).body || {}).data || {}).items) {
let HIPAAobject = {};
for (const item of response.body.data.items) {
if (typeof hipaaRequirementsFile[item] !== 'undefined')
HIPAAobject[item] = hipaaRequirementsFile[item];
}
return HIPAAobject;
} else {
log(
'wazuh-api:getPciRequirement',
'An error occurred trying to parse HIPAA requirements'
);
return ErrorResponse(
'An error occurred trying to parse HIPAA requirements',
3009,
400,
reply
);
}
} else {
if (
typeof hipaaRequirementsFile[req.params.requirement] !== 'undefined'
) {
hipaa_description = hipaaRequirementsFile[req.params.requirement];
}
return {
hipaa: {
requirement: req.params.requirement,
description: hipaa_description
}
};
}
} catch (error) {
log('wazuh-api:getPciRequirement', error.message || error);
return ErrorResponse(error.message || error, 3010, 400, reply);
}
}
/**
* This get NIST 800-53 requirements
* @param {Object} req
* @param {Object} reply
* @returns {Array<Object>} requirements or ErrorResponse
*/
async getNistRequirement(req, reply) {
try {
let nist_description = '';
if (req.params.requirement === 'all') {
if (!req.headers.id) {
return nistRequirementsFile;
}
let api = await this.wzWrapper.getWazuhConfigurationById(
req.headers.id
);
if (api.error_code > 1) {
log(
'wazuh-api:getNistRequirement',
'Elasticsearch unexpected error or cannot connect'
);
// Can not connect to elasticsearch
return ErrorResponse(
'Elasticsearch unexpected error or cannot connect',
3007,
400,
reply
);
} else if (api.error_code > 0) {
log('wazuh-api:getNistRequirement', 'Credentials do not exist');
// Credentials not found
return ErrorResponse('Credentials do not exist', 3008, 400, reply);
}
const response = await needle(
'get',
`${api.url}:${api.port}/rules/nist-800-53`,
{},
ApiHelper.buildOptionsObject(api)
);
if ((((response || {}).body || {}).data || {}).items) {
let NISTobject = {};
for (const item of response.body.data.items) {
if (typeof nistRequirementsFile[item] !== 'undefined')
NISTobject[item] = nistRequirementsFile[item];
}
return NISTobject;
} else {
log(
'wazuh-api:getNistRequirement',
'An error occurred trying to parse NIST 800-53 requirements'
);
return ErrorResponse(
'An error occurred trying to parse NIST 800-53 requirements',
3009,
400,
reply
);
}
} else {
if (
typeof nistRequirementsFile[req.params.requirement] !== 'undefined'
) {
nist_description = nistRequirementsFile[req.params.requirement];
}
return {
nist: {
requirement: req.params.requirement,
description: nist_description
}
};
}
} catch (error) {
log('wazuh-api:getNistRequirement', error.message || error);
return ErrorResponse(error.message || error, 3010, 400, reply);
}
}
/**
* Check main Wazuh daemons status
* @param {*} api API entry stored in .wazuh
@ -1143,6 +1312,63 @@ export class WazuhApiCtrl {
return apiRequestList;
}
/**
* This get the timestamp field
* @param {Object} req
* @param {Object} reply
* @returns {Object} timestamp field or ErrorResponse
*/
async getTimeStamp(req, reply) {
try {
const source = JSON.parse(fs.readFileSync(this.wazuhVersion, 'utf8'));
if (source.installationDate && source.lastRestart) {
log(
'wazuh-api:getTimeStamp',
`Installation date: ${source.installationDate}. Last restart: ${source.lastRestart}`,
'debug'
);
return {
installationDate: source.installationDate,
lastRestart: source.lastRestart
};
} else {
throw new Error('Could not fetch wazuh-version registry');
}
} catch (error) {
log('wazuh-api:getTimeStamp', error.message || error);
return ErrorResponse(
error.message || 'Could not fetch wazuh-version registry',
4001,
500,
reply
);
}
}
/**
* This get the wazuh setup settings
* @param {Object} req
* @param {Object} reply
* @returns {Object} setup info or ErrorResponse
*/
async getSetupInfo(req, reply) {
try {
const source = JSON.parse(fs.readFileSync(this.wazuhVersion, 'utf8'));
return !Object.values(source).length
? { statusCode: 200, data: '' }
: { statusCode: 200, data: source };
} catch (error) {
log('wazuh-api:getSetupInfo', error.message || error);
return ErrorResponse(
`Could not get data from wazuh-version registry due to ${error.message ||
error}`,
4005,
500,
reply
);
}
}
/**
* Get basic syscollector information for given agent.
* @param {Object} req

View File

@ -21,6 +21,7 @@ import {
import { Base } from '../reporting/base-query';
import { checkKnownFields } from '../lib/refresh-known-fields';
export class WazuhElasticCtrl {
/**
* Constructor
@ -31,42 +32,6 @@ export class WazuhElasticCtrl {
this.wzWrapper = new ElasticWrapper(server);
}
/**
* This get the timestamp field
* @param {Object} req
* @param {Object} reply
* @returns {Object} timestamp field or ErrorResponse
*/
async getTimeStamp(req, reply) {
try {
const data = await this.wzWrapper.getWazuhVersionIndexAsSearch();
const source =
((((data || {}).hits || {}).hits || [])[0] || {})._source || {};
if (source.installationDate && source.lastRestart) {
log(
'wazuh-elastic:getTimeStamp',
`Installation date: ${data.hits.hits[0]._source.installationDate}. Last restart: ${data.hits.hits[0]._source.lastRestart}`,
'debug'
);
return {
installationDate: data.hits.hits[0]._source.installationDate,
lastRestart: data.hits.hits[0]._source.lastRestart
};
} else {
throw new Error('Could not fetch .wazuh-version index');
}
} catch (error) {
log('wazuh-elastic:getTimeStamp', error.message || error);
return ErrorResponse(
error.message || 'Could not fetch .wazuh-version index',
4001,
500,
reply
);
}
}
/**
* This retrieve a template from Elasticsearch
* @param {Object} req
@ -238,8 +203,12 @@ export class WazuhElasticCtrl {
payload.aggs['2'].terms.field = req.params.field;
payload.pattern = req.params.pattern;
const data = await this.wzWrapper.searchWazuhAlertsWithPayload(payload);
const spaces = this._server.plugins.spaces;
const namespace = spaces && spaces.getSpaceId(req);
const data = await this.wzWrapper.searchWazuhAlertsWithPayload(
payload,
namespace
);
return data.hits.total.value === 0 ||
typeof data.aggregations['2'].buckets[0] === 'undefined'
@ -343,6 +312,9 @@ export class WazuhElasticCtrl {
*/
async getlist(req, reply) {
try {
const spaces = this._server.plugins.spaces;
const namespace = spaces && spaces.getSpaceId(req);
const config = getConfiguration();
const usingCredentials = await this.wzWrapper.usingCredentials();
@ -360,9 +332,14 @@ export class WazuhElasticCtrl {
req.auth.credentials.roles.includes('superuser');
const data = await this.wzWrapper.getAllIndexPatterns();
if ((((data || {}).hits || {}).hits || []).length === 0)
throw new Error('There is no index pattern');
if (namespace && namespace !== 'default') {
data.hits.hits = data.hits.hits.filter(item =>
(item._id || '').includes(namespace)
);
}
if ((((data || {}).hits || {}).hits || []).length === 0) {
throw new Error('There are no index patterns');
}
if (((data || {}).hits || {}).hits) {
let list = this.validateIndexPattern(data.hits.hits);
@ -395,15 +372,36 @@ export class WazuhElasticCtrl {
}
}
async checkCustomSpaceMonitoring(namespace, monitoringPattern) {
try {
const patterns = await this.wzWrapper.getAllIndexPatterns();
const exists = patterns.hits.hits.filter(
item =>
item._source['index-pattern'].title === monitoringPattern &&
item._source.namespace === namespace
);
if (!exists.length) {
const title = monitoringPattern;
const id = `${namespace}:index-pattern:${monitoringPattern}`;
await this.wzWrapper.createMonitoringIndexPattern(title, id, namespace);
return id;
} else {
return exists[0]._id;
}
} catch (error) {
return Promise.reject(error);
}
}
/**
* Replaces visualizations main fields to fit a certain pattern.
* @param {Array<Object>} app_objects Object containing raw visualizations.
* @param {String} id Index-pattern id to use in the visualizations. Eg: 'wazuh-alerts'
*/
buildVisualizationsRaw(app_objects, id) {
async buildVisualizationsRaw(app_objects, id, namespace = false) {
try {
const config = getConfiguration();
const monitoringPattern =
let monitoringPattern =
(config || {})['wazuh.monitoring.pattern'] || 'wazuh-monitoring-3.x-*';
log(
'wazuh-elastic:buildVisualizationsRaw',
@ -429,17 +427,35 @@ export class WazuhElasticCtrl {
) {
const defaultStr = aux_source.kibanaSavedObjectMeta.searchSourceJSON;
defaultStr.includes('wazuh-monitoring')
? (aux_source.kibanaSavedObjectMeta.searchSourceJSON = defaultStr.replace(
/wazuh-monitoring/g,
monitoringPattern[monitoringPattern.length - 1] === '*'
? monitoringPattern
: monitoringPattern + '*'
))
: (aux_source.kibanaSavedObjectMeta.searchSourceJSON = defaultStr.replace(
/wazuh-alerts/g,
id
));
const isMonitoring = defaultStr.includes('wazuh-monitoring');
if (isMonitoring) {
if (namespace && namespace !== 'default') {
monitoringPattern = await this.checkCustomSpaceMonitoring(
namespace,
monitoringPattern
);
if (
monitoringPattern.includes(namespace) &&
monitoringPattern.includes('index-pattern:')
) {
monitoringPattern = monitoringPattern.split(
'index-pattern:'
)[1];
}
}
aux_source.kibanaSavedObjectMeta.searchSourceJSON = defaultStr.replace(
/wazuh-monitoring/g,
monitoringPattern[monitoringPattern.length - 1] === '*' ||
(namespace && namespace !== 'default')
? monitoringPattern
: monitoringPattern + '*'
);
} else {
aux_source.kibanaSavedObjectMeta.searchSourceJSON = defaultStr.replace(
/wazuh-alerts/g,
id
);
}
}
// Replace index-pattern for selector visualizations
@ -569,8 +585,13 @@ export class WazuhElasticCtrl {
`Index pattern: ${req.params.pattern}`,
'debug'
);
const raw = await this.buildVisualizationsRaw(file, req.params.pattern);
const spaces = this._server.plugins.spaces;
const namespace = spaces && spaces.getSpaceId(req);
const raw = await this.buildVisualizationsRaw(
file,
req.params.pattern,
namespace
);
return { acknowledge: true, raw: raw };
} catch (error) {
log('wazuh-elastic:createVis', error.message || error);
@ -601,20 +622,25 @@ export class WazuhElasticCtrl {
const file = ClusterVisualizations['monitoring'];
const nodes = req.payload.nodes.items;
const name = req.payload.nodes.name;
const master_node = req.payload.nodes.master_node;
const masterNode = req.payload.nodes.master_node;
const pattern_doc = await this.wzWrapper.getIndexPatternUsingGet(
req.params.pattern
const spaces = this._server.plugins.spaces;
const namespace = spaces && spaces.getSpaceId(req);
const patternDoc = await this.wzWrapper.getIndexPatternUsingGet(
req.params.pattern,
namespace
);
const pattern_name = pattern_doc._source['index-pattern'].title;
const patternName = patternDoc._source['index-pattern'].title;
const raw = await this.buildClusterVisualizationsRaw(
file,
req.params.pattern,
nodes,
name,
master_node,
pattern_name
masterNode,
patternName
);
return { acknowledge: true, raw: raw };

View File

@ -30,6 +30,8 @@ import { WazuhApiCtrl } from './wazuh-api';
import clockIconRaw from '../reporting/clock-icon-raw';
import filterIconRaw from '../reporting/filter-icon-raw';
import ProcessEquivalence from '../../util/process-state-equivalence';
import { KeyEquivalence } from '../../util/csv-key-equivalence';
import { AgentConfiguration } from '../reporting/agent-configuration';
import {
AgentsVisualizations,
@ -236,6 +238,97 @@ export class WazuhReportingCtrl {
}
}
/**
* This performs the rendering of given tables
* @param {Array<Object>} tables tables to render
*/
renderConfigTables(tables) {
for (const table of tables) {
let rowsparsed = table.rows;
if (Array.isArray(rowsparsed) && rowsparsed.length) {
const rows =
rowsparsed.length > 100 ? rowsparsed.slice(0, 99) : rowsparsed;
this.dd.content.push({
text: table.title,
style: { fontSize: 11, color: '#000' },
margin: table.title && table.type === 'table' ? [0, 0, 0, 5] : ''
});
if (table.title === 'Monitored directories') {
this.dd.content.push({
text:
'RT: Real time | WD: Who-data | Per.: Permission | MT: Modification time | SL: Symbolic link | RL: Recursion level',
style: { fontSize: 8, color: '#78C8DE' },
margin: [0, 0, 0, 5]
});
}
const full_body = [];
const modifiedRows = [];
for (const row of rows) {
modifiedRows.push(
row.map(cell => ({ text: cell, style: 'standard' }))
);
}
let widths = [];
widths = Array(table.columns.length - 1).fill('auto');
widths.push('*');
if (table.type === 'config') {
full_body.push(
table.columns.map(col => ({
text: col,
border: [0, 0, 0, 20],
fontSize: 0,
colSpan: 2
})),
...modifiedRows
);
this.dd.content.push({
fontSize: 8,
table: {
headerRows: 0,
widths,
body: full_body,
dontBreakRows: true
},
layout: {
fillColor: i => (i === 0 ? '#fff' : null),
hLineColor: () => '#D3DAE6',
hLineWidth: () => 1,
vLineWidth: () => 0
}
});
} else if (table.type === 'table') {
full_body.push(
table.columns.map(col => ({
text: col,
style: 'whiteColor',
border: [0, 0, 0, 0]
})),
...modifiedRows
);
this.dd.content.push({
fontSize: 8,
table: {
headerRows: 1,
widths,
body: full_body
},
layout: {
fillColor: i => (i === 0 ? '#78C8DE' : null),
hLineColor: () => '#78C8DE',
hLineWidth: () => 1,
vLineWidth: () => 0
}
});
}
this.dd.content.push('\n');
}
}
}
/**
* Format Date to string YYYY-mm-ddTHH:mm:ss
* @param {*} date JavaScript Date
@ -362,13 +455,34 @@ export class WazuhReportingCtrl {
async renderHeader(section, tab, isAgents, apiId) {
try {
if (section && typeof section === 'string') {
this.dd.content.push({
text: descriptions[tab].title + ' report',
style: 'h1'
});
if (section !== 'agentConfig' && section !== 'groupConfig') {
this.dd.content.push({
text: descriptions[tab].title + ' report',
style: 'h1'
});
} else if (section === 'agentConfig') {
this.dd.content.push({
text: `Agent ${isAgents} configuration`,
style: 'h1'
});
} else if (section === 'groupConfig') {
this.dd.content.push({
text: `Agents in group`,
style: { fontSize: 14, color: '#000' },
margin: [0, 20, 0, 0]
});
}
this.dd.content.push('\n');
}
if (isAgents && typeof isAgents === 'object') {
await this.buildAgentsTable(
isAgents,
apiId,
section === 'groupConfig' ? tab : false
);
}
if (isAgents && typeof isAgents === 'string') {
const agent = await this.apiRequest.makeGenericRequest(
'GET',
@ -388,35 +502,23 @@ export class WazuhReportingCtrl {
}
await this.buildAgentsTable([isAgents], apiId);
let dateAddStr = '';
if (((agent || {}).data || {}).dateAdd) {
dateAddStr = `Registration date: ${agent.data.dateAdd}.`;
}
let dateLastKeepAlive = '';
if (((agent || {}).data || {}).lastKeepAlive) {
dateLastKeepAlive += `Last keep alive: ${agent.data.lastKeepAlive}.`;
}
if (dateAddStr.length) {
this.dd.content.push({ text: dateAddStr, style: 'standard' });
this.dd.content.push('\n');
}
if (dateLastKeepAlive.length) {
this.dd.content.push({ text: dateLastKeepAlive, style: 'standard' });
this.dd.content.push('\n');
}
if (((agent || {}).data || {}).group) {
let agGroups = '';
let index = 0;
for (let ag of agent.data.group) {
agGroups = agGroups.concat(ag);
if (index < agent.data.group.length - 1) {
agGroups = agGroups.concat(', ');
}
index++;
}
this.dd.content.push({
text: `Group: ${agent.data.group}`,
text: `Group${agent.data.group.length > 1 ? 's' : ''}: ${agGroups}`,
style: 'standard'
});
this.dd.content.push('\n');
}
}
if (descriptions[tab] && descriptions[tab].description) {
this.dd.content.push({
text: descriptions[tab].description,
@ -525,44 +627,79 @@ export class WazuhReportingCtrl {
* @param {Array<Strings>} ids ids of agents
* @param {String} apiId API id
*/
async buildAgentsTable(ids, apiId) {
async buildAgentsTable(ids, apiId, multi = false) {
if (!ids || !ids.length) return;
try {
const rows = [];
for (const item of ids) {
let data = false;
try {
const agent = await this.apiRequest.makeGenericRequest(
'GET',
`/agents/${item}`,
{},
apiId
);
if (agent && agent.data) {
data = {};
Object.assign(data, agent.data);
}
} catch (error) {
continue;
if (multi) {
const agents = await this.apiRequest.makeGenericRequest(
'GET',
`/agents/groups/${multi}`,
{},
apiId
);
for (let item of ((agents || {}).data || {}).items || []) {
const str = Array(6).fill('-');
if ((item || {}).id) str[0] = item.id;
if ((item || {}).name) str[1] = item.name;
if ((item || {}).ip) str[2] = item.ip;
if ((item || {}).version) str[3] = item.version;
// 3.7 <
if ((item || {}).manager_host) str[4] = item.manager_host;
// 3.7 >=
if ((item || {}).manager) str[4] = item.manager;
if ((item || {}).os && item.os.name && item.os.version)
str[5] = `${item.os.name} ${item.os.version}`;
str[6] = (item || {}).dateAdd ? item.dateAdd : '-';
str[7] = (item || {}).lastKeepAlive ? item.lastKeepAlive : '-';
rows.push(str);
}
} else {
for (const item of ids) {
let data = false;
try {
const agent = await this.apiRequest.makeGenericRequest(
'GET',
`/agents/${item}`,
{},
apiId
);
if (agent && agent.data) {
data = {};
Object.assign(data, agent.data);
}
} catch (error) {
continue;
}
const str = Array(6).fill('-');
str[0] = item;
if ((data || {}).name) str[1] = data.name;
if ((data || {}).ip) str[2] = data.ip;
if ((data || {}).version) str[3] = data.version;
// 3.7 <
if ((data || {}).manager_host) str[4] = data.manager_host;
// 3.7 >=
if ((data || {}).manager) str[4] = data.manager;
if ((data || {}).os && data.os.name && data.os.version)
str[5] = `${data.os.name} ${data.os.version}`;
str[6] = (data || {}).dateAdd ? data.dateAdd : '-';
str[7] = (data || {}).lastKeepAlive ? data.lastKeepAlive : '-';
rows.push(str);
}
const str = Array(6).fill('-');
str[0] = item;
if ((data || {}).name) str[1] = data.name;
if ((data || {}).ip) str[2] = data.ip;
if ((data || {}).version) str[3] = data.version;
// 3.7 <
if ((data || {}).manager_host) str[4] = data.manager_host;
// 3.7 >=
if ((data || {}).manager) str[4] = data.manager;
if ((data || {}).os && data.os.name && data.os.version)
str[5] = `${data.os.name} ${data.os.version}`;
rows.push(str);
}
PdfTable(
this.dd,
rows,
['ID', 'Name', 'IP', 'Version', 'Manager', 'OS'],
[
'ID',
'Name',
'IP',
'Version',
'Manager',
'OS',
'Registration date',
'Last keep alive'
],
null,
null,
true
@ -1369,6 +1506,99 @@ export class WazuhReportingCtrl {
}
}
getConfigRows = (data, labels) => {
const result = [];
for (let prop in data || []) {
if (Array.isArray(data[prop])) {
data[prop].forEach((x, idx) => {
if (typeof x === 'object') data[prop][idx] = JSON.stringify(x);
});
}
result.push([
(labels || {})[prop] || KeyEquivalence[prop] || prop,
data[prop] || '-'
]);
}
return result;
};
getConfigTables = (data, section, tab, array = []) => {
let plainData = {};
const nestedData = [];
const tableData = [];
if (data.length === 1 && Array.isArray(data)) {
tableData[section.config[tab].configuration] = data;
} else {
for (let key in data) {
if (
(typeof data[key] !== 'object' && !Array.isArray(data[key])) ||
(Array.isArray(data[key]) && typeof data[key][0] !== 'object')
) {
plainData[key] =
Array.isArray(data[key]) && typeof data[key][0] !== 'object'
? data[key].map(x => {
return typeof x === 'object' ? JSON.stringify(x) : x + '\n';
})
: data[key];
} else if (
Array.isArray(data[key]) &&
typeof data[key][0] === 'object'
) {
tableData[key] = data[key];
} else {
if (section.isGroupConfig && ['pack', 'content'].includes(key)) {
tableData[key] = [data[key]];
} else {
nestedData.push(data[key]);
}
}
}
}
array.push({
title: (section.options || {}).hideHeader
? ''
: (section.tabs || [])[tab] ||
(section.isGroupConfig ? ((section.labels || [])[0] || [])[tab] : ''),
columns: ['', ''],
type: 'config',
rows: this.getConfigRows(plainData, (section.labels || [])[0])
});
for (let key in tableData) {
const columns = Object.keys(tableData[key][0]);
columns.forEach((col, i) => {
columns[i] = col[0].toUpperCase() + col.slice(1);
});
const rows = tableData[key].map(x => {
let row = [];
for (let key in x) {
row.push(
typeof x[key] !== 'object'
? x[key]
: Array.isArray(x[key])
? x[key].map(x => {
return x + '\n';
})
: JSON.stringify(x[key])
);
}
return row;
});
array.push({
title: ((section.labels || [])[0] || [])[key] || '',
type: 'table',
columns,
rows
});
}
nestedData.forEach(nest => {
this.getConfigTables(nest, section, tab + 1, array);
});
return array;
};
/**
* Builds a PDF report from multiple PNG images
* @param {Object} req
@ -1392,13 +1622,28 @@ export class WazuhReportingCtrl {
const pattern = headers.pattern || false;
const from = (payload.time || {}).from || false;
const to = (payload.time || {}).to || false;
const kfilters = req.payload.filters;
let kfilters = req.payload.filters;
const isAgentConfig = tab === 'agentConfig';
const isGroupConfig = tab === 'groupConfig';
// Pass the namespace if present to all the requesters
if (pattern) {
const spaces = this.server.plugins.spaces;
const namespace = spaces && spaces.getSpaceId(req);
this.vulnerabilityRequest.namespace = namespace;
this.overviewRequest.namespace = namespace;
this.rootcheckRequest.namespace = namespace;
this.pciRequest.namespace = namespace;
this.gdprRequest.namespace = namespace;
this.auditRequest.namespace = namespace;
this.syscheckRequest.namespace = namespace;
}
if (!tab)
throw new Error(
'Reporting needs a valid app tab in order to work properly'
);
if (!section)
if (!section && !isAgentConfig && !isGroupConfig)
throw new Error(
'Reporting needs a valid app section in order to work properly'
);
@ -1411,9 +1656,440 @@ export class WazuhReportingCtrl {
'Reporting needs a valid file name in order to work properly'
);
const isSycollector = tab === 'syscollector';
let tables = [];
if (isGroupConfig) {
const equivalences = {
localfile: 'Local files',
osquery: 'Osquery',
command: 'Command',
syscheck: 'Syscheck',
'open-scap': 'OpenSCAP',
'cis-cat': 'CIS-CAT',
syscollector: 'Syscollector',
rootcheck: 'Rootcheck',
labels: 'Labels',
sca: 'Security configuration assessment'
};
const g_id = kfilters[0].group;
kfilters = [];
const enabledComponents = req.payload.components;
this.dd.content.push({
text: `Group ${g_id} configuration`,
style: 'h1'
});
if (enabledComponents['0']) {
let configuration = {};
try {
configuration = await this.apiRequest.makeGenericRequest(
'GET',
`/agents/groups/${g_id}/configuration`,
{},
apiId
);
} catch (err) {} //eslint-disable-line
if (Object.keys(configuration.data.items[0].config).length) {
this.dd.content.push({
text: `Configurations`,
style: { fontSize: 14, color: '#000' },
margin: [0, 10, 0, 15]
});
const section = {
labels: [],
isGroupConfig: true
};
for (let config of configuration.data.items) {
let filterTitle = '';
let index = 0;
for (let filter of Object.keys(config.filters)) {
filterTitle = filterTitle.concat(
`${filter}: ${config.filters[filter]}`
);
if (index < Object.keys(config.filters).length - 1) {
filterTitle = filterTitle.concat(' | ');
}
index++;
}
this.dd.content.push({
text: filterTitle,
style: 'h4',
margin: [0, 0, 0, 10]
});
let idx = 0;
section.tabs = [];
for (let _d of Object.keys(config.config)) {
for (let c of AgentConfiguration.configurations) {
for (let s of c.sections) {
for (let cn of s.config || []) {
if (cn.configuration === _d) {
section.labels = s.labels || [[]];
}
}
for (let wo of s.wodle || []) {
if (wo.name === _d) {
section.labels = s.labels || [[]];
}
}
}
}
section.labels[0]['pack'] = 'Packs';
section.labels[0]['content'] = 'Evaluations';
section.labels[0]['7'] = 'Scan listening netwotk ports';
section.tabs.push(equivalences[_d]);
if (Array.isArray(config.config[_d])) {
/* LOG COLLECTOR */
if (_d === 'localfile') {
let groups = [];
config.config[_d].forEach(obj => {
if (!groups[obj.logformat]) {
groups[obj.logformat] = [];
}
groups[obj.logformat].push(obj);
});
Object.keys(groups).forEach(group => {
let saveidx = 0;
groups[group].forEach((x, i) => {
if (
Object.keys(x).length >
Object.keys(groups[group][saveidx]).length
) {
saveidx = i;
}
});
const columns = Object.keys(groups[group][saveidx]);
const rows = groups[group].map(x => {
let row = [];
columns.forEach(key => {
row.push(
typeof x[key] !== 'object'
? x[key]
: Array.isArray(x[key])
? x[key].map(x => {
return x + '\n';
})
: JSON.stringify(x[key])
);
});
return row;
});
columns.forEach((col, i) => {
columns[i] = col[0].toUpperCase() + col.slice(1);
});
tables.push({
title: 'Local files',
type: 'table',
columns,
rows
});
});
} else if (_d === 'labels') {
const obj = config.config[_d][0].label;
const columns = Object.keys(obj[0]);
if (!columns.includes('hidden')) {
columns.push('hidden');
}
const rows = obj.map(x => {
let row = [];
columns.forEach(key => {
row.push(x[key]);
});
return row;
});
columns.forEach((col, i) => {
columns[i] = col[0].toUpperCase() + col.slice(1);
});
tables.push({
title: 'Labels',
type: 'table',
columns,
rows
});
} else {
for (let _d2 of config.config[_d]) {
tables.push(...this.getConfigTables(_d2, section, idx));
}
}
} else {
tables.push(
...this.getConfigTables(config.config[_d], section, idx)
);
}
for (const table of tables) {
this.renderConfigTables([table]);
}
idx++;
tables = [];
}
tables = [];
}
}
}
if (enabledComponents['1']) {
let agentsInGroup = [];
try {
agentsInGroup = await this.apiRequest.makeGenericRequest(
'GET',
`/agents/groups/${g_id}`,
{},
apiId
);
} catch (err) {} //eslint-disable-line
await this.renderHeader(
tab,
g_id,
(((agentsInGroup || []).data || []).items || []).map(x => x.id),
apiId
);
}
let agentsInGroup = [];
try {
agentsInGroup = await this.apiRequest.makeGenericRequest(
'GET',
`/agents/groups/${g_id}`,
{},
apiId
);
} catch (err) {} //eslint-disable-line
await this.renderHeader(
tab,
g_id,
(((agentsInGroup || []).data || []).items || []).map(x => x.id),
apiId
);
}
if (isAgentConfig) {
const configurations = AgentConfiguration.configurations;
const enabledComponents = req.payload.components;
const a_id = kfilters[0].agent;
let wmodules = {};
try {
wmodules = await this.apiRequest.makeGenericRequest(
'GET',
`/agents/${a_id}/config/wmodules/wmodules`,
{},
apiId
);
} catch (err) {} //eslint-disable-line
kfilters = [];
await this.renderHeader(tab, tab, a_id, apiId);
let idxComponent = 0;
for (let config of configurations) {
let titleOfSection = false;
for (let section of config.sections) {
if (
enabledComponents[idxComponent] &&
(section.config || section.wodle)
) {
let idx = 0;
const configs = (section.config || []).concat(
section.wodle || []
);
for (let conf of configs) {
let data = {};
try {
if (!conf['name']) {
data = await this.apiRequest.makeGenericRequest(
'GET',
`/agents/${a_id}/config/${conf.component}/${conf.configuration}`,
{},
apiId
);
} else {
for (let wodle of wmodules.data['wmodules']) {
if (Object.keys(wodle)[0] === conf['name']) {
data.data = wodle;
}
}
}
if (
data &&
data.data &&
Object.keys(data.data[Object.keys(data.data)[0]]).length >
0
) {
if (!titleOfSection) {
this.dd.content.push({
text: config.title,
style: 'h1',
margin: [0, 0, 0, 15]
});
titleOfSection = true;
}
for (let _d of Object.keys(data.data)) {
if (idx === 0) {
this.dd.content.push({
text: section.subtitle,
style: 'h4'
});
this.dd.content.push({
text: section.desc,
style: { fontSize: 12, color: '#000' },
margin: [0, 0, 0, 10]
});
}
if (Array.isArray(data.data[_d])) {
/* LOG COLLECTOR */
if (conf.filterBy) {
let groups = [];
data.data[_d].forEach(obj => {
if (!groups[obj.logformat]) {
groups[obj.logformat] = [];
}
groups[obj.logformat].push(obj);
});
Object.keys(groups).forEach(group => {
let saveidx = 0;
groups[group].forEach((x, i) => {
if (
Object.keys(x).length >
Object.keys(groups[group][saveidx]).length
) {
saveidx = i;
}
});
const columns = Object.keys(
groups[group][saveidx]
);
const rows = groups[group].map(x => {
let row = [];
columns.forEach(key => {
row.push(
typeof x[key] !== 'object'
? x[key]
: Array.isArray(x[key])
? x[key].map(x => {
return x + '\n';
})
: JSON.stringify(x[key])
);
});
return row;
});
columns.forEach((col, i) => {
columns[i] =
col[0].toUpperCase() + col.slice(1);
});
tables.push({
title: section.labels[0][group],
type: 'table',
columns,
rows
});
});
} else if (_d.configuration !== 'socket') {
tables.push(
...this.getConfigTables(
data.data[_d],
section,
idx
)
);
} else {
for (let _d2 of data.data[_d]) {
tables.push(
...this.getConfigTables(_d2, section, idx)
);
}
}
} else {
/*INTEGRITY MONITORING MONITORED DIRECTORIES */
if (conf.matrix) {
const directories = data.data[_d].directories;
delete data.data[_d].directories;
tables.push(
...this.getConfigTables(
data.data[_d],
section,
idx
)
);
let diffOpts = [];
Object.keys(section.opts).forEach(x => {
diffOpts.push(x);
});
const columns = [
'',
...diffOpts.filter(
x => x !== 'check_all' && x !== 'check_sum'
)
];
let rows = [];
directories.forEach(x => {
let row = [];
row.push(x.dir);
columns.forEach(y => {
if (y !== '') {
row.push(
x.opts.indexOf(y) > -1 ? 'yes' : 'no'
);
}
});
row.push(x.recursion_level);
rows.push(row);
});
columns.forEach((x, idx) => {
columns[idx] = section.opts[x];
});
columns.push('RL');
tables.push({
title: 'Monitored directories',
type: 'table',
columns,
rows
});
} else {
tables.push(
...this.getConfigTables(
data.data[_d],
section,
idx
)
);
}
}
}
} else {
// Print the section title
if (!titleOfSection) {
this.dd.content.push({
text: config.title,
style: 'h1',
margin: [0, 0, 0, 15]
});
titleOfSection = true;
}
//Print the subtitle
this.dd.content.push({
text: section.subtitle,
style: 'h4'
});
// Print no configured module and link to the documentation
this.dd.content.push({
text: [
'This module is not configured. Please take a look on how to configure it in ',
{
text: `${section.subtitle.toLowerCase()} configuration.`,
link: section.docuLink,
style: { fontSize: 12, color: '#1a0dab' }
}
],
margin: [0, 0, 0, 20]
});
}
} catch (err) {} //eslint-disable-line
idx++;
}
for (const table of tables) {
this.renderConfigTables([table]);
}
}
idxComponent++;
tables = [];
}
}
}
const isSycollector = tab === 'syscollector';
if (isSycollector) {
let agentId = '';
let agentOs = '';
@ -1583,8 +2259,9 @@ export class WazuhReportingCtrl {
} catch (err) {} //eslint-disable-line
}
await this.renderHeader(section, tab, isAgents, apiId);
if (!isAgentConfig && !isGroupConfig) {
await this.renderHeader(section, tab, isAgents, apiId);
}
let filters = false;
if (kfilters) {
filters = this.sanitizeFilters(kfilters, req.payload.searchBar);
@ -1609,13 +2286,18 @@ export class WazuhReportingCtrl {
);
}
!isSycollector &&
if (!isSycollector && !isAgentConfig && !isGroupConfig) {
this.renderVisualizations(req.payload.array, isAgents, tab);
}
if (isSycollector) {
this.renderTables(tables, false);
}
if (!isSycollector && req.payload.tables) {
if (
!isSycollector &&
!isAgentConfig &&
!isGroupConfig &&
req.payload.tables
) {
this.renderTables(req.payload.tables);
}

View File

@ -18,10 +18,12 @@ import { defaultExt } from './lib/default-ext';
import { BuildBody } from './lib/replicas-shards-helper';
import { checkKnownFields } from './lib/refresh-known-fields';
import { totalmem } from 'os';
import fs from 'fs';
import path from 'path';
export function Initialize(server) {
const wazuhVersion = path.join(__dirname, '/wazuh-version.json');
const blueWazuh = '\u001b[34mwazuh\u001b[39m';
// Elastic JS Client
const wzWrapper = new ElasticWrapper(server);
log('initialize', `Kibana index: ${wzWrapper.WZ_KIBANA_INDEX}`, 'info');
@ -39,7 +41,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) {
@ -66,10 +68,6 @@ export function Initialize(server) {
// Save Wazuh App setup
const saveConfiguration = async () => {
try {
const shardConfiguration = BuildBody(configurationFile, 'wazuh-version');
await wzWrapper.createWazuhVersionIndex(shardConfiguration);
const commonDate = new Date().toISOString();
const configuration = {
@ -81,18 +79,21 @@ export function Initialize(server) {
};
try {
await wzWrapper.insertWazuhVersionConfiguration(configuration);
fs.writeFileSync(wazuhVersion, JSON.stringify(configuration), err => {
if (err) {
throw new Error(err);
}
});
log(
'initialize:saveConfiguration',
'Wazuh configuration inserted',
'Wazuh configuration registry inserted',
'debug'
);
} catch (error) {
log('initialize:saveConfiguration', error.message || error);
server.log(
[blueWazuh, 'initialize', 'error'],
'Could not insert Wazuh configuration'
'Could not create Wazuh configuration registry'
);
}
@ -101,7 +102,7 @@ export function Initialize(server) {
log('initialize:saveConfiguration', error.message || error);
server.log(
[blueWazuh, 'initialize', 'error'],
'Error creating index .wazuh-version.'
'Error creating wazuh-version registry'
);
}
};
@ -158,13 +159,13 @@ export function Initialize(server) {
log(
'initialize:checkAPIEntriesExtensions',
`Error updating API entry extensions with ID: ${
item._id
item._id
} due to ${error.message || error}`
);
server.log(
[blueWazuh, 'initialize:checkAPIEntriesExtensions', 'error'],
`Error updating API entry extensions with ID: ${
item._id
item._id
} due to ${error.message || error}`
);
}
@ -208,28 +209,36 @@ export function Initialize(server) {
}
};
const checkWazuhVersionIndex = async () => {
const checkWazuhVersionRegistry = async () => {
try {
log(
'initialize[checkWazuhVersionIndex]',
'Checking .wazuh-version index.',
'initialize[checkWazuhVersionRegistry]',
'Checking wazuh-version registry.',
'debug'
);
try {
await wzWrapper.getWazuhVersionIndex();
const shardConfiguration = BuildBody(
configurationFile,
'wazuh-version'
);
await wzWrapper.updateIndexSettings(
'.wazuh-version',
shardConfiguration
await wzWrapper.deleteWazuhVersionIndex();
log(
'initialize[checkWazuhVersionRegistry]',
'Successfully deleted old .wazuh-version index.',
'debug'
);
} catch (error) {
log(
'initialize[checkWazuhVersionIndex]',
'.wazuh-version document does not exist. Initializating configuration...',
'initialize[checkWazuhVersionRegistry]',
'No need to delete old .wazuh-version index',
'debug'
);
}
try {
if (!fs.existsSync(wazuhVersion)) {
throw new Error();
}
} catch (error) {
log(
'initialize[checkWazuhVersionRegistry]',
'wazuh-version registry does not exist. Initializating configuration...',
'debug'
);
@ -237,10 +246,16 @@ export function Initialize(server) {
await saveConfiguration();
}
await wzWrapper.updateWazuhVersionIndexLastRestart(
packageJSON.version,
packageJSON.revision
);
let source = JSON.parse(fs.readFileSync(wazuhVersion, 'utf8'));
source['app-version'] = packageJSON.version;
source.revision = packageJSON.revision;
source.lastRestart = new Date().toISOString(); // Registry exists so we update the lastRestarted date only
fs.writeFileSync(wazuhVersion, JSON.stringify(source), err => {
if (err) {
throw new Error(err);
}
});
} catch (error) {
return Promise.reject(error);
}
@ -251,7 +266,7 @@ export function Initialize(server) {
try {
await Promise.all([
checkWazuhIndex(),
checkWazuhVersionIndex(),
checkWazuhVersionRegistry(),
checkKnownFields(wzWrapper, log, server, defaultIndexPattern)
]);
const reindexResult = await wzWrapper.reindexAppIndices();
@ -306,7 +321,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}`
)
);
@ -327,7 +342,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

@ -0,0 +1,37 @@
/*
* Wazuh app - Module for HIPAA requirements
* Copyright (C) 2015-2019 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
export const hipaaRequirementsFile = {
'164.312.a.1':
'Implement technical policies and procedures for electronic information systems that maintain electronic protected health information to allow access only to those persons or software programs that have been granted access rights.',
'164.312.a.2.I':
'Assign a unique name and/or number for identifying and tracking user identity.',
'164.312.a.2.II':
'Establish (and implement as needed) procedures for obtaining necessary electronic protected health information during an emergency.',
'164.312.a.2.III':
'Implement electronic procedures that terminate an electronic session after a predetermined time of inactivity.',
'164.312.a.2.IV':
'Implement a mechanism to encrypt and decrypt electronic protected health information.',
'164.312.b':
'Implement hardware, software, and/or procedural mechanisms that record and examine activity in information systems that contain or use electronic protected health information.',
'164.312.c.1':
'Implement policies and procedures to protect electronic protected health information from improper alteration or destruction.',
'164.312.c.2':
'Implement electronic mechanisms to corroborate that electronic protected health information has not been altered or destroyed in an unauthorized manner.',
'164.312.d':
'Implement procedures to verify that a person or entity seeking access to electronic protected health information is the one claimed.',
'164.312.e.1':
'Implement technical security measures to guard against unauthorized access to electronic protected health information that is being transmitted over an electronic communications network.',
'164.312.e.2.I':
'Implement security measures to ensure that electronically transmitted electronic protected health information is not improperly modified without detection until disposed of.',
'164.312.e.2.II':
'Implement a mechanism to encrypt electronic protected health information whenever deemed appropriate.'
};

View File

@ -4568,6 +4568,24 @@ export const knownFields = [
aggregatable: true,
readFromDocValues: true
},
{
name: 'rule.hipaa',
type: 'string',
count: 0,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true
},
{
name: 'rule.nist_800_53',
type: 'string',
count: 0,
scripted: false,
searchable: true,
aggregatable: true,
readFromDocValues: true
},
{
name: 'rule.gpg13',
type: 'string',

View File

@ -0,0 +1,59 @@
/*
* Wazuh app - Module for NIST 800-53 requirements
* Copyright (C) 2015-2019 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
export const nistRequirementsFile = {
'AC.2':
'ACCOUNT MANAGEMENT - Identifies and selects the following types of information system accounts to support organizational missions/business functions.',
'AC.6':
'LEAST PRIVILEGE - The organization employs the principle of least privilege, allowing only authorized accesses for users (or processes acting on behalf of users) which are necessary to accomplish assigned tasks in accordance with organizational missions and business functions.',
'AC.7':
'UNSUCCESSFUL LOGON ATTEMPTS - Enforces a limit of consecutive invalid logon attempts by a user during a time period.',
'AC.12':
'SESSION TERMINATION - The information system automatically terminates a user session.',
'AU.5':
'RESPONSE TO AUDIT PROCESSING FAILURES - The information system alerts organization-defined personnel or roles in the event of an audit processing failure and takes organization-defined actions to be taken (e.g., shut down information system, overwrite oldest audit records, stop generating audit records).',
'AU.6':
'AUDIT REVIEW, ANALYSIS, AND REPORTING - Reviews and analyzes information system audit records.',
'AU.8':
'TIME STAMPS - Uses internal system clocks to generate time stamps for audit records and records time stamps for audit records.',
'AU.9':
'PROTECTION OF AUDIT INFORMATION - The information system protects audit information and audit tools from unauthorized access, modification, and deletion.',
'AU.12':
'AUDIT GENERATION - The information system provides audit record generation capability for the auditable events at organization-defined information system components, allows organization-defined personnel or roles to select which auditable events are to be audited by specific components of the information system and generates audit records.',
'CA.3':
'SYSTEM INTERCONNECTIONS - Authorizes connections from the information system to other information systems through the use of Interconnection Security Agreements, Documents, for each interconnection, the interface characteristics, security requirements, and the nature of the information communicated and Reviews and updates Interconnection Security Agreements ',
'CM.1':
'CONFIGURATION MANAGEMENT POLICY AND PROCEDURES - Develops, documents, and disseminates to a configuration management policy. Revies and updates the current configuration management policy and procedures.',
'CM.3':
'CONFIGURATION CHANGE CONTROL - The organization determines the types of changes to the information system that are configuration-controlled. ',
'CM.5':
'ACCESS RESTRICTIONS FOR CHANGE - The organization defines, documents, approves, and enforces physical and logical access restrictions associated with changes to the information system.',
'IA.4':
'IDENTIFIER MANAGEMENT - The organization manages information system identifiers by: Receiving authorization from organization-defined personnel or roles to assign an individual, group, role, or device identifier. Selecting an identifier that identifies an individual, group, role, or device. Assigning the identifier to the intended individual, group, role, or device. Preventing reuse of identifiers for a organization-defined time period. Disabling the identifier after organization-defined time period of inactivity.',
'IA.5':
'AUTHENTICATOR MANAGEMENT - The organization manages information system authenticators by verifying, as part of the initial authenticator distribution, the identity of the individual, group role, or device receiving the authenticator.',
'IA.10':
'ADAPTIVE IDENTIFICATION AND AUTHENTICATION - The organization requires that individuals accessing the information system employ organization-defined supplemental authentication techniques or mechanisms under specific organization-defined circumstances or situations. ',
'SA.11':
'DEVELOPER SECURITY TESTING AND EVALUATION - The organization requires the developer of the information system, system component, or information system service to create and implement a security assessment plan.',
'SC.2':
'APPLICATION PARTITIONING - The information system separates user functionality (including user interface services) from information system management functionality.',
'SC.7':
'BOUNDARY PROTECTION - The information system monitors and controls communications at the external boundary of the system and at key internal boundaries within the system.',
'SC.8':
'TRANSMISSION CONFIDENTIALITY AND INTEGRITY - The information system protects the confidentiality and integrity of transmitted information.',
'SI.2':
'FLAW REMEDIATION - The organization identifies, reports, and corrects information system flaws; tests software and firmware updates related to flaw remediation for effectiveness and potential side effects before installation; installs security-relevant software and firmware updates within organizationdefined time period of the release of the updates and incorporates flaw remediation into the organizational configuration management process.',
'SI.3':
'MALICIOUS CODE PROTECTION - The organization employs malicious code protection mechanisms at information system entry and exit points to detect and eradicate malicious code, updates malicious code protection mechanisms whenever new releases are available in accordance with organizational configuration management policy and procedures, configures malicious code protection mechanisms and addresses the receipt of false positives during malicious code detection and eradication and the resulting potential impact on the availability of the information system.',
'SI.7':
'SOFTWARE, FIRMWARE, AND INFORMATION INTEGRITY - The organization employs integrity verification tools to detect unauthorized changes to organization-defined software, firmware, and information.'
};

View File

@ -0,0 +1,110 @@
/*
* Wazuh app - Module for Agents/HIPAA visualizations
* Copyright (C) 2015-2019 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
export default [
{
_id: 'Wazuh-App-Agents-HIPAA-Groups',
_source: {
title: 'Top 5 rule groups',
visState:
'{"title":"Top 5 rule groups","type":"pie","params":{"type":"pie","addTooltip":true,"addLegend":true,"legendPosition":"right","isDonut":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"rule.groups","size":5,"order":"desc","orderBy":"1"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Agents-HIPAA-Rule',
_source: {
title: 'Top 5 rules',
visState:
'{"title":"Top 5 rules","type":"pie","params":{"type":"pie","addTooltip":true,"addLegend":true,"legendPosition":"right","isDonut":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"rule.description","size":5,"order":"desc","orderBy":"1"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Agents-HIPAA-Requirement',
_source: {
title: 'Top 5 requirements',
visState:
'{"title":"Top 5 requirements","type":"pie","params":{"type":"pie","addTooltip":true,"addLegend":true,"legendPosition":"right","isDonut":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"rule.hipaa","size":5,"order":"desc","orderBy":"1"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Agents-HIPAA-Rule-level-distribution',
_source: {
title: 'Rule level distribution',
visState:
'{"title":"Rule level distribution","type":"pie","params":{"type":"pie","addTooltip":true,"addLegend":false,"legendPosition":"right","isDonut":true,"labels":{"show":true,"values":true,"last_level":true,"truncate":100}},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"rule.level","size":15,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}',
uiStateJSON: '{"vis":{"legendOpen":false}}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Agents-HIPAA-Requirements',
_source: {
title: 'Requirements',
visState:
'{"title":"Requirements","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"rotate":0},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"rule.hipaa","size":5,"order":"desc","orderBy":"1","customLabel":""}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"rule.hipaa","size":10,"order":"desc","orderBy":"1","customLabel":"HIPAA requirements"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Agents-HIPAA-Last-alerts',
_type: 'visualization',
_source: {
title: 'Last alerts',
visState:
'{"title":"Last alerts","type":"table","params":{"perPage":10,"showPartialRows":false,"showMeticsAtAllLevels":false,"sort":{"columnIndex":2,"direction":"desc"},"showTotal":false,"totalFunc":"sum"},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"3","enabled":true,"type":"terms","schema":"bucket","params":{"field":"rule.hipaa","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":50,"order":"desc","orderBy":"1","customLabel":"Requirement"}},{"id":"4","enabled":true,"type":"terms","schema":"bucket","params":{"field":"rule.description","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":10,"order":"desc","orderBy":"1","customLabel":"Rule description"}}]}',
uiStateJSON:
'{"vis":{"params":{"sort":{"columnIndex":2,"direction":"desc"}}}}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
}
}
];

View File

@ -0,0 +1,110 @@
/*
* Wazuh app - Module for Agents/NIST-800-53 visualizations
* Copyright (C) 2015-2019 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
export default [
{
_id: 'Wazuh-App-Agents-NIST-Groups',
_source: {
title: 'Top 5 rule groups',
visState:
'{"title":"Top 5 rule groups","type":"pie","params":{"type":"pie","addTooltip":true,"addLegend":true,"legendPosition":"right","isDonut":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"rule.groups","size":5,"order":"desc","orderBy":"1"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Agents-NIST-Rule',
_source: {
title: 'Top 5 rules',
visState:
'{"title":"Top 5 rules","type":"pie","params":{"type":"pie","addTooltip":true,"addLegend":true,"legendPosition":"right","isDonut":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"rule.description","size":5,"order":"desc","orderBy":"1"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Agents-NIST-Requirement',
_source: {
title: 'Top 5 requirements',
visState:
'{"title":"Top 5 requirements","type":"pie","params":{"type":"pie","addTooltip":true,"addLegend":true,"legendPosition":"right","isDonut":true},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"rule.nist_800_53","size":5,"order":"desc","orderBy":"1"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Agents-NIST-Rule-level-distribution',
_source: {
title: 'Rule level distribution',
visState:
'{"title":"Rule level distribution","type":"pie","params":{"type":"pie","addTooltip":true,"addLegend":false,"legendPosition":"right","isDonut":true,"labels":{"show":true,"values":true,"last_level":true,"truncate":100}},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"rule.level","size":15,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}',
uiStateJSON: '{"vis":{"legendOpen":false}}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Agents-NIST-Requirements',
_source: {
title: 'Requirements',
visState:
'{"title":"Requirements","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"rotate":0},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"rule.nist_800_53","size":5,"order":"desc","orderBy":"1","customLabel":""}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"rule.nist_800_53","size":10,"order":"desc","orderBy":"1","customLabel":"NIST requirements"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Agents-NIST-Last-alerts',
_type: 'visualization',
_source: {
title: 'Last alerts',
visState:
'{"title":"Last alerts","type":"table","params":{"perPage":10,"showPartialRows":false,"showMeticsAtAllLevels":false,"sort":{"columnIndex":2,"direction":"desc"},"showTotal":false,"totalFunc":"sum"},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"3","enabled":true,"type":"terms","schema":"bucket","params":{"field":"rule.nist_800_53","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":50,"order":"desc","orderBy":"1","customLabel":"Requirement"}},{"id":"4","enabled":true,"type":"terms","schema":"bucket","params":{"field":"rule.description","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":10,"order":"desc","orderBy":"1","customLabel":"Rule description"}}]}',
uiStateJSON:
'{"vis":{"params":{"sort":{"columnIndex":2,"direction":"desc"}}}}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
}
}
];

View File

@ -16,6 +16,8 @@ import oscap from './agents-oscap';
import ciscat from './agents-ciscat';
import pci from './agents-pci';
import gdpr from './agents-gdpr';
import hipaa from './agents-hipaa';
import nist from './agents-nist';
import pm from './agents-pm';
import virustotal from './agents-virustotal';
import vuls from './agents-vuls';
@ -30,6 +32,8 @@ export {
ciscat,
pci,
gdpr,
hipaa,
nist,
pm,
virustotal,
vuls,

View File

@ -17,6 +17,8 @@ import oscap from './overview-oscap';
import ciscat from './overview-ciscat';
import pci from './overview-pci';
import gdpr from './overview-gdpr';
import hipaa from './overview-hipaa';
import nist from './overview-nist';
import pm from './overview-pm';
import virustotal from './overview-virustotal';
import vuls from './overview-vuls';
@ -33,6 +35,8 @@ export {
ciscat,
pci,
gdpr,
hipaa,
nist,
pm,
virustotal,
vuls,

View File

@ -0,0 +1,128 @@
/*
* Wazuh app - Module for Overview/HIPAA visualizations
* Copyright (C) 2015-2019 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
export default [
{
_id: 'Wazuh-App-Overview-HIPAA-Requirements-over-time',
_source: {
title: 'Requirements over time',
visState:
'{"title":"Alerts by action over time","type":"area","params":{"type":"area","grid":{"categoryLines":true,"style":{"color":"#eee"},"valueAxis":"ValueAxis-1"},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"area","mode":"stacked","data":{"label":"Count","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"cardinal","valueAxis":"ValueAxis-1"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","timeRange":{"from":"now-24h","to":"now","mode":"quick"},"useNormalizedEsInterval":true,"interval":"auto","time_zone":"Europe/Berlin","drop_partials":false,"customInterval":"2h","min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"rule.hipaa","size":"5","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"language":"lucene","query":""}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Overview-HIPAA-Requirements-Agents-heatmap',
_type: 'visualization',
_source: {
title: 'HIPAA requirements heatmap',
visState:
'{"title":"HIPAA requirements heatmap","type":"heatmap","params":{"type":"heatmap","addTooltip":true,"addLegend":true,"enableHover":false,"legendPosition":"right","times":[],"colorsNumber":10,"colorSchema":"Greens","setColorRange":false,"colorsRange":[],"invertColors":false,"percentageMode":false,"valueAxes":[{"show":false,"id":"ValueAxis-1","type":"value","scale":{"type":"linear","defaultYExtents":false},"labels":{"show":false,"rotate":0,"overwriteColor":false,"color":"#555"}}]},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"rule.hipaa","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Requirements"}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"agent.name","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Agents"}}]}',
uiStateJSON:
'{"vis":{"defaultColors":{"0 - 13":"rgb(247,252,245)","13 - 26":"rgb(233,247,228)","26 - 39":"rgb(211,238,205)","39 - 52":"rgb(184,227,177)","52 - 65":"rgb(152,213,148)","65 - 78":"rgb(116,196,118)","78 - 91":"rgb(75,176,98)","91 - 104":"rgb(47,152,79)","104 - 117":"rgb(21,127,59)","117 - 130":"rgb(0,100,40)"}}}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","query":{"query":"","language":"lucene"},"filter":[]}'
}
}
},
{
_id: 'Wazuh-App-Overview-HIPAA-requirements',
_source: {
title: 'HIPAA requirements',
visState:
'{"title":"HIPAA requirements","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":true,"style":{"color":"#eee"},"valueAxis":"ValueAxis-1"},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Alerts"}},{"id":"ValueAxis-2","name":"RightAxis-1","type":"value","position":"right","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Unique HIPAA DSS requirements"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Alerts","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true},{"show":true,"mode":"stacked","type":"line","drawLinesBetweenPoints":false,"showCircles":true,"interpolate":"linear","data":{"id":"3","label":"Unique HIPAA DSS requirements"},"valueAxis":"ValueAxis-2"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{"customLabel":"Alerts"}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","timeRange":{"from":"now-1h","to":"now","mode":"quick"},"useNormalizedEsInterval":true,"interval":"auto","time_zone":"Europe/Berlin","drop_partials":false,"customInterval":"2h","min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"cardinality","schema":"metric","params":{"field":"rule.hipaa","customLabel":"Unique HIPAA DSS requirements"}},{"id":"4","enabled":true,"type":"count","schema":"radius","params":{}}]}',
uiStateJSON: '{"vis":{"legendOpen":false}}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Overview-HIPAA-Agents',
_source: {
title: 'Agents',
visState:
'{"title":"Agents","type":"pie","params":{"type":"pie","addTooltip":true,"addLegend":true,"legendPosition":"right","isDonut":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"agent.name","size":10,"order":"desc","orderBy":"1"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Overview-HIPAA-Requirements-by-agent',
_source: {
title: 'Requirements by agent',
visState:
'{"title":"Requirements by agent","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"rotate":0},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"radiusRatio":51},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"rule.hipaa","size":5,"order":"desc","orderBy":"1","customLabel":"Requirements"}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"agent.name","size":5,"order":"desc","orderBy":"1"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Overview-HIPAA-Last-alerts',
_type: 'visualization',
_source: {
title: 'Last alerts',
visState:
'{"title":"Last alerts","type":"table","params":{"perPage":10,"showPartialRows":false,"showMeticsAtAllLevels":false,"sort":{"columnIndex":null,"direction":null},"showTotal":false,"totalFunc":"sum"},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"bucket","params":{"field":"agent.name","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":50,"order":"desc","orderBy":"1","customLabel":"Agent name"}},{"id":"3","enabled":true,"type":"terms","schema":"bucket","params":{"field":"rule.hipaa","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":10,"order":"desc","orderBy":"1","customLabel":"Requirement"}},{"id":"4","enabled":true,"type":"terms","schema":"bucket","params":{"field":"rule.description","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":10,"order":"desc","orderBy":"1","customLabel":"Rule description"}}]}',
uiStateJSON:
'{"vis":{"params":{"sort":{"columnIndex":3,"direction":"desc"}}}}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
}
},
{
_id: 'Wazuh-App-Overview-HIPAA-Alerts-summary',
_type: 'visualization',
_source: {
title: 'Alerts summary',
visState:
'{"title":"Alerts summary","type":"table","params":{"perPage":10,"showPartialRows":false,"showMeticsAtAllLevels":false,"sort":{"columnIndex":3,"direction":"desc"},"showTotal":false,"totalFunc":"sum"},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"bucket","params":{"field":"agent.name","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":50,"order":"desc","orderBy":"1","customLabel":"Agent name"}},{"id":"3","enabled":true,"type":"terms","schema":"bucket","params":{"field":"rule.hipaa","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":10,"order":"desc","orderBy":"1","customLabel":"Requirement"}},{"id":"4","enabled":true,"type":"terms","schema":"bucket","params":{"field":"rule.description","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":10,"order":"desc","orderBy":"1","customLabel":"Rule description"}}]}',
uiStateJSON:
'{"vis":{"params":{"sort":{"columnIndex":3,"direction":"desc"}}}}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
}
}
];

View File

@ -0,0 +1,128 @@
/*
* Wazuh app - Module for Overview/NIST visualizations
* Copyright (C) 2015-2019 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
export default [
{
_id: 'Wazuh-App-Overview-NIST-Requirements-over-time',
_source: {
title: 'Requirements over time',
visState:
'{"title":"Alerts by action over time","type":"area","params":{"type":"area","grid":{"categoryLines":true,"style":{"color":"#eee"},"valueAxis":"ValueAxis-1"},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"area","mode":"stacked","data":{"label":"Count","id":"1"},"drawLinesBetweenPoints":true,"showCircles":true,"interpolate":"cardinal","valueAxis":"ValueAxis-1"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","timeRange":{"from":"now-24h","to":"now","mode":"quick"},"useNormalizedEsInterval":true,"interval":"auto","time_zone":"Europe/Berlin","drop_partials":false,"customInterval":"2h","min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"rule.nist_800_53","size":"5","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"language":"lucene","query":""}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Overview-NIST-Requirements-Agents-heatmap',
_type: 'visualization',
_source: {
title: 'NIST requirements heatmap',
visState:
'{"title":"NIST requirements heatmap","type":"heatmap","params":{"type":"heatmap","addTooltip":true,"addLegend":true,"enableHover":false,"legendPosition":"right","times":[],"colorsNumber":10,"colorSchema":"Greens","setColorRange":false,"colorsRange":[],"invertColors":false,"percentageMode":false,"valueAxes":[{"show":false,"id":"ValueAxis-1","type":"value","scale":{"type":"linear","defaultYExtents":false},"labels":{"show":false,"rotate":0,"overwriteColor":false,"color":"#555"}}]},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"rule.nist_800_53","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Requirements"}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"agent.name","size":5,"order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","customLabel":"Agents"}}]}',
uiStateJSON:
'{"vis":{"defaultColors":{"0 - 13":"rgb(247,252,245)","13 - 26":"rgb(233,247,228)","26 - 39":"rgb(211,238,205)","39 - 52":"rgb(184,227,177)","52 - 65":"rgb(152,213,148)","65 - 78":"rgb(116,196,118)","78 - 91":"rgb(75,176,98)","91 - 104":"rgb(47,152,79)","104 - 117":"rgb(21,127,59)","117 - 130":"rgb(0,100,40)"}}}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","query":{"query":"","language":"lucene"},"filter":[]}'
}
}
},
{
_id: 'Wazuh-App-Overview-NIST-requirements',
_source: {
title: 'NIST requirements',
visState:
'{"title":"NIST requirements","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":true,"style":{"color":"#eee"},"valueAxis":"ValueAxis-1"},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Alerts"}},{"id":"ValueAxis-2","name":"RightAxis-1","type":"value","position":"right","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Unique NIST DSS requirements"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Alerts","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true},{"show":true,"mode":"stacked","type":"line","drawLinesBetweenPoints":false,"showCircles":true,"interpolate":"linear","data":{"id":"3","label":"Unique NIST DSS requirements"},"valueAxis":"ValueAxis-2"}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{"customLabel":"Alerts"}},{"id":"2","enabled":true,"type":"date_histogram","schema":"segment","params":{"field":"timestamp","timeRange":{"from":"now-1h","to":"now","mode":"quick"},"useNormalizedEsInterval":true,"interval":"auto","time_zone":"Europe/Berlin","drop_partials":false,"customInterval":"2h","min_doc_count":1,"extended_bounds":{}}},{"id":"3","enabled":true,"type":"cardinality","schema":"metric","params":{"field":"rule.nist_800_53","customLabel":"Unique NIST DSS requirements"}},{"id":"4","enabled":true,"type":"count","schema":"radius","params":{}}]}',
uiStateJSON: '{"vis":{"legendOpen":false}}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Overview-NIST-Agents',
_source: {
title: 'Agents',
visState:
'{"title":"Agents","type":"pie","params":{"type":"pie","addTooltip":true,"addLegend":true,"legendPosition":"right","isDonut":false},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"agent.name","size":10,"order":"desc","orderBy":"1"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Overview-NIST-Requirements-by-agent',
_source: {
title: 'Requirements by agent',
visState:
'{"title":"Requirements by agent","type":"histogram","params":{"type":"histogram","grid":{"categoryLines":false,"style":{"color":"#eee"}},"categoryAxes":[{"id":"CategoryAxis-1","type":"category","position":"bottom","show":true,"style":{},"scale":{"type":"linear"},"labels":{"show":true,"truncate":100,"rotate":0},"title":{}}],"valueAxes":[{"id":"ValueAxis-1","name":"LeftAxis-1","type":"value","position":"left","show":true,"style":{},"scale":{"type":"linear","mode":"normal"},"labels":{"show":true,"rotate":0,"filter":false,"truncate":100},"title":{"text":"Count"}}],"seriesParams":[{"show":"true","type":"histogram","mode":"stacked","data":{"label":"Count","id":"1"},"valueAxis":"ValueAxis-1","drawLinesBetweenPoints":true,"showCircles":true}],"addTooltip":true,"addLegend":true,"legendPosition":"right","times":[],"addTimeMarker":false,"radiusRatio":51},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"segment","params":{"field":"rule.nist_800_53","size":5,"order":"desc","orderBy":"1","customLabel":"Requirements"}},{"id":"3","enabled":true,"type":"terms","schema":"group","params":{"field":"agent.name","size":5,"order":"desc","orderBy":"1"}}]}',
uiStateJSON: '{}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
},
_type: 'visualization'
},
{
_id: 'Wazuh-App-Overview-NIST-Last-alerts',
_type: 'visualization',
_source: {
title: 'Last alerts',
visState:
'{"title":"Last alerts","type":"table","params":{"perPage":10,"showPartialRows":false,"showMeticsAtAllLevels":false,"sort":{"columnIndex":null,"direction":null},"showTotal":false,"totalFunc":"sum"},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"bucket","params":{"field":"agent.name","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":50,"order":"desc","orderBy":"1","customLabel":"Agent name"}},{"id":"3","enabled":true,"type":"terms","schema":"bucket","params":{"field":"rule.nist_800_53","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":10,"order":"desc","orderBy":"1","customLabel":"Requirement"}},{"id":"4","enabled":true,"type":"terms","schema":"bucket","params":{"field":"rule.description","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":10,"order":"desc","orderBy":"1","customLabel":"Rule description"}}]}',
uiStateJSON:
'{"vis":{"params":{"sort":{"columnIndex":3,"direction":"desc"}}}}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
}
},
{
_id: 'Wazuh-App-Overview-NIST-Alerts-summary',
_type: 'visualization',
_source: {
title: 'Alerts summary',
visState:
'{"title":"Alerts summary","type":"table","params":{"perPage":10,"showPartialRows":false,"showMeticsAtAllLevels":false,"sort":{"columnIndex":3,"direction":"desc"},"showTotal":false,"totalFunc":"sum"},"aggs":[{"id":"1","enabled":true,"type":"count","schema":"metric","params":{}},{"id":"2","enabled":true,"type":"terms","schema":"bucket","params":{"field":"agent.name","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":50,"order":"desc","orderBy":"1","customLabel":"Agent name"}},{"id":"3","enabled":true,"type":"terms","schema":"bucket","params":{"field":"rule.nist_800_53","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":10,"order":"desc","orderBy":"1","customLabel":"Requirement"}},{"id":"4","enabled":true,"type":"terms","schema":"bucket","params":{"field":"rule.description","otherBucket":false,"otherBucketLabel":"Other","missingBucket":false,"missingBucketLabel":"Missing","size":10,"order":"desc","orderBy":"1","customLabel":"Rule description"}}]}',
uiStateJSON:
'{"vis":{"params":{"sort":{"columnIndex":3,"direction":"desc"}}}}',
description: '',
version: 1,
kibanaSavedObjectMeta: {
searchSourceJSON:
'{"index":"wazuh-alerts","filter":[],"query":{"query":"","language":"lucene"}}'
}
}
}
];

View File

@ -12,6 +12,8 @@
export const defaultExt = {
pci: true,
gdpr: true,
hipaa: true,
nist: true,
audit: true,
oscap: false,
ciscat: false,

View File

@ -108,7 +108,7 @@ export class ElasticWrapper {
* @param {*} title
* @param {*} id
*/
async createMonitoringIndexPattern(title, id) {
async createMonitoringIndexPattern(title, id, namespace = undefined) {
try {
if (!title)
return Promise.reject(
@ -126,7 +126,8 @@ export class ElasticWrapper {
'[{"name":"timestamp","type":"date","count":0,"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"name":"_id","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":false},{"name":"_index","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":false},{"name":"_score","type":"number","count":0,"scripted":false,"searchable":false,"aggregatable":false,"readFromDocValues":false},{"name":"_source","type":"_source","count":0,"scripted":false,"searchable":false,"aggregatable":false,"readFromDocValues":false},{"name":"_type","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":false},{"name":"dateAdd","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"group","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"host","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"name":"id","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"name":"ip","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"name":"lastKeepAlive","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"cluster.name","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"mergedSum","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"configSum","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"node_name","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"manager","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"manager_host","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"name","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"name":"os.arch","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"os.codename","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"os.major","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"os.name","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"os.platform","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"os.uname","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"os.version","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false},{"name":"status","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":true,"readFromDocValues":true},{"name":"version","type":"string","count":0,"scripted":false,"searchable":true,"aggregatable":false,"readFromDocValues":false}]',
title: title,
timeFieldName: 'timestamp'
}
},
namespace
}
});
@ -136,31 +137,6 @@ export class ElasticWrapper {
}
}
/**
* Creates the .wazuh-version index with a custom configuration.
* @param {*} config
*/
async createWazuhVersionIndex(configuration) {
try {
if (!configuration)
return Promise.reject(
new Error('No valid configuration for create .wazuh-version index')
);
const data = await this.elasticRequest.callWithInternalUser(
'indices.create',
{
index: '.wazuh-version',
body: configuration
}
);
return data;
} catch (error) {
return Promise.reject(error);
}
}
/**
* Creates the .wazuh index with a custom configuration.
* @param {*} config
@ -187,23 +163,16 @@ export class ElasticWrapper {
}
/**
* Inserts configuration on .wazuh-version index
* @param {*} configuration
* Delete .wazuh-version index if exists
*/
async insertWazuhVersionConfiguration(configuration) {
async deleteWazuhVersionIndex() {
try {
if (!configuration)
return Promise.reject(
new Error('No valid configuration for create .wazuh-version index')
);
const data = await this.elasticRequest.callWithInternalUser('create', {
index: '.wazuh-version',
type: '_doc',
id: 1,
body: configuration
});
const data = await this.elasticRequest.callWithInternalUser(
'indices.delete',
{
index: '.wazuh-version'
}
);
return data;
} catch (error) {
return Promise.reject(error);
@ -417,78 +386,19 @@ export class ElasticWrapper {
}
}
/**
* Get the .wazuh-version index
*/
async getWazuhVersionIndex() {
try {
const data = await this.elasticRequest.callWithInternalUser('get', {
index: '.wazuh-version',
type: '_doc',
id: '1'
});
return data;
} catch (error) {
return Promise.reject(error);
}
}
/**
* Updates lastRestart field on .wazuh-version index
* @param {*} version
* @param {*} revision
*/
async updateWazuhVersionIndexLastRestart(version, revision) {
try {
if (!version || !revision)
return Promise.reject(new Error('No valid version or revision given'));
const data = await this.elasticRequest.callWithInternalUser('update', {
index: '.wazuh-version',
type: '_doc',
id: 1,
body: {
doc: {
'app-version': version,
revision: revision,
lastRestart: new Date().toISOString() // Indice exists so we update the lastRestarted date only
}
}
});
return data;
} catch (error) {
return Promise.reject(error);
}
}
/**
* Get .wazuh-version index
*/
async getWazuhVersionIndexAsSearch() {
try {
const data = await this.elasticRequest.callWithInternalUser('search', {
index: '.wazuh-version',
type: '_doc'
});
return data;
} catch (error) {
return Promise.reject(error);
}
}
/**
*
* @param {*} payload
*/
async searchWazuhAlertsWithPayload(payload) {
async searchWazuhAlertsWithPayload(payload, namespace) {
try {
if (!payload) return Promise.reject(new Error('No valid payload given'));
const pattern = payload.pattern;
delete payload.pattern;
const fullPattern = await this.getIndexPatternUsingGet(pattern);
const fullPattern = await this.getIndexPatternUsingGet(
pattern,
namespace
);
const title =
(((fullPattern || {})._source || {})['index-pattern'] || {}).title ||
@ -835,14 +745,17 @@ export class ElasticWrapper {
* Get an index pattern by name and/or id
* @param {*} id Could be id and/or title
*/
async getIndexPatternUsingGet(id) {
async getIndexPatternUsingGet(id, namespace) {
try {
if (!id) return Promise.reject(new Error('No valid id given'));
let idQuery = id.includes('index-pattern:') ? id : 'index-pattern:' + id;
if (namespace && namespace !== 'default') {
idQuery = `${namespace}:${idQuery}`;
}
const data = await this.elasticRequest.callWithInternalUser('get', {
index: this.WZ_KIBANA_INDEX,
type: '_doc',
id: id.includes('index-pattern:') ? id : 'index-pattern:' + id
id: idQuery
});
return data;
@ -983,13 +896,12 @@ export class ElasticWrapper {
}
/**
* Prevent from using types, reindex .wazuh and .wazuh-version indices
* Prevent from using types, reindex .wazuh index
*/
async reindexAppIndices() {
try {
const appIndices = [
{ value: '.wazuh', copy: '.6x-wazuh', result: 'fail' },
{ value: '.wazuh-version', copy: '.6x-wazuh-version', result: 'fail' }
{ value: '.wazuh', copy: '.6x-wazuh', result: 'fail' }
];
for (const index of appIndices) {
try {

View File

@ -54,7 +54,8 @@ export async function checkKnownFields(
if (valid.length === 4) {
list.push({
id: index._id.split('index-pattern:')[1],
title: index._source['index-pattern'].title
title: index._source['index-pattern'].title,
namespace: index._source.namespace
});
}
}
@ -68,7 +69,9 @@ export async function checkKnownFields(
);
const defaultExists = list.filter(
item => item.title === defaultIndexPattern
item =>
item.title === defaultIndexPattern &&
typeof item.namespace === 'undefined'
);
if (defaultIndexPattern && defaultExists.length === 0) {
@ -126,7 +129,10 @@ export async function checkKnownFields(
`Refreshing known fields for "index-pattern:${item.title}"`,
'debug'
);
await wzWrapper.updateIndexPatternKnownFields('index-pattern:' + item.id);
const prefix = item.namespace
? `${item.namespace}:index-pattern:`
: 'index-pattern:';
await wzWrapper.updateIndexPatternKnownFields(`${prefix}${item.id}`);
}
!quiet && log('initialize', 'App ready to be used.', 'info');

View File

@ -17,8 +17,6 @@ const needRestartFields = [
'pattern',
'wazuh.shards',
'wazuh.replicas',
'wazuh-version.shards',
'wazuh-version.replicas',
'wazuh.monitoring.enabled',
'wazuh.monitoring.frequency',
'wazuh.monitoring.shards',

View File

@ -0,0 +1,322 @@
/*
* Wazuh app - Agent configuration request objet for exporting it
* Copyright (C) 2015-2019 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
export const AgentConfiguration = {
configurations: [
{
title: 'Main configurations',
sections: [
{
subtitle: 'Global configuration',
desc: 'Logging settings that apply to the agent',
config: [{ component: 'com', configuration: 'logging' }],
labels: [
{
plain: 'Write internal logs in plain text',
json: 'Write internal logs in JSON format',
server: 'List of managers to connect'
}
]
},
{
subtitle: 'Communication',
docuLink:
'https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/client.html',
desc: 'Settings related to the connection with the manager',
config: [{ component: 'agent', configuration: 'client' }],
labels: [
{
crypto_method: 'Method used to encrypt communications',
auto_restart:
'Auto-restart the agent when receiving valid configuration from manager',
notify_time:
'Time (in seconds) between agent checkings to the manager',
'time-reconnect':
'Time (in seconds) before attempting to reconnect',
server: 'List of managers to connect',
'config-profile': 'Configuration profiles',
remote_conf: 'Remote configuration is enabled'
}
]
},
{
subtitle: 'Anti-flooding settings',
docuLink:
'https://documentation.wazuh.com/current/user-manual/capabilities/antiflooding.html',
desc: 'Agent bucket parameters to avoid event flooding',
config: [{ component: 'agent', configuration: 'buffer' }],
labels: [
{
disabled: 'Buffer enabled',
queue_size: 'Queue size',
events_per_second: 'Events per second'
}
]
},
{
subtitle: 'Labels',
docuLink:
'https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/labels.html',
desc: 'User-defined information about the agent included in alerts',
config: [{ component: 'agent', configuration: 'labels' }]
}
]
},
{
title: 'Auditing and policy monitoring',
sections: [
{
subtitle: 'Policy monitoring',
docuLink:
'https://documentation.wazuh.com/current/pci-dss/policy-monitoring.html',
desc:
'Configuration to ensure compliance with security policies, standards and hardening guides',
config: [{ component: 'syscheck', configuration: 'rootcheck' }],
wodle: [{ name: 'sca' }],
labels: [
{
disabled: 'Policy monitoring service enabled',
base_directory: 'Base directory',
rootkit_files: 'Rootkit files database path',
rootkit_trojans: 'Rootkit trojans database path',
scanall: 'Scan the entire system',
skip_nfs: 'Skip scan on CIFS/NFS mounts',
frequency: 'Frequency (in seconds) to run the scan',
check_dev: 'Check /dev path',
check_files: 'Check files',
check_if: 'Check network interfaces',
check_pids: 'Check processes IDs',
check_ports: 'Check network ports',
check_sys: 'Check anomalous system objects',
check_trojans: 'Check trojans',
check_unixaudit: 'Check UNIX audit',
system_audit: 'UNIX audit files paths',
enabled: 'Security configuration assessment enabled',
scan_on_start: 'Scan on start',
interval: 'Interval',
policies: 'Policies'
}
],
tabs: ['General', 'Security configuration assessment']
},
{
subtitle: 'OpenSCAP',
docuLink:
'https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/wodle-openscap.html',
desc:
'Configuration assessment and automation of compliance monitoring using SCAP checks',
wodle: [{ name: 'open-scap' }],
labels: [
{
content: 'Evaluations',
disabled: 'OpenSCAP integration enabled',
'scan-on-start': 'Scan on start',
interval: 'Interval between scan executions',
timeout: 'Timeout (in seconds) for scan executions'
}
]
},
{
subtitle: 'CIS-CAT',
docuLink:
'https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/wodle-ciscat.html',
desc: 'Configuration assessment using CIS scanner and SCAP checks',
wodle: [{ name: 'cis-cat' }],
labels: [
{
disabled: 'CIS-CAT integration enabled',
'scan-on-start': 'Scan on start',
interval: 'Interval between scan executions',
java_path: 'Path to Java executable directory',
ciscat_path: 'Path to CIS-CAT executable directory',
timeout: 'Timeout (in seconds) for scan executions',
content: 'Benchmarks'
}
]
}
]
},
{
title: 'System threats and incident response',
sections: [
{
subtitle: 'Osquery',
docuLink:
'https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/wodle-osquery.html',
desc:
'Expose an operating system as a high-performance relational database',
wodle: [{ name: 'osquery' }],
labels: [
{
disabled: 'Osquery integration enabled',
run_daemon: 'Auto-run the Osquery daemon',
add_labels: 'Use defined labels as decorators',
log_path: 'Path to the Osquery results log file',
config_path: 'Path to the Osquery configuration file'
}
]
},
{
subtitle: 'Inventory data',
docuLink:
'https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/wodle-syscollector.html',
desc:
'Gather relevant information about system OS, hardware, networking and packages',
wodle: [{ name: 'syscollector' }],
labels: [
{
disabled: 'Syscollector integration enabled',
'scan-on-start': 'Scan on start',
interval: 'Interval between system scans',
network: 'Scan network interfaces',
os: 'Scan operating system info',
hardware: 'Scan hardware info',
packages: 'Scan installed packages',
ports: 'Scan listening network ports',
ports_all: 'Scan all network ports',
processes: 'Scan current processes'
}
]
},
{
subtitle: 'Active response',
docuLink:
'https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/active-response.html',
desc: 'Active threat addressing by inmmediate response',
config: [{ component: 'com', configuration: 'active-response' }],
labels: [
{
disabled: 'Active response enabled',
ca_store: 'Use the following list of root CA certificates',
ca_verification: 'Validate WPKs using root CA certificate'
}
]
},
{
subtitle: 'Commands',
docuLink:
'https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/wodle-command.html',
desc: 'Configuration options of the Command wodle',
wodle: [{ name: 'command' }],
labels: [
{
disabled: 'Command enabled',
run_on_start: 'Run on start',
ignore_output: 'Ignore command output',
skip_verification: 'Ignore checksum verification',
interval: 'Interval between executions',
tag: 'Command name',
command: 'Command to execute',
verify_md5: 'Verify MD5 sum',
verify_sha1: 'Verify SHA1 sum',
verify_sha256: 'Verify SHA256 sum'
}
]
},
{
subtitle: 'Docker listener',
docuLink:
'https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/wodle-docker.html',
desc:
'Monitor and collect the activity from Docker containers such as creation, running, starting, stopping or pausing events',
wodle: [{ name: 'docker-listener' }],
labels: [
{
disabled: 'Docker listener enabled',
run_on_start:
'Run the listener immediately when service is started',
interval: 'Waiting time to rerun the listener in case it fails',
attempts: 'Number of attempts to execute the listener'
}
]
}
]
},
{
title: 'Log data analysis',
sections: [
{
subtitle: 'Log collection',
docuLink:
'https://documentation.wazuh.com/current/user-manual/capabilities/log-data-collection/index.html',
desc:
'Log analysis from text files, Windows events or syslog outputs',
config: [
{
component: 'logcollector',
configuration: 'localfile',
filterBy: 'logformat'
},
{ component: 'logcollector', configuration: 'socket' }
],
labels: [
{
logformat: 'Log format',
log_format: 'Log format',
command: 'Run this command',
alias: 'Command alias',
ignore_binaries: 'Ignore binaries',
target: 'Redirect output to this socket',
frequency: 'Interval between command executions',
file: 'Log location',
location: 'Log location',
socket: 'Output sockets',
syslog: 'Syslog',
command: 'Command',
full_command: 'Full command',
audit: 'Audit'
}
],
options: { hideHeader: true }
},
{
subtitle: 'Integrity monitoring',
docuLink:
'https://documentation.wazuh.com/current/user-manual/reference/ossec-conf/syscheck.html',
desc:
'Identify changes in content, permissions, ownership, and attributes of files',
config: [
{ component: 'syscheck', configuration: 'syscheck', matrix: true }
],
tabs: ['General', 'Who data'],
labels: [
{
disabled: 'Integrity monitoring enabled',
frequency: 'Interval (in seconds) to run the integrity scan',
skip_nfs: 'Skip scan on CIFS/NFS mounts',
scan_on_start: 'Scan on start',
directories: 'Monitored directories',
nodiff: 'No diff directories',
ignore: 'Ignored files and directories',
restart_audit: 'Restart audit',
startup_healthcheck: 'Startup healthcheck'
}
],
opts: {
realtime: 'RT',
check_whodata: 'WD',
report_changes: 'Changes',
check_md5sum: 'MD5',
check_sha1sum: 'SHA1',
check_perm: 'Per.',
check_size: 'Size',
check_owner: 'Owner',
check_group: 'Group',
check_mtime: 'MT',
check_inode: 'Inode',
check_sha256sum: 'SHA256',
follow_symbolic_link: 'SL'
}
}
]
}
]
};

View File

@ -76,7 +76,10 @@ export class AuditRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const { buckets } = response.aggregations['3'];
return buckets.map(item => item.key);
} catch (error) {
@ -133,7 +136,10 @@ export class AuditRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const { buckets } = response.aggregations['3'];
const result = [];
@ -191,7 +197,10 @@ export class AuditRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const { buckets } = response.aggregations['2'];
return buckets.map(item => ({

View File

@ -58,7 +58,10 @@ export class GdprRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const aggArray = response.aggregations['2'].buckets;
return aggArray.map(item => item.key);
@ -122,7 +125,10 @@ export class GdprRequest {
requirement +
'"';
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const { buckets } = response.aggregations['2'];
const result = [];
for (const bucket of buckets) {

View File

@ -54,7 +54,10 @@ export class OverviewRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const aggArray = response.aggregations['2'].buckets;
return aggArray.map(item => item.key);

View File

@ -58,7 +58,10 @@ export class PciRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const aggArray = response.aggregations['2'].buckets;
return aggArray
@ -137,7 +140,10 @@ export class PciRequest {
requirement +
'"';
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const { buckets } = response.aggregations['2'];
const result = [];

View File

@ -56,7 +56,10 @@ export class RootcheckRequest {
base.query.bool.must[0].query_string.query +
' AND "rootkit" AND "detected"';
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const aggArray = response.aggregations['2'].buckets;
const mapped = aggArray.map(item => item.key);
const result = [];
@ -102,7 +105,10 @@ export class RootcheckRequest {
' AND "process" AND "hidden"';
// "aggregations": { "1": { "value": 1 } }
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
return response &&
response.aggregations &&
@ -145,7 +151,10 @@ export class RootcheckRequest {
base.query.bool.must[0].query_string.query + ' AND "port" AND "hidden"';
// "aggregations": { "1": { "value": 1 } }
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
return response &&
response.aggregations &&

View File

@ -55,7 +55,10 @@ export class SyscheckRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const { buckets } = response.aggregations['2'];
return buckets.map(item => item.key);
@ -100,7 +103,10 @@ export class SyscheckRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const { buckets } = response.aggregations['2'];
const result = [];
@ -159,7 +165,10 @@ export class SyscheckRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const { buckets } = response.aggregations['2'];
return buckets
@ -210,7 +219,10 @@ export class SyscheckRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const { buckets } = response.aggregations['2'];
return buckets

View File

@ -50,6 +50,16 @@ export const TabDescription = {
description:
'General Data Protection Regulation (GDPR) sets guidelines for processing of personal data.'
},
hipaa: {
title: 'HIPAA',
description:
'Health Insurance Portability and Accountability Act of 1996 (HIPAA) provides data privacy and security provisions for safeguarding medical information.'
},
nist: {
title: 'NIST 800-53',
description:
'National Institute of Standards and Technology Special Publication 800-53 (NIST 800-53) sets guidelines for federal information systems.'
},
ciscat: {
title: 'CIS-CAT',
description:

View File

@ -61,7 +61,10 @@ export class VulnerabilityRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const aggArray = response.aggregations['2'].buckets;
return aggArray.map(item => item.key);
@ -95,7 +98,10 @@ export class VulnerabilityRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const aggArray = response.aggregations['2'].buckets;
return aggArray.map(item => item.key);
@ -140,7 +146,10 @@ export class VulnerabilityRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
//aggregations: { '1': { value: 2 } } }
return response &&
@ -186,7 +195,10 @@ export class VulnerabilityRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const { buckets } = response.aggregations['2'];
return buckets.map(item => ({ package: item.key, severity: severity }));
@ -238,7 +250,10 @@ export class VulnerabilityRequest {
}
});
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(
base,
this.namespace
);
const { buckets } = response.aggregations['2'];
return buckets.map(item => ({

View File

@ -60,6 +60,24 @@ export function WazuhApiRoutes(server) {
}
});
// Return a NIST 800-53 requirement description
server.route({
method: 'GET',
path: '/api/nist/{requirement}',
handler(req, reply) {
return ctrl.getNistRequirement(req, reply);
}
});
// Return a HIPAA requirement description
server.route({
method: 'GET',
path: '/api/hipaa/{requirement}',
handler(req, reply) {
return ctrl.getHipaaRequirement(req, reply);
}
});
// Force fetch data to be inserted on wazuh-monitoring indices
server.route({
method: 'GET',
@ -96,6 +114,24 @@ export function WazuhApiRoutes(server) {
}
});
// Useful to check cookie consistence
server.route({
method: 'GET',
path: '/api/timestamp',
handler(req, res) {
return ctrl.getTimeStamp(req, res);
}
});
// Return Wazuh Appsetup info
server.route({
method: 'GET',
path: '/api/setup',
handler(req, res) {
return ctrl.getSetupInfo(req, res);
}
});
// Return basic information of syscollector for given agent
server.route({
method: 'GET',

View File

@ -75,24 +75,6 @@ export function WazuhElasticRouter(server) {
}
});
// Return Wazuh Appsetup info
server.route({
method: 'GET',
path: '/elastic/setup',
handler(req, res) {
return ctrl.getSetupInfo(req, res);
}
});
// Useful to check cookie consistence
server.route({
method: 'GET',
path: '/elastic/timestamp',
handler(req, res) {
return ctrl.getTimeStamp(req, res);
}
});
// Fetch alerts directly from Elasticsearch
server.route({
method: 'POST',

View File

@ -99,71 +99,4 @@ describe('wazuh-elastic', () => {
res.body.data.should.be.eql('Index pattern found');
});
});
/*it('GET /elastic/top/{mode}/{cluster}/{field}/{pattern}', async () => {
throw Error('Test not implemented...')
})*/
describe('Checking .wazuh-version index', () => {
it('GET /elastic/setup', async () => {
const res = await needle(
'get',
`${kibanaServer}:5601/elastic/setup`,
{},
headers
);
res.body.statusCode.should.be.eql(200);
res.body.data.should.be.a('object');
res.body.data.name.should.be.eql('Wazuh App');
res.body.data['app-version'].should.be.eql(version);
res.body.data.revision.should.be.eql(revision);
res.body.data.installationDate.should.be.a('string');
res.body.data.lastRestart.should.be.a('string');
});
it('GET /elastic/timestamp', async () => {
const res = await needle(
'get',
`${kibanaServer}:5601/elastic/timestamp`,
{},
headers
);
res.body.installationDate.should.be.a('string');
res.body.lastRestart.should.be.a('string');
});
it('POST /elastic/alerts full parameters', async () => {
const res = await needle(
'POST',
`${kibanaServer}:5601/elastic/alerts`,
{
pattern: 'wazuh-alerts-3.x-*',
'agent.id': '000',
'rule.groups': 'ossec',
'manager.name': 'master',
'cluster.name': 'wazuh',
size: 1
},
headers
);
const alerts = res.body.alerts;
alerts.should.be.a('array');
alerts.length.should.be.eql(1);
alerts[0].agent.id.should.be.eql('000');
alerts[0].rule.groups.includes('ossec').should.be.eql(true);
alerts[0].manager.name.should.be.eql('master');
alerts[0].cluster.name.should.be.eql('wazuh');
});
it('POST /elastic/alerts no parameters', async () => {
const res = await needle(
'POST',
`${kibanaServer}:5601/elastic/alerts`,
{},
headers
);
res.body.alerts.should.be.a('array');
res.body.alerts.length.should.be.eql(10);
});
});
});

View File

@ -625,6 +625,14 @@ export const apiRequestList = [
name: '/rules/pci',
args: []
},
{
name: '/rules/hipaa',
args: []
},
{
name: '/rules/nist-800-53',
args: []
},
{
name: '/syscheck/:agent_id',
args: [

View File

@ -36,6 +36,8 @@ export const KeyEquivalence = {
file: 'File',
gdpr: 'GDPR',
pci: 'PCI',
hipaa: 'HIPAA',
'nist-800-53': 'NIST 800-53',
cis: 'CIS',
event: 'Event',
groups: 'Groups',