From b0e9579d2f0aa58a2c057a420f1f980f010c1425 Mon Sep 17 00:00:00 2001 From: Lukas Puehringer Date: Thu, 9 Feb 2023 12:04:50 +0100 Subject: [PATCH] Remove obsolete gpg version utils The gpg utility functions `is_version_fully_supported` and `get_version` were used in in-toto tests to case-handle different gpg versions. With in-toto/in-toto#190 this is no longer needed. See in-toto/in-toto@28ba993, in-toto/in-toto@c3a40b8. To reduce the API surface and maintenance burden this commit removes those functions. Signed-off-by: Lukas Puehringer --- securesystemslib/gpg/util.py | 108 +-------------------------- tests/check_public_interfaces_gpg.py | 5 -- tests/test_gpg.py | 45 +---------- 3 files changed, 2 insertions(+), 156 deletions(-) diff --git a/securesystemslib/gpg/util.py b/securesystemslib/gpg/util.py index 8ae712ec..3b59d358 100644 --- a/securesystemslib/gpg/util.py +++ b/securesystemslib/gpg/util.py @@ -15,9 +15,7 @@ general-purpose utilities for binary data handling and pgp data parsing """ import binascii -import dataclasses import logging -import re import struct CRYPTO = True @@ -29,7 +27,7 @@ CRYPTO = False # pylint: disable=wrong-import-position -from securesystemslib import exceptions, process +from securesystemslib import exceptions from securesystemslib.gpg import constants from securesystemslib.gpg.exceptions import PacketParsingError @@ -308,110 +306,6 @@ def parse_subpackets(data): return parsed_subpackets -@dataclasses.dataclass(order=True) -class Version: - """A version of GPG.""" - - major: int - minor: int - patch: int - - VERSION_RE = re.compile(r"(\d)\.(\d)\.(\d+)") - EXAMPLE = "1.3.22" - - @classmethod - def from_string(cls, value: str) -> "Version": - """ - - Parses `value` as a `Version`. - - Expects a version in the format `major.minor.patch`. `major` and `minor` - must be one-digit numbers; `patch` can be any integer. - - - value: - The version string to parse. - - - ValueError: - If the version string is invalid. - - - Version - """ - match = cls.VERSION_RE.fullmatch(value) - if not match: - raise ValueError( - f"Invalid version number '{value}'; " - f"expected MAJOR.MINOR.PATCH (e.g., '{cls.EXAMPLE}')" - ) - major, minor, patch = map(int, match.groups()) - return cls(major, minor, patch) - - def __str__(self): - return f"{self.major}.{self.minor}.{self.patch}" - - -def get_version() -> Version: - """ - - Uses `gpg2 --version` to get the version info of the installed gpg2 - and extracts and returns the version number. - - The executed base command is defined in constants.gpg_version_command. - - - securesystemslib.exceptions.UnsupportedLibraryError: - If the gpg command is not available - - - Executes a command: constants.gpg_version_command. - - - Version of GPG. - - """ - if not constants.have_gpg(): # pragma: no cover - raise exceptions.UnsupportedLibraryError(constants.NO_GPG_MSG) - - command = constants.gpg_version_command() - gpg_process = process.run( - command, - stdout=process.PIPE, - stderr=process.PIPE, - universal_newlines=True, - ) - - full_version_info = gpg_process.stdout - try: - match = Version.VERSION_RE.search(full_version_info) - if not match: - raise ValueError( - f"Couldn't find version number (ex. '{Version.EXAMPLE}') " - f"in the output of `{command}`:\n" + full_version_info - ) - version = Version.from_string(match.group(0)) - except ValueError as err: - raise exceptions.UnsupportedLibraryError(constants.NO_GPG_MSG) from err - - return version - - -def is_version_fully_supported(): - """ - - Compares the version of installed gpg2 with the minimal fully supported - gpg2 version (2.1.0). - - - True if the version returned by `get_version` is greater-equal - constants.FULLY_SUPPORTED_MIN_VERSION, False otherwise. - - """ - min_version = constants.FULLY_SUPPORTED_MIN_VERSION - return get_version() >= Version.from_string(min_version) - - def get_hashing_class(hash_algorithm_id): """ diff --git a/tests/check_public_interfaces_gpg.py b/tests/check_public_interfaces_gpg.py index 4fc81809..3ed236e9 100644 --- a/tests/check_public_interfaces_gpg.py +++ b/tests/check_public_interfaces_gpg.py @@ -34,7 +34,6 @@ export_pubkeys, verify_signature, ) -from securesystemslib.gpg.util import get_version class TestPublicInterfacesGPG( @@ -60,10 +59,6 @@ def test_gpg_functions(self): export_pubkeys(["f00"]) self.assertEqual(NO_GPG_MSG, str(ctx.exception)) - with self.assertRaises(UnsupportedLibraryError) as ctx: - get_version() - self.assertEqual(NO_GPG_MSG, str(ctx.exception)) - def test_gpg_verify(self): """Signature verification does not require gpg to be installed on the host. To prove it, we run basic verification tests for rsa, dsa and eddsa with diff --git a/tests/test_gpg.py b/tests/test_gpg.py index f4ddbfd0..a65919d1 100644 --- a/tests/test_gpg.py +++ b/tests/test_gpg.py @@ -33,7 +33,7 @@ from cryptography.hazmat import backends from cryptography.hazmat.primitives import serialization -from securesystemslib import exceptions, process +from securesystemslib import process from securesystemslib.formats import ANY_PUBKEY_DICT_SCHEMA, GPG_PUBKEY_SCHEMA from securesystemslib.gpg.common import ( _assign_certified_key_info, @@ -72,10 +72,7 @@ ) from securesystemslib.gpg.rsa import create_pubkey as rsa_create_pubkey from securesystemslib.gpg.util import ( - Version, get_hashing_class, - get_version, - is_version_fully_supported, parse_packet_header, parse_subpacket_header, ) @@ -100,19 +97,6 @@ def ignore_not_found_error( class TestUtil(unittest.TestCase): """Test util functions.""" - def test_version_utils_return_types(self): - """Run dummy tests for coverage.""" - self.assertTrue(isinstance(get_version(), Version)) - self.assertTrue(isinstance(is_version_fully_supported(), bool)) - - def test_version_utils_error(self): - """Run dummy tests for coverage.""" - with patch( - "securesystemslib.gpg.constants.have_gpg", return_value=False - ): - with self.assertRaises(exceptions.UnsupportedLibraryError): - get_version() - def test_get_hashing_class(self): # Assert return expected hashing class expected_hashing_class = [hashing.SHA1, hashing.SHA256, hashing.SHA512] @@ -947,32 +931,5 @@ def test_verify_short_signature(self): self.assertTrue(verify_signature(signature, key, test_data)) -class TestVersion(unittest.TestCase): - """Tests for the Version utility class.""" - - def test_version_roundtrip_string(self): - """Version parses and formats strings correctly.""" - for value, expected in [ - ("1.3.0", Version(1, 3, 0)), - ("1.3.1", Version(1, 3, 1)), - ("1.3.22", Version(1, 3, 22)), - ]: - self.assertEqual(Version.from_string(value), expected) - self.assertEqual(str(expected), value) - - def test_version_from_string_invalid(self): - """Version.from_string rejects invalid inputs.""" - for value in [ - "1.3", - "1.33.0", - "1.3.-1", - "1.3.1a", - ]: - with self.assertRaises( - ValueError, msg=f"expected error for input '{value}'" - ): - Version.from_string(value) - - if __name__ == "__main__": unittest.main()