Blob Blame History Raw
From 2409b5204101cceafb28289db0d99c1474ee2430 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jcholast@redhat.com>
Date: Fri, 7 Apr 2017 07:43:09 +0200
Subject: [PATCH] dsinstance, httpinstance: consolidate certificate request
 code

A different code path is used for DS and httpd certificate requests in
replica promotion. This is rather unnecessary and makes the certificate
request code not easy to follow.

Consolidate the non-promotion and promotion code paths into one.

https://pagure.io/freeipa/issue/6757

Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
---
 ipaserver/install/dsinstance.py            | 76 +++++++++---------------------
 ipaserver/install/httpinstance.py          | 40 ++++++++--------
 ipaserver/install/server/install.py        |  4 --
 ipaserver/install/server/replicainstall.py | 22 +--------
 4 files changed, 43 insertions(+), 99 deletions(-)

diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index fb5f925de8e658dca9370714413012527f00c39d..31dbd4ec8bcaf4a7545b4f9f316fe609b845cb75 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -396,10 +396,7 @@ class DsInstance(service.Service):
 
         self.step("creating DS keytab", self.request_service_keytab)
         if self.promote:
-            if self.pkcs12_info:
-                self.step("configuring TLS for DS instance", self.__enable_ssl)
-            else:
-                self.step("retrieving DS Certificate", self.__get_ds_cert)
+            self.step("configuring TLS for DS instance", self.__enable_ssl)
             self.step("restarting directory server", self.__restart_instance)
 
         self.step("setting up initial replication", self.__setup_replica)
@@ -810,18 +807,23 @@ class DsInstance(service.Service):
                 dsdb.track_server_cert(
                     self.nickname, self.principal, dsdb.passwd_fname,
                     'restart_dirsrv %s' % self.serverid)
+
+            self.add_cert_to_service()
         else:
             dsdb.create_from_cacert()
-            ca_args = [
-                paths.CERTMONGER_DOGTAG_SUBMIT,
-                '--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn,
-                '--certfile', paths.RA_AGENT_PEM,
-                '--keyfile', paths.RA_AGENT_KEY,
-                '--cafile', paths.IPA_CA_CRT,
-                '--agent-submit'
-            ]
-            helper = " ".join(ca_args)
-            prev_helper = certmonger.modify_ca_helper('IPA', helper)
+            if self.master_fqdn is None:
+                ca_args = [
+                    paths.CERTMONGER_DOGTAG_SUBMIT,
+                    '--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn,
+                    '--certfile', paths.RA_AGENT_PEM,
+                    '--keyfile', paths.RA_AGENT_KEY,
+                    '--cafile', paths.IPA_CA_CRT,
+                    '--agent-submit'
+                ]
+                helper = " ".join(ca_args)
+                prev_helper = certmonger.modify_ca_helper('IPA', helper)
+            else:
+                prev_helper = None
             try:
                 cmd = 'restart_dirsrv %s' % self.serverid
                 certmonger.request_and_wait_for_cert(
@@ -835,7 +837,8 @@ class DsInstance(service.Service):
                     dns=[self.fqdn],
                     post_command=cmd)
             finally:
-                certmonger.modify_ca_helper('IPA', prev_helper)
+                if prev_helper is not None:
+                    certmonger.modify_ca_helper('IPA', prev_helper)
 
             # restart_dirsrv in the request above restarts DS, reconnect ldap2
             api.Backend.ldap2.disconnect()
@@ -843,6 +846,9 @@ class DsInstance(service.Service):
 
             self.dercert = dsdb.get_cert_from_db(self.nickname, pem=False)
 
+            if prev_helper is not None:
+                self.add_cert_to_service()
+
         dsdb.create_pin_file()
 
         self.cacert_name = dsdb.cacert_name
@@ -1236,46 +1242,6 @@ class DsInstance(service.Service):
         ipautil.config_replace_variables(paths.SYSCONFIG_DIRSRV,
                                          replacevars=vardict)
 
