Allow to setup the CA when promoting a replica

This patch makes --setup-ca work to set upa clone CA while creating
a new replica. The standalone ipa-ca-install script is not converted
yet though.

Signed-off-by: Simo Sorce <simo@redhat.com>
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
Simo Sorce 2015-08-07 15:14:58 -04:00 committed by Jan Cholasta
parent 102651b10a
commit 2606f5aecd
6 changed files with 332 additions and 62 deletions

View File

@ -11,5 +11,10 @@ default: ipaReplTopoConfRoot: o=ipaca
default: cn: ipaca
# Update CA replication settings
dn: cn=o\3Dipaca,cn=mapping tree,cn=config
add: aci: (targetattr=*)(version 3.0;acl "permission:Add Replication Agreements";allow (add) groupdn = "ldap:///cn=Add Replication Agreements,cn=permissions,cn=pbac,$SUFFIX";)
add: aci: (targetattr=*)(targetfilter="(|(objectclass=nsds5Replica)(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement)(objectClass=nsMappingTree))")(version 3.0; acl "permission:Modify Replication Agreements"; allow (read, write, search) groupdn = "ldap:///cn=Modify Replication Agreements,cn=permissions,cn=pbac,$SUFFIX";)
add: aci: (targetattr=*)(targetfilter="(|(objectclass=nsds5replicationagreement)(objectclass=nsDSWindowsReplicationAgreement))")(version 3.0;acl "permission:Remove Replication Agreements";allow (delete) groupdn = "ldap:///cn=Remove Replication Agreements,cn=permissions,cn=pbac,$SUFFIX";)
dn: cn=replica,cn=o\3Dipaca,cn=mapping tree,cn=config
onlyifexist: nsds5replicabinddngroup: cn=replication managers,cn=sysaccounts,cn=etc,$SUFFIX

View File

@ -32,16 +32,21 @@ def install_check(standalone, replica_config, options):
if standalone and api.env.ra_plugin == 'selfsign':
sys.exit('A selfsign CA can not be added')
if not ipautil.file_exists(replica_config.dir + "/cacert.p12"):
if ((not options.promote
and not ipautil.file_exists(replica_config.dir + "/cacert.p12"))):
print('CA cannot be installed in CA-less setup.')
sys.exit(1)
if standalone and not options.skip_conncheck:
principal = options.principal
if principal is None:
principal = "admin"
replica_conn_check(
replica_config.master_host_name, host_name, realm_name, True,
replica_config.ca_ds_port, options.admin_password)
replica_config.ca_ds_port, options.admin_password,
principal=principal)
if options.skip_schema_check:
if options.skip_schema_check or options.promote:
root_logger.info("Skipping CA DS schema check")
else:
cainstance.replica_ca_install_check(replica_config)

View File

