From 0ca80d059946e97813fb2a626efd5a9dc3345eec Mon Sep 17 00:00:00 2001 From: Digimer Date: Sat, 8 Dec 2018 15:37:25 -0500 Subject: [PATCH] * Started work on System->check_firewall() that will collect existing firewall information. * Updated System->get_ips() to read and parse the interface config file and ignore 'lo'. * Started working on striker-manage-install-target again. Signed-off-by: Digimer --- Anvil/Tools/System.pm | 126 +++++++++++++++++++++++++++- cgi-bin/striker | 2 +- tools/anvil-manage-firewall | 80 ++++++++++++++---- tools/striker-manage-install-target | 1 - 4 files changed, 190 insertions(+), 19 deletions(-) diff --git a/Anvil/Tools/System.pm b/Anvil/Tools/System.pm index bd89e478..35813b7a 100755 --- a/Anvil/Tools/System.pm +++ b/Anvil/Tools/System.pm @@ -753,7 +753,12 @@ sub get_ips $anvil->data->{sys}{network}{interface}{$in_iface}{dns} = "" if not defined $anvil->data->{sys}{network}{interface}{$in_iface}{dns}; } next if not $in_iface; - next if $in_iface eq "lo"; + if ($in_iface eq "lo") + { + # We don't care about 'lo'. + delete $anvil->data->{sys}{network}{interface}{$in_iface}; + next; + } if ($line =~ /inet (.*?)\/(.*?) /) { my $ip = $1; @@ -796,6 +801,69 @@ sub get_ips } } + # Read the config files for the interfaces we've found. + local(*DIRECTORY); + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 3, key => "log_0018", variables => { "path::directories::ifcfg" => $anvil->data->{path}{directories}{ifcfg} }}); + opendir(DIRECTORY, $anvil->data->{path}{directories}{ifcfg}); + while(my $file = readdir(DIRECTORY)) + { + next if $file eq "."; + next if $file eq ".."; + next if $file eq "ifcfg-lo"; + next if $file !~ /^ifcfg/; + next if $file =~ /\.bak$/; + my $full_path = $anvil->data->{path}{directories}{ifcfg}."/".$file; + $full_path =~ s/\/\///g; + next if not -f $full_path; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file => $file }}); + + # Read the file. + my $file_body = $anvil->Storage->read_file({file => $full_path}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "s1:full_path" => $full_path, + "s2:file_body" => $file_body, + }}); + + # Break it apart and store any variables. + my $temp = {}; + my $interface = ""; + foreach my $line (split/\n/, $file_body) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }}); + next if $line =~ /^#/; + if ($line =~ /(.*?)=(.*)/) + { + my $variable = $1; + my $value = $2; + $value =~ s/^"(.*)"$/$1/; + $temp->{$variable} = $value; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "temp->{$variable}" => $temp->{$variable} }}); + + if (uc($variable) eq "DEVICE") + { + $interface = $value; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "interface" => $interface }}); + } + } + + if ($interface) + { + $anvil->data->{sys}{network}{interface}{$interface}{file} = $full_path; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "sys::network::interface::${interface}::file" => $anvil->data->{sys}{network}{interface}{$interface}{file}, + }}); + foreach my $variable (sort {$a cmp $b} keys %{$temp}) + { + $anvil->data->{sys}{network}{interface}{$interface}{variable}{$variable} = $temp->{$variable}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "sys::network::interface::${interface}::file::variable::${variable}" => $anvil->data->{sys}{network}{interface}{$interface}{variable}{$variable}, + }}); + } + } + } + } + closedir(DIRECTORY); + # Get the routing info. my $lowest_metric = 99999999; my $route_interface = ""; @@ -1207,6 +1275,62 @@ sub maintenance_mode return($maintenance_mode); } +### TODO: Move and document. +sub check_firewall +{ + my $self = shift; + my $parameter = shift; + my $anvil = $self->parent; + my $debug = defined $parameter->{debug} ? $parameter->{debug} : 3; + $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => $debug, key => "log_0125", variables => { method => "System->manage_firewall()" }}); + + # Set some values. + $anvil->data->{firewall}{default_zone} = ""; + + # Checking the iptables rules in memory is very fast, relative to firewall-cmd. So we'll do an + # initial check there to see if the port in question is listed. + my $shell_call = $anvil->data->{path}{exe}{'iptables-save'}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { shell_call => $shell_call }}); + + ### NOTE: We parse apart iptables-save instead of making frewall-cmd calls as this is a lot faster, + ### if not ideal. May want to revisit how we do this later. + my $iptables = $anvil->System->call({shell_call => $shell_call}); + foreach my $line (split/\n/, $iptables) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }}); + + if ($line =~ /-A INPUT_ZONES -g IN_(.*)$/) + { + $anvil->data->{firewall}{default_zone} = $1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "firewall::default_zone" => $anvil->data->{firewall}{default_zone} }}); + } + if ($line =~ /^:PRE_(\w+) -/) + { + my $zone = $1; + next if $zone =~ /_log$/; + next if $zone =~ /_allow$/; + next if $zone =~ /_deny$/; + $anvil->data->{firewall}{zone}{$zone}{found} = 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "firewall::zone::${zone}::found" => $anvil->data->{firewall}{zone}{$zone}{found} }}); + } + } + + # Make sure, for each zone, we've got a zone file. We should, so we'll read it in. + foreach my $zone (sort {$a cmp $b} keys %{$anvil->data->{firewall}{zone}}) + { + my $file = $anvil->data->{path}{directories}{firewalld_zones}."/".$zone.".xml"; + $file =~ s/\/\//\//g; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file => $file }}); + if (-e $file) + { + my $zone = $anvil->Storage->read_file({file => $file}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { zone => $zone }}); + } + } + + return(0); +} + =head2 manage_firewall This method manages a firewalld firewall. diff --git a/cgi-bin/striker b/cgi-bin/striker index 76558366..08563ba3 100755 --- a/cgi-bin/striker +++ b/cgi-bin/striker @@ -379,7 +379,7 @@ sub process_install_target title => "#!string!striker_0044!#", description => "#!string!".$message."!#", }}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "form::body" => $anvil->data->{form}{body} }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { "form::body" => $anvil->data->{form}{body} }}); } else { diff --git a/tools/anvil-manage-firewall b/tools/anvil-manage-firewall index 847ca8fe..85e7eeb4 100755 --- a/tools/anvil-manage-firewall +++ b/tools/anvil-manage-firewall @@ -1,21 +1,8 @@ #!/usr/bin/perl # -# This manages does two main tasks; -# - On Striker dashboards, it enables and disabled the "Install Target" feauter. -# - On nodes and DR hosts, it opens and closes VNC ports as servers are booted or stopped. +# This keeps an eye on the network configuration and ensures the firewall is configured appropriately. What +# exactly that means depends on why kind of machine the local host is. # -# Examples; -# - Call without any arguments and it will check for running servers and, for each it will open the VNC port -# on both the BCN and IFN. Before doing so, it will check 'servers::::vnc::'. If that -# is found and set to '0', the port will not be opened on the network. For example, to prevent a server -# named 'foo' from being accessible over 'ifn1', set 'servers::foo::vnc::ifn1 = 0'. The network name comes -# from the first part of the interface name with the IP address. So for 'ifn1_bond1', the network is -# 'ifn1'. -# - Call it with '--enable-install-target' or '--disable-install-target' to enable or disable the "Install -# Target" feature. This also enables or disables the dhcpd daemon. This can also be called as an Anvil jobs -# to enable or disable the Install Target by setting the 'job_data' to 'install-target::enable' or -# 'install-target::disable'. -# # # Exit codes; # 0 = Normal exit. @@ -25,6 +12,8 @@ use strict; use warnings; use Anvil::Tools; +use Data::Dumper; + # Disable buffering $| = 1; @@ -45,7 +34,7 @@ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, secure = $anvil->data->{switches}{'y'} = ""; $anvil->Get->switches; - +check_initial_setup($anvil); # We're done $anvil->nice_exit({exit_code => 0}); @@ -55,3 +44,62 @@ $anvil->nice_exit({exit_code => 0}); # Private functions. # ############################################################################################################# +sub check_initial_setup +{ + my ($anvil) = @_; + + # Get a list of networks. + $anvil->System->get_ips(); + my $internet_zone = ""; + foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{sys}{network}{interface}}) + { + if ($interface =~ /^((bcn|ifn|sn)\d+)_/) + { + # We'll use the start as the zone, though it should always be overridden by the + # ZONE="" variable in each interface's config. + my $zone = $1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { zone => $zone }}); + if ((exists $anvil->data->{sys}{network}{interface}{$interface}{variable}{ZONE}) && ($anvil->data->{sys}{network}{interface}{$interface}{variable}{ZONE})) + { + $zone = $anvil->data->{sys}{network}{interface}{$interface}{variable}{ZONE}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { zone => $zone }}); + } + + $anvil->data->{zones}{$zone}{interface}{$interface}{ip} = $anvil->data->{sys}{network}{interface}{$interface}{ip}; + $anvil->data->{zones}{$zone}{interface}{$interface}{subnet} = $anvil->data->{sys}{network}{interface}{$interface}{subnet}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + "zones::${zone}::interface::${interface}::ip" => $anvil->data->{zones}{$zone}{interface}{$interface}{ip}, + "zones::${zone}::interface::${interface}::subnet" => $anvil->data->{zones}{$zone}{interface}{$interface}{subnet}, + }}); + + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + "sys::network::interface::${interface}::default_gateway" => $anvil->data->{sys}{network}{interface}{$interface}{default_gateway}, + }}); + if ($anvil->data->{sys}{network}{interface}{$interface}{default_gateway}) + { + $internet_zone = $zone; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { internet_zone => $internet_zone }}); + } + } + } + + # See what we've found... + foreach my $zone (sort {$a cmp $b} keys %{$anvil->data->{zones}}) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { zone => $zone }}); + foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{zones}{$zone}{interface}}) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { interface => $interface }}); + } + } + + # Get the list of existing zones. + my $firewall = $anvil->System->check_firewall({debug => 2}); + print Dumper $firewall; + + # What am I? + my $type = $anvil->System->get_host_type(); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { type => $type }}); + + return(0); +} diff --git a/tools/striker-manage-install-target b/tools/striker-manage-install-target index 476a6ba7..1c457a7a 100755 --- a/tools/striker-manage-install-target +++ b/tools/striker-manage-install-target @@ -35,7 +35,6 @@ use strict; use warnings; use Anvil::Tools; -use Data::Dumper; # Disable buffering $| = 1;