Blob Blame History Raw
From 11e597217fe6f1dcee3a918eef0bc3a0d2928e6d Mon Sep 17 00:00:00 2001
From: Christian Heimes <cheimes@redhat.com>
Date: Thu, 26 Apr 2018 12:06:36 +0200
Subject: [PATCH] Use single Custodia instance in installers

Installers now pass a single CustodiaInstance object around, instead of
creating new instances on demand. In case of replica promotion with CA,
the instance gets all secrets from a master with CA present. Before, an
installer created multiple instances and may have requested CA key
material from a different machine than DM password hash.

In case of Domain Level 1 and replica promotion, the CustodiaInstance no
longer adds the keys to the local instance and waits for replication to
other replica. Instead the installer directly uploads the new public
keys to the remote 389-DS instance.

Without promotion, new Custodia public keys are still added to local
389-DS over LDAPI.

Fixes: https://pagure.io/freeipa/issue/7518
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Simo Sorce <ssorce@redhat.com>
Reviewed-By: Simo Sorce <ssorce@redhat.com>
---
 install/tools/ipa-ca-install               |  13 ++-
 ipaserver/install/ca.py                    |  26 +++--
 ipaserver/install/cainstance.py            |   9 +-
 ipaserver/install/custodiainstance.py      | 150 ++++++++++++++++++++++-------
 ipaserver/install/ipa_kra_install.py       |  10 +-
 ipaserver/install/kra.py                   |   6 +-
 ipaserver/install/server/install.py        |  14 +--
 ipaserver/install/server/replicainstall.py |  15 +--
 8 files changed, 165 insertions(+), 78 deletions(-)

diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install
index f84b4749a3e2a80aca002a2aa057b200e6187f18..a3694007e5815d1c44f642057c749879d336dfc5 100755
--- a/install/tools/ipa-ca-install
+++ b/install/tools/ipa-ca-install
@@ -31,6 +31,7 @@ from ipaserver.install.installutils import create_replica_config
 from ipaserver.install.installutils import check_creds, ReplicaConfig
 from ipaserver.install import dsinstance, ca
 from ipaserver.install import cainstance, service
+from ipaserver.install import custodiainstance
 from ipapython import version
 from ipalib import api
 from ipalib.constants import DOMAIN_LEVEL_0
@@ -193,13 +194,17 @@ def install_replica(safe_options, options, filename):
     options.domain_name = config.domain_name
     options.dm_password = config.dirman_password
     options.host_name = config.host_name
+    options.ca_host_name = config.ca_host_name
     if os.path.exists(cafile):
         options.ca_cert_file = cafile
     else:
         options.ca_cert_file = None
 
     ca.install_check(True, config, options)
-    ca.install(True, config, options)
+
+    custodia = custodiainstance.get_custodia_instance(
+        options, custodiainstance.CustodiaModes.CA_PEER)
+    ca.install(True, config, options, custodia=custodia)
 
 
 def install_master(safe_options, options):
@@ -228,7 +233,11 @@ def install_master(safe_options, options):
         sys.exit("CA subject: {}".format(e.message))
 
     ca.install_check(True, None, options)
-    ca.install(True, None, options)
+
+    # No CA peer available yet.
+    custodia = custodiainstance.get_custodia_instance(
+        options, custodiainstance.CustodiaModes.STANDALONE)
+    ca.install(True, None, options, custodia=custodia)
 
 
 def install(safe_options, options, filename):
diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py
index 52cb20f1cb3612394544a6a41f10e9e939bc0657..2ac4382ccd24d217832950b94baddd113f7a8930 100644
--- a/ipaserver/install/ca.py
+++ b/ipaserver/install/ca.py
@@ -19,10 +19,7 @@ from ipalib.install.service import enroll_only, master_install_only, replica_ins
 from ipaserver.install import sysupgrade
 from ipapython.install import typing
 from ipapython.install.core import group, knob, extend_knob
-from ipaserver.install import (cainstance,
-                               custodiainstance,
-                               dsinstance,
-                               bindinstance)
+from ipaserver.install import cainstance, bindinstance, dsinstance
 from ipapython import ipautil, certdb
 from ipapython.admintool import ScriptError
 from ipaplatform import services
@@ -201,12 +198,12 @@ def install_check(standalone, replica_config, options):
                         "cannot continue." % (subject, db.secdir))
 
 
