/ag-update-shadow
#!/usr/bin/perl
use strict;
use AwesomeGrid;
use AwesomeGrid::Config;
use AwesomeGrid::User;
my $etc = '/etc'; # In production, this should be '/etc'
my $config = AwesomeGrid::Config::config();
# Get a list of awesomegrid users
opendir USERS, "$AwesomeGrid::confdir/users";
my @agusers = grep {/^[^.]/} readdir USERS;
close USERS;
# Get a list of system users
my @sysusers;
my @allsysusers;
open PASSWD, "$etc/passwd";
while (<PASSWD>) {
my ($username, undef, $uid, $gid, $gecos, $home, $shell) = split(/:/);
push(@allsysusers, $username);
next unless $gecos =~ /^\[AG\]/; # Skip non-AG-managed users
push(@sysusers, $username);
}
close PASSWD;
# Check to see what there is in /etc/passwd that should be removed.
my @deletes;
for my $sysuser (@sysusers) {
unless (grep { $_ eq $sysuser } @agusers) {
push(@deletes, $sysuser);
}
}
# Check to see which users are going to be added
my @adds;
for my $aguser (@agusers) {
unless (grep { $_ eq $aguser } @allsysusers) {
push(@adds, $aguser);
}
}
# Check to see which users should be updated
my @updates;
for my $user (@allsysusers) {
if (grep { $_ eq $user } @agusers) {
push(@updates, $user);
}
}
unless (@adds or @deletes or @updates) {
print "Nothing to do.\n";
exit 0;
}
print "Adding: ",join(' ',@adds),"\n" if @adds;
print "Deleting: ",join(' ',@deletes),"\n" if @deletes;
print "Updating: ",join(' ',@updates),"\n" if @updates;
print "Proceed? [y/N] ";
my $ans = <STDIN>;
unless ($ans =~ /^[Yy]$/) {
exit(0);
}
# Before proceeding, make a backup copy of /etc/passwd and /etc/shadow
system("cp $etc/passwd $etc/passwd.ag_backup");
system("cp $etc/shadow $etc/shadow.ag_backup");
# Note that parsing /etc/passwd and /etc/shadow like this is pretty bad
# form, but it's the only way I can test it without being root. It's
# also the only way I can dump the hash directly into /etc/shadow.
# Deletes first
if (@deletes or @updates) {
open PASSWD, "$etc/passwd";
open PASSWDOUT, ">$etc/passwd.out";
while (<PASSWD>) {
my ($username) = split(/:/);
next if grep { $username eq $_ } (@deletes,@updates);
print PASSWDOUT;
}
close PASSWDOUT;
close PASSWD;
open SHADOW, "$etc/shadow";
open SHADOWOUT, ">$etc/shadow.out";
while (<SHADOW>) {
my ($username) = split(/:/);
next if grep { $username eq $_ } (@deletes,@updates);
print SHADOWOUT;
}
close SHADOWOUT;
close SHADOW;
rename "$etc/passwd.out","$etc/passwd";
chmod 0644, "$etc/passwd";
rename "$etc/shadow.out","$etc/shadow";
chmod 0640, "$etc/shadow";
system(qq{chown root.shadow "$etc/shadow"});
}
# Then add new ones.
if (@adds or @updates) {
# Perhaps appending directly is a bad idea...
open PASSWD, ">>$etc/passwd";
open SHADOW, ">>$etc/shadow";
for my $add (@updates,@adds) {
my $agu = AwesomeGrid::User->load($add);
printf PASSWD "%s:x:%d:%d:[AG]:%s:%s\n", $agu->{username},
$agu->{uid}, $agu->{uid},
"$config->{homedir}/$agu->{username}",
$config->{'default-shell'};
printf SHADOW "%s:%s:%d:%d:%d:%d:::\n",
$agu->{username},
$agu->{'passwd-unix-md5'},
time / 86400, 0, 99999, 7;
unless (-d "$config->{homedir}/$agu->{username}") {
print "Creating homedir for $agu->{username}\n";
mkdir "$config->{homedir}/$agu->{username}";
chown $agu->{uid}, $agu->{uid},
"$config->{homedir}/$agu->{username}";
}
}
close PASSWD;
close SHADOW;
}