leapp-repository/SOURCES/0075-removeobsoletegpgkeys-Adjust-for-converting.patch
eabdullin 37f55f86cd Import from CS git
(cherry picked from commit 3f0f8c21af)
2026-01-20 12:16:09 +02:00

533 lines
20 KiB
Diff

From 37a071df9242e10821b8d6ab7a0e727ffb7e871d Mon Sep 17 00:00:00 2001
From: Matej Matuska <mmatuska@redhat.com>
Date: Fri, 19 Sep 2025 17:18:48 +0200
Subject: [PATCH 075/111] removeobsoletegpgkeys: Adjust for converting
When doing upgrade + conversion, removing obsolete GPG from the current
(or target for that matter) distro doesn't make sense, because we are
moving to a different distro.
Instead, all distro provided keys from the source distro need to be
removed, as the target distro uses it's own keys. Those are imported
elsewhere later during the upgrade.
A new list is added to the gpg-signatures.json maps, which contains the
names of the fake RPMs "generated" upon importing a GPG key into the RPM
DB.
These are in the order the key IDs ("keys" in the map) are in, however
the mapping is not always 1:1 (e.g. the Centos SIG Extras keys).
The key id could be mapped to the RPM names, however since the RPM NVR
format is:
gpg-pubkey-<last 8 chars from key ID>-<creation time of the signature packet>
there could be a collision between the key IDs.
Some key RPMs are missing in Alma Linux map as I couldn't find out what
keys some the fingerprints correspond to.
Jira: RHEL-110190
I addded annotations to the keys at:
https://github.com/oamg/leapp-repository/wiki/gpg%E2%80%90signatures.json-key-annotations.
---
.../actors/removeobsoletegpgkeys/actor.py | 11 +-
.../libraries/removeobsoleterpmgpgkeys.py | 50 +++-
.../tests/test_removeobsoleterpmgpgkeys.py | 244 ++++++++++++------
.../distro/almalinux/gpg-signatures.json | 12 +-
.../files/distro/centos/gpg-signatures.json | 12 +-
.../files/distro/rhel/gpg-signatures.json | 20 +-
6 files changed, 229 insertions(+), 120 deletions(-)
diff --git a/repos/system_upgrade/common/actors/removeobsoletegpgkeys/actor.py b/repos/system_upgrade/common/actors/removeobsoletegpgkeys/actor.py
index 5674ee3f..58b15a84 100644
--- a/repos/system_upgrade/common/actors/removeobsoletegpgkeys/actor.py
+++ b/repos/system_upgrade/common/actors/removeobsoletegpgkeys/actor.py
@@ -8,9 +8,14 @@ class RemoveObsoleteGpgKeys(Actor):
"""
Remove obsoleted RPM GPG keys.
- New version might make existing RPM GPG keys obsolete. This might be caused
- for example by the hashing algorithm becoming deprecated or by the key
- getting replaced.
+ The definition of what keys are considered obsolete depends on whether the
+ upgrade also does a conversion:
+ - If not converting, the obsolete keys are those that are no longer valid
+ on the target version. This might be caused for example by the hashing
+ algorithm becoming deprecated or by the key getting replaced. Note that
+ only keys provided by the vendor of the OS are handled.
+ - If converting, the obsolete keys are all of the keys provided by the
+ vendor of the source distribution.
A DNFWorkaround is registered to actually remove the keys.
"""
diff --git a/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py b/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py
index df08e6fa..7d047395 100644
--- a/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py
+++ b/repos/system_upgrade/common/actors/removeobsoletegpgkeys/libraries/removeobsoleterpmgpgkeys.py
@@ -1,3 +1,5 @@
+import itertools
+
from leapp.libraries.common.config import get_source_distro_id, get_target_distro_id
from leapp.libraries.common.config.version import get_target_major_version
from leapp.libraries.common.distro import get_distribution_data
@@ -6,18 +8,25 @@ from leapp.libraries.stdlib import api
from leapp.models import DNFWorkaround, InstalledRPM
+def _is_key_installed(key):
+ """
+ :param key: The NVR of the gpg key RPM (e.g. gpg-pubkey-1d997668-61bae63b)
+ """
+ name, version, release = key.rsplit("-", 2)
+ return has_package(InstalledRPM, name, version=version, release=release)
+
+
def _get_obsolete_keys():
"""
- Return keys obsoleted in target and previous versions
+ Get keys obsoleted in target and previous major versions
"""
distribution = get_target_distro_id()
- obsoleted_keys_map = get_distribution_data(distribution).get('obsoleted-keys', {})
+ obsoleted_keys_map = get_distribution_data(distribution).get("obsoleted-keys", {})
keys = []
for version in range(7, int(get_target_major_version()) + 1):
try:
for key in obsoleted_keys_map[str(version)]:
- name, version, release = key.rsplit("-", 2)
- if has_package(InstalledRPM, name, version=version, release=release):
+ if _is_key_installed(key):
keys.append(key)
except KeyError:
pass
@@ -25,6 +34,22 @@ def _get_obsolete_keys():
return keys
+def _get_source_distro_keys():
+ """
+ Get all known keys of the source distro
+
+ This includes keys from all relevant previous OS versions as all of those
+ might be present on the system.
+ """
+ distribution = get_source_distro_id()
+ keys = get_distribution_data(distribution).get("keys", {})
+ return [
+ key
+ for key in itertools.chain.from_iterable(keys.values())
+ if _is_key_installed(key)
+ ]
+
+
def register_dnfworkaround(keys):
api.produce(
DNFWorkaround(
@@ -36,13 +61,12 @@ def register_dnfworkaround(keys):
def process():
- if get_source_distro_id() != get_target_distro_id():
- # TODO adjust for conversions, in the current state it would not have
- # any effect, just skip it
- return
-
- keys = _get_obsolete_keys()
- if not keys:
- return
+ if get_source_distro_id() == get_target_distro_id():
+ # only upgrading - remove keys obsoleted in previous versions
+ keys = _get_obsolete_keys()
+ else:
+ # also converting - we need to remove all keys from the source distro
+ keys = _get_source_distro_keys()
- register_dnfworkaround(keys)
+ if keys:
+ register_dnfworkaround(keys)
diff --git a/repos/system_upgrade/common/actors/removeobsoletegpgkeys/tests/test_removeobsoleterpmgpgkeys.py b/repos/system_upgrade/common/actors/removeobsoletegpgkeys/tests/test_removeobsoleterpmgpgkeys.py
index b78174cc..8b9b842b 100644
--- a/repos/system_upgrade/common/actors/removeobsoletegpgkeys/tests/test_removeobsoleterpmgpgkeys.py
+++ b/repos/system_upgrade/common/actors/removeobsoletegpgkeys/tests/test_removeobsoleterpmgpgkeys.py
@@ -1,77 +1,79 @@
import os
+import unittest.mock as mock
import pytest
from leapp.libraries.actor import removeobsoleterpmgpgkeys
-from leapp.libraries.common.config.version import get_target_major_version
-from leapp.libraries.common.rpms import has_package
from leapp.libraries.common.testutils import CurrentActorMocked, produce_mocked
from leapp.libraries.stdlib import api
-from leapp.models import DNFWorkaround, InstalledRPM, RPM
+from leapp.models import InstalledRPM, RPM
+_CUR_DIR = os.path.dirname(os.path.abspath(__file__))
-def _get_test_installedrpm():
- return InstalledRPM(
+
+def common_folder_path_mocked(folder):
+ return os.path.join(_CUR_DIR, "../../../files/", folder)
+
+
+def test_is_key_installed(monkeypatch):
+ installed_rpms = InstalledRPM(
items=[
RPM(
- name='gpg-pubkey',
- version='d4082792',
- release='5b32db75',
- epoch='0',
- packager='Red Hat, Inc. (auxiliary key 2) <security@redhat.com>',
- arch='noarch',
- pgpsig=''
+ name="gpg-pubkey",
+ version="d4082792",
+ release="5b32db75",
+ epoch="0",
+ packager="Red Hat, Inc. (auxiliary key 2) <security@redhat.com>",
+ arch="noarch",
+ pgpsig="",
),
RPM(
- name='gpg-pubkey',
- version='2fa658e0',
- release='45700c69',
- epoch='0',
- packager='Red Hat, Inc. (auxiliary key) <security@redhat.com>',
- arch='noarch',
- pgpsig=''
+ name="gpg-pubkey",
+ version="2fa658e0",
+ release="45700c69",
+ epoch="0",
+ packager="Red Hat, Inc. (auxiliary key) <security@redhat.com>",
+ arch="noarch",
+ pgpsig="",
),
RPM(
- name='gpg-pubkey',
- version='12345678',
- release='abcdefgh',
- epoch='0',
- packager='made up',
- arch='noarch',
- pgpsig=''
+ name="gpg-pubkey",
+ version="12345678",
+ release="abcdefgh",
+ epoch="0",
+ packager="made up",
+ arch="noarch",
+ pgpsig="",
),
]
)
+ monkeypatch.setattr(
+ api, "current_actor", CurrentActorMocked(msgs=[installed_rpms])
+ )
+
+ assert removeobsoleterpmgpgkeys._is_key_installed("gpg-pubkey-d4082792-5b32db75")
+ assert removeobsoleterpmgpgkeys._is_key_installed("gpg-pubkey-2fa658e0-45700c69")
+ assert removeobsoleterpmgpgkeys._is_key_installed("gpg-pubkey-12345678-abcdefgh")
+ assert not removeobsoleterpmgpgkeys._is_key_installed(
+ "gpg-pubkey-db42a60e-37ea5438"
+ )
+
@pytest.mark.parametrize(
"version, expected",
[
- (9, ["gpg-pubkey-d4082792-5b32db75", "gpg-pubkey-2fa658e0-45700c69"]),
- (8, ["gpg-pubkey-2fa658e0-45700c69"])
+ ("9", ["gpg-pubkey-d4082792-5b32db75", "gpg-pubkey-2fa658e0-45700c69"]),
+ ("8", ["gpg-pubkey-2fa658e0-45700c69"])
]
)
def test_get_obsolete_keys(monkeypatch, version, expected):
- def get_target_major_version_mocked():
- return version
-
- monkeypatch.setattr(
- removeobsoleterpmgpgkeys,
- "get_target_major_version",
- get_target_major_version_mocked,
- )
-
+ monkeypatch.setattr(api, "current_actor", CurrentActorMocked(dst_ver=version))
+ monkeypatch.setattr(api, "get_common_folder_path", common_folder_path_mocked)
monkeypatch.setattr(
- api,
- "current_actor",
- CurrentActorMocked(
- msgs=[_get_test_installedrpm()]
- ),
+ removeobsoleterpmgpgkeys, "_is_key_installed", lambda key: key in expected
)
- cur_dir = os.path.dirname(os.path.abspath(__file__))
- monkeypatch.setattr(api, 'get_common_folder_path', lambda folder: os.path.join(cur_dir, '../../../files/', folder))
-
keys = removeobsoleterpmgpgkeys._get_obsolete_keys()
assert set(keys) == set(expected)
@@ -79,50 +81,83 @@ def test_get_obsolete_keys(monkeypatch, version, expected):
@pytest.mark.parametrize(
"version, obsoleted_keys, expected",
[
- (10, None, []),
- (10, {}, []),
- (10, {"8": ["gpg-pubkey-888-abc"], "10": ["gpg-pubkey-10-10"]}, ["gpg-pubkey-888-abc", "gpg-pubkey-10-10"]),
- (9, {"8": ["gpg-pubkey-888-abc"], "9": ["gpg-pubkey-999-def"]}, ["gpg-pubkey-999-def", "gpg-pubkey-888-abc"]),
- (8, {"8": ["gpg-pubkey-888-abc"], "9": ["gpg-pubkey-999-def"]}, ["gpg-pubkey-888-abc"])
- ]
+ ("10", None, []),
+ ("10", {}, []),
+ (
+ "10",
+ {"8": ["gpg-pubkey-888-abc"], "10": ["gpg-pubkey-10-10"]},
+ ["gpg-pubkey-888-abc", "gpg-pubkey-10-10"],
+ ),
+ (
+ "9",
+ {"8": ["gpg-pubkey-888-abc"], "9": ["gpg-pubkey-999-def"]},
+ ["gpg-pubkey-999-def", "gpg-pubkey-888-abc"],
+ ),
+ (
+ "8",
+ {"8": ["gpg-pubkey-888-abc"], "9": ["gpg-pubkey-999-def"]},
+ ["gpg-pubkey-888-abc"],
+ ),
+ ],
)
-def test_get_obsolete_keys_incomplete_data(monkeypatch, version, obsoleted_keys, expected):
- def get_target_major_version_mocked():
- return version
+def test_get_obsolete_keys_incomplete_data(
+ monkeypatch, version, obsoleted_keys, expected
+):
+ monkeypatch.setattr(api, "current_actor", CurrentActorMocked(dst_ver=version))
+ monkeypatch.setattr(
+ removeobsoleterpmgpgkeys, "_is_key_installed", lambda key: key in expected
+ )
def get_distribution_data_mocked(_distro):
if obsoleted_keys is None:
return {}
- return {'obsoleted-keys': obsoleted_keys}
-
- def has_package_mocked(*args, **kwargs):
- return True
+ return {"obsoleted-keys": obsoleted_keys}
monkeypatch.setattr(
- removeobsoleterpmgpgkeys,
- "get_target_major_version",
- get_target_major_version_mocked,
+ removeobsoleterpmgpgkeys, "get_distribution_data", get_distribution_data_mocked
)
- monkeypatch.setattr(
- removeobsoleterpmgpgkeys,
- "get_distribution_data",
- get_distribution_data_mocked,
- )
+ keys = removeobsoleterpmgpgkeys._get_obsolete_keys()
+ assert set(keys) == set(expected)
- monkeypatch.setattr(
- removeobsoleterpmgpgkeys,
- "has_package",
- has_package_mocked,
- )
+@pytest.mark.parametrize(
+ "distro, expected",
+ [
+ (
+ "centos",
+ [
+ "gpg-pubkey-8483c65d-5ccc5b19",
+ "gpg-pubkey-1d997668-621e3cac",
+ "gpg-pubkey-1d997668-61bae63b",
+ ],
+ ),
+ (
+ "rhel",
+ [
+ "gpg-pubkey-fd431d51-4ae0493b",
+ "gpg-pubkey-37017186-45761324",
+ "gpg-pubkey-f21541eb-4a5233e8",
+ "gpg-pubkey-897da07a-3c979a7f",
+ "gpg-pubkey-2fa658e0-45700c69",
+ "gpg-pubkey-d4082792-5b32db75",
+ "gpg-pubkey-5a6340b3-6229229e",
+ "gpg-pubkey-db42a60e-37ea5438",
+ ],
+ ),
+ ],
+)
+def test_get_source_distro_keys(monkeypatch, distro, expected):
+ """
+ Test that the correct keys are returned for each distro.
+ """
+ monkeypatch.setattr(api, "current_actor", CurrentActorMocked(src_distro=distro))
+ monkeypatch.setattr(api, "get_common_folder_path", common_folder_path_mocked)
monkeypatch.setattr(
- api,
- "current_actor",
- CurrentActorMocked(),
+ removeobsoleterpmgpgkeys, "_is_key_installed", lambda _key: True
)
- keys = removeobsoleterpmgpgkeys._get_obsolete_keys()
+ keys = removeobsoleterpmgpgkeys._get_source_distro_keys()
assert set(keys) == set(expected)
@@ -134,16 +169,61 @@ def test_get_obsolete_keys_incomplete_data(monkeypatch, version, obsoleted_keys,
]
)
def test_workaround_should_register(monkeypatch, keys, should_register):
- def get_obsolete_keys_mocked():
- return keys
-
monkeypatch.setattr(
- removeobsoleterpmgpgkeys,
- '_get_obsolete_keys',
- get_obsolete_keys_mocked
+ removeobsoleterpmgpgkeys, "_get_obsolete_keys", lambda: keys
)
- monkeypatch.setattr(api, 'produce', produce_mocked())
+ monkeypatch.setattr(api, "produce", produce_mocked())
monkeypatch.setattr(api, "current_actor", CurrentActorMocked())
removeobsoleterpmgpgkeys.process()
assert api.produce.called == should_register
+
+
+def test_process(monkeypatch):
+ """
+ Test that the correct path is taken depending on whether also converting
+ """
+ obsolete = ["gpg-pubkey-12345678-abcdefgh"]
+ source_distro = ["gpg-pubkey-87654321-hgfedcba"]
+
+ monkeypatch.setattr(
+ removeobsoleterpmgpgkeys, "_get_obsolete_keys", lambda: obsolete
+ )
+ monkeypatch.setattr(
+ removeobsoleterpmgpgkeys, "_get_source_distro_keys", lambda: source_distro,
+ )
+
+ # upgrade only path
+ monkeypatch.setattr(
+ api, "current_actor", CurrentActorMocked(src_distro="rhel", dst_distro="rhel")
+ )
+ with mock.patch(
+ "leapp.libraries.actor.removeobsoleterpmgpgkeys.register_dnfworkaround"
+ ):
+ removeobsoleterpmgpgkeys.process()
+ removeobsoleterpmgpgkeys.register_dnfworkaround.assert_called_once_with(
+ obsolete
+ )
+
+ # upgrade + conversion paths
+ monkeypatch.setattr(
+ api, "current_actor", CurrentActorMocked(src_distro="rhel", dst_distro="centos")
+ )
+ with mock.patch(
+ "leapp.libraries.actor.removeobsoleterpmgpgkeys.register_dnfworkaround"
+ ):
+ removeobsoleterpmgpgkeys.process()
+ removeobsoleterpmgpgkeys.register_dnfworkaround.assert_called_once_with(
+ source_distro
+ )
+
+ monkeypatch.setattr(
+ api, "current_actor", CurrentActorMocked(src_distro="centos", dst_distro="rhel")
+ )
+ with mock.patch(
+ "leapp.libraries.actor.removeobsoleterpmgpgkeys.register_dnfworkaround"
+ ):
+ removeobsoleterpmgpgkeys.process()
+ removeobsoleterpmgpgkeys.register_dnfworkaround.assert_called_once_with(
+ source_distro
+ )
diff --git a/repos/system_upgrade/common/files/distro/almalinux/gpg-signatures.json b/repos/system_upgrade/common/files/distro/almalinux/gpg-signatures.json
index 18b6c516..b17e8a66 100644
--- a/repos/system_upgrade/common/files/distro/almalinux/gpg-signatures.json
+++ b/repos/system_upgrade/common/files/distro/almalinux/gpg-signatures.json
@@ -1,10 +1,10 @@
{
- "keys": [
- "51d6647ec21ad6ea",
- "d36cb86cb86b3716",
- "2ae81e8aced7258b",
- "429785e181b961a5"
- ],
+ "keys": {
+ "51d6647ec21ad6ea": ["gpg-pubkey-3abb34f8-5ffd890e"],
+ "d36cb86cb86b3716": ["gpg-pubkey-ced7258b-6525146f"],
+ "2ae81e8aced7258b": ["gpg-pubkey-b86b3716-61e69f29"],
+ "429785e181b961a5": ["gpg-pubkey-81b961a5-64106f70"]
+ },
"obsoleted-keys": {
"7": [],
"8": [],
diff --git a/repos/system_upgrade/common/files/distro/centos/gpg-signatures.json b/repos/system_upgrade/common/files/distro/centos/gpg-signatures.json
index 1be56176..1092ff58 100644
--- a/repos/system_upgrade/common/files/distro/centos/gpg-signatures.json
+++ b/repos/system_upgrade/common/files/distro/centos/gpg-signatures.json
@@ -1,10 +1,10 @@
{
- "keys": [
- "24c6a8a7f4a80eb5",
- "4eb84e71f2ee9d55",
- "05b555b38483c65d",
- "1ff6a2171d997668"
- ],
+ "keys": {
+ "24c6a8a7f4a80eb5": [],
+ "4eb84e71f2ee9d55": [],
+ "05b555b38483c65d": ["gpg-pubkey-8483c65d-5ccc5b19"],
+ "1ff6a2171d997668": ["gpg-pubkey-1d997668-621e3cac", "gpg-pubkey-1d997668-61bae63b"]
+ },
"obsoleted-keys": {
"10": ["gpg-pubkey-8483c65d-5ccc5b19"]
}
diff --git a/repos/system_upgrade/common/files/distro/rhel/gpg-signatures.json b/repos/system_upgrade/common/files/distro/rhel/gpg-signatures.json
index 5b27e197..d6c2328d 100644
--- a/repos/system_upgrade/common/files/distro/rhel/gpg-signatures.json
+++ b/repos/system_upgrade/common/files/distro/rhel/gpg-signatures.json
@@ -1,14 +1,14 @@
{
- "keys": [
- "199e2f91fd431d51",
- "5326810137017186",
- "938a80caf21541eb",
- "fd372689897da07a",
- "45689c882fa658e0",
- "f76f66c3d4082792",
- "5054e4a45a6340b3",
- "219180cddb42a60e"
- ],
+ "keys": {
+ "199e2f91fd431d51": ["gpg-pubkey-fd431d51-4ae0493b"],
+ "5326810137017186": ["gpg-pubkey-37017186-45761324"],
+ "938a80caf21541eb": ["gpg-pubkey-f21541eb-4a5233e8"],
+ "fd372689897da07a": ["gpg-pubkey-897da07a-3c979a7f"],
+ "45689c882fa658e0": ["gpg-pubkey-2fa658e0-45700c69"],
+ "f76f66c3d4082792": ["gpg-pubkey-d4082792-5b32db75"],
+ "5054e4a45a6340b3": ["gpg-pubkey-5a6340b3-6229229e"],
+ "219180cddb42a60e": ["gpg-pubkey-db42a60e-37ea5438"]
+ },
"obsoleted-keys": {
"7": [],
"8": [
--
2.52.0