Monday, December 3, 2007

Finding User Accounts To Disable - Follow-Up Post

Hey there,

This is a follow up to a previous post where we're walking through the process of developing a decent script, from scratch; examining how to figure out what user accounts you could disable or delete (times vary, depending on your company's policy) on any particular box you have to administrate.

Today I've taken it a step farther. At this point the below script will check the modification time of all users listed in /etc/passwd and compare it against the current Unix time. If the mtime on the home directory is over 45 days and less than 90, we warn to disable (actual code not included) and if it's over 90 days, we warn to delete (same "no code" policy for that ;). If the time on the home directory is under 45 days, the account is consider active and OK.

Note that I found a few incorrect things and changed them, as I augmented this script; so this isn't just a bigger version of the original. First of all, it seems that the user's home directory is just as reliable as the existence of a history file. Also, it's much more likely to exist ;) Also, by verifying, I noticed that the mtime (Last Modification Time) was more reliable than the atime (Last Access Time) that we used before. That seems a bit counter-intuitive, but so far, it's proving out.

We've also added some extra functionality to remove users that we don't want to check. The first group are in a file we've called locked.txt, the second group are users without a valid shell and the final group are users who are in a particular group (like administrators who need accounts on all boxes, but might not login to any particular one for a long time).

Hope this script helps, at least, to point a few people in the right direction. This is a work in progress since it still contains several flaws, including no cross-referencing of possibly-available data that the system can provide with "last" and other such commands, as well as still having to deal with "touch."

Note that, on the lines ---> @locked_text = ###LOCKEDTEXT###;
and
open(LOCKEDTEXT, "###locked.txt");

the ### space-holders should be greater than and equal signs <>, in the first instance, and a < sign in the second, but the blog software interprets them as a unclosed and unallowed tags!

Have fun :)


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/bin/perl

#
# 2007 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#
# switching to mtime 9 - from atime - 8
#
# We don't need to check for errors on the command line since
# we won't be accepting any arguments
#

if ( -f "moreinfo") {
print "Removing old temporary file \"moreinfo\"\n";
unlink("moreinfo");
}

$today=time();

@no_shells=`egrep -i 'nologin|false' /etc/passwd|awk -F":" '{print \$1}`;
@in_unixtech=`grep 1621 /etc/passwd|awk -F":" '{print \$1}`;
@user_names=`awk -F":" '{print \$1}' /etc/passwd`;
open(LOCKEDTEXT, "###locked.txt");

@locked_text = ###LOCKEDTEXT###;
close(LOCKEDTEST);
print "\nRemoving LOCKED ACCOUNTS ";
foreach $locked_user (@user_names) {
print ".";
chomp($locked_user);
if ( grep /$locked_user/,@locked_text ) {
push(@tmp_user_names,$locked_user);
print "$locked_user ";
}
}
print "\n";
print "\nRemoving NO_SHELL ACCOUNTS ";
foreach $locked_user (@user_names) {
print ".";
chomp($locked_user);
if ( grep /$locked_user/,@no_shells ) {
push(@tmp_user_names,$locked_user);
print "$locked_user ";
}
}
print "\n";
print "\nRemoving UNIXTECH ACCOUNTS ";
foreach $locked_user (@user_names) {
print ".";
chomp($locked_user);
if ( grep /$locked_user/,@in_unixtech ) {
push(@tmp_user_names,$locked_user);
print "$locked_user ";
}
}
print "\n\n";
@total = @both = @unique_names = ();
%count = ();
foreach $possible_dupe (@user_names, @tmp_user_names) {
$count{$possible_dupe}++
}
foreach $possible_dupe (keys %count) {
push @total, $possible_dupe;
push @{ $count{$possible_dupe} > 1 ? \@both : \@unique_names }, $possible_dupe;
}
@user_names = @unique_names;
foreach $diruser (@user_names) {
$filer = `grep $diruser /etc/passwd|awk -F":" '{print \$6}'`;
push(@user_dirs,$filer);
}
print "FIRST RUN - Checking Home Directories...\n\n";
foreach $history_file (@user_dirs) {
chomp($history_file);
chomp($user_name = $user_names[$counter]);
print "${user_name}: ";
$counter++;
if ( -d "$history_file" ) {
@file_dates=stat("$history_file");
$file_date=$file_dates[9];
} else {
$file_date=0;
}
$difference=$today - $file_date;
if ( $difference >= 3888000 && $difference < 7776000 ) {
print "User needs to be disabled - ";
print "45 days old or older, but under 90\n";
# YOUR CUSTOM CODE HERE - "passwd -l" would probably suffice"
} elsif ( $difference >= 7776000 ) {
print "User needs to be deleted - ";
print "90 days old or older\n";
# YOUR CUSTOM CODE HERE -
} else {
print "OK\n";
}
}


, Mike