123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- #!/usr/bin/env perl -wT
- # -*- Mode: perl; indent-tabs-mode: nil -*-
- #
- # The contents of this file are subject to the Mozilla Public
- # License Version 1.1 (the "License"); you may not use this file
- # except in compliance with the License. You may obtain a copy of
- # the License at http://www.mozilla.org/MPL/
- #
- # Software distributed under the License is distributed on an "AS
- # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- # implied. See the License for the specific language governing
- # rights and limitations under the License.
- #
- # The Original Code is the LDAP to Bugzilla User Sync Tool.
- #
- # The Initial Developer of the Original Code is Andreas Höfler.
- # Portions created by Andreas Höfler are Copyright (C) 2003
- # Andreas Höfler. All Rights Reserved.
- #
- # Contributor(s): Andreas Höfler <andreas.hoefler@bearingpoint.com>
- #
- use strict;
- use lib qw(. lib);
- use Net::LDAP;
- use Bugzilla;
- use Bugzilla::User;
- my $cgi = Bugzilla->cgi;
- my $dbh = Bugzilla->dbh;
- my $readonly = 0;
- my $nodisable = 0;
- my $noupdate = 0;
- my $nocreate = 0;
- my $quiet = 0;
- ###
- # Do some preparations
- ###
- foreach my $arg (@ARGV)
- {
- if($arg eq '-r') {
- $readonly = 1;
- }
- elsif($arg eq '-d') {
- $nodisable = 1;
- }
- elsif($arg eq '-u') {
- $noupdate = 1;
- }
- elsif($arg eq '-c') {
- $nocreate = 1;
- }
- elsif($arg eq '-q') {
- $quiet = 1;
- }
- else {
- print "LDAP Sync Script\n";
- print "Syncronizes the users table from the LDAP server with the Bugzilla users.\n";
- print "Takes mail-attribute from preferences and description from 'cn' or,\n";
- print "if not available, from the uid-attribute.\n\n";
- print "usage:\n syncLDAP.pl [options]\n\n";
- print "options:\n";
- print " -r Readonly, do not make changes to Bugzilla tables\n";
- print " -d No disable, don't disable users, which are not in LDAP\n";
- print " -u No update, don't update users, which have different description in LDAP\n";
- print " -c No create, don't create users, which are in LDAP but not in Bugzilla\n";
- print " -q Quiet mode, give less output\n";
- print "\n";
- exit;
- }
- }
- my %ldap_users;
- ###
- # Get current bugzilla users
- ###
- my %bugzilla_users = %{ $dbh->selectall_hashref(
- 'SELECT login_name AS new_login_name, realname, disabledtext ' .
- 'FROM profiles', 'new_login_name') };
- foreach my $login_name (keys %bugzilla_users) {
- # remove whitespaces
- $bugzilla_users{$login_name}{'realname'} =~ s/^\s+|\s+$//g;
- }
- ###
- # Get current LDAP users
- ###
- my $LDAPserver = Bugzilla->params->{"LDAPserver"};
- if ($LDAPserver eq "") {
- print "No LDAP server defined in bugzilla preferences.\n";
- exit;
- }
- my $LDAPconn;
- if($LDAPserver =~ /:\/\//) {
- # if the "LDAPserver" parameter is in uri scheme
- $LDAPconn = Net::LDAP->new($LDAPserver, version => 3);
- } else {
- my $LDAPport = "389"; # default LDAP port
- if($LDAPserver =~ /:/) {
- ($LDAPserver, $LDAPport) = split(":",$LDAPserver);
- }
- $LDAPconn = Net::LDAP->new($LDAPserver, port => $LDAPport, version => 3);
- }
- if(!$LDAPconn) {
- print "Connecting to LDAP server failed. Check LDAPserver setting.\n";
- exit;
- }
- my $mesg;
- if (Bugzilla->params->{"LDAPbinddn"}) {
- my ($LDAPbinddn,$LDAPbindpass) = split(":",Bugzilla->params->{"LDAPbinddn"});
- $mesg = $LDAPconn->bind($LDAPbinddn, password => $LDAPbindpass);
- }
- else {
- $mesg = $LDAPconn->bind();
- }
- if($mesg->code) {
- print "Binding to LDAP server failed: " . $mesg->error . "\nCheck LDAPbinddn setting.\n";
- exit;
- }
- # We've got our anonymous bind; let's look up the users.
- $mesg = $LDAPconn->search( base => Bugzilla->params->{"LDAPBaseDN"},
- scope => "sub",
- filter => '(&(' . Bugzilla->params->{"LDAPuidattribute"} . "=*)" . Bugzilla->params->{"LDAPfilter"} . ')',
- );
-
- if(! $mesg->count) {
- print "LDAP lookup failure. Check LDAPBaseDN setting.\n";
- exit;
- }
-
- my %val = %{ $mesg->as_struct };
- while( my ($key, $value) = each(%val) ) {
- my @login_name = @{ $value->{Bugzilla->params->{"LDAPmailattribute"}} };
- my @realname = @{ $value->{"cn"} };
- # no mail entered? go to next
- if(! @login_name) {
- print "$key has no valid mail address\n";
- next;
- }
- # no cn entered? use uid instead
- if(! @realname) {
- @realname = @{ $value->{Bugzilla->params->{"LDAPuidattribute"}} };
- }
-
- my $login = shift @login_name;
- my $real = shift @realname;
- $ldap_users{$login} = { realname => $real };
- }
- print "\n" unless $quiet;
- ###
- # Sort the users into disable/update/create-Lists and display everything
- ###
- my %disable_users;
- my %update_users;
- my %create_users;
- print "Bugzilla-Users: \n" unless $quiet;
- while( my ($key, $value) = each(%bugzilla_users) ) {
- print " " . $key . " '" . $value->{'realname'} . "' " . $value->{'disabledtext'} ."\n" unless $quiet==1;
- if(!exists $ldap_users{$key}){
- if($value->{'disabledtext'} eq '') {
- $disable_users{$key} = $value;
- }
- }
- }
- print "\nLDAP-Users: \n" unless $quiet;
- while( my ($key, $value) = each(%ldap_users) ) {
- print " " . $key . " '" . $value->{'realname'} . "'\n" unless $quiet==1;
- if(!defined $bugzilla_users{$key}){
- $create_users{$key} = $value;
- }
- else {
- my $bugzilla_user_value = $bugzilla_users{$key};
- if($bugzilla_user_value->{'realname'} ne $value->{'realname'}) {
- $update_users{$key} = $value;
- }
- }
- }
- print "\nDetecting email changes: \n" unless $quiet;
- while( my ($create_key, $create_value) = each(%create_users) ) {
- while( my ($disable_key, $disable_value) = each(%disable_users) ) {
- if($create_value->{'realname'} eq $disable_value->{'realname'}) {
- print " " . $disable_key . " => " . $create_key ."'\n" unless $quiet==1;
- $update_users{$disable_key} = { realname => $create_value->{'realname'},
- new_login_name => $create_key };
- delete $create_users{$create_key};
- delete $disable_users{$disable_key};
- }
- }
- }
- if($quiet == 0) {
- print "\nUsers to disable: \n";
- while( my ($key, $value) = each(%disable_users) ) {
- print " " . $key . " '" . $value->{'realname'} . "'\n";
- }
-
- print "\nUsers to update: \n";
- while( my ($key, $value) = each(%update_users) ) {
- print " " . $key . " '" . $value->{'realname'} . "' ";
- if(defined $value->{'new_login_name'}) {
- print "has changed email to " . $value->{'new_login_name'};
- }
- print "\n";
- }
-
- print "\nUsers to create: \n";
- while( my ($key, $value) = each(%create_users) ) {
- print " " . $key . " '" . $value->{'realname'} . "'\n";
- }
-
- print "\n\n";
- }
- ###
- # now do the DB-Update
- ###
- if($readonly == 0) {
- print "Performing DB update:\nPhase 1: disabling not-existing users... " unless $quiet;
- my $sth_disable = $dbh->prepare(
- 'UPDATE profiles
- SET disabledtext = ?
- WHERE ' . $dbh->sql_istrcmp('login_name', '?'));
- if($nodisable == 0) {
- while( my ($key, $value) = each(%disable_users) ) {
- $sth_disable->execute('auto-disabled by ldap sync', $key);
- }
- print "done!\n" unless $quiet;
- }
- else {
- print "disabled!\n" unless $quiet;
- }
-
- print "Phase 2: updating existing users... " unless $quiet;
- my $sth_update_login = $dbh->prepare(
- 'UPDATE profiles
- SET login_name = ?
- WHERE ' . $dbh->sql_istrcmp('login_name', '?'));
- my $sth_update_realname = $dbh->prepare(
- 'UPDATE profiles
- SET realname = ?
- WHERE ' . $dbh->sql_istrcmp('login_name', '?'));
- if($noupdate == 0) {
- while( my ($key, $value) = each(%update_users) ) {
- if(defined $value->{'new_login_name'}) {
- $sth_update_login->execute($value->{'new_login_name'}, $key);
- } else {
- $sth_update_realname->execute($value->{'realname'}, $key);
- }
- }
- print "done!\n" unless $quiet;
- }
- else {
- print "disabled!\n" unless $quiet;
- }
-
- print "Phase 3: creating new users... " unless $quiet;
- if($nocreate == 0) {
- while( my ($key, $value) = each(%create_users) ) {
- Bugzilla::User->create({
- login_name => $key,
- realname => $value->{'realname'},
- cryptpassword => '*'});
- }
- print "done!\n" unless $quiet;
- }
- else {
- print "disabled!\n" unless $quiet;
- }
- }
- else
- {
- print "No changes to DB because readonly mode\n" unless $quiet;
- }
|