You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by ar...@apache.org on 2015/03/19 21:16:35 UTC

svn commit: r1667865 - in /vcl/trunk/managementnode/lib/VCL/Module: OS.pm OS/Linux.pm OS/Linux/ManagementNode.pm

Author: arkurth
Date: Thu Mar 19 20:16:35 2015
New Revision: 1667865

URL: http://svn.apache.org/r1667865
Log:
VCL-839
Changed Linux firewall code so that it doesn't rely on the management node private IP address which cannot be reliably determined. Instead, access firewall access is granted to all IP addresses bound on the management node.

Added Linux.pm::grant_management_node_access. This allows traffic on any port to all of the MN's IP addresses.

Added check in Linux.pm::enable_firewall_port if an attempt is made to enable port 22 with the force option. This subroutine now calls grant_management_node_access and only proceeds if it returns true. This should help eliminate the possibility of a MN locking itself out.

Added call to grant_management_node_access in disable port if the port is 22. It only proceeds if grant_management_node_access returns true.

Added OS.pm::get_ip_addresses which is used by grant_management_node_access.

Changed Linux.pm::post_load to call disable_firewall_port('tcp', 22) instead of attempting to enable TCP/22 for the management node's private IP address.

Changed Linux.pm::sanitize to call process_connect_methods with an argument of 127.0.0.1 instead of the MN's private IP address.

Changed ManagementNode.pm::initialize to not return false if the management node's private IP address cannot be determined.

Modified:
    vcl/trunk/managementnode/lib/VCL/Module/OS.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
    vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS.pm?rev=1667865&r1=1667864&r2=1667865&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS.pm Thu Mar 19 20:16:35 2015
