Author: fapeeler
Date: Mon Nov 14 21:15:16 2011
New Revision: 1201909
URL: http://svn.apache.org/viewvc?rev=1201909&view=rev
Log:
VCL-30
rework of the process connect methods routine
-- added support to Linux.pm for collect firewall configuration
-- added support for better manipulation of iptables if it exists
Modified:
incubator/vcl/trunk/managementnode/lib/VCL/Module/OS.pm
incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
incubator/vcl/trunk/managementnode/lib/VCL/inuse.pm
incubator/vcl/trunk/managementnode/lib/VCL/reserved.pm
Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS.pm
URL:
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS.pm?rev=1201909&r1=1201908&r2=1201909&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS.pm Mon Nov 14 21:15:16
2011
@@ -2046,14 +2046,32 @@ sub process_connect_methods {
my $connect_method_info = get_connect_method_info($imagerevision_id);
if (!$connect_method_info) {
notify($ERRORS{'WARNING'}, 0, "no connect methods are
configured for image revision $imagerevision_id");
+ return;
}
- my $remote_ip = $self->data->get_reservation_remote_ip();
+ my $remote_ip = shift;
if (!$remote_ip) {
- notify($ERRORS{'WARNING'}, 0, "reservation remote IP address is
not defined, connect methods will be available from any IP address");
- $remote_ip = '0.0.0.0/0.0.0.0';
+ notify($ERRORS{'OK'}, 0, "reservation remote IP address is not
defined, connect methods will be available from any IP address");
+ $remote_ip = '0.0.0.0/0';
+ }
+ elsif ($remote_ip =~ /any/i){
+ notify($ERRORS{'OK'}, 0, "reservation remote IP address is set
to ANY, connect methods will be available from any IP address");
+ $remote_ip = '0.0.0.0/0';
+ }
+ else {
+ $remote_ip .= "/24";
}
+ my $overwrite = shift;
+ if (!$overwrite) {
+ notify($ERRORS{'DEBUG'}, 0, "overwrite value was not passed as
an argument setting to 0");
+ $overwrite = 0;
+ }
+
+ my $state = $self->data->get_request_state_name();
+ notify($ERRORS{'DEBUG'}, 0, "state = $state");
+
+
CONNECT_METHOD: for my $connect_method_id (sort keys
%{$connect_method_info} ) {
notify($ERRORS{'DEBUG'}, 0, "processing connect method:\n" .
format_data($connect_method_info->{$connect_method_id}));
@@ -2065,10 +2083,33 @@ sub process_connect_methods {
my $startup_script =
$connect_method_info->{$connect_method_id}{startupscript};
my $install_script =
$connect_method_info->{$connect_method_id}{installscript};
my $disabled =
$connect_method_info->{$connect_method_id}{connectmethodmap}{disabled};
+
+ if( $state =~ /deleted|timeout/) {
+ $disabled = 1;
+ }
if ($disabled) {
- # TODO: Add code to disable the service, close the
firewall port, etc
- notify($ERRORS{'OK'}, 0, "skipping '$name' connect
method configuration, it should be disabled on $computer_node_name");
+ if ($self->service_exists($service_name)) {
+ notify($ERRORS{'DEBUG'}, 0, "attempting to stop '$service_name'
service for '$name' connect method on $computer_node_name");
+ if ($self->stop_service($service_name)) {
+ notify($ERRORS{'OK'}, 0, "'$service_name' stop on
$computer_node_name");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to stop
'$service_name' service for '$name' connect method on $computer_node_name");
+ }
+ }
+
+ #Disable firewall port
+ if (defined($port)) {
+ notify($ERRORS{'DEBUG'}, 0, "attempting to open firewall port
$port on $computer_node_name for '$name' connect method");
+ if ($self->disable_firewall_port($protocol, $port, $remote_ip, 1))
{
+ notify($ERRORS{'OK'}, 0, "closing firewall port $port on
$computer_node_name for $remote_ip $name connect method");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to close firewall port
$port on $computer_node_name for $remote_ip $name connect method");
+ }
+ }
+
}
else {
# Attempt to start and configure the connect method
@@ -2088,29 +2129,6 @@ sub process_connect_methods {
notify($ERRORS{'WARNING'}, 0,
"failed to start '$service_name' service for '$name' connect method on
$computer_node_name");
}
}
- #elsif ($install_script) {
- # notify($ERRORS{'DEBUG'}, 0,
"'$service_name' service for '$name' connect method does not exist on
$computer_node_name, attempting to execute connect method install script");
- # my ($install_exit_status,
$install_output) = $self->execute($install_script, 1, 600, 1);
- # if (!defined($install_output)) {
- # notify($ERRORS{'WARNING'}, 0,
"failed to run command to execute install script for '$name' connect method on
$computer_node_name, command: '$install_script'");
- # }
- # else {
- # notify($ERRORS{'OK'}, 0,
"executed install script for '$name' connect method on $computer_node_name,
command: '$install_script', exit status: $install_exit_status, output:\n" .
join("\n", @$install_output));
- #
- # if
($self->service_exists($service_name)) {
- # if
($self->start_service($service_name)) {
- #
notify($ERRORS{'OK'}, 0, "'$service_name' started on $computer_node_name");
- #
$service_started = 1;
- # }
- # else {
- #
notify($ERRORS{'WARNING'}, 0, "failed to start '$service_name' service after
executing install script for '$name' connect method on $computer_node_name");
- # }
- # }
- # else {
- #
notify($ERRORS{'WARNING'}, 0, "'$service_name' service does NOT exist after
executing install script for '$name' connect method on $computer_node_name");
- # }
- # }
- #}
else {
notify($ERRORS{'WARNING'}, 0,
"'$service_name' service for '$name' connect method does NOT exist on
$computer_node_name, connect method install script is not defined");
}
@@ -2134,11 +2152,11 @@ sub process_connect_methods {
# Open the firewall port
if (defined($port)) {
notify($ERRORS{'DEBUG'}, 0, "attempting to open
firewall port $port on $computer_node_name for '$name' connect method");
- if ($self->enable_firewall_port($protocol,
$port, "$remote_ip/24", 1)) {
- notify($ERRORS{'OK'}, 0, "opened
firewall port $port on $computer_node_name for '$name' connect method");
+ if ($self->enable_firewall_port($protocol,
$port, $remote_ip, 1)) {
+ notify($ERRORS{'OK'}, 0, "opened
firewall port $port on $computer_node_name for $remote_ip $name connect
method");
}
else {
- notify($ERRORS{'WARNING'}, 0, "failed
to open firewall port $port on $computer_node_name for '$name' connect method");
+ notify($ERRORS{'WARNING'}, 0, "failed
to open firewall port $port on $computer_node_name for $remote_ip $name connect
method");
}
}
}
Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm
URL:
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm?rev=1201909&r1=1201908&r2=1201909&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Linux.pm Mon Nov 14
21:15:16 2011
@@ -54,6 +54,7 @@ use diagnostics;
no warnings 'redefine';
use VCL::utils;
+use Net::Netmask;
##############################################################################
@@ -112,6 +113,7 @@ sub pre_capture {
my $computer_node_name = $self->data->get_computer_node_name();
notify($ERRORS{'OK'}, 0, "beginning Linux-specific image capture
preparation tasks");
+
if (!$self->file_exists("/root/.vclcontrol/vcl_exclude_list.sample")) {
notify($ERRORS{'DEBUG'}, 0, "/root/.vclcontrol/vcl_exclude_list.sample
does not exists");
@@ -131,9 +133,13 @@ sub pre_capture {
}
#Clean up connection methods
- if($self->process_connect_methods() ){
+ if($self->process_connect_methods("any", 1) ){
notify($ERRORS{'OK'}, 0, "processed connection methods on
$computer_node_name");
}
+
+ if(!$self->clean_iptables()) {
+ return 0;
+ }
# Try to clear /tmp
if ($self->execute("/usr/sbin/tmpwatch -f 0 /tmp; /bin/cp /dev/null
/var/log/wtmp")) {
@@ -233,6 +239,8 @@ sub post_load {
my $computer_short_name = $self->data->get_computer_short_name();
my $computer_node_name = $self->data->get_computer_node_name();
my $image_os_install_type = $self->data->get_image_os_install_type();
+ my $management_node_ip =
$self->data->get_management_node_ipaddress();
+ my $mn_private_ip =
$self->mn_os->get_private_ip_address();
notify($ERRORS{'OK'}, 0, "initiating Linux post_load: $image_name on
$computer_short_name");
@@ -303,6 +311,10 @@ sub post_load {
notify($ERRORS{'DEBUG'}, 0, "ran $script_path");
}
+ if($self->enable_firewall_port("tcp", "any", $mn_private_ip, 1) ){
+ notify($ERRORS{'OK'}, 0, "added MN_Priv_IP $mn_private_ip to firewall on
$computer_short_name");
+ }
+
# Attempt to generate ifcfg-eth* files and ifup any interfaces which
the file does not exist
$self->activate_interfaces();
@@ -960,8 +972,8 @@ sub grant_access {
} #foreach
notify($ERRORS{'OK'}, 0, "started ext_sshd on $computer_node_name");
- if($self->process_connect_methods('start') ){
- notify($ERRORS{'OK'}, 0, "processed connection methods on
$computer_node_name");
+ if($self->process_connect_methods("", 1) ){
+ notify($ERRORS{'OK'}, 0, "processed connection methods on
$computer_node_name setting 0.0.0.0 for all allowed ports");
}
@@ -1024,6 +1036,7 @@ 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()) {
@@ -1040,7 +1053,7 @@ sub sanitize {
}
#Clean up connection methods
- if($self->process_connect_methods() ){
+ if($self->process_connect_methods($mn_private_ip, 1) ){
notify($ERRORS{'OK'}, 0, "processed connection methods on
$computer_node_name");
}
@@ -3038,10 +3051,14 @@ sub service_exists {
notify($ERRORS{'DEBUG'}, 0, "'$service_name' service does not
exist on $computer_node_name");
return 0;
}
- elsif ($exit_status == 0 || grep(/not referenced in any runlevel/i,
@$output)) {
+ elsif (defined($exit_status) && $exit_status == 0 ) {
+ notify($ERRORS{'DEBUG'}, 0, "'$service_name' service exists");
+ return 1;
+ }
+ elsif (defined($exit_status) && grep(/not referenced in any runlevel/i,
@$output)) {
# chkconfig may display the following if the service exists but
has not been added:
# service ext_sshd supports chkconfig, but is not referenced in
any runlevel (run 'chkconfig --add ext_sshd')
- notify($ERRORS{'DEBUG'}, 0, "'$service_name' service exists but
is not referenced in any runlevel");
+ notify($ERRORS{'DEBUG'}, 0, "'$service_name' service exists but
is not referenced in any runlevel: output:\n" . join("\n", @$output));
}
else {
notify($ERRORS{'WARNING'}, 0, "unable to determine if
'$service_name' service exists, exit status: $exit_status, output:\n" .
join("\n", @$output));
@@ -3349,6 +3366,45 @@ sub get_total_memory {
#/////////////////////////////////////////////////////////////////////////////
+=head2 sanitize_firewall
+
+ Parameters : $scope (optional),
+ Returns : boolean
+ Description : Removes all entries for INUPT chain and Sets iptables firewall
for private management node IP
+
+=cut
+
+sub sanitize_firewall {
+ my $self = shift;
+ 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 $scope = shift;
+ if(!defined($scope)) {
+ notify($ERRORS{'CRITICAL'}, 0, "scope variable was not passed
in as an arguement");
+ return;
+ }
+
+ my $computer_node_name = $self->data->get_computer_node_name();
+ my $mn_private_ip = $self->mn_os->get_private_ip_address();
+
+ my $firewall_configuration = $self->get_firewall_configuration() ||
return;
+ my $chain;
+ my $iptables_del_cmd;
+ my $INPUT_CHAIN = "INPUT";
+
+ for my $num (sort keys %{$firewall_configuration->{$INPUT_CHAIN}} ) {
+
+
+ }
+
+
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
=head2 enable_firewall_port
Parameters : $protocol, $port, $scope (optional), $overwrite_existing
(optional), $name (optional), $description (optional)
@@ -3364,6 +3420,13 @@ sub enable_firewall_port {
return;
}
+ # Check to see if this distro has iptables
+ # If not return 1 so it does not fail
+ if (!($self->service_exists("iptables"))) {
+ notify($ERRORS{'WARNING'}, 0, "iptables does not exist on this
OS");
+ return 1;
+ }
+
my ($protocol, $port, $scope_argument, $overwrite_existing, $name,
$description) = @_;
if (!defined($protocol) || !defined($port)) {
notify($ERRORS{'WARNING'}, 0, "protocol and port arguments were
not supplied");
@@ -3371,12 +3434,114 @@ sub enable_firewall_port {
}
my $computer_node_name = $self->data->get_computer_node_name();
+ my $mn_private_ip = $self->mn_os->get_private_ip_address();
$protocol = lc($protocol);
- my $command = "/sbin/iptables -I INPUT 1 -m state --state
NEW,RELATED,ESTABLISHED -m $protocol -p $protocol --dport $port -j ACCEPT";
+ $scope_argument = '' if (!defined($scope_argument));
+
+ $name = '' if !$name;
+ $description = '' if !$description;
+
+ my $scope;
+
+ my $INPUT_CHAIN = "INPUT";
+
+
+ my $firewall_configuration = $self->get_firewall_configuration() ||
return;
+ my $chain;
+ my $iptables_del_cmd;
+
+ for my $num (sort keys %{$firewall_configuration->{$INPUT_CHAIN}} ) {
+ my $existing_scope =
$firewall_configuration->{$INPUT_CHAIN}{$num}{$protocol}{$port}{scope} || '';
+ my $existing_name =
$firewall_configuration->{$INPUT_CHAIN}{$num}{$protocol}{$port}{name} || '';
+ my $existing_description =
$firewall_configuration->{$INPUT_CHAIN}{$num}{$protocol}{$port}{name} || '';
+
+ if ($existing_scope) {
+ notify($ERRORS{'DEBUG'}, 0, " num= $num protocol=
$protocol port= $port existing_scope= $existing_scope existing_name=
$existing_name existing_description= $existing_description ");
+
+ if ($overwrite_existing) {
+ $scope = $self->parse_firewall_scope($scope_argument);
+ $iptables_del_cmd = "iptables -D $INPUT_CHAIN
$num";
+ if (!$scope) {
+ notify($ERRORS{'WARNING'}, 0, "failed to parse firewall scope
argument: '$scope_argument'");
+ return;
+ }
+
+ notify($ERRORS{'DEBUG'}, 0, "existing firewall opening on
$computer_node_name will be replaced:\n" .
+ "name: '$existing_name'\n" .
+ "num: '$num'\n" .
+ "protocol: $protocol\n" .
+ "port/type: $port\n" .
+ "existing scope: '$existing_scope'\n" .
+ "new scope: $scope\n" .
+ "overwrite existing rule: " . ($overwrite_existing ? 'yes' : 'no')
+ );
+ }
+ else {
+ my $parsed_existing_scope =
$self->parse_firewall_scope($existing_scope);
+ if (!$parsed_existing_scope) {
+ notify($ERRORS{'WARNING'}, 0, "failed to parse existing
firewall scope: '$existing_scope'");
+ return;
+ }
+
+ $scope =
$self->parse_firewall_scope("$scope_argument,$existing_scope");
+ if (!$scope) {
+ notify($ERRORS{'WARNING'}, 0, "failed to parse firewall scope
argument appended with existing scope: '$scope_argument,$existing_scope'");
+ return;
+ }
+
+ if ($scope eq $parsed_existing_scope) {
+ notify($ERRORS{'DEBUG'}, 0, "firewall is already open on
$computer_node_name, existing scope matches scope argument:\n" .
+ "name: '$existing_name'\n" .
+ "protocol: $protocol\n" .
+ "port/type: $port\n" .
+ "scope: $scope\n" .
+ "overwrite existing rule: " . ($overwrite_existing ? 'yes' :
'no')
+ );
+ return 1;
+ }
+ }
+ }
+ else {
+ next;
+ }
+ }
+
+ if(!$scope) {
+ $scope = $self->parse_firewall_scope($scope_argument);
+ if (!$scope) {
+ notify($ERRORS{'WARNING'}, 0, "failed to parse firewall
scope argument: '$scope_argument'");
+ return;
+ }
+ }
+
+
+ $name = "VCL: allow $protocol/$port from $scope" if !$name;
+
+ $name = substr($name, 0, 60) . "..." if length($name) > 60;
+
+ my $command;
+
+ if ($iptables_del_cmd ){
+ $command = "$iptables_del_cmd ; ";
+
+ }
+
+ $command .= "/sbin/iptables -I INPUT 1 -m state --state
NEW,RELATED,ESTABLISHED -m $protocol -p $protocol -j ACCEPT";
+
+ if ($port =~ /\d+/){
+ $command .= " --dport $port";
+ }
+
+ if ($scope_argument) {
+ # if($scope_argument eq '0.0.0.0') {
+ # $scope_argument .= "/0";
+ # }
+ # else {
+ # $scope_argument .= "/24";
+ # }
- if ($scope_argument) {
$command .= " -s $scope_argument";
}
@@ -3426,36 +3591,61 @@ sub disable_firewall_port {
return;
}
- my $port = shift;
- if(!$port) {
- notify($ERRORS{'CRITICAL'}, 0, "Input variable port was not passed in as
an argument");
- return 0;
+ # Check to see if this distro has iptables
+ # If not return 1 so it does not fail
+ if (!($self->service_exists("iptables"))) {
+ notify($ERRORS{'WARNING'}, 0, "iptables does not exist on this OS");
+ return 1;
}
+
+ my ($protocol, $port, $scope_argument, $overwrite_existing, $name,
$description) = @_;
+ if (!defined($protocol) || !defined($port)) {
+ notify($ERRORS{'WARNING'}, 0, "protocol and port arguments were not
supplied");
+ return;
+ }
my $computer_node_name = $self->data->get_computer_node_name();
- my $remote_ip = $self->data->get_reservation_remote_ip();
+ my $mn_private_ip = $self->mn_os->get_private_ip_address();
- my $command = "sed -i -e '/.*-p tcp --dport $port -j ACCEPT$/d'
/etc/sysconfig/iptables";
- my ($status, $output) = $self->execute($command);
+ $protocol = lc($protocol);
- if (defined $status && $status == 0) {
- notify($ERRORS{'DEBUG'}, 0, "executed command $command on
$computer_node_name");
- }
- else {
- notify($ERRORS{'WARNING'}, 0, "output from iptables:" . join("\n",
@$output));
- }
-
- #restart iptables
- $command = "/etc/init.d/iptables restart";
- my ($status_iptables,$output_iptables) = $self->execute($command);
- if (defined $status_iptables && $status_iptables == 0) {
- notify($ERRORS{'DEBUG'}, 0, "executed command $command on
$computer_node_name");
- }
- else {
- notify($ERRORS{'WARNING'}, 0, "output from iptables:" . join("\n",
@$output_iptables));
- }
+ $scope_argument = '' if (!defined($scope_argument));
- return 1;
+ $name = '' if !$name;
+ $description = '' if !$description;
+
+ my $scope;
+
+ my $INPUT_CHAIN = "INPUT";
+
+ my $firewall_configuration = $self->get_firewall_configuration() || return;
+ my $chain;
+ my $command;
+
+ for my $num (sort keys %{$firewall_configuration->{$INPUT_CHAIN}} ) {
+ my $existing_scope =
$firewall_configuration->{$INPUT_CHAIN}{$num}{$protocol}{$port}{scope} || '';
+ my $existing_name =
$firewall_configuration->{$INPUT_CHAIN}{$num}{$protocol}{$port}{name} || '';
+ if($existing_scope) {
+ $command = "iptables -D $INPUT_CHAIN $num";
+
+ notify($ERRORS{'DEBUG'}, 0, "attempting to execute
command on $computer_node_name: '$command'");
+ my ($status, $output) = $self->execute($command);
+ if (defined $status && $status == 0) {
+ notify($ERRORS{'DEBUG'}, 0, "executed command on
$computer_node_name: '$command'");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "output from iptables:\n"
. join("\n", @$output));
+ }
+
+ # Save rules to sysconfig/iptables -- incase of reboot
+ my $iptables_save_cmd = "/sbin/iptables-save >
/etc/sysconfig/iptables";
+ my ($status_save, $output_save) =
$self->execute($iptables_save_cmd);
+ if (defined $status_save && $status_save == 0) {
+ notify($ERRORS{'DEBUG'}, 0, "executed command
$iptables_save_cmd on $computer_node_name");
+ }
+ }
+ }
+ return 1;
}
@@ -3557,9 +3747,486 @@ sub generate_vclcontrol_sample_files {
return 1;
}
-##/////////////////////////////////////////////////////////////////////////////
+=head2 get_firewall_configuration
+
+ Parameters : none
+ Returns : hash reference
+ Description : Retrieves information about the open firewall ports on the
+ computer and constructs a hash. The hash keys are protocol
names.
+ Each protocol key contains a hash reference. The keys are either
+ port numbers or ICMP types.
+ Example:
+
+ "ICMP" => {
+ 8 => {
+ "description" => "Allow inbound echo request"
+ }
+ },
+ "TCP" => {
+ 22 => {
+ "interface_names" => [
+ "Local Area Connection 3"
+ ],
+ "name" => "sshd"
+ },
+ 3389 => {
+ "name" => "Remote Desktop",
+ "scope" => "192.168.53.54/255.255.255.255"
+ },
+
+=cut
+
+sub get_firewall_configuration {
+ 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;
+ }
+
+ my $computer_node_name = $self->data->get_computer_node_name();
+ my $firewall_configuration = {};
+
+ # Check to see if this distro has iptables
+ # If not return 1 so it does not fail
+ if (!($self->service_exists("iptables"))) {
+ notify($ERRORS{'WARNING'}, 0, "iptables does not exist on this OS");
+ return 1;
+ }
+
+ my $port_command = "iptables -L --line-number -n";
+ my ($iptables_exit_status, $output_iptables) =
$self->execute($port_command);
+ if (!defined($output_iptables)) {
+ notify($ERRORS{'WARNING'}, 0, "failed to run command to show open
firewall ports on $computer_node_name");
+ return;
+ }
+
+ #notify($ERRORS{'DEBUG'}, 0, "output from iptables:\n" . join("\n",
@$output_iptables));
+
+
+ # Execute the iptables -L --line-number -n command to retrieve firewall
port openings
+ # Expected output:
+ #Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
+ #num target prot opt source destination
+ #1 RH-Firewall-1-INPUT all -- 0.0.0.0/0 0.0.0.0/0
+
+ #Chain FORWARD (policy ACCEPT)
+ #num target prot opt source destination
+ #1 RH-Firewall-1-INPUT all -- 0.0.0.0/0 0.0.0.0/0
+
+ #Chain OUTPUT (policy ACCEPT)
+ #num target prot opt source destination
+
+ #Chain RH-Firewall-1-INPUT (2 references)
+ #num target prot opt source destination
+ #1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
+ #2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
+ #3 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmp
type 255
+ #4 ACCEPT esp -- 0.0.0.0/0 0.0.0.0/0
+ #5 ACCEPT ah -- 0.0.0.0/0 0.0.0.0/0
+ #6 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
state RELATED,ESTABLISHED
+ #7 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0
state NEW tcp dpt:22
+ #8 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0
state NEW tcp dpt:3389
+ #9 REJECT all -- 0.0.0.0/0 0.0.0.0/0
reject-with icmp-host-prohibited
+
+
+ my $chain;
+ my $previous_protocol;
+ my $previous_port;
+
+ for my $line (@$output_iptables) {
+ if ($line =~ /^Chain\s+(\S+)\s+(.*)/ig) {
+ $chain = $1;
+ notify($ERRORS{'DEBUG'}, 0, "output Chain = $chain");
+ }
+ elsif($line =~
/^(\d+)\s+([A-Z]*)\s+([a-z]*)\s+(--)\s+(\S+)\s+(\S+)\s+(.*)/ig ) {
+
+ my $num = $1;
+ my $target = $2;
+ my $protocol = $3;
+ my $scope = $5;
+ my $destination =$6;
+ my $port_string = $7 if (defined($7));
+ my $port = '';
+ my $name;
+
+
+ if (defined($port_string) && ($port_string =~
/([\s(a-zA-Z)]*)(dpt:)(\d+)/ig )){
+ $port = $3;
+ notify($ERRORS{'DEBUG'}, 0, "output rule: $num,
$target, $protocol, $scope, $destination, $port ");
+ }
+
+ if (!$port) {
+ $port = "any";
+ }
+
+ my $services_cmd = "cat /etc/services";
+ my ($services_status, $service_output) =
$self->execute($services_cmd);
+ if (!defined($service_output)) {
+ notify($ERRORS{'DEBUG'}, 0, "failed to get /etc/services");
+ }
+ else {
+ for my $sline (@$service_output) {
+ if ( $sline =~
/(^[_-a-zA-Z1-9]+)\s+($port\/$protocol)\s+(.*) /ig ){
+ $name = $1;
+ }
+ }
+
+ }
+
+ $name = $port if (!$name);
+
+
$firewall_configuration->{$chain}->{$num}{$protocol}{$port}{name}= $name;
+
$firewall_configuration->{$chain}->{$num}{$protocol}{$port}{number}= $num;
+
$firewall_configuration->{$chain}->{$num}{$protocol}{$port}{scope}= $scope;
+
$firewall_configuration->{$chain}->{$num}{$protocol}{$port}{target}= $target;
+
$firewall_configuration->{$chain}->{$num}{$protocol}{$port}{destination}=
$destination;
+
+
+ if (!defined($previous_protocol) ||
+ !defined($previous_port) ||
+ !defined($firewall_configuration->{$previous_protocol}) ||
+
!defined($firewall_configuration->{$previous_protocol}{$previous_port})
+ ) {
+ next;
+ }
+ elsif ($scope !~ /0.0.0.0\/0/) {
+
$firewall_configuration->{$previous_protocol}{$previous_port}{scope} = $scope;
+ }
+ }
+ }
+
+ notify($ERRORS{'DEBUG'}, 0, "retrieved firewall configuration from
$computer_node_name:\n" . format_data($firewall_configuration));
+ return $firewall_configuration;
+
+
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 parse_firewall_scope
+
+ Parameters : @scope_strings
+ Returns : string
+ Description : Parses an array of firewall scope strings and collpases them
into
+ a simplified scope if possible. A comma-separated string is
+ returned. The scope string argument may be in the form:
+ -192.168.53.54/255.255.255.192
+ -192.168.53.54/24
+ -192.168.53.54
+ -*
+ -Any
+ -LocalSubnet
+
+=cut
+
+sub parse_firewall_scope {
+ 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;
+ }
+
+ my @scope_strings = @_;
+ if (!@scope_strings) {
+ notify($ERRORS{'WARNING'}, 0, "scope array argument was not supplied");
+ return;
+ }
+
+ my @netmask_objects;
+
+ for my $scope_string (@scope_strings) {
+ if ($scope_string =~ /(\*|Any)/i) {
+ my $netmask_object = new Net::Netmask('any');
+ push @netmask_objects, $netmask_object;
+ }
+
+ elsif ($scope_string =~ /LocalSubnet/i) {
+ my $network_configuration = $self->get_network_configuration() ||
return;
+
+ for my $interface_name (sort keys %$network_configuration) {
+ for my $ip_address (keys
%{$network_configuration->{$interface_name}{ip_address}}) {
+ my $subnet_mask =
$network_configuration->{$interface_name}{ip_address}{$ip_address};
+
+ my $netmask_object_1 = new
Net::Netmask("$ip_address/$subnet_mask");
+ if ($netmask_object_1) {
+ push @netmask_objects, $netmask_object_1;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to create Net::Netmask
object, IP address: $ip_address, subnet mask: $subnet_mask");
+ return;
+ }
+ }
+ }
+ }
+
+ elsif (my @scope_sections = split(/,/, $scope_string)) {
+ for my $scope_section (@scope_sections) {
+
+ if (my ($start_address, $end_address) = $scope_section =~
/^([\d\.]+)-([\d\.]+)$/) {
+ my @netmask_range_objects =
Net::Netmask::range2cidrlist($start_address, $end_address);
+ if (@netmask_range_objects) {
+ push @netmask_objects, @netmask_range_objects;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to call
Net::Netmask::range2cidrlist to create an array of objects covering IP range:
$start_address-$end_address");
+ return;
+ }
+ }
+
+ elsif (my ($ip_address, $subnet_mask) = $scope_section =~
/^([\d\.]+)\/([\d\.]+)$/) {
+ my $netmask_object = new
Net::Netmask("$ip_address/$subnet_mask");
+ if ($netmask_object) {
+ push @netmask_objects, $netmask_object;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to create Net::Netmask
object, IP address: $ip_address, subnet mask: $subnet_mask");
+ return;
+ }
+ }
+
+ elsif (($ip_address) = $scope_section =~ /^([\d\.]+)$/) {
+ my $netmask_object = new Net::Netmask("$ip_address");
+ if ($netmask_object) {
+ push @netmask_objects, $netmask_object;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to create Net::Netmask
object, IP address: $ip_address");
+ return;
+ }
+ }
+
+ else {
+ notify($ERRORS{'WARNING'}, 0, "unable to parse '$scope_section'
section of scope: '$scope_string'");
+ return;
+ }
+ }
+ }
+
+ else {
+ notify($ERRORS{'WARNING'}, 0, "unexpected scope format:
'$scope_string'");
+ return
+ }
+ }
+
+ my @netmask_objects_collapsed = cidrs2cidrs(@netmask_objects);
+ if (@netmask_objects_collapsed) {
+ my $scope_result_string;
+ my @ip_address_ranges;
+ for my $netmask_object (@netmask_objects_collapsed) {
+
+ if ($netmask_object->first() eq $netmask_object->last()) {
+ push @ip_address_ranges, $netmask_object->first();
+ $scope_result_string .= $netmask_object->base() . ",";
+ }
+ else {
+ push @ip_address_ranges, $netmask_object->first() . "-" .
$netmask_object->last();
+ $scope_result_string .= $netmask_object->base() . "/" .
$netmask_object->mask() . ",";
+ }
+ }
+
+ $scope_result_string =~ s/,+$//;
+ my $argument_string = join(",", @scope_strings);
+ if ($argument_string ne $scope_result_string) {
+ notify($ERRORS{'DEBUG'}, 0, "parsed firewall scope:\n" .
+ "argument: '$argument_string'\n" .
+ "result: '$scope_result_string'\n" .
+ "IP address ranges:\n" . join(", ", @ip_address_ranges)
+ );
+ }
+ return $scope_result_string;
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "failed to parse firewall scope: '" .
join(",", @scope_strings) . "', no Net::Netmask objects were created");
+ return;
+ }
+}
+
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 firewall_compare_update
+
+ Parameters : @scope_strings
+ Returns : 0 , 1
+ Description : Compare iptables for listed remote IP address in reservation
+
+=cut
+
+sub firewall_compare_update {
+ 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;
+ }
+
+ # Check to see if this distro has iptables
+ # If not return 1 so it does not fail
+ if (!($self->service_exists("iptables"))) {
+ notify($ERRORS{'WARNING'}, 0, "iptables does not exist on this OS");
+ return 1;
+ }
+
+ my $computer_node_name = $self->data->get_computer_node_name();
+ my $imagerevision_id = $self->data->get_imagerevision_id();
+ my $remote_ip =
$self->data->get_reservation_remote_ip();
+
+ #collect connection_methods
+ #collect firewall_config
+ #For each port defined in connection_methods
+ #compare rule source address with remote_IP address
+
+ # Retrieve the connect method info hash
+ my $connect_method_info = get_connect_method_info($imagerevision_id);
+ if (!$connect_method_info) {
+ notify($ERRORS{'WARNING'}, 0, "no connect methods are configured for
image revision $imagerevision_id");
+ return;
+ }
+
+ # Retrieve the firewall configuration
+ my $INPUT_CHAIN = "INPUT";
+ my $firewall_configuration = $self->get_firewall_configuration() || return;
+
+ for my $connect_method_id (sort keys %{$connect_method_info} ) {
+
+ my $name = $connect_method_info->{$connect_method_id}{name};
+ my $description =
$connect_method_info->{$connect_method_id}{description};
+ my $protocol =
$connect_method_info->{$connect_method_id}{protocol} || 'TCP';
+ my $port = $connect_method_info->{$connect_method_id}{port};
+ my $scope;
+
+ $protocol = lc($protocol);
+
+ for my $num (sort keys
%{$firewall_configuration->{$INPUT_CHAIN}} ) {
+ my $existing_scope =
$firewall_configuration->{$INPUT_CHAIN}{$num}{$protocol}{$port}{scope} || '';
+ if(!$existing_scope ) {
+ }
+ else {
+ my $parsed_existing_scope =
$self->parse_firewall_scope($existing_scope);
+ if (!$parsed_existing_scope) {
+ notify($ERRORS{'WARNING'}, 0, "failed to parse existing
firewall scope: '$existing_scope'");
+ return;
+ }
+ $scope =
$self->parse_firewall_scope("$remote_ip,$existing_scope");
+ if (!$scope) {
+ notify($ERRORS{'WARNING'}, 0, "failed to parse firewall scope
argument appended with existing scope: '$remote_ip,$existing_scope'");
+ return;
+ }
+
+ if ($scope eq $parsed_existing_scope) {
+ notify($ERRORS{'DEBUG'}, 0, "firewall is already open on
$computer_node_name, existing scope matches scope argument:\n" .
+ "name: '$name'\n" .
+ "protocol: $protocol\n" .
+ "port/type: $port\n" .
+ "scope: $scope\n");
+ return 1;
+ }
+ else {
+ if
($self->enable_firewall_port($protocol, $port, "$remote_ip/24", 0)) {
+ notify($ERRORS{'OK'}, 0, "opened firewall port $port on
$computer_node_name for $remote_ip $name connect method");
+ }
+ }
+
+
+ }
+ }
+ }
+
+ return 1;
+
+}
+
+#/////////////////////////////////////////////////////////////////////////////
+
+=head2 clean_iptables
+
+ Parameters :
+ Returns : 0 , 1
+ Description : Deletes rules with any leftover -s addresses
+
+=cut
+
+sub clean_iptables {
+ 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;
+ }
+
+ # Check to see if this distro has iptables
+ # If not return 1 so it does not fail
+ if (!($self->service_exists("iptables"))) {
+ notify($ERRORS{'WARNING'}, 0, "iptables does not exist on this OS");
+ return 1;
+ }
+
+ my $computer_node_name = $self->data->get_computer_node_name();
+ my $reservation_id = $self->data->get_reservation_id();
+ my $management_node_keys = $self->data->get_management_node_keys();
+
+ # Retrieve the firewall configuration
+ my $INPUT_CHAIN = "INPUT";
+
+ # Retrieve the iptables file to work on locally
+ my $tmpfile = "/tmp/" . $reservation_id . "_iptables";
+ my $source_file_path = "/etc/sysconfig/iptables";
+ if (run_scp_command("$computer_node_name:\"$source_file_path\"",
$tmpfile, $management_node_keys)) {
+ my @lines;
+ if(open(IPTAB_TMPFILE, $tmpfile)){
+ @lines = <IPTAB_TMPFILE>;
+ close(IPTAB_TMPFILE);
+ }
+ foreach my $line (@lines){
+ if ($line =~ s/-A INPUT -s .*\n//) {
+ }
+ }
+
+ #Rewrite array to tmpfile
+ if(open(IPTAB_TMPFILE, ">$tmpfile")){
+ print IPTAB_TMPFILE @lines;
+ close (IPTAB_TMPFILE);
+ }
+
+ # Copy iptables file back to node
+ if (run_scp_command($tmpfile,
"$computer_node_name:\"$source_file_path\"", $management_node_keys)) {
+ notify($ERRORS{'DEBUG'}, 0, "copied $tmpfile to
$computer_node_name $source_file_path");
+ }
+ }
+
+
+ #my $command = "sed -i -e '/-A INPUT -s */d' /etc/sysconfig/iptables";
+ #my ($status, $output) = $self->execute($command);
+
+ #if (defined $status && $status == 0) {
+ # notify($ERRORS{'DEBUG'}, 0, "executed command $command on
$computer_node_name");
+ #}
+ #else {
+ # notify($ERRORS{'WARNING'}, 0, "output from iptables:" . join("\n",
@$output));
+ #}
+
+ #restart iptables
+ my $command = "/etc/init.d/iptables restart";
+ my ($status_iptables,$output_iptables) = $self->execute($command);
+ if (defined $status_iptables && $status_iptables == 0) {
+ notify($ERRORS{'DEBUG'}, 0, "executed command $command on
$computer_node_name");
+ }
+ else {
+ notify($ERRORS{'WARNING'}, 0, "output from iptables:" . join("\n",
@$output_iptables));
+ }
+
+ if ($self->wait_for_ssh(0)) {
+ return 1;
+ }
+ else {
+ notify($ERRORS{'CRITICAL'}, 0, "not able to login via ssh after
cleaning_iptables");
+ return 0;
+ }
+
+}
+
+
+##/////////////////////////////////////////////////////////////////////////////
1;
__END__
Modified: incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm
URL:
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm?rev=1201909&r1=1201908&r2=1201909&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/Module/OS/Windows.pm Mon Nov 14
21:15:16 2011
@@ -947,7 +947,7 @@ sub grant_access {
# Set the $remote_ip_range variable to the string 'all' if it isn't
already set (for display purposes)
$remote_ip_range = 'all' if !$remote_ip_range;
- if($self->process_connect_methods('start') ){
+ if($self->process_connect_methods("0.0.0.0", 1) ){
notify($ERRORS{'OK'}, 0, "processed connection methods on
$computer_node_name");
}
Modified: incubator/vcl/trunk/managementnode/lib/VCL/inuse.pm
URL:
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/inuse.pm?rev=1201909&r1=1201908&r2=1201909&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/inuse.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/inuse.pm Mon Nov 14 21:15:16 2011
@@ -187,6 +187,12 @@ sub process {
# Is this a poll or end time
if ($request_checktime eq "poll") {
notify($ERRORS{'OK'}, 0, "beginning to poll");
+
+ if ($self->os->can('firewall_compare_update')) {
+ if ($self->os->firewall_compare_update()) {
+ notify($ERRORS{'OK'}, 0, "confirmed firewall
scope has been updated");
+ }
+ }
if ($image_os_type =~ /windows/) {
if (firewall_compare_update($computer_nodename,
$reservation_remoteip, $identity_key, $image_os_type)) {
Modified: incubator/vcl/trunk/managementnode/lib/VCL/reserved.pm
URL:
http://svn.apache.org/viewvc/incubator/vcl/trunk/managementnode/lib/VCL/reserved.pm?rev=1201909&r1=1201908&r2=1201909&view=diff
==============================================================================
--- incubator/vcl/trunk/managementnode/lib/VCL/reserved.pm (original)
+++ incubator/vcl/trunk/managementnode/lib/VCL/reserved.pm Mon Nov 14 21:15:16
2011
@@ -336,6 +336,10 @@ sub process {
notify($ERRORS{'OK'}, 0, "$remote_ip connected to $nodename");
insertloadlog($reservation_id, $computer_id, "connected",
"reserved: user connected to remote machine");
+
+ if($self->os->process_connect_methods($remote_ip, 1)) {
+ notify($ERRORS{'OK'}, 0, "process_connect_methods
return successfully $remote_ip $nodename");
+ }
# Update the request state to either inuse or imageinuse
if (update_request_state($request_id, "inuse", "reserved")) {
@@ -368,6 +372,10 @@ sub process {
elsif ($retval_conn eq "conn_wrong_ip") {
# does the same as above, until we make a firm decision as to
how to handle this
+ if($self->os->process_connect_methods($remote_ip, 1)) {
+ notify($ERRORS{'OK'}, 0, "process_connect_methods return successfully
$remote_ip $nodename");
+ }
+
# Update the request state to inuse
if (update_request_state($request_id, "inuse", "reserved")) {
notify($ERRORS{'OK'}, 0, "setting request into inuse
state");
@@ -391,6 +399,7 @@ sub process {
else {
notify($ERRORS{'CRITICAL'}, 0, "unable to update
lastcheck time for reservation $reservation_id");
}
+
notify($ERRORS{'OK'}, 0, "exiting");
exit;