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