@@ -1882,6 +1882,44 @@ sub get_ip_address {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 get_ip_addresses
+
+ Parameters  : $no_cache (optional)
+ Returns     : array
+ Description : Returns all of the IP addresses of the computer.
+
+=cut
+
+sub get_ip_addresses {
+	my ($self, $no_cache) = @_;
+	if (ref($self) !~ /VCL::Module/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return;
+	}
+	
+	my $computer_name = $self->data->get_computer_short_name();
+	
+	# Get the network configuration hash reference
+	my $network_configuration = $self->get_network_configuration($no_cache);
+	if (!$network_configuration) {
+		notify($ERRORS{'WARNING'}, 0, "unable to retrieve IP addresses from $computer_name, failed to retrieve network configuration");
+		return;
+	}
+	
+	# Loop through all of the network interfaces found
+	my @ip_addresses;
+	for my $interface_name (sort keys %$network_configuration) {
+		if ($network_configuration->{$interface_name}{ip_address}) {
+			push @ip_addresses, keys %{$network_configuration->{$interface_name}{ip_address}};
+		}
+	}
+	
+	notify($ERRORS{'DEBUG'}, 0, "retrieved IP addresses bound on $computer_name:\n" . join("\n", @ip_addresses));
+	return @ip_addresses;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 get_private_ip_address
 
  Parameters  : $ignore_error (optional)
@@ -3733,6 +3771,7 @@ sub get_connect_method_remote_ip_address
 	my $computer_node_name = $self->data->get_computer_node_name();
 	
 	# Get the management node's IP addresses - these will be ignored
+	# TODO: change to get_ip_addresses
 	my $mn_private_ip_address = $self->mn_os->get_private_ip_address();
 	my $mn_public_ip_address = $self->mn_os->get_public_ip_address();
 	

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm?rev=1667865&r1=1667864&r2=1667865&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Thu Mar 19 20:16:35 2015
@@ -415,7 +415,6 @@ sub post_load {
 	my $image_name            = $self->data->get_image_name();
 	my $computer_node_name    = $self->data->get_computer_node_name();
 	my $image_os_install_type = $self->data->get_image_os_install_type();
-	my $mn_private_ip         = $self->mn_os->get_private_ip_address();
 	
 	notify($ERRORS{'OK'}, 0, "beginning Linux post_load tasks, image: $image_name, computer: $computer_node_name");
 
@@ -464,17 +463,9 @@ sub post_load {
 		notify($ERRORS{'WARNING'}, 0, "failed to clear known identity keys");
 	}
 	
-	# Allow all traffic from the management node's private IP address
-	# Remove existing rules which allow traffic from any IP address
-	if (!$self->enable_firewall_port("tcp", "any", $mn_private_ip, 1)) {
-		notify($ERRORS{'WARNING'}, 0, "failed to allow all traffic from management node private IP address");
-	}
-	
-	# Allow all traffic on port 22 from the management node's private IP address
-	# Remove existing rules which allow traffic from any IP address
-	if (!$self->enable_firewall_port("tcp", 22, $mn_private_ip, 1)) {
-		notify($ERRORS{'WARNING'}, 0, "failed to allow SSH traffic from management node private IP address");
-	}
+	# Disable access to TCP/22 from any IP address
+	# This causes grant_management_node_access to be called which allows access from any of the management node's IP addresses
+	$self->disable_firewall_port('tcp', 22);
 	
 	# Attempt to generate ifcfg-eth* files and ifup any interfaces which the file does not exist
 	$self->activate_interfaces();
@@ -1184,6 +1175,61 @@ sub grant_access {
 
 #/////////////////////////////////////////////////////////////////////////////
 
+=head2 grant_management_node_access
+
+ Parameters  : $overwrite (optional)
+ Returns     : boolean
+ Description : Grants firewall access to all protocols and ports from all of the
+               management node's IP addresses.
+
+=cut
+
+sub grant_management_node_access {
+	my $self = shift;
+	if (ref($self) !~ /linux/i) {
+		notify($ERRORS{'CRITICAL'}, 0, "subroutine was called as a function, it must be called as a class method");
+		return 0;
+	}
+	
+	my $overwrite = shift;
+	
+	my $port = 'any';
+	my $protocol = 'tcp';
+	
+	my $computer_name = $self->data->get_computer_short_name();
+	my $management_node_name = $self->data->get_management_node_short_name();
+	
+	# Allow traffic to any port from any of the managment node's IP addresses
+	my @mn_ip_addresses = $self->mn_os->get_ip_addresses();
+	if (!@mn_ip_addresses) {
+		notify($ERRORS{'WARNING'}, 0, "unable to grant access to $computer_name from management node $management_node_name on " . ($port eq 'any' ? 'any port' : "port $port") . ", failed to retrieve management node IP addresses");
+		return;
+	}
+	
+	my $error_occurred = 0;
+	
+	my $mn_ip_address_1 = shift @mn_ip_addresses;
+	# Allow all traffic from the management node
+	# Set the overwrite flag, this removes existing rules which allow traffic from any IP address
+	if (!$self->enable_firewall_port($protocol, $port, $mn_ip_address_1, $overwrite)) {
+		$error_occurred = 1;
+		notify($ERRORS{'WARNING'}, 0, "failed to grant access to $computer_name from management node $management_node_name IP address: $mn_ip_address_1");
+	}
+	
+	for my $mn_ip_address (@mn_ip_addresses) {
+		# Allow all traffic from the management node's other IP addresses
+		# Don't specify the overwrite flag
+		if (!$self->enable_firewall_port($protocol, $port, $mn_ip_address, 0)) {
+			$error_occurred = 1;
+			notify($ERRORS{'WARNING'}, 0, "failed to grant access to $computer_name from management node $management_node_name IP address: $mn_ip_address");
+		}
+	}
+	
+	return !$error_occurred;
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
 =head2 synchronize_time
 
  Parameters  : none
@@ -1326,7 +1372,6 @@ sub sanitize {
 	}
 	
 	my $computer_node_name = $self->data->get_computer_node_name();
-	my $mn_private_ip      = $self->mn_os->get_private_ip_address();
 	
 	# Make sure user is not connected
 	if ($self->is_connected()) {
@@ -1335,11 +1380,12 @@ sub sanitize {
 		return 0;
 	}
 	
-	# Clean up connection methods
-	if ($self->process_connect_methods($mn_private_ip, 1)) {
-		notify($ERRORS{'OK'}, 0, "processed connection methods on $computer_node_name");
+	# Call process_connect_methods with the overwrite flag to remove firewall exceptions
+	if (!$self->process_connect_methods('127.0.0.1', 1)) {
+		notify($ERRORS{'WARNING'}, 0, "failed to sanitize $computer_node_name, failed to overwrite existing connect method firewall exceptions");
+		return 0;
 	}
-	
+
 	# Delete all user associated with the reservation
 	if (!$self->delete_user_accounts()) {
 		notify($ERRORS{'WARNING'}, 0, "failed to delete all users from $computer_node_name");
@@ -3679,6 +3725,14 @@ sub enable_firewall_port {
 		return;
 	}
 	
+	# Make sure the management node is not cut off by overwriting port 22
+	if ($overwrite_existing && $port eq '22' && $parsed_scope_argument !~ /0\.0\.0\.0/) {
+		if (!$self->grant_management_node_access()) {
+			notify($ERRORS{'WARNING'}, 0, "firewall port $port not enabled because access could be cut off from the management node");
+			return;
+		}
+	}
+	
 	my $chain = "INPUT";
 	my @commands;
 	my $new_scope = '';
@@ -3888,9 +3942,10 @@ sub disable_firewall_port {
 		return;
 	}
 	elsif ($port eq '22') {
-		my $mn_private_ip = $self->mn_os->get_private_ip_address();
-		notify($ERRORS{'OK'}, 0, "disabling firewall port 22 is not allowed because it will cut off access from the management node, enabling port 22 to only the management node's private IP address: $mn_private_ip");
-		return $self->enable_firewall_port("tcp", 22, $mn_private_ip, 1);
+		if (!$self->grant_management_node_access()) {
+			notify($ERRORS{'WARNING'}, 0, "firewall port not disabled 22 because firewall could not be opened to any port from the management node");
+			return;
+		}
 	}
 	
 	my $chain = "INPUT";

Modified: vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm
URL: http://svn.apache.org/viewvc/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm?rev=1667865&r1=1667864&r2=1667865&view=diff
==============================================================================
--- vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm (original)
+++ vcl/trunk/managementnode/lib/VCL/Module/OS/Linux/ManagementNode.pm Thu Mar 19 20:16:35 2015
@@ -82,20 +82,21 @@ sub initialize {
 	my $management_node_short_name = $self->data->get_management_node_short_name() || return;
 	my $management_node_ip_address = $self->data->get_management_node_ipaddress() || return;
 	
-	my $management_node_private_ip_address = hostname_to_ip_address($management_node_hostname);
-	if (!$management_node_private_ip_address) {
-		notify($ERRORS{'WARNING'}, 0, "failed to initialize management node OS object, unable to resolve hostname '$management_node_hostname'");
-		return;
-	}
-	
 	$self->data->set_computer_id(0);
 	$self->data->set_computer_hostname($management_node_hostname);
 	$self->data->set_computer_node_name($management_node_short_name);
 	$self->data->set_computer_short_name($management_node_short_name);
 	$self->data->set_computer_public_ip_address($management_node_ip_address);
-	$self->data->set_computer_private_ip_address($management_node_private_ip_address);
 	
-	#print "\n\n" . format_data($self->data->get_request_data()) . "\n\n";
+	# TODO: remove all use of management node private IP address
+	my $management_node_private_ip_address = hostname_to_ip_address($management_node_hostname);
+	if ($management_node_private_ip_address) {
+		$self->data->set_computer_private_ip_address($management_node_private_ip_address);
+	}
+	else {
+		notify($ERRORS{'WARNING'}, 0, "failed to initialize management node private IP address in DataStructure object, unable to resolve hostname '$management_node_hostname'");
+	}
+	
 	return 1;
 }