improve searchable generic report fields (#1133)

* implement links on all v4/v6/mac found in _searchable fields

* word boundaries on matching
This commit is contained in:
Oliver Gorwits
2023-12-07 07:49:18 +00:00
committed by GitHub
parent b85ca1140f
commit bc47b54f67
4 changed files with 51 additions and 4 deletions

View File

@@ -79,6 +79,7 @@ Module::Build->new(
'Plack::Middleware::ReverseProxy' => '0.15', 'Plack::Middleware::ReverseProxy' => '0.15',
'Pod::Usage' => 0, 'Pod::Usage' => 0,
'Regexp::Common' => 2017060201, 'Regexp::Common' => 2017060201,
'Regexp::Common::net::CIDR' => 0,
'Role::Tiny' => '1.002005', 'Role::Tiny' => '1.002005',
'Scope::Guard' => 0, 'Scope::Guard' => 0,
'Sereal' => '0', 'Sereal' => '0',

View File

@@ -9,6 +9,10 @@ use Path::Class 'file';
use Storable 'dclone'; use Storable 'dclone';
use Safe; use Safe;
use HTML::Entities 'encode_entities';
use Regexp::Common qw( RE_net_IPv4 RE_net_IPv6 RE_net_MAC RE_net_domain );
use Regexp::Common::net::CIDR ();
our ($config, @data); our ($config, @data);
foreach my $report (@{setting('reports')}) { foreach my $report (@{setting('reports')}) {
@@ -72,6 +76,48 @@ foreach my $report (@{setting('reports')}) {
my @results = ((-f $munger) ? $compartment->rdo( $munger ) : @data); my @results = ((-f $munger) ? $compartment->rdo( $munger ) : @data);
return if $@ or (0 == scalar @results); return if $@ or (0 == scalar @results);
# searchable field support..
my $recidr4 = $RE{net}{CIDR}{IPv4}{-keep}; #RE_net_CIDR_IPv4(-keep);
my $rev4 = RE_net_IPv4(-keep);
my $rev6 = RE_net_IPv6(-keep);
my $remac = RE_net_MAC(-keep);
#my $redom = RE_net_domain(-keep, -nospace, -rfc1101);
foreach my $row (@results) {
foreach my $col (@column_order) {
next unless $column_config{$col}->{_searchable};
my $fields = (ref $row->{$col} ? $row->{$col} : [$row->{$col}]);
foreach my $f (@$fields) {
# seems too sensitive match to be useful :-(
#$f =~ s!\b${redom}\b!'<a href="'.
# uri_for('/search', {q => $1 .($2 ? "/$2" : '')})->path_query
# .'">'. encode_entities($1 .($2 ? "/$2" : '')) .'</a>'!gex;
$f =~ s!\b${recidr4}\b!'<a href="'.
uri_for('/search', {q => "$1/$2"})->path_query
.'">'. encode_entities("$1/$2") .'</a>'!gex;
if (not $1 and not $2) {
$f =~ s!\b${rev4}\b!'<a href="'.
uri_for('/search', {q => $1})->path_query
.'">'. encode_entities($1) .'</a>'!gex;
}
$f =~ s!\b${rev6}\b!'<a href="'.
uri_for('/search', {q => $1})->path_query
.'">'. encode_entities($1) .'</a>'!gex;
$f =~ s!\b${remac}\b!'<a href="'.
uri_for('/search', {q => $1})->path_query
.'">'. encode_entities($1) .'</a>'!gex;
$row->{$col} = $f if not ref $row->{$col};
}
}
}
if (request->is_ajax) { if (request->is_ajax) {
template 'ajax/report/generic_report.tt', template 'ajax/report/generic_report.tt',
{ results => \@results, { results => \@results,

View File

@@ -183,7 +183,7 @@ system_reports:
label: 'Blocked - Error-Disabled' label: 'Blocked - Error-Disabled'
category: Port category: Port
columns: columns:
- { ip: Device } - { ip: Device, _searchable: true }
- { dns: DNS } - { dns: DNS }
- { port: Port } - { port: Port }
- { name: Description } - { name: Description }
@@ -259,12 +259,12 @@ system_reports:
HAVING count(vlan) > COALESCE(NULLIF(?,''), '1') ::integer HAVING count(vlan) > COALESCE(NULLIF(?,''), '1') ::integer
ORDER BY vlans DESC, ip ASC, port ASC ORDER BY vlans DESC, ip ASC, port ASC
- tag: duplicateprivatenetworks - tag: duplicateprivatenetworks
category: Port category: IP
label: 'Duplicate Private Networks' label: 'Duplicate Private Networks'
columns: columns:
- { subnet: 'Subnet', _searchable: true } - { subnet: 'Subnet', _searchable: true }
- { count: 'Instances' } - { count: 'Instances' }
- { seen: 'Where Seen' } - { seen: 'Where Seen', _searchable: true }
query: | query: |
SELECT subnet, count(subnet), array_agg(host(alias)::text || ' on ' || host(ip)::text) AS seen SELECT subnet, count(subnet), array_agg(host(alias)::text || ' on ' || host(ip)::text) AS seen
FROM device_ip FROM device_ip

View File

@@ -13,7 +13,7 @@
<td> <td>
[% FOREACH record IN row.item(col) %] [% FOREACH record IN row.item(col) %]
[% IF column_options.$col._searchable %] [% IF column_options.$col._searchable %]
<a href="[% uri_for('/search') | none %]?q=[% record | uri %]">[% record | html_entity %]</a> [% record | none %]
[% ELSE %] [% ELSE %]
[% record | html_entity %] [% record | html_entity %]
[% END %] [% END %]