Commit graph

1034 commits

Author SHA1 Message Date
Jussi Kukkonen
deec2eaaa0
Merge pull request #1519 from sechkova/fetcher-max-length
Remove max_length parameter from fetch
2021-09-01 17:27:12 +03:00
Jussi Kukkonen
e1ec782f19
Merge pull request #1520 from avelichka/sslib-key
Add Key.from_securesystemslib_key
2021-08-31 09:42:39 +03:00
Jussi Kukkonen
7d77eeec31
Merge pull request #1512 from MVrachev/glob-pattern-matching
Implement glob-like pattern matching
2021-08-31 09:42:27 +03:00
Teodora Sechkova
35ef056ce6
Add tests for ngclient/fetcher
Add tests for the file/data download.

Signed-off-by: Teodora Sechkova <tsechkova@vmware.com>
2021-08-30 16:21:37 +03:00
Jussi Kukkonen
7731738590
Merge pull request #1514 from MVrachev/filename-in-targetfile
Metadata API: include target target name in TargetFile
2021-08-27 11:02:49 +03:00
Martin Vrachev
b18176db9b Implement glob-like pattern matching
According to the recently updated version of the specification the shell
style wildcard matching is glob-like (see https://github.com/theupdateframework/specification/pull/174),
and therefore a path separator in a path should not be matched by a
wildcard in the PATHPATTERN.

That's not what happens with `fnmatch.fnmatch()` which doesn't
see "/" separator as a special symbol.
For example: fnmatch.fnmatch("targets/foo.tgz", "*.tgz") will return
True which is not what glob-like implementation will do.

We should make sure that target_path and the pathpattern contain the
same number of directories and because each part of the pathpattern
could include a glob pattern we should check that fnmatch.fnmatch() is
true on each target and pathpattern directory fragment separated by "/".

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-08-26 19:57:52 +03:00
Martin Vrachev
9229a405e3 Remove filename argument from Targets.update()
After the addition of "path" argument in the TargetFile class the
filename argument in Targets.update() became redundant.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-08-26 19:48:46 +03:00
Martin Vrachev
91b0c59602 Metadata API: include target path in targetfile
Currently, TargetFile instances do not contain the path relative URL of
the file they represent. The API itself does not need it but it could be
useful for users of the API.

As an example, the current client returns a dict for
get_one_valid_targetinfo(): that dict contains a filepath field and
a targetinfo field (essentially TargetFile).
We would like to keep a similar API, but avoid hand-crafted dicts.
It would be much nicer to return a TargetFile that would contain the
full "metadata" of the targetfile.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-08-26 19:48:45 +03:00
Velichka Atanasova
c875b7ed04 Add Key.from_securesystemslib_key
The securesystemslib key dictionary representation includes
the private key in keyval. TUF key doesn't handle it in any way,
but considering that we allow unrecognized symbols in the format,
we should exclude the private key otherwise this could lead to
misuse.
A call to securesystemslib.keys.format_keyval_to_metadata
with the default private=False would do exactly that.

Signed-off-by: Velichka Atanasova <avelichka@vmware.com>
2021-08-26 15:37:25 +03:00
Jussi Kukkonen
66aac38a4a
Merge pull request #1511 from MVrachev/test-containers
new API: test containers for zero or more elements
2021-08-25 20:09:38 +03:00
Martin Vrachev
45743444b1 Remove duplicate serialization tests from test_api
I was looking at how can we simplify or split test_api.py when I noticed
that the test cases covered by those two test functions are already
covered in the test_metadata_serialization.py module in the
"invalid_keys" and "invalid_roles" datasets.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-08-25 16:03:03 +03:00
Martin Vrachev
4c3fd95cb1 Additional tests for containers with 0 or >1 items
Those tests are needed to cover use cases when syntatcticly as
standalone objects the metadata classes and their helper classes defined
in tuf/api/metadata.py are valid even if they cannot be verified.

An example where an object is valid, but cannot be verified is
if we have a Role instance with an empty list of "keyids".
This instance is valid and can be created, but cannot be verified
because there is a requirement that the threshold should be above
1, meaning that there should be at least 1 element inside the "keyids"
list to complete successful threshold verification.

The situation is the same for the rest of the tests I am adding to this
commit:
- Root object without keys
- Root object without roles
- DelegationRole object with empty "keyids"
- DelegationRole object with an empty list of "paths"
- DelegationRole object with an empty list of "path_hash_prefixes"
all of these objects can be instantiated, but cannot complete
successfully threshold verification.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-08-20 17:12:44 +03:00
Martin Vrachev
df6a399b08 new API: test containers for zero or more elements
Test metadata (de)serialization with input data containing containers
with zero or more elements.

Here is the status for the different use cases:
Root keys:
- many keys: added
Root roles:
- many roles: added
Root role keyids:
- many keids: already added in https://github.com/theupdateframework/tuf/pull/1481
MetaFile hashes:
- many hashes: already tested
- zero hashes: added. Testing as invalid test case.
Timestamp meta:
- zero elements: already tested
- many elements: added
Snapshot meta:
- zero items: added
- many items: added
Delegation keys:
- many keys: added
Delegation role keyids:
- many keyids: added
Delegation role paths:
- many paths: already tested
Delegation role path_hash_prefixes:
- many path_hash_path_prefixes: already tested
Delegation roles:
- zero roles: added
- multiple roles: added
Targets targets:
- zero items: already tested
- multiple items: added

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-08-20 17:12:43 +03:00
Jussi Kukkonen
c8696d905e tests: Remove unhelpful helper
Doing the work inline is less code and easier to understand.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-08-19 11:22:01 +03:00
Jussi Kukkonen
e3b789c306 ngclient: allow limited use of wrong snapshot version
Spec does not explicitly say so but the intent is that a snapshot
metadata can be trusted for rollback protection checks of newer
snapshots even if current snapshot version does not match the version
in current timestamp meta.

Only do the snapshot version check for the "final" snapshot by doing it
when targets is updated.

Improve test names and comments.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-08-19 11:22:01 +03:00
Jussi Kukkonen
b515997701 ngclient: Allow limited use of expired timestamp/snapshot
While this is not explicitly said in the spec, the intention is that
expired timestamp and snapshot should be used for rollback protection
checks on newer timestamp/snapshot (but not for anything else).

Move the expiry checks to the "next" metadata update: timestamp expiry
is checked when snapshot is loaded, and snapshot expiry is checked
when targets is loaded.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-08-19 11:22:01 +03:00
Jussi Kukkonen
091197288f ngclient: Remove root_update_finished()
The usefulness was debatable to begin with, and now that it has become
clear that rollback protection requires a second "final verification"
step for all three root, timestamp and snapshot it is clear that
root_update_finished() is not good design.

update_root() still accepts expired root metadata but now the final
root expiry is checked when the "next" metadata (timestamp) is loaded.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-08-19 11:09:12 +03:00
Joshua Lock
e9106b59cd
Merge pull request #1522 from jku/more-trusted-set-tests
More trusted set tests
2021-08-19 08:31:52 +01:00
Jussi Kukkonen
d3441f056a
Merge pull request #1457 from jku/use-generics-to-improve-signed-typing
Improve signed typing
2021-08-18 12:01:33 +03:00
Jussi Kukkonen
7901687017
Merge pull request #1501 from MVrachev/ngclient-support-consistent-snapshot
ng client: support for prefix_targets_with_hash when downloading targets
2021-08-18 09:20:11 +03:00
Jussi Kukkonen
f02fed2502 tests: Test TrustedMetadataSet iteration
Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-08-17 15:50:01 +03:00
Jussi Kukkonen
85656a56eb tests: Add missing test to TrustedMetadataSet
Test failing length/hash test for snapshot

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-08-17 15:40:13 +03:00
Jussi Kukkonen
efb5653016 tests: Improve TrustedSet coverage
* test for succesful root update
* fix test for snapshot version rollback in timestamp update

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-08-17 13:54:18 +03:00
Jussi Kukkonen
25993d6a2d
Merge pull request #1477 from MVrachev/ng-client-improve-metadata-set-testing
ng client improve TrustedMetadataSet testing
2021-08-17 11:00:43 +03:00
Martin Vrachev
617e87eb26 Annotations and use extensively modify_metadata
Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-08-16 18:13:01 +03:00
Martin Vrachev
7d926720d1 ng client: support for prefix_targets_with_hash
Add support for prefixing targets with their hashes when downloading or
using HASH.FILENAME.EXT as target names.
The introduction of prefix_targets_with_hash was necessary, because
there are use cases like Warehouse where you could use
consistent_snapshot, but without adding a hash prefix to your targets.

When prefix_targets_with_hash is set to True, target files conforming
the format HASH.FILENAME.EXT will be downloaded from the server, but
they will be saved on the client side without their hash prefixes or
FILENAME.EXT.
This makes sure the client won't understand the usage of
prefix_targets_with_hash.

Still, if you want to use HASH.FILENAME.EXT as target names when
downloading, then additionally you need to provide consistent_snapshot
set to True in your root.json. The reason is that the specification uses
consistent_snapshot for the same purpose:
"If consistent snapshots are not used (see § 6.2 Consistent snapshots),
then the filename used to download the target file is of the fixed form
FILENAME.EXT (e.g., foobar.tar.gz). Otherwise, the filename is of the
form HASH.FILENAME.EXT
(e.g., c14aeb4ac9f4a8fc0d83d12482b9197452f6adf3eb710e3b1e2b79e8d14cb681.foobar.tar.gz),
where HASH is one of the hashes of the targets file listed in the
targets metadata file found earlier in step § 5.6 Update the targets role.
In either case, the client MUST write the file to non-volatile
storage as FILENAME.EXT."

The same behavior of using two flags is used in the legacy code when
calling tuf.client.updater.download_target() in a repository using
prefix_targets_with_hash and consistent_snapshot.

See chapter 5.7.3:
https://theupdateframework.github.io/specification/latest/index.html#fetch-target
By default, prefix_targets_with_hash is set to true to make it easier
to the user to provide uniquely identifiable targets file names by
using consistent_snapshot set to True.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-08-16 16:54:42 +03:00
Jussi Kukkonen
13e20e9954 Metadata API: Make Metadata Generic
When we use Metadata, it is helpful if the specific signed type (and all of
the signed types attribute types are correctly annotated. Currently this is
not possible.

Making Metadata Generic with constraint T, where

    T = TypeVar("T", "Root", "Timestamp", "Snapshot", "Targets")

allows these annotations. Using Generic annotations is completely
optional so all existing code still works -- the changes in test code
are done to make IDE annotations more useful in the test code, not
because they are required.

Examples:

    md = Metadata[Root].from_bytes(data)
    md:Metadata[Root] = Metadata.from_bytes(data)

In both examples md.signed is now statically typed as "Root" allowing IDE
annotations and static type checking by mypy.

Note that it's not possible to validate that "data" actually contains a
root metadata at runtime in these examples as the annotations are _not_
visible at runtime at all: new constructors would have to be added for that.

from_file() is now a class method like from_bytes() to make sure both
have the same definition of "T" when from_file() calls from_bytes():
This makes mypy happy.

Partially fixes #1433

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-08-16 16:38:21 +03:00
Teodora Sechkova
76d4633600
Raise if none of paths and path_hash_prefixes is set
The specification does not state clearly what is the
behaviour when none of delegation's "paths" and
"path_hash_prefixes" is set. See #1497.

Until this issue is clarified, copy current
Updater which raises an error in such case.

Signed-off-by: Teodora Sechkova <tsechkova@vmware.com>
2021-08-10 09:02:37 +03:00
Martin Vrachev
11531caf42 Embed modification function helpers
Instead of using general abstract modification functions embed smaller
modification functions inside each test where it's needed and
create modify_metadata function that does all of the common stuff like:
- instantiating a metadata object
- calling the modification function
- signing the modified object
- serializing back to bytes.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-07-21 17:34:23 +03:00
Martin Vrachev
71838562dc ngcl. tests: remove modification on internal state
Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-07-21 16:40:39 +03:00
Martin Vrachev
c7c9d0f321 TrustedMetadataSet testing: use Metadata.to_bytes
Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-07-16 16:57:28 +03:00
Martin Vrachev
6a942889ff ngclient TrustedMetadataSet: improve unit testing
The current situation with the TrustedMetadataSet testing is that
we don't have a mnimimal amount of unit tests testing the different
branches in the various API functionality in the class.

This commit proposes simple unit tests covering almost all of the
branches in the API functions and increasing the unit test coverage
(as reported from the "coverage" tool) from 74 % to 97 %.

The code could be complicated at places, because the different
branches in the update_* functions depend on other metadata classes
as well.
Still, I hope we can find a way and simplify the code.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-07-16 16:57:23 +03:00
Martin Vrachev
726af73256 ng client metadata set: organize common test code
Move the shared code between tests into the "setupClass" function.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-07-16 15:49:00 +03:00
Martin Vrachev
4f37de1b53 Metadata API: add Metadata.to_bytes()
Metadata.to_bytes() is missing from the API and that is now becoming
annoying when writing the tests.
I think it makes sense to add:
it'll complete the serializing counterparts to from_bytes()/from_file().

We can also reuse to_bytes() in to_file() and that way ensure we don't
import the JSONSerializer locally twice.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-07-15 15:38:14 +03:00
Jussi Kukkonen
23e4f5cdcc
Merge pull request #1481 from MVrachev/fix-role-keyids-order
Metadata API: preserve Role.keyids order
2021-07-15 11:52:35 +03:00
samuelgregorovic
112575d987 updated docs and comments
Updated/removed documented commands and comments which were referencing Python2. Also updated links to documentation referencing Python2 docs (unchanged where needed)

Signed-off-by: Samuel Gregorovic <samuelgregorovic@gmail.com>
Signed-off-by: samuelgregorovic <samuelgregorovic@gmail.com>
2021-07-14 10:37:08 +03:00
Joshua Lock
bd5912bcc7
Merge pull request #1436 from jku/verify-delegate
Metadata API: Implement threshold verification
2021-07-12 11:45:57 +01:00
Martin Vrachev
df9f3df75d Metadata API: preserve Role.keyids order
We made Role.keyids a set because the keyids are supposed
to be unique and this still makes sense.

However, the data should also preserve order
(when deserialized and serialized) and currently, it does not.
This is fairly serious since writing signed data potentially modifies
the data (making the signature invalid).

The simplest solution (as proposed by Teodora) is to sort the
set during serialization and that would ensure the order of the items.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-07-09 16:51:25 +03:00
Jussi Kukkonen
271d5b7810 Metadata API: verify_delegate: refactor
* Rename arguments so connection between the role name and the
  metadata is stronger.
* Also add a comment on the list comprehension + next() trick.
* Add return value annotation
* Raise early if delegations is None to make the flow more obvious
  (and modify test case so we have coverage for the new case)

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-07-08 20:16:42 +03:00
Martin Vrachev
9c8aa1da06 Test new API: serialization tests for invalid arg
A while ago we decided that it's best to research each of the individuals
attributes one by one and identify what level of validation it needs
compared to how we use it:
https://github.com/theupdateframework/tuf/pull/1366#issuecomment-829288790.

This work is ongoing and there are a couple of commits already merged
for this:
- 6c5d970799
- f20664d2fc
- 41afb1e134

We want to be able to test the attributes validation against known bad
values.
The way we want to do that is with table testing we have added
using decorators for our metadata classes defined in New API:
https://github.com/theupdateframework/tuf/pull/1416.
This gives us an easy way to add new cases for each of the attributes and
not depend on external files.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-07-07 13:59:28 +03:00
Jussi Kukkonen
a91a1abf97
Merge pull request #1466 from MVrachev/unrecognized_fields
Metadata API: Simplify unrecognized fields testing
2021-07-07 11:27:55 +03:00
Jussi Kukkonen
d00af4c101 tests: Improve verify_delegate() tests
Make sure verify_delegate() succeeds when threshold is reached even if
some signatures fail to verify.

Make sure higher threshold (2/2) works.

Change error type for "Call is valid only on delegator metadata" error.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-07-05 15:13:00 +03:00
Jussi Kukkonen
37a4d41aad Metadata API: Implement threshold verification
The delegating Metadata (root or targets) verifies that the delegated
metadata is signed by required threshold of keys for the delegated
role.

Calling the function on non-delegator-metadata or giving a rolename
that is not actually delegated by the delegator is considered a
programming error and ValueError is raised.

If the threshold is not reached, UnsignedMetadataError is raised.

Tweak type annotation of Delegations.keys to match the one for
Root.keys (so they can be assigned to same local variable).

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-07-05 15:13:00 +03:00
Jussi Kukkonen
4811e880c0 Rename MetadataBundle to TrustedMetadataSet
TrustedMetadataSet is a long name but
 * it better describes the main feature
 * the name isn't used in too many places

Change the variable names "bundle" -> "trusted_set"

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-07-05 10:45:19 +03:00
Teodora Sechkova
78a0f4d3b5 Remove unsued imports in tests
Remove unused and outdated imports in test_updater_ng.py

Signed-off-by: Teodora Sechkova <tsechkova@vmware.com>
2021-07-05 10:45:19 +03:00
Jussi Kukkonen
fac151da3d ngclient: Add initial testing
This testing lacks coverage but demonstrates the happy cases.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-07-05 10:45:19 +03:00
Martin Vrachev
f34cc7e2cb Metadata API: simplify testing unrecognized_fields
We have merged ADR 8 allowing for unrecognized fields and we have
added tests for that which are too specific and not scalable.

Now, I use table testing which we have used initially in https://github.com/theupdateframework/tuf/pull/1416
to test unrecognized fields support in a cleaner and much more readable
way.

Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
2021-07-01 15:40:47 +03:00
Jussi Kukkonen
505b82a82c Metadata API: Fix Metadata.sign() return value
We've been returning Signature objects since 49aa0fc167.

Also add a test case that does something with the returned signature.

Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
2021-06-23 14:35:36 +03:00
Jussi Kukkonen
7108ea2e0e
Merge pull request #1454 from sechkova/hashes-handle-sslib-errors
BaseFile._verify_hashes: handle sslib errors
2021-06-23 10:19:14 +03:00
Jussi Kukkonen
97da5ab991
Merge pull request #1416 from MVrachev/comprehensive-testing
New API: Comprehensive serialization testing
2021-06-23 10:17:50 +03:00