# HG changeset patch # User arnold # Date 1354187549 -3600 # Node ID a04ea5e7c15b0f8616278d8a98c0ea3237010bfe import to mercurial diff -r 000000000000 -r a04ea5e7c15b .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Thu Nov 29 12:12:29 2012 +0100 @@ -0,0 +1,8 @@ +syntax: glob +*.swp +debian/files +check_ldap_repl + +syntax: regexp +(build|configure)-stamp$ +debian/nagios-plugin-ldap-repl[./] diff -r 000000000000 -r a04ea5e7c15b Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Thu Nov 29 12:12:29 2012 +0100 @@ -0,0 +1,22 @@ +SCRIPTS = check_ldap_repl +CLEANFILES = ${SCRIPTS} +DESTDIR = +prefix = /usr + +plugindir = ${prefix}/lib/nagios/plugins/ius + +.PHONY: all clean install + +all: ${SCRIPTS} + +clean: + -rm -f ${CLEANFILES} + +install: all + install -d -m 0755 ${DESTDIR}/${plugindir} + install -m 0755 $(SCRIPTS) ${DESTDIR}/${plugindir}/ + +%: %.pl + @perl -c $< + @cp -f $< $@ + @chmod +x $@ diff -r 000000000000 -r a04ea5e7c15b check_ldap_repl.pl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/check_ldap_repl.pl Thu Nov 29 12:12:29 2012 +0100 @@ -0,0 +1,402 @@ +#! /usr/bin/perl -w + +# Copyright (C) 2012 Christian Arnold +# +# 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 3 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, see . +# +# Christian Arnold + +# packages: libnet-ldap-perl +# packages: libio-prompt-perl +# packages: libio-socket-ssl-perl +# packages: libconfig-inifiles-perl +# packages: perl-doc (optional - for man page) + +use strict; +use File::Basename; +use Getopt::Long; +use Config::IniFiles; +use Net::LDAP; +use IO::Prompt; +use File::stat; +use Pod::Usage; +use if $ENV{DEBUG} => "Smart::Comments"; + +sub version($$); +sub read_config(); +sub ldap_object($); +sub get_stamp($$); +sub compare_results(%); + +my %ERRORS = ( + OK => 0, + WARNING => 1, + CRITICAL => 2, + UNKNOWN => 3, + DEPENDENT => 4 +); + +my $ME = basename $0; +my $NAME = "LDAPREPL"; +my $VERSION = "0.1"; + +my %opt = ( + init => 0, + delete => 0, + refresh => 0, + cn => "replcheck", + wait => 1, + file => "/etc/nagios/ius/plugins/config/check_ldap_repl.cfg", + master => "ldap://ldap-master:389/", + slave => "ldap://ldap-slave:389/" +); + +MAIN: { + Getopt::Long::Configure('bundling'); + GetOptions( + "i|init" => \$opt{init}, + "d|delete" => \$opt{delete}, + "r|refresh" => \$opt{refresh}, + "b|binddn=s" => \$opt{binddn}, + "p|password=s" => \$opt{password}, + "c|cn=s" => \$opt{cn}, + "w|wait=i" => \$opt{wait}, + "M|master=s" => \$opt{master}, + "S|slave=s" => \$opt{slave}, + "f|file=s" => \$opt{file}, + "h|help" => sub { pod2usage( -verbose => 1, -exitval => $ERRORS{OK} ) }, + "m|man" => sub { pod2usage( -verbose => 2, -exitval => $ERRORS{OK} ) }, + "V|version" => sub { version( $ME, $VERSION ); exit $ERRORS{OK}; } + ) or pod2usage( -verbose => 1, -exitval => $ERRORS{CRITICAL} ); + + if ($opt{init}) { + ldap_object("init"); + print "new object successfully initialized\n"; + exit $ERRORS{OK}; + } elsif ($opt{delete}) { + ldap_object("delete"); + print "object successfully deleted\n"; + exit $ERRORS{OK}; + } + + ldap_object("refresh") if ($opt{refresh}); + + my ($master, $slave, $cn) = undef; + my @slaves = (); + my %results = (); + + if (-r $opt{file}) { + (undef, undef, $master, $slave, $cn) = read_config(); + @slaves = split(/,/, $slave); + } else { + $master = $opt{master}; + @slaves = split(/,/, $opt{slave}); + $cn = $opt{cn}; + } + + $results{$master}{'master'} = get_stamp($master, $cn); + sleep $opt{wait}; + foreach (@slaves) { + $results{$_}{'slave'} = get_stamp($_, $cn); + } + + compare_results(\%results); +} + +sub compare_results(%) { + my @output = (); + my %stamps = (); + my (%results) = %{$_[0]}; + for my $server ( keys %results ) { + for my $type ( keys %{ $results{$server} } ) { + $stamps{$results{$server}{$type}} = ""; + push @output, "$type: $server = $results{$server}{$type}"; + } + } + + @output = sort(@output); + if (scalar(keys(%stamps)) != 1 ) { + print "$NAME CRITICAL: server are not in sync @output\n"; + exit $ERRORS{CRITICAL}; + } else { + print "$NAME OK: servers are in sync @output\n"; + exit $ERRORS{OK}; + } +} + +sub read_config() { + my ($binddn, $password, $cn, $master, $slave); + my $cfg = new Config::IniFiles( -file => "$opt{file}"); + $binddn = $cfg->val('bind', 'dn')?$cfg->val('bind', 'dn'):$opt{binddn}; + $password = $cfg->val('bind', 'password')?$cfg->val('bind', 'password'):$opt{password}; + $master = $cfg->val('master', 'server')?$cfg->val('master', 'server'):$opt{master}; + $slave = $cfg->val('slave', 'server')?$cfg->val('slave', 'server'):$opt{slave}; + $cn = $cfg->val('object', 'cn')? $cfg->val('object', 'cn'):$opt{cn}; + + return ($binddn, $password, $master, $slave, $cn); +} + +sub ldap_object($) { + my $type = shift; + my ($binddn, $password) = undef; + + my $master = $opt{master}; + my $cn = $opt{cn}; + + if ( ($type eq "init") || ($type eq "delete") ) { + $binddn = prompt('BindDN: '); + $password = prompt('Password: ', -e => '*'); + } else { + if ($opt{binddn} && $opt{password}) { + $binddn = $opt{binddn}; + $password = $opt{password}; + } elsif (-r $opt{file}) { + ($binddn, $password, $master, undef, $cn) = read_config(); + } else { + $binddn = prompt('BindDN: '); + $password = prompt('Password: ', -e => '*'); + } + } + + my $ldap = Net::LDAP->new( $master ) or die "$@"; + + my $mesg = $ldap->bind("$binddn", password => $password); + if ($mesg->code) { + $ldap->unbind() if ($ldap); + print "$NAME CRITICAL: " . $mesg->error . "\n"; + exit $ERRORS{CRITICAL}; + } + + # get ldap naming context + my $dse = $ldap->root_dse(); + my $context = $dse->get_value('namingContexts'); + + if (! defined $context) { + print "$NAME CRITICAL: can't determine ldap 'naming context'\n"; + exit $ERRORS{CRITICAL}; + } + + if ($mesg->code) { + print "$NAME CRITICAL: " . $mesg->error . "\n"; + exit $ERRORS{CRITICAL}; + } + + # initialize check object + $mesg = $ldap->add( + "cn=$cn,$context", + attr => [ + 'objectclass' => [ 'top', 'person' ], + 'cn' => "$cn", + 'sn' => "$cn", + 'description' => time() + ], + ) if ($type eq "init"); + + # delete check object + $mesg = $ldap->delete("cn=$cn,$context") if ($type eq "delete"); + + if ($mesg->code && ($type eq "delete" || $type eq "init")) { + print "$NAME CRITICAL: " . $mesg->error . "\n"; + exit $ERRORS{CRITICAL}; + } + + # refresh check object + $mesg = $ldap->modify( + "cn=$cn,$context", + replace => { + description => time() + } + ) if ($opt{refresh}); + + $ldap->unbind() if ($ldap); + return 0; +} + +sub get_stamp($$) { + my ($server, $cn) = @_; + my $ldap = Net::LDAP->new( $server ) or die "$@"; + my $mesg = $ldap->bind(); + + if ($mesg->code) { + $ldap->unbind() if ($ldap); + print "$NAME CRITICAL: " . $mesg->error . "\n"; + exit $ERRORS{CRITICAL}; + } + + # get ldap naming context + my $dse = $ldap->root_dse(); + my $context = $dse->get_value('namingContexts'); + + if (! defined $context) { + print "$NAME CRITICAL: can't determine ldap 'naming context'\n"; + exit $ERRORS{CRITICAL}; + } + + $mesg = $ldap->search( + base => "cn=replcheck,$context", + scope => "base", + filter => "(cn=$cn)", + attr => [ 'description' ] + + ); + + if ($mesg->code) { + $ldap->unbind() if ($ldap); + print "$NAME CRITICAL: " . $mesg->error . "\n"; + exit $ERRORS{CRITICAL}; + } + + if ($mesg->count != 1) { + print "$NAME CRITICAL: \n"; + exit $ERRORS{CRITICAL}; + } + + my $entry = $mesg->entry(0); + return $entry->get_value("description"); + + $ldap->unbind() if ($ldap); +} + +sub version($$) { + my ( $progname, $version ) = @_; + + print <<_VERSION; +$progname version $version +Copyright (C) 2012 by Christian Arnold and Schlittermann internet & unix support. + +$ME comes with ABSOLUTELY NO WARRANTY. This is free software, +and you are welcome to redistribute it under certain conditions. +See the GNU General Public Licence for details. +_VERSION +} + +__END__ + +=head1 NAME + +check_ldap_repl - nagios/icinga plugin to check correctly working of ldap replication. + +=head1 SYNOPSIS + +check_ldap_repl [-i|--init] + [-d|--delete] + [-r|--refresh] + [-c|--cn string] + [-b|--binddn string] + [-p|--password string] + [-f|--file string] + [-M|--master string] + [-S|--slave string] + [-w|--wait integer] + [-h|--help] + [-m|--man] + [-V|--version] + +=head1 OPTIONS + +=over + +=item B<-i>|B<--init> + +Add the check object cn=replcheck,I to the master server if not existis. See also the B<--cn> option. +You will ask for an B and B, if not given B<--binddn> and B<--password> options. +Your B must have write permission to the ldap master server. + +=item B<-d>|B<--delete> + +Delete the check object from the ldap master server if existis. See also the B<--cn> option. +You will ask for an B and B, if not given B<--binddn> and B<--password> options. +Your B must have write permission to the ldap master server. + +=item B<-r>|B<--refresh> + +Refresh the stamp attribute of the check attribute with current unix time. +You will ask for an B and B, if not given B<--binddn> and B<--password> options. See also B<--file> option. +Your B must have write permission to the ldap master server. + +=item B<-c>|B<--cn> I + +cn for the initialized object. See also the B<--init> option. (default: replcheck) + +=item B<-b>|B<--binddn> I + +DN to bind to ldap master server. + +=item B<-p>|B<--password> I + +Password for binddn to ldap master server. B + +=item B<-M>|B<--master> I + +LDAP master server (provider) (default: ldap://ldap-master:389/) + +=item B<-S>|B<--slave> I + +LDAP slave server (consumer), multiple slaves can be specified as a comma-separate list (default: ldap://ldap-slave:389/) + +=item B<-f>|B<--file> I + +Config file with B and B. Verify the file B/B and B, B<(0400)> is a good choice! +You can also set B and B options. (default: /etc/nagios/ius/plugins/config/check_ldap_repl.cfg) + + [bind] + dn = cn=admin,dc=local,dc=site + password = secret + + [master] + server = ldap://ldap-master:389/ + + [slave] + server = ldap://ldap-slave01:389/,ldap://ldap-slave02:389/,... + + [object] + cn = replcheck + +=item B<-w>|B<--wait> I + +Wait I seconds before check the slave servers. (default: 1) + +=item B<-h>|B<--help> + +Print detailed help screen. + +=item B<-m>|B<--man> + +Print manual page. + +=item B<-V>|B<--version> + +Print version information. + +=back + +=head1 DESCRIPTION + +This plugin checks if the ldap replication works correctly. + +=head1 VERSION + +This man page is current for version 0.1 of B. + +=head1 AUTHOR + +Written by Christian Arnold L + +=head1 COPYRIGHT + +Copyright (C) 2012 by Christian Arnold and Schlittermann internet & unix support. +This is free software, and you are welcome to redistribute it under certain conditions. +See the GNU General Public Licence for details. + +=cut diff -r 000000000000 -r a04ea5e7c15b debian/changelog --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/debian/changelog Thu Nov 29 12:12:29 2012 +0100 @@ -0,0 +1,5 @@ +nagios-plugin-ldap-repl (0.1) stable; urgency=low + + * Initial Release. + + -- Christian Arnold Thu, 29 Nov 2012 11:51:52 +0100 diff -r 000000000000 -r a04ea5e7c15b debian/compat --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/debian/compat Thu Nov 29 12:12:29 2012 +0100 @@ -0,0 +1,1 @@ +7 diff -r 000000000000 -r a04ea5e7c15b debian/control --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/debian/control Thu Nov 29 12:12:29 2012 +0100 @@ -0,0 +1,14 @@ +Source: nagios-plugin-ldap-repl +Section: net +Priority: extra +Maintainer: Christian Arnold +Build-Depends: debhelper (>= 7.0.50~) +Standards-Version: 3.8.4 +Homepage: https://ssl.schlittermann.de/hg/ius/nagios/nagios-plugin-ldap-repl/ + +Package: nagios-plugin-ldap-repl +Architecture: all +Depends: ${misc:Depends}, ${perl:Depends}, libnet-ldap-perl, libio-prompt-perl, libio-socket-ssl-perl, libconfig-inifiles-perl +Suggests: perl-doc +Description: nagios/icinga plugin to check ldap replication + This plugin checks if the ldap replication works correctly. diff -r 000000000000 -r a04ea5e7c15b debian/copyright --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/debian/copyright Thu Nov 29 12:12:29 2012 +0100 @@ -0,0 +1,39 @@ +This work was packaged for Debian by: + + Christian Arnold on Thu, 29 Nov 2012 11:51:52 +0100 + +It was downloaded from: + + https://ssl.schlittermann.de/hg/ius/nagios/nagios-plugin-ldap-repl/ + +Upstream Author(s): + + Christian Arnold + +Copyright: + + Copyright (C) 2011 Schlittermann internet & unix support + +License: + + 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 3 of the License, or + (at your option) any later version. + + This package 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, see . + +On Debian systems, the complete text of the GNU General +Public License version 3 can be found in "/usr/share/common-licenses/GPL-3". + +The Debian packaging is: + + Copyright (C) 2012 Christian Arnold + +and is licensed under the GPL version 3, see above. diff -r 000000000000 -r a04ea5e7c15b debian/docs diff -r 000000000000 -r a04ea5e7c15b debian/rules --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/debian/rules Thu Nov 29 12:12:29 2012 +0100 @@ -0,0 +1,13 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +%: + dh $@ diff -r 000000000000 -r a04ea5e7c15b debian/source/format --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/debian/source/format Thu Nov 29 12:12:29 2012 +0100 @@ -0,0 +1,1 @@ +3.0 (native)