Commit graph

259 commits

Author SHA1 Message Date
Martin Vrachev
5fd3ddccbc ngclient: pick old timestamp if new.ver is equal
In the spec version 1.0.30, a new change has been added considering what
should happen if there is a new timestamp with the same version.
It says the following:
"In case they [versions] are equal, discard the new
timestamp metadata and abort the update cycle.
This is normal and it shouldn't raise any error."

In other words, if there is a new timestamp with the same version, then
stop the update process and use the old timestamp.

Those changes reflect these latest specification modifications.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-06-21 14:52:31 +03:00
Martin Vrachev
28b6917739 Root and Targets key API changes
Here is the list of all breaking API changes:
1) The "role" and "key" arguments in "Root.add_key()" are in reverse
order - "key" becomes first and "role" second.
2) "Root.remove_key()" has been renamed to "Root.revoke_key()".
3) The "role" and "keyid" arguments in "Root.revoke_key()" are in
reverse order - "keyid" becomes first and "role" second.
4) The "role" and "key" arguments in "Targets.add_key()" are in reverse
order - "key" becomes first and "role" second.
5) "Targets.remove_key()" has been renamed to "Targets.revoke_key()".
6) The "role" and "keyid" arguments in "Targets.revoke_key()" are in
reverse order - "keyid" becomes first and "role" second.
7) In both methods "Targets.add_key()" and "Targets.revoke_key()" the
"role" argument becomes an optional with a default value of None.

Those changes are made in an effort to make those methods logical
for both cases when standard roles and succinct_roles are used.
The "Root" API change was done in order to preserve naming and argument
order consistency with "Targets" API.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-06-17 13:33:01 +03:00
Martin Vrachev
15cd42c0d6 Delegations: add support for succinct_roles
This commit contains 2 API changes in "Delegations" class from
tuf/api/metadata.py:
1. roles argment is made optional
2. unrecognized_fields argument becomes the 4-th rather than the 3-rd
as it used to be

In this commit, I add support for succinct_roles roles inside
Delegations class. This change is related to TAP 15 proposal.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-06-17 13:33:01 +03:00
Martin Vrachev
f80b4ca1d2 Clarifications and simplifications
Clarify explicitly that exactly one of "paths" and "path_hash_prefixes"
must be set inside DelegatedRole.
Also simplify the check for "paths" and "path_hash_prefixes".
Finally, add a test case inside the "test_metadata_serialization.py"
test file about wrong keyids type for "Role" serialization.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-06-17 13:33:01 +03:00
Martin Vrachev
0a92cb91e3 Add helper methods in SuccinctRoles
Add two helper methods in SuccinctRoles.
Those methods proved useful in the testing code, but I believe they have
a potential value for production code as well.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-06-17 13:33:00 +03:00
Martin Vrachev
d8808fbdcc SuccinctRoles: add zero padding to bins
Add zero padding to bin names inside SuccinctRoles.
Zero padding ensures that the bin names always have the same length.

This characteristic is implied in the example given by TAP 15 where
the third bin is named "alice.hbd-03". For context read TAP 15:
https://github.com/theupdateframework/taps/blob/master/tap15.md

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-06-14 18:26:08 +03:00
Martin Vrachev
9259ced68a Add SuccinctRole class
Add SuccinctRoles class containing the information from the
succint_roles dict described in TAP 15.
This allows for easy mypy checks on the types, easy enforcement on
TAP 15 restrictions (as for example that "bit_length" must be between 1
and 32) and support for unrecognized fields inside succinct_roles
without much of a hassle.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-06-09 20:30:30 +03:00
Abhisman Sarkar
79d924a4df Metadata API: Checking for None instead of falsyness
Fixes #1937

Initialization of unrecognized_fields acts surprisingly when the input
container is empty. Hence, We're checking for None instead of falsyness.

Signed-off-by: Abhisman Sarkar <abhisman.sarkar@gmail.com>
2022-04-29 22:39:48 +05:30
Marina Moore
9c5c5f7a73 Update supported spec version
Signed-off-by: Marina Moore <mnm678@gmail.com>
2022-04-19 10:22:43 -04:00
Abhisman Sarkar
944a540f97 Metadata API: Annotate 'unrecognized_fields' as Dict
Fixes #1938

Description of the changes being introduced by the pull request:

Annotating as Mapping seems wrong as further changes to the content might
be added in the code base. Hence, annotation changed to Dict.

