URL: https://github.com/freeipa/freeipa/pull/457
Author: martbab
 Title: #457: adtrustinstance: use LDAPI/EXTERNAL to retrieve CIFS keytab
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/457/head:pr457
git checkout pr457
From befb5e97602d1e523157b503d33a3ca8f8f84a9d Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Fri, 3 Feb 2017 17:14:20 +0100
Subject: [PATCH 1/4] allow for more flexibility when requesting service keytab

The service installers can now override the methods for cleaning up
stale keytabs and changing file ownership of the newly acquired keytabs.

The default actions should be usable by most installers without specific
overriding.

https://fedorahosted.org/freeipa/ticket/6638
---
 ipaserver/install/service.py | 41 ++++++++++++++++++++++++++---------------
 1 file changed, 26 insertions(+), 15 deletions(-)

diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
index b9d1ffc..80bb4bb 100644
--- a/ipaserver/install/service.py
+++ b/ipaserver/install/service.py
@@ -540,22 +540,35 @@ def _add_service_principal(self):
         except errors.DuplicateEntry:
             pass
 
+    def clean_previous_keytab(self, keytab=None):
+        if keytab is None:
+            keytab = self.keytab
+
+        self.fstore.backup_file(keytab)
+        try:
+            os.unlink(keytab)
+        except OSError:
+            pass
+
+    def set_keytab_owner(self, keytab=None, owner=None):
+        if keytab is None:
+            keytab = self.keytab
+        if owner is None:
+            owner = self.service_user
+
+        pent = pwd.getpwnam(owner)
+        os.chown(keytab, pent.pw_uid, pent.pw_gid)
+
     def run_getkeytab(self, ldap_uri, keytab, principal, retrieve=False):
         """
-        backup and remove old service keytab (if present) and fetch a new one
-        using ipa-getkeytab. This assumes that the service principal is already
-        created in LDAP. By default GSSAPI authentication is used unless:
+        retrieve service keytab using ipa-getkeytab. This assumes that the
+        service principal is already created in LDAP. By default GSSAPI
+        authentication is used unless:
             * LDAPI socket is used and effective process UID is 0, then
               autobind is used by EXTERNAL SASL mech
             * self.dm_password is not none, then DM credentials are used to
               fetch keytab
         """
-        self.fstore.backup_file(keytab)
-        try:
-            os.unlink(keytab)
-        except OSError:
-            pass
-
         args = [paths.IPA_GETKEYTAB,
                 '-k', keytab,
                 '-p', principal,
@@ -576,17 +589,15 @@ def run_getkeytab(self, ldap_uri, keytab, principal, retrieve=False):
         ipautil.run(args, nolog=nolog)
 
     def _request_service_keytab(self):
-        if any(attr is None for attr in (self.principal, self.keytab,
-                                         self.service_user)):
+        if any(attr is None for attr in (self.principal, self.keytab)):
             raise NotImplementedError(
                 "service must have defined principal "
-                "name, keytab, and username")
+                "name and keytab")
 
         self._add_service_principal()
+        self.clean_previous_keytab()
         self.run_getkeytab(self.api.env.ldap_uri, self.keytab, self.principal)
-
-        pent = pwd.getpwnam(self.keytab_user)
-        os.chown(self.keytab, pent.pw_uid, pent.pw_gid)
+        self.set_keytab_owner()
 
 
 class SimpleServiceInstance(Service):

From 54a7975465e965efc677e5e6efde2be239ac25d3 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Fri, 17 Feb 2017 14:31:55 +0100
Subject: [PATCH 2/4] Make request_service_keytab into a public method

a cosmetic change: we had private method comprising of calls to public
ones, which did not make much sense in our case

https://fedorahosted.org/freeipa/ticket/6638
---
 ipaserver/install/dsinstance.py   | 6 +++---
 ipaserver/install/httpinstance.py | 2 +-
 ipaserver/install/service.py      | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index 9172b65..bf80ae0 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -393,7 +393,7 @@ def create_replica(self, realm_name, master_fqdn, fqdn,
         self.__common_setup(enable_ssl=(not self.promote))
         self.step("restarting directory server", self.__restart_instance)
 
-        self.step("creating DS keytab", self._request_service_keytab)
+        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)
@@ -1221,8 +1221,8 @@ def __set_domain_level(self):
         if self.domainlevel is not None:
             self._ldap_mod("domainlevel.ldif", self.sub_dict)
 
-    def _request_service_keytab(self):
-        super(DsInstance, self)._request_service_keytab()
+    def request_service_keytab(self):
+        super(DsInstance, self).request_service_keytab()
 
         # Configure DS to use the keytab
         vardict = {"KRB5_KTNAME": self.keytab}
diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
index 6383e27..435130b 100644
--- a/ipaserver/install/httpinstance.py
+++ b/ipaserver/install/httpinstance.py
@@ -166,7 +166,7 @@ def create_instance(self, realm, fqdn, domain_name, pkcs12_info=None,
         self.step("enabling mod_nss renegotiate", self.enable_mod_nss_renegotiate)
         self.step("adding URL rewriting rules", self.__add_include)
         self.step("configuring httpd", self.__configure_http)
-        self.step("setting up httpd keytab", self._request_service_keytab)
+        self.step("setting up httpd keytab", self.request_service_keytab)
         self.step("retrieving anonymous keytab", self.request_anon_keytab)
         self.step("configuring Gssproxy", self.configure_gssproxy)
         self.step("setting up ssl", self.__setup_ssl)
diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
index 80bb4bb..837880f 100644
--- a/ipaserver/install/service.py
+++ b/ipaserver/install/service.py
@@ -588,7 +588,7 @@ def run_getkeytab(self, ldap_uri, keytab, principal, retrieve=False):
 
         ipautil.run(args, nolog=nolog)
 
-    def _request_service_keytab(self):
+    def request_service_keytab(self):
         if any(attr is None for attr in (self.principal, self.keytab)):
             raise NotImplementedError(
                 "service must have defined principal "

From 8cadbfedbd5264eab720ca677f7117f46dccf4f4 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Fri, 17 Feb 2017 14:33:40 +0100
Subject: [PATCH 3/4] httpinstance: re-use parent's methods to retrieve
 anonymous keytab

https://fedorahosted.org/freeipa/ticket/6638
---
 ipaserver/install/httpinstance.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
index 435130b..7979ca1 100644
--- a/ipaserver/install/httpinstance.py
+++ b/ipaserver/install/httpinstance.py
@@ -317,12 +317,15 @@ def request_anon_keytab(self):
         parent = os.path.dirname(paths.ANON_KEYTAB)
         if not os.path.exists(parent):
             os.makedirs(parent, 0o755)
+
+        self.clean_previous_keytab(keytab=paths.ANON_KEYTAB)
         self.run_getkeytab(self.api.env.ldap_uri, paths.ANON_KEYTAB, ANON_USER)
 
         pent = pwd.getpwnam(IPAAPI_USER)
         os.chmod(parent, 0o700)
         os.chown(parent, pent.pw_uid, pent.pw_gid)
-        os.chown(paths.ANON_KEYTAB, pent.pw_uid, pent.pw_gid)
+
+        self.set_keytab_owner(keytab=paths.ANON_KEYTAB, owner=IPAAPI_USER)
 
     def create_password_conf(self):
         """

From 5d0bed65fffbbf292759c4ff016647ce64cdfcd1 Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Fri, 3 Feb 2017 17:16:59 +0100
Subject: [PATCH 4/4] use the methods of the parent class to retrieve CIFS
 kerberos keys

adtrustinstance will now use parent's methods to retrieve keys for CIFS
principal. Since the keys are appended to the host keytab
(/etc/krb5.keytab) we need to make sure that only the stale CIFS keys
are purged from the file and that we do not re-set its ownership.

https://fedorahosted.org/freeipa/ticket/6638
---
 ipaserver/install/adtrustinstance.py | 30 +++++++++++-------------------
 1 file changed, 11 insertions(+), 19 deletions(-)

diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py
index c866cdd..0b18985 100644
--- a/ipaserver/install/adtrustinstance.py
+++ b/ipaserver/install/adtrustinstance.py
@@ -530,27 +530,18 @@ def __setup_group_membership(self):
             api.Backend.ldap2, self.smb_dn, "member",
             [self.cifs_agent, self.host_princ])
 
-    def __setup_principal(self):
-        try:
-            api.Command.service_add(unicode(self.principal))
-        except errors.DuplicateEntry:
-            # CIFS principal already exists, it is not the first time
-            # adtrustinstance is managed
-            # That's fine, we we'll re-extract the key again.
-            pass
-        except Exception as e:
-            self.print_msg("Cannot add CIFS service: %s" % e)
-
+    def clean_previous_keytab(self, keytab=None):
+        """
+        Purge old CIFS keys from samba and clean up samba ccache
+        """
         self.clean_samba_keytab()
         installutils.remove_ccache(paths.KRB5CC_SAMBA)
 
-        try:
-            ipautil.run(["ipa-getkeytab", "--server", self.fqdn,
-                                          "--principal", self.principal,
-                                          "-k", self.keytab])
-        except ipautil.CalledProcessError:
-            root_logger.critical("Failed to add key for %s"
-                                 % self.principal)
+    def set_keytab_owner(self, keytab=None, owner=None):
+        """
+        Do not re-set ownership of samba keytab
+        """
+        pass
 
     def clean_samba_keytab(self):
         if os.path.exists(self.keytab):
@@ -818,7 +809,8 @@ def create_instance(self):
                   self.__create_samba_domain_object)
         self.step("creating samba config registry", self.__write_smb_registry)
         self.step("writing samba config file", self.__write_smb_conf)
-        self.step("adding cifs Kerberos principal", self.__setup_principal)
+        self.step("adding cifs Kerberos principal",
+                  self.request_service_keytab)
         self.step("adding cifs and host Kerberos principals to the adtrust agents group", \
                   self.__setup_group_membership)
         self.step("check for cifs services defined on other replicas", self.__check_replica)
-- 
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