Discussed with Ludwig, but it might be interesting to the rest of the team(and mainly Simo)

In FreeIPA 4.3 - management of CA agmts by a replication plugin, there is a scenario as follows:


- existing couple of replicas of version 4.2 and earlier (no topology management)
- upgrade all to future 4.3
- raise domain level to 1
- optionally add a replica

All agmts are now managed by a topology plugin but there is an issue with the old CA agreements because they were created with bind method: simple. Atm. no code in IPA framework is executed after raising a domain level. Therefore the old CA agreements are not converted to use GSSAPI.

If the segments related to the old agreements are removed and then re-added, topology plugin creates agreements which use GSSAPI.

The old agreements are not converted automatically by a topology plugin because simple auth is still required for ipa-replica-install (for both realm and o=ipaca suffix).

Nor they can't be converted in IPA upgrade because domain level is raised after the upgrade.

Question is who should convert the old amgts after raising a domain level. IPA or topology plugin?

Some of possible solutions are:

1. Convert the CA agmts in domailevel-set method
2. Change replica installer to setup Kerberos earlier so that new agreements could use GSSAPI and therefore topology plugin can convert all managed agreements which don't use GSSAPI automatically. 3. Automatically convert all agmts by topo plugin. Introduce an attr in repl agmnt which would be set during replica installation to tell the topo plugin to not covert the agmnt while the attr is set. Then convert in installer or when the attr is removed.

#1 is an easy workaround but it creates yet another "sort of upgrade path" in domain level set.
#2 is more or less a replica promotion.
#3 another workaround

From long term perspective, I like #2 but I don't know what's the state of replica promotion. Simo?