-    def __get_ds_cert(self):
-        nssdb_dir = config_dirname(self.serverid)
-        db = certs.CertDB(
-            self.realm,
-            nssdir=nssdb_dir,
-            subject_base=self.subject_base,
-            ca_subject=self.ca_subject,
-        )
-        db.create_from_cacert()
-        db.request_service_cert(self.nickname, self.principal, self.fqdn)
-        db.create_pin_file()
-
-        # Connect to self over ldapi as Directory Manager and configure SSL
-        ldap_uri = ipaldap.get_ldap_uri(protocol='ldapi', realm=self.realm)
-        conn = ipaldap.LDAPClient(ldap_uri)
-        conn.external_bind()
-
-        mod = [(ldap.MOD_REPLACE, "nsSSLClientAuth", "allowed"),
-               (ldap.MOD_REPLACE, "nsSSL3Ciphers", "default"),
-               (ldap.MOD_REPLACE, "allowWeakCipher", "off")]
-        conn.modify_s(DN(('cn', 'encryption'), ('cn', 'config')), mod)
-
-        mod = [(ldap.MOD_ADD, "nsslapd-security", "on")]
-        conn.modify_s(DN(('cn', 'config')), mod)
-
-        entry = conn.make_entry(
-            DN(('cn', 'RSA'), ('cn', 'encryption'), ('cn', 'config')),
-            objectclass=["top", "nsEncryptionModule"],
-            cn=["RSA"],
-            nsSSLPersonalitySSL=[self.nickname],
-            nsSSLToken=["internal (software)"],
-            nsSSLActivation=["on"],
-        )
-        conn.add_entry(entry)
-
-        conn.unbind()
-
-        # check for open secure port 636 from now on
-        self.open_ports.append(636)
-
 
 def write_certmap_conf(realm, ca_subject):
     """(Re)write certmap.conf with given CA subject DN."""
diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
index d7cd776ab9831b5408797ae41b7c7fbb10707b18..45bf479d1088c3b3396d955bf2592c4bce1e886f 100644
--- a/ipaserver/install/httpinstance.py
+++ b/ipaserver/install/httpinstance.py
@@ -376,12 +376,12 @@ class HTTPInstance(service.Service):
         return False
 
     def __setup_ssl(self):
-        truncate = not self.promote or not self.ca_is_configured
         db = certs.CertDB(self.realm, nssdir=paths.HTTPD_ALIAS_DIR,
                           subject_base=self.subject_base, user="root",
                           group=constants.HTTPD_GROUP,
-                          truncate=truncate)
+                          truncate=True)
         self.disable_system_trust()
+        self.create_password_conf()
         if self.pkcs12_info:
             if self.ca_is_configured:
                 trust_flags = 'CT,C,C'
@@ -394,8 +394,6 @@ class HTTPInstance(service.Service):
             if len(server_certs) == 0:
                 raise RuntimeError("Could not find a suitable server cert in import in %s" % self.pkcs12_info[0])
 
-            self.create_password_conf()
-
             # We only handle one server cert
             nickname = server_certs[0][0]
             if nickname == 'ipaCert':
@@ -410,7 +408,6 @@ class HTTPInstance(service.Service):
 
         else:
             if not self.promote:
-                self.create_password_conf()
                 ca_args = [
                     paths.CERTMONGER_DOGTAG_SUBMIT,
                     '--ee-url', 'https://%s:8443/ca/ee/ca' % self.fqdn,
@@ -421,23 +418,26 @@ class HTTPInstance(service.Service):
                 ]
                 helper = " ".join(ca_args)
                 prev_helper = certmonger.modify_ca_helper('IPA', helper)
