#!/usr/bin/perl
#
# updatenagiosadmin.pl  -  Updates the cgi access list and creates contacts
#                          for Nagios using LDAP queries.
#
# Version 1.01
#
# Copyright (C) 2008 Thomas Guyot-Sionnest <tguyot@gmail.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#


use strict;
use warnings;

## CONFIG SECTION ##

# Program to run to dump nagios admin users data
my $dumpapp = '/usr/local/bin/getadnagiosadmin.pl';

# New users dump. This should be written by $dumpapp
my $newdump = '/tmp/nagiosadmin.txt.new';

# Backup from the last run. Can be anything but $newdump
my $olddump = '/tmp/nagiosadmin.txt.old';

# Temp config file
my $tempcfg = '/tmp/webcontacts.cfg.new';

# Full path of the final config
my $cfgfile = '/usr/local/nagios/etc/webcontacts.cfg';

# Temp access file
my $tempacc = '/tmp/cgi.cfg.new';

# Full path of the final access file
my $accfile = '/usr/local/nagios/etc/cgi.cfg';

# Access entries to match in $accfile (separated by '|' without spaces)
my $accmatch = 'authorized_for_system_commands|authorized_for_all_service_commands|authorized_for_all_host_commands';

# Config test command
my $cfgtestrun = '/usr/local/nagios/bin/nagios -v /usr/local/nagios/etc/nagios.cfg >/dev/null 2>/dev/null';

# Config reload command
my $cfgreloadrun = 'killall -HUP nagios && /usr/local/nagios/libexec/eventhandlers/enable_notifications';

# send_nsca binary
my $send_nsca = '/usr/local/bin/send_nsca';

# send_nsca config file
my $nsca_config = '/etc/send_nsca.cfg';

# Which host to send reports to
my $nsca_host = `hostname`;
chomp $nsca_host;

# Which service to send report to
my $nsca_service = 'Nagios Admins Update';

## END OF CONFIG SECTION ##

## TEMPLATE SECTION ##

my $contactgroup_template = 
'"### Nagios Admins (Exchange/AD Distribution Group) CONTACT GROUP
### AND CONTACT DEFINITIONS.
###
### WARNING: This file is automatically generated by $0.
###          Do not edit by hands!
  
# \'webadmin\' contact group definition
define contactgroup{
  contactgroup_name       webadmin
  alias                   Nagios Admins
  members                 $contactlist
}

"';

my $contact_template =
'"# \'$name\' contact definition
define contact{
  contact_name                  $name
  alias                         $fullname
  service_notification_period   none
  host_notification_period      none
  service_notification_options  n
  host_notification_options     n
  service_notification_commands notify-by-email
  host_notification_commands    host-notify-by-email
  email                         $email
}

"';

## END OF TEMPLATE SECTION ##

# Use IP address to report status - it's usually the most reliable way.
my $hostname = `hostname`;
chomp $hostname;
$hostname = `gethostip -d $hostname`;
chomp $hostname;

sub report_err {
  my $report = shift;
  warn($report);
  open(RESULT, "|$send_nsca -H $nsca_host -c $nsca_config") or warn "couldn't connect";
  print RESULT "$hostname\t$nsca_service\t1\tWARNING: $report\n";
  close(RESULT);
  exit;
}

sub write_config {
  my %contacts;

  open(INFILE, "<$newdump") or report_err("Can't open $newdump for reading: $!");
  while(<INFILE>) {
    (my $name, my $fullname, my $email) = split(/\t/);
    $contacts{$name} = [$fullname, $email];
  }
  close(INFILE);


  # Get the keys we need...
  my $contactlist;
  foreach my $name (sort keys %contacts) {
    $contactlist .= "$name,";
  }
  chop($contactlist);

  open(OUTFILE, ">$tempcfg") or report_err("Can't open $tempcfg for writing: $!");
  # Write the contactgroup
  print OUTFILE eval($contactgroup_template);

  foreach my $name (sort keys %contacts) {
    (my $fullname, my $email) = @{$contacts{$name}};

    # print each contact definition...
    print OUTFILE eval($contact_template);
  }
  close(OUTFILE);

  # Now write access data
  # But first get some stats for sanity checking :)
  my $accounter = 0;
  my $accmatchnum = 0;
  for (split(/\|/, $accmatch)) { $accmatchnum++; }

  open(ACCINFILE, "<$accfile") or report_err("Can't open $accfile for reading: $!");
  open(ACCOUTFILE, ">$tempacc") or report_err("Can't open $tempacc for writing: $!");
  while(<ACCINFILE>) {
    if (/^($accmatch)=/o) {
      print ACCOUTFILE "$1=$contactlist\n";
      $accounter++;
    } else {
      print ACCOUTFILE;
    }
  }
  close(ACCINFILE);
  close(ACCOUTFILE);
  report_err("Been told to update $accmatchnum lines but $accounter have changed!")
    if ($accounter != $accmatchnum);
}

report_err("last run unsuccessful, aborting (check $newdump)")
  if (-e $newdump);

# This should write $newdump
`$dumpapp`;

report_err("Error retrieving data from $dumpapp") if ($?);

## Compare old with new
if (-e $olddump) {
  print "Comparing data files\n";
  my $old = `wc -l <$olddump`;
  my $new = `wc -l <$newdump`;

  if (!$old || !$new || abs($old - $new) > 10) {
    report_err("Too many differences: " . abs($new - $old));
  }
}

## Good to go, write down config if needed.
write_config();

`diff -q $tempcfg $cfgfile >/dev/null 2>/dev/null`;
if (($? >> 8) == 1 || !-e $cfgfile) {
  unlink $cfgfile or -e $cfgfile and report_err("Can't unlink $cfgfile: $!");
  `mv $tempcfg $cfgfile`;
  report_err("Can't copy new config over $cfgfile") if ($?);
  unlink $accfile or report_err("Can't unlink $accfile: $!");
  `mv $tempacc $accfile`;
  report_err("Can't copy new config over $accfile") if ($?);
  `$cfgtestrun`;
  report_err("Nagios test run failed, please ckeck") if ($?);
  `$cfgreloadrun`;
  report_err("Couldn't SIGHUP Nagios, please ckeck") if ($?);
}

## backup old txt file
`mv $newdump $olddump`;

print "All done\n";

open(RESULT, "|$send_nsca -H $nsca_host -c $nsca_config") or die;
print RESULT "$hostname\t$nsca_service\t0\tOK: Nagios Admins update succesfully completed.\n";
close(RESULT);