Attaching IPA patches which I use now (doesn't contain required topo plugin patches).
--
Petr Vobornik
>From 5a1f8ad3b8948d858729b8562e2c01eef161272e Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Wed, 15 Jul 2015 11:17:14 +0200
Subject: [PATCH 1/2] topology: manage ca replication agreements

Configure IPA so that topology plugin will manage also CA replication
agreements.
If domain level > 0, ipa-replica-install:
- ipa replica install prepares DB for PKI
- setups replications agreements (o=ipaca) with simple bind method
- re-initializes the suffix
- calls pkispawn
- changes agreements to use GSSAPI

upgrades if CA is congigured:
- ipaca suffix is added to cn=topology,cn=ipa,cn=etc,$SUFFIX
- ipaReplTopoManagedSuffix: o=ipaca is added to master entry
- binddngroup is added to o=ipaca replica entry
---
 freeipa.spec.in                                 |  4 +-
 install/share/Makefile.am                       |  1 +
 install/share/ca-topology.uldif                 | 15 +++++
 install/updates/20-replication.update           |  5 ++
 install/updates/90-post_upgrade_plugins.update  |  1 +
 ipaplatform/base/paths.py                       |  1 +
 ipaserver/install/cainstance.py                 | 80 ++++++++++++++++++++++++-
 ipaserver/install/installutils.py               |  1 +
 ipaserver/install/krbinstance.py                | 19 ++++--
 ipaserver/install/plugins/update_ca_topology.py | 34 +++++++++++
 ipaserver/install/replication.py                | 68 ++++++++++++---------
 ipaserver/install/server/replicainstall.py      |  4 +-
 12 files changed, 195 insertions(+), 38 deletions(-)
 create mode 100644 install/share/ca-topology.uldif
 create mode 100644 ipaserver/install/plugins/update_ca_topology.py

diff --git a/freeipa.spec.in b/freeipa.spec.in
index 328894c551acde88fbf789537fd9c9a5a39da816..b1da0a66ff51e5b9a1a3bbf3e1504e4fdbaacdd9 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -143,8 +143,8 @@ Requires(post): systemd-units
 Requires: selinux-policy >= %{selinux_policy_version}
 Requires(post): selinux-policy-base
 Requires: slapi-nis >= 0.54.2-1
-Requires: pki-ca >= 10.2.6
-Requires: pki-kra >= 10.2.6
+Requires: pki-ca >= 10.2.7
+Requires: pki-kra >= 10.2.7
 Requires(preun): python systemd-units
 Requires(postun): python systemd-units
 Requires: python-dns >= 1.11.1
diff --git a/install/share/Makefile.am b/install/share/Makefile.am
index 80e959a751a0800c4d56c379a73b68a2f12570d7..156ee3f528a10a3615b0cc48a8fccad36e143da3 100644
--- a/install/share/Makefile.am
+++ b/install/share/Makefile.am
@@ -27,6 +27,7 @@ app_DATA =				\
 	72domainlevels.ldif			\
 	anonymous-vlv.ldif		\
 	bootstrap-template.ldif		\
+	ca-topology.uldif		\
 	caJarSigningCert.cfg.template	\
 	default-aci.ldif		\
 	default-caacl.ldif		\
diff --git a/install/share/ca-topology.uldif b/install/share/ca-topology.uldif
new file mode 100644
index 0000000000000000000000000000000000000000..3da9eaee1478ba0849a164fd2a150772c0151dd8
--- /dev/null
+++ b/install/share/ca-topology.uldif
@@ -0,0 +1,15 @@
+# add IPA CA managed suffix to master entry
+dn: cn=$FQDN,cn=masters,cn=ipa,cn=etc,$SUFFIX
+add: objectclass: ipaReplTopoManagedServer
+add: ipaReplTopoManagedSuffix: o=ipaca
+
+# add IPA CA topology configuration area
+dn: cn=ipaca,cn=topology,cn=ipa,cn=etc,$SUFFIX
+default: objectclass: top
+default: objectclass: iparepltopoconf
+default: ipaReplTopoConfRoot: o=ipaca
+default: cn: ipaca
+
+# Update CA replication settings
+dn: cn=replica,cn=o\3Dipaca,cn=mapping tree,cn=config
+onlyifexist: nsds5replicabinddngroup: cn=replication managers,cn=sysaccounts,cn=etc,$SUFFIX
diff --git a/install/updates/20-replication.update b/install/updates/20-replication.update
index 066b9fcd4933864cdcbc451897c98063bdf55bbe..b4908c2a9a38cdef4729098a1e28c5ca4affc1ac 100644
--- a/install/updates/20-replication.update
+++ b/install/updates/20-replication.update
@@ -27,3 +27,8 @@ default: objectclass: top
 default: objectclass: iparepltopoconf
 default: ipaReplTopoConfRoot: $SUFFIX
 default: cn: realm
+
+# add IPA realm managed suffix to master entry
+dn: cn=$FQDN,cn=masters,cn=ipa,cn=etc,$SUFFIX
+add: objectclass: ipaReplTopoManagedServer
+add: ipaReplTopoManagedSuffix: $SUFFIX
\ No newline at end of file
diff --git a/install/updates/90-post_upgrade_plugins.update b/install/updates/90-post_upgrade_plugins.update
index 3df3a4574705dbd8df8f25149c13877898afb66b..2089b332032dfd3eb930a2e1f01e38c5ed578fe4 100644
--- a/install/updates/90-post_upgrade_plugins.update
+++ b/install/updates/90-post_upgrade_plugins.update
@@ -2,6 +2,7 @@
 
 
 # middle
+plugin: update_ca_topology
 plugin: update_dnszones
 plugin: update_dns_limits
 plugin: update_default_range
diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
index 4c93c1f7162b0aeb4f798ef84e1ac8db4573518b..e9c1c4b2caeb8f034de9952a9d72b65a610557f3 100644
--- a/ipaplatform/base/paths.py
+++ b/ipaplatform/base/paths.py
@@ -236,6 +236,7 @@ class BasePathNamespace(object):
     SMBD = "/usr/sbin/smbd"
     USERADD = "/usr/sbin/useradd"
     USR_SHARE_IPA_DIR = "/usr/share/ipa/"
+    CA_TOPOLOGY_ULDIF = "/usr/share/ipa/ca-topology.uldif"
     FFEXTENSION = "/usr/share/ipa/ffextension"
     IPA_HTML_DIR = "/usr/share/ipa/html"
     CA_CRT = "/usr/share/ipa/html/ca.crt"
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 5fd3017e16e0d7ed4b4f8eead0e59266fdaff097..7e384a7236b01dc49e5e4754930ec501608dc37d 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -61,6 +61,8 @@ from ipapython.ipa_log_manager import log_mgr,\
 from ipaserver.install import certs
 from ipaserver.install import dsinstance
 from ipaserver.install import installutils
+from ipaserver.install import ldapupdate
+from ipaserver.install import replication
 from ipaserver.install import service
 from ipaserver.install.dogtaginstance import DogtagInstance
 from ipaserver.install.dogtaginstance import PKI_USER, DEFAULT_DSPORT
@@ -391,7 +393,7 @@ class CAInstance(DogtagInstance):
                            cert_file=None, cert_chain_file=None,
                            master_replication_port=None,
                            subject_base=None, ca_signing_algorithm=None,
-                           ca_type=None):
+                           ca_type=None, domain_level=0):
         """Create a CA instance.
 
            For Dogtag 9, this may involve creating the pki-ca instance.
@@ -405,6 +407,7 @@ class CAInstance(DogtagInstance):
         """
         self.fqdn = host_name
         self.domain = domain
