sub delete_user()

in managementnode/lib/VCL/Module/OS/Linux.pm [3058:3226]


sub delete_user {
	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;
	}
	
	# Make sure the user login ID was passed
	my $username = shift;
	$username = $self->data->get_user_login_id() if (!$username);
	if (!$username) {
		notify($ERRORS{'WARNING'}, 0, "user could not be determined");
		return;
	}
	
	my $computer_node_name = $self->data->get_computer_node_name();
	
	# Make sure the user exists
	if (!$self->user_exists($username)) {
		notify($ERRORS{'DEBUG'}, 0, "user NOT deleted from $computer_node_name because it does not exist: $username");
		
		# Make sure user does not exist in sudoers
		$self->revoke_administrative_access($username);
		
		return 1;
	}
	
	# Check if the user is logged in
	if ($self->user_logged_in($username)) {
		if (!$self->logoff_user($username)) {
			notify($ERRORS{'WARNING'}, 0, "failed to delete user $username from $computer_node_name, user appears to be logged in but could NOT be logged off");
			return;
		}
	}
	
	# Determine if home directory is on a local device or network share
	my $home_directory_path = "/home/$username";
	my $home_directory_on_local_disk = $self->is_file_on_local_disk($home_directory_path);
	
	# Assemble the userdel command
	my $userdel_command = "/usr/sbin/userdel";
	
	my $delete_home_directory = 0;
	
	if ($home_directory_on_local_disk) {
		$delete_home_directory = 1;
		
		# Fetch exclude_list
		my @exclude_list = $self->get_exclude_list();
		if ((grep(/\/home\/$username/, @exclude_list))) {
			notify($ERRORS{'DEBUG'}, 0, "home directory will NOT be deleted: $home_directory_path");
			$delete_home_directory = 0;
		}
		else {
			# Make sure no NFS shares are mounted under home directory
			my @nfs_mount_strings = $self->get_nfs_mount_strings();
			for my $nfs_mount_string (@nfs_mount_strings) {
				my ($nfs_remote_host, $nfs_remote_path, $nfs_local_path) = $nfs_mount_string =~
					/
						^
						([^:]+)		# Remote hostname or IP address
						:
						(\/.+)		# Remote path
						\s+
						(\/.+)		# Local path
						\s+
						nfs\d*		# ' nfs ' or ' nfs4 '
						\s+
					/gx;
				
				if ($nfs_local_path) {
					if ($nfs_local_path =~ /^$home_directory_path/) {
						notify($ERRORS{'WARNING'}, 0, "home directory will NOT be deleted, NFS share is mounted under it\n" .
							"NFS mount string    : $nfs_mount_string\n" .
							"home directory path : $home_directory_path\n" .
							"local mount path    : $nfs_local_path"
						);
						$delete_home_directory = 0;
						last;
					}
					else {
						notify($ERRORS{'DEBUG'}, 0, "NFS share is NOT mounted under home directory\n" .
							"NFS mount string    : $nfs_mount_string\n" .
							"home directory path : $home_directory_path\n" .
							"local mount path    : $nfs_local_path"
						);
					}
				}
				else {
					notify($ERRORS{'WARNING'}, 0, "home directory will NOT be deleted: $home_directory_path, failed to parse NFS mount string: $nfs_mount_string");
					$delete_home_directory = 0;
					last;
				}
			}
		}
	}
	
	if ($delete_home_directory) {
		notify($ERRORS{'DEBUG'}, 0, "home directory will be deleted: $home_directory_path");
		$userdel_command .= ' -r';
	}
	$userdel_command .= " $username";
	
	# Call userdel to delete the user
	my ($userdel_exit_status, $userdel_output) = $self->execute($userdel_command);
	if (!defined($userdel_output)) {
		notify($ERRORS{'WARNING'}, 0, "failed to execute command to delete user from $computer_node_name: $username");
		return;
	}
	elsif (grep(/does not exist/i, @$userdel_output)) {
		notify($ERRORS{'DEBUG'}, 0, "user '$username' NOT deleted from $computer_node_name because it does not exist");
	}
	elsif (grep(/not found/i, @$userdel_output)) {
		notify($ERRORS{'DEBUG'}, 0, "userdel warning '$username' $computer_node_name :\n" . join("\n", @$userdel_output));
	}
	elsif (grep(/userdel: /i, @$userdel_output)) {
		notify($ERRORS{'WARNING'}, 0, "failed to delete user '$username' from $computer_node_name, command: '$userdel_command', exit status: $userdel_exit_status, output:\n" . join("\n", @$userdel_output));
		return;
	}
	else {
		notify($ERRORS{'OK'}, 0, "deleted user '$username' from $computer_node_name");
	}
	
	# Call groupdel to delete the user's group
	my $groupdel_command = "/usr/sbin/groupdel $username";
	my ($groupdel_exit_status, $groupdel_output) = $self->execute($groupdel_command);
	if (!defined($groupdel_output)) {
		notify($ERRORS{'WARNING'}, 0, "failed to execute command to delete group from $computer_node_name: $username");
		return;
	}
	elsif (grep(/does not exist/i, @$groupdel_output)) {
		notify($ERRORS{'DEBUG'}, 0, "group '$username' NOT deleted from $computer_node_name because it does not exist");
	}
	elsif (grep(/groupdel: /i, @$groupdel_output)) {
		notify($ERRORS{'WARNING'}, 0, "failed to delete group '$username' from $computer_node_name, command: '$groupdel_command', output:\n" . join("\n", @$groupdel_output));
	}
	else {
		notify($ERRORS{'OK'}, 0, "deleted group '$username' from $computer_node_name");
	}
	
	# Remove username from AllowUsers lines in ssh/external_sshd_config
	my $external_sshd_config_file_path = '/etc/ssh/external_sshd_config';
	my @original_lines = $self->get_file_contents($external_sshd_config_file_path);
	my @modified_lines;
	my $new_file_contents;
	for my $line (@original_lines) {
		if ($line =~ /AllowUsers.*\s$username(\s|$)/) {
			push @modified_lines, $line;
			$line =~ s/\s*$username//g;
			# If user was only username listed on line, don't add empty AllowUsers line back to file
			if ($line !~ /AllowUsers\s+\w/) {
				next;
			}
		}
		$new_file_contents .= "$line\n";
	}
	if (@modified_lines) {
		notify($ERRORS{'OK'}, 0, "removing or modifying AllowUsers lines in $external_sshd_config_file_path:\n" . join("\n", @modified_lines));
		$self->create_text_file($external_sshd_config_file_path, $new_file_contents) || return;
	}
	else {
		notify($ERRORS{'DEBUG'}, 0, "no AllowUsers lines were found in $external_sshd_config_file_path containing '$username'");
	}
	
	# Remove lines from sudoers
	$self->revoke_administrative_access($username);
	
	return 1;
} ## end sub delete_user