Signed-off-by: Abhisman Sarkar <abhisman.sarkar@gmail.com>
2022-04-12 22:25:33 +05:30
Jussi Kukkonen
0d3bb682dd Metadata API: Document constructor default arguments
Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2022-04-04 13:49:06 +03:00
Jussi Kukkonen
96b2cd46b5 Metadata API: Set default expires to utcnow()
This means the metadata is by default expired: this seems like a fine
default since we only allow a default value for practical reasons (not
allowing it would mean backwards incompatible API change).

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2022-03-24 15:43:06 +02:00
Jussi Kukkonen
d8c0f3b3f3 Metadata API: Be more careful with container args
If argument is an empty container, we want to use the given empty
container. Only create a new container if argument is None.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2022-03-24 15:38:53 +02:00
Jussi Kukkonen
d2f8c99c19 Metadata API: Add default constructor arguments
This allows creating new metadata with less boilerplate:
    root = Metadata(Root())
    targets = Metadata(Targets())

Set reasonable default values for all the arguments -- version to
1, spec_version to current supported version, etc.

Expires does not have a good default value and my original plan was
to require expires argument to be set. That would mean an
incompatible API change though as arguments before expires would be
now optional... So expires now defaults to an arbitrary value of 1
day from moment of creation.

One noteworthy special case is consistent_snapshot where the default
value is True (since that's what we want people to use for new
metadata) but None is also used to imply that metadata does not contain
the field at all.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2022-03-23 17:25:40 +02:00
Jussi Kukkonen
1d166f0b4e
Merge pull request #1876 from jku/more-details-on-verify-failure
Logging and error message improvements
2022-03-21 14:21:44 +02:00
Ivana Atanasova
e71aa4a7d7 Improve Signer docstrings in Metadata API
Change to @lukpueh proposal with more clarification on why and how
the `securesystemslib.signer.Signer` interface is used

Co-authored-by: Lukas Pühringer <luk.puehringer@gmail.com>

Signed-off-by: Ivana Atanasova <iyovcheva@vmware.com>
2022-03-18 18:32:25 +02:00
Ivana Atanasova
db7fbb21fa Improve docstrings in Metadata API to be more descritpive
This change updates some parts of the Metadata API docstrings
that did not give enough details and context

Fixes #1600

Signed-off-by: Ivana Atanasova <iyovcheva@vmware.com>
2022-03-18 18:32:25 +02:00
Martin Vrachev
6ea5372edb Take order into account for certain cases
After we have dropped OrderedDict in e3b267e2e0
we are relying on python3.7+ default behavior to preserve the insertion
order, but there is one caveat.
When comparing dictionaries the order is still irrelevant compared to
OrderedDict. For example:
>>> OrderedDict([(1,1), (2,2)]) == OrderedDict([(2,2), (1,1)])
False
>>> dict([(1,1), (2,2)]) == dict([(2,2), (1,1)])
True

There are two special attributes, defined in the specification, where
the order makes a difference when comparing two objects:
- Metadata.signatures
- Targets.delegations.roles.
We want to make sure that the order in those two cases makes a
difference when comparing two objects and that's why those changes
are required inside two __eq__ implementations.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-02-28 14:42:06 +02:00
Martin Vrachev
a17ceda4e5 Add "validation" arg in JSONSerializer
If the "validation" argument is set then when
serializing the metadata object will be validated.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-02-28 14:42:06 +02:00
Martin Vrachev
30a707c297 Add __eq__ to classes in Metadata API
By adding __eq__ we can compare that two objects are equal.
That will be useful when adding validation API call.

One bug I have found during testing is that I don't check if the type
of "other" in the __eq__ implementations are the expected ones.
I assumed that when comparing "root == obj" if "obj" is None that
automatically the result will be false.
Later after a mypy warning, I realized we should implement the __eq__
methods to accept "Any" type as other and we should check manually
that "other" is the expected type.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-02-28 14:42:04 +02:00
Jussi Kukkonen
fc1558bfd4 Metadata API: Log details of verify error
We don't want to error out from the whole verify_delegate() process if
e.g. a single key fails to load but we do want to provide details for
debugging in the unexpected failure cases.

This means "example_client -vv  download file1.txt" fails like this:

    Found trusted root in /home/jku/.local/share/python-tuf-client-example
    INFO:tuf.api.metadata:Key
4e777de0d275f9d28588dd9a1606cc748e548f9e22b6795b7cb3f63f98035fcb failed
to verify sig: Failed to load PEM key bogus-key-content-here
    INFO:tuf.api.metadata:Key 4e777de0d275f9d28588dd9a1606cc748e548f9e22b6795b7cb3f63f98035fcb failed to verify root
    Failed to download target x: root was signed by 0/1 keys

Fixes #1875

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2022-02-21 16:35:49 +02:00
Jussi Kukkonen
d4814e86d8 Metadata API: Add messages to serialization errors
We can't really add any details but this at least means
printing the error works.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2022-02-21 16:04:55 +02:00
Martin Vrachev
922c5d28e5 Add support for unrecognized fields in Metadata
The Document formats section (chapter 4) of the
specification says the following:

