On 10/13/2015 09:17 AM, Petr Spacek wrote:
On 12.10.2015 13:38, Martin Babinsky wrote:

each service possessing Kerberos keytab wiil now remove it and destroy any
associated credentials cache during its uninstall

https://fedorahosted.org/freeipa/ticket/5243

BTW some time ago Simo proposed that we should remove caches and old keytabs
during *install* so problems caused by failing uninstallation will be fixed on
repeated install. This is yet another step towards idempotent installer.

To me this makes more sense than doing so on uninstall. Does it make sense to
you, too?


Attaching updated patch that does cleanup also before each instance creation. It is a bit ugly I admit, but I couldn't think of a better way to do it and didn't want to poke into service/instance code more than neccesary.

--
Martin^3 Babinsky
From 2b138292da7f19d0a199bad6ebc5aac56ec15373 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Fri, 9 Oct 2015 18:08:38 +0200
Subject: [PATCH] remove Kerberos authenticators when installing/uninstalling
 service instance

each service possessing Kerberos keytab/ccache will now perform their removal
before creation and after uninstall

https://fedorahosted.org/freeipa/ticket/5243
---
 ipaserver/install/bindinstance.py        |  5 +++++
 ipaserver/install/dnskeysyncinstance.py  |  5 +++++
 ipaserver/install/dsinstance.py          |  4 ++--
 ipaserver/install/httpinstance.py        | 11 ++++++++---
 ipaserver/install/installutils.py        | 28 ++++++++++++++++++++++++++++
 ipaserver/install/odsexporterinstance.py |  9 +++++++++
 ipaserver/install/service.py             |  7 +++++++
 7 files changed, 64 insertions(+), 5 deletions(-)

diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index 0bc0557cc10a6d32f71cc0426ce350c394216022..d503451bc12736fde58381d50bf9afd4e27ebbcb 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -604,6 +604,9 @@ class BindInstance(service.Service):
         os.close(bind_fd)
         print("Sample zone file for bind has been created in "+bind_name)
 
+    def pre_creation_setup(self):
+        installutils.remove_krb5_credentials(paths.NAMED_KEYTAB, user='named')
+
     def create_instance(self):
 
         try:
@@ -1202,3 +1205,5 @@ class BindInstance(service.Service):
 
         if named_regular_running:
             self.named_regular.start()
+
+        installutils.remove_krb5_credentials(paths.NAMED_KEYTAB, user='named')
diff --git a/ipaserver/install/dnskeysyncinstance.py b/ipaserver/install/dnskeysyncinstance.py
index 68130c92558a4feb8d08fa826dbf6333d4461d1f..1dcfbf6c415b81fabdaec5fac7e52b99f9f41720 100644
--- a/ipaserver/install/dnskeysyncinstance.py
+++ b/ipaserver/install/dnskeysyncinstance.py
@@ -116,6 +116,9 @@ class DNSKeySyncInstance(service.Service):
         print("Restarting ipa-dnskeysyncd")
         self.__start()
 
+    def pre_creation_setup(self):
+        installutils.remove_krb5_credentials(paths.IPA_DNSKEYSYNCD_KEYTAB)
+
     def create_instance(self, fqdn, realm_name):
         self.fqdn = fqdn
         self.realm = realm_name
@@ -497,3 +500,5 @@ class DNSKeySyncInstance(service.Service):
             os.remove(paths.DNSSEC_SOFTHSM_PIN)
         except Exception:
             pass
+
+        installutils.remove_krb5_credentials(paths.IPA_DNSKEYSYNCD_KEYTAB)
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index 07083460d8544f2b37c0894e29b1a359fdbc3864..6198bf50410c3fbef6ca7fe7694c06920879a19c 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -937,8 +937,8 @@ class DsInstance(service.Service):
             root_logger.debug("Removing DS instance %s" % serverid)
             try:
                 remove_ds_instance(serverid)
-                root_logger.debug("Removing DS keytab")
-                installutils.remove_file(paths.DS_KEYTAB)
+                installutils.remove_krb5_credentials(paths.DS_KEYTAB,
+                                                     user=DS_USER)
             except ipautil.CalledProcessError:
                 root_logger.error("Failed to remove DS instance. You may "
                                   "need to remove instance data manually")
diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
index 0d1074dbda486f6102dd1628d720080e6dfb7ff7..93238b0e236e84bffa3ac603cd6c862415d1ab72 100644
--- a/ipaserver/install/httpinstance.py
+++ b/ipaserver/install/httpinstance.py
@@ -109,6 +109,11 @@ class HTTPInstance(service.Service):
 
     subject_base = ipautil.dn_attribute_property('_subject_base')
 
+    def pre_creation_setup(self):
+        if not self.promote:
+            installutils.remove_krb5_credentials(
+                paths.IPA_KEYTAB, ccache=paths.KRB5CC_HTTPD, user='apache')
+
     def create_instance(self, realm, fqdn, domain_name, dm_password=None,
                         autoconfig=True, pkcs12_info=None,
                         subject_base=None, auto_redirect=True, ca_file=None,
@@ -496,9 +501,9 @@ class HTTPInstance(service.Service):
                 root_logger.debug(error)
                 pass
 
-        # Remove the ccache file for the HTTPD service
-        ipautil.run([paths.KDESTROY, '-c', paths.KRB5CC_HTTPD], runas='apache',
-                    raiseonerr=False)
+        # Remove HTTPD service keytab and credentials cache
+        installutils.remove_krb5_credentials(
+            paths.IPA_KEYTAB, ccache=paths.KRB5CC_HTTPD, user='apache')
 
         # Remove the configuration files we create
         installutils.remove_file(paths.HTTPD_IPA_REWRITE_CONF)
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index 1d3551f8bb9cfcac1f6fa24043aea4b5d0a07719..bee13ee991cbda48978451e87c421120bd5592a9 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -1353,3 +1353,31 @@ class ModifyLDIF(ldif.LDIFParser):
         for dn in remaining_changes:
             root_logger.error(
                 "DN: %s does not exists or haven't been updated", dn)
+
+
+def remove_krb5_credentials(keytab, ccache=None, user=None):
+    """
+    Remove service keytab and credential cache if they are defined
+    """
+    try:
+        root_logger.debug("Removing service keytab: {}".format(keytab))
+        os.remove(keytab)
+    except OSError as e:
+        if e.errno != 2:
+            root_logger.warning("Failed to remove Kerberos keytab '{}': "
+                                "{}".format(keytab, e))
+            root_logger.warning("You may have to remove it manually")
+
+    if ccache is None and user is None:
+        return
+
+    root_logger.debug("Removing service credentials cache")
+    kdestroy_cmd = [paths.KDESTROY, '-A']
+    if ccache is not None:
+        root_logger.debug("Ccache path: '{}'".format(ccache))
+        kdestroy_cmd.extend(['-c', ccache])
+
+    try:
+        ipautil.run(kdestroy_cmd, runas=user)
+    except ipautil.CalledProcessError as e:
+        root_logger.warning("Failed to clear Kerberos credentials cache:", e)
diff --git a/ipaserver/install/odsexporterinstance.py b/ipaserver/install/odsexporterinstance.py
index e9ba51027eb1386384361e3f0190c40267134e9e..82d1c27eb9d053deb7e27f72a159190df9b566a2 100644
--- a/ipaserver/install/odsexporterinstance.py
+++ b/ipaserver/install/odsexporterinstance.py
@@ -41,6 +41,11 @@ class ODSExporterInstance(service.Service):
 
     suffix = ipautil.dn_attribute_property('_suffix')
 
+    def pre_creation_setup(self):
+        installutils.remove_krb5_credentials(
+            paths.IPA_ODS_EXPORTER_KEYTAB,
+            ccache=paths.IPA_ODS_EXPORTER_CCACHE)
+
     def create_instance(self, fqdn, realm_name):
         self.backup_state("enabled", self.is_enabled())
         self.backup_state("running", self.is_running())
@@ -192,3 +197,7 @@ class ODSExporterInstance(service.Service):
 
         if signerd_running:
             signerd_service.start()
+
+        installutils.remove_krb5_credentials(
+            paths.IPA_ODS_EXPORTER_KEYTAB,
+            ccache=paths.IPA_ODS_EXPORTER_CCACHE)
diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
index 7b7b68c15adc477b751e8a03aed9627685898f0f..905fe2a02161e64697581066b6e6b584e406a75e 100644
--- a/ipaserver/install/service.py
+++ b/ipaserver/install/service.py
@@ -386,6 +386,12 @@ class Service(object):
     def step(self, message, method, run_after_failure=False):
         self.steps.append((message, method, run_after_failure))
 
+    def pre_creation_setup(self):
+        """
+        tasks which are run before the service installation steps are executed
+        """
+        pass
+
     def start_creation(self, start_message=None, end_message=None,
         show_service_name=True, runtime=-1):
         """
@@ -440,6 +446,7 @@ class Service(object):
         step = 0
         steps_iter = iter(self.steps)
         try:
+            self.pre_creation_setup()
             for message, method, run_after_failure in steps_iter:
                 full_msg = "  [%d/%d]: %s" % (step+1, len(self.steps), message)
                 run_step(full_msg, method)
-- 
2.4.3

-- 
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