Bulk Provisioning
Zmprov Command Files
The Zmprov command will accept commands from a file. Just pass the commands in on standard input like this.
As Zimbra:
zmprov < commands.zmp
As Root:
cat commands.zmp | su - zimbra -c zmprov
Below are some ways to create a command file from your existing account data.
Create Accounts
Passwd File to Zmprov
Following is a perl script to take a passwd file and turn it into a zmprov command file for account provisioning.
#!/usr/bin/perl ################################################################################ # $Id: passwd2zmprov,v 1.1.1.1 2007/01/23 18:04:38 dlbewley Exp $ #------------------------------------------------------------------------------- # Description: # Tool to create commands suitable for zmprov from a unix passwd file. # We don't use getpwent etc., because we are likely working on a copy. # # See Also: # http://wiki.zimbra.com/index.php?title=Bulk_Create # # Usage: # ./passwd2zmprov /etc/passwd > users.zmp # zmprov < users.zmp ################################################################################ my $DOMAIN='hostname.foo.bar'; # zimbra installation domain name my $MIN_UID=500; # skip system accounts like httpd my $MAX_UID=5000; # skip other system accounts like nfsnobody my $PASSWORD='password'; # default password # Zimbra Class Of Service for users my $COS_ID = 'e00000a0-0c00-00d0-000a-000d00afea0a'; # use during testing only #my $COS_ID = `su - zimbra -c 'zmprov gc Default |grep zimbraId:'`; #$COS_ID =~ s/zimbraId:\s*|\s*$//g; while(<>) { chomp; my ($uname,$x,$uid,$gid,$gecos,$dir,$shell) = split(/:/); if (! ($MIN_UID < $uid && $uid < $MAX_UID)) { warn "skipping $uname, $uid not between $MIN_UID and $MAX_UID"; next; } my $date = localtime(time); my ($fullname,$description) = split(/\s*,\s*/,$gecos,2); my ($fname,$initial,$lname) = split(/\s+/,$fullname); if (! $lname) { $lname = $initial; undef $initial; } my $displayname = "$fname $initial $lname"; $displayname =~ s/\s+/ /; print qq{ca $uname\@$DOMAIN "$PASSWORD"\n}; print qq{ma $uname\@$DOMAIN zimbraCOSid "$COS_ID"\n}; print qq{ma $uname\@$DOMAIN givenName "$fname"\n}; print qq{ma $uname\@$DOMAIN sn "$lname"\n}; print qq{ma $uname\@$DOMAIN cn "$uname"\n}; print qq{ma $uname\@$DOMAIN displayName "$displayname"\n}; print qq{ma $uname\@$DOMAIN description "$description"\n}; print qq{ma $uname\@$DOMAIN zimbraNotes "Migrated $date"\n}; print qq{ma $uname\@$DOMAIN zimbraPasswordMustChange TRUE\n}; print qq{\n}; }
To execute:
perl passwd2zmprov < passwd > mydata.zmp
CSV File to Zmprov
Following is a simple perl script to take a CSV file and turn it into the correct zmprov commands
#!/usr/bin/perl # Lookup the valid COS (Class of Service) ID in the interface or like this my $cosid = `su - zimbra -c 'zmprov gc Default |grep zimbraId:'`; $cosid =~ s/zimbraId:\s*|\s*$//g; while (<>) { chomp; # CHANGE ME: To the actual fields you use in your CSV file my ($email, $password, $first, $last) = split(/\,/, $_, 4); my ($uid, $domain) = split(/@/, $email, 2); print qq{ca $uid\@$domain $password\n}; print qq{ma $uid\@$domain zimbraCOSid "$cosid"\n}; print qq{ma $uid\@$domain givenName "$first"\n}; print qq{ma $uid\@$domain sn "$last"\n}; print qq{ma $uid\@$domain cn "$uid"\n}; print qq{ma $uid\@$domain displayName "$first $last"\n}; print qq{ma $uid\@$domain zimbraPasswordMustChange TRUE\n}; print qq{\n}; }
The above is only a starting place, you will need to change other options (eg: the zimbraPasswordMustChange is an example only) and of course how you create and split the input data.
Also, some CSV files may contain quotes you want to remove.
Create Aliases
Aliases File to Zmprov
#!/usr/bin/perl ################################################################################ # $Id: aliases2zmprov,v 1.3 2007/02/09 18:35:26 dlbewley Exp $ #------------------------------------------------------------------------------- # Description: # Tool to create commands suitable for zmprov from a unix aliases file. # Handles the case of an :include: construct. # Handles the case of remote and multiple recipients by making a dist list. # - A Zimbra alias must be associated with exactly one Zimbra account. # - A Zimbra distribution list may contain users on remote hosts. # # See Also: # http://wiki.zimbra.com/index.php?title=Bulk_Create # # Usage: # ./aliases2zmprov /etc/aliases 1> aliases.zmp 2> aliases.err # zmprov < aliases.zmp # ################################################################################ my @CNAME_SKIP= qw( ftp news postmaster root webmaster ); my @ALIAS_SKIP= qw( abuse mailer-daemon postmaster ); my $DOMAIN = 'host.foo.bar'; use File::Basename; while(<>) { chomp; s/#.*$//; # skip comments next if /^\s*$/; # skip blank lines my @cnames; my ($alias,$cname) = split(/:/,$_,2); $alias =~ s/\s*//g; # scrutinize the aliases if (grep /^$alias$/, @ALIAS_SKIP) { warn "skipping alias $alias -> $cname"; next; } $cname =~ s/\s*//g; # scrutinize the canonical names if ($cname =~ m/:include:/) { # need to pull in contents of file and make a dist # list instead of an alias my $fullfile = $cname; $fullfile =~ s/:include://; my ($file,$path) = fileparse($fullfile); if (! -e $file) { warn "WARNING skipping $alias -> $cname Please run 'scp mail:$fullfile .'"; next; # go to next line of aliases file } else { # process include file open(F,$file) || warn "Can not read $file"; while (<F>) { chomp; s/#.*$//; # skip comments next if /^\s*$/; # skip blank lines push @cnames, $_; } } #next; # go to next line of aliases file } if ($cname =~ m/,/) { # multiple recipients make this a list instead of an alias @cnames = split(/,/,$cname); } # if more than one cname then it is a dist list if (length($cnames[0])) { print "cdl $alias\@$DOMAIN\n"; foreach my $member (@cnames) { # skip aliases to certain users if (grep /^$member$/, @CNAME_SKIP) { warn "skipping cname $member <- $alias"; next; # go to next member } # A Zimbra distribution list may contain users on remote hosts. if ($member =~ m/\@/) { print "adlm $alias\@$DOMAIN $member\n"; } else { print "adlm $alias\@$DOMAIN $member\@$DOMAIN\n"; } } @cnames=(); next; # go to next line of aliases file } # skip aliases to certain users if (grep /^$cname$/, @CNAME_SKIP) { warn "skipping cname $cname <- $alias"; next; } if ($cname =~ m/\/|\|/) { # alias to a file or a program. don't try to accomodate warn "WARNING skipping cname $cname <- $alias it is a file or pipe"; next; } # A Zimbra alias must be associated with exactly one Zimbra account. if ($cname =~ m/\@/) { # alias to remote host. this could be created as a dist list with 1 member # that seems undersirable though. print "cdl $alias\@$DOMAIN\n"; print "adlm $alias\@$DOMAIN $cname\n"; next; # go to next line of aliases file } # are we sure $cname\@$DOMAIN exists? print "aaa $cname\@$DOMAIN $alias\@$DOMAIN\n"; } # example data __DATA__ admin: root dudes: me,you postmaster: sarah wsu: :include:/etc/mail/lists/wsu.list jon.doe: jdoe
Remove Accounts
Here is a script that can be used to remove all accounts and distribution lists, save for accounts you specify. By default it leaves the admin account, the wiki account, and the ham and spam accounts.
#!/bin/bash ################################################################################ # $Id: deprovision,v 1.2 2007/02/18 20:41:43 dlbewley Exp $ #------------------------------------------------------------------------------- # Description: # Script to remove all Zimbra accounts and distribution lists. # This may be useful for getting back to square one if you are testing bulk # provisioning during a migration. # # See Also: # http://wiki.zimbra.com/index.php?title=Bulk_Create # # Usage: # su - zimbra # ./deprovision > deprovision.zmp # zmprov < deprovision.zmp # ################################################################################ # this will be passed to grep -vE which acts as an exclude list KEEP_ACCOUNTS='^(admin@|ham\.|spam\.|wiki@)' # this will be passed to grep -vE which acts as an exclude list KEEP_LISTS='' # files to hold distlist and account lists ACCOUNTS='accounts.zmprov' LISTS='distlists.zmprov' TMPA=`mktemp "$ACCOUNTS.XXXXXX"` TMPL=`mktemp "$LISTS.XXXXXX"` # get accounts lists zmprov gaa > "$TMPA" if [ -n "$KEEP_ACCOUNTS" ]; then grep -vE "$KEEP_ACCOUNTS" "$TMPA" > "$ACCOUNTS" rm "$TMPA" else mv "$TMPA" "$ACCOUNTS" fi # get distribution lists zmprov gadl > "$TMPL" if [ -n "$KEEP_LISTS" ]; then grep -vE "$KEEP_LISTS" "$TMPL" > "$LISTS" rm "$TMPL" else mv "$TMPL" "$LISTS" fi # remove accounts cat "$ACCOUNTS" | while read account; do echo "da $account" done # remove lists cat "$LISTS" | while read list; do echo "ddl $list" done