Created
March 19, 2020 13:20
-
-
Save tsuchm/3f62b51514be34268a308123c25346c6 to your computer and use it in GitHub Desktop.
LDAP health check daemon
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 <[email protected]> | |
=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