+        self.domain_level = domain_level
         self.dm_password = dm_password
         self.admin_password = admin_password
         self.ds_port = ds_port
@@ -437,8 +440,15 @@ class CAInstance(DogtagInstance):
             self.external = 2
 
         self.step("creating certificate server user", create_ca_user)
+
         if self.dogtag_constants.DOGTAG_VERSION >= 10:
+            if self.domain_level > 0 and self.clone:
+                self.step("creating certificate server db", self.__create_ds_db)
+                self.step("setting up initial replication", self.__setup_replication)
+                self.step("updating topology configuration", self.__update_topology)
             self.step("configuring certificate server instance", self.__spawn_instance)
+            if self.domain_level > 0 and not self.clone:
+                self.step("updating topology configuration", self.__update_topology)
         else:
             if not ipautil.dir_exists(paths.VAR_LIB_PKI_CA_DIR):
                 self.step("creating pki-ca instance", self.create_instance)
@@ -497,6 +507,10 @@ class CAInstance(DogtagInstance):
         config.optionxform = str
         config.add_section("CA")
 
+        # config.set("CA", "pki_clone_replication_security", "LDAP")
+        # config.set("CA", "pki_clone_replication_bind_group", str(self.replication_bind_group))
+        # config.set("CA", "pki_clone_replication_bind_method", "SASL/GSSAPI")
+
         # Server
         config.set("CA", "pki_security_domain_name", self.security_domain_name)
         config.set("CA", "pki_enable_proxy", "True")
@@ -550,6 +564,10 @@ class CAInstance(DogtagInstance):
         config.set("CA", "pki_ca_signing_key_algorithm", self.ca_signing_algorithm)
 
         if self.clone:
+            if self.domain_level > 0:
+                config.set("CA", "pki_ds_create_new_db", "False")
+                config.set("CA", "pki_clone_setup_replication", "False")
+
             cafile = self.pkcs12_info[0]
             shutil.copy(cafile, paths.TMP_CA_P12)
             pent = pwd.getpwnam(PKI_USER)
@@ -773,6 +791,63 @@ class CAInstance(DogtagInstance):
         except Exception, e:
             root_logger.warning("Failed to backup CS.cfg: %s", e)
 
