Bug 2211985 - Leapp inhibits the upgrade when openssh-server is not installed but /etc/ssh/sshd_config is present
Summary: Leapp inhibits the upgrade when openssh-server is not installed but /etc/ssh/...
Keywords:
Status: NEW
Alias: None
Product: Red Hat Enterprise Linux 8
Classification: Red Hat
Component: leapp-repository
Version: 8.8
Hardware: Unspecified
OS: Unspecified
medium
medium
Target Milestone: rc
: ---
Assignee: Petr Stodulka
QA Contact: upgrades-and-conversions
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2023-06-02 20:47 UTC by jcastran
Modified: 2023-07-31 07:08 UTC (History)
1 user (show)

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed:
Type: Bug
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Issue Tracker OAMG-9247 0 None None None 2023-06-02 20:48:29 UTC
Red Hat Issue Tracker RHELPLAN-158892 0 None None None 2023-06-02 20:48:21 UTC

Description jcastran 2023-06-02 20:47:39 UTC
Leapp outputs this inhibitor when the /etc/ssh/sshd_config file is unmodified.

Risk Factor: high (inhibitor)
Title: Possible problems with remote login using root account
Summary: OpenSSH configuration file will get updated to RHEL9 version, no longer allowing root login with password. It is a good practice to use non-root administrative user and non-password authentications, but if you rely on the remote root login, this change can lock you out of this system.
Remediation: [hint] If you depend on remote root logins using passwords, consider setting up a different user for remote administration or adding a comment into the sshd_config next to the "PermitRootLogin yes" directive to prevent rpm replacing it during the upgrade.

https://github.com/oamg/leapp-repository/blob/c3f32c8cd95011b9fb6b4c8a9ee27736ba551ae2/repos/system_upgrade/common/actors/opensshpermitrootlogincheck/actor.py#L114


The resolution for this inhibitor is to modify the sshd_config which prevents the new openssh-server package from replacing the old "unmodified" configuration file.


## The issue

If a customer does not have openssh-server installed, this inhibitor is impossible to resolve. 

The code first checks if the configuration is present. It then detects if the configuration is modified with rpm -V, but if the package is not present, this results in leapp considering the file unmodified.

~~~
# grep  def\ _read_rpm_modifications -A11 repositories/system_upgrade/common/libraries/rpms.py
def _read_rpm_modifications(config):
    """
    Ask RPM database whether the configuration file was modified.

    :param config: a config file to check
    """
    try:
        return stdlib.run(['rpm', '-Vf', config], split=True, checked=False)['stdout']
    except OSError as err:
        error = 'Failed to check the modification status of the file {}: {}'.format(config, str(err))
        stdlib.api.current_logger().error(error)
        return []
~~~


With the package removed we see that leapp reads the file and knows PermitRootLogin is false (which is a modified state) but shows at modified.

~~~
# yum remove openssh-server
# touch /etc/ssh/sshd_config
# leapp upgrade
# sqlite3 /var/lib/leapp/leapp.db "select message_data from messages_data where actor='read_openssh_config'" | jq '.'
{
"ciphers": null,
"deprecated_directives": [],
"macs": null,
"modified": false,
"permit_root_login": [],
"protocol": null,
"subsystem_sftp": null,
"use_privilege_separation": null
}
~~~

Leapp is inhibited unless the file is removed, or the openssh-server package is installed. 



## Expectations
Verify the openssh-server package is installed before performing any checks on openssh-server configuration files.



**Kyle Walker**
# diff /usr/share/leapp-repository/repositories/system_upgrade/common/actors/opensshpermitrootlogincheck/actor.py.orig /usr/share/leapp-repository/repositories/system_upgrade/common/actors/opensshpermitrootlogincheck/actor.py
5a6
> from leapp.libraries.common.rpms import has_package
7c8
< from leapp.models import OpenSshConfig, Report
---
> from leapp.models import OpenSshConfig, InstalledRedHatSignedRPM, Report
35c36
<   consumes = (OpenSshConfig, )
---
>   consumes = (OpenSshConfig, InstalledRedHatSignedRPM, )
40,55c41,59
<     openssh_messages = self.consume(OpenSshConfig)
<     config = next(openssh_messages, None)
<     if list(openssh_messages):
<       api.current_logger().warning('Unexpectedly received more than one OpenSshConfig message.')
<     if not config:
<       raise StopActorExecutionError(
<         'Could not check openssh configuration', details={'details': 'No OpenSshConfig facts found.'}
<       )
<
<     if get_source_major_version() == '7':
<       self.process7to8(config)
<     elif get_source_major_version() == '8':
<       self.process8to9(config)
<     else:
<       api.current_logger().warning('Unknown source major version: {} (expecting 7 or 8)'
<                     .format(get_source_major_version()))
---
>     has_server = has_package(InstalledRedHatSignedRPM, 'openssh-server')
>
>     if has_server:
>      openssh_messages = self.consume(OpenSshConfig)
>      config = next(openssh_messages, None)
>      if list(openssh_messages):
>        api.current_logger().warning('Unexpectedly received more than one OpenSshConfig message.')
>      if not config:
>        raise StopActorExecutionError(
>          'Could not check openssh configuration', details={'details': 'No OpenSshConfig facts found.'}
>        )
>
>      if get_source_major_version() == '7':
>        self.process7to8(config)
>      elif get_source_major_version() == '8':
>        self.process8to9(config)
>      else:
>        api.current_logger().warning('Unknown source major version: {} (expecting 7 or 8)'
>                      .format(get_source_major_version()))

Comment 1 Petr Stodulka 2023-06-06 12:32:06 UTC
Hi John, thanks for the report. Just curious, what is the reason for keeping the config file present on the system when openssh-server is not installed? Is customer using own "ssh server" app? Just want to understand the use case / customer story behind this scenario. Thanks

Comment 2 jcastran 2023-06-21 12:14:54 UTC
The configuration file should not have been kept on the system. We suspect the package was removed during the 6>7 upgrade incorrectly.

The file is present and the upgrade is completely blocked for false reasons. We can't continue the upgrade because the package is not marked as installed, so we can't verify the file has been modified. Leapp should verify the package is installed first, then check the files to avoid this issue.

Comment 3 Petr Stodulka 2023-06-21 12:24:11 UTC
I agree with you, just in this customer should not be really blocked as they can simply remove the file or install the missing package before the upgrade. But yes, I agree we should check it.


Note You need to log in before you can comment on or make changes to this bug.