"All of the formats described below include the ability to add more
attribute-value fields to objects for backward-compatible format
changes. Implementers who encounter undefined attribute-value pairs in
the format must include the data when calculating hashes or verifying
signatures and must preserve the data when re-serializing."

I initially thought it's applicable only to the SIGNED fields as
"undefined attribute-value pairs in the format must include the data
when calculating hashes or verifying signatures"
This doesn't mean that the sentence before that excludes "Metadata" as a
possible place for additional fields.
The other maintainers agreed with me and we are going to add support for
'unrecognized_fields" inside "Metadata".

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-02-14 12:12:54 +02:00
Lukas Pühringer
d4dd652582
Merge pull request #1836 from MVrachev/verify-sig-serialization-error
verify_signature(): handle SerializationError
2022-02-08 14:52:35 +01:00
Lukas Pühringer
177976a890
Merge pull request #1840 from MVrachev/from-securesystemslib-key-sslib-error
Key.from_securesystemslib_key() raise ValueError
2022-02-08 12:49:47 +01:00
Martin Vrachev
8b6566ab3b from_securesystemslib_key() raise ValueError
If a securesystemslib.FormatError is raised inside
Key.from_securesystemslib_key() then reraise ValueError.
This is done so that our users don't have to import securesystemslib
in order to handle the error and because the securesystemslib error
itself is securesystemslib implementation-specific.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-02-08 13:44:12 +02:00
Martin Vrachev
5f515791df verify_delegate() doc ValueError and TypeError
Add missing documentation for ValueError and TypeError inside
Metadata.verify_delegate().

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-02-08 13:10:46 +02:00
Ivana Atanasova
9169fcb575 Update repetitive docstrings language in Metadata API
This change updates some obvious and unnecessary fields docs in the
Metadata API with more despriptive details

Signed-off-by: Ivana Atanasova <iyovcheva@vmware.com>
2022-02-08 12:43:11 +02:00
Ivana Atanasova
acf3df67ff Improve docstrings language in Metadata API - article
This change unifies as mush as the context allows and improves the
use of definite vs. indefinite vs. no article across docs in the
Metadata API. It sticks to no article in most cases for simplisity
and readability, but leaves definite article where it's strictly
necessary

Signed-off-by: Ivana Atanasova <iyovcheva@vmware.com>
2022-02-08 12:39:33 +02:00
Ivana Atanasova
40aef7ee23 Improve docstrings language in Metadata API - wording
This change unifies wording across docs in the Metadata API, like
Args vs. Arguments and same repetitive descriptions written
differently in different classes/methods

Signed-off-by: Ivana Atanasova <iyovcheva@vmware.com>
2022-02-08 12:37:23 +02:00
Ivana Atanasova
0feec0c5f5 Improve docstrings language in Metadata API - quotes
This change unifies quotes to double backtick across docs in the
Metadata API in order to provide better visualisation

Signed-off-by: Ivana Atanasova <iyovcheva@vmware.com>
2022-02-08 12:37:19 +02:00
Lukas Pühringer
9cda6e591f
Merge pull request #1796 from jku/accept-two-part-spec-version
Metadata API: Accept X.Y spec_version
2022-02-08 11:29:57 +01:00
Martin Vrachev
2f381aee9a verify_signature(): handle SerializationError
We should handle the possible SerializationError inside
Key.verify_signature(), because the user of this API is not interested
in SerializationError when he is trying to verify his signature.

Note that the SerializationError can be thrown when calling
signed_serializer.serialize() on the metadata signed part.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-02-08 12:18:55 +02:00
Lukas Pühringer
0b2f98585c
Merge pull request #1820 from MVrachev/constructors-documentation
Add exceptions docs for __init__ and from_dict()
2022-02-08 10:21:18 +01:00
Jussi Kukkonen
ba911e07b2
Merge pull request #1825 from MVrachev/specification-version
Update supported specification version to 1.0.28
2022-02-07 16:44:26 +02:00
Martin Vrachev
5b2290cf42 Exceptions docs for __init__ and from_dict()
Document ValueError, KeyError and TypeError exceptions for __init__ and
from_dict() methods in Metadata API.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-02-07 15:19:03 +02:00
Lukas Pühringer
70c7358040
Merge pull request #1800 from jku/document-serialization-hash-issue
Metadata API: Document serialization "repro" issue
2022-02-07 11:28:02 +01:00
Jussi Kukkonen
3f3b921337 Metadata API: Document serialization "repro" issue
It's not obvious to casual reader that reading metadata and then
writing it might not always produce the same file. It's also not
immediately obvious why this matters.

Document both concepts.