+    def __update_topology(self):
+        ld = ldapupdate.LDAPUpdate(ldapi=True, sub_dict={
+            'SUFFIX': api.env.basedn,
+            'FQDN': self.fqdn,
+        })
+        rv = ld.update([paths.CA_TOPOLOGY_ULDIF])
+        if not rv:
+            raise RuntimeError("Failed to update CA topology configuration")
+
+    def __create_ds_db(self):
+        '''
+        Create PKI database. Is needed when pkispawn option
+        pki_ds_create_new_db is set to False
+        '''
+
+        conn = ipaldap.IPAdmin(self.fqdn, self.ds_port)
+        conn.do_simple_bind(DN(('cn', 'Directory Manager')), self.dm_password)
+
+        backend = 'ipaca'
+        suffix = DN(('o', 'ipaca'))
+
+        # replication
+        dn = DN(('cn', str(suffix)), ('cn', 'mapping tree'), ('cn', 'config'))
+        entry = conn.make_entry(
+            dn,
+            objectclass=["top", "extensibleObject", "nsMappingTree"],
+            cn=[suffix],
+        )
+        entry['nsslapd-state'] = ['Backend']
+        entry['nsslapd-backend'] = [backend]
+        conn.add_entry(entry)
+
+        # database
+        dn = DN(('cn', 'ipaca'), ('cn', 'ldbm database'), ('cn', 'plugins'),
+                ('cn', 'config'))
+        entry = conn.make_entry(
+            dn,
+            objectclass=["top", "extensibleObject", "nsBackendInstance"],
+            cn=[backend],
+        )
+        entry['nsslapd-suffix'] = [suffix]
+        conn.add_entry(entry)
+
+    def __setup_replication(self):
+
+        master = replication.get_cs_replication_manager(
+            self.realm, self.master_host, self.dm_password,
+            domain_level=self.domain_level)
+        clone = replication.CSReplicationManager(
+            self.realm, self.fqdn, self.dm_password,
+            dogtag.Dogtag10Constants.DS_PORT, domain_level=self.domain_level)
+
+        clone.setup_replication(
+            self.master_host, master.port, 0, DN(('cn', 'Directory Manager')),
+            self.dm_password, is_cs_replica=True, local_port=clone.port)
+
+
     def __disable_nonce(self):
         # Turn off Nonces
         update_result = installutils.update_file(
@@ -1523,7 +1598,8 @@ def install_replica_ca(config, postinstall=False):
                           pkcs12_info=(cafile,),
                           master_host=config.master_host_name,
                           master_replication_port=config.ca_ds_port,
-                          subject_base=config.subject_base)
+                          subject_base=config.subject_base,
+                          domain_level=config.domain_level)
 
     # Restart httpd since we changed it's config and added ipa-pki-proxy.conf
     # Without the restart, CA service status check would fail due to missing
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index 02e8526317dbab909ed48a1823000922ce6e6b7a..a8d738c0152901f9d5a6172cd0259f0825cab814 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -105,6 +105,7 @@ class ReplicaConfig:
         self.setup_ca = False
         self.version = 0
         self.top_dir = top_dir
+        self.domain_level = 0
 
     subject_base = ipautil.dn_attribute_property('_subject_base')
 
diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
index 648fc76018f8342e787e74863e62dd85164af247..874c3f5ccdd6443b53956b6259540b531d89a936 100644
--- a/ipaserver/install/krbinstance.py
+++ b/ipaserver/install/krbinstance.py
@@ -193,10 +193,11 @@ class KrbInstance(service.Service):
                        master_fqdn, host_name,
                        domain_name, admin_password,
                        setup_pkinit=False, pkcs12_info=None,
-                       subject_base=None):
+                       subject_base=None, domain_level=0):
         self.pkcs12_info = pkcs12_info
         self.subject_base = subject_base
         self.master_fqdn = master_fqdn
+        self.domain_level = domain_level
 
         self.__common_setup(realm_name, host_name, domain_name, admin_password)
 
@@ -430,12 +431,22 @@ class KrbInstance(service.Service):
         self.admin_conn.update_entry(entry)
 
     def __convert_to_gssapi_replication(self):
+        binddn = DN(('cn', 'Directory Manager'))
         repl = replication.ReplicationManager(self.realm,
                                               self.fqdn,
                                               self.dm_password)
-        repl.convert_to_gssapi_replication(self.master_fqdn,
-                                           r_binddn=DN(('cn', 'Directory Manager')),
-                                           r_bindpw=self.dm_password)
+        repl.convert_to_gssapi_replication(
+            self.master_fqdn, r_binddn=binddn, r_bindpw=self.dm_password)
+
+        if self.domain_level > 0:
+            # Convert CS agreements
+            csrepl = replication.get_cs_replication_manager(
+                self.realm, self.fqdn, self.dm_password,
+                domain_level=self.domain_level)
+            csmasterrepl = replication.get_cs_replication_manager(
+                self.realm, self.master_fqdn, self.dm_password,
+                domain_level=self.domain_level)
+            csrepl.gssapi_update_agreements(csrepl.conn, csmasterrepl.conn)
 
     def uninstall(self):
         if self.is_configured():
