Bug 1211764

Summary: Installer defaults to unconditionally enabling sshd service and port 22
Product: [openSUSE] openSUSE Tumbleweed Reporter: Andrei Borzenkov <arvidjaar>
Component: YaST2Assignee: YaST Team <yast-internal>
Status: RESOLVED FIXED QA Contact: Jiri Srain <jsrain>
Severity: Normal    
Priority: P5 - None CC: jreidinger, pdostal
Version: Current   
Target Milestone: ---   
Hardware: Other   
OS: Other   
URL: https://trello.com/c/ofwfoQfm
Whiteboard:
Found By: --- Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---
Attachments: YaST installer logs
Debug logs with a reproducer

Description Andrei Borzenkov 2023-05-27 05:00:32 UTC
Created attachment 867258 [details]
YaST installer logs

At least for the firewall the explicit default in control file is still to block port 22:

<firewall_enable_ssh config:type="boolean">false</firewall_enable_ssh>

with the only exceptions for server and transactional server roles.

Testing new Tumbleweed installation selecting KDE desktop and explicit root password (no public key) results in enabled sshd and open port 22.

As far as see in YaST installation security_settings.rb, service/port should be enabled if user root does not have password which is not the case here.

Log just says that these settings are enabled without any details *why* they are enabled

2023-05-27 00:37:35 <1> 10(4032) [Ruby] installation/security_settings.rb(enable_sshd!):104 Enabling SSHD
2023-05-27 00:37:35 <1> 10(4032) [Ruby] installation/security_settings.rb(open_ssh!):118 Opening SSH port

For the sake of completeness attached are logs from within installer at the summary screen.

For comparison, Leap 15.4 installer with the same settings defaults to sshd disabled and port 22 blocked and Leap 15.5 installer defaults to sshd enabled and port 22 open.
Comment 1 Lukas Ocilka 2023-05-29 10:42:53 UTC
Selected role: kde

YaST2/control-inst/control.xml contains
globals -> enable_firewall = true
        -> firewall_enable_ssh = false

installation/security_settings.rb(enable_sshd!):104 Enabling SSHD
is called when: Yast::Linuxrc.usessh || only_public_key_auth || @enable_sshd
at https://github.com/yast/yast-installation/blob/master/src/lib/installation/security_settings.rb#L183-L185

SSH was not used in Linuxrc

It does not seem that you would use a pub-key only, so I tried to reproduce with some simple root pass (there is some "yes" confirmation recorded in the macro recorder log)

And indeed, at the end

SSH service will be "enabled"
SSH port will be "open"
Comment 2 Lukas Ocilka 2023-05-29 10:47:26 UTC
Created attachment 867274 [details]
Debug logs with a reproducer
Comment 3 Stefan Hundhammer 2023-06-01 15:57:08 UTC
AFAICS we have a problem with the order of initialization:

Installation::SecuritySettings is meant to be used as a singleton. And as the singleton instance is used for the first time, all its values are initialized, and those values are FINAL.

That includes the values for opening the ssh port and the firewall. And as a fallback, if there is no root user yet, or the root password is empty, it assumes that there is only public key authentication, and in that case, it opens the ssh port and enables sshd.

The trouble is that all this happens BEFORE the user is prompted for the root password, so at that point, of course the root password is still empty, so it always falls back to public key authentication.

You can see this from the sequence in the debug logs:

2023-05-29 06:36:47 <1> install(3971) [Ruby]
  installation/security_settings.rb(enable_sshd!):104
  Enabling SSHD

2023-05-29 06:36:47 <1> install(3971) [Ruby]
  installation/security_settings.rb(open_ssh!):118
  Opening SSH port


Nevermind the changed system time, but the dialog for the root password actually comes after initializing those settings:

