From 9037c4d84bcf9cde48beb83d69f05c3733106c2d Mon Sep 17 00:00:00 2001 From: Jan Cholasta Date: Mon, 10 Nov 2014 16:24:22 +0000 Subject: [PATCH] Fix CA certificate backup and restore Backup and restore /etc/pki/ca-trust/source/ipa.p11-kit. Create /etc/ipa/nssdb after restore if necessary. https://fedorahosted.org/freeipa/ticket/4711 Reviewed-By: Petr Viktorin --- ipaplatform/base/paths.py | 2 +- ipaplatform/base/tasks.py | 9 +++++++++ ipaplatform/redhat/tasks.py | 43 ++++++++++++++++++++-------------------- ipaserver/install/ipa_backup.py | 2 ++ ipaserver/install/ipa_restore.py | 35 +++++++++++++++++++++++++++++++- 5 files changed, 67 insertions(+), 24 deletions(-) diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py index af502628e493ad7b4d8d30ed1acb98bba8cb39e4..e28147ab4aa1faa3859c38665a83f57fb67e96b2 100644 --- a/ipaplatform/base/paths.py +++ b/ipaplatform/base/paths.py @@ -92,7 +92,7 @@ class BasePathNamespace(object): PAM_LDAP_CONF = "/etc/pam_ldap.conf" PASSWD = "/etc/passwd" ETC_PKI_CA_DIR = "/etc/pki-ca" - SYSTEMWIDE_CA_STORE = "/etc/pki/ca-trust/source/anchors/" + SYSTEMWIDE_IPA_CA_CRT = "/etc/pki/ca-trust/source/anchors/ipa-ca.crt" IPA_P11_KIT = "/etc/pki/ca-trust/source/ipa.p11-kit" NSS_DB_DIR = "/etc/pki/nssdb" PKI_TOMCAT = "/etc/pki/pki-tomcat" diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py index 408447e43cd36d0cdf11a1877b3bc9880c4785de..a6684d7653d6de8202a489edb1f7a38f4b344bbc 100644 --- a/ipaplatform/base/tasks.py +++ b/ipaplatform/base/tasks.py @@ -49,6 +49,15 @@ class BaseTaskNamespace(object): return + def reload_systemwide_ca_store(self): + """ + Reloads the systemwide CA store. + + Returns True if the operation succeeded, False otherwise. + """ + + return True + def insert_ca_certs_into_systemwide_ca_store(self, ca_certs): """ Adds CA certificates from 'ca_certs' to the systemwide CA store diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py index 555516d90a6d1a7d3d9aced5de82a5c1efe6b8c2..4977e1c7c496e36d56110bcdf040ab5c932d31a2 100644 --- a/ipaplatform/redhat/tasks.py +++ b/ipaplatform/redhat/tasks.py @@ -158,8 +158,19 @@ class RedHatTaskNamespace(BaseTaskNamespace): auth_config.add_option("nostart") auth_config.execute() + def reload_systemwide_ca_store(self): + try: + ipautil.run([paths.UPDATE_CA_TRUST]) + except CalledProcessError, e: + root_logger.error( + "Could not update systemwide CA trust database: %s", e) + return False + else: + root_logger.info("Systemwide CA database updated.") + return True + def insert_ca_certs_into_systemwide_ca_store(self, ca_certs): - new_cacert_path = os.path.join(paths.SYSTEMWIDE_CA_STORE, 'ipa-ca.crt') + new_cacert_path = paths.SYSTEMWIDE_IPA_CA_CRT if os.path.exists(new_cacert_path): try: @@ -248,24 +259,18 @@ class RedHatTaskNamespace(BaseTaskNamespace): f.close() # Add the CA to the systemwide CA trust database - try: - ipautil.run([paths.UPDATE_CA_TRUST]) - except CalledProcessError, e: - root_logger.info("Failed to add CA to the systemwide " - "CA trust database: %s" % str(e)) - else: - root_logger.info('Added the CA to the systemwide CA trust ' - 'database.') - return True + if not self.reload_systemwide_ca_store(): + return False - return False + return True def remove_ca_certs_from_systemwide_ca_store(self): - ipa_ca_crt = os.path.join(paths.SYSTEMWIDE_CA_STORE, 'ipa-ca.crt') + result = True update = False # Remove CA cert from systemwide store - for new_cacert_path in (paths.IPA_P11_KIT, ipa_ca_crt): + for new_cacert_path in (paths.IPA_P11_KIT, + paths.SYSTEMWIDE_IPA_CA_CRT): if not os.path.exists(new_cacert_path): continue try: @@ -273,21 +278,15 @@ class RedHatTaskNamespace(BaseTaskNamespace): except OSError, e: root_logger.error( "Could not remove %s: %s", new_cacert_path, e) + result = False else: update = True if update: - try: - ipautil.run([paths.UPDATE_CA_TRUST]) - except CalledProcessError, e: - root_logger.error( - "Could not update systemwide CA trust database: %s", e) + if not self.reload_systemwide_ca_store(): return False - else: - root_logger.info("Systemwide CA database updated.") - return True - return False + return result def backup_and_replace_hostname(self, fstore, statestore, hostname): old_hostname = socket.gethostname() diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py index 75ee243d1c8deb6f8452744df4c040fd0794250c..5d583f7e9186f20ebe8187ba70db28de0c255ae7 100644 --- a/ipaserver/install/ipa_backup.py +++ b/ipaserver/install/ipa_backup.py @@ -138,6 +138,8 @@ class Backup(admintool.AdminTool): paths.SYSCONFIG_ODS, paths.ETC_SYSCONFIG_AUTHCONFIG, paths.IPA_NSSDB_PWDFILE_TXT, + paths.IPA_P11_KIT, + paths.SYSTEMWIDE_IPA_CA_CRT, paths.NSSWITCH_CONF, paths.KRB5_KEYTAB, paths.SSSD_CONF, diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py index 352a1ca2bf283c0beb8c95925c6eb9c9984b3338..8b1e80f5ed5e140ccb17ea0b63d92b6049507b74 100644 --- a/ipaserver/install/ipa_restore.py +++ b/ipaserver/install/ipa_restore.py @@ -26,7 +26,7 @@ import pwd from ConfigParser import SafeConfigParser from ipalib import api, errors -from ipapython import version +from ipapython import version, ipautil, certdb from ipapython.ipautil import run, user_input from ipapython import admintool from ipapython.dn import DN @@ -278,7 +278,9 @@ class Restore(admintool.AdminTool): create_ca_user() if options.online: raise admintool.ScriptError('File restoration cannot be done online.') + self.cert_restore_prepare() self.file_restore(options.no_logs) + self.cert_restore() if 'CA' in self.backup_services: self.__create_dogtag_log_dirs() @@ -660,3 +662,34 @@ class Restore(admintool.AdminTool): tasks.set_selinux_booleans(bools) except ipapython.errors.SetseboolError as e: self.log.error('%s', e) + + def cert_restore_prepare(self): + for basename in ('cert8.db', 'key3.db', 'secmod.db', 'pwdfile.txt'): + filename = os.path.join(paths.IPA_NSSDB_DIR, basename) + try: + ipautil.backup_file(filename) + except OSError as e: + self.log.error("Failed to backup %s: %s" % (filename, e)) + + tasks.remove_ca_certs_from_systemwide_ca_store() + + def cert_restore(self): + if not os.path.exists(os.path.join(paths.IPA_NSSDB_DIR, 'cert8.db')): + certdb.create_ipa_nssdb() + ipa_db = certdb.NSSDatabase(paths.IPA_NSSDB_DIR) + sys_db = certdb.NSSDatabase(paths.NSS_DB_DIR) + for nickname, trust_flags in (('IPA CA', 'CT,C,C'), + ('External CA cert', 'C,,')): + try: + cert = sys_db.get_cert(nickname) + except RuntimeError: + pass + else: + try: + ipa_db.add_cert(cert, nickname, trust_flags) + except ipautil.CalledProcessError as e: + self.log.error( + "Failed to add %s to %s: %s" % + (nickname, paths.IPA_NSSDB_DIR, e)) + + tasks.reload_systemwide_ca_store() -- 2.1.0