Difference between revisions of "Bulk Provisioning"

m (Passwd File to Zmprov)
(tool to migrate aliases)
Line 10: Line 10:
 
Below are some ways to create a command file from your existing account data.
 
Below are some ways to create a command file from your existing account data.
  
= Passwd File to Zmprov =
+
= 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.
 
Following is a perl script to take a passwd file and turn it into a zmprov command file for account provisioning.
Line 76: Line 78:
 
   perl passwd2zmprov < passwd > mydata.zmp
 
   perl passwd2zmprov < passwd > mydata.zmp
  
= CSV File to Zmprov =
+
== CSV File to Zmprov ==
  
 
Following is a simple perl script to take a CSV file and turn it into the correct zmprov commands
 
Following is a simple perl script to take a CSV file and turn it into the correct zmprov commands
Line 108: Line 110:
 
Also, some CSV files may contain quotes you want to remove.
 
Also, some CSV files may contain quotes you want to remove.
  
To execute:
 
  
   perl csv2zmprov < mydata.csv > mydata.zmp
+
= Create Aliases =
 +
 
 +
== Aliases File to Zmprov ==
 +
 
 +
<pre>
 +
#!/usr/bin/perl
 +
################################################################################
 +
# $Id: aliases2zmprov,v 1.2 2007/02/09 00:11:34 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 multiple recipients for an alias 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 = 'hostname.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
 +
    }
 +
 
 +
    # 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.
 +
        warn "WARNING skipping cname $cname <- $alias it is a not here - TODO";
 +
        next; # go to next line of aliases file
 +
    }
 +
    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;
 +
    }
 +
 
 +
    # skip aliases to certain users
 +
    if (grep /^$cname$/, @CNAME_SKIP) {
 +
        warn "skipping cname $cname <- $alias";
 +
        next;
 +
    }
 +
 
 +
    # are we sure $cname\@$DOMAIN exists?
 +
    print "aaa $cname\@$DOMAIN $alias\@$DOMAIN\n";
 +
}
 +
# example data
 +
__DATA__
 +
admin: root
 +
dudes: me,you
 +
postmaster: sarah
 +
wax: :include:/etc/mail/lists/wax.list
 +
jon.doe: jdoe
 +
</pre>

Revision as of 00:18, 9 February 2007


Zmprov Command Files

The zmprov command will accept commands from a file. Just pass the commands in on standard input like this:

 zmprov < mydata.zmp

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.2 2007/02/09 00:11:34 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 multiple recipients for an alias 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 = 'hostname.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
    }

    # 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.
        warn "WARNING skipping cname $cname <- $alias it is a not here - TODO";
        next; # go to next line of aliases file
    }
    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;
    }

    # skip aliases to certain users
    if (grep /^$cname$/, @CNAME_SKIP) {
        warn "skipping cname $cname <- $alias";
        next;
    }

    # are we sure $cname\@$DOMAIN exists?
    print "aaa $cname\@$DOMAIN $alias\@$DOMAIN\n";
}
# example data
__DATA__
admin: root
dudes: me,you
postmaster: sarah
wax: :include:/etc/mail/lists/wax.list
jon.doe: jdoe
Jump to: navigation, search