-def install(standalone, replica_config, options):
-    install_step_0(standalone, replica_config, options)
-    install_step_1(standalone, replica_config, options)
+def install(standalone, replica_config, options, custodia):
+    install_step_0(standalone, replica_config, options, custodia=custodia)
+    install_step_1(standalone, replica_config, options, custodia=custodia)
 
 
-def install_step_0(standalone, replica_config, options):
+def install_step_0(standalone, replica_config, options, custodia):
     realm_name = options.realm_name
     dm_password = options.dm_password
     host_name = options.host_name
@@ -237,9 +234,6 @@ def install_step_0(standalone, replica_config, options):
     else:
         cafile = os.path.join(replica_config.dir, 'cacert.p12')
         if options.promote:
-            custodia = custodiainstance.CustodiaInstance(
-                replica_config.host_name,
-                replica_config.realm_name)
             custodia.get_ca_keys(
                 replica_config.ca_host_name,
                 cafile,
@@ -266,7 +260,9 @@ def install_step_0(standalone, replica_config, options):
         'certmap.conf', 'subject_base', str(subject_base))
     dsinstance.write_certmap_conf(realm_name, ca_subject)
 
-    ca = cainstance.CAInstance(realm_name, host_name=host_name)
+    ca = cainstance.CAInstance(
+        realm=realm_name, host_name=host_name, custodia=custodia
+    )
     ca.configure_instance(host_name, dm_password, dm_password,
                           subject_base=subject_base,
                           ca_subject=ca_subject,
@@ -284,7 +280,7 @@ def install_step_0(standalone, replica_config, options):
                           use_ldaps=standalone)
 
 
-def install_step_1(standalone, replica_config, options):
+def install_step_1(standalone, replica_config, options, custodia):
     if replica_config is not None and not replica_config.setup_ca:
         return
 
@@ -293,7 +289,9 @@ def install_step_1(standalone, replica_config, options):
     subject_base = options._subject_base
     basedn = ipautil.realm_to_suffix(realm_name)
 
-    ca = cainstance.CAInstance(realm_name, host_name=host_name)
+    ca = cainstance.CAInstance(
+        realm=realm_name, host_name=host_name, custodia=custodia
+    )
 
     ca.stop('pki-tomcat')
 
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 20635eae22268ff72de73b8b9c430050114bb45b..eefc30b6e01dcf744703b8607cbe169fbec5d859 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -59,7 +59,6 @@ from ipapython.ipa_log_manager import log_mgr,\
 from ipaserver.secrets.kem import IPAKEMKeys
 
 from ipaserver.install import certs
-from ipaserver.install import custodiainstance
 from ipaserver.install import dsinstance
 from ipaserver.install import installutils
 from ipaserver.install import ldapupdate
@@ -285,7 +284,7 @@ class CAInstance(DogtagInstance):
                      'caSigningCert cert-pki-ca')
     server_cert_name = 'Server-Cert cert-pki-ca'
 