diff --git a/ipaserver/install/plugins/update_ca_topology.py b/ipaserver/install/plugins/update_ca_topology.py
new file mode 100644
index 0000000000000000000000000000000000000000..ce4b5bc9aa04f70df32b9184a10728696ff091e3
--- /dev/null
+++ b/ipaserver/install/plugins/update_ca_topology.py
@@ -0,0 +1,34 @@
+#
+# Copyright (C) 2015  FreeIPA Contributors see COPYING for license
+#
+
+from ipalib import api
+from ipalib import Updater
+from ipaserver.install import certs, cainstance
+from ipaserver.install import ldapupdate
+from ipaplatform.paths import paths
+
+
+class update_ca_topology(Updater):
+    """
+    Updates CA topology configuration entries
+    """
+
+    def execute(self, **options):
+
+        ca = cainstance.CAInstance(self.api.env.realm, certs.NSS_DIR)
+        if not ca.is_configured():
+            self.log.debug("CA is not configured on this host")
+            return False, []
+
+        ld = ldapupdate.LDAPUpdate(ldapi=True, sub_dict={
+            'SUFFIX': self.api.env.basedn,
+            'FQDN': self.api.env.host,
+        })
+        rv = ld.update([paths.CA_TOPOLOGY_ULDIF])
+        if not rv:
+            self.log.error("Failed to update CA topology configuration")
+
+        return False, []
+
+api.register(update_ca_topology)
diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py
index 2b36a5eb9287bf1789009a3198e540e333869e98..ad289f1400a927de2fc36e5ff3c765752c60b019 100644
--- a/ipaserver/install/replication.py
+++ b/ipaserver/install/replication.py
@@ -177,7 +177,8 @@ def wait_for_entry(connection, entry, timeout=7200, attr='', quiet=True):
 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, conn=None):
+    def __init__(self, realm, hostname, dirman_passwd, port=PORT,
+                 starttls=False, conn=None, domain_level=None):
         self.hostname = hostname
         self.port = port
         self.dirman_passwd = dirman_passwd
@@ -185,6 +186,8 @@ class ReplicationManager(object):
         self.starttls = starttls
         self.suffix = ipautil.realm_to_suffix(realm)
         self.need_memberof_fixup = False
+        # TODO: get domain level if it's None
+        self.domain_level = domain_level
 
         # The caller is allowed to pass in an existing IPAdmin connection.
         # Open a new one if not provided
