/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; }