-    def __init__(self, realm=None, host_name=None):
+    def __init__(self, realm=None, host_name=None, custodia=None):
         super(CAInstance, self).__init__(
             realm=realm,
             subsystem="CA",
@@ -310,6 +309,8 @@ class CAInstance(DogtagInstance):
         self.no_db_setup = False
         self.keytab = os.path.join(
             paths.PKI_TOMCAT, self.service_prefix + '.keytab')
+        # Custodia instance for RA key retrieval
+        self._custodia = custodia
 
     def configure_instance(self, host_name, dm_password, admin_password,
                            pkcs12_info=None, master_host=None, csr_file=None,
@@ -711,9 +712,7 @@ class CAInstance(DogtagInstance):
         self.configure_agent_renewal()
 
     def __import_ra_key(self):
-        custodia = custodiainstance.CustodiaInstance(host_name=self.fqdn,
-                                                     realm=self.realm)
-        custodia.import_ra_key(self.master_host)
+        self._custodia.import_ra_key(self.master_host)
         self.__set_ra_cert_perms()
 
         self.configure_agent_renewal()
diff --git a/ipaserver/install/custodiainstance.py b/ipaserver/install/custodiainstance.py
index 0a90bb3954486b9773e3553e9981d2a8d0d4e44a..262ae5857c64719ff5cebde31b4b107e1245d458 100644
--- a/ipaserver/install/custodiainstance.py
+++ b/ipaserver/install/custodiainstance.py
@@ -1,5 +1,9 @@
 # Copyright (C) 2015 FreeIPa Project Contributors, see 'COPYING' for license.
 
+from __future__ import print_function, absolute_import
+
+import enum
+
 from ipaserver.secrets.kem import IPAKEMKeys, KEMLdap
 from ipaserver.secrets.client import CustodiaClient
 from ipaplatform.paths import paths
@@ -21,12 +25,84 @@ import time
 import pwd
 
 
+class CustodiaModes(enum.Enum):
+    # peer must have a CA
+    CA_PEER = 'Custodia CA peer'
+    # peer must have a CA, KRA preferred
+    KRA_PEER = 'Custodia KRA peer'
+    # any master will do
+    MASTER_PEER = 'Custodia master peer'
+    # standalone / local instance
+    STANDALONE = 'Custodia standalone'
+
+
+def get_custodia_instance(config, mode):
+    """Create Custodia instance
+
+    :param config: configuration/installer object
+    :param mode: CustodiaModes member
+    :return: CustodiaInstance object
+
+    The config object must have the following attribute
+
+    *host_name*
+      FQDN of the new replica/master
+    *realm_name*
+      Kerberos realm
+    *promote*
+      True, when instance will be promoted from client to replica
+    *master_host_name* (for *CustodiaModes.MASTER_PEER*)
+      hostname of a master (may not have a CA)
+    *ca_host_name* (for *CustodiaModes.CA_PEER*)
+      hostname of a master with CA
+    *kra_host_name* (for *CustodiaModes.KRA_PEER*)
+      hostname of a master with KRA or CA
+
+    For promotion, the instance will upload new keys and retrieve secrets
+    from the same host. Therefore it uses *ca_host_name* instead of
+    *master_host_name* to create a replica with CA.
+    """
+    assert isinstance(mode, CustodiaModes)
+    root_logger.info(
+        "Custodia client for '%r' with promotion %s.",
+        mode, 'yes' if config.promote else 'no'
+    )
+    if config.promote:
+        if mode == CustodiaModes.CA_PEER:
+            # In case we install replica with CA, prefer CA host as source for
+            # all Custodia secret material.
+            custodia_master = config.ca_host_name
+        elif mode == CustodiaModes.KRA_PEER:
+            custodia_master = config.kra_host_name
+        elif mode == CustodiaModes.MASTER_PEER:
+            custodia_master = config.master_host_name
+        elif mode == CustodiaModes.STANDALONE:
+            custodia_master = None
+    else:
+        custodia_master = None
+
+    if custodia_master is None:
+        # use ldapi with local dirsrv instance
+        root_logger.info("Custodia uses LDAPI.")
+        ldap_uri = None
+    else:
+        root_logger.info("Custodia uses '%s' as master peer.",
+                         custodia_master)
+        ldap_uri = 'ldap://{}'.format(custodia_master)
+
+    return CustodiaInstance(
+        host_name=config.host_name,
+        realm=config.realm_name,
+        ldap_uri=ldap_uri
+    )
+
+
 class CustodiaInstance(SimpleServiceInstance):
-    def __init__(self, host_name=None, realm=None):
+    def __init__(self, host_name=None, realm=None, ldap_uri=None):
         super(CustodiaInstance, self).__init__("ipa-custodia")
         self.config_file = paths.IPA_CUSTODIA_CONF
         self.server_keys = paths.IPA_CUSTODIA_KEYS
-        self.ldap_uri = None
+        self.ldap_uri = ldap_uri
         self.fqdn = host_name
         self.realm = realm
 
@@ -49,14 +125,19 @@ class CustodiaInstance(SimpleServiceInstance):
             ipautil.flush_sync(f)
 
     def create_instance(self):
-        suffix = ipautil.realm_to_suffix(self.realm)
+        if self.ldap_uri is None or self.ldap_uri.startswith('ldapi://'):
+            # local case, ensure container exists
+            self.step("Making sure custodia container exists",
+                      self.__create_container)
+
         self.step("Generating ipa-custodia config file", self.__config_file)
-        self.step("Making sure custodia container exists", self.__create_container)
         self.step("Generating ipa-custodia keys", self.__gen_keys)
-        super(CustodiaInstance, self).create_instance(gensvc_name='KEYS',
-                                                      fqdn=self.fqdn,
-                                                      ldap_suffix=suffix,
-                                                      realm=self.realm)
+        super(CustodiaInstance, self).create_instance(
+            gensvc_name='KEYS',
+            fqdn=self.fqdn,
+            ldap_suffix=ipautil.realm_to_suffix(self.realm),
+            realm=self.realm
+        )
         sysupgrade.set_upgrade_state('custodia', 'installed', True)
 
     def __gen_keys(self):
@@ -81,18 +162,6 @@ class CustodiaInstance(SimpleServiceInstance):
             root_logger.info("Secure server.keys mode")
             os.chmod(self.server_keys, 0o600)
 
-    def create_replica(self, master_host_name):
-        suffix = ipautil.realm_to_suffix(self.realm)
-        self.ldap_uri = 'ldap://%s' % master_host_name
-        self.master_host_name = master_host_name
-
-        self.step("Generating ipa-custodia config file", self.__config_file)
-        self.step("Generating ipa-custodia keys", self.__gen_keys)
-        super(CustodiaInstance, self).create_instance(gensvc_name='KEYS',
-                                                      fqdn=self.fqdn,
-                                                      ldap_suffix=suffix,
-                                                      realm=self.realm)
-
     def __create_container(self):
         """
         Runs the custodia update file to ensure custodia container is present.
@@ -106,7 +175,7 @@ class CustodiaInstance(SimpleServiceInstance):
         updater.update([os.path.join(paths.UPDATES_DIR, '73-custodia.update')])
 
     def import_ra_key(self, master_host_name):
-        cli = self.__CustodiaClient(server=master_host_name)
+        cli = self._get_custodia_client(server=master_host_name)
         # please note that ipaCert part has to stay here for historical
         # reasons (old servers expect you to ask for ra/ipaCert during
         # replication as they store the RA agent cert in an NSS database
@@ -114,14 +183,14 @@ class CustodiaInstance(SimpleServiceInstance):
         cli.fetch_key('ra/ipaCert')
 
     def import_dm_password(self, master_host_name):
-        cli = self.__CustodiaClient(server=master_host_name)
+        cli = self._get_custodia_client(server=master_host_name)
         cli.fetch_key('dm/DMHash')
 
-    def __wait_keys(self, host, timeout=300):
+    def _wait_keys(self, host, timeout=300):
         ldap_uri = 'ldap://%s' % host
         deadline = int(time.time()) + timeout
-        root_logger.info("Waiting up to {} seconds to see our keys "
-                         "appear on host: {}".format(timeout, host))
+        root_logger.info("Waiting up to %s seconds to see our keys "
+                         "appear on host: %s", timeout, host)
 
         konn = KEMLdap(ldap_uri)
         saved_e = None
@@ -129,6 +198,12 @@ class CustodiaInstance(SimpleServiceInstance):
             try:
                 return konn.check_host_keys(self.fqdn)
             except Exception as e:
+                # Print message to console only once for first error.
+                if saved_e is None:
+                    # FIXME: Change once there's better way to show this
+                    # message in installer output,
+                    print("  Waiting for keys to appear on host: {}, please "
+                          "wait until this has completed.".format(host))
                 # log only once for the same error
                 if not isinstance(e, type(saved_e)):
                     root_logger.debug(
@@ -138,22 +213,23 @@ class CustodiaInstance(SimpleServiceInstance):
                     raise RuntimeError("Timed out trying to obtain keys.")
                 time.sleep(1)
 
-    def __CustodiaClient(self, server):
+    def _get_custodia_client(self, server):
         # Before we attempt to fetch keys from this host, make sure our public
         # keys have been replicated there.
-        self.__wait_keys(server)
-
-        return CustodiaClient('host@%s' % self.fqdn, self.server_keys,
-                              paths.KRB5_KEYTAB, server, realm=self.realm)
+        self._wait_keys(server)
 
-    def __get_keys(self, ca_host, cacerts_file, cacerts_pwd, data):
-        # Fecth all needed certs one by one, then combine them in a single
-        # p12 file
+        return CustodiaClient(
+            client_service='host@{}'.format(self.fqdn),
+            keyfile=self.server_keys, keytab=paths.KRB5_KEYTAB,
+            server=server, realm=self.realm
+        )
 
+    def _get_keys(self, ca_host, cacerts_file, cacerts_pwd, data):
+        # Fetch all needed certs one by one, then combine them in a single
+        # PKCS12 file
         prefix = data['prefix']
         certlist = data['list']
-
-        cli = self.__CustodiaClient(server=ca_host)
+        cli = self._get_custodia_client(server=ca_host)
 
         # Temporary nssdb
         tmpnssdir = tempfile.mkdtemp(dir=paths.TMP)
@@ -203,7 +279,7 @@ class CustodiaInstance(SimpleServiceInstance):
                     'subsystemCert cert-pki-ca']
         data = {'prefix': 'ca',
                 'list': certlist}
-        self.__get_keys(ca_host, cacerts_file, cacerts_pwd, data)
+        self._get_keys(ca_host, cacerts_file, cacerts_pwd, data)
 
     def get_kra_keys(self, ca_host, cacerts_file, cacerts_pwd):
         certlist = ['auditSigningCert cert-pki-kra',
@@ -212,7 +288,7 @@ class CustodiaInstance(SimpleServiceInstance):
                     'transportCert cert-pki-kra']
         data = {'prefix': 'ca',
                 'list': certlist}
-        self.__get_keys(ca_host, cacerts_file, cacerts_pwd, data)
+        self._get_keys(ca_host, cacerts_file, cacerts_pwd, data)
 
     def __start(self):
         super(CustodiaInstance, self).__start()
diff --git a/ipaserver/install/ipa_kra_install.py b/ipaserver/install/ipa_kra_install.py
index 3e08f4da94651b49876e1427daddbd957f0027ae..9ebabe057513141ee76d238a3f20e76a27dd932e 100644
--- a/ipaserver/install/ipa_kra_install.py
+++ b/ipaserver/install/ipa_kra_install.py
@@ -32,6 +32,7 @@ from ipapython import admintool
 from ipapython import ipautil
 from ipaserver.install import service
 from ipaserver.install import cainstance
+from ipaserver.install import custodiainstance
 from ipaserver.install import krainstance
 from ipaserver.install import dsinstance
 from ipaserver.install import installutils
@@ -176,7 +177,6 @@ class KRAInstaller(KRAInstall):
 
         api.Backend.ldap2.connect()
 
-        config = None
         if self.installing_replica:
             if self.options.promote:
                 config = ReplicaConfig()
@@ -196,6 +196,7 @@ class KRAInstaller(KRAInstall):
                 config.kra_host_name = config.master_host_name
 
             config.setup_kra = True
+            config.promote = self.options.promote
 
             if config.subject_base is None:
                 attrs = api.Backend.ldap2.get_ipa_config()
@@ -204,6 +205,11 @@ class KRAInstaller(KRAInstall):
             if config.kra_host_name is None:
                 config.kra_host_name = service.find_providing_server(
                     'KRA', api.Backend.ldap2, api.env.ca_host)
+            custodia = custodiainstance.get_custodia_instance(
+                config, custodiainstance.CustodiaModes.KRA_PEER)
+        else:
+            config = None
+            custodia = None
 
         try:
             kra.install_check(api, config, self.options)
@@ -213,7 +219,7 @@ class KRAInstaller(KRAInstall):
         print(dedent(self.INSTALLER_START_MESSAGE))
 
         try:
-            kra.install(api, config, self.options)
+            kra.install(api, config, self.options, custodia=custodia)
         except:
             self.log.error(dedent(self.FAIL_MESSAGE))
             raise
diff --git a/ipaserver/install/kra.py b/ipaserver/install/kra.py
index 3545b301a977f4b7e7801ca1ef87d594bb3ba54f..3333970e8af9e36d6b7614286cc1e774f6eb9b25 100644
--- a/ipaserver/install/kra.py
+++ b/ipaserver/install/kra.py
@@ -16,7 +16,6 @@ from ipaplatform.paths import paths
 from ipapython import certdb
 from ipapython import ipautil
 from ipapython.install.core import group
-from ipaserver.install import custodiainstance
 from ipaserver.install import cainstance
 from ipaserver.install import krainstance
 from ipaserver.install import dsinstance
@@ -68,7 +67,7 @@ def install_check(api, replica_config, options):
                                    "new replica file.")
 
 
-def install(api, replica_config, options):
+def install(api, replica_config, options, custodia):
     if replica_config is None:
         if not options.setup_kra:
             return
@@ -91,9 +90,6 @@ def install(api, replica_config, options):
                     'host/{env.host}@{env.realm}'.format(env=api.env),
                     paths.KRB5_KEYTAB,
                     ccache)
-                custodia = custodiainstance.CustodiaInstance(
-                    replica_config.host_name,
-                    replica_config.realm_name)
                 custodia.get_kra_keys(
                     replica_config.kra_host_name,
                     krafile,
diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py
index 422474fa915b4876530f304ef9424f6b31cf26cc..f4338ed0428f7f44decd004f6a183258bef7f795 100644
--- a/ipaserver/install/server/install.py
+++ b/ipaserver/install/server/install.py
@@ -709,6 +709,7 @@ def install(installer):
     host_name = options.host_name
     ip_addresses = options.ip_addresses
     setup_ca = options.setup_ca
+    options.promote = False  # first master, no promotion
 
     # Installation has started. No IPA sysrestore items are restored in case of
     # failure to enable root cause investigation
@@ -789,6 +790,10 @@ def install(installer):
                       setup_pkinit=not options.no_pkinit,
                       subject_base=options.subject_base)
 
+    custodia = custodiainstance.get_custodia_instance(
+        options, custodiainstance.CustodiaModes.MASTER_PEER)
+    custodia.create_instance()
+
     if setup_ca:
         if not options.external_cert_files and options.external_ca:
             # stage 1 of external CA installation
@@ -803,7 +808,7 @@ def install(installer):
                           if n in options.__dict__}
             write_cache(cache_vars)
 
-        ca.install_step_0(False, None, options)
+        ca.install_step_0(False, None, options, custodia=custodia)
     else:
         # Put the CA cert where other instances expect it
         x509.write_certificate(http_ca_cert, paths.IPA_CA_CRT)
@@ -823,15 +828,12 @@ def install(installer):
     ds.enable_ssl()
 
     if setup_ca:
-        ca.install_step_1(False, None, options)
+        ca.install_step_1(False, None, options, custodia=custodia)
 
     otpd = otpdinstance.OtpdInstance()
     otpd.create_instance('OTPD', host_name,
                          ipautil.realm_to_suffix(realm_name))
 
-    custodia = custodiainstance.CustodiaInstance(host_name, realm_name)
-    custodia.create_instance()
-
     # Create a HTTP instance
     http = httpinstance.HTTPInstance(fstore)
     if options.http_cert_files:
@@ -863,7 +865,7 @@ def install(installer):
     krb.restart()
 
     if options.setup_kra:
-        kra.install(api, None, options)
+        kra.install(api, None, options, custodia=custodia)
 
     if options.setup_dns:
         dns.install(False, False, options)
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
index 42e4615ad2dc1f604f5d8d14f8e57e3e4674bcb9..2ecc0abe0c5918cf5aefccc1bd6f09e70503baab 100644
--- a/ipaserver/install/server/replicainstall.py
+++ b/ipaserver/install/server/replicainstall.py
@@ -1357,6 +1357,7 @@ def install(installer):
     fstore = installer._fstore
     sstore = installer._sstore
     config = installer._config
+    config.promote = installer.promote
     promote = installer.promote
     cafile = installer._ca_file
     dirsrv_pkcs12_info = installer._dirsrv_pkcs12_info
@@ -1483,19 +1484,19 @@ def install(installer):
     otpd.create_instance('OTPD', config.host_name,
                          ipautil.realm_to_suffix(config.realm_name))
 
-    custodia = custodiainstance.CustodiaInstance(config.host_name,
-                                                 config.realm_name)
-    if promote:
-        custodia.create_replica(config.master_host_name)
+    if ca_enabled:
+        mode = custodiainstance.CustodiaModes.CA_PEER
     else:
-        custodia.create_instance()
+        mode = custodiainstance.CustodiaModes.MASTER_PEER
+    custodia = custodiainstance.get_custodia_instance(config, mode)
+    custodia.create_instance()
 
     if ca_enabled:
         options.realm_name = config.realm_name
         options.domain_name = config.domain_name
         options.host_name = config.host_name
         options.dm_password = config.dirman_password
-        ca.install(False, config, options)
+        ca.install(False, config, options, custodia=custodia)
 
     # configure PKINIT now that all required services are in place
     krb.enable_ssl()
@@ -1505,7 +1506,7 @@ def install(installer):
     ds.apply_updates()
 
     if kra_enabled:
-        kra.install(api, config, options)
+        kra.install(api, config, options, custodia=custodia)
 
     service.print_msg("Restarting the KDC")
     krb.restart()
-- 
2.14.3