Commit graph

76 commits

Author SHA1 Message Date
Martin Vrachev
37de69050a Change "update()" argument types
Currently, when we call Targets/Snapshot/Timestamp.update() we are
passing all of the necessary values to create MetaFile/Targets File
respectively.
This is not needed, given that one of the reasons we have created
MetaFile and TargetFile is to make the API easier to use.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-05-19 13:21:32 +03:00
Martin Vrachev
aaa5bb4fc0 Disable "C0302" for tuf/api/metadata.py
Disable the "C0302: Too many lines in module" warning which warns for modules
with more 1000 lines, because all of the code here is logically connected
and currently, we are above 1000 lines by a small margin.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-05-19 13:21:32 +03:00
Martin Vrachev
60bbb165a8 New API: Add TargetFile class
In the top-level metadata classes, there are complex attributes such as
"meta" in Targets and Snapshot, "key" and "roles" in Root etc.
We want to represent those complex attributes with a class to allow
easier verification and support for metadata with unrecognized fields.
For more context read ADR 0004 and ADR 0008 in the docs/adr folder.

As written in the spec "targets" in "targets.json" has defined the
"custom" field serving the same purpose as "unrecognized_fields" in the
implementation.
That's why to conform against the spec and support "custom" and allow
"unrecognized_fields" everywhere where it's not sensitive we can define
custom as property which actually access data stored in
unrecognized_fields.
For context read ADR 8 in tuf/docs/adr.

Additionally, after adding the TargetFile class, when we create a
Targets an object we are now calling from dict twice - one for the main
Targets class and one for each of the complex attributes
TargetFile.from_dict() and Delegations.from_dict().
Given that the "from_dict" methods have the side effect of destroying
the given dictionary, we would need to start using deepcopy()
for our tests.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-05-19 13:21:31 +03:00
Martin Vrachev
3771a77ffe New API: Add MetaFile class
In the top-level metadata classes, there are complex attributes such as
"meta" in Targets and Snapshot, "key" and "roles" in Root etc.
We want to represent those complex attributes with a class to allow
easier verification and support for metadata with unrecognized fields.
For more context read ADR 0004 and ADR 0008 in the docs/adr folder.

Additionally, after adding the MetaFile class, when we create an object
we are now calling from dict twice - one for the main class (Timestamp,
Snapshot) and one for the pacticular complex attribute -
MetaFile.from_dict(). Given that the "from_dict" methods have the
side effect of destroying the given dictionary, we would need to
start using deepcopy() for our tests.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-05-19 13:04:24 +03:00
Jussi Kukkonen
8348523b77
Merge pull request #1394 from MVrachev/optional-consistent-snapshot
Metadata API: Make consistent_snapshot optional
2021-05-18 21:11:57 +03:00
Martin Vrachev
de2644f3d0 Breaking: new API: consistent_snapshot optional
NOTE: making consistent_snapshot optional requires using a default value
for the argument in __init__ in Root and thus consistent_snapshot should
be rearranged in the end.
Read more: https://github.com/theupdateframework/tuf/pull/1394#issuecomment-842134961

From chapter 7 in the spec (version 1.0.17)
"Finally, the root metadata should write the Boolean
"consistent_snapshot" attribute at the root level of its keys of
attributes.
If consistent snapshots are not written by the repository,
then the attribute may either be left unspecified or be set to the
False value. Otherwise, it must be set to the True value."

We want to make sure we support repositories
without consistent_snapshot set.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-05-17 11:41:52 +03:00
Jussi Kukkonen
14f5957eee Metadata API: Don't do equality comparisons on containers
Use either "if X is not None:" or a try-except instead of a "if X:".

I believe Targets.from_dict() was not really broken with previous code
but it looks suspicious and did fail the added test with a strange
exception: I expect the from_dict() methods to mainly fail with
KeyErrors, ValueErrors or AttributeErrors if file format structure
is incorrect.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-05-14 16:12:50 +03:00
Jussi Kukkonen
aa480b1280 Metadata API: Fix DelegatedRole serialization issue
A DelegatedRole with paths=[] fails to serialize correctly (paths is not
included in the output json).

Fix the issue, modify tests to notice a regression.

Fixes #1389

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-05-14 14:02:29 +03:00
Teodora Sechkova
167e1793d0 Fix Root.add_key() argument's type
After the implementation of a Key class representing
the public portion of a key, the method add_key() should
take an argument of type Key, instead of a dictionary.

Test cases are updated accordingly.

