+

Project migrated to https://gogs.zionetrix.net/bn8/check_syncrepl_extended

Benjamin Renard [2017-09-11 10:30:39]
Project migrated to https://gogs.zionetrix.net/bn8/check_syncrepl_extended
Filename
README
check_syncrepl_extended
diff --git a/README b/README
index de4a0c1..3727fdf 100644
--- a/README
+++ b/README
@@ -1,95 +1,3 @@
-Script to check LDAP syncrepl replication state between two servers
-===================================================================
+This project have been migrated to :

-This script check LDAP syncrepl replication state between two servers.
-One server is consider as provider and the other as consumer.
-
-This script can check replication state with two method :
- - by the fisrt, entryCSN of all entries of LDAP directory will be
-   compare between two servers
- - by the second, all values of all atributes of all entries will
-   be compare between two servers.
-
-In all case, contextCSN of servers will be compare and entries not
-present in consumer or in provider will be notice. You can decide to
-disable contextCSN verification by using argument --no-check-contextCSN.
-
-This script is also able to "touch" LDAP object on provider to force
-synchronisation of this object. This mechanism consist to add '%%TOUCH%%'
-value to an attribute of this object and remove it just after. The
-touched attribute is specify by parameter --touch. Of course, couple of
-DN and password provided, must have write right on this attribute.
-
-If your prefer, you can use --replace-touch parameter to replace value
-of touched attribute instead of adding the touched value. Use-ful in
-case of single-value attribute.
-
-To use this script as Nagios plugin, use -n argument
-
-Requirement
------------
-
-A single couple of DN and password able to connect to both server
-and without restriction to retrieve objects from servers.
-
-Usage
------
-
-  Usage: check_syncrepl_extended [options]
-
-  Options:
-    --version             show program's version number and exit
-    -h, --help            show this help message and exit
-    -p PROVIDER, --provider=PROVIDER
-                          LDAP provider URI (example :
-                          ldaps://ldapmaster.foo:636)
-    -c CONSUMER, --consumer=CONSUMER
-                          LDAP consumer URI (example :
-                          ldaps://ldapslave.foo:636)
-    -D DN, --dn=DN        LDAP bind DN (example :
-                          uid=nagios,ou=sysaccounts,o=example
-    -P PWD, --pwd=PWD     LDAP bind password
-    -b BASEDN, --basedn=BASEDN
-                          LDAP base DN (example : o=example)
-    -f FILTER, --filter=FILTER
-                          LDAP filter (default : (objectClass=*))
-    -d, --debug           Debug mode
-    -n, --nagios          Nagios check plugin mode
-    -q, --quiet           Quiet mode
-    --no-check-certificate
-                          Don't check the server certificate (Default : False)
-    --no-check-contextCSN
-                          Don't check servers contextCSN (Default : False)
-    -a, --attributes      Check attributes values (Default : check only
-                          entryCSN)
-    --exclude-attributes=EXCL_ATTRS
-                          Don't check this attribut (only in attribute check
-                          mode)
-    --touch=TOUCH         Touch attribute giving in parameter to force resync a
-                          this LDAP object from provider. A value '%%TOUCH%%'
-                          will be add to this attribute and remove after. The
-                          user use to connect to the LDAP directory must have
-                          write permission on this attribute on each object.
-    --replace-touch       In touch mode, replace value instead of adding.
-
-
-Copyright
----------
-
-Copyright (c) 2013 Benjamin Renard
-
-License
--------
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License version 2
-as published by the Free Software Foundation.
-
-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.
+https://gogs.zionetrix.net/bn8/check_syncrepl_extended
diff --git a/check_syncrepl_extended b/check_syncrepl_extended
deleted file mode 100755
index ed30636..0000000
--- a/check_syncrepl_extended
+++ /dev/null
@@ -1,406 +0,0 @@
-#!/usr/bin/python
-
-#
-# Script to check LDAP syncrepl replication state between two servers.
-# One server is consider as provider and the other as consumer.
-#
-# This script can check replication state with two method :
-#  - by the fisrt, entryCSN of all entries of LDAP directory will be
-#    compare between two servers
-#  - by the second, all values of all atributes of all entries will
-#    be compare between two servers.
-#
-# In all case, contextCSN of servers will be compare and entries not
-# present in consumer or in provider will be notice. You can decide to
-# disable contextCSN verification by using argument --no-check-contextCSN.
-#
-# This script is also able to "touch" LDAP object on provider to force
-# synchronisation of this object. This mechanism consist to add '%%TOUCH%%'
-# value to an attribute of this object and remove it just after. The
-# touched attribute is specify by parameter --touch. Of course, couple of
-# DN and password provided, must have write right on this attribute.
-#
-# If your prefer, you can use --replace-touch parameter to replace value
-# of touched attribute instead of adding the touched value. Use-ful in
-# case of single-value attribute.
-#
-# This script could be use as Nagios plugin (-n argument)
-#
-# Requirement :
-# A single couple of DN and password able to connect to both server
-# and without restriction to retrieve objects from servers.
-#
-# Author : Benjamin Renard <brenard@easter-eggs.com>
-# Date : Mon, 10 Dec 2012 18:04:24 +0100
-# Source : http://git.zionetrix.net/check_syncrepl_extended
-#
-
-import ldap
-import ldap.modlist as modlist
-import logging
-import sys
-import getpass
-
-from optparse import OptionParser
-
-TOUCH_VALUE='%%TOUCH%%'
-
-parser = OptionParser(version="%prog version 1.0\n\nDate : Mon, 10 Dec 2012 18:04:24 +0100\nAuthor : Benjamin Renard <brenard@easter-eggs.com>\nSource : http://git.zionetrix.net/check_syncrepl_extended")
-
-parser.add_option(	"-p", "--provider",
-			dest="provider",
-			action="store",
-			type='string',
-			help="LDAP provider URI (example : ldaps://ldapmaster.foo:636)")
-
-parser.add_option(	"-c", "--consumer",
-			dest="consumer",
-			action="store",
-			type='string',
-			help="LDAP consumer URI (example : ldaps://ldapslave.foo:636)")
-
-parser.add_option(	"-T", "--starttls",
-			dest="starttls",
-			action="store_true",
-			help="Start TLS on LDAP provider/consumers connections",
-			default=False)
-
-parser.add_option(	"-D", "--dn",
-			dest="dn",
-			action="store",
-			type='string',
-			help="LDAP bind DN (example : uid=nagios,ou=sysaccounts,o=example")
-
-parser.add_option(	"-P", "--pwd",
-			dest="pwd",
-			action="store",
-			type='string',
-			help="LDAP bind password. Specify '-P -' to ask for a prompt.")
-
-parser.add_option(	"-b", "--basedn",
-			dest="basedn",
-			action="store",
-			type='string',
-			help="LDAP base DN (example : o=example)")
-
-parser.add_option(	"-f", "--filter",
-			dest="filter",
-			action="store",
-			type='string',
-			help="LDAP filter (default : (objectClass=*))",
-			default='(objectClass=*)')
-
-parser.add_option(	"-d", "--debug",
-			dest="debug",
-			action="store_true",
-			help="Debug mode",
-			default=False)
-
-parser.add_option(	"-n", "--nagios",
-			dest="nagios",
-			action="store_true",
-			help="Nagios check plugin mode",
-			default=False)
-
-parser.add_option(	"-q", "--quiet",
-			dest="quiet",
-			action="store_true",
-			help="Quiet mode",
-			default=False)
-
-parser.add_option(	"--no-check-certificate",
-			dest="nocheckcert",
-			action="store_true",
-			help="Don't check the server certificate (Default : False)",
-			default=False)
-
-parser.add_option(	"--no-check-contextCSN",
-			dest="nocheckcontextcsn",
-			action="store_true",
-			help="Don't check servers contextCSN (Default : False)",
-			default=False)
-
-parser.add_option(	"-a", "--attributes",
-			dest="attrs",
-			action="store_true",
-			help="Check attributes values (Default : check only entryCSN)",
-			default=False)
-
-parser.add_option(	"--exclude-attributes",
-			dest="excl_attrs",
-			action="store",
-			type='string',
-			help="Don't check this attribut (only in attribute check mode)",
-			default=None)
-
-parser.add_option(	"--touch",
-			dest="touch",
-			action="store",
-			type='string',
-			help="Touch attribute giving in parameter to force resync a this LDAP object from provider. A value '%s' will be add to this attribute and remove after. The user use to connect to the LDAP directory must have write permission on this attribute on each object." % TOUCH_VALUE,
-			default=None)
-
-parser.add_option(	"--replace-touch",
-			dest="replacetouch",
-			action="store_true",
-			help="In touch mode, replace value instead of adding.",
-			default=False)
-
-(options, args) = parser.parse_args()
-
-if not options.provider or not options.consumer:
-	print "You must provide provider and customer URI"
-	sys.exit(1)
-
-if not options.basedn:
-	print "You must provide base DN of connection to LDAP servers"
-	sys.exit(1)
-
-if options.touch and not options.attrs:
-	logging.info('Force option attrs on touch mode')
-	options.attrs=True
-
-if options.pwd == '-':
-	options.pwd=getpass.getpass()
-
-excl_attrs=[]
-if options.excl_attrs:
-	for ex in options.excl_attrs.split(','):
-		excl_attrs.append(ex.strip())
-
-FORMAT="%(asctime)s - %(levelname)s : %(message)s"
-
-if options.debug:
-	logging.basicConfig(level=logging.DEBUG,format=FORMAT)
-	ldap.set_option(ldap.OPT_DEBUG_LEVEL,0)
-	ldapmodule_trace_level = 1
-	ldapmodule_trace_file = sys.stderr
-elif options.nagios:
-	logging.basicConfig(level=logging.ERROR,format=FORMAT)
-elif options.quiet:
-	logging.basicConfig(level=logging.WARNING,format=FORMAT)
-else:
-	logging.basicConfig(level=logging.INFO,format=FORMAT)
-
-class LdapServer(object):
-
-	uri = ""
-	dn = ""
-	pwd = ""
-	start_tls = False
-
-	con = 0
-
-	def __init__(self,uri,dn,pwd, start_tls=False):
-		self.uri	= uri
-		self.dn		= dn
-		self.pwd	= pwd
-		self.start_tls	= start_tls
-
-	def connect(self):
-		if self.con == 0:
-			try:
-				con = ldap.initialize(self.uri)
-				con.protocol_version = ldap.VERSION3
-				if self.start_tls:
-					con.start_tls_s()
-				if self.dn:
-					con.simple_bind_s(self.dn,self.pwd)
-				self.con = con
-				return True
-			except ldap.LDAPError, e:
-				logging.error("LDAP Error : %s" % e)
-				return
-
-	def getContextCSN(self,basedn):
-		data=self.search(basedn,'(objectclass=*)',['contextCSN'])
-		if len(data)>0:
-			return data[0][0][1]['contextCSN'][0]
-		else:
-			return False
-
-	def search(self,basedn,filter,attrs):
-		res_id = self.con.search(basedn,ldap.SCOPE_SUBTREE,filter,attrs)
-		ret = []
-		while 1:
-			res_type, res_data = self.con.result(res_id,0)
-			if res_data == []:
-				break
-			else:
-				if res_type == ldap.RES_SEARCH_ENTRY:
-					ret.append(res_data)
-		return ret
-
-	def update_object(self,dn,old,new):
-		ldif = modlist.modifyModlist(old,new)
-		if ldif == []:
-			return True
-		try:
-			logging.debug('Update object %s : %s' % (dn,ldif))
-			self.con.modify_s(dn,ldif)
-			return True
-		except ldap.LDAPError, e:
-			logging.error('Error updating object %s : %s' % (dn,e))
-		return False
-
-	def get_attr(self,obj,attr):
-		if attr in obj[0][1]:
-			return obj[0][1][attr]
-		return []
-
-	def touch_object(self,dn,attr,orig_value):
-		if options.replacetouch:
-			new_value=[TOUCH_VALUE]
-		else:
-			new_value=list(orig_value)
-			new_value.append(TOUCH_VALUE)
-		try:
-			logging.info('Add value "%s" to attribute %s of object %s' % (TOUCH_VALUE,attr,dn))
-			if self.update_object(dn,{attr: orig_value}, {attr: new_value}):
-				logging.info('Remove value "%s" to attribute %s of object %s' % (TOUCH_VALUE,attr,dn))
-				self.update_object(dn,{attr: new_value}, {attr: orig_value})
-				return True
-		except ldap.LDAPError, e:
-			logging.error('Error touching object %s : %s' % (dn,e))
-		return False
-
-if options.nocheckcert:
-	ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT,ldap.OPT_X_TLS_NEVER)
-
-servers=[options.provider,options.consumer]
-
-LdapServers={}
-LdapObjects={}
-LdapServersCSN={}
-
-for srv in servers:
-	logging.info('Connect to %s' % srv)
-	LdapServers[srv]=LdapServer(srv,options.dn,options.pwd,options.starttls)
-
-	if not LdapServers[srv].connect():
-		if options.nagios:
-			print "UNKWNON - Failed to connect to %s" % srv
-			sys.exit(3)
-		else:
-			sys.exit(1)
-
-	if not options.nocheckcontextcsn:
-		LdapServersCSN[srv]=LdapServers[srv].getContextCSN(options.basedn)
-		logging.info('ContextCSN of %s : %s' % (srv, LdapServersCSN[srv]))
-
-	logging.info('List objects from %s' % srv)
-	LdapObjects[srv]={}
-
-	if options.attrs:
-		for obj in LdapServers[srv].search(options.basedn,options.filter,[]):
-			logging.debug('Found on %s : %s' % (srv,obj[0][0]))
-			LdapObjects[srv][obj[0][0]]=obj[0][1]
-	else:
-		for obj in LdapServers[srv].search(options.basedn,options.filter,['entryCSN']):
-			logging.debug('Found on %s : %s / %s' % (srv,obj[0][0],obj[0][1]['entryCSN'][0]))
-			LdapObjects[srv][obj[0][0]]=obj[0][1]['entryCSN'][0]
-
-	logging.info('%s objects founds' % len(LdapObjects[srv]))
-
-
-not_found={}
-not_sync={}
-
-for srv in servers:
-	not_found[srv]=[]
-	not_sync[srv]=[]
-
-if options.attrs:
-	logging.info("Check if objects a are synchronized (by comparing attributes's values)")
-else:
-	logging.info('Check if objets are synchronized (by comparing entryCSN)')
-for obj in LdapObjects[options.provider]:
-	logging.debug('Check obj %s' % (obj))
-	for srv in LdapObjects:
-		if srv == options.provider:
-			continue
-		if obj in LdapObjects[srv]:
-			touch=False
-			if LdapObjects[options.provider][obj] != LdapObjects[srv][obj]:
-				if options.attrs:
-					attrs_list=[]
-					for attr in LdapObjects[options.provider][obj]:
-						if attr in excl_attrs:
-							continue
-						if attr not in LdapObjects[srv][obj]:
-							attrs_list.append(attr)
-							logging.debug("Obj %s not synchronized : %s not present on %s" % (obj,','.join(attrs_list),srv))
-							touch=True
-						else:
-							LdapObjects[srv][obj][attr].sort()
-							LdapObjects[options.provider][obj][attr].sort()
-							if LdapObjects[srv][obj][attr]!=LdapObjects[options.provider][obj][attr]:
-								attrs_list.append(attr)
-								logging.debug("Obj %s not synchronized : %s not same value(s)" % (obj,','.join(attrs_list)))
-								touch=True
-					if len(attrs_list)>0:
-						not_sync[srv].append("%s (%s)" % (obj,','.join(attrs_list)))
-				else:
-					logging.debug("Obj %s not synchronized : %s <-> %s" % (obj,LdapObjects[options.provider][obj],LdapObjects[srv][obj]))
-					not_sync[srv].append(obj)
-			if touch and options.touch:
-				orig_value=[]
-				if options.touch in LdapObjects[options.provider][obj]:
-					orig_value=LdapObjects[options.provider][obj][options.touch]
-				LdapServers[options.provider].touch_object(obj,options.touch,orig_value)
-		else:
-			logging.debug('Obj %s : not found on %s' % (obj,srv))
-			not_found[srv].append(obj)
-			if options.touch:
-				orig_value=[]
-				if options.touch in LdapObjects[options.provider][obj]:
-					orig_value=LdapObjects[options.provider][obj][options.touch]
-				LdapServers[options.provider].touch_object(obj,options.touch,orig_value)
-
-for obj in LdapObjects[options.consumer]:
-	logging.debug('Check obj %s of consumer' % obj)
-	if obj not in LdapObjects[options.provider]:
-		logging.debug('Obj %s : not found on provider' % obj)
-		not_found[options.provider].append(obj)
-
-if options.nagios:
-	errors=[]
-
-	if not options.nocheckcontextcsn:
-		for srv in LdapServersCSN:
-			if srv==options.provider:
-				continue
-			if LdapServersCSN[srv]!=LdapServersCSN[options.provider]:
-				errors.append('ContextCSN of %s not the same of provider' % srv)
-
-	if len(not_found[options.consumer])>0:
-		errors.append("%s not found object(s) on consumer" % len(not_found[options.consumer]))
-	if len(not_found[options.provider])>0:
-		errors.append("%s not found object(s) on provider" % len(not_found[options.provider]))
-	if len(not_sync[options.consumer])>0:
-		errors.append("%s not synchronized object(s) on consumer" % len(not_sync[options.consumer]))
-	if len(errors)>0:
-		print "CRITICAL : "+', '.join(errors)
-		sys.exit(2)
-	else:
-		print 'OK : consumer and provider are synchronized'
-		sys.exit(0)
-else:
-	noerror=True
-	for srv in servers:
-		if not options.nocheckcontextcsn:
-			if srv==options.provider:
-				continue
-			if LdapServersCSN[srv]!=LdapServersCSN[options.provider]:
-				logging.warning('ContextCSN of %s not the same of provider' % srv)
-				noerror=False
-
-		if len(not_found[srv])>0:
-			logging.warning('Not found objects on %s :\n  - %s' % (srv,'\n  - '.join(not_found[srv])))
-			noerror=False
-		if len(not_sync[srv])>0:
-			logging.warning('Not sync objects on %s : %s' % (srv,'\n  - '.join(not_sync[srv])))
-			noerror=False
-
-	if noerror:
-		logging.info('No sync problem detected')
ViewGit