diff options
Diffstat (limited to 'ipaserver')
-rw-r--r-- | ipaserver/install/plugins/Makefile.am | 1 | ||||
-rw-r--r-- | ipaserver/install/plugins/fix_replica_memberof.py | 62 | ||||
-rw-r--r-- | ipaserver/install/replication.py | 29 |
3 files changed, 80 insertions, 12 deletions
diff --git a/ipaserver/install/plugins/Makefile.am b/ipaserver/install/plugins/Makefile.am index a96d0be5c..cfa84c36d 100644 --- a/ipaserver/install/plugins/Makefile.am +++ b/ipaserver/install/plugins/Makefile.am @@ -4,6 +4,7 @@ appdir = $(pythondir)/ipaserver/install app_PYTHON = \ __init__.py \ baseupdate.py \ + fix_replica_memberof.py \ rename_managed.py \ updateclient.py \ $(NULL) diff --git a/ipaserver/install/plugins/fix_replica_memberof.py b/ipaserver/install/plugins/fix_replica_memberof.py new file mode 100644 index 000000000..4ab3df426 --- /dev/null +++ b/ipaserver/install/plugins/fix_replica_memberof.py @@ -0,0 +1,62 @@ +# Authors: +# Rob Crittenden <rcritten@redhat.com> +# +# Copyright (C) 2012 Red Hat +# see file 'COPYING' for use and warranty information +# +# 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 <http://www.gnu.org/licenses/>. + +import os +import pwd +from ipaserver.install.plugins import PRE_UPDATE, MIDDLE +from ipaserver.install.plugins.baseupdate import PreUpdate +from ipaserver import ipaldap +from ipaserver.install import replication +from ipalib import api + +class update_replica_memberof(PreUpdate): + """ + Run through all replication agreements and ensure that memberOf is + included in the EXCLUDE list so we don't cause replication storms. + """ + order=MIDDLE + + def execute(self, **options): + # We need an IPAdmin connection to the backend + conn = ipaldap.IPAdmin(api.env.host, ldapi=True, realm=api.env.realm) + conn.do_external_bind(pwd.getpwuid(os.geteuid()).pw_name) + + repl = replication.ReplicationManager(api.env.realm, api.env.host, + None, conn=conn) + entries = repl.find_replication_agreements() + self.log.debug("Found %d agreement(s)" % len(entries)) + for replica in entries: + self.log.debug(replica.description) + if 'memberof' not in replica.nsDS5ReplicatedAttributeList: + self.log.debug("Attribute list needs updating") + current = replica.toDict() + replica.setValue('nsDS5ReplicatedAttributeList', + replica.nsDS5ReplicatedAttributeList + ' memberof') + try: + repl.conn.updateEntry(replica.dn, current, replica.toDict()) + self.log.debug("Updated") + except Exception, e: + self.log.error("Error caught updating replica: %s" % str(e)) + else: + self.log.debug("No update necessary") + self.log.debug("Done updating agreements") + + return (False, False, []) # No restart, no apply now, no updates + +api.register(update_replica_memberof) diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py index 6f6372514..b36fbf8de 100644 --- a/ipaserver/install/replication.py +++ b/ipaserver/install/replication.py @@ -100,7 +100,7 @@ def enable_replication_version_checking(hostname, realm, dirman_passwd): class ReplicationManager(object): """Manage replication agreements between DS servers, and sync agreements with Windows servers""" - def __init__(self, realm, hostname, dirman_passwd, port=PORT, starttls=False): + def __init__(self, realm, hostname, dirman_passwd, port=PORT, starttls=False, conn=None): self.hostname = hostname self.port = port self.dirman_passwd = dirman_passwd @@ -110,18 +110,23 @@ class ReplicationManager(object): self.suffix = str(DN(tmp)).lower() self.need_memberof_fixup = False - # If we are passed a password we'll use it as the DM password - # otherwise we'll do a GSSAPI bind. - if starttls: - self.conn = ipaldap.IPAdmin(hostname, port=port) - ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, CACERT) - self.conn.start_tls_s() - else: - self.conn = ipaldap.IPAdmin(hostname, port=port, cacert=CACERT) - if dirman_passwd: - self.conn.do_simple_bind(bindpw=dirman_passwd) + # The caller is allowed to pass in an existing IPAdmin connection. + # Open a new one if not provided + if conn is None: + # If we are passed a password we'll use it as the DM password + # otherwise we'll do a GSSAPI bind. + if starttls: + self.conn = ipaldap.IPAdmin(hostname, port=port) + ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, CACERT) + self.conn.start_tls_s() + else: + self.conn = ipaldap.IPAdmin(hostname, port=port, cacert=CACERT) + if dirman_passwd: + self.conn.do_simple_bind(bindpw=dirman_passwd) + else: + self.conn.do_sasl_gssapi_bind() else: - self.conn.do_sasl_gssapi_bind() + self.conn = conn self.repl_man_passwd = dirman_passwd |