From 95d978bebefca54bb7a3246f8a8600482ed11edd Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Apr 28 2020 08:53:14 +0000 Subject: import ipa-healthcheck-0.4-4.module+el8.2.0+5489+95477d9f --- diff --git a/.gitignore b/.gitignore index 137847c..7218656 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/freeipa-healthcheck-0.3.tar.gz +SOURCES/freeipa-healthcheck-0.4.tar.gz diff --git a/.ipa-healthcheck.metadata b/.ipa-healthcheck.metadata index 8b355c4..f0c76cd 100644 --- a/.ipa-healthcheck.metadata +++ b/.ipa-healthcheck.metadata @@ -1 +1 @@ -d06ba28575381405cf0e303f6ab388484c768899 SOURCES/freeipa-healthcheck-0.3.tar.gz +2e61604c36f6f793612b1e3bb3f5e78df1cb58ac SOURCES/freeipa-healthcheck-0.4.tar.gz diff --git a/SOURCES/0002-Change-DNA-no-range-from-SUCCESS-to-WARNING.patch b/SOURCES/0002-Change-DNA-no-range-from-SUCCESS-to-WARNING.patch deleted file mode 100644 index 1cbb6e9..0000000 --- a/SOURCES/0002-Change-DNA-no-range-from-SUCCESS-to-WARNING.patch +++ /dev/null @@ -1,50 +0,0 @@ -From acd807b6e054b06b7b6fafe86741e00bae7d2527 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Tue, 30 Jul 2019 17:25:30 -0400 -Subject: [PATCH] Change DNA no range from SUCCESS to WARNING - -Elevate the not set version to WARNING so admins can be aware in -advance that with no range then uid/gid cannot be allocated from -this master. This is particularly important if the only master with -a range defined is retired. - -https://github.com/freeipa/freeipa-healthcheck/issues/60 ---- - src/ipahealthcheck/ipa/dna.py | 6 ++++-- - tests/test_ipa_dna.py | 2 +- - 2 files changed, 5 insertions(+), 3 deletions(-) - -diff --git a/src/ipahealthcheck/ipa/dna.py b/src/ipahealthcheck/ipa/dna.py -index 9dd2ffa..4d85057 100644 ---- a/src/ipahealthcheck/ipa/dna.py -+++ b/src/ipahealthcheck/ipa/dna.py -@@ -41,9 +41,11 @@ class IPADNARangeCheck(IPAPlugin): - next_start=next_start or 0, - next_max=next_max or 0) - else: -- yield Result(self, constants.SUCCESS, -+ yield Result(self, constants.WARNING, - range_start=0, - range_max=0, - next_start=0, - next_max=0, -- msg='No range defined') -+ msg='No DNA range defined. If no masters define a ' -+ 'range then users and groups cannot be ' -+ 'created.') -diff --git a/tests/test_ipa_dna.py b/tests/test_ipa_dna.py -index 0ff7dd4..3d5dd3e 100644 ---- a/tests/test_ipa_dna.py -+++ b/tests/test_ipa_dna.py -@@ -66,7 +66,7 @@ class TestDNARange(BaseTest): - assert len(self.results) == 1 - - result = self.results.results[0] -- assert result.result == constants.SUCCESS -+ assert result.result == constants.WARNING - assert result.source == 'ipahealthcheck.ipa.dna' - assert result.check == 'IPADNARangeCheck' - assert result.kw.get('range_start') == 0 --- -2.20.1 - diff --git a/SOURCES/0002-Move-main-to-run_healthcheck-for-abstraction-purpose.patch b/SOURCES/0002-Move-main-to-run_healthcheck-for-abstraction-purpose.patch new file mode 100644 index 0000000..c14ea28 --- /dev/null +++ b/SOURCES/0002-Move-main-to-run_healthcheck-for-abstraction-purpose.patch @@ -0,0 +1,106 @@ +From eb87d277442dd1a1076ba9ae74c18ace8cc7dda8 Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Mon, 11 Nov 2019 10:29:53 -0500 +Subject: [PATCH 2/5] Move main to run_healthcheck for abstraction purposes + +Take as arguments the entry point name and the configuration +file. +--- + src/ipahealthcheck/core/config.py | 4 ++-- + src/ipahealthcheck/core/main.py | 37 +++++++++++++++++-------------- + 2 files changed, 22 insertions(+), 19 deletions(-) + +diff --git a/src/ipahealthcheck/core/config.py b/src/ipahealthcheck/core/config.py +index 46da507..0cb72b7 100644 +--- a/src/ipahealthcheck/core/config.py ++++ b/src/ipahealthcheck/core/config.py +@@ -5,7 +5,7 @@ + import logging + from configparser import ConfigParser, ParsingError + +-from ipahealthcheck.core.constants import CONFIG_FILE, CONFIG_SECTION ++from ipahealthcheck.core.constants import CONFIG_SECTION + from ipahealthcheck.core.constants import DEFAULT_CONFIG + + logger = logging.getLogger() +@@ -70,7 +70,7 @@ class Config: + self.__d[key] = d[key] + + +-def read_config(config_file=CONFIG_FILE): ++def read_config(config_file): + """ + Simple configuration file reader + +diff --git a/src/ipahealthcheck/core/main.py b/src/ipahealthcheck/core/main.py +index b3fbe6a..f59a8a8 100644 +--- a/src/ipahealthcheck/core/main.py ++++ b/src/ipahealthcheck/core/main.py +@@ -28,11 +28,14 @@ else: + from ipahealthcheck.meta.services import ServiceCheck + + +-def find_registries(): +- return { +- ep.name: ep.resolve() +- for ep in pkg_resources.iter_entry_points('ipahealthcheck.registry') +- } ++def find_registries(entry_points): ++ registries = {} ++ for entry_point in entry_points: ++ registries.update({ ++ ep.name: ep.resolve() ++ for ep in pkg_resources.iter_entry_points(entry_point) ++ }) ++ return registries + + + def find_plugins(name, registry): +@@ -194,9 +197,7 @@ def limit_results(results, source, check): + return new_results + + +-def main(): +- environ["KRB5_CLIENT_KTNAME"] = "/etc/krb5.keytab" +- environ["KRB5CCNAME"] = "MEMORY:" ++def run_healthcheck(entry_points, configfile): + framework = object() + plugins = [] + output = constants.DEFAULT_OUTPUT +@@ -208,17 +209,11 @@ def main(): + if options.debug: + logger.setLevel(logging.DEBUG) + +- config = read_config() ++ config = read_config(configfile) + if config is None: + sys.exit(1) + +- if not ( +- options.source or options.list_sources +- ) and not is_ipa_configured(): +- logging.error("IPA is not configured on this system.") +- sys.exit(1) +- +- for name, registry in find_registries().items(): ++ for name, registry in find_registries(entry_points).items(): + try: + registry.initialize(framework) + except Exception as e: +@@ -283,4 +278,12 @@ def main(): + return_value = 1 + break + +- sys.exit(return_value) ++ return return_value ++ ++ ++def main(): ++ environ["KRB5_CLIENT_KTNAME"] = "/etc/krb5.keytab" ++ environ["KRB5CCNAME"] = "MEMORY:" ++ ++ sys.exit(run_healthcheck(['ipahealthcheck.registry'], ++ constants.CONFIG_FILE)) +-- +2.20.1 + diff --git a/SOURCES/0003-Abstract-ServiceCheck-to-not-be-IPA-specific.patch b/SOURCES/0003-Abstract-ServiceCheck-to-not-be-IPA-specific.patch new file mode 100644 index 0000000..1ae8db6 --- /dev/null +++ b/SOURCES/0003-Abstract-ServiceCheck-to-not-be-IPA-specific.patch @@ -0,0 +1,187 @@ +From c40e32b9d0ac49806b8336bd5065350574d29672 Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Mon, 18 Nov 2019 12:51:27 -0500 +Subject: [PATCH 3/5] Abstract ServiceCheck to not be IPA-specific + +It is up to the implementor to check for services running for now. +--- + src/ipahealthcheck/core/main.py | 9 +-------- + src/ipahealthcheck/core/service.py | 10 ++++++++++ + src/ipahealthcheck/meta/services.py | 29 +++++++++++++++-------------- + 3 files changed, 26 insertions(+), 22 deletions(-) + create mode 100644 src/ipahealthcheck/core/service.py + +diff --git a/src/ipahealthcheck/core/main.py b/src/ipahealthcheck/core/main.py +index f59a8a8..2b818d4 100644 +--- a/src/ipahealthcheck/core/main.py ++++ b/src/ipahealthcheck/core/main.py +@@ -15,18 +15,11 @@ from ipahealthcheck.core.config import read_config + from ipahealthcheck.core.plugin import Result, Results, json_to_results + from ipahealthcheck.core.output import output_registry + from ipahealthcheck.core import constants ++from ipahealthcheck.core.service import ServiceCheck + + logging.basicConfig(format='%(message)s') + logger = logging.getLogger() + +-try: +- from ipaserver.install.installutils import is_ipa_configured +-except ImportError: +- logging.error("IPA server packages are not installed on this system.") +- sys.exit(1) +-else: +- from ipahealthcheck.meta.services import ServiceCheck +- + + def find_registries(entry_points): + registries = {} +diff --git a/src/ipahealthcheck/core/service.py b/src/ipahealthcheck/core/service.py +new file mode 100644 +index 0000000..f9e2645 +--- /dev/null ++++ b/src/ipahealthcheck/core/service.py +@@ -0,0 +1,10 @@ ++# ++# Copyright (C) 2019 FreeIPA Contributors see COPYING for license ++# ++ ++from ipahealthcheck.core.plugin import Plugin ++ ++ ++class ServiceCheck(Plugin): ++ def check(self, instance=''): ++ raise NotImplementedError +diff --git a/src/ipahealthcheck/meta/services.py b/src/ipahealthcheck/meta/services.py +index d375066..a987108 100644 +--- a/src/ipahealthcheck/meta/services.py ++++ b/src/ipahealthcheck/meta/services.py +@@ -6,7 +6,8 @@ import logging + + from ipahealthcheck.core import constants + from ipahealthcheck.core.plugin import Result, duration +-from ipahealthcheck.meta.plugin import Plugin, registry ++from ipahealthcheck.core.service import ServiceCheck ++from ipahealthcheck.meta.plugin import registry + try: + from ipapython.ipaldap import realm_to_serverid + except ImportError: +@@ -20,7 +21,7 @@ from ipaserver.install import cainstance + logger = logging.getLogger() + + +-class ServiceCheck(Plugin): ++class IPAServiceCheck(ServiceCheck): + @duration + def check(self, instance=''): + try: +@@ -47,7 +48,7 @@ class ServiceCheck(Plugin): + + + @registry +-class certmonger(ServiceCheck): ++class certmonger(IPAServiceCheck): + def check(self): + self.service_name = 'certmonger' + +@@ -55,7 +56,7 @@ class certmonger(ServiceCheck): + + + @registry +-class dirsrv(ServiceCheck): ++class dirsrv(IPAServiceCheck): + def check(self): + self.service_name = 'dirsrv' + +@@ -63,7 +64,7 @@ class dirsrv(ServiceCheck): + + + @registry +-class gssproxy(ServiceCheck): ++class gssproxy(IPAServiceCheck): + def check(self): + self.service_name = 'gssproxy' + +@@ -71,7 +72,7 @@ class gssproxy(ServiceCheck): + + + @registry +-class httpd(ServiceCheck): ++class httpd(IPAServiceCheck): + def check(self): + self.service_name = 'httpd' + +@@ -79,7 +80,7 @@ class httpd(ServiceCheck): + + + @registry +-class ipa_custodia(ServiceCheck): ++class ipa_custodia(IPAServiceCheck): + def check(self): + self.service_name = 'ipa-custodia' + +@@ -87,7 +88,7 @@ class ipa_custodia(ServiceCheck): + + + @registry +-class ipa_dnskeysyncd(ServiceCheck): ++class ipa_dnskeysyncd(IPAServiceCheck): + def check(self): + self.service_name = 'ipa-dnskeysyncd' + +@@ -98,7 +99,7 @@ class ipa_dnskeysyncd(ServiceCheck): + + + @registry +-class ipa_otpd(ServiceCheck): ++class ipa_otpd(IPAServiceCheck): + def check(self): + self.service_name = 'ipa-otpd' + +@@ -106,7 +107,7 @@ class ipa_otpd(ServiceCheck): + + + @registry +-class kadmin(ServiceCheck): ++class kadmin(IPAServiceCheck): + def check(self): + self.service_name = 'kadmin' + +@@ -114,7 +115,7 @@ class kadmin(ServiceCheck): + + + @registry +-class krb5kdc(ServiceCheck): ++class krb5kdc(IPAServiceCheck): + def check(self): + self.service_name = 'krb5kdc' + +@@ -122,7 +123,7 @@ class krb5kdc(ServiceCheck): + + + @registry +-class named(ServiceCheck): ++class named(IPAServiceCheck): + def check(self): + self.service_name = 'named' + +@@ -133,7 +134,7 @@ class named(ServiceCheck): + + + @registry +-class pki_tomcatd(ServiceCheck): ++class pki_tomcatd(IPAServiceCheck): + def check(self): + self.service_name = 'pki_tomcatd' + +@@ -145,7 +146,7 @@ class pki_tomcatd(ServiceCheck): + + + @registry +-class sssd(ServiceCheck): ++class sssd(IPAServiceCheck): + def check(self): + self.service_name = 'sssd' + +-- +2.20.1 + diff --git a/SOURCES/0003-Always-initialize-AD-roles-even-if-the-IPA-API-is-in.patch b/SOURCES/0003-Always-initialize-AD-roles-even-if-the-IPA-API-is-in.patch deleted file mode 100644 index e585c76..0000000 --- a/SOURCES/0003-Always-initialize-AD-roles-even-if-the-IPA-API-is-in.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 5fb1b2049889705d2cda60d745be5b1dacb23146 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Tue, 6 Aug 2019 18:00:50 +0000 -Subject: [PATCH 3/8] Always initialize AD roles even if the IPA API is - initialized - -The setting of these roles in the registry were guarded by whether -the IPA API was initialized. If another plugin intialized the API -then these values weren't being set, effectively disabling the -AD Trust checks. - -https://github.com/freeipa/freeipa-healthcheck/issues/62 ---- - src/ipahealthcheck/ipa/plugin.py | 14 ++++++-------- - 1 file changed, 6 insertions(+), 8 deletions(-) - -diff --git a/src/ipahealthcheck/ipa/plugin.py b/src/ipahealthcheck/ipa/plugin.py -index a73a7df..c4cef9b 100644 ---- a/src/ipahealthcheck/ipa/plugin.py -+++ b/src/ipahealthcheck/ipa/plugin.py -@@ -40,15 +40,13 @@ class IPARegistry(Registry): - def initialize(self, framework): - installutils.check_server_configuration() - -- if api.isdone('finalize'): -- return -- -- if not api.isdone('bootstrap'): -- api.bootstrap(in_server=True, -- context='ipahealthcheck', -- log=None) - if not api.isdone('finalize'): -- api.finalize() -+ if not api.isdone('bootstrap'): -+ api.bootstrap(in_server=True, -+ context='ipahealthcheck', -+ log=None) -+ if not api.isdone('finalize'): -+ api.finalize() - - if not api.Backend.ldap2.isconnected(): - try: --- -2.20.1 - diff --git a/SOURCES/0004-Create-a-default-set-of-mock-to-always-apply-to-all-.patch b/SOURCES/0004-Create-a-default-set-of-mock-to-always-apply-to-all-.patch deleted file mode 100644 index a8db556..0000000 --- a/SOURCES/0004-Create-a-default-set-of-mock-to-always-apply-to-all-.patch +++ /dev/null @@ -1,449 +0,0 @@ -From 14c7619284c5d29507b74d87c01b7c2d362be5c5 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Tue, 6 Aug 2019 16:00:24 -0400 -Subject: [PATCH 4/8] Create a default set of mock to always apply to all test - cases - -There are some common cases related to initialization where it makes -sense to centralize them in the base class. ---- - tests/base.py | 15 ++++++++++++- - tests/test_dogtag_ca.py | 2 -- - tests/test_dogtag_connectivity.py | 2 -- - tests/test_ds_replication.py | 7 +----- - tests/test_ipa_agent.py | 2 -- - tests/test_ipa_certfile_expiration.py | 2 -- - tests/test_ipa_certmonger_ca.py | 2 -- - tests/test_ipa_dna.py | 7 +----- - tests/test_ipa_expiration.py | 2 -- - tests/test_ipa_nssdb.py | 2 -- - tests/test_ipa_nssvalidation.py | 2 -- - tests/test_ipa_opensslvalidation.py | 2 -- - tests/test_ipa_revocation.py | 2 -- - tests/test_ipa_roles.py | 12 +--------- - tests/test_ipa_topology.py | 6 ----- - tests/test_ipa_tracking.py | 2 -- - tests/test_ipa_trust.py | 32 --------------------------- - tests/test_meta_services.py | 6 ----- - 18 files changed, 17 insertions(+), 90 deletions(-) - -diff --git a/tests/base.py b/tests/base.py -index 9a54941..8b9e37c 100644 ---- a/tests/base.py -+++ b/tests/base.py -@@ -17,18 +17,31 @@ class BaseTest(TestCase): - - If a test needs a particular value then it will need to use - @patch individually. -+ -+ A default set of Mock patches is set because they apply to all or -+ nearly all test cases. - """ -+ default_patches = { -+ 'ipaserver.install.installutils.check_server_configuration': -+ mock.Mock(return_value=None), -+ } -+ patches = {} - - def setup_class(self): - # collect the list of patches to be applied for this class of - # tests -+ self.default_patches.update(self.patches) -+ - self.applied_patches = [ -- mock.patch(patch, data) for patch, data in self.patches.items() -+ mock.patch(patch, data) for patch, data in -+ self.default_patches.items() - ] - - for patch in self.applied_patches: - patch.start() - -+ self.results = None -+ - def teardown_class(self): - mock.patch.stopall() - -diff --git a/tests/test_dogtag_ca.py b/tests/test_dogtag_ca.py -index 5c7faed..b5c5351 100644 ---- a/tests/test_dogtag_ca.py -+++ b/tests/test_dogtag_ca.py -@@ -37,8 +37,6 @@ class mock_CertDB: - - class TestCACerts(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ipaserver.install.cainstance.CAInstance': - Mock(return_value=CAInstance()), - 'ipaserver.install.krainstance.KRAInstance': -diff --git a/tests/test_dogtag_connectivity.py b/tests/test_dogtag_connectivity.py -index ad57bdf..544e325 100644 ---- a/tests/test_dogtag_connectivity.py -+++ b/tests/test_dogtag_connectivity.py -@@ -14,8 +14,6 @@ from ipalib.errors import CertificateOperationError - - class TestCAConnectivity(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ipaserver.install.cainstance.CAInstance': - Mock(return_value=CAInstance()), - } -diff --git a/tests/test_ds_replication.py b/tests/test_ds_replication.py -index dd2bfc9..b6b3652 100644 ---- a/tests/test_ds_replication.py -+++ b/tests/test_ds_replication.py -@@ -4,7 +4,7 @@ - - import pytest - from base import BaseTest --from unittest.mock import Mock, patch -+from unittest.mock import patch - from util import capture_results, m_api - - from ipahealthcheck.core import config, constants -@@ -37,11 +37,6 @@ class mock_ldap: - - - class TestReplicationConflicts(BaseTest): -- patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), -- } -- - @pytest.mark.skipif(NUM_VERSION < 40790, - reason="no way of currently testing this") - @patch('ipapython.ipaldap.LDAPClient.from_realm') -diff --git a/tests/test_ipa_agent.py b/tests/test_ipa_agent.py -index f614bb1..c58c7a6 100644 ---- a/tests/test_ipa_agent.py -+++ b/tests/test_ipa_agent.py -@@ -56,8 +56,6 @@ class mock_ldap_conn: - class TestNSSAgent(BaseTest): - cert = IPACertificate() - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ldap.initialize': - Mock(return_value=mock_ldap_conn()), - 'ipaserver.install.cainstance.CAInstance': -diff --git a/tests/test_ipa_certfile_expiration.py b/tests/test_ipa_certfile_expiration.py -index 61cb29b..d5601c5 100644 ---- a/tests/test_ipa_certfile_expiration.py -+++ b/tests/test_ipa_certfile_expiration.py -@@ -24,8 +24,6 @@ class IPACertificate: - - class TestIPACertificateFile(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ipahealthcheck.ipa.certs.get_expected_requests': - Mock(return_value=get_expected_requests()), - 'ipalib.install.certmonger._cm_dbus_object': -diff --git a/tests/test_ipa_certmonger_ca.py b/tests/test_ipa_certmonger_ca.py -index ac56a60..4eec1ba 100644 ---- a/tests/test_ipa_certmonger_ca.py -+++ b/tests/test_ipa_certmonger_ca.py -@@ -12,8 +12,6 @@ from unittest.mock import Mock, patch - - class TestCertmonger(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ipaserver.install.cainstance.CAInstance': - Mock(return_value=CAInstance()), - } -diff --git a/tests/test_ipa_dna.py b/tests/test_ipa_dna.py -index 3d5dd3e..5450642 100644 ---- a/tests/test_ipa_dna.py -+++ b/tests/test_ipa_dna.py -@@ -3,7 +3,7 @@ - # - - from base import BaseTest --from unittest.mock import Mock, patch -+from unittest.mock import patch - from util import capture_results - - from ipahealthcheck.core import config, constants -@@ -27,11 +27,6 @@ class mock_ReplicationManager: - - - class TestDNARange(BaseTest): -- patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), -- } -- - @patch('ipaserver.install.replication.ReplicationManager') - def test_dnarange_set(self, mock_manager): - mock_manager.return_value = mock_ReplicationManager(start=1, max=100) -diff --git a/tests/test_ipa_expiration.py b/tests/test_ipa_expiration.py -index f29f319..4c177f8 100644 ---- a/tests/test_ipa_expiration.py -+++ b/tests/test_ipa_expiration.py -@@ -17,8 +17,6 @@ from datetime import datetime, timedelta, timezone - - class TestExpiration(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ipahealthcheck.ipa.certs.get_expected_requests': - Mock(return_value=get_expected_requests()), - 'ipalib.install.certmonger._cm_dbus_object': -diff --git a/tests/test_ipa_nssdb.py b/tests/test_ipa_nssdb.py -index 67b9a55..7d5664e 100644 ---- a/tests/test_ipa_nssdb.py -+++ b/tests/test_ipa_nssdb.py -@@ -28,8 +28,6 @@ def my_unparse_trust_flags(trust_flags): - - class TestNSSDBTrust(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ipaserver.install.cainstance.CAInstance': - Mock(return_value=CAInstance()), - 'ipapython.certdb.unparse_trust_flags': -diff --git a/tests/test_ipa_nssvalidation.py b/tests/test_ipa_nssvalidation.py -index ba93ba5..1e567d8 100644 ---- a/tests/test_ipa_nssvalidation.py -+++ b/tests/test_ipa_nssvalidation.py -@@ -19,8 +19,6 @@ class DsInstance: - - class TestNSSValidation(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ipahealthcheck.ipa.certs.get_dogtag_cert_password': - Mock(return_value='foo'), - 'ipaserver.install.dsinstance.DsInstance': -diff --git a/tests/test_ipa_opensslvalidation.py b/tests/test_ipa_opensslvalidation.py -index 74751e3..0d334cd 100644 ---- a/tests/test_ipa_opensslvalidation.py -+++ b/tests/test_ipa_opensslvalidation.py -@@ -14,8 +14,6 @@ from ipapython.ipautil import _RunResult - - class TestOpenSSLValidation(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ipaserver.install.cainstance.CAInstance': - Mock(return_value=CAInstance()), - } -diff --git a/tests/test_ipa_revocation.py b/tests/test_ipa_revocation.py -index 3d1ea84..39cf3e7 100644 ---- a/tests/test_ipa_revocation.py -+++ b/tests/test_ipa_revocation.py -@@ -23,8 +23,6 @@ class IPACertificate: - - class TestRevocation(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ipaserver.install.certs.is_ipa_issued_cert': - Mock(return_value=True), - 'ipalib.x509.load_certificate_from_file': -diff --git a/tests/test_ipa_roles.py b/tests/test_ipa_roles.py -index 35c7a1d..453db06 100644 ---- a/tests/test_ipa_roles.py -+++ b/tests/test_ipa_roles.py -@@ -3,7 +3,7 @@ - # - - from base import BaseTest --from unittest.mock import Mock, patch -+from unittest.mock import patch - from util import capture_results, CAInstance - from util import m_api - -@@ -14,11 +14,6 @@ from ipahealthcheck.ipa.roles import (IPACRLManagerCheck, - - - class TestCRLManagerRole(BaseTest): -- patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), -- } -- - @patch('ipaserver.install.cainstance.CAInstance') - def test_not_crlmanager(self, mock_ca): - mock_ca.return_value = CAInstance(crlgen=False) -@@ -57,11 +52,6 @@ class TestCRLManagerRole(BaseTest): - - - class TestRenewalMaster(BaseTest): -- patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), -- } -- - def test_renewal_master_not_set(self): - framework = object() - registry.initialize(framework) -diff --git a/tests/test_ipa_topology.py b/tests/test_ipa_topology.py -index ebf7657..a4ff6d9 100644 ---- a/tests/test_ipa_topology.py -+++ b/tests/test_ipa_topology.py -@@ -5,7 +5,6 @@ - from util import capture_results - from util import m_api - from base import BaseTest --from unittest.mock import Mock - - from ipahealthcheck.core import config, constants - from ipahealthcheck.ipa.plugin import registry -@@ -13,11 +12,6 @@ from ipahealthcheck.ipa.topology import IPATopologyDomainCheck - - - class TestTopology(BaseTest): -- patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), -- } -- - def test_topology_ok(self): - m_api.Command.topologysuffix_verify.side_effect = [ - { -diff --git a/tests/test_ipa_tracking.py b/tests/test_ipa_tracking.py -index abcb9af..c40d8f4 100644 ---- a/tests/test_ipa_tracking.py -+++ b/tests/test_ipa_tracking.py -@@ -15,8 +15,6 @@ from mock_certmonger import get_expected_requests, set_requests - - class TestTracking(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ipahealthcheck.ipa.certs.get_expected_requests': - Mock(return_value=get_expected_requests()), - 'ipalib.install.certmonger._cm_dbus_object': -diff --git a/tests/test_ipa_trust.py b/tests/test_ipa_trust.py -index 2dcc4b3..0a1d58c 100644 ---- a/tests/test_ipa_trust.py -+++ b/tests/test_ipa_trust.py -@@ -102,11 +102,6 @@ class SSSDConfig(): - - - class TestTrustAgent(BaseTest): -- patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), -- } -- - def test_no_trust_agent(self): - framework = object() - registry.initialize(framework) -@@ -182,11 +177,6 @@ class TestTrustAgent(BaseTest): - - - class TestTrustDomains(BaseTest): -- patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), -- } -- - def test_no_trust_agent(self): - framework = object() - registry.initialize(framework) -@@ -371,11 +361,6 @@ class TestTrustDomains(BaseTest): - - - class TestTrustCatalog(BaseTest): -- patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), -- } -- - def test_no_trust_agent(self): - framework = object() - registry.initialize(framework) -@@ -477,8 +462,6 @@ class TestTrustCatalog(BaseTest): - - class Testsidgen(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ldap.initialize': - Mock(return_value=mock_ldap_conn()), - } -@@ -562,8 +545,6 @@ class Testsidgen(BaseTest): - - class TestTrustAgentMember(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ldap.initialize': - Mock(return_value=mock_ldap_conn()), - } -@@ -642,8 +623,6 @@ class TestTrustAgentMember(BaseTest): - - class TestControllerPrincipal(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ldap.initialize': - Mock(return_value=mock_ldap_conn()), - } -@@ -724,8 +703,6 @@ class TestControllerPrincipal(BaseTest): - - class TestControllerService(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ldap.initialize': - Mock(return_value=mock_ldap_conn()), - } -@@ -798,8 +775,6 @@ class TestControllerService(BaseTest): - - class TestControllerGroupSID(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ldap.initialize': - Mock(return_value=mock_ldap_conn()), - } -@@ -877,8 +852,6 @@ class TestControllerGroupSID(BaseTest): - - class TestControllerConf(BaseTest): - patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), - 'ldap.initialize': - Mock(return_value=mock_ldap_conn()), - } -@@ -922,11 +895,6 @@ class TestControllerConf(BaseTest): - - - class TestPackageCheck(BaseTest): -- patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), -- } -- - def test_agent_with_package(self): - # Note that this test assumes the import is installed - framework = object() -diff --git a/tests/test_meta_services.py b/tests/test_meta_services.py -index 0cb8f03..6fbea13 100644 ---- a/tests/test_meta_services.py -+++ b/tests/test_meta_services.py -@@ -7,15 +7,9 @@ from base import BaseTest - - from ipahealthcheck.ipa.plugin import registry - from ipahealthcheck.meta.services import httpd --from unittest.mock import Mock - - - class TestServices(BaseTest): -- patches = { -- 'ipaserver.install.installutils.check_server_configuration': -- Mock(return_value=None), -- } -- - def test_simple_service(self): - """ - Test a service. It was chosen at random. --- -2.20.1 - diff --git a/SOURCES/0004-Move-the-abstracted-plugin-runner-code-into-a-separa.patch b/SOURCES/0004-Move-the-abstracted-plugin-runner-code-into-a-separa.patch new file mode 100644 index 0000000..a27845e --- /dev/null +++ b/SOURCES/0004-Move-the-abstracted-plugin-runner-code-into-a-separa.patch @@ -0,0 +1,579 @@ +From 952fc6f6dee99523360c9826ad865086cd31474f Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Mon, 18 Nov 2019 14:33:32 -0500 +Subject: [PATCH 4/5] Move the abstracted plugin runner code into a separate + file + +This way main.py contains just the ipa-healthcheck main code +and not the rest of the abstracted code. + +Also replace sys.exit(1) with return 1. +--- + src/ipahealthcheck/core/core.py | 272 ++++++++++++++++++++++++++++++++ + src/ipahealthcheck/core/main.py | 267 +------------------------------ + 2 files changed, 273 insertions(+), 266 deletions(-) + create mode 100644 src/ipahealthcheck/core/core.py + +diff --git a/src/ipahealthcheck/core/core.py b/src/ipahealthcheck/core/core.py +new file mode 100644 +index 0000000..182eac3 +--- /dev/null ++++ b/src/ipahealthcheck/core/core.py +@@ -0,0 +1,272 @@ ++# ++# Copyright (C) 2019 FreeIPA Contributors see COPYING for license ++# ++ ++import argparse ++import json ++import logging ++import pkg_resources ++ ++from datetime import datetime ++ ++from ipahealthcheck.core.config import read_config ++from ipahealthcheck.core.plugin import Result, Results, json_to_results ++from ipahealthcheck.core.output import output_registry ++from ipahealthcheck.core import constants ++from ipahealthcheck.core.service import ServiceCheck ++ ++logging.basicConfig(format='%(message)s') ++logger = logging.getLogger() ++ ++ ++def find_registries(entry_points): ++ registries = {} ++ for entry_point in entry_points: ++ registries.update({ ++ ep.name: ep.resolve() ++ for ep in pkg_resources.iter_entry_points(entry_point) ++ }) ++ return registries ++ ++ ++def find_plugins(name, registry): ++ for ep in pkg_resources.iter_entry_points(name): ++ # load module ++ ep.load() ++ return registry.get_plugins() ++ ++ ++def run_plugin(plugin, available=()): ++ # manually calculate duration when we create results of our own ++ start = datetime.utcnow() ++ try: ++ for result in plugin.check(): ++ if result is None: ++ # Treat no result as success, fudge start time ++ result = Result(plugin, constants.SUCCESS, start=start) ++ yield result ++ except Exception as e: ++ logger.debug('Exception raised: %s', e) ++ yield Result(plugin, constants.CRITICAL, exception=str(e), ++ start=start) ++ ++ ++def source_or_check_matches(plugin, source, check): ++ """Determine whether a given a plugin matches if a source ++ and optional check are provided. ++ """ ++ if source is not None and plugin.__module__ != source: ++ return False ++ ++ if check and plugin.__class__.__name__ != check: ++ return False ++ ++ return True ++ ++ ++def run_service_plugins(plugins, config, source, check): ++ """Execute plugins with the base class of ServiceCheck ++ ++ This is a specialized check to use systemd to determine ++ if a service is running or not. ++ """ ++ results = Results() ++ available = [] ++ ++ for plugin in plugins: ++ if not isinstance(plugin, ServiceCheck): ++ continue ++ ++ logger.debug('Calling check %s', plugin) ++ for result in plugin.check(): ++ # always run the service checks so dependencies work ++ if result is not None and result.result == constants.SUCCESS: ++ available.append(plugin.service.service_name) ++ if not source_or_check_matches(plugin, source, check): ++ continue ++ if result is not None: ++ results.add(result) ++ ++ return results, set(available) ++ ++ ++def run_plugins(plugins, config, available, source, check): ++ """Execute plugins without the base class of ServiceCheck ++ ++ These are the remaining, non-service checking checks ++ that do validation for various parts of a system. ++ """ ++ results = Results() ++ ++ for plugin in plugins: ++ if isinstance(plugin, ServiceCheck): ++ continue ++ ++ if not source_or_check_matches(plugin, source, check): ++ continue ++ ++ logger.debug('Calling check %s' % plugin) ++ plugin.config = config ++ if not set(plugin.requires).issubset(available): ++ logger.debug('Skipping %s:%s because %s service(s) not running', ++ plugin.__class__.__module__, ++ plugin.__class__.__name__, ++ ', '.join(set(plugin.requires) - available)) ++ # Not providing a Result in this case because if a required ++ # service isn't available then this could generate a lot of ++ # false positives. ++ else: ++ for result in run_plugin(plugin, available): ++ results.add(result) ++ ++ return results ++ ++ ++def list_sources(plugins): ++ """Print list of all sources and checks""" ++ source = None ++ for plugin in plugins: ++ if source != plugin.__class__.__module__: ++ print(plugin.__class__.__module__) ++ source = plugin.__class__.__module__ ++ print(" ", plugin.__class__.__name__) ++ ++ return 0 ++ ++ ++def parse_options(output_registry): ++ output_names = [plugin.__name__.lower() for ++ plugin in output_registry.plugins] ++ parser = argparse.ArgumentParser() ++ parser.add_argument('--debug', dest='debug', action='store_true', ++ default=False, help='Include debug output') ++ parser.add_argument('--list-sources', dest='list_sources', ++ action='store_true', default=False, ++ help='List all available sources') ++ parser.add_argument('--source', dest='source', ++ default=None, ++ help='Source of checks, e.g. ipahealthcheck.foo.bar') ++ parser.add_argument('--check', dest='check', ++ default=None, ++ help='Check to execute, e.g. BazCheck') ++ parser.add_argument('--output-type', dest='output', choices=output_names, ++ default='json', help='Output method') ++ parser.add_argument('--output-file', dest='outfile', default=None, ++ help='File to store output') ++ parser.add_argument('--input-file', dest='infile', ++ help='File to read as input') ++ parser.add_argument('--failures-only', dest='failures_only', ++ action='store_true', default=False, ++ help='Exclude SUCCESS results on output') ++ parser.add_argument('--severity', dest='severity', action="append", ++ help='Include only the selected severity(s)', ++ choices=[key for key in constants._nameToLevel]) ++ for plugin in output_registry.plugins: ++ onelinedoc = plugin.__doc__.split('\n\n', 1)[0].strip() ++ group = parser.add_argument_group(plugin.__name__.lower(), ++ onelinedoc) ++ for option in plugin.options: ++ group.add_argument(option[0], **option[1]) ++ ++ options = parser.parse_args() ++ ++ # Validation ++ if options.check and not options.source: ++ print("--source is required when --check is used") ++ return 1 ++ ++ return options ++ ++ ++def limit_results(results, source, check): ++ """Return ony those results which match source and/or check""" ++ new_results = Results() ++ for result in results.results: ++ if result.source == source: ++ if check is None or result.check == check: ++ new_results.add(result) ++ return new_results ++ ++ ++def run_healthcheck(entry_points, configfile): ++ framework = object() ++ plugins = [] ++ output = constants.DEFAULT_OUTPUT ++ ++ logger.setLevel(logging.INFO) ++ ++ options = parse_options(output_registry) ++ ++ if options.debug: ++ logger.setLevel(logging.DEBUG) ++ ++ config = read_config(configfile) ++ if config is None: ++ return 1 ++ ++ for name, registry in find_registries(entry_points).items(): ++ try: ++ registry.initialize(framework) ++ except Exception as e: ++ print("Unable to initialize %s: %s" % (name, e)) ++ return 1 ++ for plugin in find_plugins(name, registry): ++ plugins.append(plugin) ++ ++ for out in output_registry.plugins: ++ if out.__name__.lower() == options.output: ++ output = out(options) ++ ++ if options.list_sources: ++ return list_sources(plugins) ++ ++ if options.infile: ++ try: ++ with open(options.infile, 'r') as f: ++ raw_data = f.read() ++ ++ json_data = json.loads(raw_data) ++ results = json_to_results(json_data) ++ available = () ++ except Exception as e: ++ print("Unable to import '%s': %s" % (options.infile, e)) ++ return 1 ++ if options.source: ++ results = limit_results(results, options.source, options.check) ++ else: ++ results, available = run_service_plugins(plugins, config, ++ options.source, ++ options.check) ++ results.extend(run_plugins(plugins, config, available, ++ options.source, options.check)) ++ ++ if options.source and len(results.results) == 0: ++ for plugin in plugins: ++ if not source_or_check_matches(plugin, options.source, ++ options.check): ++ continue ++ ++ if not set(plugin.requires).issubset(available): ++ print("Source '%s' is missing one or more requirements '%s'" % ++ (options.source, ', '.join(plugin.requires))) ++ return 1 ++ ++ if options.check: ++ print("Check '%s' not found in Source '%s'" % ++ (options.check, options.source)) ++ else: ++ print("Source '%s' not found" % options.source) ++ return 1 ++ ++ try: ++ output.render(results) ++ except Exception as e: ++ logger.error('Output raised %s: %s', e.__class__.__name__, e) ++ ++ return_value = 0 ++ for result in results.results: ++ if result.result != constants.SUCCESS: ++ return_value = 1 ++ break ++ ++ return return_value +diff --git a/src/ipahealthcheck/core/main.py b/src/ipahealthcheck/core/main.py +index 2b818d4..d9e85d7 100644 +--- a/src/ipahealthcheck/core/main.py ++++ b/src/ipahealthcheck/core/main.py +@@ -2,276 +2,11 @@ + # Copyright (C) 2019 FreeIPA Contributors see COPYING for license + # + +-import argparse +-import json +-import logging + from os import environ +-import pkg_resources + import sys + +-from datetime import datetime +- +-from ipahealthcheck.core.config import read_config +-from ipahealthcheck.core.plugin import Result, Results, json_to_results +-from ipahealthcheck.core.output import output_registry + from ipahealthcheck.core import constants +-from ipahealthcheck.core.service import ServiceCheck +- +-logging.basicConfig(format='%(message)s') +-logger = logging.getLogger() +- +- +-def find_registries(entry_points): +- registries = {} +- for entry_point in entry_points: +- registries.update({ +- ep.name: ep.resolve() +- for ep in pkg_resources.iter_entry_points(entry_point) +- }) +- return registries +- +- +-def find_plugins(name, registry): +- for ep in pkg_resources.iter_entry_points(name): +- # load module +- ep.load() +- return registry.get_plugins() +- +- +-def run_plugin(plugin, available=()): +- # manually calculate duration when we create results of our own +- start = datetime.utcnow() +- try: +- for result in plugin.check(): +- if result is None: +- # Treat no result as success, fudge start time +- result = Result(plugin, constants.SUCCESS, start=start) +- yield result +- except Exception as e: +- logger.debug('Exception raised: %s', e) +- yield Result(plugin, constants.CRITICAL, exception=str(e), +- start=start) +- +- +-def source_or_check_matches(plugin, source, check): +- """Determine whether a given a plugin matches if a source +- and optional check are provided. +- """ +- if source is not None and plugin.__module__ != source: +- return False +- +- if check and plugin.__class__.__name__ != check: +- return False +- +- return True +- +- +-def run_service_plugins(plugins, config, source, check): +- """Execute plugins with the base class of ServiceCheck +- +- This is a specialized check to use systemd to determine +- if a service is running or not. +- """ +- results = Results() +- available = [] +- +- for plugin in plugins: +- if not isinstance(plugin, ServiceCheck): +- continue +- +- logger.debug('Calling check %s', plugin) +- for result in plugin.check(): +- # always run the service checks so dependencies work +- if result is not None and result.result == constants.SUCCESS: +- available.append(plugin.service.service_name) +- if not source_or_check_matches(plugin, source, check): +- continue +- if result is not None: +- results.add(result) +- +- return results, set(available) +- +- +-def run_plugins(plugins, config, available, source, check): +- """Execute plugins without the base class of ServiceCheck +- +- These are the remaining, non-service checking checks +- that do validation for various parts of a system. +- """ +- results = Results() +- +- for plugin in plugins: +- if isinstance(plugin, ServiceCheck): +- continue +- +- if not source_or_check_matches(plugin, source, check): +- continue +- +- logger.debug('Calling check %s' % plugin) +- plugin.config = config +- if not set(plugin.requires).issubset(available): +- logger.debug('Skipping %s:%s because %s service(s) not running', +- plugin.__class__.__module__, +- plugin.__class__.__name__, +- ', '.join(set(plugin.requires) - available)) +- # Not providing a Result in this case because if a required +- # service isn't available then this could generate a lot of +- # false positives. +- else: +- for result in run_plugin(plugin, available): +- results.add(result) +- +- return results +- +- +-def list_sources(plugins): +- """Print list of all sources and checks""" +- source = None +- for plugin in plugins: +- if source != plugin.__class__.__module__: +- print(plugin.__class__.__module__) +- source = plugin.__class__.__module__ +- print(" ", plugin.__class__.__name__) +- +- return 0 +- +- +-def parse_options(output_registry): +- output_names = [plugin.__name__.lower() for +- plugin in output_registry.plugins] +- parser = argparse.ArgumentParser() +- parser.add_argument('--debug', dest='debug', action='store_true', +- default=False, help='Include debug output') +- parser.add_argument('--list-sources', dest='list_sources', +- action='store_true', default=False, +- help='List all available sources') +- parser.add_argument('--source', dest='source', +- default=None, +- help='Source of checks, e.g. ipahealthcheck.foo.bar') +- parser.add_argument('--check', dest='check', +- default=None, +- help='Check to execute, e.g. BazCheck') +- parser.add_argument('--output-type', dest='output', choices=output_names, +- default='json', help='Output method') +- parser.add_argument('--output-file', dest='outfile', default=None, +- help='File to store output') +- parser.add_argument('--input-file', dest='infile', +- help='File to read as input') +- parser.add_argument('--failures-only', dest='failures_only', +- action='store_true', default=False, +- help='Exclude SUCCESS results on output') +- parser.add_argument('--severity', dest='severity', action="append", +- help='Include only the selected severity(s)', +- choices=[key for key in constants._nameToLevel]) +- for plugin in output_registry.plugins: +- onelinedoc = plugin.__doc__.split('\n\n', 1)[0].strip() +- group = parser.add_argument_group(plugin.__name__.lower(), +- onelinedoc) +- for option in plugin.options: +- group.add_argument(option[0], **option[1]) +- +- options = parser.parse_args() +- +- # Validation +- if options.check and not options.source: +- print("--source is required when --check is used") +- sys.exit(1) +- +- return options +- +- +-def limit_results(results, source, check): +- """Return ony those results which match source and/or check""" +- new_results = Results() +- for result in results.results: +- if result.source == source: +- if check is None or result.check == check: +- new_results.add(result) +- return new_results +- +- +-def run_healthcheck(entry_points, configfile): +- framework = object() +- plugins = [] +- output = constants.DEFAULT_OUTPUT +- +- logger.setLevel(logging.INFO) +- +- options = parse_options(output_registry) +- +- if options.debug: +- logger.setLevel(logging.DEBUG) +- +- config = read_config(configfile) +- if config is None: +- sys.exit(1) +- +- for name, registry in find_registries(entry_points).items(): +- try: +- registry.initialize(framework) +- except Exception as e: +- print("Unable to initialize %s: %s" % (name, e)) +- sys.exit(1) +- for plugin in find_plugins(name, registry): +- plugins.append(plugin) +- +- for out in output_registry.plugins: +- if out.__name__.lower() == options.output: +- output = out(options) +- +- if options.list_sources: +- return list_sources(plugins) +- +- if options.infile: +- try: +- with open(options.infile, 'r') as f: +- raw_data = f.read() +- +- json_data = json.loads(raw_data) +- results = json_to_results(json_data) +- available = () +- except Exception as e: +- print("Unable to import '%s': %s" % (options.infile, e)) +- sys.exit(1) +- if options.source: +- results = limit_results(results, options.source, options.check) +- else: +- results, available = run_service_plugins(plugins, config, +- options.source, +- options.check) +- results.extend(run_plugins(plugins, config, available, +- options.source, options.check)) +- +- if options.source and len(results.results) == 0: +- for plugin in plugins: +- if not source_or_check_matches(plugin, options.source, +- options.check): +- continue +- +- if not set(plugin.requires).issubset(available): +- print("Source '%s' is missing one or more requirements '%s'" % +- (options.source, ', '.join(plugin.requires))) +- sys.exit(1) +- +- if options.check: +- print("Check '%s' not found in Source '%s'" % +- (options.check, options.source)) +- else: +- print("Source '%s' not found" % options.source) +- sys.exit(1) +- +- try: +- output.render(results) +- except Exception as e: +- logger.error('Output raised %s: %s', e.__class__.__name__, e) +- +- return_value = 0 +- for result in results.results: +- if result.result != constants.SUCCESS: +- return_value = 1 +- break +- +- return return_value ++from ipahealthcheck.core.core import run_healthcheck + + + def main(): +-- +2.20.1 + diff --git a/SOURCES/0005-Convert-running-healthchecks-into-a-class-and-add-pr.patch b/SOURCES/0005-Convert-running-healthchecks-into-a-class-and-add-pr.patch new file mode 100644 index 0000000..7a071e4 --- /dev/null +++ b/SOURCES/0005-Convert-running-healthchecks-into-a-class-and-add-pr.patch @@ -0,0 +1,228 @@ +From af5c169151f0697d34954ac5c9dd0686dc73ef3f Mon Sep 17 00:00:00 2001 +From: Rob Crittenden +Date: Mon, 18 Nov 2019 15:13:44 -0500 +Subject: [PATCH 5/5] Convert running healthchecks into a class and add + pre-check + +Add a pre-check so that dependencies can be checked per product. +In the case of IPA verify that the server is installed otherwise +bail out. +--- + src/ipahealthcheck/core/core.py | 168 +++++++++++++++++--------------- + src/ipahealthcheck/core/main.py | 17 +++- + 2 files changed, 104 insertions(+), 81 deletions(-) + +diff --git a/src/ipahealthcheck/core/core.py b/src/ipahealthcheck/core/core.py +index 182eac3..aef6197 100644 +--- a/src/ipahealthcheck/core/core.py ++++ b/src/ipahealthcheck/core/core.py +@@ -188,85 +188,97 @@ def limit_results(results, source, check): + return new_results + + +-def run_healthcheck(entry_points, configfile): +- framework = object() +- plugins = [] +- output = constants.DEFAULT_OUTPUT +- +- logger.setLevel(logging.INFO) +- +- options = parse_options(output_registry) +- +- if options.debug: +- logger.setLevel(logging.DEBUG) +- +- config = read_config(configfile) +- if config is None: +- return 1 +- +- for name, registry in find_registries(entry_points).items(): +- try: +- registry.initialize(framework) +- except Exception as e: +- print("Unable to initialize %s: %s" % (name, e)) +- return 1 +- for plugin in find_plugins(name, registry): +- plugins.append(plugin) +- +- for out in output_registry.plugins: +- if out.__name__.lower() == options.output: +- output = out(options) +- +- if options.list_sources: +- return list_sources(plugins) +- +- if options.infile: +- try: +- with open(options.infile, 'r') as f: +- raw_data = f.read() +- +- json_data = json.loads(raw_data) +- results = json_to_results(json_data) +- available = () +- except Exception as e: +- print("Unable to import '%s': %s" % (options.infile, e)) ++class RunChecks: ++ def __init__(self, entry_points, configfile): ++ self.entry_points = entry_points ++ self.configfile = configfile ++ ++ def pre_check(self): ++ pass ++ ++ def run_healthcheck(self): ++ framework = object() ++ plugins = [] ++ output = constants.DEFAULT_OUTPUT ++ ++ logger.setLevel(logging.INFO) ++ ++ options = parse_options(output_registry) ++ ++ if options.debug: ++ logger.setLevel(logging.DEBUG) ++ ++ config = read_config(self.configfile) ++ if config is None: + return 1 +- if options.source: +- results = limit_results(results, options.source, options.check) +- else: +- results, available = run_service_plugins(plugins, config, +- options.source, +- options.check) +- results.extend(run_plugins(plugins, config, available, +- options.source, options.check)) +- +- if options.source and len(results.results) == 0: +- for plugin in plugins: +- if not source_or_check_matches(plugin, options.source, +- options.check): +- continue + +- if not set(plugin.requires).issubset(available): +- print("Source '%s' is missing one or more requirements '%s'" % +- (options.source, ', '.join(plugin.requires))) ++ rval = self.pre_check() ++ if rval is not None: ++ return rval ++ ++ for name, registry in find_registries(self.entry_points).items(): ++ try: ++ registry.initialize(framework) ++ except Exception as e: ++ print("Unable to initialize %s: %s" % (name, e)) + return 1 +- +- if options.check: +- print("Check '%s' not found in Source '%s'" % +- (options.check, options.source)) ++ for plugin in find_plugins(name, registry): ++ plugins.append(plugin) ++ ++ for out in output_registry.plugins: ++ if out.__name__.lower() == options.output: ++ output = out(options) ++ ++ if options.list_sources: ++ return list_sources(plugins) ++ ++ if options.infile: ++ try: ++ with open(options.infile, 'r') as f: ++ raw_data = f.read() ++ ++ json_data = json.loads(raw_data) ++ results = json_to_results(json_data) ++ available = () ++ except Exception as e: ++ print("Unable to import '%s': %s" % (options.infile, e)) ++ return 1 ++ if options.source: ++ results = limit_results(results, options.source, options.check) + else: +- print("Source '%s' not found" % options.source) +- return 1 +- +- try: +- output.render(results) +- except Exception as e: +- logger.error('Output raised %s: %s', e.__class__.__name__, e) +- +- return_value = 0 +- for result in results.results: +- if result.result != constants.SUCCESS: +- return_value = 1 +- break +- +- return return_value ++ results, available = run_service_plugins(plugins, config, ++ options.source, ++ options.check) ++ results.extend(run_plugins(plugins, config, available, ++ options.source, options.check)) ++ ++ if options.source and len(results.results) == 0: ++ for plugin in plugins: ++ if not source_or_check_matches(plugin, options.source, ++ options.check): ++ continue ++ ++ if not set(plugin.requires).issubset(available): ++ print("Source '%s' is missing one or more requirements '%s'" % ++ (options.source, ', '.join(plugin.requires))) ++ return 1 ++ ++ if options.check: ++ print("Check '%s' not found in Source '%s'" % ++ (options.check, options.source)) ++ else: ++ print("Source '%s' not found" % options.source) ++ return 1 ++ ++ try: ++ output.render(results) ++ except Exception as e: ++ logger.error('Output raised %s: %s', e.__class__.__name__, e) ++ ++ return_value = 0 ++ for result in results.results: ++ if result.result != constants.SUCCESS: ++ return_value = 1 ++ break ++ ++ return return_value +diff --git a/src/ipahealthcheck/core/main.py b/src/ipahealthcheck/core/main.py +index d9e85d7..63a1de6 100644 +--- a/src/ipahealthcheck/core/main.py ++++ b/src/ipahealthcheck/core/main.py +@@ -6,12 +6,23 @@ from os import environ + import sys + + from ipahealthcheck.core import constants +-from ipahealthcheck.core.core import run_healthcheck ++from ipahealthcheck.core.core import RunChecks ++ ++from ipaserver.install.installutils import is_ipa_configured ++ ++ ++class IPAChecks(RunChecks): ++ def pre_check(self): ++ if not is_ipa_configured(): ++ print("IPA is not configured") ++ return 1 + + + def main(): + environ["KRB5_CLIENT_KTNAME"] = "/etc/krb5.keytab" + environ["KRB5CCNAME"] = "MEMORY:" + +- sys.exit(run_healthcheck(['ipahealthcheck.registry'], +- constants.CONFIG_FILE)) ++ ipachecks = IPAChecks(['ipahealthcheck.registry', ++ 'pkihealthcheck.registry'], ++ constants.CONFIG_FILE) ++ sys.exit(ipachecks.run_healthcheck()) +-- +2.20.1 + diff --git a/SOURCES/0005-Mock-the-AD-trust-roles.patch b/SOURCES/0005-Mock-the-AD-trust-roles.patch deleted file mode 100644 index 910c6e2..0000000 --- a/SOURCES/0005-Mock-the-AD-trust-roles.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0727c05df8e2b9cd6977bf076e88e5da0fd573a6 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Tue, 6 Aug 2019 16:04:40 -0400 -Subject: [PATCH 5/8] Mock the AD trust roles - -The actual values are set directly in the registry but these classes -provide just enough implementation to allow the code to initialize. ---- - src/ipahealthcheck/ipa/plugin.py | 4 +++- - tests/base.py | 5 +++++ - tests/util.py | 27 +++++++++++++++++++++++++++ - 3 files changed, 35 insertions(+), 1 deletion(-) - -diff --git a/src/ipahealthcheck/ipa/plugin.py b/src/ipahealthcheck/ipa/plugin.py -index c4cef9b..bd95c16 100644 ---- a/src/ipahealthcheck/ipa/plugin.py -+++ b/src/ipahealthcheck/ipa/plugin.py -@@ -12,7 +12,6 @@ from ipaserver.install import cainstance - from ipaserver.install import dsinstance - from ipaserver.install import httpinstance - from ipaserver.install import installutils --from ipaserver.servroles import ADtrustBasedRole, ServiceBasedRole - - from ipahealthcheck.core.plugin import Plugin, Registry - -@@ -38,6 +37,9 @@ class IPARegistry(Registry): - self.trust_controller = False - - def initialize(self, framework): -+ # deferred import for mock -+ from ipaserver.servroles import ADtrustBasedRole, ServiceBasedRole -+ - installutils.check_server_configuration() - - if not api.isdone('finalize'): -diff --git a/tests/base.py b/tests/base.py -index 8b9e37c..d1d2442 100644 ---- a/tests/base.py -+++ b/tests/base.py -@@ -3,6 +3,7 @@ - # - from unittest import mock, TestCase - from util import no_exceptions -+from util import ADtrustBasedRole, ServiceBasedRole - - - class BaseTest(TestCase): -@@ -24,6 +25,10 @@ class BaseTest(TestCase): - default_patches = { - 'ipaserver.install.installutils.check_server_configuration': - mock.Mock(return_value=None), -+ 'ipaserver.servroles.ServiceBasedRole': -+ mock.Mock(return_value=ServiceBasedRole()), -+ 'ipaserver.servroles.ADtrustBasedRole': -+ mock.Mock(return_value=ADtrustBasedRole()), - } - patches = {} - -diff --git a/tests/util.py b/tests/util.py -index 603185f..5bd592e 100644 ---- a/tests/util.py -+++ b/tests/util.py -@@ -76,6 +76,33 @@ class KRAInstance: - return self.installed - - -+class ServiceBasedRole: -+ """A bare-bones role override -+ -+ This is just enough to satisfy the initialization code so -+ the AD Trust status can be determined. It will always default -+ to false and the registry should be overridden directly in the -+ test cases. -+ """ -+ def __init__(self, attr_name=None, name=None, component_services=None): -+ pass -+ -+ def status(self, api_instance, server=None, attrs_list=("*",)): -+ return [dict()] -+ -+ -+class ADtrustBasedRole(ServiceBasedRole): -+ """A bare-bones role override -+ -+ This is just enough to satisfy the initialization code so -+ the AD Trust status can be determined. It will always default -+ to false and the registry should be overridden directly in the -+ test cases. -+ """ -+ def __init__(self, attr_name=None, name=None): -+ pass -+ -+ - # Mock api. This file needs to be imported before anything that would - # import ipalib.api in order for it to be replaced properly. - --- -2.20.1 - diff --git a/SOURCES/0006-Force-the-KRA-to-be-off-during-NSS-db-trust-tests.patch b/SOURCES/0006-Force-the-KRA-to-be-off-during-NSS-db-trust-tests.patch deleted file mode 100644 index 7a095de..0000000 --- a/SOURCES/0006-Force-the-KRA-to-be-off-during-NSS-db-trust-tests.patch +++ /dev/null @@ -1,36 +0,0 @@ -From ae70afc781098b628b40894f9e0e841d3ba5b585 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Tue, 6 Aug 2019 16:45:46 -0400 -Subject: [PATCH 6/8] Force the KRA to be off during NSS db trust tests - -This avoids the side-effect of something else enabling the KRA and that -bleeding into the test. ---- - tests/test_ipa_nssdb.py | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/tests/test_ipa_nssdb.py b/tests/test_ipa_nssdb.py -index 7d5664e..590401c 100644 ---- a/tests/test_ipa_nssdb.py -+++ b/tests/test_ipa_nssdb.py -@@ -2,7 +2,7 @@ - # Copyright (C) 2019 FreeIPA Contributors see COPYING for license - # - --from util import capture_results, CAInstance -+from util import capture_results, CAInstance, KRAInstance - from base import BaseTest - from ipahealthcheck.core import config, constants - from ipahealthcheck.ipa.plugin import registry -@@ -30,6 +30,8 @@ class TestNSSDBTrust(BaseTest): - patches = { - 'ipaserver.install.cainstance.CAInstance': - Mock(return_value=CAInstance()), -+ 'ipaserver.install.krainstance.KRAInstance': -+ Mock(return_value=KRAInstance(False)), - 'ipapython.certdb.unparse_trust_flags': - Mock(side_effect=my_unparse_trust_flags), - } --- -2.20.1 - diff --git a/SOURCES/0006-Move-config-object-from-plugins-to-registry.patch b/SOURCES/0006-Move-config-object-from-plugins-to-registry.patch new file mode 100644 index 0000000..df32763 --- /dev/null +++ b/SOURCES/0006-Move-config-object-from-plugins-to-registry.patch @@ -0,0 +1,1535 @@ +From 9b6a90f1fc2508252bcb33791b24ec53f6b471cb Mon Sep 17 00:00:00 2001 +From: Dinesh Prasanth M K +Date: Tue, 10 Dec 2019 14:02:16 -0500 +Subject: [PATCH] Move config object from plugins to registry + +This patch moves the config object from the plugins +to the registry, thereby allowing the plugins to use +the values parsed from the healthcheck.conf file while +initializing. This improves the way a plugin can use +the values defined in the conf + +Signed-off-by: Dinesh Prasanth M K +--- + src/ipahealthcheck/core/core.py | 11 ++- + src/ipahealthcheck/core/plugin.py | 6 +- + src/ipahealthcheck/dogtag/plugin.py | 3 +- + src/ipahealthcheck/ds/plugin.py | 3 +- + src/ipahealthcheck/ipa/plugin.py | 3 +- + src/ipahealthcheck/system/plugin.py | 2 +- + tests/test_dogtag_ca.py | 9 +-- + tests/test_dogtag_connectivity.py | 8 +-- + tests/test_ds_replication.py | 6 +- + tests/test_ds_ruv.py | 9 +-- + tests/test_ipa_agent.py | 21 ++---- + tests/test_ipa_certfile_expiration.py | 9 +-- + tests/test_ipa_certmonger_ca.py | 6 +- + tests/test_ipa_dna.py | 9 +-- + tests/test_ipa_dns.py | 27 +++----- + tests/test_ipa_expiration.py | 18 ++--- + tests/test_ipa_nssdb.py | 12 ++-- + tests/test_ipa_nssvalidation.py | 9 +-- + tests/test_ipa_opensslvalidation.py | 6 +- + tests/test_ipa_revocation.py | 6 +- + tests/test_ipa_roles.py | 15 ++--- + tests/test_ipa_topology.py | 12 ++-- + tests/test_ipa_tracking.py | 8 +-- + tests/test_ipa_trust.py | 96 +++++++++------------------ + tests/test_meta_services.py | 3 +- + tests/test_system_filesystemspace.py | 9 +-- + 26 files changed, 120 insertions(+), 206 deletions(-) + +diff --git a/src/ipahealthcheck/core/core.py b/src/ipahealthcheck/core/core.py +index aef6197..ade8455 100644 +--- a/src/ipahealthcheck/core/core.py ++++ b/src/ipahealthcheck/core/core.py +@@ -64,7 +64,7 @@ def source_or_check_matches(plugin, source, check): + return True + + +-def run_service_plugins(plugins, config, source, check): ++def run_service_plugins(plugins, source, check): + """Execute plugins with the base class of ServiceCheck + + This is a specialized check to use systemd to determine +@@ -90,7 +90,7 @@ def run_service_plugins(plugins, config, source, check): + return results, set(available) + + +-def run_plugins(plugins, config, available, source, check): ++def run_plugins(plugins, available, source, check): + """Execute plugins without the base class of ServiceCheck + + These are the remaining, non-service checking checks +@@ -106,7 +106,6 @@ def run_plugins(plugins, config, available, source, check): + continue + + logger.debug('Calling check %s' % plugin) +- plugin.config = config + if not set(plugin.requires).issubset(available): + logger.debug('Skipping %s:%s because %s service(s) not running', + plugin.__class__.__module__, +@@ -218,7 +217,7 @@ class RunChecks: + + for name, registry in find_registries(self.entry_points).items(): + try: +- registry.initialize(framework) ++ registry.initialize(framework, config) + except Exception as e: + print("Unable to initialize %s: %s" % (name, e)) + return 1 +@@ -246,10 +245,10 @@ class RunChecks: + if options.source: + results = limit_results(results, options.source, options.check) + else: +- results, available = run_service_plugins(plugins, config, ++ results, available = run_service_plugins(plugins, + options.source, + options.check) +- results.extend(run_plugins(plugins, config, available, ++ results.extend(run_plugins(plugins, available, + options.source, options.check)) + + if options.source and len(results.results) == 0: +diff --git a/src/ipahealthcheck/core/plugin.py b/src/ipahealthcheck/core/plugin.py +index 6a29a7f..5754808 100644 +--- a/src/ipahealthcheck/core/plugin.py ++++ b/src/ipahealthcheck/core/plugin.py +@@ -41,9 +41,11 @@ class Registry: + def __init__(self): + self.plugins = [] + self.framework = None ++ self.config = dict() + +- def initialize(self, framework): ++ def initialize(self, framework, config): + self.framework = framework ++ self.config = config + + def __call__(self, cls): + if not callable(cls): +@@ -98,7 +100,7 @@ class Plugin: + + def __init__(self, registry): + self.registry = registry +- self.config = dict() ++ self.config = registry.config + + + class Result: +diff --git a/src/ipahealthcheck/dogtag/plugin.py b/src/ipahealthcheck/dogtag/plugin.py +index 3d8257e..d54fe3b 100644 +--- a/src/ipahealthcheck/dogtag/plugin.py ++++ b/src/ipahealthcheck/dogtag/plugin.py +@@ -16,7 +16,8 @@ class DogtagPlugin(Plugin): + + + class DogtagRegistry(Registry): +- def initialize(self, framework): ++ def initialize(self, framework, config): ++ super(DogtagRegistry, self).initialize(framework, config) + installutils.check_server_configuration() + if not api.isdone('bootstrap'): + api.bootstrap(in_server=True, +diff --git a/src/ipahealthcheck/ds/plugin.py b/src/ipahealthcheck/ds/plugin.py +index 9ef3461..0e40922 100644 +--- a/src/ipahealthcheck/ds/plugin.py ++++ b/src/ipahealthcheck/ds/plugin.py +@@ -16,7 +16,8 @@ class DSPlugin(Plugin): + + + class DSRegistry(Registry): +- def initialize(self, framework): ++ def initialize(self, framework, config): ++ super(DSRegistry, self).initialize(framework, config) + installutils.check_server_configuration() + if not api.isdone('bootstrap'): + api.bootstrap(in_server=True, +diff --git a/src/ipahealthcheck/ipa/plugin.py b/src/ipahealthcheck/ipa/plugin.py +index 34cb8c9..c1a6d39 100644 +--- a/src/ipahealthcheck/ipa/plugin.py ++++ b/src/ipahealthcheck/ipa/plugin.py +@@ -36,7 +36,8 @@ class IPARegistry(Registry): + self.trust_agent = False + self.trust_controller = False + +- def initialize(self, framework): ++ def initialize(self, framework, config): ++ super(IPARegistry, self).initialize(framework, config) + # deferred import for mock + from ipaserver.servroles import ADtrustBasedRole, ServiceBasedRole + +diff --git a/src/ipahealthcheck/system/plugin.py b/src/ipahealthcheck/system/plugin.py +index 23e8b5e..03d8c23 100644 +--- a/src/ipahealthcheck/system/plugin.py ++++ b/src/ipahealthcheck/system/plugin.py +@@ -12,7 +12,7 @@ class SystemPlugin(Plugin): + + + class SystemRegistry(Registry): +- def initialize(self, framework): ++ def initialize(self, framework, config): + pass + + +diff --git a/tests/test_dogtag_ca.py b/tests/test_dogtag_ca.py +index 48eba20..0820aba 100644 +--- a/tests/test_dogtag_ca.py ++++ b/tests/test_dogtag_ca.py +@@ -59,10 +59,9 @@ class TestCACerts(BaseTest): + mock_directive.side_effect = [name for name, nsstrust in trust.items()] + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config()) + f = DogtagCertsConfigCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 6 +@@ -98,10 +97,9 @@ class TestCACerts(BaseTest): + mock_directive.side_effect = nicknames + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = DogtagCertsConfigCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + num = len(self.results.results) +@@ -129,10 +127,9 @@ class TestCACerts(BaseTest): + mock_cainstance.return_value = CAInstance(False) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config) + f = DogtagCertsConfigCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 0 +diff --git a/tests/test_dogtag_connectivity.py b/tests/test_dogtag_connectivity.py +index 544e325..7165706 100644 +--- a/tests/test_dogtag_connectivity.py ++++ b/tests/test_dogtag_connectivity.py +@@ -5,7 +5,7 @@ + from util import capture_results, CAInstance + from util import m_api + from base import BaseTest +-from ipahealthcheck.core import constants ++from ipahealthcheck.core import constants, config + from ipahealthcheck.dogtag.plugin import registry + from ipahealthcheck.dogtag.ca import DogtagCertsConnectivityCheck + from unittest.mock import Mock +@@ -26,7 +26,7 @@ class TestCAConnectivity(BaseTest): + } + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = DogtagCertsConnectivityCheck(registry) + + self.results = capture_results(f) +@@ -47,7 +47,7 @@ class TestCAConnectivity(BaseTest): + ) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = DogtagCertsConnectivityCheck(registry) + + self.results = capture_results(f) +@@ -67,7 +67,7 @@ class TestCAConnectivity(BaseTest): + ) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = DogtagCertsConnectivityCheck(registry) + + self.results = capture_results(f) +diff --git a/tests/test_ds_replication.py b/tests/test_ds_replication.py +index b6b3652..24e909e 100644 +--- a/tests/test_ds_replication.py ++++ b/tests/test_ds_replication.py +@@ -44,10 +44,9 @@ class TestReplicationConflicts(BaseTest): + mock_conn.return_value = mock_ldap(None) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = ReplicationConflictCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + # A valid call relies on a success to be set by core +@@ -73,10 +72,9 @@ class TestReplicationConflicts(BaseTest): + mock_conn.return_value = mock_ldap([ldapentry]) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = ReplicationConflictCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + result = self.results.results[0] + +diff --git a/tests/test_ds_ruv.py b/tests/test_ds_ruv.py +index 37070f5..8a3fe84 100644 +--- a/tests/test_ds_ruv.py ++++ b/tests/test_ds_ruv.py +@@ -63,11 +63,10 @@ class TestRUV(BaseTest): + + def test_no_ruvs(self): + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = RUVCheck(registry) + + f.conn = mock_ldap(None) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 0 +@@ -88,11 +87,10 @@ class TestRUV(BaseTest): + ) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = RUVCheck(registry) + + f.conn = mock_ldap(entries) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 2 +@@ -123,11 +121,10 @@ class TestRUV(BaseTest): + entries.append(None) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = RUVCheck(registry) + + f.conn = mock_ldap(entries) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +diff --git a/tests/test_ipa_agent.py b/tests/test_ipa_agent.py +index c58c7a6..8021298 100644 +--- a/tests/test_ipa_agent.py ++++ b/tests/test_ipa_agent.py +@@ -76,11 +76,10 @@ class TestNSSAgent(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config()) + f = IPARAAgent(registry) + + f.conn = mock_ldap([ldapentry]) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -101,11 +100,10 @@ class TestNSSAgent(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config()) + f = IPARAAgent(registry) + + f.conn = mock_ldap([ldapentry]) +- f.config = config.Config() + self.results = capture_results(f) + result = self.results.results[0] + +@@ -118,10 +116,9 @@ class TestNSSAgent(BaseTest): + mock_load_cert.side_effect = IOError('test') + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config()) + f = IPARAAgent(registry) + +- f.config = config.Config() + self.results = capture_results(f) + result = self.results.results[0] + +@@ -131,11 +128,10 @@ class TestNSSAgent(BaseTest): + def test_nss_agent_no_entry_found(self): + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config()) + f = IPARAAgent(registry) + + f.conn = mock_ldap(None) # None == NotFound +- f.config = config.Config() + self.results = capture_results(f) + result = self.results.results[0] + +@@ -158,11 +154,10 @@ class TestNSSAgent(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config()) + f = IPARAAgent(registry) + + f.conn = mock_ldap([ldapentry, ldapentry2]) +- f.config = config.Config() + self.results = capture_results(f) + result = self.results.results[0] + +@@ -183,11 +178,10 @@ class TestNSSAgent(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config()) + f = IPARAAgent(registry) + + f.conn = mock_ldap([ldapentry]) +- f.config = config.Config() + self.results = capture_results(f) + result = self.results.results[0] + +@@ -208,11 +202,10 @@ class TestNSSAgent(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPARAAgent(registry) + + f.conn = mock_ldap([ldapentry]) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +diff --git a/tests/test_ipa_certfile_expiration.py b/tests/test_ipa_certfile_expiration.py +index d5601c5..43e59b4 100644 +--- a/tests/test_ipa_certfile_expiration.py ++++ b/tests/test_ipa_certfile_expiration.py +@@ -41,10 +41,9 @@ class TestIPACertificateFile(BaseTest): + mock_load_cert.return_value = cert + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertfileExpirationCheck(registry) + +- f.config = config.Config() + f.config.cert_expiration_days = 28 + self.results = capture_results(f) + +@@ -65,10 +64,9 @@ class TestIPACertificateFile(BaseTest): + mock_load_cert.return_value = cert + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertfileExpirationCheck(registry) + +- f.config = config.Config() + f.config.cert_expiration_days = 30 + self.results = capture_results(f) + +@@ -90,10 +88,9 @@ class TestIPACertificateFile(BaseTest): + mock_load_cert.return_value = cert + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertfileExpirationCheck(registry) + +- f.config = config.Config() + f.config.cert_expiration_days = 30 + self.results = capture_results(f) + +diff --git a/tests/test_ipa_certmonger_ca.py b/tests/test_ipa_certmonger_ca.py +index 4eec1ba..3b67784 100644 +--- a/tests/test_ipa_certmonger_ca.py ++++ b/tests/test_ipa_certmonger_ca.py +@@ -4,7 +4,7 @@ + + from util import capture_results, CAInstance + from base import BaseTest +-from ipahealthcheck.core import constants ++from ipahealthcheck.core import constants, config + from ipahealthcheck.ipa.plugin import registry + from ipahealthcheck.ipa.certs import IPACertmongerCA + from unittest.mock import Mock, patch +@@ -24,7 +24,7 @@ class TestCertmonger(BaseTest): + 'dogtag-ipa-ca-renew-agent-reuse' + ] + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertmongerCA(registry) + + self.results = capture_results(f) +@@ -44,7 +44,7 @@ class TestCertmonger(BaseTest): + ] + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertmongerCA(registry) + + self.results = capture_results(f) +diff --git a/tests/test_ipa_dna.py b/tests/test_ipa_dna.py +index 5450642..5c88c22 100644 +--- a/tests/test_ipa_dna.py ++++ b/tests/test_ipa_dna.py +@@ -31,10 +31,9 @@ class TestDNARange(BaseTest): + def test_dnarange_set(self, mock_manager): + mock_manager.return_value = mock_ReplicationManager(start=1, max=100) + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPADNARangeCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -52,10 +51,9 @@ class TestDNARange(BaseTest): + def test_dnarange_noset(self, mock_manager): + mock_manager.return_value = mock_ReplicationManager() + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPADNARangeCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -76,10 +74,9 @@ class TestDNARange(BaseTest): + next=101, + next_max=200) + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPADNARangeCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +diff --git a/tests/test_ipa_dns.py b/tests/test_ipa_dns.py +index dde4c4d..61e9a27 100644 +--- a/tests/test_ipa_dns.py ++++ b/tests/test_ipa_dns.py +@@ -192,10 +192,9 @@ class TestDNSSystemRecords(BaseTest): + ] + }] + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPADNSSystemRecordsCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 9 +@@ -235,10 +234,9 @@ class TestDNSSystemRecords(BaseTest): + }] + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPADNSSystemRecordsCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 17 +@@ -286,10 +284,9 @@ class TestDNSSystemRecords(BaseTest): + }] + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPADNSSystemRecordsCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 25 +@@ -335,10 +332,9 @@ class TestDNSSystemRecords(BaseTest): + }] + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPADNSSystemRecordsCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 23 +@@ -389,10 +385,9 @@ class TestDNSSystemRecords(BaseTest): + }] + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPADNSSystemRecordsCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 25 +@@ -447,10 +442,9 @@ class TestDNSSystemRecords(BaseTest): + }] + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPADNSSystemRecordsCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 25 +@@ -509,10 +503,9 @@ class TestDNSSystemRecords(BaseTest): + }] + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPADNSSystemRecordsCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 32 +@@ -545,10 +538,9 @@ class TestDNSSystemRecords(BaseTest): + ] + }] + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPADNSSystemRecordsCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 9 +@@ -581,10 +573,9 @@ class TestDNSSystemRecords(BaseTest): + ] + }] + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPADNSSystemRecordsCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 15 +diff --git a/tests/test_ipa_expiration.py b/tests/test_ipa_expiration.py +index 6cd6952..cd7de82 100644 +--- a/tests/test_ipa_expiration.py ++++ b/tests/test_ipa_expiration.py +@@ -30,10 +30,9 @@ class TestExpiration(BaseTest): + set_requests() + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertmongerExpirationCheck(registry) + +- f.config = config.Config() + f.config.cert_expiration_days = 7 + self.results = capture_results(f) + +@@ -66,10 +65,9 @@ class TestExpiration(BaseTest): + set_requests(remove=0, add=replaceme) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertmongerExpirationCheck(registry) + +- f.config = config.Config() + f.config.cert_expiration_days = 30 + self.results = capture_results(f) + +@@ -122,10 +120,9 @@ class TestChainExpiration(BaseTest): + ) + ] + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACAChainExpirationCheck(registry) + +- f.config = config.Config() + f.config.cert_expiration_days = 7 + self.results = capture_results(f) + +@@ -160,10 +157,9 @@ class TestChainExpiration(BaseTest): + ) + ] + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACAChainExpirationCheck(registry) + +- f.config = config.Config() + f.config.cert_expiration_days = 7 + self.results = capture_results(f) + +@@ -200,10 +196,9 @@ class TestChainExpiration(BaseTest): + ) + ] + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACAChainExpirationCheck(registry) + +- f.config = config.Config() + f.config.cert_expiration_days = 7 + self.results = capture_results(f) + +@@ -238,10 +233,9 @@ class TestChainExpiration(BaseTest): + ) + ] + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACAChainExpirationCheck(registry) + +- f.config = config.Config() + f.config.cert_expiration_days = 7 + self.results = capture_results(f) + +diff --git a/tests/test_ipa_nssdb.py b/tests/test_ipa_nssdb.py +index 590401c..9def3d1 100644 +--- a/tests/test_ipa_nssdb.py ++++ b/tests/test_ipa_nssdb.py +@@ -48,10 +48,9 @@ class TestNSSDBTrust(BaseTest): + mock_certdb.return_value = mock_CertDB(trust) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertNSSTrust(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 4 +@@ -74,10 +73,9 @@ class TestNSSDBTrust(BaseTest): + mock_certdb.return_value = mock_CertDB(trust) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertNSSTrust(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + # The check reports success for those that it found and are correct and +@@ -114,10 +112,9 @@ class TestNSSDBTrust(BaseTest): + mock_certdb.return_value = mock_CertDB(trust) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertNSSTrust(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + result = self.results.results[1] +@@ -149,10 +146,9 @@ class TestNSSDBTrust(BaseTest): + mock_cainstance.return_value = CAInstance(False) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertNSSTrust(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 0 +diff --git a/tests/test_ipa_nssvalidation.py b/tests/test_ipa_nssvalidation.py +index 1e567d8..08135e7 100644 +--- a/tests/test_ipa_nssvalidation.py ++++ b/tests/test_ipa_nssvalidation.py +@@ -38,10 +38,9 @@ class TestNSSValidation(BaseTest): + mock_cainstance.return_value = CAInstance() + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPANSSChainValidation(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 2 +@@ -68,10 +67,9 @@ class TestNSSValidation(BaseTest): + mock_cainstance.return_value = CAInstance() + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPANSSChainValidation(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 2 +@@ -97,10 +95,9 @@ class TestNSSValidation(BaseTest): + mock_cainstance.return_value = CAInstance(False) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPANSSChainValidation(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +diff --git a/tests/test_ipa_opensslvalidation.py b/tests/test_ipa_opensslvalidation.py +index 0d334cd..e73138c 100644 +--- a/tests/test_ipa_opensslvalidation.py ++++ b/tests/test_ipa_opensslvalidation.py +@@ -30,10 +30,9 @@ class TestOpenSSLValidation(BaseTest): + mock_run.side_effect = run + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPAOpenSSLChainValidation(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 2 +@@ -59,10 +58,9 @@ class TestOpenSSLValidation(BaseTest): + mock_run.side_effect = run + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPAOpenSSLChainValidation(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 2 +diff --git a/tests/test_ipa_revocation.py b/tests/test_ipa_revocation.py +index 39cf3e7..c6423c0 100644 +--- a/tests/test_ipa_revocation.py ++++ b/tests/test_ipa_revocation.py +@@ -54,10 +54,9 @@ class TestRevocation(BaseTest): + set_requests() + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertRevocation(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 2 +@@ -84,10 +83,9 @@ class TestRevocation(BaseTest): + set_requests() + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertRevocation(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 2 +diff --git a/tests/test_ipa_roles.py b/tests/test_ipa_roles.py +index 453db06..21c0069 100644 +--- a/tests/test_ipa_roles.py ++++ b/tests/test_ipa_roles.py +@@ -18,10 +18,9 @@ class TestCRLManagerRole(BaseTest): + def test_not_crlmanager(self, mock_ca): + mock_ca.return_value = CAInstance(crlgen=False) + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACRLManagerCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -36,10 +35,9 @@ class TestCRLManagerRole(BaseTest): + def test_crlmanager(self, mock_ca): + mock_ca.return_value = CAInstance() + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACRLManagerCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -54,7 +52,7 @@ class TestCRLManagerRole(BaseTest): + class TestRenewalMaster(BaseTest): + def test_renewal_master_not_set(self): + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPARenewalMasterCheck(registry) + + m_api.Command.config_show.side_effect = [{ +@@ -62,7 +60,6 @@ class TestRenewalMaster(BaseTest): + } + }] + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -75,7 +72,7 @@ class TestRenewalMaster(BaseTest): + + def test_not_renewal_master(self): + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPARenewalMasterCheck(registry) + + m_api.Command.config_show.side_effect = [{ +@@ -84,7 +81,6 @@ class TestRenewalMaster(BaseTest): + } + }] + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -97,7 +93,7 @@ class TestRenewalMaster(BaseTest): + + def test_is_renewal_master(self): + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPARenewalMasterCheck(registry) + + m_api.Command.config_show.side_effect = [{ +@@ -106,7 +102,6 @@ class TestRenewalMaster(BaseTest): + } + }] + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +diff --git a/tests/test_ipa_topology.py b/tests/test_ipa_topology.py +index a4ff6d9..11931d9 100644 +--- a/tests/test_ipa_topology.py ++++ b/tests/test_ipa_topology.py +@@ -28,10 +28,9 @@ class TestTopology(BaseTest): + m_api.Command.ca_is_enabled.return_value = {'result': True} + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPATopologyDomainCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 2 +@@ -71,10 +70,9 @@ class TestTopology(BaseTest): + m_api.Command.ca_is_enabled.return_value = {'result': True} + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPATopologyDomainCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 3 +@@ -135,10 +133,9 @@ class TestTopology(BaseTest): + m_api.Command.ca_is_enabled.return_value = {'result': True} + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPATopologyDomainCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 3 +@@ -193,10 +190,9 @@ class TestTopology(BaseTest): + m_api.Command.ca_is_enabled.return_value = {'result': True} + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPATopologyDomainCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 2 +diff --git a/tests/test_ipa_tracking.py b/tests/test_ipa_tracking.py +index c40d8f4..4b982d0 100644 +--- a/tests/test_ipa_tracking.py ++++ b/tests/test_ipa_tracking.py +@@ -5,7 +5,7 @@ + from util import capture_results + from base import BaseTest + +-from ipahealthcheck.core import constants ++from ipahealthcheck.core import constants, config + from ipahealthcheck.ipa.plugin import registry + from ipahealthcheck.ipa.certs import IPACertTracking + from unittest.mock import Mock +@@ -27,7 +27,7 @@ class TestTracking(BaseTest): + set_requests() + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertTracking(registry) + + self.results = capture_results(f) +@@ -39,7 +39,7 @@ class TestTracking(BaseTest): + set_requests(remove=0) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertTracking(registry) + + self.results = capture_results(f) +@@ -71,7 +71,7 @@ class TestTracking(BaseTest): + set_requests(add=unknown) + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = IPACertTracking(registry) + + self.results = capture_results(f) +diff --git a/tests/test_ipa_trust.py b/tests/test_ipa_trust.py +index 01fdf3c..cf2281c 100644 +--- a/tests/test_ipa_trust.py ++++ b/tests/test_ipa_trust.py +@@ -109,11 +109,10 @@ class SSSDConfig(): + class TestTrustAgent(BaseTest): + def test_no_trust_agent(self): + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = False + f = IPATrustAgentCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + # Zero because the call was skipped altogether +@@ -124,11 +123,10 @@ class TestTrustAgent(BaseTest): + mock_sssd.return_value = SSSDConfig(return_domains=True, + return_ipa_server_mode=True) + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = True + f = IPATrustAgentCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -143,11 +141,10 @@ class TestTrustAgent(BaseTest): + mock_sssd.return_value = SSSDConfig(return_domains=True, + return_ipa_server_mode=False) + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = True + f = IPATrustAgentCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -164,11 +161,10 @@ class TestTrustAgent(BaseTest): + mock_sssd.return_value = SSSDConfig(return_domains=True, + return_ipa_server_mode=None) + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = True + f = IPATrustAgentCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -184,11 +180,10 @@ class TestTrustAgent(BaseTest): + class TestTrustDomains(BaseTest): + def test_no_trust_agent(self): + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = False + f = IPATrustDomainsCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + # Zero because the call was skipped altogether +@@ -202,11 +197,10 @@ class TestTrustDomains(BaseTest): + mock_run.return_value = run_result + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = True + f = IPATrustDomainsCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -230,11 +224,10 @@ class TestTrustDomains(BaseTest): + mock_trust.side_effect = errors.NotFound(reason='bad') + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = True + f = IPATrustDomainsCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + # There are more than one result I just care about this particular +@@ -279,11 +272,10 @@ class TestTrustDomains(BaseTest): + }] + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = True + f = IPATrustDomainsCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 3 +@@ -344,11 +336,10 @@ class TestTrustDomains(BaseTest): + }] + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = True + f = IPATrustDomainsCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 2 +@@ -374,12 +365,11 @@ class TestIPADomain(BaseTest): + def test_ipa_domain_ok(self, mock_sssd): + mock_sssd.return_value = SSSDConfig(provider='ipa') + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + # being a trust agent isn't mandatory, test without + registry.trust_agent = False + f = IPADomainCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + print(self.results.results) +@@ -394,11 +384,10 @@ class TestIPADomain(BaseTest): + def test_ipa_domain_ad(self, mock_sssd): + mock_sssd.return_value = SSSDConfig(provider='ad') + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = True + f = IPADomainCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 4 +@@ -413,11 +402,10 @@ class TestIPADomain(BaseTest): + class TestTrustCatalog(BaseTest): + def test_no_trust_agent(self): + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = False + f = IPATrustCatalogCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + # Zero because the call was skipped altogether +@@ -464,11 +452,10 @@ class TestTrustCatalog(BaseTest): + }] + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = True + f = IPATrustCatalogCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 6 +@@ -524,11 +511,10 @@ class Testsidgen(BaseTest): + + def test_no_trust_agent(self): + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = False + f = IPAsidgenpluginCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + # Zero because the call was skipped altogether +@@ -544,12 +530,11 @@ class Testsidgen(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = True + f = IPAsidgenpluginCheck(registry) + + f.conn = mock_ldap(ldapentry) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 2 +@@ -576,12 +561,11 @@ class Testsidgen(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = True + f = IPAsidgenpluginCheck(registry) + + f.conn = mock_ldap(ldapentry) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 2 +@@ -607,11 +591,10 @@ class TestTrustAgentMember(BaseTest): + + def test_no_trust_agent(self): + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = False + f = IPATrustAgentMemberCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + # Zero because the call was skipped altogether +@@ -632,12 +615,11 @@ class TestTrustAgentMember(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = True + f = IPATrustAgentMemberCheck(registry) + + f.conn = mock_ldap(ldapentry) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -660,12 +642,11 @@ class TestTrustAgentMember(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_agent = True + f = IPATrustAgentMemberCheck(registry) + + f.conn = mock_ldap(ldapentry) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -685,11 +666,10 @@ class TestControllerPrincipal(BaseTest): + + def test_not_trust_controller(self): + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_controller = False + f = IPATrustControllerPrincipalCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + # Zero because the call was skipped altogether +@@ -711,12 +691,11 @@ class TestControllerPrincipal(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_controller = True + f = IPATrustControllerPrincipalCheck(registry) + + f.conn = mock_ldap(ldapentry) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -740,12 +719,11 @@ class TestControllerPrincipal(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_controller = True + f = IPATrustControllerPrincipalCheck(registry) + + f.conn = mock_ldap(ldapentry) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -765,11 +743,10 @@ class TestControllerService(BaseTest): + + def test_not_trust_controller(self): + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_controller = False + f = IPATrustControllerServiceCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + # Zero because the call was skipped altogether +@@ -786,12 +763,11 @@ class TestControllerService(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_controller = True + f = IPATrustControllerServiceCheck(registry) + + f.conn = mock_ldap(ldapentry) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -813,12 +789,11 @@ class TestControllerService(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_controller = True + f = IPATrustControllerServiceCheck(registry) + + f.conn = mock_ldap(ldapentry) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -837,11 +812,10 @@ class TestControllerGroupSID(BaseTest): + + def test_not_trust_controller(self): + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_controller = False + f = IPATrustControllerGroupSIDCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + # Zero because the call was skipped altogether +@@ -859,12 +833,11 @@ class TestControllerGroupSID(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_controller = True + f = IPATrustControllerGroupSIDCheck(registry) + + f.conn = mock_ldap(ldapentry) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -888,12 +861,11 @@ class TestControllerGroupSID(BaseTest): + ldapentry[attr] = values + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_controller = True + f = IPATrustControllerGroupSIDCheck(registry) + + f.conn = mock_ldap(ldapentry) +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -914,11 +886,10 @@ class TestControllerConf(BaseTest): + + def test_not_trust_controller(self): + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_controller = False + f = IPATrustControllerConfCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + # Zero because the call was skipped altogether +@@ -934,11 +905,10 @@ class TestControllerConf(BaseTest): + mock_run.return_value = run_result + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_controller = True + f = IPATrustControllerConfCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + assert len(self.results) == 1 +@@ -954,11 +924,10 @@ class TestPackageCheck(BaseTest): + def test_agent_with_package(self): + # Note that this test assumes the import is installed + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_controller = False + registry.trust_agent = True + f = IPATrustPackageCheck(registry) +- f.config = config.Config() + self.results = capture_results(f) + assert len(self.results) == 1 + result = self.results.results[0] +@@ -969,14 +938,13 @@ class TestPackageCheck(BaseTest): + def test_agent_without_package(self): + # Note that this test assumes the import is installed + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + registry.trust_controller = False + registry.trust_agent = True + # Hose up the module so the import fails + save = sys.modules['ipaserver.install'] + sys.modules['ipaserver.install'] = 'foo' + f = IPATrustPackageCheck(registry) +- f.config = config.Config() + self.results = capture_results(f) + assert len(self.results) == 1 + result = self.results.results[0] +diff --git a/tests/test_meta_services.py b/tests/test_meta_services.py +index 6fbea13..b7a71a4 100644 +--- a/tests/test_meta_services.py ++++ b/tests/test_meta_services.py +@@ -7,6 +7,7 @@ from base import BaseTest + + from ipahealthcheck.ipa.plugin import registry + from ipahealthcheck.meta.services import httpd ++from ipahealthcheck.core import config + + + class TestServices(BaseTest): +@@ -19,7 +20,7 @@ class TestServices(BaseTest): + running. + """ + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = httpd(registry) + + self.results = capture_results(f) +diff --git a/tests/test_system_filesystemspace.py b/tests/test_system_filesystemspace.py +index 3317f62..873b977 100644 +--- a/tests/test_system_filesystemspace.py ++++ b/tests/test_system_filesystemspace.py +@@ -28,10 +28,9 @@ class TestFileSystemNotEnoughFreeSpace(BaseTest): + def test_filesystem_near_enospc(self): + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = FileSystemSpaceCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + expected_results = 10 if in_container() else 12 +@@ -64,10 +63,9 @@ class TestFileSystemNotEnoughFreeSpacePercentage(BaseTest): + def test_filesystem_risking_fragmentation(self): + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = FileSystemSpaceCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + expected_results = 10 if in_container() else 12 +@@ -100,10 +98,9 @@ class TestFileSystemEnoughFreeSpace(BaseTest): + def test_filesystem_with_enough_space(self): + + framework = object() +- registry.initialize(framework) ++ registry.initialize(framework, config.Config) + f = FileSystemSpaceCheck(registry) + +- f.config = config.Config() + self.results = capture_results(f) + + expected_results = 10 if in_container() else 12 +-- +2.21.0 + diff --git a/SOURCES/0007-Lookup-AD-user-by-SID-and-not-by-hardcoded-username.patch b/SOURCES/0007-Lookup-AD-user-by-SID-and-not-by-hardcoded-username.patch deleted file mode 100644 index acc0071..0000000 --- a/SOURCES/0007-Lookup-AD-user-by-SID-and-not-by-hardcoded-username.patch +++ /dev/null @@ -1,298 +0,0 @@ -From d6d06a3a22d441fbfb208eeb63caae7aafd434b4 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Thu, 8 Aug 2019 18:46:32 +0000 -Subject: [PATCH 7/8] Lookup AD user by SID and not by hardcoded username - -Looking up the user user as Administrator@REALM is not -portable because the administrator login name may be -localized. ---- - .travis.yml | 2 +- - src/ipahealthcheck/ipa/plugin.py | 8 ++++ - src/ipahealthcheck/ipa/trust.py | 44 +++++++++++++++---- - tests/test_ipa_trust.py | 72 ++++++++++++++++++-------------- - 4 files changed, 85 insertions(+), 41 deletions(-) - -diff --git a/.travis.yml b/.travis.yml -index 16722fe..25dbf1e 100644 ---- a/.travis.yml -+++ b/.travis.yml -@@ -19,4 +19,4 @@ install: - - script: - - tox -epep8,flake8 -- - 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" -+ - 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" -diff --git a/src/ipahealthcheck/ipa/plugin.py b/src/ipahealthcheck/ipa/plugin.py -index bd95c16..34cb8c9 100644 ---- a/src/ipahealthcheck/ipa/plugin.py -+++ b/src/ipahealthcheck/ipa/plugin.py -@@ -57,6 +57,14 @@ class IPARegistry(Registry): - logging.debug('Failed to connect to LDAP: %s', e) - return - -+ # This package is pulled in when the trust package is installed -+ # and is required to lookup trust users. If this is not installed -+ # then it can be inferred that trust is not enabled. -+ try: -+ import pysss_nss_idmap # noqa: F401 -+ except ImportError: -+ return -+ - roles = ( - ADtrustBasedRole(u"ad_trust_agent_server", - u"AD trust agent"), -diff --git a/src/ipahealthcheck/ipa/trust.py b/src/ipahealthcheck/ipa/trust.py -index 2da20c0..6c5978d 100644 ---- a/src/ipahealthcheck/ipa/trust.py -+++ b/src/ipahealthcheck/ipa/trust.py -@@ -16,6 +16,12 @@ from ipaplatform.paths import paths - from ipapython import ipautil - from ipapython.dn import DN - -+try: -+ import pysss_nss_idmap -+except ImportError: -+ # agent and controller will be set to False in init, all tests will -+ # be skipped -+ pass - try: - from ipaserver.masters import ENABLED_SERVICE - except ImportError: -@@ -33,13 +39,19 @@ def get_trust_domains(): - Get the list of AD trust domains from IPA - - The caller is expected to catch any exceptions. -+ -+ Each entry is a dictionary representating an AD domain. - """ - result = api.Command.trust_find() - results = result['result'] - trust_domains = [] - for result in results: - if result.get('trusttype')[0] == 'Active Directory domain': -- trust_domains.append(result.get('cn')[0]) -+ domain = dict() -+ domain['domain'] = result.get('cn')[0] -+ domain['domainsid'] = result.get('ipanttrusteddomainsid')[0] -+ domain['netbios'] = result.get('ipantflatname')[0] -+ trust_domains.append(domain) - return trust_domains - - -@@ -123,14 +135,17 @@ class IPATrustDomainsCheck(IPAPlugin): - if 'implicit_files' in sssd_domains: - sssd_domains.remove('implicit_files') - -+ trust_domains = [] - try: -- trust_domains = get_trust_domains() -+ domains = get_trust_domains() - except Exception as e: - yield Result(self, constants.WARNING, - key='trust-find', - error=str(e), - msg='Execution of {key} failed: {error}') -- trust_domains = [] -+ else: -+ for entry in domains: -+ trust_domains.append(entry.get('domain')) - - if api.env.domain in sssd_domains: - sssd_domains.remove(api.env.domain) -@@ -204,17 +219,28 @@ class IPATrustCatalogCheck(IPAPlugin): - msg='Execution of {key} failed: {error}') - trust_domains = [] - -- for domain in trust_domains: -+ for trust_domain in trust_domains: -+ sid = trust_domain.get('domainsid') - try: -- ipautil.run(['/bin/id', "Administrator@%s" % domain], -- capture_output=True) -+ id = pysss_nss_idmap.getnamebysid(sid + '-500') - except Exception as e: -- yield Result(self, constants.WARNING, -- key='/bin/id', -+ yield Result(self, constants.ERROR, -+ key=sid, - error=str(e), -- msg='Execution of {key} failed: {error}') -+ msg='Look up of{key} failed: {error}') - continue - -+ if not id: -+ yield Result(self, constants.WARNING, -+ key=sid, -+ error='returned nothing', -+ msg='Look up of {key} {error}') -+ else: -+ yield Result(self, constants.SUCCESS, -+ key='Domain Security Identifier', -+ sid=sid) -+ -+ domain = trust_domain.get('domain') - args = [paths.SSSCTL, "domain-status", domain, "--active-server"] - try: - result = ipautil.run(args, capture_output=True) -diff --git a/tests/test_ipa_trust.py b/tests/test_ipa_trust.py -index 0a1d58c..89d3bff 100644 ---- a/tests/test_ipa_trust.py -+++ b/tests/test_ipa_trust.py -@@ -261,12 +261,14 @@ class TestTrustDomains(BaseTest): - { - 'cn': ['ad.example'], - 'ipantflatname': ['ADROOT'], -- "trusttype": ["Active Directory domain"], -+ 'ipanttrusteddomainsid': ['S-1-5-21-abc'], -+ 'trusttype': ['Active Directory domain'], - }, - { - 'cn': ['child.example'], - 'ipantflatname': ['ADROOT'], -- "trusttype": ["Active Directory domain"], -+ 'ipanttrusteddomainsid': ['S-1-5-21-def'], -+ 'trusttype': ['Active Directory domain'], - }, - ] - }] -@@ -324,12 +326,14 @@ class TestTrustDomains(BaseTest): - { - 'cn': ['ad.example'], - 'ipantflatname': ['ADROOT'], -- "trusttype": ["Active Directory domain"], -+ 'ipanttrusteddomainsid': ['S-1-5-21-abc'], -+ 'trusttype': ['Active Directory domain'], - }, - { - 'cn': ['child.example'], - 'ipantflatname': ['ADROOT'], -- "trusttype": ["Active Directory domain"], -+ 'ipanttrusteddomainsid': ['S-1-5-21-def'], -+ 'trusttype': ['Active Directory domain'], - }, - ] - }] -@@ -373,41 +377,27 @@ class TestTrustCatalog(BaseTest): - # Zero because the call was skipped altogether - assert len(self.results) == 0 - -+ @patch('pysss_nss_idmap.getnamebysid') - @patch('ipapython.ipautil.run') -- def test_trust_catalog_ok(self, mock_run): -+ def test_trust_catalog_ok(self, mock_run, mock_getnamebysid): - # id Administrator@ad.example -- idresult = namedtuple('run', ['returncode', 'error_log']) -- idresult.returncode = 0 -- idresult.error_log = '' -- idresult.output = '797600500(administrator@ad.example),' \ -- '1797600520(group policy creator owners@ad.example),' \ -- '1797600519(enterprise admins@ad.example),' \ -- '1797600512(domain admins@ad.example),' \ -- '1797600518(schema admins@ad.example)' \ -- ',1797600513(domain users@ad.example)\n' - 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' -- # id Administrator@client.example -- id2result = namedtuple('run', ['returncode', 'error_log']) -- id2result.returncode = 0 -- id2result.error_log = '' -- id2result.output = '797600500(administrator@client.example),' \ -- '1797600520(group policy creator owners@client.example),' \ -- '1797600519(enterprise admins@client.example),' \ -- '1797600512(domain admins@client.example),' \ -- '1797600518(schema admins@client.example)' \ -- ',1797600513(domain users@client.example)\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 = [idresult, dsresult, id2result, ds2result] -+ mock_run.side_effect = [dsresult, ds2result] -+ mock_getnamebysid.side_effect = [ -+ {'S-1-5-21-abc-500': {'name': 'admin@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 = [{ -@@ -415,12 +405,14 @@ class TestTrustCatalog(BaseTest): - { - 'cn': ['ad.example'], - 'ipantflatname': ['ADROOT'], -- "trusttype": ["Active Directory domain"], -+ 'ipanttrusteddomainsid': ['S-1-5-21-abc'], -+ 'trusttype': ['Active Directory domain'], - }, - { - 'cn': ['child.example'], - 'ipantflatname': ['ADROOT'], -- "trusttype": ["Active Directory domain"], -+ 'ipanttrusteddomainsid': ['S-1-5-21-def'], -+ 'trusttype': ['Active Directory domain'], - }, - ] - }] -@@ -433,31 +425,49 @@ class TestTrustCatalog(BaseTest): - f.config = config.Config() - self.results = capture_results(f) - -- assert len(self.results) == 4 -+ assert len(self.results) == 6 - - 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') == 'AD Global Catalog' -+ assert result.kw.get('key') == 'Domain Security Identifier' -+ assert result.kw.get('sid') == 'S-1-5-21-abc' - - 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') == 'AD Domain Controller' -+ assert result.kw.get('key') == 'AD Global Catalog' -+ assert result.kw.get('domain') == 'ad.example' - - 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') == 'AD Domain Controller' -+ assert result.kw.get('domain') == 'ad.example' -+ -+ result = self.results.results[3] -+ assert result.result == constants.SUCCESS -+ assert result.source == 'ipahealthcheck.ipa.trust' -+ assert result.check == 'IPATrustCatalogCheck' -+ assert result.kw.get('key') == 'Domain Security Identifier' -+ assert result.kw.get('sid') == 'S-1-5-21-def' -+ -+ result = self.results.results[4] -+ assert result.result == constants.SUCCESS -+ assert result.source == 'ipahealthcheck.ipa.trust' -+ assert result.check == 'IPATrustCatalogCheck' - assert result.kw.get('key') == 'AD Global Catalog' -+ assert result.kw.get('domain') == 'child.example' - -- result = self.results.results[1] -+ result = self.results.results[5] - assert result.result == constants.SUCCESS - assert result.source == 'ipahealthcheck.ipa.trust' - assert result.check == 'IPATrustCatalogCheck' - assert result.kw.get('key') == 'AD Domain Controller' -+ assert result.kw.get('domain') == 'child.example' - - - class Testsidgen(BaseTest): --- -2.20.1 - diff --git a/SOURCES/0008-Rename-misspelled-sslctl-to-sssctl-for-the-SSSD-cont.patch b/SOURCES/0008-Rename-misspelled-sslctl-to-sssctl-for-the-SSSD-cont.patch deleted file mode 100644 index 43ed20d..0000000 --- a/SOURCES/0008-Rename-misspelled-sslctl-to-sssctl-for-the-SSSD-cont.patch +++ /dev/null @@ -1,53 +0,0 @@ -From c3586321aa82bd4e12e70c8463b85c2e3888c510 Mon Sep 17 00:00:00 2001 -From: Rob Crittenden -Date: Fri, 9 Aug 2019 09:34:14 -0400 -Subject: [PATCH 8/8] Rename misspelled sslctl to sssctl for the SSSD control - script - ---- - src/ipahealthcheck/ipa/trust.py | 12 ++++++------ - 1 file changed, 6 insertions(+), 6 deletions(-) - -diff --git a/src/ipahealthcheck/ipa/trust.py b/src/ipahealthcheck/ipa/trust.py -index 6c5978d..cb18378 100644 ---- a/src/ipahealthcheck/ipa/trust.py -+++ b/src/ipahealthcheck/ipa/trust.py -@@ -127,9 +127,9 @@ class IPATrustDomainsCheck(IPAPlugin): - if result.returncode != 0: - yield Result(self, constants.ERROR, - key='domain_list_error', -- sslctl=paths.SSSCTL, -+ sssctl=paths.SSSCTL, - error=result.error_log, -- msg='Execution of {sslctl} failed: {error}') -+ msg='Execution of {sssctl} failed: {error}') - return - sssd_domains = result.output.strip().split('\n') - if 'implicit_files' in sssd_domains: -@@ -152,8 +152,8 @@ class IPATrustDomainsCheck(IPAPlugin): - else: - yield Result(self, constants.ERROR, - key=api.env.domain, -- sslctl=paths.SSSCTL, -- msg='{key} not in {sslctl} domain-list') -+ sssctl=paths.SSSCTL, -+ msg='{key} not in {sssctl} domain-list') - - trust_domains_out = ', '.join(trust_domains) - sssd_domains_out = ', '.join(sssd_domains) -@@ -161,10 +161,10 @@ class IPATrustDomainsCheck(IPAPlugin): - if set(trust_domains).symmetric_difference(set(sssd_domains)): - yield Result(self, constants.ERROR, - key='domain-list', -- sslctl=paths.SSSCTL, -+ sssctl=paths.SSSCTL, - sssd_domains=sssd_domains_out, - trust_domains=trust_domains_out, -- msg='{sslctl} {key} reports mismatch: ' -+ msg='{sssctl} {key} reports mismatch: ' - 'sssd domains {sssd_domains} ' - 'trust domains {trust_domains}') - else: --- -2.20.1 - diff --git a/SPECS/ipa-healthcheck.spec b/SPECS/ipa-healthcheck.spec index 6ccacf0..c127f2a 100644 --- a/SPECS/ipa-healthcheck.spec +++ b/SPECS/ipa-healthcheck.spec @@ -7,23 +7,21 @@ Name: ipa-healthcheck -Version: 0.3 +Version: 0.4 Release: 4%{?dist} Summary: Health check tool for IdM BuildArch: noarch License: GPLv3 -URL: https://github.com/%{project}/%{name} -Source0: https://github.com/%{project}/%{name}/archive/release-%{version}.tar.gz#/%{project}-%{shortname}-%{version}.tar.gz +URL: https://github.com/%{project}/freeipa-healthcheck +Source0: https://github.com/%{project}/%{name}/archive/%{version}.tar.gz#/%{project}-%{shortname}-%{version}.tar.gz Source1: %{longname}.conf Patch0001: 0001-Remove-requirement-for-pytest-runner-since-PyPI-isn-.patch -Patch0002: 0002-Change-DNA-no-range-from-SUCCESS-to-WARNING.patch -Patch0003: 0003-Always-initialize-AD-roles-even-if-the-IPA-API-is-in.patch -Patch0004: 0004-Create-a-default-set-of-mock-to-always-apply-to-all-.patch -Patch0005: 0005-Mock-the-AD-trust-roles.patch -Patch0006: 0006-Force-the-KRA-to-be-off-during-NSS-db-trust-tests.patch -Patch0007: 0007-Lookup-AD-user-by-SID-and-not-by-hardcoded-username.patch -Patch0008: 0008-Rename-misspelled-sslctl-to-sssctl-for-the-SSSD-cont.patch +Patch0002: 0002-Move-main-to-run_healthcheck-for-abstraction-purpose.patch +Patch0003: 0003-Abstract-ServiceCheck-to-not-be-IPA-specific.patch +Patch0004: 0004-Move-the-abstracted-plugin-runner-code-into-a-separa.patch +Patch0005: 0005-Convert-running-healthchecks-into-a-class-and-add-pr.patch +Patch0006: 0006-Move-config-object-from-plugins-to-registry.patch Requires: ipa-server Requires: python3-ipalib @@ -32,6 +30,7 @@ Requires: python3-ipaserver Requires: anacron Requires: logrotate Requires(post): systemd-units +Requires: %{name}-core = %{version}-%{release} BuildRequires: python3-devel BuildRequires: systemd-devel %{?systemd_requires} @@ -41,6 +40,14 @@ BuildRequires: systemd-devel The FreeIPA health check tool provides a set of checks to proactively detect defects in a FreeIPA cluster. +%package -n %{name}-core +Summary: Core plugin system for healthcheck +# to allow package downgrades where this subpackage doesn't exist +Obsoletes: %{name} < 0.4 + +%description -n %{name}-core +Core files + %prep %autosetup -p1 -n %{project}-%{shortname}-%{version} @@ -73,6 +80,11 @@ mkdir -p %{buildroot}/%{_mandir}/man5 install -p -m644 %{_builddir}/%{project}-%{shortname}-%{version}/man/man1/ipa-%{shortname}.1 %{buildroot}%{_mandir}/man1/ install -p -m644 %{_builddir}/%{project}-%{shortname}-%{version}/man/man5/%{longname}.conf.5 %{buildroot}%{_mandir}/man5/ +(cd %{buildroot}/%{python3_sitelib}/ipahealthcheck && find . -type f | \ + grep -v '^./core' | \ + grep -v 'opt-1' | \ + sed -e 's,\.py.*$,.*,g' | sort -u | \ + sed -e 's,\./,%%{python3_sitelib}/ipahealthcheck/,g' ) >healthcheck.list %post %systemd_post ipa-%{shortname}.service @@ -86,7 +98,7 @@ install -p -m644 %{_builddir}/%{project}-%{shortname}-%{version}/man/man5/%{long %systemd_postun_with_restart ipa-%{shortname}.service -%files +%files -f healthcheck.list %{!?_licensedir:%global license %%doc} %license COPYING %doc README.md @@ -95,7 +107,6 @@ install -p -m644 %{_builddir}/%{project}-%{shortname}-%{version}/man/man5/%{long %dir %{_localstatedir}/log/ipa/%{shortname} %config(noreplace) %{_sysconfdir}/%{longname}/%{longname}.conf %config(noreplace) %{_sysconfdir}/logrotate.d/%{longname} -%{python3_sitelib}/%{longname}/ %{python3_sitelib}/%{longname}-%{version}-*.egg-info/ %{python3_sitelib}/%{longname}-%{version}-*-nspkg.pth %{_unitdir}/* @@ -103,8 +114,32 @@ install -p -m644 %{_builddir}/%{project}-%{shortname}-%{version}/man/man5/%{long %{_mandir}/man1/* %{_mandir}/man5/* +%files -n %{name}-core +%{!?_licensedir:%global license %%doc} +%license COPYING +%doc README.md +%{python3_sitelib}/%{longname}/core/ + %changelog +* Thu Jan 16 2020 Rob Crittenden - 0.4-4 +- Allow plugins to read contents from config during initialization (#1784037) + +* Thu Dec 5 2019 Rob Crittenden - 0.4-3 +- Add Obsoletes to core subpackage (#1780121) + +* Mon Dec 2 2019 Rob Crittenden - 0.4-2 +- Abstract processing so core package is standalone (#1771710) + +* Mon Dec 2 2019 Rob Crittenden - 0.4-1 +- Rebase to upstream 0.4 (#1770346) +- Create subpackage to split out core processing (#1771710) +- Correct URL (#1773512) +- Errors not translated to strings (#1752849) +- JSON output not indented by default (#1729043) +- Add dependencies to checks to avoid false-positives (#1727900) +- Verify expected DNS records (#1695125) + * Mon Aug 12 2019 Rob Crittenden - 0.3-4 - Lookup AD user by SID and not by hardcoded username (#1739500)