Skip to content

Commit

Permalink
Fix custom spaces for 3.10 (#1600)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jesús Ángel committed Jul 12, 2019
1 parent ed662ee commit 598a545
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 51 deletions.
101 changes: 80 additions & 21 deletions server/controllers/wazuh-elastic.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,9 @@ 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'
Expand Down Expand Up @@ -308,6 +309,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();
Expand All @@ -325,9 +329,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 !== '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);
Expand Down Expand Up @@ -360,15 +369,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',
Expand All @@ -394,17 +424,36 @@ export class WazuhElasticCtrl {
) {
const defaultStr = aux_source.kibanaSavedObjectMeta.searchSourceJSON;

defaultStr.includes('wazuh-monitoring')
? (aux_source.kibanaSavedObjectMeta.searchSourceJSON = defaultStr.replace(
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] === '*'
monitoringPattern[monitoringPattern.length - 1] === '*' ||
(namespace && namespace !== 'default')
? monitoringPattern
: monitoringPattern + '*'
))
: (aux_source.kibanaSavedObjectMeta.searchSourceJSON = defaultStr.replace(
);
} else {
aux_source.kibanaSavedObjectMeta.searchSourceJSON = defaultStr.replace(
/wazuh-alerts/g,
id
));
);
}

}

// Replace index-pattern for selector visualizations
Expand Down Expand Up @@ -536,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);
Expand Down Expand Up @@ -568,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 };
Expand Down
13 changes: 13 additions & 0 deletions server/controllers/wazuh-reporting.js
Original file line number Diff line number Diff line change
Expand Up @@ -1626,6 +1626,19 @@ export class WazuhReportingCtrl {
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'
Expand Down
18 changes: 11 additions & 7 deletions server/lib/elastic-wrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export class ElasticWrapper {
* @param {*} title
* @param {*} id
*/
async createMonitoringIndexPattern(title, id) {
async createMonitoringIndexPattern(title, id, namespace = undefined) {
try {
if (!title)
return Promise.reject(
Expand All @@ -125,7 +125,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
}
});

Expand Down Expand Up @@ -387,12 +388,12 @@ export class ElasticWrapper {
*
* @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 ||
Expand Down Expand Up @@ -724,14 +725,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;
Expand Down
10 changes: 7 additions & 3 deletions server/lib/refresh-known-fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
});
}
}
Expand All @@ -68,7 +69,7 @@ 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) {
Expand Down Expand Up @@ -126,7 +127,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');
Expand Down
15 changes: 12 additions & 3 deletions server/reporting/audit-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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 = [];
Expand Down Expand Up @@ -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 => ({
Expand Down
10 changes: 8 additions & 2 deletions server/reporting/gdpr-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
5 changes: 4 additions & 1 deletion server/reporting/overview-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 8 additions & 2 deletions server/reporting/pci-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 = [];
Expand Down
Loading

0 comments on commit 598a545

Please sign in to comment.