@@ -243,7 +246,7 @@ class ReplicationManager(object):
         :param attempts: number of attempts to update nsDS5ReplicaId
         :return: value of nsDS5ReplicaId before incrementation
         """
-        dn = DN(('cn','replication'),('cn','etc'), self.suffix)
+        dn = DN(('cn', 'replication'), ('cn', 'etc'), api.env.basedn)
 
         for a in range(1, attempts + 1):
             try:
@@ -418,7 +421,7 @@ class ReplicationManager(object):
         assert isinstance(dn, DN)
         replica_groupdn = DN(
             ('cn', 'replication managers'), ('cn', 'sysaccounts'),
-            ('cn', 'etc'), self.suffix)
+            ('cn', 'etc'), api.env.basedn)
 
         try:
             entry = conn.get_entry(dn)
@@ -711,13 +714,13 @@ class ReplicationManager(object):
         while (retries > 0 ):
             root_logger.info('Getting ldap service principals for conversion: %s and %s' % (filter_a, filter_b))
             try:
-                a_entry = b.get_entries(self.suffix, ldap.SCOPE_SUBTREE,
+                a_entry = b.get_entries(api.env.basedn, ldap.SCOPE_SUBTREE,
                                         filter=filter_a)
             except errors.NotFound:
                 pass
 
             try:
-                b_entry = a.get_entries(self.suffix, ldap.SCOPE_SUBTREE,
+                b_entry = a.get_entries(api.env.basedn, ldap.SCOPE_SUBTREE,
                                         filter=filter_b)
             except errors.NotFound:
                 pass
@@ -762,7 +765,7 @@ class ReplicationManager(object):
 
         rep_dn = self.replica_dn()
         group_dn = DN(('cn', 'replication managers'), ('cn', 'sysaccounts'),
-                      ('cn', 'etc'), self.suffix)
+                      ('cn', 'etc'), api.env.basedn)
         assert isinstance(rep_dn, DN)
         (a_dn, b_dn) = self.get_replica_principal_dns(a, b, retries=100)
         assert isinstance(a_dn, DN)
@@ -965,8 +968,8 @@ class ReplicationManager(object):
         self.setup_changelog(conn)
 
     def setup_replication(self, r_hostname, r_port=389, r_sslport=636,
-                          r_binddn=None, r_bindpw=None,
-                          is_cs_replica=False, local_port=None):
+                          r_binddn=None, r_bindpw=None, is_cs_replica=False,
+                          local_port=None):
         assert isinstance(r_binddn, DN)
         if local_port is None:
             local_port = r_port
@@ -1081,11 +1084,7 @@ class ReplicationManager(object):
             raise RuntimeError("Failed to start replication")
 
     def convert_to_gssapi_replication(self, r_hostname, r_binddn, r_bindpw):
-        r_conn = ipaldap.IPAdmin(r_hostname, port=PORT, cacert=CACERT)
-        if r_bindpw:
-            r_conn.do_simple_bind(binddn=r_binddn, bindpw=r_bindpw)
-        else:
-            r_conn.do_sasl_gssapi_bind()
+        r_conn = self.create_conn(r_hostname, r_binddn, r_bindpw)
 
         # First off make sure servers are in sync so that both KDCs
         # have all principals and their passwords and can release
@@ -1103,20 +1102,23 @@ class ReplicationManager(object):
         # change the agreements to use GSSAPI
         self.gssapi_update_agreements(self.conn, r_conn)
 
+    def create_conn(self, hostname, binddn=None, bindpw=None):
+        # note - there appears to be a bug in python-ldap - it does not
+        # allow connections using two different CA certs
+        conn = ipaldap.IPAdmin(hostname, port=PORT, cacert=CACERT)
+        if bindpw:
+            conn.do_simple_bind(binddn=binddn, bindpw=bindpw)
+        else:
+            conn.do_sasl_gssapi_bind()
+        return conn
+
     def setup_gssapi_replication(self, r_hostname, r_binddn=None, r_bindpw=None):
         """
         Directly sets up GSSAPI replication.
         Only usable to connect 2 existing replicas (needs existing kerberos
         principals)
         """
-        # note - there appears to be a bug in python-ldap - it does not
-        # allow connections using two different CA certs
-        r_conn = ipaldap.IPAdmin(r_hostname, port=PORT, cacert=CACERT)
-        if r_bindpw:
-            r_conn.do_simple_bind(binddn=r_binddn, bindpw=r_bindpw)
-        else:
-            r_conn.do_sasl_gssapi_bind()
-
+        r_conn = self.create_conn(r_hostname, r_binddn, r_bindpw)
         # Allow krb principals to act as replicas
         self.setup_krb_princs_as_replica_binddns(self.conn, r_conn)
 
@@ -1611,23 +1613,30 @@ class CSReplicationManager(ReplicationManager):
     an appropriate CSReplicationManager.
     """
 
-    def __init__(self, realm, hostname, dirman_passwd, port):
+    def __init__(self, realm, hostname, dirman_passwd, port, domain_level=None):
         super(CSReplicationManager, self).__init__(
-            realm, hostname, dirman_passwd, port, starttls=True)
+            realm, hostname, dirman_passwd, port, starttls=True,
+            domain_level=domain_level)
         self.suffix = DN(('o', 'ipaca'))
         self.hostnames = [] # set before calling or agreement_dn() will fail
 
     def agreement_dn(self, hostname, master=None):
         """
         Construct a dogtag replication agreement name. This needs to be much
-        more agressive than the IPA replication agreements because the name
-        is different on each side.
+        more agressive than the IPA replication agreements in a topology which
+        is not managed by topology plugin because the name is different on each
+        side.
 
         hostname is the local hostname, not the remote one, for both sides
         NOTE: The agreement number is hardcoded in dogtag as well
-
-        TODO: configurable instance name
         """
