Skip to content

Instantly share code, notes, and snippets.

@tsuchm
Created March 19, 2020 13:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tsuchm/3f62b51514be34268a308123c25346c6 to your computer and use it in GitHub Desktop.
Save tsuchm/3f62b51514be34268a308123c25346c6 to your computer and use it in GitHub Desktop.
LDAP health check daemon
#!/usr/bin/perl
=head1 NAME
ldap-health-check
=head1 INSTALL
First, put this script into /usr/local/bin/ and make it executable.
Second, prepare the following service file as
/etc/systemd/system/ldap-health-check.service.
[Unit]
Description = ldap-health-check daemon
[Service]
ExecStart = /usr/local/bin/ldap-health-check --conffile /etc/postfix/your-ldap-config.cf
Type = simple
Restart = always
StartLimitBurst = 1
[Install]
RequiredBy = postfix.service
Finally, configure your cron daemon to make postfix start
periodically.
=head1 AUTHOR
TSUCHIYA Masatoshi <tsuchm@gmail.com>
=head1 LICENSE
GPL3.
=cut
use English qw/ $PROGRAM_NAME $PID $UID /;
use File::Basename qw/ basename /;
use Getopt::Long;
use Net::LDAP;
use Sys::Syslog qw/ LOG_MAIL LOG_INFO LOG_NDELAY /;
use User::pwent;
use POSIX qw/ setgid setuid /;
use strict;
our @SERVER;
our $BINDDN;
our $BINDPW;
our $BASEDN;
our $INTERVAL = 30;
our $DEBUG;
&GetOptions( 'conffile=s' => sub { &readconffile($_[1]); },
'server=s@' => \@SERVER,
'binddn=s' => \$BINDDN,
'bindpw=s' => \$BINDPW,
'basedn=s' => \$BASEDN,
'interval=i' => \$INTERVAL,
'debug!' => \$DEBUG );
&main();
sub main {
if( $UID == 0 ){
my $pw = getpwnam('nobody') or die;
&setgid( $pw->gid );
&setuid( $pw->uid );
}
sleep $INTERVAL while &check();
exit 1;
}
sub check {
my $ldap;
for my $server ( @SERVER ){
last if ( $ldap = Net::LDAP->new( $server ) );
}
unless( $ldap ){
&syslog( 'LDAP connection error' );
return 0;
}
my $msg = $BINDDN ? $ldap->bind( $BINDDN, password => $BINDPW ) : $ldap->bind();
if( $msg->code ){
&syslog( 'LDAP bind error: dn=%s, code=%s, reason=%s', $BINDDN, $msg->code, $msg->error );
return 0;
}
$msg = $ldap->search( filter => '(objectClass=*)', base => $BASEDN, scope => 'base' );
if( $msg->code ){
&syslog( 'LDAP search error: dn=%s, code=%s, reason=%s', $BASEDN, $msg->code, $msg->error );
0;
} else {
&syslog( 'LDAP search success: dn=%s', $BASEDN );
1;
}
}
INIT {
&Sys::Syslog::openlog( sprintf( '%s[%d]', &basename($PROGRAM_NAME), $PID ), LOG_NDELAY, LOG_MAIL );
}
sub syslog {
my $message = sprintf( shift, @_ );
&Sys::Syslog::syslog( LOG_INFO, $message );
print 'DEBUG: ', $message, "\n" if $DEBUG;
}
END {
&Sys::Syslog::closelog();
}
sub readconffile {
my( $file ) = @_;
if( open( my $fh, '<:bytes', $file ) ){
while ( <$fh> ) {
s/\s+\Z//;
if( s/\Abind_dn=// ){
$BINDDN = $_;
} elsif( s/\Abind_pw=// ){
$BINDPW = $_;
} elsif( s/\Asearch_base=// ){
s/%d/%s/;
$BASEDN = $_;
} elsif( s/\Aserver_host=// ){
@SERVER = ( $_ );
}
}
close $fh;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment