From 15eb0d93c48a98cf748eeb45dec6f9f969f394f9 Mon Sep 17 00:00:00 2001 From: Martin Vrachev Date: Tue, 1 Jun 2021 17:10:06 +0300 Subject: [PATCH 1/2] Remove question about version validation place In issue #1418 in this comment: https://github.com/theupdateframework/tuf/issues/1418#issuecomment-852147689 I summarized the discussion we had with the participants in this issue. In summary: no additional changes are needed for "version" validation considering there is "bump_version()" function for that. If we won't be adding "version" validation elsewhere we can keep it the way it is. Signed-off-by: Martin Vrachev --- tuf/api/metadata.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tuf/api/metadata.py b/tuf/api/metadata.py index 5f6a210e45..12d294c9f3 100644 --- a/tuf/api/metadata.py +++ b/tuf/api/metadata.py @@ -293,7 +293,6 @@ def __init__( self.spec_version = spec_version self.expires = expires - # TODO: Should we separate data validation from constructor? if version <= 0: raise ValueError(f"version must be > 0, got {version}") self.version = version From 41afb1e1342d5f8870180ba1ecea8894c03aec24 Mon Sep 17 00:00:00 2001 From: Martin Vrachev Date: Tue, 8 Jun 2021 15:37:00 +0300 Subject: [PATCH 2/2] Validate spec_version during initialization According to point 2 in the semver specification: "A normal version number MUST take the form X.Y.Z where X, Y, and Z are non-negative integers...". See: https://semver.org/#spec-item-2 Also, even though version strings like "2.0.0-rc.2" or "1.0.0-beta" are valid strings in semantic versioning format, in TUF we never needed to add letters for our specification number. That's why I validate that: spec_version is a . separated string and when split it has a length of 3 and that each of the three elements is a number. The modules under the tuf/api folder in TUF are an alternative TUF implementation. That's why they should use their own constant for SPECIFICATION_VERSION in tuf/metadata/api. This time, I used a list for the SPECIFICATION_VERSION constant in order to retrieve major and minor versions easier. I use the SPECIFICATION_VERSION to check that the given spec_version is supported against the tuf code spec version. Signed-off-by: Martin Vrachev --- tuf/api/metadata.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tuf/api/metadata.py b/tuf/api/metadata.py index 12d294c9f3..49e6db4b28 100644 --- a/tuf/api/metadata.py +++ b/tuf/api/metadata.py @@ -37,6 +37,10 @@ # and currently, we are above 1000 lines by a small margin. # pylint: disable=C0302 +# We aim to support SPECIFICATION_VERSION and require the input metadata +# files to have the same major version (the first number) as ours. +SPECIFICATION_VERSION = ["1", "0", "19"] + class Metadata: """A container for signed TUF metadata. @@ -290,6 +294,16 @@ def __init__( expires: datetime, unrecognized_fields: Optional[Mapping[str, Any]] = None, ) -> None: + spec_list = spec_version.split(".") + if ( + len(spec_list) != 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)}" + ) self.spec_version = spec_version self.expires = expires