Blame SOURCES/0007-Lookup-AD-user-by-SID-and-not-by-hardcoded-username.patch

23f808
From d6d06a3a22d441fbfb208eeb63caae7aafd434b4 Mon Sep 17 00:00:00 2001
23f808
From: Rob Crittenden <rcritten@redhat.com>
23f808
Date: Thu, 8 Aug 2019 18:46:32 +0000
23f808
Subject: [PATCH 7/8] Lookup AD user by SID and not by hardcoded username
23f808
23f808
Looking up the user user as Administrator@REALM is not
23f808
portable because the administrator login name may be
23f808
localized.
23f808
---
23f808
 .travis.yml                      |  2 +-
23f808
 src/ipahealthcheck/ipa/plugin.py |  8 ++++
23f808
 src/ipahealthcheck/ipa/trust.py  | 44 +++++++++++++++----
23f808
 tests/test_ipa_trust.py          | 72 ++++++++++++++++++--------------
23f808
 4 files changed, 85 insertions(+), 41 deletions(-)
23f808
23f808
diff --git a/.travis.yml b/.travis.yml
23f808
index 16722fe..25dbf1e 100644
23f808
--- a/.travis.yml
23f808
+++ b/.travis.yml
23f808
@@ -19,4 +19,4 @@ install:
23f808
 
23f808
 script:
23f808
     - tox -epep8,flake8
23f808
-    - docker run -v ${TRAVIS_BUILD_DIR}:/root/src/ fedora:29 /bin/sh -c "dnf -y install freeipa-server tox python3-pytest; cd /root/src; tox -epy3"
23f808
+    - docker run -v ${TRAVIS_BUILD_DIR}:/root/src/ fedora:29 /bin/sh -c "dnf -y install freeipa-server freeipa-server-trust-ad tox python3-pytest; cd /root/src; tox -epy3"
23f808
diff --git a/src/ipahealthcheck/ipa/plugin.py b/src/ipahealthcheck/ipa/plugin.py
23f808
index bd95c16..34cb8c9 100644
23f808
--- a/src/ipahealthcheck/ipa/plugin.py
23f808
+++ b/src/ipahealthcheck/ipa/plugin.py
23f808
@@ -57,6 +57,14 @@ class IPARegistry(Registry):
23f808
                 logging.debug('Failed to connect to LDAP: %s', e)
23f808
             return
23f808
 