-
-                try:
-                    certmonger.request_and_wait_for_cert(
-                        certpath=db.secdir,
-                        nickname=self.cert_nickname,
-                        principal=self.principal,
-                        passwd_fname=db.passwd_fname,
-                        subject=str(DN(('CN', self.fqdn), self.subject_base)),
-                        ca='IPA',
-                        profile=dogtag.DEFAULT_PROFILE,
-                        dns=[self.fqdn],
-                        post_command='restart_httpd')
-                    self.dercert = db.get_cert_from_db(
-                        self.cert_nickname, pem=False)
-                finally:
+            else:
+                prev_helper = None
+            try:
+                certmonger.request_and_wait_for_cert(
+                    certpath=db.secdir,
+                    nickname=self.cert_nickname,
+                    principal=self.principal,
+                    passwd_fname=db.passwd_fname,
+                    subject=str(DN(('CN', self.fqdn), self.subject_base)),
+                    ca='IPA',
+                    profile=dogtag.DEFAULT_PROFILE,
+                    dns=[self.fqdn],
+                    post_command='restart_httpd')
+            finally:
+                if prev_helper is not None:
                     certmonger.modify_ca_helper('IPA', prev_helper)
 
+            self.dercert = db.get_cert_from_db(self.cert_nickname, pem=False)
+
+            if prev_helper is not None:
                 self.add_cert_to_service()
 
             # Verify we have a valid server cert
diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py
index d7eb0bfacd0815026c82f59d76962f527e2b7dad..f8e64ec26e85bbc6218018eec8f403a0567b45a2 100644
--- a/ipaserver/install/server/install.py
+++ b/ipaserver/install/server/install.py
@@ -807,10 +807,6 @@ def install(installer):
     if setup_ca:
         ca.install_step_1(False, None, options)
 
-    # The DS instance is created before the keytab, add the SSL cert we
-    # generated
-    ds.add_cert_to_service()
-
     otpd = otpdinstance.OtpdInstance()
     otpd.create_instance('OTPD', host_name,
                          ipautil.realm_to_suffix(realm_name))
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
index f489e691999fd9d6e82879341922510e56eac47d..cd6a62f9540f4a46da70e0cc5686eff5f54e7dfe 100644
--- a/ipaserver/install/server/replicainstall.py
+++ b/ipaserver/install/server/replicainstall.py
@@ -27,7 +27,6 @@ from ipapython.dn import DN
 from ipapython.ipa_log_manager import root_logger
 from ipapython.admintool import ScriptError
 from ipaplatform import services
-from ipaplatform.constants import constants as pconstants
 from ipaplatform.tasks import tasks
 from ipaplatform.paths import paths
 from ipalib import api, constants, create_api, errors, rpc, x509
@@ -77,18 +76,6 @@ def make_pkcs12_info(directory, cert_name, password_name):
         return None
 
 
-def install_http_certs(host_name, realm_name, subject_base):
-    principal = 'HTTP/%s@%s' % (host_name, realm_name)
-    subject = subject_base or DN(('O', realm_name))
-    db = certs.CertDB(realm_name, nssdir=paths.HTTPD_ALIAS_DIR,
-                      subject_base=subject, user="root",
-                      group=pconstants.HTTPD_GROUP, truncate=True)
-    db.request_service_cert('Server-Cert', principal, host_name)
-    # Obtain certificate for the HTTP service
-    http = httpinstance.HTTPInstance()
-    http.create_password_conf()
-
-
 def install_replica_ds(config, options, ca_is_configured, remote_api,
                        ca_file, promote=False, pkcs12_info=None):
     dsinstance.check_ports()
@@ -175,7 +162,8 @@ def install_http(config, auto_redirect, ca_is_configured, ca_file,
     http.create_instance(
         config.realm_name, config.host_name, config.domain_name,
         pkcs12_info, auto_redirect=auto_redirect, ca_file=ca_file,
-        ca_is_configured=ca_is_configured, promote=promote)
+        ca_is_configured=ca_is_configured, promote=promote,
+        subject_base=config.subject_base)
 
     return http
 
@@ -1414,12 +1402,6 @@ def install(installer):
         # Always try to install DNS records
         install_dns_records(config, options, remote_api)
 
-        if promote and ca_enabled:
-            # we need to install http certs to setup ssl for httpd
-            install_http_certs(config.host_name,
-                               config.realm_name,
-                               config.subject_base)
-
         ntpinstance.ntp_ldap_enable(config.host_name, ds.suffix,
                                     remote_api.env.realm)
     finally:
-- 
2.9.3