diff options
-rwxr-xr-x | scripts/moco-ldap-check.pl | 542 |
1 files changed, 0 insertions, 542 deletions
diff --git a/scripts/moco-ldap-check.pl b/scripts/moco-ldap-check.pl deleted file mode 100755 index 7a3a6ca8c..000000000 --- a/scripts/moco-ldap-check.pl +++ /dev/null @@ -1,542 +0,0 @@ -#!/usr/bin/perl - -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. -# -# This Source Code Form is "Incompatible With Secondary Licenses", as -# defined by the Mozilla Public License, v. 2.0. - -use strict; -use warnings; - -use FindBin qw($Bin); -use lib "$Bin/.."; -use lib "$Bin/../lib"; - -use Bugzilla; -use Bugzilla::Constants; -use Bugzilla::Group; -use Bugzilla::Mailer; -use Data::Dumper; -use File::Slurp; -use Getopt::Long; -use Net::LDAP; -use Safe; - -# - -use constant BUGZILLA_IGNORE => <<'EOF'; - infra+bot@mozilla.com # Mozilla Infrastructure Bot - qa-auto@mozilla.com # QA Desktop Automation - qualys@mozilla.com # Qualys Security Scanner - recruiting@mozilla.com # Recruiting - release@mozilla.com # Mozilla RelEng Bot - sumo-dev@mozilla.com # SUMOdev [:sumodev] - airmozilla@mozilla.com # Air Mozilla - ux-review@mozilla.com - release-mgmt@mozilla.com - reps@mozilla.com - moz_bug_r_a4@mozilla.com # Security contractor - nightwatch@mozilla.com # Security distribution list for whines -EOF - -use constant LDAP_IGNORE => <<'EOF'; - airmozilla@mozilla.com # Air Mozilla -EOF - -# REPORT_SENDER has to be a valid @mozilla.com LDAP account -use constant REPORT_SENDER => 'bjones@mozilla.com'; - -use constant BMO_RECIPIENTS => qw( - glob@mozilla.com - dkl@mozilla.com -); - -use constant SUPPORT_RECIPIENTS => qw( - desktop@mozilla.com -); - -# - -my ($ldap_host, $ldap_user, $ldap_pass, $debug, $no_update); -GetOptions('h=s' => \$ldap_host, - 'u=s' => \$ldap_user, - 'p=s' => \$ldap_pass, - 'd' => \$debug, - 'n' => \$no_update); -die "syntax: -h ldap_host -u ldap_user -p ldap_pass\n" - unless $ldap_host && $ldap_user && $ldap_pass; - -my $data_dir = bz_locations()->{'datadir'} . '/moco-ldap-check'; -mkdir($data_dir) unless -d $data_dir; - -if ($ldap_user !~ /,/) { - $ldap_user = "mail=$ldap_user,o=com,dc=mozilla"; -} - -# -# group members -# - -my @bugzilla_ignore; -foreach my $line (split(/\n/, BUGZILLA_IGNORE)) { - $line =~ s/^([^#]+)#.*$/$1/; - $line =~ s/(^\s+|\s+$)//g; - push @bugzilla_ignore, clean_email($line); -} - -my @bugzilla_moco; -if ($no_update && -s "$data_dir/bugzilla_moco.last") { - $debug && print "Using cached user list from Bugzilla...\n"; - my $ra = deserialise("$data_dir/bugzilla_moco.last"); - @bugzilla_moco = @$ra; -} else { - $debug && print "Getting user list from Bugzilla...\n"; - - my $group = Bugzilla::Group->new({ name => 'mozilla-corporation' }) - or die "Failed to find group mozilla-corporation\n"; - - foreach my $user (@{ $group->members_non_inherited }) { - next unless $user->is_enabled; - my $mail = clean_email($user->login); - my $name = trim($user->name); - $name =~ s/\s+/ /g; - next if grep { $mail eq $_ } @bugzilla_ignore; - push @bugzilla_moco, { - mail => $user->login, - canon => $mail, - name => $name, - }; - } - - @bugzilla_moco = sort { $a->{mail} cmp $b->{mail} } @bugzilla_moco; - serialise("$data_dir/bugzilla_moco.last", \@bugzilla_moco); -} - -# -# build list of current mo-co bugmail accounts -# - -my @ldap_ignore; -foreach my $line (split(/\n/, LDAP_IGNORE)) { - $line =~ s/^([^#]+)#.*$/$1/; - $line =~ s/(^\s+|\s+$)//g; - push @ldap_ignore, canon_email($line); -} - -my %ldap; -if ($no_update && -s "$data_dir/ldap.last") { - $debug && print "Using cached user list from LDAP...\n"; - my $rh = deserialise("$data_dir/ldap.last"); - %ldap = %$rh; -} else { - $debug && print "Logging into LDAP as $ldap_user...\n"; - my $ldap = Net::LDAP->new($ldap_host, - scheme => 'ldaps', onerror => 'die') or die "$@"; - $ldap->bind($ldap_user, password => $ldap_pass); - foreach my $ldap_base ('o=com,dc=mozilla', 'o=org,dc=mozilla') { - $debug && print "Getting user list from LDAP $ldap_base...\n"; - my $result = $ldap->search( - base => $ldap_base, - scope => 'sub', - filter => '(mail=*)', - attrs => ['mail', 'bugzillaEmail', 'emailAlias', 'cn', 'employeeType'], - ); - foreach my $entry ($result->entries) { - my ($name, $bugMail, $mail, $type) = - map { $entry->get_value($_) || '' } - qw(cn bugzillaEmail mail employeeType); - next if $type eq 'DISABLED'; - $mail = lc $mail; - next if grep { $_ eq canon_email($mail) } @ldap_ignore; - $bugMail = '' if $bugMail !~ /\@/; - $bugMail =~ s/(^\s+|\s+$)//g; - if ($bugMail =~ / /) { - $bugMail = (grep { /\@/ } split / /, $bugMail)[0]; - } - $name =~ s/\s+/ /g; - $ldap{$mail}{name} = trim($name); - $ldap{$mail}{bugmail} = $bugMail; - $ldap{$mail}{bugmail_canon} = canon_email($bugMail); - $ldap{$mail}{aliases} = []; - foreach my $alias ( - @{$entry->get_value('emailAlias', asref => 1) || []} - ) { - push @{$ldap{$mail}{aliases}}, canon_email($alias); - } - } - $debug && printf "Found %s entries\n", scalar($result->entries); - } - serialise("$data_dir/ldap.last", \%ldap); -} - -# -# validate all bugmail entries from the phonebook -# - -my %bugzilla_login; -if ($no_update && -s "$data_dir/bugzilla_login.last") { - $debug && print "Using cached bugzilla checks...\n"; - my $rh = deserialise("$data_dir/bugzilla_login.last"); - %bugzilla_login = %$rh; -} else { - my %logins; - foreach my $mail (keys %ldap) { - $logins{$mail} = 1; - $logins{$ldap{$mail}{bugmail}} = 1 if $ldap{$mail}{bugmail}; - } - my @logins = sort keys %logins; - $debug && print "Checking " . scalar(@logins) . " bugmail accounts...\n"; - - foreach my $login (@logins) { - if (Bugzilla::User->new({ name => $login })) { - $bugzilla_login{$login} = 1; - } - } - serialise("$data_dir/bugzilla_login.last", \%bugzilla_login); -} - -# -# load previous ldap list -# - -my %ldap_old; -{ - my $rh = deserialise("$data_dir/ldap.data"); - %ldap_old = %$rh if $rh; -} - -# -# save current ldap list -# - -{ - serialise("$data_dir/ldap.data", \%ldap); -} - -# -# new ldap accounts -# - -my @new_ldap; -{ - foreach my $mail (sort keys %ldap) { - next if exists $ldap_old{$mail}; - push @new_ldap, { - mail => $mail, - name => $ldap{$mail}{name}, - bugmail => $ldap{$mail}{bugmail}, - }; - } -} - -# -# deleted ldap accounts -# - -my @gone_ldap_bmo; -my @gone_ldap_no_bmo; -{ - foreach my $mail (sort keys %ldap_old) { - next if exists $ldap{$mail}; - if ($ldap_old{$mail}{bugmail}) { - push @gone_ldap_bmo, { - mail => $mail, - name => $ldap_old{$mail}{name}, - bugmail => $ldap_old{$mail}{bugmail}, - } - } else { - push @gone_ldap_no_bmo, { - mail => $mail, - name => $ldap_old{$mail}{name}, - } - } - } -} - -# -# check bugmail entry for all users in bmo/moco group -# - -my @suspect_bugzilla; -my @invalid_bugzilla; -foreach my $rh (@bugzilla_moco) { - my @check = ($rh->{mail}, $rh->{canon}); - if ($rh->{mail} =~ /^([^\@]+)\@mozilla\.org$/) { - push @check, "$1\@mozilla.com"; - } - - my $exists; - foreach my $check (@check) { - $exists = 0; - - # don't complain about deleted accounts - if (grep { $_->{mail} eq $check } (@gone_ldap_bmo, @gone_ldap_no_bmo)) { - $exists = 1; - last; - } - - # check for matching bugmail entry - foreach my $mail (sort keys %ldap) { - next unless $ldap{$mail}{bugmail_canon} eq $check; - $exists = 1; - last; - } - last if $exists; - - # check for matching mail - $exists = 0; - foreach my $mail (sort keys %ldap) { - next unless $mail eq $check; - $exists = 1; - last; - } - last if $exists; - - # check for matching email alias - $exists = 0; - foreach my $mail (sort keys %ldap) { - next unless grep { $check eq $_ } @{$ldap{$mail}{aliases}}; - $exists = 1; - last; - } - last if $exists; - } - - if (!$exists) { - # flag the account - if ($rh->{mail} =~ /\@mozilla\.(com|org)$/i) { - push @invalid_bugzilla, { - mail => $rh->{mail}, - name => $rh->{name}, - }; - } else { - push @suspect_bugzilla, { - mail => $rh->{mail}, - name => $rh->{name}, - }; - } - } -} - -# -# check bugmail entry for ldap users -# - -my @ldap_unblessed; -my @invalid_ldap; -my @invalid_bugmail; -foreach my $mail (sort keys %ldap) { - # try to find the bmo account - my $found; - foreach my $address ($ldap{$mail}{bugmail}, $ldap{$mail}{bugmail_canon}, $mail, @{$ldap{$mail}{aliases}}) { - if (exists $bugzilla_login{$address}) { - $found = $address; - last; - } - } - - # not on bmo - if (!$found) { - # if they have specified a bugmail account, warn, otherwise ignore - if ($ldap{$mail}{bugmail}) { - if (grep { $_->{canon} eq $ldap{$mail}{bugmail_canon} } @bugzilla_moco) { - push @invalid_bugmail, { - mail => $mail, - name => $ldap{$mail}{name}, - bugmail => $ldap{$mail}{bugmail}, - }; - } else { - push @invalid_ldap, { - mail => $mail, - name => $ldap{$mail}{name}, - bugmail => $ldap{$mail}{bugmail}, - }; - } - } - next; - } - - # warn about mismatches - if ($ldap{$mail}{bugmail} && $found ne $ldap{$mail}{bugmail}) { - push @invalid_bugmail, { - mail => $mail, - name => $ldap{$mail}{name}, - bugmail => $ldap{$mail}{bugmail}, - }; - } - - # warn about unblessed accounts - if ($mail =~ /\@mozilla\.com$/) { - unless (grep { $_->{mail} eq $found || $_->{canon} eq canon_email($found) } @bugzilla_moco) { - push @ldap_unblessed, { - mail => $mail, - name => $ldap{$mail}{name}, - bugmail => $ldap{$mail}{bugmail} || $mail, - }; - } - } -} - -# -# reports -# - -my @bmo_report; -push @bmo_report, generate_report( - 'new ldap accounts', - 'no action required', - @new_ldap); - -push @bmo_report, generate_report( - 'deleted ldap accounts', - 'disable bmo account', - @gone_ldap_bmo); - -push @bmo_report, generate_report( - 'deleted ldap accounts', - 'no action required (no bmo account)', - @gone_ldap_no_bmo); - -push @bmo_report, generate_report( - 'suspect bugzilla accounts', - 'remove from mo-co if required', - @suspect_bugzilla); - -push @bmo_report, generate_report( - 'miss-configured bugzilla accounts', - 'ask owner to update phonebook, disable if not on phonebook', - @invalid_bugzilla); - -push @bmo_report, generate_report( - 'ldap accounts without mo-co group', - 'verify, and add mo-co group to bmo account', - @ldap_unblessed); - -push @bmo_report, generate_report( - 'missmatched bugmail entries on ldap accounts', - 'ask owner to update phonebook', - @invalid_bugmail); - -push @bmo_report, generate_report( - 'invalid bugmail entries on ldap accounts', - 'ask owner to update phonebook', - @invalid_ldap); - -if (!scalar @bmo_report) { - push @bmo_report, '**'; - push @bmo_report, '** nothing to report \o/'; - push @bmo_report, '**'; -} - -email_report(\@bmo_report, 'moco-ldap-check', BMO_RECIPIENTS); - -my @support_report; - -push @support_report, generate_report( - 'Missmatched "Bugzilla Email" entries on LDAP accounts', - 'Ask owner to update phonebook, or update directly', - @invalid_bugmail); - -push @support_report, generate_report( - 'Invalid "Bugzilla Email" entries on LDAP accounts', - 'Ask owner to update phonebook', - @invalid_ldap); - -if (scalar @support_report) { - email_report(\@support_report, 'Invalid "Bugzilla Email" entries in LDAP', SUPPORT_RECIPIENTS); -} - -# -# -# - -sub generate_report { - my ($title, $action, @lines) = @_; - - my $count = scalar @lines; - return unless $count; - - my @report; - push @report, ''; - push @report, '**'; - push @report, "** $title ($count)"; - push @report, "** [ $action ]"; - push @report, '**'; - push @report, ''; - - my $max_length = 0; - foreach my $rh (@lines) { - $max_length = length($rh->{mail}) if length($rh->{mail}) > $max_length; - } - - foreach my $rh (@lines) { - my $template = "%-${max_length}s %s"; - my @fields = ($rh->{mail}, $rh->{name}); - - if ($rh->{bugmail}) { - $template .= ' (%s)'; - push @fields, $rh->{bugmail}; - }; - - push @report, sprintf($template, @fields); - } - - return @report; -} - -sub email_report { - my ($report, $subject, @recipients) = @_; - unshift @$report, ( - "Subject: $subject", - 'X-Bugzilla-Type: moco-ldap-check', - 'From: ' . REPORT_SENDER, - 'To: ' . join(',', @recipients), - ); - if ($debug) { - print "\n", join("\n", @$report), "\n"; - } else { - MessageToMTA(join("\n", @$report)); - } -} - -sub clean_email { - my $email = shift; - $email = trim($email); - $email = $1 if $email =~ /^(\S+)/; - $email =~ s/@/@/; - $email = lc $email; - return $email; -} - -sub canon_email { - my $email = shift; - $email = clean_email($email); - $email =~ s/^([^\+]+)\+[^\@]+(\@.+)$/$1$2/; - return $email; -} - -sub trim { - my $value = shift; - $value =~ s/(^\s+|\s+$)//g; - return $value; -} - -sub serialise { - my ($filename, $ref) = @_; - local $Data::Dumper::Purity = 1; - local $Data::Dumper::Deepcopy = 1; - local $Data::Dumper::Sortkeys = 1; - write_file($filename, Dumper($ref)); -} - -sub deserialise { - my ($filename) = @_; - return unless -s $filename; - my $cpt = Safe->new(); - $cpt->reval('our ' . read_file($filename)) - || die "$!"; - return ${$cpt->varglob('VAR1')}; -} - |