590d18
From df641e93d2f88f642f476ad8c5b7313bdfce8d9e Mon Sep 17 00:00:00 2001
590d18
From: Tomas Babej <tbabej@redhat.com>
590d18
Date: Thu, 6 Aug 2015 10:10:04 +0200
590d18
Subject: [PATCH] trusts: Detect missing Samba instance
590d18
590d18
In the event of invocation of trust related commands, IPA server needs to
590d18
contact local Samba instance. This is not possible on servers that
590d18
merely act as AD trust agents, since they do not have Samba instance
590d18
running.
590d18
590d18
Properly detect the absence of the Samba instance and output
590d18
user-friendly
590d18
message which includes list of servers that are capable of running
590d18
the command, if such exist.
590d18
590d18
List of commands affected:
590d18
* ipa trust-add
590d18
* ipa trust-fetch-domains
590d18
* all of the trustdomain commands available via CLI
590d18
590d18
https://fedorahosted.org/freeipa/ticket/5165
590d18
590d18
Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
590d18
---
590d18
 ipalib/plugins/trust.py | 99 +++++++++++++++++++++++++++++++++++++++----------
590d18
 1 file changed, 79 insertions(+), 20 deletions(-)
590d18
590d18
diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py
590d18
index 0bb5e6558b680ac1acad44461d78a571098c7b25..c7546692bdd8dd827ee9772b72a758042d97aa71 100644
590d18
--- a/ipalib/plugins/trust.py
590d18
+++ b/ipalib/plugins/trust.py
590d18
@@ -199,6 +199,73 @@ def make_trust_dn(env, trust_type, dn):
590d18
         return DN(dn, container_dn)
590d18
     return dn
590d18
 
590d18
+def find_adtrust_masters(ldap, api):
590d18
+    """
590d18
+    Returns a list of names of IPA servers with ADTRUST component configured.
590d18
+    """
590d18
+
590d18
+    try:
590d18
+        entries, truncated = ldap.find_entries(
590d18
+                "cn=ADTRUST",
590d18
+                base_dn=api.env.container_masters + api.env.basedn
590d18
+        )
590d18
+    except errors.NotFound:
590d18
+        entries = []
590d18
+
590d18
+    return [entry.dn[1].value for entry in entries]
590d18
+
590d18
+def verify_samba_component_presence(ldap, api):
590d18
+    """
590d18
+    Verifies that Samba is installed and configured on this particular master.
590d18
+    If Samba is not available, provide a heplful hint with the list of masters
590d18
+    capable of running the commands.
590d18
+    """
590d18
+
590d18
+    adtrust_present = api.Command['adtrust_is_enabled']()['result']
590d18
+
590d18
+    hint = _(
590d18
+        ' Alternatively, following servers are capable of running this '
590d18
+        'command: %(masters)s'
590d18
+        )
590d18
+
590d18
+    def raise_missing_component_error(message):
590d18
+        masters_with_adtrust = find_adtrust_masters(ldap, api)
590d18
+
590d18
+        # If there are any masters capable of running Samba requiring commands
590d18
+        # let's advertise them directly
590d18
+        if masters_with_adtrust:
590d18
+            message += hint % dict(masters=', '.join(masters_with_adtrust))
590d18
+
590d18
+        raise errors.NotFound(
590d18
+            name=_('AD Trust setup'),
590d18
+            reason=message,
590d18
+        )
590d18
+
590d18
+    # We're ok in this case, bail out
590d18
+    if adtrust_present and _bindings_installed:
590d18
+        return
590d18
+
590d18
+    # First check for packages missing
590d18
+    elif not _bindings_installed:
590d18
+        error_message=_(
590d18
+            'Cannot perform the selected command without Samba 4 support '
590d18
+            'installed. Make sure you have installed server-trust-ad '
590d18
+            'sub-package of IPA.'
590d18
+        )
590d18
+
590d18
+        raise_missing_component_error(error_message)
590d18
+
590d18
+    # Packages present, but ADTRUST instance is not configured
590d18
+    elif not adtrust_present:
590d18
+        error_message=_(
590d18
+            'Cannot perform the selected command without Samba 4 instance '
590d18
+            'configured on this machine. Make sure you have run '
590d18
+            'ipa-adtrust-install on this server.'
590d18
+        )
590d18
+
590d18
+        raise_missing_component_error(error_message)
590d18
+
590d18
+
590d18
 def generate_creds(trustinstance, style, **options):
