leapp-repository/0058-Add-actors-for-OpenSSL-conf-and-IBMCA.patch
Petr Stodulka e5599cfda4 RHEL 8.10: CTC2 candidate - 0
- 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
2024-01-12 20:45:10 +01:00

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