osbuild-composer icon indicating copy to clipboard operation
osbuild-composer copied to clipboard

The "new" way of getting RHSM secrets does not work with the default RHEL repos shipped by composer

Open thozza opened this issue 3 years ago • 1 comments

Describe the bug The new code for getting RHSM secrets does not work with the currently shipped repo definitions for RHEL. The reason is that these use release with minor version (e.g. 8.5) as the releasever in the baseurl https://github.com/osbuild/osbuild-composer/blob/c37b688dd2c0dbc325533c0919b9c56dfe789c25/repositories/rhel-85.json#L53, however the RHSM code is replacing the $releasever in the baseurl found in redhat.repo with value returned by Distro.Releasever() , which is always only the major version, e.g. 8 for all RHEL-8.Y distros.

Relevant code is: https://github.com/osbuild/osbuild-composer/blob/c37b688dd2c0dbc325533c0919b9c56dfe789c25/internal/rhsm/secrets.go#L144 https://github.com/osbuild/osbuild-composer/blob/c37b688dd2c0dbc325533c0919b9c56dfe789c25/internal/distro/rhel85/distro.go#L59-L61 https://github.com/osbuild/osbuild-composer/blob/c37b688dd2c0dbc325533c0919b9c56dfe789c25/internal/distro/rhel85/distro.go#L21

So as a result, the condition https://github.com/osbuild/osbuild-composer/blob/e4d535ea5fdc730d0a8eed310e64efbd4baa4a5c/internal/rhsm/secrets.go#L146 will always evaluate on RHEL as false and the code falls back to the old way - using the first cert found on the disk.

I implemented extension to the RHSM unit test which test this situation and fails on current main: https://github.com/thozza/osbuild-composer/commit/1cc9f35bf472b7587318123108558dcc9750a95e

diff --git a/internal/rhsm/secrets_test.go b/internal/rhsm/secrets_test.go
index 55d3740d..906c49c3 100644
--- a/internal/rhsm/secrets_test.go
+++ b/internal/rhsm/secrets_test.go
@@ -32,6 +32,32 @@ sslclientkey = /etc/pki/entitlement/789-key.pem
 sslclientcert = /etc/pki/entitlement/101112.pem
 metadata_expire = 86400
 enabled_metadata = 0
+
+[rhel-8-for-x86_64-appstream-rpms]
+name = Red Hat Enterprise Linux 8 for x86_64 - AppStream (RPMs)
+baseurl = https://cdn.redhat.com/content/dist/rhel8/$releasever/x86_64/appstream/os
+enabled = 1
+gpgcheck = 1
+gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
+sslverify = 1
+sslcacert = /etc/rhsm/ca/redhat-uep.pem
+sslclientkey = /etc/pki/entitlement/121-key.pem
+sslclientcert = /etc/pki/entitlement/121.pem
+metadata_expire = 86400
+enabled_metadata = 1
+
+[rhel-8-for-x86_64-baseos-rpms]
+name = Red Hat Enterprise Linux 8 for x86_64 - BaseOS (RPMs)
+baseurl = https://cdn.redhat.com/content/dist/rhel8/$releasever/x86_64/baseos/os
+enabled = 1
+gpgcheck = 1
+gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
+sslverify = 1
+sslcacert = /etc/rhsm/ca/redhat-uep.pem
+sslclientkey = /etc/pki/entitlement/121-key.pem
+sslclientcert = /etc/pki/entitlement/121.pem
+metadata_expire = 86400
+enabled_metadata = 1
 `
 
 func TestParseRepoFile(t *testing.T) {
@@ -46,4 +72,16 @@ func TestParseRepoFile(t *testing.T) {
        assert.Equal(t, secrets.SSLCACert, "/etc/rhsm/ca/redhat-uep.pem", "Unexpected path to the CA certificate")
        assert.Equal(t, secrets.SSLClientCert, "/etc/pki/entitlement/456.pem", "Unexpected path to the client cert")
        assert.Equal(t, secrets.SSLClientKey, "/etc/pki/entitlement/123-key.pem", "Unexpected path to the client key")
+
+       // BaseURL from `repositories/rhel-85.json`
+       x86ComposerRepoBaseURL := "https://cdn.redhat.com/content/dist/rhel8/8.5/x86_64/baseos/os"
+       x86ArchName := "x86_64"
+       // value returned by rhel_85 Distro.Releasever()
+       rhel85distroReleasever := "8"
+
+       secrets, err = subscriptions.GetSecretsForBaseurl(x86ComposerRepoBaseURL, x86ArchName, rhel85distroReleasever)
+       require.NoError(t, err, "Failed to get secrets for a baseurl")
+       assert.Equal(t, secrets.SSLCACert, "/etc/rhsm/ca/redhat-uep.pem", "Unexpected path to the CA certificate")
+       assert.Equal(t, secrets.SSLClientCert, "/etc/pki/entitlement/121.pem", "Unexpected path to the client cert")
+       assert.Equal(t, secrets.SSLClientKey, "/etc/pki/entitlement/121-key.pem", "Unexpected path to the client key")
 }

Environment

  • OS version (/etc/os-release and /etc/redhat-release): RHEL
  • osbuild-composer version (rpm -qi osbuild-composer): latest main

To Reproduce Steps to reproduce the behavior: Hard to reproduce, because of the fallback code which makes all work in the most usual simple case.

Expected behavior Either the RHSM code should be extended to cope with the minor version in releasever or composer should not ship RHEL repo definitions with minor version specified in it.

thozza avatar Nov 23 '21 18:11 thozza

This is a problem because there are multiple sources of this information:

  1. There is the redhat-release package (see rpm -q --provides redhat-release)
  2. There are overrides in /etc/dnf/vars/releasever

I tried to run fresh RHEL 8.5 QCOW2 and subscribe it. It defaults to the URL without minor version (8 instead of 8.5). It might be confusing for some users if the images are built using a different distro than the host system is subscribed to.

And what is even worse is the combination with cross-distro (in this case cross-minor-version) image building. Imagine you have the same URL for two minor versions. The only difference is in the $releasever variable. I don't know if that is possible, but if there were two subscriptions, one for each minor version, how is the osbuild-composer going to decide which one to use?

I'm afraid we are doomed to fail if we try to cover all use cases in composer for example by allowing the user to set the releasever by hand.

It might be better to rethink the source management, e.g.:

  • Using system repos if the user wish to do so (by configuring composer). This seems to be the most common use case in our internal bug reports.
  • Specifying exact repos and their CA/cert/key. Tedious but at least it would provide a space for a workaround.

msehnout avatar Nov 24 '21 09:11 msehnout