2023-05-29 12:37:40 <0> install(3971) [Ruby]
  binary/Yast.cc(ycp_module_call_ycp_function):401
  Append parameter
  `HSquash (`VBox (`RadioButtonGroup (`id (`action), `VBox (`VBox
  (`Left (`RadioButton (`id (`new_user), `opt (`notify), "&Create
  New User", true)), `VSpacing (0.3), `Left (`HBox (`HSpacing (5),
  `VBox (`InputField (`id (`full_name), `opt (`notify, `hstretch),
  "User's &Full Name", ""), `InputField (`id (`username), `opt
  (`notify, `hstretch), "&Username", ""), `Password (`id (`pw1),
  `opt (`hstretch), "&Password", ""), `Password (`id (`pw2), `opt
  (`hstretch), "C&onfirm Password", ""), `VSpacing (0.2), `Left
  (`CheckBox (`id (`root_pw), "U&se this password for system
  administrator", true)), `Left (`CheckBox (`id (`autologin),
  "&Automatic Login", true))))), `VSpacing (1)), `Empty (), `Left
  (`RadioButton (`id (`skip), `opt (`notify), "&Skip User
  Creation", false))))))
Comment 4 Stefan Hundhammer 2023-06-01 15:58:49 UTC
Oops, that was the dialog for creating the first user, but the root password is assigned even after that, so that does not invalidate the conclusion: This initialization of settings is too simplistic.
Comment 5 Stefan Hundhammer 2023-06-01 16:07:19 UTC
Installation::SecuritySettings::initialize():

https://github.com/yast/yast-installation/blob/master/src/lib/installation/security_settings.rb#L45-L60

> def initialize
>   textdomain "installation"
>   Yast.import "PackagesProposal"
>   Yast.import "ProductFeatures"
>   Yast.import "Linuxrc"
>
>   load_features
>   enable_firewall! if @enable_firewall
>   enable_sshd! if wanted_enable_sshd?
>   open_ssh! if wanted_open_ssh?
>   open_vnc! if wanted_open_vnc?
>   propose_lsm_config
>   # FIXME: obtain from Y2Firewall::Firewalld, control file or allow to
>   # chose a different one in the proposal
>   @default_zone = "public"
> end

https://github.com/yast/yast-installation/blob/master/src/lib/installation/security_settings.rb#L187-L189

> def wanted_open_ssh?
>   Yast::Linuxrc.usessh || only_public_key_auth || @open_ssh
> end


https://github.com/yast/yast-installation/blob/master/src/lib/installation/security_settings.rb#L200-L206

> # Determines whether only public key authentication is supported
> #
> # @note If the root user does not have a password, we assume that we will use a public
> #   key in order to log into the system. In such a case, we need to enable the SSH
> #   service (including opening the port).
> def only_public_key_auth
>   return true unless root_user
>
>   password = root_user.password_content || ""
>
>   password.empty?
> end
Comment 6 Stefan Hundhammer 2023-06-01 16:08:59 UTC
So, rather than nailing those values down in the constructor already, we will need to either postpone this or introduce a recalc() method to be called when appropriate; for example, when making the security settings proposal.
Comment 7 Stefan Hundhammer 2023-06-01 16:14:33 UTC
And BTW the logging in several of the methods is plain wrong:

https://github.com/yast/yast-installation/blob/master/src/lib/installation/security_settings.rb#L122-L126

    # Set the ssh port to be closed
    def close_ssh!
      log.info "Opening SSH port"
      self.open_ssh = false
    end

https://github.com/yast/yast-installation/blob/master/src/lib/installation/security_settings.rb#L128-L132

    # Set the vnc port to be opened
    def open_vnc!
      log.info "Close VNC port"
      self.open_vnc = true
    end
Comment 8 Stefan Hundhammer 2023-06-05 11:28:08 UTC
Added to our Trello task queue.
Comment 9 Stefan Hundhammer 2023-06-13 11:18:10 UTC
Knut found the change that apparently caused the premature instantiation of the singleton:

https://github.com/yast/yast-security/blob/master/src/lib/y2security/security_policies/target_config.rb#L90

This is in SLE-15-SP4 and SP5, not in -SP3.
Comment 10 Stefan Hundhammer 2023-06-15 15:09:26 UTC
Fix for SLE-15-SP4 / Leap 15.4 with explanations:

  https://github.com/yast/yast-installation/pull/1090

A merge for SLE-15-SP5 / Leap 15.5 and later Factory / TW will follow.
Comment 13 Stefan Hundhammer 2023-06-20 09:09:46 UTC
Fix for SLE-15-SP4 / Leap 15.4:

  https://github.com/yast/yast-installation/pull/1090

SR to IBS for SLE-15-SP4 / Leap 15.4:

  https://build.suse.de/request/show/301289

This will arrive in SLE-15-SP4 / Leap 15.4 as 

  yast2-installation-4.4.59

-----------------------

Fix for SLE-15-SP5 / Leap 15.5:

  https://github.com/yast/yast-installation/pull/1091

SR to IBS for SLE-15-SP5 / Leap 15.5:

  https://build.suse.de/request/show/301289

This will arrive in SLE-15-SP4 / Leap 15.4 as 

  yast2-installation-4.5.17

-----------------------

Fix for master / Factory:

  https://github.com/yast/yast-installation/pull/1092

SR for master / Factory:

  https://build.suse.de/request/show/301436

This will arrive in Factory / TW as 

  yast2-installation-4.6.4
Comment 14 Maintenance Automation 2023-08-07 12:37:01 UTC
SUSE-RU-2023:3203-1: An update that has one recommended fix can now be installed.

Category: recommended (moderate)
Bug References: 1211764
Sources used:
openSUSE Leap 15.5 (src): yast2-installation-4.5.17-150500.3.3.1
Basesystem Module 15-SP5 (src): yast2-installation-4.5.17-150500.3.3.1

NOTE: This line indicates an update has been released for the listed product(s). At times this might be only a partial fix. If you have questions please reach out to maintenance coordination.
Comment 15 Maintenance Automation 2023-08-07 16:30:34 UTC
SUSE-RU-2023:3205-1: An update that has one recommended fix can now be installed.

Category: recommended (moderate)
Bug References: 1211764
Sources used:
openSUSE Leap 15.4 (src): yast2-installation-4.4.59-150400.3.18.1
SUSE Linux Enterprise High Performance Computing 15 SP4 (src): yast2-installation-4.4.59-150400.3.18.1
SUSE Linux Enterprise Server 15 SP4 (src): yast2-installation-4.4.59-150400.3.18.1
SUSE Manager Server 4.3 (src): yast2-installation-4.4.59-150400.3.18.1
SUSE Linux Enterprise Server for SAP Applications 15 SP4 (src): yast2-installation-4.4.59-150400.3.18.1
SUSE Linux Enterprise Desktop 15 SP4 (src): yast2-installation-4.4.59-150400.3.18.1
SUSE Manager Retail Branch Server 4.3 (src): yast2-installation-4.4.59-150400.3.18.1
SUSE Manager Proxy 4.3 (src): yast2-installation-4.4.59-150400.3.18.1
Basesystem Module 15-SP4 (src): yast2-installation-4.4.59-150400.3.18.1

NOTE: This line indicates an update has been released for the listed product(s). At times this might be only a partial fix. If you have questions please reach out to maintenance coordination.