23f808
+        # This package is pulled in when the trust package is installed
23f808
+        # and is required to lookup trust users. If this is not installed
23f808
+        # then it can be inferred that trust is not enabled.
23f808
+        try:
23f808
+            import pysss_nss_idmap  # noqa: F401
23f808
+        except ImportError:
23f808
+            return
23f808
+
23f808
         roles = (
23f808
             ADtrustBasedRole(u"ad_trust_agent_server",
23f808
                              u"AD trust agent"),
23f808
diff --git a/src/ipahealthcheck/ipa/trust.py b/src/ipahealthcheck/ipa/trust.py
23f808
index 2da20c0..6c5978d 100644
23f808
--- a/src/ipahealthcheck/ipa/trust.py
23f808
+++ b/src/ipahealthcheck/ipa/trust.py
23f808
@@ -16,6 +16,12 @@ from ipaplatform.paths import paths
23f808
 from ipapython import ipautil
23f808
 from ipapython.dn import DN
23f808
 
23f808
+try:
23f808
+    import pysss_nss_idmap
23f808
+except ImportError:
23f808
+    # agent and controller will be set to False in init, all tests will
23f808
+    # be skipped
23f808
+    pass
23f808
 try:
23f808
     from ipaserver.masters import ENABLED_SERVICE
23f808
 except ImportError:
23f808
@@ -33,13 +39,19 @@ def get_trust_domains():
23f808
     Get the list of AD trust domains from IPA
23f808
 
23f808
     The caller is expected to catch any exceptions.
23f808
+
23f808
+    Each entry is a dictionary representating an AD domain.
23f808
     """
23f808
     result = api.Command.trust_find()
23f808
     results = result['result']
23f808
     trust_domains = []
23f808
     for result in results:
23f808
         if result.get('trusttype')[0] == 'Active Directory domain':
23f808
-            trust_domains.append(result.get('cn')[0])
23f808
+            domain = dict()
23f808
+            domain['domain'] = result.get('cn')[0]
23f808
+            domain['domainsid'] = result.get('ipanttrusteddomainsid')[0]
23f808
+            domain['netbios'] = result.get('ipantflatname')[0]
23f808
+            trust_domains.append(domain)
23f808
     return trust_domains
23f808
 
23f808
 
23f808
@@ -123,14 +135,17 @@ class IPATrustDomainsCheck(IPAPlugin):
23f808
         if 'implicit_files' in sssd_domains:
23f808
             sssd_domains.remove('implicit_files')
23f808
 
23f808
+        trust_domains = []
23f808
         try:
23f808
-            trust_domains = get_trust_domains()
23f808
+            domains = get_trust_domains()
23f808
         except Exception as e:
23f808
             yield Result(self, constants.WARNING,
23f808
                          key='trust-find',
23f808
                          error=str(e),
23f808
                          msg='Execution of {key} failed: {error}')
23f808
-            trust_domains = []
23f808
+        else:
23f808
+            for entry in domains:
23f808
+                trust_domains.append(entry.get('domain'))
23f808
 
23f808
         if api.env.domain in sssd_domains:
23f808
             sssd_domains.remove(api.env.domain)
23f808
@@ -204,17 +219,28 @@ class IPATrustCatalogCheck(IPAPlugin):
23f808
                          msg='Execution of {key} failed: {error}')
23f808
             trust_domains = []
23f808
 
23f808
-        for domain in trust_domains:
23f808
+        for trust_domain in trust_domains:
23f808
+            sid = trust_domain.get('domainsid')
23f808
             try:
23f808
-                ipautil.run(['/bin/id', "Administrator@%s" % domain],
23f808
-                            capture_output=True)
23f808
+                id = pysss_nss_idmap.getnamebysid(sid + '-500')
23f808
             except Exception as e:
23f808
-                yield Result(self, constants.WARNING,
23f808
-                             key='/bin/id',
23f808
+                yield Result(self, constants.ERROR,
23f808
+                             key=sid,
23f808
                              error=str(e),
23f808
-                             msg='Execution of {key} failed: {error}')
23f808
+                             msg='Look up of{key} failed: {error}')
23f808
                 continue
23f808
 
23f808
+            if not id:
23f808
+                yield Result(self, constants.WARNING,
23f808
+                             key=sid,
23f808
+                             error='returned nothing',
23f808
+                             msg='Look up of {key} {error}')
23f808
+            else:
23f808
+                yield Result(self, constants.SUCCESS,
23f808
+                             key='Domain Security Identifier',
23f808
+                             sid=sid)
23f808
+
23f808
+            domain = trust_domain.get('domain')
23f808
             args = [paths.SSSCTL, "domain-status", domain, "--active-server"]
23f808
             try:
23f808
                 result = ipautil.run(args, capture_output=True)
23f808
diff --git a/tests/test_ipa_trust.py b/tests/test_ipa_trust.py
23f808
index 0a1d58c..89d3bff 100644
23f808
--- a/tests/test_ipa_trust.py
23f808
+++ b/tests/test_ipa_trust.py
23f808
@@ -261,12 +261,14 @@ class TestTrustDomains(BaseTest):
23f808
                 {
23f808
                     'cn': ['ad.example'],
23f808
                     'ipantflatname': ['ADROOT'],
23f808
-                    "trusttype": ["Active Directory domain"],
23f808
+                    'ipanttrusteddomainsid': ['S-1-5-21-abc'],
23f808
+                    'trusttype': ['Active Directory domain'],
23f808
                 },
23f808
                 {
23f808
                     'cn': ['child.example'],
23f808
                     'ipantflatname': ['ADROOT'],
23f808
-                    "trusttype": ["Active Directory domain"],
23f808
+                    'ipanttrusteddomainsid': ['S-1-5-21-def'],
23f808
+                    'trusttype': ['Active Directory domain'],
23f808
                 },
23f808
             ]
23f808
         }]
23f808
@@ -324,12 +326,14 @@ class TestTrustDomains(BaseTest):
23f808
                 {
23f808
                     'cn': ['ad.example'],
23f808
                     'ipantflatname': ['ADROOT'],
23f808
-                    "trusttype": ["Active Directory domain"],
23f808
+                    'ipanttrusteddomainsid': ['S-1-5-21-abc'],
23f808
+                    'trusttype': ['Active Directory domain'],
23f808
                 },
23f808
                 {
23f808
                     'cn': ['child.example'],
23f808
                     'ipantflatname': ['ADROOT'],
23f808
-                    "trusttype": ["Active Directory domain"],
23f808
+                    'ipanttrusteddomainsid': ['S-1-5-21-def'],
23f808
+                    'trusttype': ['Active Directory domain'],
23f808
                 },
23f808
             ]
23f808
         }]
23f808
@@ -373,41 +377,27 @@ class TestTrustCatalog(BaseTest):
23f808
         # Zero because the call was skipped altogether
23f808
         assert len(self.results) == 0
23f808
 
23f808
+    @patch('pysss_nss_idmap.getnamebysid')
23f808
     @patch('ipapython.ipautil.run')
23f808
-    def test_trust_catalog_ok(self, mock_run):
23f808
+    def test_trust_catalog_ok(self, mock_run, mock_getnamebysid):
23f808
         # id Administrator@ad.example
23f808
-        idresult = namedtuple('run', ['returncode', 'error_log'])
23f808
-        idresult.returncode = 0
23f808
-        idresult.error_log = ''
23f808
-        idresult.output = '797600500(administrator@ad.example),' \
23f808
-            '1797600520(group policy creator owners@ad.example),' \
23f808
-            '1797600519(enterprise admins@ad.example),' \
23f808
-            '1797600512(domain admins@ad.example),' \
23f808
-            '1797600518(schema admins@ad.example)' \
23f808
-            ',1797600513(domain users@ad.example)\n'
23f808
         dsresult = namedtuple('run', ['returncode', 'error_log'])
23f808
         dsresult.returncode = 0
23f808
         dsresult.error_log = ''
23f808
         dsresult.output = 'Active servers:\nAD Global Catalog: ' \
23f808
             'root-dc.ad.vm\nAD Domain Controller: root-dc.ad.vm\n' \
23f808
             'IPA: master.ipa.vm\n\n'
23f808
-        # id Administrator@client.example
23f808
-        id2result = namedtuple('run', ['returncode', 'error_log'])
23f808
-        id2result.returncode = 0
23f808
-        id2result.error_log = ''
23f808
-        id2result.output = '797600500(administrator@client.example),' \
23f808
-            '1797600520(group policy creator owners@client.example),' \
23f808
-            '1797600519(enterprise admins@client.example),' \
23f808
-            '1797600512(domain admins@client.example),' \
23f808
-            '1797600518(schema admins@client.example)' \
23f808
-            ',1797600513(domain users@client.example)\n'
23f808
         ds2result = namedtuple('run', ['returncode', 'error_log'])
23f808
         ds2result.returncode = 0
23f808
         ds2result.error_log = ''
23f808
         ds2result.output = 'Active servers:\nAD Global Catalog: ' \
23f808
             'root-dc.ad.vm\nAD Domain Controller: root-dc.ad.vm\n' \
23f808
 
23f808
-        mock_run.side_effect = [idresult, dsresult, id2result, ds2result]
23f808
+        mock_run.side_effect = [dsresult, ds2result]
23f808
+        mock_getnamebysid.side_effect = [
23f808
+           {'S-1-5-21-abc-500': {'name': 'admin@ad.example', 'type': 3}},
23f808
+           {'S-1-5-21-def-500': {'name': 'admin@child.example', 'type': 3}}
23f808
+        ]
23f808
 
23f808
         # get_trust_domains()
23f808
         m_api.Command.trust_find.side_effect = [{
23f808
@@ -415,12 +405,14 @@ class TestTrustCatalog(BaseTest):
23f808
                 {
23f808
                     'cn': ['ad.example'],
23f808
                     'ipantflatname': ['ADROOT'],
23f808
-                    "trusttype": ["Active Directory domain"],
23f808
+                    'ipanttrusteddomainsid': ['S-1-5-21-abc'],
23f808
+                    'trusttype': ['Active Directory domain'],
23f808
                 },
23f808
                 {
23f808
                     'cn': ['child.example'],
23f808
                     'ipantflatname': ['ADROOT'],
23f808
-                    "trusttype": ["Active Directory domain"],
23f808
+                    'ipanttrusteddomainsid': ['S-1-5-21-def'],
23f808
+                    'trusttype': ['Active Directory domain'],
23f808
                 },
23f808
             ]
23f808
         }]
23f808
@@ -433,31 +425,49 @@ class TestTrustCatalog(BaseTest):
23f808
         f.config = config.Config()
23f808
         self.results = capture_results(f)
23f808
 
23f808
-        assert len(self.results) == 4
23f808
+        assert len(self.results) == 6
23f808
 
23f808
         result = self.results.results[0]
23f808
         assert result.result == constants.SUCCESS
23f808
         assert result.source == 'ipahealthcheck.ipa.trust'
23f808
         assert result.check == 'IPATrustCatalogCheck'
23f808
-        assert result.kw.get('key') == 'AD Global Catalog'
23f808
+        assert result.kw.get('key') == 'Domain Security Identifier'
23f808
+        assert result.kw.get('sid') == 'S-1-5-21-abc'
23f808
 
23f808
         result = self.results.results[1]
23f808
         assert result.result == constants.SUCCESS
23f808
         assert result.source == 'ipahealthcheck.ipa.trust'
23f808
         assert result.check == 'IPATrustCatalogCheck'
23f808
-        assert result.kw.get('key') == 'AD Domain Controller'
23f808
+        assert result.kw.get('key') == 'AD Global Catalog'
23f808
+        assert result.kw.get('domain') == 'ad.example'
23f808
 
23f808
         result = self.results.results[2]
23f808
         assert result.result == constants.SUCCESS
23f808
         assert result.source == 'ipahealthcheck.ipa.trust'
23f808
         assert result.check == 'IPATrustCatalogCheck'
23f808
+        assert result.kw.get('key') == 'AD Domain Controller'
23f808
+        assert result.kw.get('domain') == 'ad.example'
23f808
+
23f808
+        result = self.results.results[3]
23f808
+        assert result.result == constants.SUCCESS
23f808
+        assert result.source == 'ipahealthcheck.ipa.trust'
23f808
+        assert result.check == 'IPATrustCatalogCheck'
23f808
+        assert result.kw.get('key') == 'Domain Security Identifier'
23f808
+        assert result.kw.get('sid') == 'S-1-5-21-def'
23f808
+
23f808
+        result = self.results.results[4]
23f808
+        assert result.result == constants.SUCCESS
23f808
+        assert result.source == 'ipahealthcheck.ipa.trust'
23f808
+        assert result.check == 'IPATrustCatalogCheck'
23f808
         assert result.kw.get('key') == 'AD Global Catalog'
23f808
+        assert result.kw.get('domain') == 'child.example'
23f808
 
23f808
-        result = self.results.results[1]
23f808
+        result = self.results.results[5]
23f808
         assert result.result == constants.SUCCESS
23f808
         assert result.source == 'ipahealthcheck.ipa.trust'
23f808
         assert result.check == 'IPATrustCatalogCheck'
23f808
         assert result.kw.get('key') == 'AD Domain Controller'
23f808
+        assert result.kw.get('domain') == 'child.example'
23f808
 
23f808
 
23f808
 class Testsidgen(BaseTest):
23f808
-- 
23f808
2.20.1
23f808