@ -64,6 +64,7 @@ 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 (
DEFAULT_DSPORT, PKI_USER, export_kra_agent_pem, DogtagInstance)
@ -99,6 +100,13 @@ ConfigFile = /usr/share/pki/ca/conf/database.ldif
"""
ADMIN_GROUPS = [
'Enterprise CA Administrators',
'Enterprise KRA Administrators',
'Security Domain Administrators'
]
def check_port():
"""
Check that dogtag port (8443) is available.
@ -419,6 +427,7 @@ class CAInstance(DogtagInstance):
self.ra_cert = None
self.requestId = None
self.log = log_mgr.get_logger(self)
self.no_db_setup = False
def configure_instance(self, host_name, dm_password,
admin_password, ds_port=DEFAULT_DSPORT,
@ -440,6 +449,7 @@ class CAInstance(DogtagInstance):
"""
self.fqdn = host_name
self.dm_password = dm_password
self.admin_user = "admin"
self.admin_password = admin_password
self.ds_port = ds_port
self.pkcs12_info = pkcs12_info
@ -546,8 +556,8 @@ class CAInstance(DogtagInstance):
config.set("CA", "pki_client_pkcs12_password", self.admin_password)
# Administrator
config.set("CA", "pki_admin_name", "admin")
config.set("CA", "pki_admin_uid", "admin")
config.set("CA", "pki_admin_name", self.admin_user)
config.set("CA", "pki_admin_uid", self.admin_user)
config.set("CA", "pki_admin_email", "root@localhost")
config.set("CA", "pki_admin_password", self.admin_password)
config.set("CA", "pki_admin_nickname", "ipa-ca-agent")
@ -584,6 +594,12 @@ class CAInstance(DogtagInstance):
config.set("CA", "pki_ca_signing_key_algorithm", self.ca_signing_algorithm)
if self.clone:
if self.no_db_setup:
config.set("CA", "pki_ds_create_new_db", "False")
config.set("CA", "pki_clone_setup_replication", "False")
config.set("CA", "pki_clone_reindex_data", "True")
cafile = self.pkcs12_info[0]
shutil.copy(cafile, paths.TMP_CA_P12)
pent = pwd.getpwnam(PKI_USER)
@ -592,7 +608,7 @@ class CAInstance(DogtagInstance):
# Security domain registration
config.set("CA", "pki_security_domain_hostname", self.master_host)
config.set("CA", "pki_security_domain_https_port", "443")
config.set("CA", "pki_security_domain_user", "admin")
config.set("CA", "pki_security_domain_user", self.admin_user)
config.set("CA", "pki_security_domain_password", self.admin_password)
# Clone
@ -701,7 +717,7 @@ class CAInstance(DogtagInstance):
"-client_certdb_pwd", self.admin_password,
"-preop_pin" , preop_pin,
"-domain_name", self.security_domain_name,
"-admin_user", "admin",
"-admin_user", self.admin_user,
"-admin_email", "root@localhost",
"-admin_password", self.admin_password,
"-agent_name", "ipa-ca-agent",
@ -769,7 +785,7 @@ class CAInstance(DogtagInstance):
args.append("-sd_admin_port")
args.append("443")
args.append("-sd_admin_name")
args.append("admin")
args.append(self.admin_user)
args.append("-sd_admin_password")
args.append(self.admin_password)
args.append("-clone_master_port")
@ -1482,6 +1498,211 @@ class CAInstance(DogtagInstance):
dogtag.configured_constants().CS_CFG_PATH,
dogtag_constants)
def __create_ds_db(self):
'''
Create PKI database. Is needed when pkispawn option
pki_ds_create_new_db is set to False
'''
if not self.admin_conn:
self.ldap_connect()
backend = 'ipaca'
suffix = DN(('o', 'ipaca'))
# replication
dn = DN(('cn', str(suffix)), ('cn', 'mapping tree'), ('cn', 'config'))
entry = self.admin_conn.make_entry(
dn,
objectclass=["top", "extensibleObject", "nsMappingTree"],
cn=[suffix],
)
entry['nsslapd-state'] = ['Backend']
entry['nsslapd-backend'] = [backend]
self.admin_conn.add_entry(entry)
# database
dn = DN(('cn', 'ipaca'), ('cn', 'ldbm database'), ('cn', 'plugins'),
('cn', 'config'))
entry = self.admin_conn.make_entry(
dn,
objectclass=["top", "extensibleObject", "nsBackendInstance"],
cn=[backend],
)
entry['nsslapd-suffix'] = [suffix]
self.admin_conn.add_entry(entry)
def __setup_replication(self):
repl = replication.CAReplicationManager(self.realm, self.fqdn)
repl.setup_cs_replication(self.master_host)
# Activate Topology for o=ipaca segments
self.__update_topology()
def __add_admin_to_group(self, group):
dn = DN(('cn', group), ('ou', 'groups'), ('o', 'ipaca'))
entry = self.admin_conn.get_entry(dn)
members = entry.get('uniqueMember', [])
members.append(self.admin_dn)
mod = [(ldap.MOD_REPLACE, 'uniqueMember', members)]
try:
self.admin_conn.modify_s(dn, mod)
except ldap.TYPE_OR_VALUE_EXISTS:
# already there
pass
def __setup_admin(self):
self.admin_user = "admin-%s" % self.fqdn
self.admin_password = binascii.hexlify(os.urandom(16))
if not self.admin_conn:
self.ldap_connect()
self.admin_dn = DN(('uid', self.admin_user),
('ou', 'people'), ('o', 'ipaca'))
# remove user if left-over exists
try:
entry = self.admin_conn.delete_entry(self.admin_dn)
except errors.NotFound:
pass
# add user
entry = self.admin_conn.make_entry(
self.admin_dn,
objectclass=["top", "person", "organizationalPerson",
"inetOrgPerson", "cmsuser"],
uid=[self.admin_user],
cn=[self.admin_user],
sn=[self.admin_user],
usertype=['adminType'],
mail=['root@localhost'],
userPassword=[self.admin_password],
userstate=['1']
)
self.admin_conn.add_entry(entry)
for group in ADMIN_GROUPS:
self.__add_admin_to_group(group)
# Now wait until the other server gets replicated this data
master_conn = ipaldap.IPAdmin(self.master_host,
port=replication.DEFAULT_PORT,
protocol='ldap')
master_conn.do_sasl_gssapi_bind()
replication.wait_for_entry(master_conn, entry)
del master_conn
def __remove_admin_from_group(self, group):
dn = DN(('cn', group), ('ou', 'groups'), ('o', 'ipaca'))
entry = self.admin_conn.get_entry(dn)
mod = [(ldap.MOD_DELETE, 'uniqueMember', self.admin_dn)]
try:
self.admin_conn.modify_s(dn, mod)
except ldap.NO_SUCH_ATTRIBUTE:
# already removed
pass
def __teardown_admin(self):
if not self.admin_conn:
self.ldap_connect()
for group in ADMIN_GROUPS:
self.__remove_admin_from_group(group)
self.admin_conn.delete_entry(self.admin_dn)
def __restart_ds_instance(self):
self.ldap_disconnect()
services.knownservices.dirsrv.restart()
def __client_auth_to_db(self):
self.enable_client_auth_to_db(self.dogtag_constants.CS_CFG_PATH)
def __restart_http_instance(self):
# We need to restart apache as we drop a new config file in there
services.knownservices.httpd.restart(capture_output=True)
def __enable_instance(self):
basedn = ipautil.realm_to_suffix(self.realm)
self.ldap_enable('CA', self.fqdn, None, basedn, ['caRenewalMaster'])
def configure_replica(self, master_host, subject_base=None,
ca_cert_bundle=None, ca_signing_algorithm=None,
ca_type=None):
"""Creates a replica CA, creating a local DS backend and using
the topology plugin to manage replication.
Requires domain_level >=1 and custodia on the master.
"""
self.ds_port = DEFAULT_DSPORT
self.master_host = master_host
self.master_replication_port = DEFAULT_DSPORT
if subject_base is None:
self.subject_base = DN(('O', self.realm))
else:
self.subject_base = subject_base
if ca_signing_algorithm is None:
self.ca_signing_algorithm = 'SHA256withRSA'
else:
self.ca_signing_algorithm = ca_signing_algorithm
if ca_type is not None:
self.ca_type = ca_type
else:
self.ca_type = 'generic'
self.pkcs12_info = ca_cert_bundle
self.no_db_setup = True
self.clone = True
# TODO: deal with "Externally signed CA setups"
# Set up steps
self.step("creating certificate server user", create_ca_user)
# Setup Database
self.step("creating certificate server db", self.__create_ds_db)
self.step("setting up initial replication", self.__setup_replication)
self.step("creating installation admin user", self.__setup_admin)
# Setup instance
self.step("setting up certificate server", self.__spawn_instance)
self.step("stopping instance to update CS.cfg", self.stop_instance)
self.step("backing up CS.cfg", self.backup_config)
self.step("disabling nonces", self.__disable_nonce)
self.step("set up CRL publishing", self.__enable_crl_publish)
self.step("enable PKIX certificate path discovery and validation",
self.enable_pkix)
self.step("set up client auth to db", self.__client_auth_to_db)
self.step("destroying installation admin user", self.__teardown_admin)
self.step("starting instance", self.start_instance)
self.step("importing CA chain to RA certificate database",
self.__import_ca_chain)
self.step("fixing RA database permissions", self.fix_ra_perms)
self.step("setting up signing cert profile", self.__setup_sign_profile)
self.step("setting audit signing renewal to 2 years",
self.set_audit_renewal)
self.step("configure certmonger for renewals",
self.configure_certmonger_renewal)
self.step("configure certificate renewals",
self.configure_renewal)
self.step("configure RA certificate renewal",
self.configure_agent_renewal)
self.step("configure Server-Cert certificate renewal",
self.track_servercert)
self.step("Configure HTTP to proxy connections",
self.http_proxy)
self.step("Restart HTTP server to pick up changes",
self.__restart_http_instance)
self.step("enabling CA instance", self.__enable_instance)
self.start_creation(runtime=210)
def replica_ca_install_check(config):
if not config.setup_ca:
return

View File

@ -138,7 +138,6 @@ class DogtagInstance(service.Service):
self.dogtag_constants = dogtag_constants
self.realm = realm
self.dm_password = None
self.admin_password = None
self.fqdn = host_name
self.pkcs12_info = None

View File

@ -40,6 +40,7 @@ WIN_USER_CONTAINER = DN(('cn', 'Users'))
# the default container used by IPA for user entries
IPA_USER_CONTAINER = DN(('cn', 'users'), ('cn', 'accounts'))
PORT = 636
DEFAULT_PORT = 389
TIMEOUT = 120
REPL_MAN_DN = DN(('cn', 'replication manager'), ('cn', 'config'))
DNA_DN = DN(('cn', 'Posix IDs'), ('cn', 'Distributed Numeric Assignment Plugin'), ('cn', 'plugins'), ('cn', 'config'))
@ -190,6 +191,8 @@ class ReplicationManager(object):
self.starttls = starttls
self.suffix = ipautil.realm_to_suffix(realm)
self.need_memberof_fixup = False
self.db_suffix = self.suffix
self.agreement_name_format = "meTo%s"
# The caller is allowed to pass in an existing IPAdmin connection.
# Open a new one if not provided
@ -303,7 +306,7 @@ class ReplicationManager(object):
agreement_types_filters = []
if IPA_REPLICA in agreement_types:
agreement_types_filters.append('(&(objectclass=nsds5ReplicationAgreement)(nsDS5ReplicaRoot=%s))'
% self.suffix)
% self.db_suffix)
if WINSYNC in agreement_types:
agreement_types_filters.append('(objectclass=nsDSWindowsReplicationAgreement)')
if len(agreement_types_filters) > 1:
@ -415,7 +418,8 @@ class ReplicationManager(object):
return "2"
def replica_dn(self):
return DN(('cn','replica'),('cn',self.suffix),('cn','mapping tree'),('cn','config'))
return DN(('cn', 'replica'), ('cn', self.db_suffix),
('cn', 'mapping tree'), ('cn', 'config'))
def replica_config(self, conn, replica_id, replica_binddn):
assert isinstance(replica_binddn, DN)
@ -446,7 +450,7 @@ class ReplicationManager(object):
dn,
objectclass=["top", "nsds5replica", "extensibleobject"],
cn=["replica"],
nsds5replicaroot=[str(self.suffix)],
nsds5replicaroot=[str(self.db_suffix)],
nsds5replicaid=[str(replica_id)],
nsds5replicatype=[replica_type],
nsds5flags=["1"],
@ -496,7 +500,7 @@ class ReplicationManager(object):
'objectclass': [
'top', 'extensibleObject', 'nsBackendInstance'],
'cn': [cn],
'nsslapd-suffix': [str(self.suffix)],
'nsslapd-suffix': [str(self.db_suffix)],
'nsfarmserverurl': urls,
'nsmultiplexorbinddn': [self.repl_man_dn],
'nsmultiplexorcredentials': [self.repl_man_passwd],
@ -517,22 +521,23 @@ class ReplicationManager(object):
def setup_chaining_farm(self, conn):
try:
conn.modify_s(self.suffix, [(ldap.MOD_ADD, 'aci',
conn.modify_s(self.db_suffix, [(ldap.MOD_ADD, 'aci',
[ "(targetattr = \"*\")(version 3.0; acl \"Proxied authorization for database links\"; allow (proxy) userdn = \"ldap:///%s\";)" % self.repl_man_dn ])])
except ldap.TYPE_OR_VALUE_EXISTS:
root_logger.debug("proxy aci already exists in suffix %s on %s" % (self.suffix, conn.host))
root_logger.debug("proxy aci already exists in suffix %s on %s"
% (self.db_suffix, conn.host))
def get_mapping_tree_entry(self):
try:
entries = self.conn.get_entries(
DN(('cn', 'mapping tree'), ('cn', 'config')),
ldap.SCOPE_ONELEVEL,
"(cn=\"%s\")" % (self.suffix))
"(cn=\"%s\")" % (self.db_suffix))
# TODO: Check we got only one entry
return entries[0]
except errors.NotFound:
root_logger.debug(
"failed to find mapping tree entry for %s", self.suffix)
"failed to find mapping tree entry for %s", self.db_suffix)
raise
@ -554,7 +559,8 @@ class ReplicationManager(object):
try:
self.conn.modify_s(dn, mod)
except ldap.TYPE_OR_VALUE_EXISTS:
root_logger.debug("chainOnUpdate already enabled for %s" % self.suffix)
root_logger.debug("chainOnUpdate already enabled for %s"
% self.db_suffix)
def setup_chain_on_update(self, other_conn):
chainbe = self.setup_chaining_backend(other_conn)
@ -623,7 +629,7 @@ class ReplicationManager(object):
master is not used for IPA agreements but for dogtag it will
tell which side we want.
"""
cn = "meTo%s" % (hostname)
cn = self.agreement_name_format % (hostname)
dn = DN(('cn', cn), self.replica_dn())
return (cn, dn)
@ -656,7 +662,7 @@ class ReplicationManager(object):
nsds5replicahost=[b_hostname],
nsds5replicaport=[str(port)],
nsds5replicatimeout=[str(TIMEOUT)],
nsds5replicaroot=[str(self.suffix)],
nsds5replicaroot=[str(self.db_suffix)],
description=["me to %s" % b_hostname],
)
if master is None:
@ -841,10 +847,12 @@ class ReplicationManager(object):
return self.conn.delete_entry(dn)
def delete_referral(self, hostname):
dn = DN(('cn', self.suffix), ('cn', 'mapping tree'), ('cn', 'config'))
dn = DN(('cn', self.db_suffix),
('cn', 'mapping tree'), ('cn', 'config'))
# TODO: should we detect proto/port somehow ?
mod = [(ldap.MOD_DELETE, 'nsslapd-referral',
'ldap://%s/%s' % (ipautil.format_netloc(hostname, 389), self.suffix))]
'ldap://%s/%s' % (ipautil.format_netloc(hostname, 389),
self.db_suffix))]
try:
self.conn.modify_s(dn, mod)
@ -1709,8 +1717,8 @@ class CSReplicationManager(ReplicationManager):
def __init__(self, realm, hostname, dirman_passwd, port):
super(CSReplicationManager, self).__init__(
realm, hostname, dirman_passwd, port, starttls=True)
self.suffix = DN(('o', 'ipaca'))
realm, hostname, dirman_passwd, port)
self.db_suffix = DN(('o', 'ipaca'))
self.hostnames = [] # set before calling or agreement_dn() will fail
def agreement_dn(self, hostname, master=None):
@ -1755,24 +1763,27 @@ class CSReplicationManager(ReplicationManager):
raise errors.NotFound(reason='No agreement found for %s' % hostname)
def delete_referral(self, hostname, port):
dn = DN(('cn', self.suffix), ('cn', 'mapping tree'), ('cn', 'config'))
dn = DN(('cn', self.db_suffix),
('cn', 'mapping tree'), ('cn', 'config'))
entry = self.conn.get_entry(dn)
try:
# TODO: should we detect proto somehow ?
entry['nsslapd-referral'].remove('ldap://%s/%s' %
(ipautil.format_netloc(hostname, port), self.suffix))
entry['nsslapd-referral'].remove(
'ldap://%s/%s' %
(ipautil.format_netloc(hostname, port), self.db_suffix))
self.conn.update_entry(entry)
except Exception as e:
root_logger.debug("Failed to remove referral value: %s" % e)
def has_ipaca(self):
try:
entry = self.conn.get_entry(self.suffix)
entry = self.conn.get_entry(self.db_suffix)
except errors.NotFound:
return False
else:
return True
def get_cs_replication_manager(realm, host, dirman_passwd):
"""Get a CSReplicationManager for a remote host
@ -1801,3 +1812,42 @@ def get_cs_replication_manager(realm, host, dirman_passwd):
root_logger.debug('PKI tree not found on %s:%s' % (host, port))
raise errors.NotFound(reason='Cannot reach PKI DS at %s on ports %s' % (host, ports))
class CAReplicationManager(ReplicationManager):
"""ReplicationManager specific to CA agreements for domain level 1 and
above servers.
"""
def __init__(self, realm, hostname):
# Always connect to self over ldapi
conn = ipaldap.IPAdmin(hostname, ldapi=True, realm=realm)
conn.do_external_bind('root')
super(CAReplicationManager, self).__init__(
realm, hostname, None, port=DEFAULT_PORT, conn=conn)
self.db_suffix = DN(('o', 'ipaca'))
self.agreement_name_format = "caTo%s"
def setup_cs_replication(self, r_hostname):
"""
Assumes a promote replica with working GSSAPI for replication
and unified DS instance.
"""
r_conn = ipaldap.IPAdmin(r_hostname, port=389, protocol='ldap')
r_conn.do_sasl_gssapi_bind()
# Setup the first half
l_id = self._get_replica_id(self.conn, r_conn)
self.basic_replication_setup(self.conn, l_id, self.repl_man_dn, None)
# Now setup the other half
r_id = self._get_replica_id(r_conn, r_conn)
self.basic_replication_setup(r_conn, r_id, self.repl_man_dn, None)
self.setup_agreement(r_conn, self.conn.host, isgssapi=True)
self.setup_agreement(self.conn, r_hostname, isgssapi=True)
# Finally start replication
ret = self.start_replication(r_conn, master=False)
if ret != 0:
raise RuntimeError("Failed to start replication")

View File

@ -771,9 +771,9 @@ def install(installer):
def promote_check(installer):
options = installer
installer._top_dir = tempfile.mkdtemp("ipa")
# FIXME: to implement yet
if options.setup_ca:
raise NotImplementedError
if options.setup_kra:
raise NotImplementedError
@ -814,8 +814,10 @@ def promote_check(installer):
config.host_name = api.env.host
config.domain_name = api.env.domain
config.master_host_name = api.env.server
config.ca_host_name = api.env.ca_host
config.setup_ca = options.setup_ca
config.setup_kra = options.setup_kra
config.dir = installer._top_dir
installutils.verify_fqdn(config.host_name, options.no_host_dns)
installutils.verify_fqdn(config.master_host_name, options.no_host_dns)
@ -1117,14 +1119,6 @@ def promote(installer):
config.realm_name)
custodia.create_replica(config.master_host_name)
if config.setup_ca:
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)
krb = install_krb(config,
setup_pkinit=not options.no_pkinit,
promote=True)
@ -1133,37 +1127,33 @@ def promote(installer):
auto_redirect=not options.no_ui_redirect,
promote=True)
otpd = otpdinstance.OtpdInstance()
otpd.create_instance('OTPD', config.host_name, config.dirman_password,
ipautil.realm_to_suffix(config.realm_name))
CA = cainstance.CAInstance(
config.realm_name, certs.NSS_DIR,
dogtag_constants=dogtag_constants)
CA.dm_password = config.dirman_password
CA.configure_certmonger_renewal()
CA.fix_ra_perms()
# Apply any LDAP updates. Needs to be done after the replica is synced-up
service.print_msg("Applying LDAP updates")
ds.apply_updates()
if options.setup_kra:
kra.install(api, config, options)
else:
service.print_msg("Restarting the directory server")
ds.restart()
service.print_msg("Restarting the KDC")
krb.restart()
otpd = otpdinstance.OtpdInstance()
otpd.create_instance('OTPD', config.host_name, config.dirman_password,
ipautil.realm_to_suffix(config.realm_name))
if config.setup_ca:
dogtag_service = services.knownservices[dogtag_constants.SERVICE_NAME]
dogtag_service.restart(dogtag_constants.PKI_INSTANCE_NAME)
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_data = (os.path.join(config.dir, 'cacert.p12'),
config.dirman_password)
custodia.get_ca_keys(config.ca_host_name, ca_data[0], ca_data[1])
# Restart httpd to pick up the new IPA configuration
service.print_msg("Restarting the web server")
http.restart()
ca = cainstance.CAInstance(config.realm_name, certs.NSS_DIR,
dogtag_constants=dogtag.install_constants,
host_name=config.host_name,
dm_password=config.dirman_password)
ca.configure_replica(config.ca_host_name,
subject_base=config.subject_base,
ca_cert_bundle=ca_data)
if options.setup_kra:
kra.install(api, config, options)
ds.replica_populate()