On 26/11/15 15:01, David Kupka wrote:
https://fedorahosted.org/freeipa/ticket/5441
Replaced accidentally inserted tabs. -- David Kupka
From bae8482da29c97becbd1d5de58aed91c3e5f05d9 Mon Sep 17 00:00:00 2001 From: David Kupka <dku...@redhat.com> Date: Thu, 26 Nov 2015 09:01:27 +0100 Subject: [PATCH] ipa-replica-install support caless install with promotion. https://fedorahosted.org/freeipa/ticket/5441 --- ipaserver/install/custodiainstance.py | 8 +- ipaserver/install/dsinstance.py | 3 +- ipaserver/install/server/replicainstall.py | 145 ++++++++++++++++++++++++----- 3 files changed, 127 insertions(+), 29 deletions(-) diff --git a/ipaserver/install/custodiainstance.py b/ipaserver/install/custodiainstance.py index c2ecd397063db3dfe27006232831023d865aac40..300733ce8b9919288a43336feabb8cb2cbaad2f2 100644 --- a/ipaserver/install/custodiainstance.py +++ b/ipaserver/install/custodiainstance.py @@ -16,7 +16,7 @@ import tempfile class CustodiaInstance(SimpleServiceInstance): - def __init__(self, host_name=None, realm=None): + def __init__(self, host_name=None, realm=None, ca_is_configured=True): super(CustodiaInstance, self).__init__("ipa-custodia") self.config_file = paths.IPA_CUSTODIA_CONF self.server_keys = os.path.join(paths.IPA_CUSTODIA_CONF_DIR, @@ -24,6 +24,7 @@ class CustodiaInstance(SimpleServiceInstance): self.ldap_uri = None self.fqdn = host_name self.realm = realm + self.ca_is_configured = ca_is_configured def __config_file(self): template_file = os.path.basename(self.config_file) + '.template' @@ -65,8 +66,9 @@ class CustodiaInstance(SimpleServiceInstance): 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) - self.step("Importing RA Key", self.__import_ra_key) + 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, diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index e47e85ca6f25c33e4327fc5ee1cd2e90e6c2ca4a..a58b0f7c2f1a6baae09e38695b8e569d7495d524 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -381,7 +381,8 @@ class DsInstance(service.Service): if self.promote: self.step("creating DS keytab", self.__get_ds_keytab) - self.step("retrieving DS Certificate", self.__get_ds_cert) + if self.ca_is_configured: + self.step("retrieving DS Certificate", self.__get_ds_cert) self.step("restarting directory server", self.__restart_instance) self.step("setting up initial replication", self.__setup_replica) diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py index 4b811105be3409e7c673fb55f96c8b3e58be63b5..447486bf0d4a1229733cef88d3fa3fece8473bb3 100644 --- a/ipaserver/install/server/replicainstall.py +++ b/ipaserver/install/server/replicainstall.py @@ -32,6 +32,7 @@ from ipaserver.install import ( ntpinstance, otpdinstance, custodiainstance, service) from ipaserver.install.installutils import create_replica_config from ipaserver.install.installutils import ReplicaConfig +from ipaserver.install.installutils import load_pkcs12 from ipaserver.install.replication import ( ReplicationManager, replica_conn_check) import SSSDConfig @@ -87,13 +88,20 @@ def install_http_certs(config, fstore): # FIXME: need Signing-Cert too ? -def install_replica_ds(config, options, promote=False): +def install_replica_ds(config, options, promote=False, pkcs12_info=None, + ca_configured=False): dsinstance.check_ports() # if we have a pkcs12 file, create the cert db from # that. Otherwise the ds setup will create the CA # cert - pkcs12_info = make_pkcs12_info(config.dir, "dscert.p12", "dirsrv_pin.txt") + if pkcs12_info is None: + pkcs12_info = make_pkcs12_info(config.dir, "dscert.p12", "dirsrv_pin.txt") + + if promote: + ca_file = paths.IPA_CA_CRT + else: + ca_file = os.path.join(config.dir, "ca.crt") ds = dsinstance.DsInstance( config_ldif=options.dirsrv_config_file) @@ -105,8 +113,8 @@ def install_replica_ds(config, options, promote=False): dm_password=config.dirman_password, subject_base=config.subject_base, pkcs12_info=pkcs12_info, - ca_is_configured=ipautil.file_exists(config.dir + "/cacert.p12"), - ca_file=config.dir + "/ca.crt", + ca_is_configured=ca_configured, + ca_file=ca_file, promote=promote, ) @@ -144,11 +152,21 @@ def install_ca_cert(ldap, base_dn, realm, cafile): sys.exit(1) -def install_http(config, auto_redirect, promote=False): +def install_http(config, auto_redirect, promote=False, pkcs12_info=None, + ca_is_configured=None): # if we have a pkcs12 file, create the cert db from # that. Otherwise the ds setup will create the CA # cert - pkcs12_info = make_pkcs12_info(config.dir, "httpcert.p12", "http_pin.txt") + if pkcs12_info is None: + pkcs12_info = make_pkcs12_info(config.dir, "httpcert.p12", "http_pin.txt") + + if promote: + ca_file = paths.IPA_CA_CRT + else: + ca_file = os.path.join(config.dir, "ca.crt") + + if ca_is_configured is None: + ca_is_configured = ipautil.file_exists(config.dir + "/cacert.p12") memcache = memcacheinstance.MemcacheInstance() memcache.create_instance('MEMCACHE', config.host_name, @@ -159,9 +177,8 @@ def install_http(config, auto_redirect, promote=False): http.create_instance( config.realm_name, config.host_name, config.domain_name, config.dirman_password, False, pkcs12_info, - auto_redirect=auto_redirect, ca_file=config.dir + "/ca.crt", - ca_is_configured=ipautil.file_exists(config.dir + "/cacert.p12"), - promote=promote) + auto_redirect=auto_redirect, ca_file=ca_file, + ca_is_configured=ca_is_configured, promote=promote) http.setup_firefox_extension(config.realm_name, config.domain_name) @@ -799,6 +816,61 @@ def promote_check(installer): config.setup_kra = options.setup_kra config.dir = installer._top_dir + http_pkcs12_file = None + http_pkcs12_info = None + dirsrv_pkcs12_file = None + dirsrv_pkcs12_info = None + pkinit_pkcs12_file = None + pkinit_pkcs12_info = None + + if options.http_cert_files: + if options.http_pin is None: + options.http_pin = installutils.read_password( + "Enter Apache Server private key unlock", + confirm=False, validate=False) + if options.http_pin is None: + sys.exit( + "Apache Server private key unlock password required") + http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12( + cert_files=options.http_cert_files, + key_password=options.http_pin, + key_nickname=options.http_cert_name, + ca_cert_files=options.ca_cert_files, + host_name=config.host_name) + http_pkcs12_info = (http_pkcs12_file.name, http_pin) + + if options.dirsrv_cert_files: + if options.dirsrv_pin is None: + options.dirsrv_pin = installutils.read_password( + "Enter Directory Server private key unlock", + confirm=False, validate=False) + if options.dirsrv_pin is None: + sys.exit( + "Directory Server private key unlock password required") + dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12( + cert_files=options.dirsrv_cert_files, + key_password=options.dirsrv_pin, + key_nickname=options.dirsrv_cert_name, + ca_cert_files=options.ca_cert_files, + host_name=config.host_name) + dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin) + + if options.pkinit_cert_files: + if options.pkinit_pin is None: + options.pkinit_pin = installutils.read_password( + "Enter Kerberos KDC private key unlock", + confirm=False, validate=False) + if options.pkinit_pin is None: + sys.exit( + "Kerberos KDC private key unlock password required") + pkinit_pkcs12_file, pkinit_pin, pkinit_ca_cert = load_pkcs12( + cert_files=options.pkinit_cert_files, + key_password=options.pkinit_pin, + key_nickname=options.pkinit_cert_name, + ca_cert_files=options.ca_cert_files, + host_name=config.host_name) + pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin) + installutils.verify_fqdn(config.host_name, options.no_host_dns) installutils.verify_fqdn(config.master_host_name, options.no_host_dns) installutils.check_creds(options, config.realm_name) @@ -903,15 +975,20 @@ def promote_check(installer): config.subject_base = DN(subject_base) # Find if any server has a CA + ca_enabled = False ca_host = service.find_providing_server('CA', conn, api.env.server) if ca_host is not None: config.ca_host_name = ca_host ca_enabled = True + if options.dirsrv_cert_files: + root_logger.error("Certificates could not be provided when " + "CA is present on some master.") + sys.exit(3) else: - # FIXME: add way to pass in certificates - root_logger.error("The remote master does not have a CA " - "installed, can't proceed without certs") - sys.exit(3) + if not options.dirsrv_cert_files: + root_logger.error("The remote master does not have a CA " + "installed, can't proceed without certs") + sys.exit(3) config.kra_host_name = service.find_providing_server('KRA', conn, api.env.server) @@ -969,6 +1046,12 @@ def promote_check(installer): installer._fstore = fstore installer._sstore = sstore installer._config = config + installer._dirsrv_pkcs12_file = dirsrv_pkcs12_file + installer._dirsrv_pkcs12_info = dirsrv_pkcs12_info + installer._http_pkcs12_file = http_pkcs12_file + installer._http_pkcs12_info = http_pkcs12_info + installer._pkinit_pkcs12_file = pkinit_pkcs12_file + installer._pkinit_pkcs12_info = pkinit_pkcs12_info @common_cleanup @@ -977,6 +1060,12 @@ def promote(installer): fstore = installer._fstore sstore = installer._sstore config = installer._config + dirsrv_pkcs12_file = installer._dirsrv_pkcs12_file + dirsrv_pkcs12_info = installer._dirsrv_pkcs12_info + http_pkcs12_file = installer._http_pkcs12_file + http_pkcs12_info = installer._http_pkcs12_info + pkinit_pkcs12_file = installer._pkinit_pkcs12_file + pkinit_pkcs12_info = installer._pkinit_pkcs12_info # Save client file and merge in server directives target_fname = paths.IPA_DEFAULT_CONF @@ -1002,7 +1091,9 @@ def promote(installer): ntp.create_instance() # Configure dirsrv - ds = install_replica_ds(config, options, promote=True) + ds = install_replica_ds(config, options, promote=True, + pkcs12_info=dirsrv_pkcs12_info, + ca_configured=installer._ca_enabled) # Always try to install DNS records install_dns_records(config, options, api) @@ -1031,7 +1122,8 @@ def promote(installer): os.chmod(target_fname, 0o644) # must be readable for httpd custodia = custodiainstance.CustodiaInstance(config.host_name, - config.realm_name) + config.realm_name, + installer._ca_enabled) custodia.create_replica(config.master_host_name) krb = install_krb(config, @@ -1040,7 +1132,8 @@ def promote(installer): http = install_http(config, auto_redirect=not options.no_ui_redirect, - promote=True) + promote=True, pkcs12_info=http_pkcs12_info, + ca_is_configured=installer._ca_enabled) # Apply any LDAP updates. Needs to be done after the replica is synced-up service.print_msg("Applying LDAP updates") @@ -1158,15 +1251,6 @@ class Replica(BaseServer): external_ca = None external_ca_type = None external_cert_files = None - dirsrv_cert_files = None - http_cert_files = None - pkinit_cert_files = None - dirsrv_pin = None - http_pin = None - pkinit_pin = None - dirsrv_cert_name = None - http_cert_name = None - pkinit_cert_name = None ca_cert_files = None subject = None ca_signing_algorithm = None @@ -1184,6 +1268,12 @@ class Replica(BaseServer): self._top_dir = None self._config = None self._update_hosts_file = False + self._dirsrv_pkcs12_file = None + self._http_pkcs12_file = None + self._pkinit_pkcs12_file = None + self._dirsrv_pkcs12_info = None + self._http_pkcs12_info = None + self._pkinit_pkcs12_info = None if self.replica_file is None: self.promote = True @@ -1191,6 +1281,11 @@ class Replica(BaseServer): if not ipautil.file_exists(self.replica_file): raise RuntimeError("Replica file %s does not exist" % self.replica_file) + #pylint: disable=no-member + if any(self.ca.dirsrv_pkcs12_file, self.ca.http_pkcs12_file, + self.ca.pkinit_pkcs12_file): + raise RuntimeError("You cannot provide certificates together " + "with replica file") if self.setup_dns: #pylint: disable=no-member -- 2.5.0
-- 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