Skip to content

Fixes #39518 - Fall back safely when tls_ciphers 'PROFILE=SYSTEM' is unsupported - #953

Draft
ogajduse wants to merge 1 commit into
theforeman:developfrom
ogajduse:fix/tls-ciphers-profile-system-fallback
Draft

Fixes #39518 - Fall back safely when tls_ciphers 'PROFILE=SYSTEM' is unsupported#953
ogajduse wants to merge 1 commit into
theforeman:developfrom
ogajduse:fix/tls-ciphers-profile-system-fallback

Conversation

@ogajduse

Copy link
Copy Markdown
Member

Problem

resolve_tls_ciphers (added in #947 / #39405) defaults tls_ciphers to the literal string 'PROFILE=SYSTEM' whenever /etc/crypto-policies/back-ends/opensslcnf.config exists, on the assumption that presence of that file means the currently-linked OpenSSL understands PROFILE=SYSTEM (a Red Hat/Fedora-only OpenSSL patch keyword).

This breaks on a nominally-RHEL host whose Ruby is linked against a vendored, non-RHEL-patched OpenSSL. Concretely: smart-proxy-develop-source-release's ruby=3.0.4 CI leg runs on RHEL/CentOS Stream 9 (crypto-policies present, correctly detected), but rbenv/ruby-build vendors a plain openssl-1.1.1w built from openssl.org source for that specific Ruby version (its needs_openssl gate requires 1.0.1-1.x.x; CentOS9's system OpenSSL 3.5.x falls outside that range). That vendored OpenSSL rejects 'PROFILE=SYSTEM' outright:

Invalid tls_ciphers value 'PROFILE=SYSTEM': SSL_CTX_set_cipher_list: no cipher match (RuntimeError)

...and the proxy never starts. Reproduced this exact failure directly by compiling openssl-1.1.1w from source in a real centos:stream9 container and confirming the byte-identical error. Full root-cause writeup: https://projects.theforeman.org/issues/39518

Fix

opensslcnf.config isn't just a "RHEL detected" signal file — it contains the actual resolved cipher spec in plain, portable OpenSSL syntax (CipherString = @SECLEVEL=2:kEECDH:...), independent of the PROFILE= keyword. resolve_tls_ciphers now:

  1. Probes 'PROFILE=SYSTEM' before committing to it (via a live OpenSSL::SSL::SSLContext#ciphers= check).
  2. If unsupported, parses and uses the CipherString from opensslcnf.config directly — same security intent as the active crypto policy, but works on any OpenSSL build.
  3. Falls back to 'HIGH' only if that also fails, so the auto-detected default can never crash startup.

validate_tls_ciphers! is refactored to share the same probe helper (cipher_string_supported?) — pure dedup, no behavior change for explicitly-configured tls_ciphers values.

Testing

  • bundle exec rake test TEST=test/launcher_test.rb — 25/25 pass, including 3 new tests covering the fallback chain.
  • Full suite (bundle exec rake test, excluding bmc/libvirt modules which need unrelated native system libs) — 872/872 pass.
  • Verified live end-to-end on a machine where PROFILE=SYSTEM is also rejected by the local OpenSSL build: resolve_tls_ciphers correctly falls through to the parsed CipherString instead of returning an unusable value.
  • Reproduced the original failure and the fix directly on real CentOS Stream 9 via podman (see issue #39518 for full transcript).

Marked as draft pending maintainer input — opening for early visibility/feedback.

…unsupported

resolve_tls_ciphers previously trusted the presence of
/etc/crypto-policies/back-ends/opensslcnf.config alone to mean the
'PROFILE=SYSTEM' cipher-list alias would work, but that alias is a
Red Hat/Fedora OpenSSL patch. On a nominally-RHEL host whose Ruby links
a vendored, non-RHEL-patched OpenSSL (e.g. rbenv/ruby-build compiling
openssl-1.1.1w for Ruby 3.0.4 on CentOS Stream 9), SSL_CTX_set_cipher_list
rejects it outright and the server fails to start.

Probe 'PROFILE=SYSTEM' before committing to it. If unsupported, parse and
use the CipherString already resolved in opensslcnf.config directly (plain,
portable OpenSSL syntax, not RHEL-specific) to preserve the active crypto
policy's intent. Fall back to 'HIGH' only if that also fails, so the
auto-detected default can never crash startup.
@lhellebr

Copy link
Copy Markdown
Contributor

When discussing #947 - and we discussed it a lot - there seemed to be a prevailing opinion that a RHEL system where Foreman can't use PROFILE=SYSTEM is a broken system and it's on user to deal with it.
This may or may not be a different case because it's specific to Ruby distribution being used. I'm interested in @ekohl opinion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants