diff --git a/tests/test_metadata_serialization.py b/tests/test_metadata_serialization.py index 3714eec00c..f116d33326 100644 --- a/tests/test_metadata_serialization.py +++ b/tests/test_metadata_serialization.py @@ -44,8 +44,8 @@ class TestSerialization(unittest.TestCase): "_type wrong type": '{"_type": "foo", "spec_version": "1.0.0", "version": 1, "expires": "2030-01-01T00:00:00Z", "meta": {}}', "version wrong type": '{"_type": "signed", "spec_version": "1.0.0", "version": "a", "expires": "2030-01-01T00:00:00Z", "meta": {}}', "invalid spec_version str": '{"_type": "signed", "spec_version": "abc", "version": 1, "expires": "2030-01-01T00:00:00Z", "meta": {}}', - "two digit spec_version": '{"_type": "signed", "spec_version": "1.2.a", "version": 1, "expires": "2030-01-01T00:00:00Z", "meta": {}}', - "no digit spec_version": '{"_type": "signed", "spec_version": "a.b.c", "version": 1, "expires": "2030-01-01T00:00:00Z", "meta": {}}', + "non-number spec_version": '{"_type": "signed", "spec_version": "1.2.a", "version": 1, "expires": "2030-01-01T00:00:00Z", "meta": {}}', + "one part spec_version": '{"_type": "signed", "spec_version": "1", "version": 1, "expires": "2030-01-01T00:00:00Z", "meta": {}}', "different major spec_version": '{"_type": "signed", "spec_version": "0.0.0", "version": 1, "expires": "2030-01-01T00:00:00Z", "meta": {}}', "version 0": '{"_type": "signed", "spec_version": "1.0.0", "version": 0, "expires": "2030-01-01T00:00:00Z", "meta": {}}', "version below 0": '{"_type": "signed", "spec_version": "1.0.0", "version": -1, "expires": "2030-01-01T00:00:00Z", "meta": {}}', @@ -254,6 +254,8 @@ def test_invalid_timestamp_serialization(self, test_case_data: str) -> None: valid_timestamps: utils.DataSet = { "all": '{ "_type": "timestamp", "spec_version": "1.0.0", "version": 1, "expires": "2030-01-01T00:00:00Z", \ "meta": {"snapshot.json": {"hashes": {"sha256" : "abc"}, "version": 1}}}', + "two part spec_version": '{ "_type": "timestamp", "spec_version": "1.9000", "version": 1, "expires": "2030-01-01T00:00:00Z", \ + "meta": {"snapshot.json": {"hashes": {"sha256" : "abc"}, "version": 1}}}', "unrecognized field": '{ "_type": "timestamp", "spec_version": "1.0.0", "version": 1, "expires": "2030-01-01T00:00:00Z", \ "meta": {"snapshot.json": {"hashes": {"sha256" : "abc"}, "version": 1}}, "foo": "bar"}', } diff --git a/tuf/api/metadata.py b/tuf/api/metadata.py index cd73985e8c..ce552fad83 100644 --- a/tuf/api/metadata.py +++ b/tuf/api/metadata.py @@ -431,16 +431,18 @@ def __init__( expires: datetime, unrecognized_fields: Optional[Mapping[str, Any]] = None, ): + # Accept semver (X.Y.Z) but also X.Y for legacy compatibility spec_list = spec_version.split(".") if ( - len(spec_list) != 3 + len(spec_list) not in [2, 3] or not all(el.isdigit() for el in spec_list) - or spec_list[0] != SPECIFICATION_VERSION[0] ): - raise ValueError( - f"Unsupported spec_version, got {spec_list}, " - f"supported {'.'.join(SPECIFICATION_VERSION)}" - ) + raise ValueError(f"Failed to parse spec_version {spec_version}") + + # major version must match + if spec_list[0] != SPECIFICATION_VERSION[0]: + raise ValueError(f"Unsupported spec_version {spec_version}") + self.spec_version = spec_version self.expires = expires