diff --git a/.gitignore b/.gitignore index 6bddb01..487a6ec 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/0.12.tar.gz +SOURCES/0.16.tar.gz diff --git a/.ipa-healthcheck.metadata b/.ipa-healthcheck.metadata index ee30a78..9650b1d 100644 --- a/.ipa-healthcheck.metadata +++ b/.ipa-healthcheck.metadata @@ -1 +1 @@ -dc05dc0ca441dcb1a87e3b3bd7d440d79c17ac0a SOURCES/0.12.tar.gz +b6edbda881bceb9e0266169e06eb35984b1a7a77 SOURCES/0.16.tar.gz diff --git a/SOURCES/0001-Remove-ipaclustercheck.patch b/SOURCES/0001-Remove-ipaclustercheck.patch index 040236d..2118a27 100644 --- a/SOURCES/0001-Remove-ipaclustercheck.patch +++ b/SOURCES/0001-Remove-ipaclustercheck.patch @@ -1,6 +1,6 @@ -From 9d5f9d21442ee483044fc55a5c02039af23869d7 Mon Sep 17 00:00:00 2001 +From 378e0a353e670a6b498d454558a9139a859890d4 Mon Sep 17 00:00:00 2001 From: Rob Crittenden -Date: Thu, 1 Dec 2022 14:22:46 -0500 +Date: Thu, 9 Nov 2023 10:49:05 -0500 Subject: [PATCH] Remove ipaclustercheck --- @@ -26,13 +26,13 @@ Subject: [PATCH] Remove ipaclustercheck delete mode 100644 tests/test_cluster_ruv.py diff --git a/setup.py b/setup.py -index 0cfa486..b9e1ca1 100644 +index d926302..cb6265a 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ from setuptools import find_packages, setup setup( name='ipahealthcheck', - version='0.12', + version='0.16', - namespace_packages=['ipahealthcheck', 'ipaclustercheck'], + namespace_packages=['ipahealthcheck'], package_dir={'': 'src'}, diff --git a/SOURCES/0002-Disable-two-failing-tests.patch b/SOURCES/0002-Disable-two-failing-tests.patch deleted file mode 100644 index 6abba0f..0000000 --- a/SOURCES/0002-Disable-two-failing-tests.patch +++ /dev/null @@ -1,64 +0,0 @@ -From d2cd8292d8a1d7c2fd2a5f978f8ed76c0769e5e9 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Tue, 8 Feb 2022 14:16:06 -0500 -Subject: [PATCH] Disable two failing tests - -These test that healthcheck can properly detect when IPA -is not installed or configured. Its not ideal to remove them -from the check process but they aren't critical. ---- - tests/test_commands.py | 41 ----------------------------------------- - 1 file changed, 41 deletions(-) - -diff --git a/tests/test_commands.py b/tests/test_commands.py -index 988d7fc..e14114b 100644 ---- a/tests/test_commands.py -+++ b/tests/test_commands.py -@@ -14,44 +14,3 @@ def test_version(): - """ - output = run(['ipa-healthcheck', '--version'], env=os.environ) - assert 'ipahealthcheck' in output.raw_output.decode('utf-8') -- -- --@pytest.fixture --def python_ipalib_dir(tmpdir): -- ipalib_dir = tmpdir.mkdir("ipalib") -- ipalib_dir.join("__init__.py").write("") -- -- def _make_facts(configured=None): -- if configured is None: -- module_text = "" -- elif isinstance(configured, bool): -- module_text = f"def is_ipa_configured(): return {configured}" -- else: -- raise TypeError( -- f"'configured' must be None or bool, got '{configured!r}'" -- ) -- -- ipalib_dir.join("facts.py").write(module_text) -- return str(tmpdir) -- -- return _make_facts -- -- --def test_ipa_notinstalled(python_ipalib_dir, monkeypatch): -- """ -- Test ipa-healthcheck handles the missing IPA stuff -- """ -- monkeypatch.setenv("PYTHONPATH", python_ipalib_dir(configured=None)) -- output = run(["ipa-healthcheck"], raiseonerr=False, env=os.environ) -- assert output.returncode == 1 -- assert "IPA server is not installed" in output.raw_output.decode("utf-8") -- -- --def test_ipa_unconfigured(python_ipalib_dir, monkeypatch): -- """ -- Test ipa-healthcheck handles the unconfigured IPA server -- """ -- monkeypatch.setenv("PYTHONPATH", python_ipalib_dir(configured=False)) -- output = run(["ipa-healthcheck"], raiseonerr=False, env=os.environ) -- assert output.returncode == 1 -- assert "IPA server is not configured" in output.raw_output.decode("utf-8") --- -2.31.1 - diff --git a/SOURCES/0002-Don-t-fail-if-a-service-name-cannot-be-looked-up-in-.patch b/SOURCES/0002-Don-t-fail-if-a-service-name-cannot-be-looked-up-in-.patch new file mode 100644 index 0000000..5233083 --- /dev/null +++ b/SOURCES/0002-Don-t-fail-if-a-service-name-cannot-be-looked-up-in-.patch @@ -0,0 +1,44 @@ +From 35ff77300758c12110132d6d638802d5b223bd6d Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Mon, 13 Nov 2023 14:09:16 -0500 +Subject: [PATCH] Don't fail if a service name cannot be looked up in LDAP + +A new method was introduced to handle more IPA services. This +requires looking some of them up in LDAP. dirsrv not running +was not being caught so raised an error instead. + +Fixes: https://github.com/freeipa/freeipa-healthcheck/issues/312 + +Signed-off-by: Rob Crittenden +--- + src/ipahealthcheck/meta/services.py | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/src/ipahealthcheck/meta/services.py b/src/ipahealthcheck/meta/services.py +index 10fa83f..9838128 100644 +--- a/src/ipahealthcheck/meta/services.py ++++ b/src/ipahealthcheck/meta/services.py +@@ -25,10 +25,18 @@ class IPAServiceCheck(ServiceCheck): + def get_service_name(self, role): + """Roles define broad services. Translate a role name into + an individual service name. ++ ++ Returns a string on success, None if the service is not ++ configured or cannot be determined. + """ + conn = api.Backend.ldap2 +- if not api.Backend.ldap2.isconnected(): +- api.Backend.ldap2.connect() ++ try: ++ if not api.Backend.ldap2.isconnected(): ++ api.Backend.ldap2.connect() ++ except errors.NetworkError: ++ logger.debug("Service '%s' is not running", self.service_name) ++ return None ++ + dn = DN( + ("cn", role), ("cn", api.env.host), + ("cn", "masters"), ("cn", "ipa"), ("cn", "etc"), +-- +2.41.0 + diff --git a/SOURCES/0003-Skip-AD-domains-with-posix-ranges-in-the-catalog-che.patch b/SOURCES/0003-Skip-AD-domains-with-posix-ranges-in-the-catalog-che.patch deleted file mode 100644 index 0b20f70..0000000 --- a/SOURCES/0003-Skip-AD-domains-with-posix-ranges-in-the-catalog-che.patch +++ /dev/null @@ -1,340 +0,0 @@ -From 30471ebdc9fe5871c115ca06f78a415275a320e6 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Thu, 16 Jun 2022 20:02:51 +0000 -Subject: [PATCH] Skip AD domains with posix ranges in the catalog check - -The catalog check is intended to ensure that the trust is -working by looking up a user. For a non-posix range we can use -the Administrator user because it has a predicible SID. - -With a posix range the UID/GID may not be set so the lookup -can fail (with an empty return value). - -So skip domain which have a posix range associated with it. - -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1775199 - -Signed-off-by: Rob Crittenden ---- - src/ipahealthcheck/ipa/trust.py | 34 ++++- - tests/test_ipa_trust.py | 214 +++++++++++++++++++++++++++++++- - 2 files changed, 243 insertions(+), 5 deletions(-) - -diff --git a/src/ipahealthcheck/ipa/trust.py b/src/ipahealthcheck/ipa/trust.py -index 27a2c86..b962807 100644 ---- a/src/ipahealthcheck/ipa/trust.py -+++ b/src/ipahealthcheck/ipa/trust.py -@@ -183,6 +183,7 @@ class IPATrustDomainsCheck(IPAPlugin): - except Exception as e: - yield Result(self, constants.WARNING, - key='domain-status', -+ domain=domain, - error=str(e), - msg='Execution of {key} failed: {error}') - continue -@@ -262,6 +263,10 @@ class IPATrustCatalogCheck(IPAPlugin): - This should populate the 'AD Global catalog' and 'AD Domain Controller' - fields in 'sssctl domain-status' output (means SSSD actually talks to AD - DCs) -+ -+ If the associated idrange type is ipa-ad-trust-posix then the -+ check will be skipped because we can't predict what the UID of the -+ Administrator account will be. - """ - @duration - def check(self): -@@ -280,20 +285,41 @@ class IPATrustCatalogCheck(IPAPlugin): - - for trust_domain in trust_domains: - sid = trust_domain.get('domainsid') -+ domain = trust_domain['domain'] -+ idrange = api.Command.idrange_find(sid) -+ if len(idrange['result']) == 0: -+ yield Result(self, constants.WARNING, -+ key=sid, -+ domain=domain, -+ msg='Domain {domain} does not have an idrange') -+ continue -+ -+ if 'ipa-ad-trust-posix' in idrange['result'][0]['iparangetyperaw']: -+ yield Result(self, constants.SUCCESS, -+ key=sid, -+ domain=domain, -+ type='ipa-ad-trust-posix') -+ logger.debug("Domain %s is a POSIX range, skip the lookup", -+ domain) -+ continue -+ - try: - id = pysss_nss_idmap.getnamebysid(sid + '-500') - except Exception as e: - yield Result(self, constants.ERROR, -- key=sid, -+ key=id, -+ domain=domain, - error=str(e), -- msg='Look up of{key} failed: {error}') -+ msg='Look up of ID {key} for {domain} failed: ' -+ '{error}') - continue - - if not id: - yield Result(self, constants.WARNING, -- key=sid, -+ key=id, -+ domain=trust_domain['domain'], - error='returned nothing', -- msg='Look up of {key} {error}') -+ msg='Look up of ID {key} for {domain} {error}') - else: - yield Result(self, constants.SUCCESS, - key='Domain Security Identifier', -diff --git a/tests/test_ipa_trust.py b/tests/test_ipa_trust.py -index c314b70..6c4754a 100644 ---- a/tests/test_ipa_trust.py -+++ b/tests/test_ipa_trust.py -@@ -129,6 +129,74 @@ def trustdomain_find(): - ] - - -+def idrange_find_adrange_type(): -+ """ -+ Return a set of idranges of type "Active Directory domain range" -+ """ -+ -+ return { -+ "result": [ -+ { -+ "cn": ["AD.EXAMPLE_id_range"], -+ "ipabaseid": ["1664000000"], -+ "ipabaserid": ["0"], -+ "ipaidrangesize": ["200000"], -+ "ipanttrusteddomainsid": ["S-1-5-21-abc"], -+ "iparangetype": ["Active Directory domain range"], -+ "iparangetyperaw": ["ipa-ad-trust"] -+ }, -+ { -+ "cn": ["CHILD.AD.EXAMPLE_id_range"], -+ "ipabaseid": ["538600000"], -+ "ipabaserid": ["0"], -+ "ipaidrangesize": ["200000"], -+ "ipanttrusteddomainsid": [ -+ "S-1-5-21-38045160-610119595-3099869984" -+ ], -+ "iparangetype": ["Active Directory domain range"], -+ "iparangetyperaw": ["ipa-ad-trust"] -+ }, -+ { -+ "cn": ["IPA.EXAMPLE_id_range"], -+ "ipabaseid": ["447400000"], -+ "ipabaserid": ["1000"], -+ "ipaidrangesize": ["200000"], -+ "iparangetype": ["local domain range"], -+ "iparangetyperaw": ["ipa-local"], -+ "ipasecondarybaserid": ["100000000"] -+ }] -+ } -+ -+ -+def idrange_find_adrange_posix(): -+ """ -+ Return a set of idranges of type -+ "Active Directory trust range with POSIX attributes" -+ """ -+ -+ return { -+ "result": [ -+ { -+ "cn": ["AD.EXAMPLE_id_range"], -+ "ipabaseid": ["1664000000"], -+ "ipaidrangesize": ["200000"], -+ "ipanttrusteddomainsid": ["S-1-5-21-abc"], -+ "iparangetype": [ -+ "Active Directory trust range with POSIX attributes"], -+ "iparangetyperaw": ["ipa-ad-trust-posix"] -+ }, -+ { -+ "cn": ["IPA.EXAMPLE_id_range"], -+ "ipabaseid": ["447400000"], -+ "ipabaserid": ["1000"], -+ "ipaidrangesize": ["200000"], -+ "iparangetype": ["local domain range"], -+ "iparangetyperaw": ["ipa-local"], -+ "ipasecondarybaserid": ["100000000"] -+ }] -+ } -+ -+ - class SSSDDomain: - def __init__(self, return_ipa_server_mode=True, provider='ipa'): - self.return_ipa_server_mode = return_ipa_server_mode -@@ -454,7 +522,8 @@ class TestTrustCatalog(BaseTest): - - @patch('pysss_nss_idmap.getnamebysid') - @patch('ipapython.ipautil.run') -- def test_trust_catalog_ok(self, mock_run, mock_getnamebysid): -+ def test_trust_catalog_adrange(self, mock_run, mock_getnamebysid): -+ """The associated ID ranges are Active Directory domain range""" - # id Administrator@ad.example - dsresult = namedtuple('run', ['returncode', 'error_log']) - dsresult.returncode = 0 -@@ -478,6 +547,11 @@ class TestTrustCatalog(BaseTest): - # get_trust_domains() - m_api.Command.trust_find.side_effect = trust_find() - m_api.Command.trustdomain_find.side_effect = trustdomain_find() -+ m_api.Command.idrange_find.side_effect = [ -+ idrange_find_adrange_type(), -+ idrange_find_adrange_type(), -+ idrange_find_adrange_type() -+ ] - - framework = object() - registry.initialize(framework, config.Config) -@@ -550,6 +624,144 @@ class TestTrustCatalog(BaseTest): - assert result.kw.get('key') == 'AD Domain Controller' - assert result.kw.get('domain') == 'child.example' - -+ @patch('pysss_nss_idmap.getnamebysid') -+ @patch('ipapython.ipautil.run') -+ def test_trust_catalog_posix(self, mock_run, mock_getnamebysid): -+ """AD POSIX ranges""" -+ # id Administrator@ad.example -+ dsresult = namedtuple('run', ['returncode', 'error_log']) -+ dsresult.returncode = 0 -+ dsresult.error_log = '' -+ dsresult.output = 'Active servers:\nAD Global Catalog: ' \ -+ 'root-dc.ad.vm\nAD Domain Controller: root-dc.ad.vm\n' \ -+ 'IPA: master.ipa.vm\n\n' -+ ds2result = namedtuple('run', ['returncode', 'error_log']) -+ ds2result.returncode = 0 -+ ds2result.error_log = '' -+ ds2result.output = 'Active servers:\nAD Global Catalog: ' \ -+ 'root-dc.ad.vm\nAD Domain Controller: root-dc.ad.vm\n' \ -+ -+ mock_run.side_effect = [dsresult, dsresult, ds2result] -+ mock_getnamebysid.side_effect = [ -+ {'S-1-5-21-abc-500': {'name': 'admin@ad.example', 'type': 3}}, -+ {'S-1-5-21-ghi-500': {'name': 'admin@child.ad.example', 'type': 3}}, -+ {'S-1-5-21-def-500': {'name': 'admin@child.example', 'type': 3}} -+ ] -+ -+ # get_trust_domains() -+ m_api.Command.trust_find.side_effect = trust_find() -+ m_api.Command.trustdomain_find.side_effect = trustdomain_find() -+ m_api.Command.idrange_find.side_effect = [ -+ idrange_find_adrange_posix(), -+ idrange_find_adrange_posix(), -+ idrange_find_adrange_posix() -+ ] -+ -+ framework = object() -+ registry.initialize(framework, config.Config) -+ registry.trust_agent = True -+ f = IPATrustCatalogCheck(registry) -+ -+ self.results = capture_results(f) -+ -+ assert len(self.results) == 3 -+ -+ result = self.results.results[0] -+ assert result.result == constants.SUCCESS -+ assert result.source == 'ipahealthcheck.ipa.trust' -+ assert result.check == 'IPATrustCatalogCheck' -+ assert result.kw.get('key') == 'S-1-5-21-abc' -+ assert result.kw.get('domain') == 'ad.example' -+ assert result.kw.get('type') == 'ipa-ad-trust-posix' -+ -+ result = self.results.results[1] -+ assert result.result == constants.SUCCESS -+ assert result.source == 'ipahealthcheck.ipa.trust' -+ assert result.check == 'IPATrustCatalogCheck' -+ assert result.kw.get('key') == 'S-1-5-22-def' -+ assert result.kw.get('domain') == 'child.ad.example' -+ assert result.kw.get('type') == 'ipa-ad-trust-posix' -+ -+ result = self.results.results[2] -+ assert result.result == constants.SUCCESS -+ assert result.source == 'ipahealthcheck.ipa.trust' -+ assert result.check == 'IPATrustCatalogCheck' -+ assert result.kw.get('key') == 'S-1-5-21-ghi' -+ assert result.kw.get('domain') == 'child.example' -+ assert result.kw.get('type') == 'ipa-ad-trust-posix' -+ -+ @patch('pysss_nss_idmap.getnamebysid') -+ @patch('ipapython.ipautil.run') -+ def test_trust_catalog_posix_missing(self, mock_run, mock_getnamebysid): -+ """AD POSIX ranges""" -+ # id Administrator@ad.example -+ dsresult = namedtuple('run', ['returncode', 'error_log']) -+ dsresult.returncode = 0 -+ dsresult.error_log = '' -+ dsresult.output = 'Active servers:\nAD Global Catalog: ' \ -+ 'root-dc.ad.vm\nAD Domain Controller: root-dc.ad.vm\n' \ -+ 'IPA: master.ipa.vm\n\n' -+ ds2result = namedtuple('run', ['returncode', 'error_log']) -+ ds2result.returncode = 0 -+ ds2result.error_log = '' -+ ds2result.output = 'Active servers:\nAD Global Catalog: ' \ -+ 'root-dc.ad.vm\nAD Domain Controller: root-dc.ad.vm\n' \ -+ -+ mock_run.side_effect = [dsresult, dsresult, ds2result] -+ mock_getnamebysid.side_effect = [ -+ {'S-1-5-21-abc-500': {'name': 'admin@ad.example', 'type': 3}}, -+ {'S-1-5-21-ghi-500': {'name': 'admin@child.ad.example', 'type': 3}}, -+ {'S-1-5-21-def-500': {'name': 'admin@child.example', 'type': 3}} -+ ] -+ -+ # get_trust_domains() -+ m_api.Command.trust_find.side_effect = trust_find() -+ m_api.Command.trustdomain_find.side_effect = trustdomain_find() -+ m_api.Command.idrange_find.side_effect = [ -+ idrange_find_adrange_posix(), -+ {'result': []}, -+ {'result': []} -+ ] -+ -+ framework = object() -+ registry.initialize(framework, config.Config) -+ registry.trust_agent = True -+ f = IPATrustCatalogCheck(registry) -+ -+ self.results = capture_results(f) -+ -+ assert len(self.results) == 3 -+ -+ result = self.results.results[0] -+ assert result.result == constants.SUCCESS -+ assert result.source == 'ipahealthcheck.ipa.trust' -+ assert result.check == 'IPATrustCatalogCheck' -+ assert result.kw.get('key') == 'S-1-5-21-abc' -+ assert result.kw.get('domain') == 'ad.example' -+ assert result.kw.get('type') == 'ipa-ad-trust-posix' -+ -+ result = self.results.results[1] -+ assert result.result == constants.WARNING -+ assert result.source == 'ipahealthcheck.ipa.trust' -+ assert result.check == 'IPATrustCatalogCheck' -+ assert result.kw.get('key') == 'S-1-5-22-def' -+ assert result.kw.get('domain') == 'child.ad.example' -+ assert ( -+ result.kw.get('msg') -+ == 'Domain {domain} does not have an idrange' -+ ) -+ -+ result = self.results.results[2] -+ assert result.result == constants.WARNING -+ assert result.source == 'ipahealthcheck.ipa.trust' -+ assert result.check == 'IPATrustCatalogCheck' -+ assert result.kw.get('key') == 'S-1-5-21-ghi' -+ assert result.kw.get('domain') == 'child.example' -+ assert ( -+ result.kw.get('msg') -+ == 'Domain {domain} does not have an idrange' -+ ) -+ - - class Testsidgen(BaseTest): - patches = { --- -2.39.2 - diff --git a/SOURCES/0003-Temporarily-disable-the-ipa-ods-exporter-service-sta.patch b/SOURCES/0003-Temporarily-disable-the-ipa-ods-exporter-service-sta.patch new file mode 100644 index 0000000..2795766 --- /dev/null +++ b/SOURCES/0003-Temporarily-disable-the-ipa-ods-exporter-service-sta.patch @@ -0,0 +1,44 @@ +From d1cb1997737c938bbc61d547aae277e308e78fce Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Tue, 14 Nov 2023 20:32:54 -0500 +Subject: [PATCH] Temporarily disable the ipa-ods-exporter service status check + +There is a bug in this service such that it will almost always +report as down. Rather than spamming users with this error give +time for it to be fixed in IPA upstream. + +See https://pagure.io/freeipa/issue/9463 + +Signed-off-by: Rob Crittenden +--- + src/ipahealthcheck/meta/services.py | 14 -------------- + 1 file changed, 14 deletions(-) + +diff --git a/src/ipahealthcheck/meta/services.py b/src/ipahealthcheck/meta/services.py +index 9838128..b8973cb 100644 +--- a/src/ipahealthcheck/meta/services.py ++++ b/src/ipahealthcheck/meta/services.py +@@ -202,20 +202,6 @@ class ods_enforcerd(IPAServiceCheck): + return super().check() + + +-@registry +-class ipa_ods_exporter(IPAServiceCheck): +- requires = ('dirsrv',) +- +- def check(self, instance=''): +- self.service_name = self.get_service_name('DNSKeyExporter') +- +- if self.service_name is None: +- # No service name means it is not configured +- return () +- +- return super().check() +- +- + @registry + class ipa_dnskeysyncd(IPAServiceCheck): + requires = ('dirsrv',) +-- +2.40.1 + diff --git a/SOURCES/0004-Catch-exceptions-during-user-group-name-lookup-in-Fi.patch b/SOURCES/0004-Catch-exceptions-during-user-group-name-lookup-in-Fi.patch deleted file mode 100644 index 4234843..0000000 --- a/SOURCES/0004-Catch-exceptions-during-user-group-name-lookup-in-Fi.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 4906c52b629bfce275558d4701c083f4c020ef32 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Fri, 30 Jun 2023 14:35:40 -0400 -Subject: [PATCH] Catch exceptions during user/group name lookup in FileCheck - -It's possible that one or more of the allowed users/groups -in a file check do not exist on the system. Catch this -exception and try to proceed as best as possible. - -https://github.com/freeipa/freeipa-healthcheck/issues/296 - -Signed-off-by: Rob Crittenden ---- - src/ipahealthcheck/core/files.py | 33 +++++++++++++++++++++++---- - tests/test_core_files.py | 38 ++++++++++++++++++++++++++++++++ - 2 files changed, 67 insertions(+), 4 deletions(-) - -diff --git a/src/ipahealthcheck/core/files.py b/src/ipahealthcheck/core/files.py -index 59e8b76..85d42bc 100644 ---- a/src/ipahealthcheck/core/files.py -+++ b/src/ipahealthcheck/core/files.py -@@ -3,12 +3,15 @@ - # - - import grp -+import logging - import os - import pwd - - from ipahealthcheck.core import constants - from ipahealthcheck.core.plugin import Result, duration - -+logger = logging.getLogger() -+ - - class FileCheck: - """Generic check to validate permission and ownership of files -@@ -77,14 +80,25 @@ class FileCheck: - - found = False - for o in owner: -- fowner = pwd.getpwnam(o) -+ try: -+ fowner = pwd.getpwnam(o) -+ except Exception as e: -+ logging.debug('user lookup "%s" for "%s" failed: %s', -+ o, path, e) -+ continue - if fowner.pw_uid == stat.st_uid: - found = True - break - - if not found: -- actual = pwd.getpwuid(stat.st_uid) - key = '%s_owner' % path.replace('/', '_') -+ try: -+ actual = pwd.getpwuid(stat.st_uid) -+ except Exception: -+ yield Result(self, constants.WARNING, key=key, -+ path=path, type='owner', expected=owner, -+ got='Unknown uid %s' % stat.st_uid) -+ continue - if len(owner) == 1: - msg = 'Ownership of %s is %s and should ' \ - 'be %s' % \ -@@ -104,14 +118,25 @@ class FileCheck: - - found = False - for g in group: -- fgroup = grp.getgrnam(g) -+ try: -+ fgroup = grp.getgrnam(g) -+ except Exception as e: -+ logging.debug('group lookup "%s" for "%s" failed: %s', -+ g, path, e) -+ continue - if fgroup.gr_gid == stat.st_gid: - found = True - break - - if not found: - key = '%s_group' % path.replace('/', '_') -- actual = grp.getgrgid(stat.st_gid) -+ try: -+ actual = grp.getgrgid(stat.st_gid) -+ except Exception: -+ yield Result(self, constants.WARNING, key=key, -+ path=path, type='group', expected=group, -+ got='Unknown gid %s' % stat.st_gid) -+ continue - if len(group) == 1: - msg = 'Group of %s is %s and should ' \ - 'be %s' % \ -diff --git a/tests/test_core_files.py b/tests/test_core_files.py -index 6e3ec38..924d7fa 100644 ---- a/tests/test_core_files.py -+++ b/tests/test_core_files.py -@@ -197,3 +197,41 @@ def test_files_not_found(mock_exists): - for result in my_results.results: - assert result.result == constants.SUCCESS - assert result.kw.get('msg') == 'File does not exist' -+ -+ -+@patch('os.stat') -+@patch('pwd.getpwnam') -+@patch('pwd.getpwuid') -+def test_files_owner_not_found(mock_pwuid, mock_pwnam, mock_stat): -+ mock_pwuid.side_effect = KeyError('getpwnam(): name not found') -+ mock_pwnam.side_effect = KeyError('getpwuid(): uid not found') -+ mock_stat.return_value = make_stat() -+ -+ f = FileCheck() -+ f.files = files -+ -+ results = capture_results(f) -+ -+ my_results = get_results(results, 'owner') -+ for result in my_results.results: -+ assert result.result == constants.WARNING -+ assert result.kw.get('got') == 'Unknown uid 0' -+ -+ -+@patch('os.stat') -+@patch('grp.getgrnam') -+@patch('grp.getgrgid') -+def test_files_group_not_found(mock_grgid, mock_grnam, mock_stat): -+ mock_grgid.side_effect = KeyError('getgrnam(): name not found') -+ mock_grnam.side_effect = KeyError('getgruid(): gid not found') -+ mock_stat.return_value = make_stat() -+ -+ f = FileCheck() -+ f.files = files -+ -+ results = capture_results(f) -+ -+ my_results = get_results(results, 'group') -+ for result in my_results.results: -+ assert result.result == constants.WARNING -+ assert result.kw.get('got') == 'Unknown gid 0' --- -2.41.0 - diff --git a/SOURCES/0004-Skip-DogtagCertsConfigCheck-for-PKI-versions-11.5.0.patch b/SOURCES/0004-Skip-DogtagCertsConfigCheck-for-PKI-versions-11.5.0.patch new file mode 100644 index 0000000..a31c062 --- /dev/null +++ b/SOURCES/0004-Skip-DogtagCertsConfigCheck-for-PKI-versions-11.5.0.patch @@ -0,0 +1,46 @@ +From e556edc0b1cb607caa50f760d5059877f35fbcdc Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Thu, 11 Jan 2024 14:40:02 -0500 +Subject: [PATCH] Skip DogtagCertsConfigCheck for PKI versions >= 11.5.0 + +In 11.5.0 the PKI project stopped storing the certificate +blobs in CS.cfg. If we continue to check it we will report a +false positive so skip it in that case. + +Fixes: https://github.com/freeipa/freeipa-healthcheck/issues/317 + +Signed-off-by: Rob Crittenden +--- + src/ipahealthcheck/dogtag/ca.py | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/src/ipahealthcheck/dogtag/ca.py b/src/ipahealthcheck/dogtag/ca.py +index 4afa5d7..ddf5ece 100644 +--- a/src/ipahealthcheck/dogtag/ca.py ++++ b/src/ipahealthcheck/dogtag/ca.py +@@ -16,6 +16,8 @@ from ipaserver.install import krainstance + from ipapython.directivesetter import get_directive + from cryptography.hazmat.primitives.serialization import Encoding + ++import pki.util ++ + logger = logging.getLogger() + + +@@ -30,6 +32,13 @@ class DogtagCertsConfigCheck(DogtagPlugin): + logger.debug("No CA configured, skipping dogtag config check") + return + ++ pki_version = pki.util.Version(pki.specification_version()) ++ if pki_version >= pki.util.Version("11.5.0"): ++ logger.debug( ++ "PKI 11.5.0 no longer stores certificats in CS.cfg" ++ ) ++ return ++ + kra = krainstance.KRAInstance(api.env.realm) + + blobs = {'auditSigningCert cert-pki-ca': 'ca.audit_signing.cert', +-- +2.42.0 + diff --git a/SOURCES/0005-Don-t-error-in-DogtagCertsConnectivityCheck-with-ext.patch b/SOURCES/0005-Don-t-error-in-DogtagCertsConnectivityCheck-with-ext.patch deleted file mode 100644 index 7fa1b4d..0000000 --- a/SOURCES/0005-Don-t-error-in-DogtagCertsConnectivityCheck-with-ext.patch +++ /dev/null @@ -1,372 +0,0 @@ -From 29855ec76bcb445543e1f2b16b13e5bcfeb67723 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Mon, 27 Mar 2023 16:43:11 -0400 -Subject: [PATCH] Don't error in DogtagCertsConnectivityCheck with external CAs - -The purpose of the check is to validate that communication -with the CA works. In the past we looked up serial number 1 -for this check. The problem is that if the server was -installed with RSNv3 so had no predictable CA serial number. - -It also was broken with externally-issued CA certificate which -cannot be looked up in IPA. - -Instead use the IPA RA agent certificate which should definitely -have a serial number in the IPA CA if one is configured. - -Fixes: https://github.com/freeipa/freeipa-healthcheck/issues/285 - -Signed-off-by: Rob Crittenden ---- - src/ipahealthcheck/dogtag/ca.py | 45 +++----- - tests/test_dogtag_connectivity.py | 175 +++++------------------------- - 2 files changed, 39 insertions(+), 181 deletions(-) - -diff --git a/src/ipahealthcheck/dogtag/ca.py b/src/ipahealthcheck/dogtag/ca.py -index 868876f..4afa5d7 100644 ---- a/src/ipahealthcheck/dogtag/ca.py -+++ b/src/ipahealthcheck/dogtag/ca.py -@@ -12,10 +12,8 @@ from ipahealthcheck.core import constants - from ipalib import api, errors, x509 - from ipaplatform.paths import paths - from ipaserver.install import certs --from ipaserver.install import ca - from ipaserver.install import krainstance - from ipapython.directivesetter import get_directive --from ipapython.dn import DN - from cryptography.hazmat.primitives.serialization import Encoding - - logger = logging.getLogger() -@@ -95,6 +93,10 @@ class DogtagCertsConfigCheck(DogtagPlugin): - class DogtagCertsConnectivityCheck(DogtagPlugin): - """ - Test basic connectivity by using cert-show to fetch a cert -+ -+ The RA agent certificate is used because if a CA is configured we -+ know this certificate should exist. Use its serial number to do -+ the lookup. - """ - requires = ('dirsrv',) - -@@ -104,59 +106,38 @@ class DogtagCertsConnectivityCheck(DogtagPlugin): - logger.debug('CA is not configured, skipping connectivity check') - return - -- config = api.Command.config_show() -- -- subject_base = config['result']['ipacertificatesubjectbase'][0] -- ipa_subject = ca.lookup_ca_subject(api, subject_base) - try: -- certs = x509.load_certificate_list_from_file(paths.IPA_CA_CRT) -+ cert = x509.load_certificate_from_file(paths.RA_AGENT_PEM) - except Exception as e: - yield Result(self, constants.ERROR, -- key='ipa_ca_crt_file_missing', -- path=paths.IPA_CA_CRT, -+ key='ipa_ra_crt_file_missing', -+ path=paths.RA_AGENT_PEM, - error=str(e), -- msg='The IPA CA cert file {path} could not be ' -+ msg='The IPA RA cert file {path} could not be ' - 'opened: {error}') - return - -- found = False -- for cert in certs: -- if DN(cert.subject) == ipa_subject: -- found = True -- break -- -- if not found: -- yield Result(self, constants.ERROR, -- key='ipa_ca_cert_not_found', -- subject=str(ipa_subject), -- path=paths.IPA_CA_CRT, -- msg='The CA certificate with subject {subject} ' -- 'was not found in {path}') -- return -- # Load the IPA CA certificate to obtain its serial number. This -- # was traditionally 1 prior to random serial number support. -- # There is nothing special about cert 1. Even if there is no cert -- # serial number 1 but the connection is ok it is considered passing. -+ # We used to use serial #1 but with RSNv3 it can be anything. - try: - api.Command.cert_show(cert.serial_number, all=True) - except errors.CertificateOperationError as e: - if 'not found' in str(e): - yield Result(self, constants.ERROR, -- key='cert_show_1', -+ key='cert_show_ra', - error=str(e), - serial=str(cert.serial_number), - msg='Serial number not found: {error}') - else: - yield Result(self, constants.ERROR, -- key='cert_show_1', -+ key='cert_show_ra', - error=str(e), - serial=str(cert.serial_number), - msg='Request for certificate failed: {error}') - except Exception as e: - yield Result(self, constants.ERROR, -- key='cert_show_1', -+ key='cert_show_ra', - error=str(e), - serial=str(cert.serial_number), -- msg='Request for certificate failed: {error') -+ msg='Request for certificate failed: {error}') - else: - yield Result(self, constants.SUCCESS) -diff --git a/tests/test_dogtag_connectivity.py b/tests/test_dogtag_connectivity.py -index d81e598..4413fe1 100644 ---- a/tests/test_dogtag_connectivity.py -+++ b/tests/test_dogtag_connectivity.py -@@ -13,14 +13,23 @@ from ipahealthcheck.dogtag.ca import DogtagCertsConnectivityCheck - - from ipalib.errors import CertificateOperationError - from ipaplatform.paths import paths --from ipapython.dn import DN -+ -+ -+default_subject_base = [{ -+ 'result': -+ { -+ 'ipacertificatesubjectbase': [f'O={m_api.env.realm}'], -+ }, -+}] - - - class IPACertificate: - def __init__(self, serial_number=1, -- subject='CN=Certificate Authority, O=%s' % m_api.env.realm): -+ subject='CN=Certificate Authority, O=%s' % m_api.env.realm, -+ issuer='CN=Certificate Authority, O=%s' % m_api.env.realm): - self.serial_number = serial_number - self.subject = subject -+ self.issuer = issuer - - def __eq__(self, other): - return self.serial_number == other.serial_number -@@ -50,18 +59,15 @@ class TestCAConnectivity(BaseTest): - Mock(return_value=CAInstance()), - } - -- @patch('ipaserver.install.ca.lookup_ca_subject') -- @patch('ipalib.x509.load_certificate_list_from_file') -- def test_ca_connection_ok(self, mock_load_cert, mock_ca_subject): -+ @patch('ipalib.x509.load_certificate_from_file') -+ def test_ca_connection_ok(self, mock_load_cert): - """CA connectivity check when cert_show returns a valid value""" - m_api.Command.cert_show.side_effect = None - m_api.Command.config_show.side_effect = subject_base - m_api.Command.cert_show.return_value = { - u'result': {u'revoked': False} - } -- mock_load_cert.return_value = [IPACertificate(12345)] -- mock_ca_subject.return_value = DN(('cn', 'Certificate Authority'), -- f'O={m_api.env.realm}') -+ mock_load_cert.return_value = IPACertificate(12345) - - framework = object() - registry.initialize(framework, config.Config) -@@ -76,10 +82,8 @@ class TestCAConnectivity(BaseTest): - assert result.source == 'ipahealthcheck.dogtag.ca' - assert result.check == 'DogtagCertsConnectivityCheck' - -- @patch('ipaserver.install.ca.lookup_ca_subject') -- @patch('ipalib.x509.load_certificate_list_from_file') -- def test_ca_connection_cert_not_found(self, mock_load_cert, -- mock_ca_subject): -+ @patch('ipalib.x509.load_certificate_from_file') -+ def test_ca_connection_cert_not_found(self, mock_load_cert): - """CA connectivity check for a cert that doesn't exist""" - m_api.Command.cert_show.reset_mock() - m_api.Command.config_show.side_effect = subject_base -@@ -87,9 +91,7 @@ class TestCAConnectivity(BaseTest): - message='Certificate operation cannot be completed: ' - 'EXCEPTION (Certificate serial number 0x0 not found)' - ) -- mock_load_cert.return_value = [IPACertificate()] -- mock_ca_subject.return_value = DN(('cn', 'Certificate Authority'), -- f'O={m_api.env.realm}') -+ mock_load_cert.return_value = IPACertificate(serial_number=7) - - framework = object() - registry.initialize(framework, config.Config) -@@ -103,46 +105,16 @@ class TestCAConnectivity(BaseTest): - assert result.result == constants.ERROR - assert result.source == 'ipahealthcheck.dogtag.ca' - assert result.check == 'DogtagCertsConnectivityCheck' -- assert result.kw.get('key') == 'cert_show_1' -- assert result.kw.get('serial') == '1' -+ assert result.kw.get('key') == 'cert_show_ra' -+ assert result.kw.get('serial') == '7' - assert result.kw.get('msg') == 'Serial number not found: {error}' - -- @patch('ipaserver.install.ca.lookup_ca_subject') -- @patch('ipalib.x509.load_certificate_list_from_file') -- def test_ca_connection_cert_file_not_found(self, mock_load_cert, -- mock_ca_subject): -+ @patch('ipalib.x509.load_certificate_from_file') -+ def test_ca_connection_cert_file_not_found(self, mock_load_cert): - """CA connectivity check for a cert that doesn't exist""" - m_api.Command.cert_show.reset_mock() - m_api.Command.config_show.side_effect = subject_base - mock_load_cert.side_effect = FileNotFoundError() -- mock_ca_subject.return_value = DN(('cn', 'Certificate Authority'), -- f'O={m_api.env.realm}') -- -- framework = object() -- registry.initialize(framework, config.Config) -- f = DogtagCertsConnectivityCheck(registry) -- -- self.results = capture_results(f) -- -- assert len(self.results) == 1 -- -- result = self.results.results[0] -- assert result.result == constants.ERROR -- assert result.source == 'ipahealthcheck.dogtag.ca' -- assert result.check == 'DogtagCertsConnectivityCheck' -- assert result.kw.get('key') == 'ipa_ca_crt_file_missing' -- assert result.kw.get('path') == paths.IPA_CA_CRT -- -- @patch('ipaserver.install.ca.lookup_ca_subject') -- @patch('ipalib.x509.load_certificate_list_from_file') -- def test_ca_connection_cert_not_in_file_list(self, mock_load_cert, -- mock_ca_subject): -- """CA connectivity check for a cert that isn't in IPA_CA_CRT""" -- m_api.Command.cert_show.reset_mock() -- m_api.Command.config_show.side_effect = bad_subject_base -- mock_load_cert.return_value = [IPACertificate()] -- mock_ca_subject.return_value = DN(('cn', 'Certificate Authority'), -- 'O=BAD') - - framework = object() - registry.initialize(framework, config.Config) -@@ -156,26 +128,18 @@ class TestCAConnectivity(BaseTest): - assert result.result == constants.ERROR - assert result.source == 'ipahealthcheck.dogtag.ca' - assert result.check == 'DogtagCertsConnectivityCheck' -- bad = bad_subject_base[0]['result']['ipacertificatesubjectbase'][0] -- bad_subject = DN(f'CN=Certificate Authority,{bad}') -- assert DN(result.kw['subject']) == bad_subject -- assert result.kw['path'] == paths.IPA_CA_CRT -- assert result.kw['msg'] == ( -- 'The CA certificate with subject {subject} was not found in {path}' -- ) -+ assert result.kw.get('key') == 'ipa_ra_crt_file_missing' -+ assert result.kw.get('path') == paths.RA_AGENT_PEM - -- @patch('ipaserver.install.ca.lookup_ca_subject') -- @patch('ipalib.x509.load_certificate_list_from_file') -- def test_ca_connection_down(self, mock_load_cert, mock_ca_subject): -+ @patch('ipalib.x509.load_certificate_from_file') -+ def test_ca_connection_down(self, mock_load_cert): - """CA connectivity check with the CA down""" - m_api.Command.cert_show.side_effect = CertificateOperationError( - message='Certificate operation cannot be completed: ' - 'Unable to communicate with CMS (503)' - ) - m_api.Command.config_show.side_effect = subject_base -- mock_load_cert.return_value = [IPACertificate()] -- mock_ca_subject.return_value = DN(('cn', 'Certificate Authority'), -- f'O={m_api.env.realm}') -+ mock_load_cert.return_value = IPACertificate() - - framework = object() - registry.initialize(framework, config.Config) -@@ -192,90 +156,3 @@ class TestCAConnectivity(BaseTest): - assert result.kw.get('msg') == ( - 'Request for certificate failed: {error}' - ) -- -- @patch('ipaserver.install.ca.lookup_ca_subject') -- @patch('ipalib.x509.load_certificate_list_from_file') -- def test_ca_connection_multiple_ok(self, mock_load_cert, mock_ca_subject): -- """CA connectivity check when cert_show returns a valid value""" -- m_api.Command.cert_show.side_effect = None -- m_api.Command.config_show.side_effect = subject_base -- m_api.Command.cert_show.return_value = { -- u'result': {u'revoked': False} -- } -- mock_load_cert.return_value = [ -- IPACertificate(1, 'CN=something'), -- IPACertificate(12345), -- ] -- mock_ca_subject.return_value = DN(('cn', 'Certificate Authority'), -- f'O={m_api.env.realm}') -- -- framework = object() -- registry.initialize(framework, config.Config) -- f = DogtagCertsConnectivityCheck(registry) -- -- self.results = capture_results(f) -- -- assert len(self.results) == 1 -- -- result = self.results.results[0] -- assert result.result == constants.SUCCESS -- assert result.source == 'ipahealthcheck.dogtag.ca' -- -- @patch('ipaserver.install.ca.lookup_ca_subject') -- @patch('ipalib.x509.load_certificate_list_from_file') -- def test_ca_connection_multiple_ok_reverse(self, mock_load_cert, -- mock_ca_subject): -- """CA connectivity check when cert_show returns a valid value""" -- m_api.Command.cert_show.side_effect = None -- m_api.Command.config_show.side_effect = subject_base -- m_api.Command.cert_show.return_value = { -- u'result': {u'revoked': False} -- } -- mock_load_cert.return_value = [ -- IPACertificate(12345), -- IPACertificate(1, 'CN=something'), -- ] -- mock_ca_subject.return_value = DN(('cn', 'Certificate Authority'), -- f'O={m_api.env.realm}') -- -- framework = object() -- registry.initialize(framework, config.Config) -- f = DogtagCertsConnectivityCheck(registry) -- -- self.results = capture_results(f) -- -- assert len(self.results) == 1 -- -- result = self.results.results[0] -- assert result.result == constants.SUCCESS -- assert result.source == 'ipahealthcheck.dogtag.ca' -- -- @patch('ipaserver.install.ca.lookup_ca_subject') -- @patch('ipalib.x509.load_certificate_list_from_file') -- def test_ca_connection_not_found(self, mock_load_cert, mock_ca_subject): -- """CA connectivity check when cert_show returns a valid value""" -- m_api.Command.cert_show.side_effect = None -- m_api.Command.config_show.side_effect = subject_base -- m_api.Command.cert_show.return_value = { -- u'result': {u'revoked': False} -- } -- mock_load_cert.return_value = [ -- IPACertificate(1, 'CN=something'), -- ] -- mock_ca_subject.return_value = DN(('cn', 'Certificate Authority'), -- f'O={m_api.env.realm}') -- -- framework = object() -- registry.initialize(framework, config.Config) -- f = DogtagCertsConnectivityCheck(registry) -- -- self.results = capture_results(f) -- -- assert len(self.results) == 1 -- -- result = self.results.results[0] -- assert result.result == constants.ERROR -- assert result.source == 'ipahealthcheck.dogtag.ca' -- assert result.kw['msg'] == ( -- 'The CA certificate with subject {subject} was not found in {path}' -- ) --- -2.41.0 - diff --git a/SOURCES/0005-test-Handle-PKI-11.5.0-not-storing-certs-in-CS.cfg.patch b/SOURCES/0005-test-Handle-PKI-11.5.0-not-storing-certs-in-CS.cfg.patch new file mode 100644 index 0000000..3c62ac0 --- /dev/null +++ b/SOURCES/0005-test-Handle-PKI-11.5.0-not-storing-certs-in-CS.cfg.patch @@ -0,0 +1,59 @@ +From cafe01a23a36c408c8c60357ad2651688dc63599 Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Fri, 12 Jan 2024 10:17:18 -0500 +Subject: [PATCH] test: Handle PKI >= 11.5.0 not storing certs in CS.cfg + +Update the test to expect 0 results if the PKI version is +>= 11.5.0. + +Fixes: https://github.com/freeipa/freeipa-healthcheck/issues/317 + +Signed-off-by: Rob Crittenden +--- + tests/test_dogtag_ca.py | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/tests/test_dogtag_ca.py b/tests/test_dogtag_ca.py +index 0820aba..1f61dea 100644 +--- a/tests/test_dogtag_ca.py ++++ b/tests/test_dogtag_ca.py +@@ -2,12 +2,16 @@ + # Copyright (C) 2019 FreeIPA Contributors see COPYING for license + # + ++import pki.util + from util import capture_results, CAInstance, KRAInstance + from base import BaseTest + from ipahealthcheck.core import config, constants + from ipahealthcheck.dogtag.plugin import registry + from ipahealthcheck.dogtag.ca import DogtagCertsConfigCheck + from unittest.mock import Mock, patch ++import pytest ++ ++pki_version = pki.util.Version(pki.specification_version()) + + + class mock_Cert: +@@ -43,6 +47,9 @@ class TestCACerts(BaseTest): + Mock(return_value=KRAInstance()), + } + ++ @pytest.mark.skipif( ++ pki_version >= pki.util.Version("11.5.0"), ++ reason='Does not apply to PKI 11.5.0+') + @patch('ipahealthcheck.dogtag.ca.get_directive') + @patch('ipaserver.install.certs.CertDB') + def test_ca_certs_ok(self, mock_certdb, mock_directive): +@@ -71,6 +78,9 @@ class TestCACerts(BaseTest): + assert result.source == 'ipahealthcheck.dogtag.ca' + assert result.check == 'DogtagCertsConfigCheck' + ++ @pytest.mark.skipif( ++ pki_version >= pki.util.Version("11.5.0"), ++ reason='Does not apply to PKI 11.5.0+') + @patch('ipahealthcheck.dogtag.ca.get_directive') + @patch('ipaserver.install.certs.CertDB') + def test_cert_missing_from_file(self, mock_certdb, mock_directive): +-- +2.42.0 + diff --git a/SPECS/freeipa-healthcheck.spec b/SPECS/freeipa-healthcheck.spec index eb94088..644a290 100644 --- a/SPECS/freeipa-healthcheck.spec +++ b/SPECS/freeipa-healthcheck.spec @@ -16,8 +16,8 @@ %bcond_without tests Name: %{prefix}-healthcheck -Version: 0.12 -Release: 4%{?dist} +Version: 0.16 +Release: 3%{?dist} Summary: Health check tool for %{productname} BuildArch: noarch License: GPLv3 @@ -26,10 +26,10 @@ Source0: https://github.com/freeipa/freeipa-healthcheck/archive/%{version Source1: ipahealthcheck.conf Patch0001: 0001-Remove-ipaclustercheck.patch -Patch0002: 0002-Disable-two-failing-tests.patch -Patch0003: 0003-Skip-AD-domains-with-posix-ranges-in-the-catalog-che.patch -Patch0004: 0004-Catch-exceptions-during-user-group-name-lookup-in-Fi.patch -Patch0005: 0005-Don-t-error-in-DogtagCertsConnectivityCheck-with-ext.patch +Patch0002: 0002-Don-t-fail-if-a-service-name-cannot-be-looked-up-in-.patch +Patch0003: 0003-Temporarily-disable-the-ipa-ods-exporter-service-sta.patch +Patch0004: 0004-Skip-DogtagCertsConfigCheck-for-PKI-versions-11.5.0.patch +Patch0005: 0005-test-Handle-PKI-11.5.0-not-storing-certs-in-CS.cfg.patch Requires: %{name}-core = %{version}-%{release} Requires: %{prefix}-server @@ -159,6 +159,16 @@ PYTHONPATH=src PATH=$PATH:$RPM_BUILD_ROOT/usr/bin pytest-3 tests/test_* %changelog +* Fri Jan 12 2024 Rob Crittenden - 0.16-3 +- Skip DogtagCertsConfigCheck for PKI versions 11.5.0 (RHEL-21367) + +* Tue Nov 14 2023 Rob Crittenden - 0.16-2 +- Don't fail if a service name cannot be looked up in LDAP +- Disable the ipa-ods-exporter service check + +* Thu Nov 9 2023 Rob Crittenden - 0.16-1 +- Update to upstream 0.16 (RHEL-12494) + * Mon Jul 24 2023 Rob Crittenden - 0.12-4 - Error in DogtagCertsConnectivityCheckCA with external CA (#2224595)