Commit graph

77 commits

Author SHA1 Message Date
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
Jussi Kukkonen
efd412aa90 Metadata API/pylintrc: Use old style logging
This is suggested by the Google style guide: the old style logging
(%-format) allows the log strings to be lazily formatted so there's less
need to think about performance when forming debug messages.

No actual code changes are needed because the metadata API does not yet
log anything.

Fixes #1334

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-05-11 11:47:38 +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
4648fbfadd Update tuf/api/pylintrc for new code
The updated pylintrc is based on the Google Python Style Guide
pylint configuration at
https://google.github.io/styleguide/pylintrc with the following
differences:
- We don't list defaults which are applied anyway.
- We don't configure checks that seem unrelated to the code style
  guide.
- We don't disable any checks that are not in conflict with the
  current code or code style guide.

This has the advantage of a minimal configuration file which should
be easy to maintain and extend as required, e.g. if conflicting
code is added, or linting time becomes too long, due to unnecessary
checks.

Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-12 12:27:59 +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
a53d68b91d Re-word api.serializer.json docstrings
- Make class docstrings wording consistent.
- Emphasize that we use the OLPC Canonical JSON specification.

Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-10 09:44:38 +01:00
Lukas Puehringer
bd94f6d8d1 Remove py2 compat from api.serialization package
tuf.api is not designed for Python 2 compatibility. This commit
removes the following stray compatibility constructs in its
serialization subpackage:

- '__metaclass__ = abc.ABCMeta'
- six.raise_from

Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-10 09:44:38 +01:00
Lukas Puehringer
ab92ba257f Fix inconsistent returns in json serializers
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
Lukas Puehringer
2b4085718b Re-word serialization cyclic import code comments
- Try to clarify purpose and remove unimportant TODO note
- Use pylint block-level control for shorter lines, see
  http://pylint.pycqa.org/en/latest/user_guide/message-control.html#block-disables

Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-10 09:44:03 +01:00
Lukas Puehringer
2f57eb8ed7 Add SPDX style license and copyright boilerplate
Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-04 16:26:34 +01:00
Lukas Puehringer
8e9afc96f9 Revert "Move to/from_dict metadata API methods..."
Revert an earlier commit that moved to/from_dict metadata class
model methods to a util module of the serialization sub-package.

We keep to/from_dict methods on the metadata classes because:
- It seems **idiomatic** (see e.g. 3rd-party libaries such as attrs,
pydantic, marshmallow, or built-ins that provide default or
customizable dict representation for higher-level objects).
The idiomatic choice should make usage more intuitive.
- It feels better **structured** when each method is encapsulated
within the corresponding class, which in turn should make
maintaining/modifying/extending the class model easier.
- It allows us to remove function-scope imports (see subsequent
commit).

Caveat:
Now that "the meat" of the sub-packaged JSON serializer is
implemented on the class, it might make it harder to create a
non-dict based serializer by copy-paste-amending the JSON
serializer.

However, the benefits from above seem to outweigh the disadvantage.

See option 5 of ADR0006 for further details (#1270).

Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
2021-03-04 12:46:16 +01:00