diff --git a/Anvil/Tools.pm b/Anvil/Tools.pm index 5a42a285..21c66ed2 100644 --- a/Anvil/Tools.pm +++ b/Anvil/Tools.pm @@ -870,29 +870,29 @@ sub _set_defaults password => "Initial1", timezone => "Etc/GMT --isUtc", }, - ## Network stuff... The second octet auto-increments to handle N-number of netowrks. As such, - ## we need to use a wider spread between the BCNs, SNs and IFNs than we had - ## in v2. + # See 'striker' -> 'sub generate_ip()' function comments for details on how m3 IPs are handled. network => { - # BCN starts at 10.(0+n)/16 + # BCN starts at 10.200(+n)/16 bcn => { - subnet => "10.0.0.0", - netmask => "255.255.0.0", - pdu_octet3 => "1", - ups_octet3 => "2", - switch_octet3 => "3", - striker_octet3 => "4", + subnet => "10.200.0.0", + netmask => "255.255.0.0", + switch_octet3 => "1", + pdu_octet3 => "2", + ups_octet3 => "3", + striker_octet3 => "4", + striker_ipmi_octet3 => "5", }, dns => "8.8.8.8, 8.8.4.4", - # IFN starts at 10.(80+)/16 + # The IFN will not be under our control. So for suggestion to the user purpose only, + # IFN starts at 10.255/16 ifn => { - subnet => "10.100.0.0", + subnet => "10.255.0.0", netmask => "255.255.0.0", striker_octet3 => "4", }, - # SN starts at 10.(40+n)/16 + # SN starts at 10.100(+n)/16 sn => { - subnet => "10.50.0.0", + subnet => "10.100.0.0", netmask => "255.255.0.0", }, }, @@ -940,7 +940,8 @@ sub _set_paths backups => "/root/anvil-backups", 'cgi-bin' => "/var/www/cgi-bin", firewalld_services => "/usr/lib/firewalld/services", - firewalld_zones => "/etc/firewalld/zones", + #firewalld_zones => "/etc/firewalld/zones", + firewalld_zones => "/usr/lib/firewalld/zones", html => "/var/www/html", ifcfg => "/etc/sysconfig/network-scripts", scan_agents => "/usr/sbin/scancore-agents", diff --git a/Anvil/Tools/System.pm b/Anvil/Tools/System.pm index ef7ab3ff..da90ba96 100644 --- a/Anvil/Tools/System.pm +++ b/Anvil/Tools/System.pm @@ -1278,6 +1278,7 @@ sub maintenance_mode } ### TODO: Move and document. +### NOTE: This only works if the firewall is enabled. sub check_firewall { my $self = shift; @@ -1286,56 +1287,99 @@ sub check_firewall 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 }}); + # Show live or permanent rules? Permanent is default + my $permanent = defined $parameter->{permanent} ? $parameter->{permanent} : 1; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { permanent => $permanent }}); - ### 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. - $anvil->data->{firewall}{default_zone} = ""; - my $iptables = $anvil->System->call({shell_call => $shell_call}); - foreach my $line (split/\n/, $iptables) + # Read in /etc/firewalld/firewalld.conf and parse the 'DefaultZone' variable. + my $firewall_conf = $anvil->Storage->read_file({file => $anvil->data->{path}{configs}{'firewalld.conf'}}); + foreach my $line (split/\n/, $firewall_conf) { $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { line => $line }}); - - if ($line =~ /-A INPUT_ZONES -g IN_(.*)$/) + if ($line =~ /^DefaultZone=(.*?)$/) { $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} }}); + last; } - if ($line =~ /^:PRE_(\w+) -/) + } + $anvil->data->{firewall}{default_zone} = "" if not defined $anvil->data->{firewall}{default_zone}; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "firewall::default_zone" => $anvil->data->{firewall}{default_zone} }}); + + ### NOTE: 'iptables-save' doesn't seem to show the loaded firewall in RHEL8. Slower or not, we seem + ### to have to use 'firewall-cmd' + my $shell_call = $anvil->data->{path}{exe}{'firewall-cmd'}." --permanent --list-all-zones"; + if (not $permanent) + { + $shell_call = $anvil->data->{path}{exe}{'firewall-cmd'}." --list-all-zones"; + } + $anvil->data->{firewall}{default_zone} = ""; + my $zone = ""; + my $active_state = ""; + my $firewall_data = $anvil->System->call({debug => $debug, shell_call => $shell_call}); + foreach my $line (split/\n/, $firewall_data) + { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + 's1:zone' => $zone, + 's2:line' => $line, + }}); + + if ($line =~ /^(\w.*)$/) { - my $zone = $1; - next if $zone =~ /_log$/; - next if $zone =~ /_allow$/; - next if $zone =~ /_deny$/; + $zone = $1; + $active_state = ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { zone => $zone }}); + if ($line =~ /^(\w+) \((.*?)\)/) + { + $zone = $1; + $active_state = $2; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + zone => $zone, + active_state => $active_state + }}); + } $anvil->data->{firewall}{zone}{$zone}{file} = ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "firewall::zone::${zone}::found" => $anvil->data->{firewall}{zone}{$zone}{file} }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "firewall::zone::${zone}::file" => $anvil->data->{firewall}{zone}{$zone}{file} }}); } - if ($line =~ /-A INPUT_ZONES -i (\S+) -g IN_(.*)$/) + elsif ($zone) { - my $interface = $1; - my $zone = $2; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { - interface => $interface, - zone => $zone, - }}); - - $anvil->data->{firewall}{interface}{$interface}{zone} = $zone; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { - "firewall::interface::${interface}::zone" => $anvil->data->{firewall}{interface}{$interface}{zone}, - }}); - } - 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 ((not $line) or ($line =~ /^\s+$/)) + { + # Done reading this zone, record. + my $interfaces = defined $anvil->data->{firewall}{zone}{$zone}{variable}{interfaces} ? $anvil->data->{firewall}{zone}{$zone}{variable}{interfaces} : ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + zone => $zone, + interfaces => $interfaces, + }}); + foreach my $interface (split/ /, $interfaces) + { + $anvil->data->{firewall}{interface}{$interface}{zone} = $zone; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "firewall::interface::${interface}::zone" => $anvil->data->{firewall}{interface}{$interface}{zone}, + }}); + } + + $zone = ""; + $active_state = ""; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + zone => $zone, + active_state => $active_state, + }}); + } + elsif (($active_state) && ($line =~ /(\S.*?):(.*)$/)) + { + my $variable = $1; + my $value = $2; + $variable =~ s/^\s+//; + $variable =~ s/\s+$//; + $value =~ s/^\s+//; + $value =~ s/\s+$//; + $anvil->data->{firewall}{zone}{$zone}{variable}{$variable} = $value; + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { + "s1:line" => $line, + "s2:firewall::zone::${zone}::variable::${variable}" => $anvil->data->{firewall}{zone}{$zone}{variable}{$variable}, + }}); + } } } diff --git a/cgi-bin/striker b/cgi-bin/striker index 04d8ffa2..7350f3a4 100755 --- a/cgi-bin/striker +++ b/cgi-bin/striker @@ -2676,6 +2676,43 @@ sub get_network_details_form return($network); } +=cut +Network planning; + + 10.x.y.z / 255.255.0.0 + 10.x.y.z / 255.255.0.0 + +x = Network; + - BCN = 200 + network + ie: BCN1 = 10.201.y.z + BCN2 = 10.202.y.z + - SN = 100 + network + ie: SN1 = 10.101.y.z + SN2 = 10.102.y.z + +y = Device Type. + Foudation Pack; + 1. Switches + 2. PDUs + 3. UPSes + 4. Switches + 5. Strikers + 6. Striker IPMI (BCN only) + + Anvil! systems; + 1st - 10 = Node IP + 11 = Node IPMI + 2nd - 12 = Node IP + 13 = Node IPMI + 3rd - 14 = Node IP + 15 = Node IPMI + N... + +z = Device Sequence + - Foundation pack devices are simple sequence + - Anvils; .1 = node 1, .2 = node 2, .3 = DR host +=cut + # This is a rudimentary function for generating default Striker IPs. sub generate_ip { @@ -2712,10 +2749,13 @@ sub generate_ip if ($default_netmark eq "255.255.0.0") { # We can work with this. - $ip_octet2 += $network_sequence; - $ip_octet3 = $anvil->data->{defaults}{network}{$network}{striker_octet3}; - $ip_octet4 = $device_sequence; - $ip = $ip_octet1.".".$ip_octet2.".".$ip_octet3.".".$ip_octet4; + if ($network ne "ifn") + { + $ip_octet2 += $network_sequence; + } + $ip_octet3 = $anvil->data->{defaults}{network}{$network}{striker_octet3}; + $ip_octet4 = $device_sequence; + $ip = $ip_octet1.".".$ip_octet2.".".$ip_octet3.".".$ip_octet4; $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { "s1:ip_octet2" => $ip_octet2, "s2:ip_octet3" => $ip_octet3, diff --git a/html/skins/alteeve/firewall.txt b/html/skins/alteeve/firewall.txt index 7b0427a1..1aca9b97 100644 --- a/html/skins/alteeve/firewall.txt +++ b/html/skins/alteeve/firewall.txt @@ -6,6 +6,7 @@ #!variable!zone!# #!variable!description!# + @@ -19,6 +20,7 @@ #!variable!zone!# #!variable!description!# + diff --git a/notes b/notes index edd96d25..4c6e48d1 100644 --- a/notes +++ b/notes @@ -39,7 +39,6 @@ DOCS; - Network planning; - 10.x.y.z / 255.255.0.0 10.x.y.z / 255.255.0.0 @@ -74,6 +73,11 @@ z = Device Sequence ==== +RHEL 8 Firewall +- https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8-beta/html/configuring_and_managing_networking/assembly_using-firewalls_configuring-networking-with-gnome-gui + +============================= + Ports we care about Porto Number Used by Nets Description diff --git a/tools/anvil-cycle-vm-nics b/tools/anvil-cycle-vm-nics index 52231901..8e9902be 100755 --- a/tools/anvil-cycle-vm-nics +++ b/tools/anvil-cycle-vm-nics @@ -172,9 +172,10 @@ sub get_nic_list my $line = $_; print __LINE__."; [ Debug ] - line: [".$line."]\n" if $debug >= 2; - if ($line =~ //) + if (($line =~ //) or ($line =~ //)) { $in_interface = 1; + print __LINE__."; [ Debug ] - in_interface: [".$in_interface."]\n" if $debug >= 2; } if ($in_interface) diff --git a/tools/anvil-manage-firewall b/tools/anvil-manage-firewall index 6d4ce5c9..e823e519 100755 --- a/tools/anvil-manage-firewall +++ b/tools/anvil-manage-firewall @@ -47,7 +47,7 @@ if (not $anvil->data->{sys}{manage}{firewall}) # Do nothing. $anvil->nice_exit({exit_code => 0}); } -$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }}); +$anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 3, secure => 0, key => "log_0115", variables => { program => $THIS_FILE }}); # Read switches $anvil->data->{switches}{'y'} = ""; @@ -76,20 +76,24 @@ sub check_initial_setup $anvil->data->{firewall}{reload} = 0; # Get a list of networks. - $anvil->System->get_ips(); + $anvil->System->get_ips({debug => 3}); + + # Get the list of existing zones from iptables/firewalld. + $anvil->System->check_firewall({debug => 3}); my $internet_zone = ""; foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{sys}{network}{interface}}) { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { interface => $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. + # We'll use the start of the string (network type) 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 }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, 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->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { zone => $zone }}); } push @{$needed_zones}, $zone; @@ -111,59 +115,60 @@ sub check_initial_setup } } - # Get the list of existing zones from iptables/firewalld. - $anvil->System->check_firewall({debug => 3}); + # Process the list of existing zones from iptables/firewalld. foreach my $zone (sort {$a cmp $b} keys %{$anvil->data->{firewall}{zone}}) { my $file = exists $anvil->data->{firewall}{zone}{$zone}{file} ? $anvil->data->{firewall}{zone}{$zone}{file} : $anvil->data->{path}{directories}{firewalld_zones}."/".$zone.".xml"; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "s1:zone" => $zone, "s2:file" => $file, }}); - # Is this a zone I want/need? - my $wanted = 0; - foreach my $needed_zone (sort {$a cmp $b} @{$needed_zones}) - { - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { - "s1:zone" => $zone, - "s2:needed_zone" => $needed_zone, - }}); - if ($needed_zone eq $zone) - { - $wanted = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { wanted => $wanted }}); - last; - } - } - - # Remove the file if needed, and then skip this zone if we don't care about it. - if (not $wanted) - { - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 3, key => "message_0135", variables => { zone => $zone }}); - if (-e $file) - { - # Archive and delete it. - my $backup_file = $anvil->Storage->backup({file => $file }); - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, secure => 0, key => "log_0242", variables => { - zone => $zone, - file => $file, - backup => $backup_file, - }}); - unlink $file; - - if (-e $file) - { - # Failed to unlink the unneeed zone file. - $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0243", variables => { file => $file }}); - $anvil->nice_exit({exit_code => 1}); - } - } - delete $anvil->data->{firewall}{zone}{$zone}; - - reload_firewall($anvil); - next; - } + ### NOTE: This is probably overkill. +# # Is this a zone I want/need? +# my $wanted = 0; +# foreach my $needed_zone (sort {$a cmp $b} @{$needed_zones}) +# { +# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { +# "s1:zone" => $zone, +# "s2:needed_zone" => $needed_zone, +# }}); +# if ($needed_zone eq $zone) +# { +# $wanted = 1; +# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { wanted => $wanted }}); +# last; +# } +# } +# +# # Remove the file if needed, and then skip this zone if we don't care about it. +# $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { wanted => $wanted }}); +# if (not $wanted) +# { +# $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 2, key => "message_0135", variables => { zone => $zone }}); +# if (-e $file) +# { +# # Archive and delete it. +# my $backup_file = $anvil->Storage->backup({file => $file }); +# $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 0, secure => 0, key => "log_0242", variables => { +# zone => $zone, +# file => $file, +# backup => $backup_file, +# }}); +# unlink $file; +# +# if (-e $file) +# { +# # Failed to unlink the unneeed zone file. +# $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 0, priority => "err", key => "log_0243", variables => { file => $file }}); +# $anvil->nice_exit({exit_code => 1}); +# } +# } +# delete $anvil->data->{firewall}{zone}{$zone}; +# +# reload_firewall($anvil); +# next; +# } # Create or update the zone file, if needed. my $template = ""; @@ -186,7 +191,7 @@ sub check_initial_setup $template = "ifn_zone"; $description = $anvil->Words->string({key => "message_0133", variables => { number => $number }}); } - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "s1:template" => $template, "s2:description" => $description, }}); @@ -205,13 +210,13 @@ sub check_initial_setup { # Has it changed? my $diff = diff \$old_zone_body, \$new_zone_body, { STYLE => 'Unified' }; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { diff => $diff }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { diff => $diff }}); if ($diff) { # Update it $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0136", variables => { zone => $zone, file => $file }}); $update_file = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { update_file => $update_file }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_file => $update_file }}); } } else @@ -219,9 +224,10 @@ sub check_initial_setup # Create it $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0137", variables => { zone => $zone, file => $file }}); $update_file = 1; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { update_file => $update_file }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_file => $update_file }}); } + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { update_file => $update_file }}); if ($update_file) { my $error = $anvil->Storage->write_file({ @@ -232,7 +238,7 @@ sub check_initial_setup mode => "0644", overwrite => 1, }); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { error => $error }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { error => $error }}); if ($error) { @@ -247,12 +253,13 @@ sub check_initial_setup foreach my $interface (sort {$a cmp $b} keys %{$anvil->data->{firewall}{zone}{$zone}{interface}}) { my $in_zone = exists $anvil->data->{firewall}{interface}{$interface}{zone} ? $anvil->data->{firewall}{interface}{$interface}{zone} : ""; - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { "s1:interface" => $interface, "s2:in_zone" => $in_zone, "s3:zone" => $zone, }}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { in_zone => $in_zone, zone => $zone }}); if ((not $in_zone) or ($zone ne $in_zone)) { # Add it @@ -261,8 +268,8 @@ sub check_initial_setup zone => $zone, }}); - my $output = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{'firewall-cmd'}." --zone=".$zone." --change-interface=".$interface}); - $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output }}); + my $output = $anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{'firewall-cmd'}." --zone=".$zone." --change-interface=".$interface}); + $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { output => $output }}); reload_firewall($anvil); } @@ -281,7 +288,7 @@ sub check_initial_setup { # Yup $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 3, key => "message_0141", variables => { zone => $internet_zone }}); - my $output = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{'firewall-cmd'}." --set-default-zone=".$internet_zone}); + my $output = $anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{'firewall-cmd'}." --set-default-zone=".$internet_zone}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output }}); } @@ -305,7 +312,7 @@ sub reload_firewall my ($anvil) = @_; $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, 'print' => 1, level => 1, key => "message_0139"}); - my $output = $anvil->System->call({shell_call => $anvil->data->{path}{exe}{'firewall-cmd'}." --reload"}); + my $output = $anvil->System->call({debug => 2, shell_call => $anvil->data->{path}{exe}{'firewall-cmd'}." --complete-reload"}); $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 3, list => { output => $output }}); $anvil->data->{firewall}{reload} = 1;