From 822e1bc82af3a6c1556546c4fbe96eeafad45762 Mon Sep 17 00:00:00 2001 From: Jan Cholasta Date: Nov 11 2016 11:13:56 +0000 Subject: replica install: merge RA cert import into CA install Merge all RA cert import code paths into a single code path in CA install. https://fedorahosted.org/freeipa/ticket/6392 Reviewed-By: Stanislav Laznicka --- diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py index b9db14c..a033e23 100644 --- a/ipaserver/install/ca.py +++ b/ipaserver/install/ca.py @@ -25,6 +25,9 @@ def install_check(standalone, replica_config, options): global external_cert_file global external_ca_file + if replica_config is not None and not replica_config.setup_ca: + return + realm_name = options.realm_name host_name = options.host_name subject_base = options.subject @@ -143,6 +146,7 @@ def install_step_0(standalone, replica_config, options): master_host = None master_replication_port = None ra_p12 = None + ra_only = False promote = False else: cafile = os.path.join(replica_config.dir, 'cacert.p12') @@ -167,12 +171,11 @@ def install_step_0(standalone, replica_config, options): master_host = replica_config.ca_host_name master_replication_port = replica_config.ca_ds_port ra_p12 = os.path.join(replica_config.dir, 'ra.p12') + ra_only = not replica_config.setup_ca promote = options.promote ca = cainstance.CAInstance(realm_name, certs.NSS_DIR, host_name=host_name) - if standalone or replica_config is not None: - ca.create_ra_agent_db = False ca.configure_instance(host_name, dm_password, dm_password, subject_base=subject_base, ca_signing_algorithm=ca_signing_algorithm, @@ -184,10 +187,14 @@ def install_step_0(standalone, replica_config, options): master_host=master_host, master_replication_port=master_replication_port, ra_p12=ra_p12, + ra_only=ra_only, promote=promote) def install_step_1(standalone, replica_config, options): + if replica_config is not None and not replica_config.setup_ca: + return + realm_name = options.realm_name dm_password = options.dm_password host_name = options.host_name diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py index be5adb5..9bad441 100644 --- a/ipaserver/install/cainstance.py +++ b/ipaserver/install/cainstance.py @@ -60,13 +60,16 @@ from ipapython.ipa_log_manager import log_mgr,\ from ipapython.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 from ipaserver.install import replication from ipaserver.install import sysupgrade +# pylint: disable=unused-import from ipaserver.install.dogtaginstance import (export_kra_agent_pem, DogtagInstance) +# pylint: enable=unused-import from ipaserver.plugins import ldap2 # We need to reset the template because the CA uses the regular boot @@ -309,7 +312,6 @@ class CAInstance(DogtagInstance): self.csr_file = None self.cert_file = None self.cert_chain_file = None - self.create_ra_agent_db = True if realm is not None: self.canickname = get_ca_nickname(realm) @@ -330,7 +332,8 @@ class CAInstance(DogtagInstance): cert_file=None, cert_chain_file=None, master_replication_port=None, subject_base=None, ca_signing_algorithm=None, - ca_type=None, ra_p12=None, promote=False): + ca_type=None, ra_p12=None, ra_only=False, + promote=False): """Create a CA instance. To create a clone, pass in pkcs12_info. @@ -374,62 +377,72 @@ class CAInstance(DogtagInstance): self.cert_chain_file = cert_chain_file self.external = 2 - self.step("creating certificate server user", create_ca_user) - if promote: - # 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) - self.step("configuring certificate server instance", - self.__spawn_instance) - self.step("stopping certificate server 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) - if promote: - self.step("destroying installation admin user", self.teardown_admin) - self.step("starting certificate server instance", self.start_instance) + if self.clone: + cert_db = certs.CertDB(self.realm) + has_ra_cert = (cert_db.get_cert_from_db('ipaCert') != '') + else: + has_ra_cert = False + + if not ra_only: + self.step("creating certificate server user", create_ca_user) + if promote: + # 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) + self.step("configuring certificate server instance", + self.__spawn_instance) + self.step("stopping certificate server 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) + if promote: + self.step("destroying installation admin user", self.teardown_admin) + self.step("starting certificate server instance", self.start_instance) # Step 1 of external is getting a CSR so we don't need to do these # steps until we get a cert back from the external CA. if self.external != 1: - self.step("importing CA chain to RA certificate database", self.__import_ca_chain) - 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) - if not self.clone: + if not has_ra_cert: + self.step("configure certmonger for renewals", + self.configure_certmonger_renewal) + if not self.clone: + self.step("requesting RA certificate from CA", self.__request_ra_certificate) + elif promote: + self.step("Importing RA key", self.__import_ra_key) + else: + self.step("importing RA certificate from PKCS #12 file", + lambda: self.import_ra_cert(ra_p12)) + if not ra_only: + self.step("importing CA chain to RA certificate database", self.__import_ca_chain) + 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("restarting certificate server", self.restart_instance) - self.step("requesting RA certificate from CA", self.__request_ra_certificate) - self.step("exporting RA agent certificate", - lambda: export_kra_agent_pem()) - self.step("adding RA agent as a trusted user", self.__create_ca_agent) - elif not promote and ra_p12 is not None: - self.step("importing RA certificate from PKCS #12 file", - lambda: self.import_ra_cert(ra_p12, configure_renewal=False)) - self.step("authorizing RA to modify profiles", configure_profiles_acl) - self.step("authorizing RA to manage lightweight CAs", - configure_lightweight_ca_acls) - self.step("Ensure lightweight CAs container exists", - ensure_lightweight_cas_container) - self.step("configure certificate renewals", self.configure_renewal) - self.step("configure Server-Cert certificate renewal", self.track_servercert) - self.step("Configure HTTP to proxy connections", - self.http_proxy) - self.step("restarting certificate server", self.restart_instance) - if not promote: - self.step("migrating certificate profiles to LDAP", - migrate_profiles_to_ldap) - self.step("importing IPA certificate profiles", - import_included_profiles) - self.step("adding default CA ACL", ensure_default_caacl) - self.step("adding 'ipa' CA entry", ensure_ipa_authority_entry) - self.step("updating IPA configuration", update_ipa_conf) - - self.step("enabling CA instance", self.__enable_instance) - - self.step("configuring certmonger renewal for lightweight CAs", - self.__add_lightweight_ca_tracking_requests) + if not self.clone: + self.step("adding RA agent as a trusted user", self.__create_ca_agent) + self.step("authorizing RA to modify profiles", configure_profiles_acl) + self.step("authorizing RA to manage lightweight CAs", + configure_lightweight_ca_acls) + self.step("Ensure lightweight CAs container exists", + ensure_lightweight_cas_container) + self.step("configure certificate renewals", self.configure_renewal) + self.step("configure Server-Cert certificate renewal", self.track_servercert) + self.step("Configure HTTP to proxy connections", + self.http_proxy) + self.step("restarting certificate server", self.restart_instance) + if not promote: + self.step("migrating certificate profiles to LDAP", + migrate_profiles_to_ldap) + self.step("importing IPA certificate profiles", + import_included_profiles) + self.step("adding default CA ACL", ensure_default_caacl) + self.step("adding 'ipa' CA entry", ensure_ipa_authority_entry) + self.step("updating IPA configuration", update_ipa_conf) + + self.step("enabling CA instance", self.__enable_instance) + + self.step("configuring certmonger renewal for lightweight CAs", + self.__add_lightweight_ca_tracking_requests) self.start_creation(runtime=210) @@ -485,9 +498,6 @@ class CAInstance(DogtagInstance): config.set("CA", "pki_ds_base_dn", self.basedn) config.set("CA", "pki_ds_database", "ipaca") - if not self.create_ra_agent_db and not self.clone: - self._use_ldaps_during_spawn(config) - # Certificate subject DN's config.set("CA", "pki_subsystem_subject_dn", str(DN(('cn', 'CA Subsystem'), self.subject_base))) @@ -642,10 +652,10 @@ class CAInstance(DogtagInstance): finally: os.remove(agent_name) - if configure_renewal: - self.configure_agent_renewal() - - export_kra_agent_pem() + def __import_ra_key(self): + custodia = custodiainstance.CustodiaInstance(host_name=self.fqdn, + realm=self.realm) + custodia.import_ra_key(self.master_host) def __create_ca_agent(self): """ diff --git a/ipaserver/install/custodiainstance.py b/ipaserver/install/custodiainstance.py index 7d2082c..50efab4 100644 --- a/ipaserver/install/custodiainstance.py +++ b/ipaserver/install/custodiainstance.py @@ -22,7 +22,7 @@ import pwd class CustodiaInstance(SimpleServiceInstance): - def __init__(self, host_name=None, realm=None, ca_is_configured=True): + def __init__(self, host_name=None, realm=None): super(CustodiaInstance, self).__init__("ipa-custodia") self.config_file = paths.IPA_CUSTODIA_CONF self.server_keys = os.path.join(paths.IPA_CUSTODIA_CONF_DIR, @@ -30,7 +30,6 @@ class CustodiaInstance(SimpleServiceInstance): self.ldap_uri = None self.fqdn = host_name self.realm = realm - self.ca_is_configured = ca_is_configured self.__CustodiaClient = functools.partial( CustodiaClient, client_service='host@%s' % self.fqdn, @@ -86,8 +85,6 @@ class CustodiaInstance(SimpleServiceInstance): self.step("Generating ipa-custodia config file", self.__config_file) self.step("Generating ipa-custodia keys", self.__gen_keys) - if self.ca_is_configured: - self.step("Importing RA Key", self.__import_ra_key) super(CustodiaInstance, self).create_instance(gensvc_name='KEYS', fqdn=self.fqdn, ldap_suffix=suffix, @@ -105,8 +102,8 @@ class CustodiaInstance(SimpleServiceInstance): updater = ldapupdate.LDAPUpdate(sub_dict=sub_dict) updater.update([os.path.join(paths.UPDATES_DIR, '73-custodia.update')]) - def __import_ra_key(self): - cli = self.__CustodiaClient(server=self.master_host_name) + def import_ra_key(self, master_host_name): + cli = self.__CustodiaClient(server=master_host_name) cli.fetch_key('ra/ipaCert') def import_dm_password(self, master_host_name): diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py index e9f2af1..a166cc9 100644 --- a/ipaserver/install/httpinstance.py +++ b/ipaserver/install/httpinstance.py @@ -354,6 +354,8 @@ class HTTPInstance(service.Service): # We only handle one server cert nickname = server_certs[0][0] + if nickname == 'ipaCert': + nickname = server_certs[1][0] self.dercert = db.get_cert_from_db(nickname, pem=False) if self.ca_is_configured: diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py index be9038b..0957231 100644 --- a/ipaserver/install/server/replicainstall.py +++ b/ipaserver/install/server/replicainstall.py @@ -713,7 +713,7 @@ def install_check(installer): root_logger.debug('No IPA DNS servers, ' 'skipping forward/reverse resolution check') - if options.setup_ca: + if ca_enabled: options.realm_name = config.realm_name options.host_name = config.host_name options.subject = config.subject_base @@ -762,6 +762,7 @@ def install_check(installer): options.setup_ca, config.ca_ds_port, options.admin_password, ca_cert_file=cafile) + installer._ca_enabled = ca_enabled installer._remote_api = remote_api installer._fstore = fstore installer._sstore = sstore @@ -771,6 +772,7 @@ def install_check(installer): @common_cleanup def install(installer): options = installer + ca_enabled = installer._ca_enabled fstore = installer._fstore sstore = installer._sstore config = installer._config @@ -781,8 +783,6 @@ def install(installer): http_instance = httpinstance.HTTPInstance() http_instance.create_cert_db() - ca_enabled = ipautil.file_exists(config.dir + "/cacert.p12") - # Create DS user/group if it doesn't exist yet dsinstance.create_ds_user() @@ -816,7 +816,7 @@ def install(installer): options.dm_password = config.dirman_password - if config.setup_ca: + if ca_enabled: options.realm_name = config.realm_name options.domain_name = config.domain_name options.host_name = config.host_name @@ -826,7 +826,7 @@ def install(installer): http = install_http(config, auto_redirect=not options.no_ui_redirect, ca_is_configured=ca_enabled) - if config.setup_ca: + if ca_enabled: # Done after install_krb() because lightweight CA key # retrieval setup needs to create kerberos principal. ca.install_step_1(False, config, options) @@ -836,11 +836,7 @@ def install(installer): ipautil.realm_to_suffix(config.realm_name)) if ca_enabled: - CA = cainstance.CAInstance(config.realm_name, certs.NSS_DIR) - CA.dm_password = config.dirman_password - - CA.configure_certmonger_renewal() - CA.import_ra_cert(config.dir + "/ra.p12") + cainstance.export_kra_agent_pem() custodia = custodiainstance.CustodiaInstance(config.host_name, config.realm_name) @@ -1268,6 +1264,10 @@ def promote_check(installer): "CA is present on some master.") raise ScriptError(rval=3) else: + if options.setup_ca: + root_logger.error("The remote master does not have a CA " + "installed, can't set up CA") + raise ScriptError(rval=3) ca_enabled = False if not options.dirsrv_cert_files: root_logger.error("Cannot issue certificates: a CA is not " @@ -1283,12 +1283,7 @@ def promote_check(installer): "setup a KRA clone") raise ScriptError(rval=3) - if options.setup_ca: - if not ca_enabled: - root_logger.error("The remote master does not have a CA " - "installed, can't set up CA") - raise ScriptError(rval=3) - + if ca_enabled: options.realm_name = config.realm_name options.host_name = config.host_name options.subject = config.subject_base @@ -1365,6 +1360,7 @@ def promote_check(installer): @common_cleanup def promote(installer): options = installer + ca_enabled = installer._ca_enabled fstore = installer._fstore sstore = installer._sstore config = installer._config @@ -1401,7 +1397,7 @@ def promote(installer): http_instance.create_cert_db() # FIXME: allow to use passed in certs instead - if installer._ca_enabled: + if ca_enabled: configure_certmonger() # Create DS user/group if it doesn't exist yet @@ -1417,7 +1413,7 @@ def promote(installer): conn.connect(ccache=ccache) # Configure dirsrv - ds = install_replica_ds(config, options, installer._ca_enabled, + ds = install_replica_ds(config, options, ca_enabled, remote_api, promote=True, pkcs12_info=dirsrv_pkcs12_info) @@ -1451,7 +1447,7 @@ def promote(installer): ipaconf.setOption('mode', 'production') ] - if installer._ca_enabled: + if ca_enabled: gopts.extend([ ipaconf.setOption('enable_ra', 'True'), ipaconf.setOption('ra_plugin', 'dogtag'), @@ -1472,15 +1468,10 @@ def promote(installer): os.chmod(target_fname, 0o644) # must be readable for httpd custodia = custodiainstance.CustodiaInstance(config.host_name, - config.realm_name, - installer._ca_enabled) + config.realm_name) custodia.create_replica(config.master_host_name) if installer._ca_enabled: - CA = cainstance.CAInstance(config.realm_name, certs.NSS_DIR) - - CA.configure_certmonger_renewal() - CA.configure_agent_renewal() cainstance.export_kra_agent_pem() install_krb( @@ -1492,7 +1483,7 @@ def promote(installer): config, auto_redirect=not options.no_ui_redirect, promote=True, pkcs12_info=http_pkcs12_info, - ca_is_configured=installer._ca_enabled) + ca_is_configured=ca_enabled) # Apply any LDAP updates. Needs to be done after the replica is synced-up service.print_msg("Applying LDAP updates") @@ -1502,7 +1493,7 @@ def promote(installer): otpd.create_instance('OTPD', config.host_name, ipautil.realm_to_suffix(config.realm_name)) - if config.setup_ca: + if ca_enabled: options.realm_name = config.realm_name options.domain_name = config.domain_name options.host_name = config.host_name