On 26/11/15 15:13, David Kupka wrote:
On 26/11/15 15:01, David Kupka wrote:
https://fedorahosted.org/freeipa/ticket/5441


Replaced accidentally inserted tabs.



Fixed indentation I screwed up when replacing tabs :-/

--
David Kupka
From 7716a6797b547ba01d189c1772a5896c76777783 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      |   6 +-
 ipaserver/install/dsinstance.py            |   3 +-
 ipaserver/install/server/replicainstall.py | 145 ++++++++++++++++++++++++-----
 3 files changed, 126 insertions(+), 28 deletions(-)

diff --git a/ipaserver/install/custodiainstance.py b/ipaserver/install/custodiainstance.py
index c2ecd397063db3dfe27006232831023d865aac40..fbd9ddf1b39493538c33cb84c58f3292d2aeb0b0 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'
@@ -66,7 +67,8 @@ class CustodiaInstance(SimpleServiceInstance):
 
         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)
+        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..38d73872b739149e9ef81764f75e0730bb26cba0 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

Reply via email to