Signed-off-by: Teodora Sechkova <tsechkova@vmware.com>
2021-05-13 11:23:15 +03:00
Martin Vrachev
b2cde9bbbf Don't use Mapping for mutable dicts
Stop using Mapping where we actually mean Dict:
Mapping means "we only need a read-only dict" and most of the time
this is not really the case.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-05-11 16:04:25 +03:00
Martin Vrachev
f98f4f750a Add Delegation/DelegatednRole specific tests
Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-05-11 16:04:25 +03:00
Martin Vrachev
8e4d3b9a84 Add DelegatedRole and Delegations
In the top level metadata classes, there are complex attributes such as
"meta" in Targets and Snapshot, "key" and "roles" in Root etc.
We want to represent those complex attributes with a class to allow
easier verification and support for metadata with unrecognized fields.
For more context read ADR 0004 and ADR 0008 in the docs/adr folder.

DelegatedRole shares a couple of fields with the Role class and that's
why it inherits it.
I decided to use a separate Delegations class because I thought it will
make it easier to read, verify and add additional helper functions.
Also, I tried to make sure that I test each level of the delegations
representation for support of storing unrecognized fields.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-05-11 16:03:56 +03:00
Jussi Kukkonen
a261d49253
Merge pull request #1379 from jku/metadata-minor-fixes
Metadata minor fixes
2021-05-11 15:18:24 +03:00
Joshua Lock
d5deba2185
Merge pull request #1376 from jku/duplicate-type-property
Metadata API: Provide type as well as _type
2021-05-10 21:27:24 +01:00
Jussi Kukkonen
084df969a4 Metadata API: Fix type hints
* Define missing argument type hints
* Stop using Mapping where we actually mean Dict:
  Mapping means "we only need a read-only dict" and most of the
  time this is not really the case.
* Use List, not list (latter only works from Python 3.9)
* Update Metadata.signatures documentation

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-05-10 21:27:24 +03:00
Jussi Kukkonen
17121bad28 Metadata API: remove_key() improvements
We should not do multiple lookups through data structures if one is
enough (here we have extra lookups on both roles and keyids).

Also in this case raising on missing key seems like the preferable
alternative so even a try-except is not needed.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-05-10 17:02:12 +03:00
Martin Vrachev
139bfc0ea9 BREAKING CHANGE: Make delegations optional
According to the spec, delegations in targets are marked as optional:
https://theupdateframework.github.io/specification/latest/#file-formats-targets
and a pr, clarifying that even more, is approved:
https://github.com/theupdateframework/specification/pull/157.

This is a possible breaking change.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-05-10 15:27:37 +03:00
Martin Vrachev
0604f7026e NEW API: Fix documentation indentation
From the reST/sphinx docs:
https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#literal-blocks