+
+        # in managed topology the DN could be arbitrary
+        if self.domain_level > 0:
+            cn = 'caTo%s' % hostname
+            dn = DN(('cn', cn), self.replica_dn())
+            return (cn, dn)
+
         dn = None
         cn = None
         if self.conn.port == 7389:
@@ -1677,7 +1686,8 @@ class CSReplicationManager(ReplicationManager):
         else:
             return True
 
-def get_cs_replication_manager(realm, host, dirman_passwd):
+
+def get_cs_replication_manager(realm, host, dirman_passwd, domain_level=None):
     """Get a CSReplicationManager for a remote host
 
     Detects if the host has a merged database, connects to appropriate port.
@@ -1697,7 +1707,7 @@ def get_cs_replication_manager(realm, host, dirman_passwd):
     for port in ports:
         root_logger.debug('Looking for PKI DS on %s:%s' % (host, port))
         replication_manager = CSReplicationManager(
-            realm, host, dirman_passwd, port)
+            realm, host, dirman_passwd, port, domain_level)
         if replication_manager.has_ipaca():
             root_logger.debug('PKI DS found on %s:%s' % (host, port))
             return replication_manager
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
index 1ad291a1eada080361031a5723a0ea61679fc72e..a577494e6aba0ecc16aea1a5968fd2fe0b6dcc59 100644
--- a/ipaserver/install/server/replicainstall.py
+++ b/ipaserver/install/server/replicainstall.py
@@ -90,7 +90,8 @@ def install_krb(config, setup_pkinit=False):
     krb.create_replica(config.realm_name,
                        config.master_host_name, config.host_name,
                        config.domain_name, config.dirman_password,
-                       setup_pkinit, pkcs12_info)
+                       setup_pkinit, pkcs12_info,
+                       domain_level=config.domain_level)
 
     return krb
 
@@ -428,6 +429,7 @@ def install_check(installer):
             # If we're joining an older master, domain entry is not
             # available
             current = 0
+        config.domain_level = current
 
         # Detect if current level is out of supported range
         # for this IPA version
-- 
2.4.3

>From 988843c6779901141d3917e2ccc1f72c3b130d9b Mon Sep 17 00:00:00 2001
From: Petr Vobornik <pvobo...@redhat.com>
Date: Thu, 23 Jul 2015 14:56:12 +0200
Subject: [PATCH 2/2] topology plugin configuration workaround

---
 daemons/ipa-slapi-plugins/topology/ipa-topology-conf.ldif | 1 +
 1 file changed, 1 insertion(+)

diff --git a/daemons/ipa-slapi-plugins/topology/ipa-topology-conf.ldif b/daemons/ipa-slapi-plugins/topology/ipa-topology-conf.ldif
index a7acb350772a00a8a49365f92e9d219271e65935..4b3c4ce990425de1d0ec28f2451babc2ee13c22a 100755
--- a/daemons/ipa-slapi-plugins/topology/ipa-topology-conf.ldif
+++ b/daemons/ipa-slapi-plugins/topology/ipa-topology-conf.ldif
@@ -10,6 +10,7 @@ nsslapd-pluginType: object
 nsslapd-pluginEnabled: on
 nsslapd-topo-plugin-shared-config-base: cn=ipa,cn=etc,$SUFFIX
 nsslapd-topo-plugin-shared-replica-root: $SUFFIX
+nsslapd-topo-plugin-shared-replica-root: o=ipaca
 nsslapd-topo-plugin-shared-binddngroup: cn=replication managers,cn=sysaccounts,cn=etc,$SUFFIX
 nsslapd-topo-plugin-startup-delay: 20
 nsslapd-pluginId: none
-- 
2.4.3

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to