#!/usr/bin/perl -w # $Id: dcm3.pl,v 1.2 2003/06/03 04:30:58 seph Exp $ # this script take a passwd file, and a group file. # it then mundges users according to the passwd file. # if they don't exist, it creates them. # if they're unprivledged, it makes them privledged. # it also sets stuff based on the GECOS # because we're dealing with rt through the API, we will need to be # setgid rt. or be running as root... # FIXME: this is probably different now that we're in rt3 use strict; use Getopt::Long; # varibles related to command line options, and their defaults my $verbose = 0; my $dcm_dir = "/var/local/dcm"; my $passwd_file = "" ; my $group_file = ""; my $admin_user = "root"; GetOptions ( 'verbose|v' => \$verbose, 'dcm_dir|d=s' => \$dcm_dir, 'passwd|p=s' => \$passwd_file, 'group|g=s' => \$group_file, 'user|u=s' => \$admin_user, ); # now set the file locations to their default. (this way we can pull # from $dcm_dir $passwd_file = $dcm_dir . "/passwd" unless (length $passwd_file); $group_file = $dcm_dir . "/group" unless (length $group_file); my $current_user = initialize_rt(); open(PASSWD, "<$passwd_file"); while() { chomp; frob_rt_user($current_user, $_); } open(GROUP, "<$group_file"); while() { chomp; frob_rt_group($current_user, $_); } sub initialize_rt { # initialize rt, and get whatever we need for the API use lib "/usr/local/rt3/lib"; use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc); use RT::Group; #Clean out all the nasties from the environment CleanEnv(); #let's talk to RT' use RT; #Load RT's config file RT::LoadConfig(); # Connect to the database. set up loggign RT::Init(); #Get the current user all loaded #my $CurrentUser = GetCurrentUser(); my $CurrentUser = RT::CurrentUser->new(); $CurrentUser->Load($admin_user); unless ($CurrentUser->Id) { print "Couldn't login to rt as $admin_user. yer fucked\n"; exit(1); } return $CurrentUser; } sub frob_rt_group { # this takes a /etc/groups style line, and makes an rt group look # like that. it does the various user adds and removes. # get the RT thingy my $CurrentUser = shift; my $group_line = shift; my ($name, $password, $gid, $users) = split (/:/, $group_line); my %new_users; foreach ( split(/,/, $users) ) { chomp; my $user_name = lc $_; $user_name = $user_name . '@mit.edu' unless($user_name =~ /\@/); $new_users{$user_name} = 1; } # clean up various bits my $group_name = 'moira:' . $name; # let's create an rt group object, (we need it for rt stuff) my $group_obj = new RT::Group($CurrentUser); # now let's see if this group already exists... $group_obj->LoadUserDefinedGroup($group_name); unless ($group_obj->Id) { print "Group $group_name not found, creating\n" if($verbose); my ($val, $msg) = $group_obj->CreateUserDefinedGroup(Name => $group_name); print $msg ."\n" if($verbose); } # now load the group, and get to work $group_obj->LoadUserDefinedGroup($group_name); unless ($group_obj->Id) { print "couldn't load $group_name. fucked\n---\n"; return 1; } print "CHECKING GROUP $group_name\n" if($verbose); # now we know we have a group loaded. let's set it's members my $existing_members = $group_obj->UserMembersObj(); # if they're currently a member, but not in what the dcm feeds us, # delete them. while (my $member = $existing_members->Next()) { print "checking existing user " . $member->Name(), "\n" if($verbose); unless( $new_users{$member->Name()} ) { print " deleting\n" if($verbose); $group_obj->DeleteMember($member->Id()); } } # now iterate over the various new members, and make sure # they're already in the group. foreach my $user_name (keys %new_users) { print "checking $user_name group $group_name\n" if($verbose); # we need to add members by id, not name. my $new_user = new RT::User($CurrentUser); $new_user->Load($user_name); # FIXME: checking to see if they're all ready a member is kinda annoying. # the HasMember function wants an RT::Principal, not an RT::User print " adding\n" if($verbose); $group_obj->AddMember( $new_user->Id() ); } } sub frob_rt_user { # this function takes a passwd style line and frobs the rt user # if the user doesn't exist, it creates it. # if the user is unprivledged, it makes said user privleged # it also set's the name and gecos my $CurrentUser = shift; my $passwd_line = shift; my ($login, $pass, $uid, $gid, $gecos, $home, $shell) = split(/:/, $passwd_line); my ($name, $nickname, $office, $office_phone, $phone) = split(/,/, $gecos); # clean up various varibles before we pass them into rt my $user_email = $login; $user_email = $user_email . '@MIT.EDU' unless($user_email =~ /\@/); my $user_name = $login; $user_name = $user_name . '@mit.edu' unless($user_name =~ /\@/); # set up the attributes array: my %user_attributes; $user_attributes{'Name'} = $user_name; $user_attributes{'Gecos'} = $login; $user_attributes{'EmailAddress'} = $user_email; $user_attributes{'Privileged'} = 1; $user_attributes{'Comments'} = 'frobbed by the dcm'; $user_attributes{'RealName'} = $name; $user_attributes{'NickName'} = $nickname; $user_attributes{'HomePhone'} = $phone; $user_attributes{'WorkPhone'} = $office_phone; # let's create an rt user object, and we'll see my $user_obj = new RT::User($CurrentUser); $user_obj->Load($user_name); # alrighty, create the user, if they don't exist. unless ($user_obj->id) { print "User '$user_name' not found, creating\n" if($verbose); my ($status, $msg) = $user_obj->Create( %user_attributes ); print "$msg\n" if($verbose); } # if they already exist, let's just frob them... else { # now that we know we have a user, let's set it's attributes # this bit of code lifted from rtadmin my @attributes = ('Name', 'Gecos', 'EmailAddress', 'Privileged', 'Comments', 'Signature', 'Organization', 'RealName', 'NickName', 'ExternalContactInfoId', 'ContactInfoSystem', 'ExternalAuthId', 'AuthSystem', 'HomePhone', 'WorkPhone', 'MobilePhone', 'PagerPhone', 'Address1', 'Address2', 'City', 'State', 'Zip', 'Country', 'FreeformContactInfo'); foreach my $attrib (@attributes) { if ( (exists ($user_attributes{"$attrib"})) and ($user_obj->$attrib() ne $user_attributes{"$attrib"})) { my $method = "Set$attrib"; my ($val, $msg) = $user_obj->$method($user_attributes{"$attrib"}); print "User ".$user_obj->Name. " $attrib: $msg\n" if($verbose); } } } }