lzap
September 9, 2026, 7:11pm
7
You mean the code path that was using any SSH key from Foreman’s HOME folder?
To keep the status quo, I added a one commit to the existing PR: when /var/lib/foreman/ssh_finish_key file exists (and has 600 permissions) then use it as a possible SSH key. This way users who were using SSH keys in Foreman home directory can still do this.
develop ← lzap:core-ssh1-39645
opened 01:19PM - 18 Aug 26 UTC
Rubygem `net-ssh` does not provide all features for PQC and overall, we would li… ke to simplify crypto stack in Foreman. This patch refactors the SSH service class so it shells out to `ssh` and `sshpass` instead.
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 `scp` which is also unnecessary. Instead, there are simply two connections made using `ssh` command:
* The initial wait for the VM is done via `ping` method, previously this was named `estabilish_connection!` but this would be confusing. I made the method explicit so constructor does not perform this - this was confusing behavior.
* The final call is then done via `deploy!` method, instead of `scp` the script is simply passed via STDIN - no need of temporary files.
Other major changes to further simplify the code:
* For sshkey authentication, the temporary file with the private key is no longer created in the constructor relying on the `cleanup` method call. Instead, it is created just for the minimum possible time in the `run_ssh` method and cleaned immediately.
* Logging was moved to `run_ssh` method (DRY).
* Unit test was written by Claude, a bit heavy to my taste I will happily drop some cases.
I thought for a moment that we could even get rid of the `ping` and 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):
```
systemd-run --pipe --wait --service-type=oneshot \
-p SELinuxContext=system_u:system_r:foreman_rails_t:s0 \
-p User=foreman \
-p WorkingDirectory=/usr/share/foreman \
-p Environment=RAILS_ENV=production \
-p PrivateTmp=no \
/usr/share/foreman/bin/rails runner /tmp/test_ssh_provision.rb
```
This is a followup for previous work in https://github.com/theforeman/foreman/pull/10518 and https://github.com/theforeman/foreman/pull/10615 which was reverted.
**TODO**
* [x] Create PR to SELinux policy with the changes.
* [x] Add `ssh` and `sshpass` dependencies to `foreman` package.
* [ ] Drop `ssh-ssh/scp` packages from our repos. (After we drop the library from ReX)
Relevant PRs:
* https://github.com/theforeman/foreman-packaging/pull/14041
* https://github.com/theforeman/foreman-packaging/pull/14042
@ekohl do you want me to create a Jira Feature or Spike? This is definitely something we will not have time in 2026 or early 2027 but just in case.