I added new lines and an identation where it was missed.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-05-10 15:27:37 +03:00
Martin Vrachev
71c4992cea Make length and hashes optional in Timestamp
As per the specification (v1.0.1) length and hashes fields
in timestamp and snapshot metadata are optional.
We have implement this in the older API
(see https://github.com/theupdateframework/tuf/pull/1031) and we should
implement it in the new API.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-05-10 15:27:37 +03:00
Jussi Kukkonen
85971beaee Metadata API: Provide type as well as _type
Using Metadata APIs '_type' attribute (from outside metadata.py) currently
results in linter errors.

Add a duplicate 'type': this way the API users can avoid linter errors
but '_type' is still available in case the strict file format
compatibility is needed.

Fixes #1375

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-05-10 14:12:06 +03:00
Jussi Kukkonen
57bd9af7c2 API: Make _type read-only
Also remove _type from Signed constructor arguments: the value is in a
class atttribute. This way _type never needs to be validated (except
in the dispatcher in Metadata). There is a double-check in
_common_fields_from_dict() just to be sure.

This makes the API easier to use correctly as the public property is
immutable.

This is an API break as all Signed constructors change -- this could be
avoided but seems like the correct choice.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-05-04 09:36:53 +03:00
Martin Vrachev
1ce94b95cb keyid: verify adding an existing key is ignored
Verify that adding an already existing key to keyid for a particular
role in Root won't create duplicate key.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-04-29 12:26:40 +03:00
Martin Vrachev
0c9dc0ea36 Check the format of keyval in Root
Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-04-27 15:26:39 +03:00
Martin Vrachev
0c3131b4a2 Make keyids in Role a set
From the specification:
"Clients MUST ensure that for any KEYID represented in this key list
and in other files, only one unique key has that KEYID."

The “only one unique key has that KEYID” is a requirement which can’t
be achieved if two keyids are the same.
So, in order to mandate that requirement it makes sense to use a set
which will guarantee us the keyid’s uniqueness.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-04-27 15:26:13 +03:00
Martin Vrachev
ef71c2df76 Add from_dict methods in Key and Role classes
The from_dict() method simplifies the object creation.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-04-27 15:19:03 +03:00
Martin Vrachev
eab8c318f0 Add a Role class and integrate it into Root
In the top level metadata classes, there are complex attributes such as
"meta" in Targets and Snapshot, "key" and "roles" in Root etc.
We want to represent those complex attributes with a class to allow
easier verification and support for metadata with unrecognized fields.
For more context read ADR 0004 and ADR 0008 in the docs/adr folder.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-04-27 15:13:40 +03:00
Martin Vrachev
11e0a87bde Add Key class and integrate it into Root
In the top level metadata classes, there are complex attributes such as
"meta" in Targets and Snapshot, "key" and "roles" in Root etc.
We want to represent those complex attributes with a class to allow
easier verification and support for metadata with unrecognized fields.
For more context read ADR 0004 and ADR 0008 in the docs/adr folder.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-04-27 15:09:48 +03:00
Martin Vrachev
1712b71b55 Fix black docstring indentation errors
Black was updated from 20.8b1 to 21.4b0 requiring that one-line
docstring don't add additional space before the closing quotes.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-04-27 14:08:24 +03:00
Jussi Kukkonen
ec7173f03e
Merge pull request #1359 from sechkova/metadata-version
Fix api/metadata version check
2021-04-26 14:34:47 +03:00
Jussi Kukkonen
feb340f8da
Merge pull request #1345 from MVrachev/implement-adr-8
New metadata API: add support for ADR 0008
2021-04-22 21:54:32 +03:00
Martin Vrachev
79391f1d85 New API: accept metadata with unrecognized fields
In order to support ADR 0008 we would want to accept unrecognized
fields in all metadata classes.
Input that contains unknown fields in the 'signed' dictionary should
successfully deserialize into a Metadata object, and that object should
successfully serialize with the unknown fields intact.

Also, we should test that we support unrecognized fields when adding
new classes or modifying existing ones to make sure we support
ADR 0008.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-04-22 17:11:05 +03:00
Teodora Sechkova
92257a84c3
Fix metadata version check
VERSION is an integer that is greater than 0.

Signed-off-by: Teodora Sechkova <tsechkova@vmware.com>
2021-04-21 16:35:20 +03:00
Jussi Kukkonen
4e8738ffa5 api: Add Metadata.from_bytes()
This is essentially short-hand for
    JSONDeserializer().deserialize(data)
but seems much easier for the API user so may be worth it.

Metadata.from_file() now uses Metadata.from_bytes() internally.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-04-21 09:36:34 +03:00
Velichka Atanasova
1eaef0093b Add is_expired method to the Signed class
Checks metadata expiration against a reference time (a naive datetime in UTC).
If not provided, checks against the current UTC date and time.
Returns True if expiration time is less than the reference time.

Signed-off-by: Velichka Atanasova <avelichka@vmware.com>
2021-04-14 13:28:36 +03:00
lukpueh
974de44ce9
Merge pull request #1323 from MVrachev/fix-version-comment
New API: Fix exception message for version
2021-03-24 15:07:16 +01:00
Martin Vrachev
cbc814ffa8 New API: Fix exception message for version
Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-03-24 15:55:29 +02:00
Martin Vrachev
901b7f4491 Remove additional version settup in Signed
Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-03-24 15:38:11 +02:00
Jussi Kukkonen
ab56344a53 metadata: Make isort happy and bundle imports
Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-03-19 17:10:45 +02:00
Jussi Kukkonen
4575637efd imports: Make 'formats' imports vendoring-compatible
Use "from tuf import <module>" instead of "import tuf.<module>": this
makes it possible for vendoring tool to vendor tuf. Fix all references
to <module> in the code.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-03-19 16:56:47 +02:00
Jussi Kukkonen
4b078b0975 imports: Make 'exceptions' imports vendoring-compatible
Use "from tuf import <module>" instead of "import tuf.<module>": this
makes it possible for vendoring tool to vendor tuf. Fix all references
to <module> in the code.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-03-19 16:54:39 +02:00
Lukas Puehringer
be0cef067c Manually standardize quotes where black cannot
Black standardizes single to double quotes where feasible.
However, it doesn't seem to change double to single quotes nor adds
escape characters, as a consequence it skips standardization on
strings with mixed quotes.

Unfortunately, pylint's quote consistency check also doesn't detect
this, so the onus will remain on the reviewer in these cases.

**Unrelated changes**:
The commit still enables pylint's "check-quote-consistency" just in
case it can detect something the black doesn't.

The commit also fixes a syntax inconsistency in pylintrc.

Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-17 11:57:45 +01:00
Lukas Puehringer
42a797b4a1 Re-format tuf/api/* using black and isort
Use black and isort to reformat new code in tuf/api/*, like so:

```
black --line-length 80 api
isort --line-length 80 --profile black api
```

Besides downsizing the default line length to fit our Code Style
Guide no extra configuration is required.

Unified format according to black and isort will be enforced by
CI/CD in a future commit.

**Changes include:**
- Use double quotes instead of single quotes where feasible
- Re-wrap and re-indent long lines such as dict literals, function
  signatures and function calls, using hanging indent
  This will require an update in our Code Style Guide, which the
  benefits of using black seem worth.
  https://github.com/secure-systems-lab/code-style-guidelines/blob/master/python.md#indentation-and-line-continuation
- Update vertical and horizontal spacing
- Sort and wrap imports

See black and isort docs for details:
https://black.readthedocs.io/en/stable/the_black_code_style.html
https://pycqa.github.io/isort/docs/configuration/black_compatibility/

NOTE: If desired I can split commits by change and/or configure git
for this repo to ignore the corresponding revision(s) in git-blame.
https://github.com/psf/black#migrating-your-code-style-without-ruining-git-blame

Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-12 11:51:55 +01:00
Martin Vrachev
49aa0fc167 Make new API compatible with the Signing interface
In the securesystemslib pr https://github.com/secure-systems-lab/securesystemslib/pull/319
I added a new Signer interface with the purpose of supporting multiple
signing implementations.
Additionally, I added the SSlibSigner implementation of that interface
which implements the signing operation for rsa, ed25519 and ecdsa
schemes.
With this commit, I integrate the SSlibSigner into the new API in tuf.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-03-10 10:57:45 +01:00
Lukas Puehringer
ef91964db0 Call mixin-style parent methods on cls/self
Call an instance method and a static method that are only defined
in a parent class from child instances using self (instance) and
cls (static) instead of super().

While this doesn't make a practical difference, the new syntax is
probably less confusing to the reader.

Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-10 09:44:38 +01:00
Lukas Puehringer
326d2af7c4 Fix blank lines in tuf.api as per styleguide
https://github.com/google/styleguide/blob/gh-pages/pyguide.md#35-blank-lines

Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-10 09:44:38 +01:00
Lukas Puehringer
ace25e4ad3 Demystify from/to_dict methods in Signed baseclass
Prior to this commit the (abstract) 'Signed' base class implemented
from/to_dict methods, to be used by any subclass in addition to
or instead of a custom from/to_dict method. The design led to some
confusion, especially in 'Signed.from_dict' factories, which
instantiated subclass objects when called on a subclass, which
didn't implement its own 'from_dict' method.

This commit demystifies the design, by implementing from/to_dict
on all 'Signed' subclasses, and moving common from/to_dict tasks
to helper functions in the 'Signed' class.

The newly gained clarity and explicitness comes at the cost of
slightly more lines of code.

Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-10 09:44:38 +01:00
Lukas Puehringer
f8fc5e263b Reduce JSON-bias in metadata class model
Clarify that the TUF metadata class model is not bound to a JSON
wireline format by:

- re-wording module, class and method docstrings and code comments
  to add details about custom and default serialization and the
  purpose of from/to_dict methods, and

- removing the 'JsonDict' type annotation -- instead we use
  generic Mapping[str, Any] for method arguments and strict
  Dict[str, Any] as return value as suggested in
  https://docs.python.org/3/library/typing.html#typing.Dict

Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-10 09:44:38 +01:00
Lukas Puehringer
aba6ba3f30 Use named argument instead of clarifying comment
Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-10 09:44:38 +01:00
Lukas Puehringer
d823c8fc01 Rename a few variables in tuf.api
- Rename _dict to json_dict to avoid wrong semantics of leading
  underscore. (leading underscore was initially chosen to avoid name
  shadowing)

- Rename 'serializer' argument of type 'SignedSerializer' to
  'signed_serializer', to distinguish from 'serializer' argument of
  type 'MetadataSerializer'.

Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-10 09:44:30 +01:00
Lukas Puehringer
aa8225cb07 Mark kwargs in metadata API methods as Optional
Use typing.Optional for optional kwargs that default to None.

Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-10 09:44:09 +01:00