Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix IPV6 visualizations #5471

Merged
merged 30 commits into from
Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2488615
add ipv6 service
Tostti May 19, 2023
87b1b89
add test for service
Tostti May 19, 2023
4b3f253
Fix issue in agents-table
Tostti May 19, 2023
5d9abd4
fix issue in agents-info
Tostti May 19, 2023
c8af811
fix groups agents issue
Tostti May 19, 2023
0c9eed3
Fix width in groups agents
Tostti May 19, 2023
284de6a
use mapResponseItem
Tostti May 22, 2023
7395607
Add copy button to groups
Tostti May 22, 2023
84a12cf
Add copy button to info
Tostti May 22, 2023
c124839
fix for node list
Tostti May 22, 2023
9fa8501
Optimize code
Tostti May 22, 2023
7c55468
Fix styles
Tostti May 22, 2023
741d8f7
Edit changelog
Tostti May 22, 2023
2ae12d4
Edit changelog
Tostti May 22, 2023
9c781c9
Add imposter changes to test ipv6
Tostti May 22, 2023
c85dfad
Replace onMouseDown with onClick
Tostti May 22, 2023
3304863
Move copy buttons to the left
Tostti May 22, 2023
7ca7bbb
Merge branch '4.4' into 5464-fix-ipv6
Tostti May 22, 2023
65cd1de
fix: removed compressipv6 property of TableWzAPI
Desvelao May 26, 2023
9ff5433
feat: add tableLayout property to some tables and remove IPv6 address…
Desvelao May 26, 2023
2f0a20d
Merge branch '4.4' of https://github.com/wazuh/wazuh-kibana-app into …
Desvelao May 26, 2023
69f75e0
remove: remove unused service to IPv6 compression
Desvelao May 26, 2023
50cc973
revert: revert changes in TableWzAPI component
Desvelao May 26, 2023
5f94d96
add: add mocked responses to some syscollector endpoints
Desvelao May 26, 2023
8c688b2
remove: unwanted table columns properties
Desvelao May 26, 2023
ee10024
changelog: add pull request entry
Desvelao May 26, 2023
c499cb7
Merge branch '4.4' into 5464-fix-ipv6
AlexRuiz7 May 29, 2023
f767514
Fix imposter
yenienserrano Jun 2, 2023
30b0ab2
Merge branch '4.4' into 5464-fix-ipv6
Desvelao Jun 7, 2023
516fcad
Merge branch '4.4' into 5464-fix-ipv6
AlexRuiz7 Jun 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 43 additions & 26 deletions public/components/common/tables/table-with-search-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { WzSearchBar } from '../../wz-search-bar/';
import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types';
import { UI_LOGGER_LEVELS } from '../../../../common/constants';
import { getErrorOrchestrator } from '../../../react-services/common-services';
import { compressIPv6 } from '../../../services/ipv6-services';

