Fixes #39645 - Replace Fog::SSH/SCP with system SSH - #11176
Conversation
ogajduse
left a comment
There was a problem hiding this comment.
Packaging ACK, as I see that you have the packaging changes on your radar.
Reading from the PR description:
Drop ssh-ssh/scp packages from our repos.
For the record, the packages can be only removed after ReX also drops the dependency, it still needs it for relatively trivial reason and there is a ticket for that. I created https://redhat.atlassian.net/browse/SAT-49367 and I will move it to the ReX epic if core is merged earlier. |
stejskalleos
left a comment
There was a problem hiding this comment.
Few comments from the first look, after the fix I will test the workflow
|
|
||
| def scp | ||
| Fog::SCP.new(address, username, options) | ||
| Tempfile.open("foreman-ssh-#{@uuid}") do |f| |
There was a problem hiding this comment.
From Ruby 3.0.z docs:
This method is not recommended and exists mostly for backward compatibility. Please use Tempfile.create instead, which avoids the cost of delegation, does not rely on a finalizer, and also unlinks the file when given a block.
| end | ||
| end | ||
|
|
||
| test "key file has 0600 permissions" do |
There was a problem hiding this comment.
I assume the file is created with 0600 permissions, but what if it isn't?
I'm not sure if it is possible, but could we explicitly set the permissions after the key file is created?
Just to be sure.
There was a problem hiding this comment.
Both functions has 0600 hardcoded in them, but I wrote test just to be sure. Not sure where your comment aims?
| def initialize(address, username = "root", options = {}) | ||
| @username = username | ||
| @address = address | ||
| @template = options.delete(:template) || raise("must provide a template") |
There was a problem hiding this comment.
| @template = options.delete(:template) || raise("must provide a template") | |
| @template = options.delete(:template) || raise ::Foreman::Exception.new(N_('must provide a template')) |
| end | ||
| end | ||
| if Process.clock_gettime(Process::CLOCK_MONOTONIC) >= deadline | ||
| raise "Failed to connect to #{@address} after #{Setting[:ssh_timeout]} seconds" |
There was a problem hiding this comment.
| raise "Failed to connect to #{@address} after #{Setting[:ssh_timeout]} seconds" | |
| raise ::Foreman::Exception.new(N_("Failed to connect to #{@address} after #{Setting[:ssh_timeout]} seconds")) |
There was a problem hiding this comment.
Because of exception extractor, I will use placeholders instead. But thanks for the catch.
| :logger => logger, | ||
| } | ||
| end | ||
| def ssh_options(key_file) |
There was a problem hiding this comment.
Comment from AI:
ssh_options missing -oBatchMode=yes
Not setting -oBatchMode=yes means SSH could prompt for a passphrase interactively if key auth is configured but the key is encrypted (or if sshpass fails for password auth). Since these are machine-generated ephemeral keys in a provisioning context this is low-risk, but worth noting.
78f884e to
4d55293
Compare
|
Thanks for the review, all remarks done except not sure what you meant by the 0600 comment. I just added the test there for extra coverage - it is hardcoded in (both) functions). |
Rubygem
net-sshdoes not provide all features for PQC and overall, we would like to simplify crypto stack in Foreman. This patch refactors the SSH service class so it shells out tosshandsshpassinstead.The previous workflow was also quite complex, the main goal of the SSH finish script is not super-resilient SSH scheduling, but to bootstrap other components like Remote Execution or Ansible and for this, there is no need to establish a long-lasting connection via sockets.
Furthermore, the old solution copied the script using
scpwhich is also unnecessary. Instead, there are simply two connections made usingsshcommand:pingmethod, previously this was namedestabilish_connection!but this would be confusing. I made the method explicit so constructor does not perform this - this was confusing behavior.deploy!method, instead ofscpthe script is simply passed via STDIN - no need of temporary files.Other major changes to further simplify the code:
cleanupmethod call. Instead, it is created just for the minimum possible time in therun_sshmethod and cleaned immediately.run_sshmethod (DRY).I thought for a moment that we could even get rid of the
pingand simply try to execute the template directly in a loop, but I discarded the idea. It is safer to be explicit.I tested this via rails command in the proper SELinux policy with a small change (see the linked PR):
This is a followup for previous work in #10518 and #10615 which was reverted.
TODO
sshandsshpassdependencies toforemanpackage.ssh-ssh/scppackages from our repos. (After we drop the library from ReX)Relevant PRs: