Skip to content

Commit

Permalink
Replace discover Office 365 (#6290)
Browse files Browse the repository at this point in the history
* Replace discover

* Add changelog

* Stringify geo_point type field

---------

Co-authored-by: Julio César Biset <43619595+jbiset@users.noreply.github.com>
  • Loading branch information
yenienserrano and jbiset committed Feb 9, 2024
1 parent 943786e commit 3de2cc0
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 146 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ All notable changes to the Wazuh app project will be documented in this file.

### Changed

- Removed embedded discover [#6120](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6120) [#6235](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6235) [#6254](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6254) [#6285](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6285) [#6275](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6275) [#6287](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6287)
- Removed embedded discover [#6120](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6120) [#6235](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6235) [#6254](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6254) [#6285](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6285) [#6290](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6290) [#6275](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6275) [#6287](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6287)
- Develop logic of a new index for the fim module [#6227](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6227)
- Allow editing groups for an agent from Endpoints Summary [#6250](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6250)

Expand Down
312 changes: 168 additions & 144 deletions plugins/main/public/components/common/data-grid/data-grid-service.ts
Original file line number Diff line number Diff line change
@@ -1,163 +1,187 @@
import { SearchResponse } from "../../../../../../src/core/server";
import { SearchResponse } from '../../../../../../src/core/server';
import * as FileSaver from '../../../services/file-saver';
import { beautifyDate } from "../../agents/vuls/inventory/lib";
import { SearchParams, search } from "../search-bar/search-bar-service";
import { IFieldType, IndexPattern } from "../../../../../../src/plugins/data/common";
import { beautifyDate } from '../../agents/vuls/inventory/lib';
import { SearchParams, search } from '../search-bar/search-bar-service';
import { IFieldType } from '../../../../../../src/plugins/data/common';
export const MAX_ENTRIES_PER_QUERY = 10000;
import { EuiDataGridColumn } from '@elastic/eui';

export const parseData = (resultsHits: SearchResponse['hits']['hits']): any[] => {
const data = resultsHits.map((hit) => {
if (!hit) {
return {}
}
const source = hit._source as object;
const data = {
...source,
_id: hit._id,
_index: hit._index,
_type: hit._type,
_score: hit._score,
};
return data;
});
export const parseData = (
resultsHits: SearchResponse['hits']['hits'],
): any[] => {
const data = resultsHits.map(hit => {
if (!hit) {
return {};
}
const source = hit._source as object;
const data = {
...source,
_id: hit._id,
_index: hit._index,
_type: hit._type,
_score: hit._score,
};
return data;
}

});
return data;
};

export const getFieldFormatted = (rowIndex, columnId, indexPattern, rowsParsed) => {
const field = indexPattern.fields.find((field) => field.name === columnId);
let fieldValue = null;
if (columnId.includes('.')) {
// when the column is a nested field. The column could have 2 to n levels
// get dinamically the value of the nested field
const nestedFields = columnId.split('.');
fieldValue = rowsParsed[rowIndex];
nestedFields.forEach((field) => {
if (fieldValue) {
fieldValue = fieldValue[field];
}
});
export const getFieldFormatted = (
rowIndex,
columnId,
indexPattern,
rowsParsed,
) => {
const field = indexPattern.fields.find(field => field.name === columnId);
let fieldValue = null;
if (columnId.includes('.')) {
// when the column is a nested field. The column could have 2 to n levels
// get dinamically the value of the nested field
const nestedFields = columnId.split('.');
fieldValue = rowsParsed[rowIndex];
nestedFields.forEach(field => {
if (fieldValue) {
fieldValue = fieldValue[field];
}
});
} else {
const rowValue = rowsParsed[rowIndex];
// when not exist the column in the row value then the value is null
if (!rowValue.hasOwnProperty(columnId)) {
fieldValue = null;
} else {
const rowValue = rowsParsed[rowIndex];
// when not exist the column in the row value then the value is null
if(!rowValue.hasOwnProperty(columnId)){
fieldValue = null;
}else{
fieldValue = rowValue[columnId]?.formatted || rowValue[columnId];
}
}
// when fieldValue is null or undefined then return a empty string
if (fieldValue === null || fieldValue === undefined) {
return '';
}
// if is date field
if (field?.type === 'date') {
// @ts-ignore
fieldValue = beautifyDate(fieldValue);
fieldValue = rowValue[columnId]?.formatted || rowValue[columnId];
}
return fieldValue;
}
}
// when fieldValue is null or undefined then return a empty string
if (fieldValue === null || fieldValue === undefined) {
return '';
}
// if is date field
if (field?.type === 'date') {
// @ts-ignore
fieldValue = beautifyDate(fieldValue);
}

// if is geo_point field then convert to string to appear in the Discover table
if (field?.type === 'geo_point') {
// @ts-ignore
fieldValue = JSON.stringify(fieldValue);
}
return fieldValue;
};

// receive search params
export const exportSearchToCSV = async (params: SearchParams): Promise<void> => {
const DEFAULT_MAX_SIZE_PER_CALL = 1000;
const { indexPattern, filters = [], query, sorting, fields, pagination } = params;
// when the pageSize is greater than the default max size per call (10000)
// then we need to paginate the search
const mustPaginateSearch = pagination?.pageSize && pagination?.pageSize > DEFAULT_MAX_SIZE_PER_CALL;
const pageSize = mustPaginateSearch ? DEFAULT_MAX_SIZE_PER_CALL : pagination?.pageSize;
const totalHits = pagination?.pageSize || DEFAULT_MAX_SIZE_PER_CALL;
let pageIndex = params.pagination?.pageIndex || 0;
let hitsCount = 0;
let allHits = [];
let searchResults;
if (mustPaginateSearch) {
// paginate the search
while (hitsCount < totalHits &&  hitsCount < MAX_ENTRIES_PER_QUERY) {
const searchParams = {
indexPattern,
filters,
query,
pagination: {
pageIndex,
pageSize,
},
sorting,
fields,
};
searchResults = await search(searchParams);
allHits = allHits.concat(searchResults.hits.hits);
hitsCount = allHits.length;
pageIndex++;
}
} else {
searchResults = await search(params);
allHits = searchResults.hits.hits;
export const exportSearchToCSV = async (
params: SearchParams,
): Promise<void> => {
const DEFAULT_MAX_SIZE_PER_CALL = 1000;
const {
indexPattern,
filters = [],
query,
sorting,
fields,
pagination,
} = params;
// when the pageSize is greater than the default max size per call (10000)
// then we need to paginate the search
const mustPaginateSearch =
pagination?.pageSize && pagination?.pageSize > DEFAULT_MAX_SIZE_PER_CALL;
const pageSize = mustPaginateSearch
? DEFAULT_MAX_SIZE_PER_CALL
: pagination?.pageSize;
const totalHits = pagination?.pageSize || DEFAULT_MAX_SIZE_PER_CALL;
let pageIndex = params.pagination?.pageIndex || 0;
let hitsCount = 0;
let allHits = [];
let searchResults;
if (mustPaginateSearch) {
// paginate the search
while (hitsCount < totalHits && hitsCount < MAX_ENTRIES_PER_QUERY) {
const searchParams = {
indexPattern,
filters,
query,
pagination: {
pageIndex,
pageSize,
},
sorting,
fields,
};
searchResults = await search(searchParams);
allHits = allHits.concat(searchResults.hits.hits);
hitsCount = allHits.length;
pageIndex++;
}

const resultsFields = fields;
const data = allHits.map((hit) => {
// check if the field type is a date
const dateFields = indexPattern.fields.getByType('date');
const dateFieldsNames = dateFields.map((field) => field.name);
const flattenHit = indexPattern.flattenHit(hit);
// replace the date fields with the formatted date
dateFieldsNames.forEach((field) => {
if (flattenHit[field]) {
flattenHit[field] = beautifyDate(flattenHit[field]);
}
});
return flattenHit;
} else {
searchResults = await search(params);
allHits = searchResults.hits.hits;
}

const resultsFields = fields;
const data = allHits.map(hit => {
// check if the field type is a date
const dateFields = indexPattern.fields.getByType('date');
const dateFieldsNames = dateFields.map(field => field.name);
const flattenHit = indexPattern.flattenHit(hit);
// replace the date fields with the formatted date
dateFieldsNames.forEach(field => {
if (flattenHit[field]) {
flattenHit[field] = beautifyDate(flattenHit[field]);
}
});
return flattenHit;
});

if (!resultsFields || resultsFields.length === 0){
return;
}
if (!resultsFields || resultsFields.length === 0) {
return;
}

if (!data || data.length === 0)
return;
if (!data || data.length === 0) return;

const parsedData = data.map((row) => {
const parsedRow = resultsFields?.map((field) => {
const value = row[field];
if (value === undefined || value === null) {
return '';
}
if (typeof value === 'object') {
return JSON.stringify(value);
}
return `"${value}"`;
});
return parsedRow?.join(',');
}).join('\n');
const parsedData = data
.map(row => {
const parsedRow = resultsFields?.map(field => {
const value = row[field];
if (value === undefined || value === null) {
return '';
}
if (typeof value === 'object') {
return JSON.stringify(value);
}
return `"${value}"`;
});
return parsedRow?.join(',');
})
.join('\n');

// create a csv file using blob
const blobData = new Blob(
[
`${resultsFields?.join(',')}\n${parsedData}`
],
{ type: 'text/csv' }
);
// create a csv file using blob
const blobData = new Blob([`${resultsFields?.join(',')}\n${parsedData}`], {
type: 'text/csv',
});

if (blobData) {
// @ts-ignore
FileSaver?.saveAs(blobData, `events-${new Date().toISOString()}.csv`);
}
}
if (blobData) {
// @ts-ignore
FileSaver?.saveAs(blobData, `events-${new Date().toISOString()}.csv`);
}
};

export const parseColumns = (fields: IFieldType[]): EuiDataGridColumn[] => {
// remove _source field becuase is a object field and is not supported
fields = fields.filter((field) => field.name !== '_source');
return fields.map((field) => {
return {
...field,
id: field.name,
display: field.name,
schema: field.type,
actions: {
showHide: true,
},
};
}) || [];
}
// remove _source field becuase is a object field and is not supported
fields = fields.filter(field => field.name !== '_source');
return (
fields.map(field => {
return {
...field,
id: field.name,
display: field.name,
schema: field.type,
actions: {
showHide: true,
},
};
}) || []
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { vulnerabilitiesColumns } from '../../overview/vulnerabilities/events/vu
import { DashboardFim } from '../../overview/fim/dashboard/dashboard';
import { InventoryFim } from '../../overview/fim/inventory/inventory';
import React from 'react';
import { office365Columns } from '../../overview/office-panel/events/office-365-columns';
import { fileIntegrityMonitoringColumns } from '../../overview/fim/events/file-integrity-monitoring-columns';
import { configurationAssessmentColumns } from '../../agents/sca/events/configuration-assessment-columns';

Expand Down Expand Up @@ -151,7 +152,15 @@ export const ModulesDefaults = {
buttons: [ButtonModuleExploreAgent],
component: withModuleNotForAgent(OfficePanel),
},
{ ...EventsTab, component: withModuleNotForAgent(Events) },
{
...renderDiscoverTab(DEFAULT_INDEX_PATTERN, office365Columns),
component: withModuleNotForAgent(() => (
<WazuhDiscover
indexPatternName={DEFAULT_INDEX_PATTERN}
tableColumns={office365Columns}
/>
)),
},
],
availableFor: ['manager'],
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { tDataGridColumn } from '../../../common/data-grid';

export const office365Columns: tDataGridColumn[] = [
{
id: 'data.office365.Subscription',
},
{
id: 'data.office365.Operation',
},
{
id: 'data.office365.UserId',
},
{
id: 'data.office365.ClientIP',
},
{
id: 'rule.level',
},
{
id: 'rule.id',
},
];

0 comments on commit 3de2cc0

Please sign in to comment.