forked from rpms/leapp-repository
e5599cfda4
- Add detection of possible usage of OpenSSL IBMCA engine on IBM Z machines - Add detection of modified /etc/pki/tls/openssl.cnf file - Update the leapp upgrade data files - Fix handling of symlinks under /etc/pki with relative paths specified - Report custom actors and modifications of the upgrade tooling - Requires xfsprogs and e2fsprogs to ensure that Ext4 and XFS tools are installed - Bump leapp-repository-dependencies to 10 - Resolves: RHEL-1774, RHEL-16729
582 lines
25 KiB
Diff
582 lines
25 KiB
Diff
From c8321a9da33ecfb71d4f6ebd03c4b334f9e91dcc Mon Sep 17 00:00:00 2001
|
|
From: Petr Stodulka <pstodulk@redhat.com>
|
|
Date: Fri, 20 Oct 2023 16:40:09 +0200
|
|
Subject: [PATCH 58/60] Add actors for OpenSSL conf and IBMCA
|
|
|
|
* The openssl-ibmca needs to be reconfigured manually after the upgrade.
|
|
Report it to the user if the package is installed.
|
|
|
|
* The openssl configuration file (/etc/pki/tls/openssl.cnf) is not
|
|
100% compatible between major verions of RHEL due to different
|
|
versions of OpenSSL. Also the configuration is supposed to be
|
|
done via system wide crypto policies instead, so it's expected
|
|
to not modify this file anymore. If the content of the file has
|
|
been modified, report to user what will happen during the upgrade
|
|
and what they should do after it.
|
|
|
|
* If the openssl config file is modified (rpm -Vf <file>) and
|
|
*.rpmnew file exists, back up the file with .leappsave suffix
|
|
and replace it by the *.rpmsave one.
|
|
---
|
|
.../actors/openssl/checkopensslconf/actor.py | 33 ++++
|
|
.../libraries/checkopensslconf.py | 135 ++++++++++++++++
|
|
.../tests/unit_test_checkopensslconf.py | 102 ++++++++++++
|
|
.../openssl/migrateopensslconf/actor.py | 26 ++++
|
|
.../libraries/migrateopensslconf.py | 54 +++++++
|
|
.../tests/unit_test_migrateopensslconf.py | 145 ++++++++++++++++++
|
|
.../libraries/scansourcefiles.py | 1 +
|
|
7 files changed, 496 insertions(+)
|
|
create mode 100644 repos/system_upgrade/common/actors/openssl/checkopensslconf/actor.py
|
|
create mode 100644 repos/system_upgrade/common/actors/openssl/checkopensslconf/libraries/checkopensslconf.py
|
|
create mode 100644 repos/system_upgrade/common/actors/openssl/checkopensslconf/tests/unit_test_checkopensslconf.py
|
|
create mode 100644 repos/system_upgrade/common/actors/openssl/migrateopensslconf/actor.py
|
|
create mode 100644 repos/system_upgrade/common/actors/openssl/migrateopensslconf/libraries/migrateopensslconf.py
|
|
create mode 100644 repos/system_upgrade/common/actors/openssl/migrateopensslconf/tests/unit_test_migrateopensslconf.py
|
|
|
|
diff --git a/repos/system_upgrade/common/actors/openssl/checkopensslconf/actor.py b/repos/system_upgrade/common/actors/openssl/checkopensslconf/actor.py
|
|
new file mode 100644
|
|
index 00000000..dd05db9c
|
|
--- /dev/null
|
|
+++ b/repos/system_upgrade/common/actors/openssl/checkopensslconf/actor.py
|
|
@@ -0,0 +1,33 @@
|
|
+from leapp.actors import Actor
|
|
+from leapp.libraries.actor import checkopensslconf
|
|
+from leapp.models import DistributionSignedRPM, Report, TrackedFilesInfoSource
|
|
+from leapp.tags import ChecksPhaseTag, IPUWorkflowTag
|
|
+
|
|
+
|
|
+class CheckOpenSSLConf(Actor):
|
|
+ """
|
|
+ Check whether the openssl configuration and openssl-IBMCA.
|
|
+
|
|
+ See the report messages for more details. The summary is that since RHEL 8
|
|
+ it's expected to configure OpenSSL via crypto policies. Also, OpenSSL has
|
|
+ different versions between major versions of RHEL:
|
|
+ * RHEL 7: 1.0,
|
|
+ * RHEL 8: 1.1,
|
|
+ * RHEL 9: 3.0
|
|
+ So OpenSSL configuration from older system does not have to be 100%
|
|
+ compatible with the new system. In some cases, the old configuration could
|
|
+ make the system inaccessible remotely. So new approach is to ensure the
|
|
+ upgraded system will use always new default /etc/pki/tls/openssl.cnf
|
|
+ configuration file (the original one will be backed up if modified by user).
|
|
+
|
|
+ Similar for OpenSSL-IBMCA, when it's expected to configure it again on
|
|
+ each newer system.
|
|
+ """
|
|
+
|
|
+ name = 'check_openssl_conf'
|
|
+ consumes = (DistributionSignedRPM, TrackedFilesInfoSource)
|
|
+ produces = (Report,)
|
|
+ tags = (IPUWorkflowTag, ChecksPhaseTag)
|
|
+
|
|
+ def process(self):
|
|
+ checkopensslconf.process()
|
|
diff --git a/repos/system_upgrade/common/actors/openssl/checkopensslconf/libraries/checkopensslconf.py b/repos/system_upgrade/common/actors/openssl/checkopensslconf/libraries/checkopensslconf.py
|
|
new file mode 100644
|
|
index 00000000..06a30fa1
|
|
--- /dev/null
|
|
+++ b/repos/system_upgrade/common/actors/openssl/checkopensslconf/libraries/checkopensslconf.py
|
|
@@ -0,0 +1,135 @@
|
|
+from leapp import reporting
|
|
+from leapp.libraries.common.config import architecture, version
|
|
+from leapp.libraries.common.rpms import has_package
|
|
+from leapp.libraries.stdlib import api
|
|
+from leapp.models import DistributionSignedRPM, TrackedFilesInfoSource
|
|
+
|
|
+DEFAULT_OPENSSL_CONF = '/etc/pki/tls/openssl.cnf'
|
|
+URL_8_CRYPTOPOLICIES = 'https://red.ht/rhel-8-system-wide-crypto-policies'
|
|
+URL_9_CRYPTOPOLICIES = 'https://red.ht/rhel-9-system-wide-crypto-policies'
|
|
+
|
|
+
|
|
+def check_ibmca():
|
|
+ if not architecture.matches_architecture(architecture.ARCH_S390X):
|
|
+ # not needed check really, but keeping it to make it clear
|
|
+ return
|
|
+ if not has_package(DistributionSignedRPM, 'openssl-ibmca'):
|
|
+ return
|
|
+ # In RHEL 9 has been introduced new technology: openssl providers. The engine
|
|
+ # is deprecated, so keep proper teminology to not confuse users.
|
|
+ dst_tech = 'engine' if version.get_target_major_version() == '8' else 'providers'
|
|
+ summary = (
|
|
+ 'The presence of openssl-ibmca package suggests that the system may be configured'
|
|
+ ' to use the IBMCA OpenSSL engine.'
|
|
+ ' Due to major changes in OpenSSL and libica between RHEL {source} and RHEL {target} it is not'
|
|
+ ' possible to migrate OpenSSL configuration files automatically. Therefore,'
|
|
+ ' it is necessary to enable IBMCA {tech} in the OpenSSL config file manually'
|
|
+ ' after the system upgrade.'
|
|
+ .format(
|
|
+ source=version.get_source_major_version(),
|
|
+ target=version.get_target_major_version(),
|
|
+ tech=dst_tech
|
|
+ )
|
|
+ )
|
|
+
|
|
+ hint = (
|
|
+ 'Configure the IBMCA {tech} manually after the upgrade.'
|
|
+ ' Please, be aware that it is not recommended to configure the system default'
|
|
+ ' {fpath}. Instead, it is recommended to configure a copy of'
|
|
+ ' that file and use this copy only for particular applications that are supposed'
|
|
+ ' to utilize the IBMCA {tech}. The location of the OpenSSL configuration file'
|
|
+ ' can be specified using the OPENSSL_CONF environment variable.'
|
|
+ .format(tech=dst_tech, fpath=DEFAULT_OPENSSL_CONF)
|
|
+ )
|
|
+
|
|
+ reporting.create_report([
|
|
+ reporting.Title('Detected possible use of IBMCA in OpenSSL'),
|
|
+ reporting.Summary(summary),
|
|
+ reporting.Remediation(hint=hint),
|
|
+ reporting.Severity(reporting.Severity.MEDIUM),
|
|
+ reporting.Groups([
|
|
+ reporting.Groups.POST,
|
|
+ reporting.Groups.ENCRYPTION
|
|
+ ]),
|
|
+ ])
|
|
+
|
|
+
|
|
+def _is_openssl_modified():
|
|
+ tracked_files = next(api.consume(TrackedFilesInfoSource), None)
|
|
+ if not tracked_files:
|
|
+ # unexpected at all, skipping testing, but keeping the log just in case
|
|
+ api.current_logger.warning('The TrackedFilesInfoSource message is missing! Skipping check of openssl config.')
|
|
+ return False
|
|
+ for finfo in tracked_files.files:
|
|
+ if finfo.path == DEFAULT_OPENSSL_CONF:
|
|
+ return finfo.is_modified
|
|
+ return False
|
|
+
|
|
+
|
|
+def check_default_openssl():
|
|
+ if not _is_openssl_modified():
|
|
+ return
|
|
+
|
|
+ crypto_url = URL_8_CRYPTOPOLICIES if version.get_target_major_version == '8' else URL_9_CRYPTOPOLICIES
|
|
+
|
|
+ # TODO(pstodulk): Needs in future some rewording, as OpenSSL engines are
|
|
+ # deprecated since "RHEL 8" and people should use OpenSSL providers instead.
|
|
+ # (IIRC, they are required to use OpenSSL providers since RHEL 9.) The
|
|
+ # current wording could be inaccurate.
|
|
+ summary = (
|
|
+ 'The OpenSSL configuration file ({fpath}) has been'
|
|
+ ' modified on the system. RHEL 8 (and newer) systems provide a crypto-policies'
|
|
+ ' mechanism ensuring usage of system-wide secure cryptography algorithms.'
|
|
+ ' Also the target system uses newer version of OpenSSL that is not fully'
|
|
+ ' compatible with the current one.'
|
|
+ ' To ensure the upgraded system uses crypto-policies as expected,'
|
|
+ ' the new version of the openssl configuration file must be installed'
|
|
+ ' during the upgrade. This will be done automatically.'
|
|
+ ' The original configuration file will be saved'
|
|
+ ' as "{fpath}.leappsave".'
|
|
+ '\n\nNote this can affect the ability to connect to the system after'
|
|
+ ' the upgrade if it depends on the current OpenSSL configuration.'
|
|
+ ' Such a problem may be caused by using a particular OpenSSL engine, as'
|
|
+ ' OpenSSL engines built for the'
|
|
+ ' RHEL {source} system are not compatible with RHEL {target}.'
|
|
+ .format(
|
|
+ fpath=DEFAULT_OPENSSL_CONF,
|
|
+ source=version.get_source_major_version(),
|
|
+ target=version.get_target_major_version()
|
|
+ )
|
|
+ )
|
|
+ if version.get_target_major_version() == '9':
|
|
+ # NOTE(pstodulk): that a try to make things with engine/providers a
|
|
+ # little bit better (see my TODO note above)
|
|
+ summary += (
|
|
+ '\n\nNote the legacy ENGINE API is deprecated since RHEL 8 and'
|
|
+ ' it is required to use the new OpenSSL providers API instead on'
|
|
+ ' RHEL 9 systems.'
|
|
+ )
|
|
+ hint = (
|
|
+ 'Check that your ability to login to the system does not depend on'
|
|
+ ' the OpenSSL configuration. After the upgrade, review the system configuration'
|
|
+ ' and configure the system as needed.'
|
|
+ ' Please, be aware that it is not recommended to configure the system default'
|
|
+ ' {fpath}. Instead, it is recommended to copy the file and use this copy'
|
|
+ ' to configure particular applications.'
|
|
+ ' The default OpenSSL configuration file should be modified only'
|
|
+ ' when it is really necessary.'
|
|
+ )
|
|
+ reporting.create_report([
|
|
+ reporting.Title('The /etc/pki/tls/openssl.cnf file is modified and will be replaced during the upgrade.'),
|
|
+ reporting.Summary(summary),
|
|
+ reporting.Remediation(hint=hint),
|
|
+ reporting.Severity(reporting.Severity.HIGH),
|
|
+ reporting.Groups([reporting.Groups.POST, reporting.Groups.SECURITY]),
|
|
+ reporting.RelatedResource('file', DEFAULT_OPENSSL_CONF),
|
|
+ reporting.ExternalLink(
|
|
+ title='Using system-wide cryptographic policies.',
|
|
+ url=crypto_url
|
|
+ )
|
|
+ ])
|
|
+
|
|
+
|
|
+def process():
|
|
+ check_ibmca()
|
|
+ check_default_openssl()
|
|
diff --git a/repos/system_upgrade/common/actors/openssl/checkopensslconf/tests/unit_test_checkopensslconf.py b/repos/system_upgrade/common/actors/openssl/checkopensslconf/tests/unit_test_checkopensslconf.py
|
|
new file mode 100644
|
|
index 00000000..541ff75d
|
|
--- /dev/null
|
|
+++ b/repos/system_upgrade/common/actors/openssl/checkopensslconf/tests/unit_test_checkopensslconf.py
|
|
@@ -0,0 +1,102 @@
|
|
+import pytest
|
|
+
|
|
+from leapp import reporting
|
|
+from leapp.libraries.actor import checkopensslconf
|
|
+from leapp.libraries.common.config import architecture
|
|
+from leapp.libraries.common.testutils import create_report_mocked, CurrentActorMocked, logger_mocked
|
|
+from leapp.libraries.stdlib import api
|
|
+from leapp.models import DistributionSignedRPM, FileInfo, RPM, TrackedFilesInfoSource
|
|
+
|
|
+_DUMP_PKG_NAMES = ['random', 'pkgs', 'openssl-ibmca-nope', 'ibmca', 'nope-openssl-ibmca']
|
|
+_SSL_CONF = checkopensslconf.DEFAULT_OPENSSL_CONF
|
|
+
|
|
+
|
|
+def _msg_pkgs(pkgnames):
|
|
+ rpms = []
|
|
+ for pname in pkgnames:
|
|
+ rpms.append(RPM(
|
|
+ name=pname,
|
|
+ epoch='0',
|
|
+ version='1.0',
|
|
+ release='1',
|
|
+ arch='noarch',
|
|
+ pgpsig='RSA/SHA256, Mon 01 Jan 1970 00:00:00 AM -03, Key ID 199e2f91fd431d51',
|
|
+ packager='Red Hat, Inc. (auxiliary key 2) <security@redhat.com>'
|
|
+
|
|
+ ))
|
|
+ return DistributionSignedRPM(items=rpms)
|
|
+
|
|
+
|
|
+@pytest.mark.parametrize('arch,pkgnames,ibmca_report', (
|
|
+ (architecture.ARCH_S390X, [], False),
|
|
+ (architecture.ARCH_S390X, _DUMP_PKG_NAMES, False),
|
|
+ (architecture.ARCH_S390X, ['openssl-ibmca'], True),
|
|
+ (architecture.ARCH_S390X, _DUMP_PKG_NAMES + ['openssl-ibmca'], True),
|
|
+ (architecture.ARCH_S390X, ['openssl-ibmca'] + _DUMP_PKG_NAMES, True),
|
|
+
|
|
+ # stay false for non-IBM-z arch - invalid scenario basically
|
|
+ (architecture.ARCH_X86_64, ['openssl-ibmca'], False),
|
|
+ (architecture.ARCH_PPC64LE, ['openssl-ibmca'], False),
|
|
+ (architecture.ARCH_ARM64, ['openssl-ibmca'], False),
|
|
+
|
|
+))
|
|
+@pytest.mark.parametrize('src_maj_ver', ('7', '8', '9'))
|
|
+def test_check_ibmca(monkeypatch, src_maj_ver, arch, pkgnames, ibmca_report):
|
|
+ monkeypatch.setattr(reporting, "create_report", create_report_mocked())
|
|
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(
|
|
+ arch=arch,
|
|
+ msgs=[_msg_pkgs(pkgnames)],
|
|
+ src_ver='{}.6'.format(src_maj_ver),
|
|
+ dst_ver='{}.0'.format(int(src_maj_ver) + 1)
|
|
+ ))
|
|
+ checkopensslconf.check_ibmca()
|
|
+
|
|
+ if not ibmca_report:
|
|
+ assert not reporting.create_report.called, 'IBMCA report created when it should not.'
|
|
+ else:
|
|
+ assert reporting.create_report.called, 'IBMCA report has not been created.'
|
|
+
|
|
+
|
|
+def _msg_files(fnames_changed, fnames_untouched):
|
|
+ res = []
|
|
+ for fname in fnames_changed:
|
|
+ res.append(FileInfo(
|
|
+ path=fname,
|
|
+ exists=True,
|
|
+ is_modified=True
|
|
+ ))
|
|
+
|
|
+ for fname in fnames_untouched:
|
|
+ res.append(FileInfo(
|
|
+ path=fname,
|
|
+ exists=True,
|
|
+ is_modified=False
|
|
+ ))
|
|
+
|
|
+ return TrackedFilesInfoSource(files=res)
|
|
+
|
|
+
|
|
+# NOTE(pstodulk): Ignoring situation when _SSL_CONF is missing (modified, do not exists).
|
|
+# It's not a valid scenario actually, as this file just must exists on the system to
|
|
+# consider it in a supported state.
|
|
+@pytest.mark.parametrize('msg,openssl_report', (
|
|
+ # matrix focused on openssl reports only (positive)
|
|
+ (_msg_files([], []), False),
|
|
+ (_msg_files([_SSL_CONF], []), True),
|
|
+ (_msg_files(['what/ever', _SSL_CONF, 'something'], []), True),
|
|
+ (_msg_files(['what/ever'], [_SSL_CONF]), False),
|
|
+))
|
|
+@pytest.mark.parametrize('src_maj_ver', ('7', '8', '9'))
|
|
+def test_check_openssl(monkeypatch, src_maj_ver, msg, openssl_report):
|
|
+ monkeypatch.setattr(reporting, "create_report", create_report_mocked())
|
|
+ monkeypatch.setattr(api, 'current_actor', CurrentActorMocked(
|
|
+ msgs=[msg],
|
|
+ src_ver='{}.6'.format(src_maj_ver),
|
|
+ dst_ver='{}.0'.format(int(src_maj_ver) + 1)
|
|
+ ))
|
|
+ checkopensslconf.process()
|
|
+
|
|
+ if not openssl_report:
|
|
+ assert not reporting.create_report.called, 'OpenSSL report created when it should not.'
|
|
+ else:
|
|
+ assert reporting.create_report.called, 'OpenSSL report has not been created.'
|
|
diff --git a/repos/system_upgrade/common/actors/openssl/migrateopensslconf/actor.py b/repos/system_upgrade/common/actors/openssl/migrateopensslconf/actor.py
|
|
new file mode 100644
|
|
index 00000000..f373b5c4
|
|
--- /dev/null
|
|
+++ b/repos/system_upgrade/common/actors/openssl/migrateopensslconf/actor.py
|
|
@@ -0,0 +1,26 @@
|
|
+from leapp.actors import Actor
|
|
+from leapp.libraries.actor import migrateopensslconf
|
|
+from leapp.tags import ApplicationsPhaseTag, IPUWorkflowTag
|
|
+
|
|
+
|
|
+class MigrateOpenSslConf(Actor):
|
|
+ """
|
|
+ Enforce the target default configuration file to be used.
|
|
+
|
|
+ If the /etc/pki/tls/openssl.cnf has been modified and openssl.cnf.rpmnew
|
|
+ file is created, backup the original one and replace it by the new default.
|
|
+
|
|
+ tl;dr: (simplified)
|
|
+ if the file is modified; then
|
|
+ mv /etc/pki/tls/openssl.cnf{,.leappsave}
|
|
+ mv /etc/pki/tls/openssl.cnf{.rpmnew,}
|
|
+ fi
|
|
+ """
|
|
+
|
|
+ name = 'migrate_openssl_conf'
|
|
+ consumes = ()
|
|
+ produces = ()
|
|
+ tags = (IPUWorkflowTag, ApplicationsPhaseTag)
|
|
+
|
|
+ def process(self):
|
|
+ migrateopensslconf.process()
|
|
diff --git a/repos/system_upgrade/common/actors/openssl/migrateopensslconf/libraries/migrateopensslconf.py b/repos/system_upgrade/common/actors/openssl/migrateopensslconf/libraries/migrateopensslconf.py
|
|
new file mode 100644
|
|
index 00000000..140c5718
|
|
--- /dev/null
|
|
+++ b/repos/system_upgrade/common/actors/openssl/migrateopensslconf/libraries/migrateopensslconf.py
|
|
@@ -0,0 +1,54 @@
|
|
+import os
|
|
+
|
|
+from leapp.libraries.stdlib import api, CalledProcessError, run
|
|
+
|
|
+DEFAULT_OPENSSL_CONF = '/etc/pki/tls/openssl.cnf'
|
|
+OPENSSL_CONF_RPMNEW = '{}.rpmnew'.format(DEFAULT_OPENSSL_CONF)
|
|
+OPENSSL_CONF_BACKUP = '{}.leappsave'.format(DEFAULT_OPENSSL_CONF)
|
|
+
|
|
+
|
|
+def _is_openssl_modified():
|
|
+ """
|
|
+ Return True if modified in any way
|
|
+ """
|
|
+ # NOTE(pstodulk): this is different from the approach in scansourcefiles,
|
|
+ # where we are interested about modified content. In this case, if the
|
|
+ # file is modified in any way, let's do something about that..
|
|
+ try:
|
|
+ run(['rpm', '-Vf', DEFAULT_OPENSSL_CONF])
|
|
+ except CalledProcessError:
|
|
+ return True
|
|
+ return False
|
|
+
|
|
+
|
|
+def _safe_mv_file(src, dst):
|
|
+ """
|
|
+ Move the file from src to dst. Return True on success, otherwise False.
|
|
+ """
|
|
+ try:
|
|
+ run(['mv', src, dst])
|
|
+ except CalledProcessError:
|
|
+ return False
|
|
+ return True
|
|
+
|
|
+
|
|
+def process():
|
|
+ if not _is_openssl_modified():
|
|
+ return
|
|
+ if not os.path.exists(OPENSSL_CONF_RPMNEW):
|
|
+ api.current_logger().debug('The {} file is modified, but *.rpmsave not found. Cannot do anything.')
|
|
+ return
|
|
+ if not _safe_mv_file(DEFAULT_OPENSSL_CONF, OPENSSL_CONF_BACKUP):
|
|
+ # NOTE(pstodulk): One of reasons could be the file is missing, however
|
|
+ # that's not expected to happen at all. If the file is missing before
|
|
+ # the upgrade, it will be installed by new openssl* package
|
|
+ api.current_logger().error(
|
|
+ 'Could not back up the {} file. Skipping other actions.'
|
|
+ .format(DEFAULT_OPENSSL_CONF)
|
|
+ )
|
|
+ return
|
|
+ if not _safe_mv_file(OPENSSL_CONF_RPMNEW, DEFAULT_OPENSSL_CONF):
|
|
+ # unexpected, it's double seatbelt
|
|
+ api.current_logger().error('Cannot apply the new openssl configuration file! Restore it from the backup.')
|
|
+ if not _safe_mv_file(OPENSSL_CONF_BACKUP, DEFAULT_OPENSSL_CONF):
|
|
+ api.current_logger().error('Cannot restore the openssl configuration file!')
|
|
diff --git a/repos/system_upgrade/common/actors/openssl/migrateopensslconf/tests/unit_test_migrateopensslconf.py b/repos/system_upgrade/common/actors/openssl/migrateopensslconf/tests/unit_test_migrateopensslconf.py
|
|
new file mode 100644
|
|
index 00000000..e9200312
|
|
--- /dev/null
|
|
+++ b/repos/system_upgrade/common/actors/openssl/migrateopensslconf/tests/unit_test_migrateopensslconf.py
|
|
@@ -0,0 +1,145 @@
|
|
+import os
|
|
+
|
|
+import pytest
|
|
+
|
|
+from leapp.libraries.actor import migrateopensslconf
|
|
+from leapp.libraries.common.testutils import CurrentActorMocked, logger_mocked
|
|
+from leapp.libraries.stdlib import CalledProcessError
|
|
+
|
|
+
|
|
+class PathExistsMocked(object):
|
|
+ def __init__(self, existing_files=None):
|
|
+ self.called = 0
|
|
+ self._existing_files = existing_files if existing_files else []
|
|
+
|
|
+ def __call__(self, fpath):
|
|
+ self.called += 1
|
|
+ return fpath in self._existing_files
|
|
+
|
|
+
|
|
+class IsOpensslModifiedMocked(object):
|
|
+ def __init__(self, ret_values):
|
|
+ self._ret_values = ret_values
|
|
+ # ret_values is list of bools to return on each call. ret_values.pop(0)
|
|
+ # if the list becomes empty, returns False
|
|
+
|
|
+ self.called = 0
|
|
+
|
|
+ def __call__(self):
|
|
+ self.called += 1
|
|
+ if not self._ret_values:
|
|
+ return False
|
|
+ return self._ret_values.pop(0)
|
|
+
|
|
+
|
|
+class SafeMVFileMocked(object):
|
|
+ def __init__(self, ret_values):
|
|
+ self._ret_values = ret_values
|
|
+ # ret_values is list of bools to return on each call. ret_values.pop(0)
|
|
+ # if the list becomes empty, returns False
|
|
+
|
|
+ self.called = 0
|
|
+ self.args_list = []
|
|
+
|
|
+ def __call__(self, src, dst):
|
|
+ self.called += 1
|
|
+ self.args_list.append((src, dst))
|
|
+ if not self._ret_values:
|
|
+ return False
|
|
+ return self._ret_values.pop(0)
|
|
+
|
|
+
|
|
+def test_migrate_openssl_nothing_to_do(monkeypatch):
|
|
+ monkeypatch.setattr(migrateopensslconf.api, 'current_logger', logger_mocked())
|
|
+ monkeypatch.setattr(migrateopensslconf, '_is_openssl_modified', IsOpensslModifiedMocked([False]))
|
|
+ monkeypatch.setattr(migrateopensslconf, '_safe_mv_file', SafeMVFileMocked([False]))
|
|
+ monkeypatch.setattr(os.path, 'exists', PathExistsMocked())
|
|
+
|
|
+ migrateopensslconf.process()
|
|
+ assert not os.path.exists.called
|
|
+ assert not migrateopensslconf._safe_mv_file.called
|
|
+
|
|
+ monkeypatch.setattr(migrateopensslconf, '_is_openssl_modified', IsOpensslModifiedMocked([True]))
|
|
+ migrateopensslconf.process()
|
|
+ assert os.path.exists.called
|
|
+ assert migrateopensslconf.api.current_logger.dbgmsg
|
|
+ assert not migrateopensslconf._safe_mv_file.called
|
|
+
|
|
+
|
|
+def test_migrate_openssl_failed_backup(monkeypatch):
|
|
+ monkeypatch.setattr(migrateopensslconf.api, 'current_logger', logger_mocked())
|
|
+ monkeypatch.setattr(migrateopensslconf, '_is_openssl_modified', IsOpensslModifiedMocked([True]))
|
|
+ monkeypatch.setattr(migrateopensslconf, '_safe_mv_file', SafeMVFileMocked([False]))
|
|
+ monkeypatch.setattr(os.path, 'exists', PathExistsMocked([migrateopensslconf.OPENSSL_CONF_RPMNEW]))
|
|
+
|
|
+ migrateopensslconf.process()
|
|
+ assert migrateopensslconf._safe_mv_file.called == 1
|
|
+ assert migrateopensslconf._safe_mv_file.args_list[0][0] == migrateopensslconf.DEFAULT_OPENSSL_CONF
|
|
+ assert migrateopensslconf.api.current_logger.errmsg
|
|
+
|
|
+
|
|
+def test_migrate_openssl_ok(monkeypatch):
|
|
+ monkeypatch.setattr(migrateopensslconf.api, 'current_logger', logger_mocked())
|
|
+ monkeypatch.setattr(migrateopensslconf, '_is_openssl_modified', IsOpensslModifiedMocked([True]))
|
|
+ monkeypatch.setattr(migrateopensslconf, '_safe_mv_file', SafeMVFileMocked([True, True]))
|
|
+ monkeypatch.setattr(os.path, 'exists', PathExistsMocked([migrateopensslconf.OPENSSL_CONF_RPMNEW]))
|
|
+
|
|
+ migrateopensslconf.process()
|
|
+ assert migrateopensslconf._safe_mv_file.called == 2
|
|
+ assert migrateopensslconf._safe_mv_file.args_list[1][1] == migrateopensslconf.DEFAULT_OPENSSL_CONF
|
|
+ assert not migrateopensslconf.api.current_logger.errmsg
|
|
+
|
|
+
|
|
+def test_migrate_openssl_failed_migrate(monkeypatch):
|
|
+ monkeypatch.setattr(migrateopensslconf.api, 'current_logger', logger_mocked())
|
|
+ monkeypatch.setattr(migrateopensslconf, '_is_openssl_modified', IsOpensslModifiedMocked([True]))
|
|
+ monkeypatch.setattr(migrateopensslconf, '_safe_mv_file', SafeMVFileMocked([True, False, True]))
|
|
+ monkeypatch.setattr(os.path, 'exists', PathExistsMocked([migrateopensslconf.OPENSSL_CONF_RPMNEW]))
|
|
+
|
|
+ migrateopensslconf.process()
|
|
+ assert migrateopensslconf._safe_mv_file.called == 3
|
|
+ assert migrateopensslconf._safe_mv_file.args_list[2][1] == migrateopensslconf.DEFAULT_OPENSSL_CONF
|
|
+ assert migrateopensslconf.api.current_logger.errmsg
|
|
+
|
|
+
|
|
+def test_migrate_openssl_failed_restore(monkeypatch):
|
|
+ monkeypatch.setattr(migrateopensslconf.api, 'current_logger', logger_mocked())
|
|
+ monkeypatch.setattr(migrateopensslconf, '_is_openssl_modified', IsOpensslModifiedMocked([True]))
|
|
+ monkeypatch.setattr(migrateopensslconf, '_safe_mv_file', SafeMVFileMocked([True]))
|
|
+ monkeypatch.setattr(os.path, 'exists', PathExistsMocked([migrateopensslconf.OPENSSL_CONF_RPMNEW]))
|
|
+
|
|
+ migrateopensslconf.process()
|
|
+ assert migrateopensslconf._safe_mv_file.called == 3
|
|
+ assert len(migrateopensslconf.api.current_logger.errmsg) == 2
|
|
+
|
|
+
|
|
+class MockedRun(object):
|
|
+ def __init__(self, raise_err):
|
|
+ self.called = 0
|
|
+ self.args = None
|
|
+ self._raise_err = raise_err
|
|
+
|
|
+ def __call__(self, args):
|
|
+ self.called += 1
|
|
+ self.args = args
|
|
+ if self._raise_err:
|
|
+ raise CalledProcessError(
|
|
+ message='A Leapp Command Error occurred.',
|
|
+ command=args,
|
|
+ result={'signal': None, 'exist_code': 1, 'pid': 0, 'stdout': 'fale', 'stderr': 'fake'}
|
|
+ )
|
|
+ # NOTE(pstodulk) ignore return as the code in the library does not use it
|
|
+
|
|
+
|
|
+@pytest.mark.parametrize('result', (True, False))
|
|
+def test_is_openssl_modified(monkeypatch, result):
|
|
+ monkeypatch.setattr(migrateopensslconf, 'run', MockedRun(result))
|
|
+ assert migrateopensslconf._is_openssl_modified() is result
|
|
+ assert migrateopensslconf.run.called == 1
|
|
+
|
|
+
|
|
+@pytest.mark.parametrize('result', (True, False))
|
|
+def test_safe_mv_file(monkeypatch, result):
|
|
+ monkeypatch.setattr(migrateopensslconf, 'run', MockedRun(not result))
|
|
+ assert migrateopensslconf._safe_mv_file('foo', 'bar') is result
|
|
+ assert ['mv', 'foo', 'bar'] == migrateopensslconf.run.args
|
|
diff --git a/repos/system_upgrade/common/actors/scansourcefiles/libraries/scansourcefiles.py b/repos/system_upgrade/common/actors/scansourcefiles/libraries/scansourcefiles.py
|
|
index 33e0275f..16c0e8aa 100644
|
|
--- a/repos/system_upgrade/common/actors/scansourcefiles/libraries/scansourcefiles.py
|
|
+++ b/repos/system_upgrade/common/actors/scansourcefiles/libraries/scansourcefiles.py
|
|
@@ -9,6 +9,7 @@ from leapp.models import FileInfo, TrackedFilesInfoSource
|
|
# '8' (etc..) -> files supposed to be scanned when particular major version of OS is used
|
|
TRACKED_FILES = {
|
|
'common': [
|
|
+ '/etc/pki/tls/openssl.cnf',
|
|
],
|
|
'8': [
|
|
],
|
|
--
|
|
2.43.0
|
|
|