#!/bin/bash
# vim: cindent:shiftwidth=4:tabstop=4:smarttab:textwidth=100

#$title$ LDAP database synchronization
#$check$ hourly test updates of the syncrepl user are recent enough
#$ref$ /etc/cron.hourly/ldap-syncrepl-touch
#$author$ Rafal Rzeczkowski
#$version$ 0.7.0

#CHANGELOG
#0.50	initial
#0.51	test exit codes directly via if, not in sub-shell
#0.52	use awk for all processing (bypass grep)
#0.53	BUG: correctly include ldapsearch output in error message
#0.54	UNKNOWN if no PID file
#0.55	removed IPv6 dependency for now: sync with SLAPD_SERVICES in /etc/default/slapd
#0.56	removed incorrect instances of non-zero exit when returning via "fail warning" API
#0.57	removed semicolon from "fail" warning message - confuses munin2icinga
#0.58	added help messages
#0.59	restyle according to https://kb.clearcable.ca/KB/ProgrammingStyleStandards
#0.6.0	import TIME_UNIT_* constants
#0.7.0	detect stray LMDB files

level_check short

set -o posix
set -o errexit
set -o pipefail
set -o nounset
#set -o xtrace

declare -r -i BEHIND_MAX=$(( 2 * TIME_UNIT_HOUR + TIME_UNIT_MINUTE ))
readonly BEHIND_MAX_SCALED=$(print_size_scaled $BEHIND_MAX 60)
declare -r PIDFILE='/var/run/slapd/slapd.pid'
declare -r LDAPHOST='ip6-localhost'
declare -r CONF='/etc/ldap/replication.conf'
readonly rootdn=$(awk -F: '{if ($1=="##rootdn") { print $2 } }' $CONF)
declare -r DATABASE_DIRECTORY='/var/lib/ldap'

if [[ ! -f $PIDFILE ]]; then
	unknown "slapd PID file $PIDFILE is missing"
	exit
fi

if SEARCH_RESULT=$(ldapsearch -h $LDAPHOST -LLL -x -b "$rootdn" 'cn=syncrepl' 'modifyTimestamp' 2>&1); then
	echodebug 'ldapsearch exec success'
else
	fail warning "failed to retrieve modifyTimestamp for cn=syncrepl: $SEARCH_RESULT"
	helpmsg 'database not initialized?'
	exit
fi

if [[ -z "$SEARCH_RESULT" ]]; then
	fail warning 'ldapsearch result is empty'
	helpmsg 'missing indices?'
	exit
fi

modifyTimestamp=$(awk -F: '{if ($1=="modifyTimestamp") {gsub(" ","",$2);print $2}}' <<< "$SEARCH_RESULT")
if [[ -z "$modifyTimestamp" ]]; then
	fail warning 'modifyTimestamp is empty'
	helpmsg 'syscheck plugin general failure?'
	exit
fi

TIMESTAMP="${modifyTimestamp:0:4}-${modifyTimestamp:4:2}-${modifyTimestamp:6:2} ${modifyTimestamp:8:2}:${modifyTimestamp:10:2}:${modifyTimestamp:12:2}"
DATE_CUR=$(date --utc +%s)
DATE_LDAP=$(date --utc --date="$TIMESTAMP" +%s)
DATE_DIFF=$(( DATE_CUR - DATE_LDAP ))
DATE_DIFF_SCALED=$(print_size_scaled $DATE_DIFF 60)

if [[ $DATE_DIFF -gt $BEHIND_MAX ]]; then
	fail warning "modifyTimestamp is $DATE_DIFF_SCALED behind (maximum allowed is $BEHIND_MAX_SCALED)"
	helpmsg 'replication is broken - master server down, network connectivity, DNS'
	exit
else
	echodebug "LDAP modifyTimestamp=$DATE_DIFF_SCALED(<$BEHIND_MAX_SCALED)"
fi

LMDB_FILES=$(find "$DATABASE_DIRECTORY" -name '*.mdb')
if [[ -n "$LMDB_FILES" ]]; then
	fail warning "LMDB files present in database directory $DATABASE_DIRECTORY"
	helpmsg 'database type should be set globally to {hdb}'
	exit
fi

ok