590d18
     """
590d18
     Generate string representing credentials using trust instance
590d18
@@ -554,6 +621,10 @@ sides.
590d18
     has_output_params = LDAPCreate.has_output_params + trust_output_params
590d18
 
590d18
     def execute(self, *keys, **options):
590d18
+        ldap = self.obj.backend
590d18
+
590d18
+        verify_samba_component_presence(ldap, self.api)
590d18
+
590d18
         full_join = self.validate_options(*keys, **options)
590d18
         old_range, range_name, dom_sid = self.validate_range(*keys, **options)
590d18
         result = self.execute_ad(full_join, *keys, **options)
590d18
@@ -569,7 +640,6 @@ sides.
590d18
             created_range_type = old_range['result']['iparangetype'][0]
590d18
 
590d18
         trust_filter = "cn=%s" % result['value']
590d18
-        ldap = self.obj.backend
590d18
         (trusts, truncated) = ldap.find_entries(
590d18
                          base_dn=DN(self.api.env.container_trusts, self.api.env.basedn),
590d18
                          filter=trust_filter)
590d18
@@ -642,16 +712,6 @@ sides.
590d18
     def validate_options(self, *keys, **options):
590d18
         trusted_realm_domain = keys[-1]
590d18
 
590d18
-        if not _bindings_installed:
590d18
-            raise errors.NotFound(
590d18
-                name=_('AD Trust setup'),
590d18
-                reason=_(
590d18
-                    'Cannot perform join operation without Samba 4 support '
590d18
-                    'installed. Make sure you have installed server-trust-ad '
590d18
-                    'sub-package of IPA'
590d18
-                )
590d18
-            )
590d18
-
590d18
         if not _murmur_installed and 'base_id' not in options:
590d18
             raise errors.ValidationError(
590d18
                 name=_('missing base_id'),
590d18
@@ -1398,6 +1458,9 @@ class trustdomain_del(LDAPDelete):
590d18
     msg_summary = _('Removed information about the trusted domain "%(value)s"')
590d18
 
590d18
     def execute(self, *keys, **options):
590d18
+        ldap = self.api.Backend.ldap2
590d18
+        verify_samba_component_presence(ldap, self.api)
590d18
+
590d18
         # Note that pre-/post- callback handling for LDAPDelete is causing pre_callback
590d18
         # to always receive empty keys. We need to catch the case when root domain is being deleted
590d18
 
590d18
@@ -1470,15 +1533,9 @@ class trust_fetch_domains(LDAPRetrieve):
590d18
     )
590d18
 
590d18
     def execute(self, *keys, **options):
590d18
-        if not _bindings_installed:
590d18
-            raise errors.NotFound(
590d18
-                name=_('AD Trust setup'),
590d18
-                reason=_(
590d18
-                    'Cannot perform join operation without Samba 4 support '
590d18
-                    'installed. Make sure you have installed server-trust-ad '
590d18
-                    'sub-package of IPA'
590d18
-                )
590d18
-            )
590d18
+        ldap = self.api.Backend.ldap2
590d18
+        verify_samba_component_presence(ldap, self.api)
590d18
+
590d18
         trust = self.api.Command.trust_show(keys[0], raw=True)['result']
590d18
 
590d18
         result = dict()
590d18
@@ -1524,6 +1581,7 @@ class trustdomain_enable(LDAPQuery):
590d18
 
590d18
     def execute(self, *keys, **options):
590d18
         ldap = self.api.Backend.ldap2
590d18
+        verify_samba_component_presence(ldap, self.api)
590d18
 
590d18
         if keys[0].lower() == keys[1].lower():
590d18
             raise errors.ValidationError(name='domain',
590d18
@@ -1564,6 +1622,7 @@ class trustdomain_disable(LDAPQuery):
590d18
 
590d18
     def execute(self, *keys, **options):
590d18
         ldap = self.api.Backend.ldap2
590d18
+        verify_samba_component_presence(ldap, self.api)
590d18
 
590d18
         if keys[0].lower() == keys[1].lower():
590d18
             raise errors.ValidationError(name='domain',
590d18
-- 
590d18
2.4.3
590d18