Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 316460 Details for
Bug 459729
Windows sync support in IPA
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Support IPA in IPA server install and ipa-replica-manage
0008-Added-support-to-IPA-server-install-to-install-the-w.patch (text/plain), 16.44 KB, created by
Rich Megginson
on 2008-09-11 17:10:20 UTC
(
hide
)
Description:
Support IPA in IPA server install and ipa-replica-manage
Filename:
MIME Type:
Creator:
Rich Megginson
Created:
2008-09-11 17:10:20 UTC
Size:
16.44 KB
patch
obsolete
>From 64ba55237f67ba089f5d3de86c496f794ea8e2b5 Mon Sep 17 00:00:00 2001 >From: Rich Megginson <rmeggins@redhat.com> >Date: Thu, 11 Sep 2008 10:56:55 -0600 >Subject: [PATCH] Added support to IPA server install to install the winsync plugin configuration entry > Added support to ipa-replica-manage to add winsync agreements. I mostly used the existing code for setting up replication agreements since replication and winsync are quite similar in their configuration. I just had to add some extra attributes to the sync agreement configuration. > The tricky part was importing the Windows CA cert. > >--- > ipa-server/ipa-install/ipa-replica-manage | 36 ++++++++- > .../ipa-winsync/ipa-winsync-conf.ldif | 7 ++- > ipa-server/ipaserver/dsinstance.py | 59 ++++++++++++++ > ipa-server/ipaserver/ipaldap.py | 2 + > ipa-server/ipaserver/replication.py | 84 +++++++++++++++----- > 5 files changed, 164 insertions(+), 24 deletions(-) > >diff --git a/ipa-server/ipa-install/ipa-replica-manage b/ipa-server/ipa-install/ipa-replica-manage >index 78cfe88..2021eab 100644 >--- a/ipa-server/ipa-install/ipa-replica-manage >+++ b/ipa-server/ipa-install/ipa-replica-manage >@@ -34,11 +34,21 @@ def parse_options(): > parser.add_option("-p", "--password", dest="dirman_passwd", help="Directory Manager password") > parser.add_option("-v", "--verbose", dest="verbose", action="store_true", default=False, > help="provide additional information") >+ parser.add_option("--port", type="int", dest="port", >+ help="port number of other server") >+ parser.add_option("--binddn", dest="binddn", >+ help="Bind DN to use with remote server") >+ parser.add_option("--bindpw", dest="bindpw", >+ help="Password for Bind DN to use with remote server") >+ parser.add_option("--winsync", dest="winsync", action="store_true", default=False, >+ help="This is a Windows Sync Agreement") >+ parser.add_option("--cacert", dest="cacert", >+ help="Full path and filename of CA certificate to use with TLS/SSL to the remote server") > > options, args = parser.parse_args() > > if not len(args) or not ("list" in args[0] or "add" in args[0] or "del" in args[0] or "init" in args[0] or "synch" in args[0]): >- parser.error("must provide a comment [list | add | del | init | synch]") >+ parser.error("must provide a command [list | add | del | init | synch]") > > return options, args > >@@ -81,8 +91,26 @@ def del_master(replman, hostname): > replman.delete_agreement(other_replman.conn) > other_replman.delete_agreement(replman.conn) > >-def add_master(replman, hostname): >- replman.setup_replication(hostname, get_realm_name()) >+def add_master(replman, hostname, options): >+ other_args = {} >+ if options.winsync: >+ # these are the parameters required to create a winsync agreement >+ other_args['winsync'] = True >+ if options.port: >+ other_args['port'] = options.port >+ other_args['binddn'] = options.binddn >+ other_args['bindpw'] = options.bindpw >+ other_args['cacert'] = options.cacert >+ # have to install the windows ca cert before doing anything else >+ ds = dsinstance.DsInstance(realm_name = get_realm_name(), >+ dm_password = replman.dirman_passwd) >+ if not ds.add_ca_cert(options.cacert): >+ logging.error("Could not load the required CA certificate file [%s] - cannot add winsync agreement" % >+ options.cacert) >+ sys.exit(1) >+ # have to reconnect replman connection since the directory server was restarted >+ replman = replication.ReplicationManager(replman.hostname, replman.dirman_passwd) >+ replman.setup_replication(hostname, get_realm_name(), **other_args) > > def init_master(replman, dirman_passwd, hostname): > filter = "(&(nsDS5ReplicaHost=%s)(objectclass=nsds5ReplicationAgreement))" % hostname >@@ -133,7 +161,7 @@ def main(): > if len(args) != 2: > print "must provide hostname of master to add" > sys.exit(1) >- add_master(r, args[1]) >+ add_master(r, args[1], options) > elif args[0] == "init": > if len(args) != 2: > print "hostname of supplier to initialize from is required." >diff --git a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif b/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif >index 3fdcc54..8bf8e27 100644 >--- a/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif >+++ b/ipa-server/ipa-slapi-plugins/ipa-winsync/ipa-winsync-conf.ldif >@@ -1,10 +1,15 @@ > dn: cn=ipa-winsync,cn=plugins,cn=config >+changetype: add > objectclass: top > objectclass: nsSlapdPlugin > objectclass: extensibleObject > cn: ipa-winsync >-nsslapd-pluginpath: libipa-winsync >+nsslapd-pluginpath: libipa_winsync > nsslapd-plugininitfunc: ipa_winsync_plugin_init >+nsslapd-pluginDescription: Allows IPA to work with the DS windows sync feature >+nsslapd-pluginid: ipa-winsync >+nsslapd-pluginversion: 1.0 >+nsslapd-pluginvendor: Red Hat > nsslapd-plugintype: preoperation > nsslapd-pluginenabled: on > nsslapd-plugin-depends-on-type: database >diff --git a/ipa-server/ipaserver/dsinstance.py b/ipa-server/ipaserver/dsinstance.py >index d313b4e..c4b04d1 100644 >--- a/ipa-server/ipaserver/dsinstance.py >+++ b/ipa-server/ipaserver/dsinstance.py >@@ -27,6 +27,7 @@ import os > import re > import time > import tempfile >+import stat > > from ipa import ipautil > >@@ -68,6 +69,10 @@ def erase_ds_instance_data(serverid): > except: > pass > try: >+ shutil.rmtree("/usr/lib64/dirsrv/slapd-%s" % serverid) >+ except: >+ pass >+ try: > shutil.rmtree("/var/lib/dirsrv/slapd-%s" % serverid) > except: > pass >@@ -75,6 +80,10 @@ def erase_ds_instance_data(serverid): > shutil.rmtree("/var/lock/dirsrv/slapd-%s" % serverid) > except: > pass >+# try: >+# shutil.rmtree("/var/log/dirsrv/slapd-%s" % serverid) >+# except: >+# pass > > def check_existing_installation(): > dirs = glob.glob("/etc/dirsrv/slapd-*") >@@ -164,6 +173,7 @@ class DsInstance(service.Service): > self.step("enabling memberof plugin", self.__add_memberof_module) > self.step("enabling referential integrity plugin", self.__add_referint_module) > self.step("enabling distributed numeric assignment plugin", self.__add_dna_module) >+ self.step("enabling winsync plugin", self.__add_winsync_module) > self.step("configuring uniqueness plugin", self.__set_unique_attrs) > self.step("creating indices", self.__create_indices) > self.step("configuring ssl for ds instance", self.__enable_ssl) >@@ -319,6 +329,9 @@ class DsInstance(service.Service): > def __add_master_entry_first_master(self): > self.__ldap_mod("master-entry.ldif", self.sub_dict) > >+ def __add_winsync_module(self): >+ self.__ldap_mod("ipa-winsync-conf.ldif") >+ > def __enable_ssl(self): > dirname = config_dirname(self.serverid) > ca = certs.CertDB(dirname) >@@ -415,3 +428,49 @@ class DsInstance(service.Service): > > if self.restore_state("running"): > self.start() >+ >+ # we could probably move this function into the service.Service >+ # class - it's very generic - all we need is a way to get an >+ # instance of a particular Service >+ def add_ca_cert(self, cacert_fname, cacert_name=''): >+ """Add a CA certificate to the directory server cert db. We >+ first have to shut down the directory server in case it has >+ opened the cert db read-only. Then we use the CertDB class >+ to add the CA cert. We have to provide a nickname, and we >+ do not use 'CA certificate' since that's the default, so >+ we use 'Imported CA' if none specified. Then we restart >+ the server.""" >+ # first make sure we have a valid cacert_fname >+ try: >+ if not os.access(cacert_fname, os.R_OK): >+ logging.critical("The given CA cert file named [%s] could not be read" % >+ cacert_fname) >+ return False >+ except OSError, e: >+ logging.critical("The given CA cert file named [%s] could not be read: %s" % >+ (cacert_fname, str(e))) >+ return False >+ # ok - ca cert file can be read >+ # shutdown the server >+ running = self.restore_state("running") >+ >+ if not running is None: >+ self.stop() >+ >+ dirname = config_dirname(realm_to_serverid(self.realm_name)) >+ certdb = certs.CertDB(dirname) >+ if not cacert_name or len(cacert_name) == 0: >+ cacert_name = "Imported CA" >+ # we can't pass in the nickname, so we set the instance variable >+ certdb.cacert_name = cacert_name >+ status = True >+ try: >+ certdb.load_cacert(cacert_fname) >+ except CalledProcessError, e: >+ logging.critical("Error importaing CA cert file named [%s]: %s" % >+ (cacert_fname, str(e))) >+ status = False >+ # restart the directory server >+ self.start() >+ >+ return status >diff --git a/ipa-server/ipaserver/ipaldap.py b/ipa-server/ipaserver/ipaldap.py >index 3006d47..c2dbe4e 100644 >--- a/ipa-server/ipaserver/ipaldap.py >+++ b/ipa-server/ipaserver/ipaldap.py >@@ -243,6 +243,8 @@ class IPAdmin(SimpleLDAPObject): > self.dbdir = os.path.dirname(ent.getValue('nsslapd-directory')) > except (ldap.INSUFFICIENT_ACCESS, ldap.CONNECT_ERROR): > pass # usually means >+ except ldap.OPERATIONS_ERROR, e: >+ pass # usually means this is Active Directory > except ldap.LDAPError, e: > print "caught exception ", e > raise >diff --git a/ipa-server/ipaserver/replication.py b/ipa-server/ipaserver/replication.py >index d3b1551..3ab2e6b 100644 >--- a/ipa-server/ipaserver/replication.py >+++ b/ipa-server/ipaserver/replication.py >@@ -25,11 +25,15 @@ from ipa import ipaerror > > DIRMAN_CN = "cn=directory manager" > CACERT="/usr/share/ipa/html/ca.crt" >+# the default container used by AD for user entries >+WIN_USER_CONTAINER="cn=Users" >+# the default container used by IPA for user entries >+IPA_USER_CONTAINER="cn=users,cn=accounts" > PORT = 636 > TIMEOUT = 120 >- > class ReplicationManager: >- """Manage replicatin agreements between DS servers""" >+ """Manage replication agreements between DS servers, and sync >+ agreements with Windows servers""" > def __init__(self, hostname, dirman_passwd): > self.hostname = hostname > self.dirman_passwd = dirman_passwd >@@ -197,6 +201,23 @@ class ReplicationManager: > chainbe = self.setup_chaining_backend(other_conn) > self.enable_chain_on_update(chainbe) > >+ def setup_winsync_agmt(self, entry, **kargs): >+ entry.setValues("objectclass", "nsDSWindowsReplicationAgreement") >+ entry.setValues("nsds7WindowsReplicaSubtree", >+ kargs.get("win_subtree", >+ WIN_USER_CONTAINER + "," + self.suffix)) >+ entry.setValues("nsds7DirectoryReplicaSubtree", >+ kargs.get("ds_subtree", >+ IPA_USER_CONTAINER + "," + self.suffix)) >+ # for now, just sync users and ignore groups >+ entry.setValues("nsds7NewWinUserSyncEnabled", kargs.get('newwinusers', 'true')) >+ entry.setValues("nsds7NewWinGroupSyncEnabled", kargs.get('newwingroups', 'false')) >+ windomain = '' >+ if kargs.has_key('windomain'): >+ windomain = kargs['windomain'] >+ else: >+ windomain = '.'.join(ldap.explode_dn(self.suffix, 1)) >+ entry.setValues("nsds7WindowsDomain", windomain) > > def agreement_dn(self, conn): > cn = "meTo%s%d" % (conn.host, PORT) >@@ -204,7 +225,7 @@ class ReplicationManager: > > return (cn, dn) > >- def setup_agreement(self, a, b): >+ def setup_agreement(self, a, b, **kargs): > cn, dn = self.agreement_dn(b) > try: > a.getEntry(dn, ldap.SCOPE_BASE) >@@ -212,20 +233,27 @@ class ReplicationManager: > except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND): > pass > >+ iswinsync = kargs.get("winsync", False) >+ repl_man_dn = kargs.get("binddn", self.repl_man_dn) >+ repl_man_passwd = kargs.get("bindpw", self.repl_man_passwd) >+ port = kargs.get("port", PORT) >+ > entry = ipaldap.Entry(dn) >- entry.setValues('objectclass', "top", "nsds5replicationagreement") >+ entry.setValues('objectclass', "nsds5replicationagreement") > entry.setValues('cn', cn) > entry.setValues('nsds5replicahost', b.host) >- entry.setValues('nsds5replicaport', str(PORT)) >+ entry.setValues('nsds5replicaport', str(port)) > entry.setValues('nsds5replicatimeout', str(TIMEOUT)) >- entry.setValues('nsds5replicabinddn', self.repl_man_dn) >- entry.setValues('nsds5replicacredentials', self.repl_man_passwd) >+ entry.setValues('nsds5replicabinddn', repl_man_dn) >+ entry.setValues('nsds5replicacredentials', repl_man_passwd) > entry.setValues('nsds5replicabindmethod', 'simple') > entry.setValues('nsds5replicaroot', self.suffix) > entry.setValues('nsds5replicaupdateschedule', '0000-2359 0123456') > entry.setValues('nsds5replicatransportinfo', 'SSL') > entry.setValues('nsDS5ReplicatedAttributeList', '(objectclass=*) $ EXCLUDE memberOf') >- entry.setValues('description', "me to %s%d" % (b.host, PORT)) >+ entry.setValues('description', "me to %s%d" % (b.host, port)) >+ if iswinsync: >+ self.setup_winsync_agmt(entry, **kargs) > > a.add_s(entry) > >@@ -278,9 +306,11 @@ class ReplicationManager: > done, haserror = self.check_repl_init(conn, agmtdn) > return haserror > >- def start_replication(self, other_conn): >+ def start_replication(self, other_conn, conn=None): > print "Starting replication, please wait until this has completed." >- cn, dn = self.agreement_dn(self.conn) >+ if conn == None: >+ conn = self.conn >+ cn, dn = self.agreement_dn(conn) > > mod = [(ldap.MOD_ADD, 'nsds5BeginReplicaRefresh', 'start')] > other_conn.modify_s(dn, mod) >@@ -292,24 +322,40 @@ class ReplicationManager: > self.local_replica_config(conn, replica_id) > self.setup_changelog(conn) > >- def setup_replication(self, other_hostname, realm_name): >+ def setup_replication(self, other_hostname, realm_name, **kargs): > """ > NOTES: > - the directory manager password needs to be the same on >- both directories. >+ both directories. Or use the optional binddn and bindpw > """ >- other_conn = ipaldap.IPAdmin(other_hostname, port=PORT, cacert=CACERT) >- other_conn.do_simple_bind(bindpw=self.dirman_passwd) >+ iswinsync = kargs.get("winsync", False) >+ oth_port = kargs.get("port", PORT) >+ oth_cacert = kargs.get("cacert", CACERT) >+ oth_binddn = kargs.get("binddn", DIRMAN_CN) >+ oth_bindpw = kargs.get("bindpw", self.dirman_passwd) >+ # note - there appears to be a bug in python-ldap - it does not >+ # allow connections using two different CA certs >+ other_conn = ipaldap.IPAdmin(other_hostname, port=oth_port, cacert=oth_cacert) >+ try: >+ other_conn.do_simple_bind(binddn=oth_binddn, bindpw=oth_bindpw) >+ except Exception, e: >+ if iswinsync: >+ logging.info("Could not validate connection to remote server %s:%d - continuing" % >+ (other_hostname, oth_port)) >+ else: >+ raise e > > self.suffix = ipaldap.IPAdmin.normalizeDN(dsinstance.realm_to_suffix(realm_name)) > > self.basic_replication_setup(self.conn, 1) >- self.basic_replication_setup(other_conn, 2) >- >- self.setup_agreement(other_conn, self.conn) >- self.setup_agreement(self.conn, other_conn) > >- return self.start_replication(other_conn) >+ if not iswinsync: >+ self.basic_replication_setup(other_conn, 2) >+ self.setup_agreement(other_conn, self.conn) >+ return self.start_replication(other_conn) >+ else: >+ self.setup_agreement(self.conn, other_conn, **kargs) >+ return self.start_replication(self.conn, other_conn) > > def initialize_replication(self, dn, conn): > mod = [(ldap.MOD_ADD, 'nsds5BeginReplicaRefresh', 'start')] >-- >1.5.5.1 >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 459729
:
314729
|
314730
|
314731
|
314732
|
314733
|
314844
|
314845
| 316460 |
317002
|
317807
|
318214
|
319412
|
319413
|
319414
|
319415
|
319416
|
319786
|
320039
|
320040