export function TableWithSearchBar({
onSearch,
Expand All @@ -31,6 +32,7 @@ export function TableWithSearchBar({
tableProps = {},
reload,
endpoint,
compressipv6 = false,
...rest
}) {
const [loading, setLoading] = useState(false);
Expand Down Expand Up @@ -79,31 +81,46 @@ export function TableWithSearchBar({
}
}, [endpoint, reload]);

useEffect(function () {
(async () => {
try {
setLoading(true);
const { items, totalItems } = await onSearch(endpoint, filters, pagination, sorting);
setItems(items);
setTotalItems(totalItems);
} catch (error) {
setItems([]);
setTotalItems(0);
const options = {
context: `${TableWithSearchBar.name}.useEffect`,
level: UI_LOGGER_LEVELS.ERROR,
severity: UI_ERROR_SEVERITIES.BUSINESS,
error: {
error: error,
message: error.message || error,
title: `${error.name}: Error fetching items`,
},
};
getErrorOrchestrator().handleError(options);
}
setLoading(false);
})();
}, [filters, pagination, sorting]);
useEffect(
function () {
(async () => {
try {
setLoading(true);
let { items, totalItems } = await onSearch(
endpoint,
filters,
pagination,
sorting,
);
if (compressipv6) {
items.forEach(item => {
if (item.ip) {
item.ip = compressIPv6(item.ip);
}
});
Tostti marked this conversation as resolved.
Show resolved Hide resolved
}
setItems(items);
setTotalItems(totalItems);
} catch (error) {
setItems([]);
setTotalItems(0);
const options = {
context: `${TableWithSearchBar.name}.useEffect`,
level: UI_LOGGER_LEVELS.ERROR,
severity: UI_ERROR_SEVERITIES.BUSINESS,
error: {
error: error,
message: error.message || error,
title: `${error.name}: Error fetching items`,
},
};
getErrorOrchestrator().handleError(options);
}
setLoading(false);
})();
},
[filters, pagination, sorting],
);

useEffect(() => {
// This effect is triggered when the component is mounted because of how to the useEffect hook works.
Expand Down Expand Up @@ -136,7 +153,7 @@ export function TableWithSearchBar({
placeholder={searchBarPlaceholder}
{...searchBarProps}
/>
<EuiSpacer size="s" />
<EuiSpacer size='s' />
<EuiBasicTable
columns={tableColumns}
items={items}
Expand Down
48 changes: 36 additions & 12 deletions public/components/common/tables/table-wz-api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,19 +52,27 @@ export function TableWzAPI({
showReload?: boolean;
searchBarProps?: any;
reload?: boolean;
compressipv6?: boolean;
}) {
const [totalItems, setTotalItems] = useState(0);
const [filters, setFilters] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const onFiltersChange = (filters) =>
typeof rest.onFiltersChange === 'function' ? rest.onFiltersChange(filters) : null;
const onFiltersChange = filters =>
typeof rest.onFiltersChange === 'function'
? rest.onFiltersChange(filters)
: null;

/**
* Changing the reloadFootprint timestamp will trigger reloading the table
*/
const [reloadFootprint, setReloadFootprint] = useState(rest.reload || 0);

const onSearch = useCallback(async function (endpoint, filters, pagination, sorting) {
const onSearch = useCallback(async function (
endpoint,
filters,
pagination,
sorting,
) {
try {
const { pageIndex, pageSize } = pagination;
const { field, direction } = sorting.sort;
Expand All @@ -85,7 +93,10 @@ export function TableWzAPI({
).data;
setIsLoading(false);
setTotalItems(totalItems);
return { items: rest.mapResponseItem ? items.map(rest.mapResponseItem) : items, totalItems };
return {
items: rest.mapResponseItem ? items.map(rest.mapResponseItem) : items,
totalItems,
};
} catch (error) {
setIsLoading(false);
setTotalItems(0);
Expand All @@ -101,7 +112,8 @@ export function TableWzAPI({
};
getErrorOrchestrator().handleError(options);
}
}, []);
},
[]);

const renderActionButtons = (
<>
Expand Down Expand Up @@ -132,7 +144,7 @@ export function TableWzAPI({
<EuiFlexItem grow={false}>
<EuiButtonEmpty
isDisabled={totalItems == 0}
iconType="refresh"
iconType='refresh'
onClick={() => triggerReload()}
>
Refresh
Expand All @@ -142,16 +154,22 @@ export function TableWzAPI({

const header = (
<EuiFlexGroup wrap>
<EuiFlexItem className="wz-flex-basis-auto" grow={false}>
<EuiFlexItem className='wz-flex-basis-auto' grow={false}>
{rest.title && (
<EuiTitle size="s">
<EuiTitle size='s'>
<h1>
{rest.title}{' '}
{isLoading ? <EuiLoadingSpinner size="s" /> : <span>({totalItems})</span>}
{isLoading ? (
<EuiLoadingSpinner size='s' />
) : (
<span>({totalItems})</span>
)}
</h1>
</EuiTitle>
)}
{rest.description && <EuiText color="subdued">{rest.description}</EuiText>}
{rest.description && (
<EuiText color='subdued'>{rest.description}</EuiText>
)}
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGroup wrap justifyContent={'flexEnd'} alignItems={'center'}>
Expand All @@ -174,9 +192,15 @@ export function TableWzAPI({
);

const table = rest.searchTable ? (
<TableWithSearchBar onSearch={onSearch} {...{ ...rest, reload: reloadFootprint }} />
<TableWithSearchBar
onSearch={onSearch}
{...{ ...rest, reload: reloadFootprint }}
/>
) : (
<TableDefault onSearch={onSearch} {...{ ...rest, reload: reloadFootprint }} />
<TableDefault
onSearch={onSearch}
{...{ ...rest, reload: reloadFootprint }}
/>
);

return (
Expand Down
12 changes: 6 additions & 6 deletions public/components/common/welcome/agents-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
} from '@elastic/eui';
import { WzRequest } from '../../../react-services/wz-request';
import { formatUIDate } from '../../../react-services/time-service';

import { compressIPv6 } from '../../../services/ipv6-services';
import WzTextWithTooltipIfTruncated from '../wz-text-with-tooltip-if-truncated';
import { WzStat } from '../../wz-stat';
import { GroupTruncate } from '../util/agent-group-truncate'
Expand Down Expand Up @@ -73,7 +73,7 @@ export class AgentInfo extends Component {
const osName = os_name === '- -' ? '-' : os_name;

return (
<WzTextWithTooltipIfTruncated position='bottom' tooltipProps={{ anchorClassName: 'wz-width-100'}} elementStyle={{ maxWidth: style.maxWidth, fontSize: 12 }}>
<WzTextWithTooltipIfTruncated position='bottom' tooltipProps={{ anchorClassName: 'wz-width-100' }} elementStyle={{ maxWidth: style.maxWidth, fontSize: 12 }}>
{this.getPlatformIcon(this.props.agent)}
{' '}{osName}
</WzTextWithTooltipIfTruncated>
Expand Down Expand Up @@ -105,7 +105,7 @@ export class AgentInfo extends Component {
};
const stats = items.map(item => {
// We add tooltipProps, so that the ClusterNode and Operating System fields occupy their space and do not exceed this, overlapping with the one on the right
const tooltipProps = item.description === 'Cluster node' ? { anchorClassName: 'wz-width-100'} : {};
const tooltipProps = item.description === 'Cluster node' ? { anchorClassName: 'wz-width-100' } : {};
return (
<EuiFlexItem key={item.description} style={item.style || null}>
<WzStat
Expand All @@ -122,7 +122,7 @@ export class AgentInfo extends Component {
) : item.description === 'Operating system' ? (
this.addTextPlatformRender(this.props.agent, item.style)
) : item.description === 'Status' ? (
<AgentStatus status={this.props.agent.status} style={{...item.style, fontSize: '12px'}} />
<AgentStatus status={this.props.agent.status} style={{ ...item.style, fontSize: '12px' }} />
) : (
<WzTextWithTooltipIfTruncated position='bottom' tooltipProps={tooltipProps} elementStyle={{ maxWidth: item.style.maxWidth, fontSize: 12 }}>
{checkField(item.title)}
Expand Down Expand Up @@ -157,7 +157,7 @@ export class AgentInfo extends Component {
arrayStats = [
{ title: agent.id, description: 'ID', style: { minWidth: 30 } },
{ title: agent.status, description: 'Status', style: { minWidth: 130 } },
{ title: agent.ip, description: 'IP address', style: { minWidth: 80 } },
{ title: compressIPv6(agent.ip), description: 'IP address', style: { width: 'fit-content' } },
{ title: agent.version, description: 'Version', style: { minWidth: 100 } },
{ title: agent.group, description: 'Groups', style: { minWidth: 150 } },
{ title: agent.name, description: 'Operating system', style: { minWidth: 150 } },
Expand All @@ -173,7 +173,7 @@ export class AgentInfo extends Component {

return (
<Fragment>
<EuiFlexGroup wrap style={{responsive: true }} className="wz-welcome-page-agent-info-details">
<EuiFlexGroup wrap style={{ responsive: true }} className="wz-welcome-page-agent-info-details">
{stats}
</EuiFlexGroup>
</Fragment>
Expand Down
4 changes: 3 additions & 1 deletion public/controllers/agent/components/agents-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/
import { getErrorOrchestrator } from '../../../react-services/common-services';
import { AgentStatus } from '../../../components/agents/agent_status';
import { AgentSynced } from '../../../components/agents/agent-synced';
import { compressIPv6 } from '../../../services/ipv6-services';

export const AgentsTable = withErrorBoundary(
class AgentsTable extends Component {
Expand Down Expand Up @@ -289,7 +290,7 @@ export const AgentsTable = withErrorBoundary(
return {
id: agent.id,
name: agent.name,
ip: agent.ip,
ip: compressIPv6(agent.ip),
status: agent.status,
group_config_status: agent.group_config_status,
group: checkField(agent.group),
Expand Down Expand Up @@ -481,6 +482,7 @@ export const AgentsTable = withErrorBoundary(
name: 'IP address',
sortable: true,
show: true,
truncateText: true,
},
{
field: 'group',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ class WzGroupAgentsTable extends Component {
name: 'Id',
align: 'left',
sortable: true,
width: '5%',
},
{
field: 'name',
Expand All @@ -154,8 +155,10 @@ class WzGroupAgentsTable extends Component {
{
field: 'ip',
name: 'IP address',
align: 'left',
sortable: true,
show: true,
truncateText: false,
width: '25%',
},
{
field: 'status',
Expand Down Expand Up @@ -254,6 +257,7 @@ class WzGroupAgentsTable extends Component {
endpoint={`/groups/${this.props.state.itemDetail.name}/agents`}
reload={this.props.state.reload}
searchTable={true}
compressipv6={true}
/>
);
} else {
Expand Down
20 changes: 20 additions & 0 deletions public/services/ipv6-services.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { compressIPv6 } from './ipv6-services';

describe('[settings] Input validation', () => {
it.each`
value | expectedValidation
${'192.168.100.1'} | ${'192.168.100.1'}
${'FE80:1234:2223:A000:2202:B3FF:FE1E:8329'} | ${'FE80:1234:2223:A000:2202:B3FF:FE1E:8329'}
${'FE80:0034:0223:A000:0002:B3FF:0000:8329'} | ${'FE80:34:223:A000:2:B3FF:0:8329'}
${'FE80:1234:2223:0000:0000:B3FF:FE1E:8329'} | ${'FE80:1234:2223::B3FF:FE1E:8329'}
${'FE80:0000:0000:A000:0000:0000:0000:8329'} | ${'FE80:0:0:A000::8329'}
${'FE80:0000:0000:0000:2202:00FF:0E1E:8329'} | ${'FE80::2202:FF:E1E:8329'}
${'0000:0000:0000:0000:2202:00FF:0E1E:8329'} | ${'::2202:FF:E1E:8329'}
${'2202:00FF:0E1E:8329:2202:0000:0000:0000'} | ${'2202:FF:E1E:8329:2202::'}
${'0000:0000:0000:0000:0000:0000:0000:0000'} | ${'::'}
${undefined} | ${undefined}
${234} | ${234}
`('$value | $expectedValidation', ({ value, expectedValidation }) => {
expect(compressIPv6(value)).toBe(expectedValidation);
});
});
24 changes: 24 additions & 0 deletions public/services/ipv6-services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
export function compressIPv6(ip: string) {
if (typeof ip !== 'string') {
return ip;
}
if (ip?.split(':').length !== 8) {
return ip;
}

let output = ip
.split(':')
.map(terms => terms.replace(/\b0+/g, '') || '0')
.join(':');
const zeros = Array.from(output.matchAll(/\b:?(?:0+:?){2,}/g));
if (zeros.length > 0) {
let max = '';
zeros.forEach(item => {
if (item[0].replace(/:/g, '').length > max.replace(/:/g, '').length) {
max = item[0];
}
});
output = output.replace(max, '::');
}
return output;
}