Fixes #1392

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2022-02-06 18:06:11 +02:00
Martin Vrachev
99a4d71b72 Update supported specification version to 1.0.28
I looked into all changes between our current version 1.0.19 and the
current version of the specification 1.0.28 and I agree with Jussi that
the only one not fully resolved is:
"8dafd00 (tag: v1.0.24) Clarify optional attributes" and more precisely
the changes from commit:
4dd279bc31

It doesn't make sense to have a target file without "paths" or
"path_hash_prefixes", so our `python-tuf requirement to have at least
one of them set makes sense.

Both with Jussi we agreed that we can easily loosen this requirement if
when solving https://github.com/theupdateframework/specification/issues/200
it's decided that both of them can be omitted,
but for now, we decided it's better to stick to our current requirement
to have one of them set.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-02-04 15:38:34 +02:00
Jussi Kukkonen
17f2ddff02 exceptions: rename FetcherHTTPError
I've not supported many renames but I'm suggesting this one:
FetcherHTTPError was created because we needed to signal 403/404
from the fetcher to updater. At that time the download error hierarchy
in general was not thought out.

Now we have a couple of different errors all derived from
DownloadError. I believe it does not make sense to point out "Fetcher"
in one of their names: DownloadHTTPError makes it clearer this is a
specific type of DownloadError.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2022-02-04 11:03:12 +02:00
lukpueh
f0043eea61
Merge pull request #1794 from jku/remove-todos
Remove TODOs about too-many-arguments
2022-02-03 10:48:48 +01:00
Martin Vrachev
896e552fd7 sign sslib.exceptions -> UnsignedMetadataError
Catch Metadata.sign() securesystemslib exceptions and instead throw
a more general UnsignedMetadataError exception.
We don't want to expose securesystemslib exceptions and it's better
to replace them with a more general exception that could be easily
handled.

As the signer is an argument implementing securesystemslib.signer.Signer
interface we don't know what exception will it throw.
That's why we need to catch all possible exceptions during signing and
raise UnsignedMetadataError.
That is the same reason why we should move the serialization outside
the "try" block, so a tuf.api.serialization.SerializationError can
propagate and warn the user that 'signed' cannot be serialized.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-01-27 17:31:02 +02:00
Martin Vrachev
b5fbfed194 Reexport sslib StorageError and change docs
Reexport securesystemslib StorageError, so that our users can catch
it without importing securesystemslib.
The securesystemslib StorageError makes sense in the context of
metadata API, because it supports different storage interfaces and
this exception is denoting all possible errors that could arrise
from using any kind of storage interface.

Additionally, I changed the places where we mention that StorageError
is thrown, so that our users will know they can directly import it
from tuf/api/exceptions.py instead of importing securesystemslib.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-01-27 17:05:57 +02:00
Jussi Kukkonen
572084e2db Metadata API: Accept X.Y spec_version
All TUF implementations used to use "1.0" as the spec version and most
of them have never modified that value since.

Accept two-part spec_version for legacy compatibility: it is strictly
speaking against the current spec (which requires semver) but there
should be no harm in doing this and it allows us to deserialize
metadata generated by e.g. go-tuf.

Fixes #1751

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2022-01-26 15:34:38 +02:00
Jussi Kukkonen
08432961ea Remove TODOs about too-many-arguments
The lint warning about argument count is useful in general but in these
two cases we want to break the rule: remove TODOs.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2022-01-25 14:17:03 +02:00
lukpueh
b2704a56a8
Merge pull request #1783 from MVrachev/drop-python3.6
Drop python3.6 and remove the usage of OrderedDict
2022-01-20 14:46:52 +01:00
Martin Vrachev
e3b267e2e0 Remove OrderedDict in favor of python3.7+ dict
After we drop support for python3.6 we can relly that dictionaries
preserve the insertion order:
https://docs.python.org/3.7/whatsnew/3.7.html

This means we can replace the usage of OrderedDict with a standard
dictionaries.

Something we have to keep in mind is that even thought the insertion
order is preserved the equality comparison for normal dicts is
insensitive for normal dicts compared to OrderedDict

For example:
>>> OrderedDict([(1,1), (2,2)]) == OrderedDict([(2,2), (1,1)])
False
>>> dict([(1,1), (2,2)]) == dict([(2,2), (1,1)])
True

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-01-19 18:19:56 +02:00
Martin Vrachev
8327ea12d3 Make (De)SerializationError a RepositoryError
SerializationError and DeserializationError are both errors coming
from the repository side looking from the clients point of view.
That's why it makes sense to make them repository errors.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-01-19 16:52:19 +02:00
Martin Vrachev
8fbe24b487 Fix typo
Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-01-19 16:52:19 +02:00
Martin Vrachev
199b91df3c Clarify what RepositoryError stands for
Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2022-01-19 16:52:19 +02:00