* move code to only create objects after potential raises
* Use 'with' when possible
* close manually if those did not help
Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
We want the tests own log output visible as well, and they are not
under the "tuf" logger. Set root level to the same value as "tuf".
Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
all test_*.py files now accept zero or more '-v' to increase tuf
logging level. The default is now ERROR.
default: ERROR
"-v": ERROR, but unittest prints test names
"-vv": WARNING
"-vvv": INFO
"-vvvv": DEBUG
Example to run a single test with DEBUG level:
python3 test_updater.py -vvvv TestUpdater.test_4_refresh
Also make test_log.py restore the log level it modifies during test.
Fixes#1093
Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
All of these tests create an exception and log it. They do not
actually test anything.
The alternative would be to change the log level to something that is
not error to prevent verbose error output on successful test runs --
but that still wouldn't make them actual tests.
Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
Change Metadata.verify(key) behavior to raise an exception if
none or multiple signatures for the passed key are found on the
Metadata object.
Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
Add convenience wrapper that takes a json string and passes it
to from_dict to create a Metadata object.
Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
This commit better separates the Metadata class model from the
Metadata wireline format, by tailoring the constructors
towards class-based parameters and adding an additional
factory classmethod that creates Metadata objects based on the
wireline json/dictionary metadata representation. (pythonic
way of constructor overloading).
This 'from_dict' factory method recurses into the 'from_dict'
methods of each contained complex field/attribute that is also
represented by a class. Currently 'signed' is the only such
attribute.
This commit further:
- Changes optional constructor keyword arguments to mandatory
positional arguments: Reduces code and simplifies usage by
restricting it. For now, users are unlikely to call
constructor directly anyway, but the 'from_dict' factory (or
its 'from_json_file' wrapper) instead.
- Removes Signed.__expiration (datetime) vs. Signed.expires
(datestring) dichotomy: Keeping only one representation of the
same attribute in memory makes the interface simpler and less
ambiguous. We choose the datetime object, because it is more
convenient to modify. Transformation from and to the string
format required by the tuf wireline format is performed in the
corresponding metadata de/serialization methods, i.e.
('to_dict' and 'from_dict').
Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
Consistenly rename de/serialization interface methods, using
a 'from_' and 'to_' prefix.
read_from_json -> from_json_file
write_to_json -> to_json_file
as_json -> to_json
as_dict -> to_dict
signed_bytes -> to_canonical_bytes
The latter is also changed from a property to a method for
consistency with the other serialization methods.
Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
Remove metadata factory on Signed class, for the sake of API
simplicity/non-ambiguity, i.e. it's enough to have one
way of loading any Metadata, that is:
Metadata.read_from_json
Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
Add simple methods to create or verify signatures of the
canonical_signed property of a Metadata object.
See corresponding docstrings for behavior and design
considerations.
The commit also adds tests and updates the test setup to load
some test keys into memory.
Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
Add simple as_json Metadata method and use it instead of repository
lib's internal _get_written_metadata function in write_to_json.
This commit further adds code documentation and the possibility to
write compact json by excluding whitespace to write_to_json, and
also removes a call to the sign method from write_to_json.
The commit also adds tests.
Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
Add generic read from json class method that returns a Metadata
object with a signed field that contains the appropriate Signed
subclass, based on the signed._type field of the read metadata.
Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
The new metadata module uses constructs that are only available
on Python >= 3.6 (typing, f-format strings, etc.).
Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
Add a new test case in test_generate_targets_metadata
to check if targets metadata is up-to-date with its delegated
roles.
Signed-off-by: Teodora Sechkova <tsechkova@vmware.com>
Tests logic is modified to accommodate for the update of the
delegations during generate_targets_metadata().
Signed-off-by: Teodora Sechkova <tsechkova@vmware.com>
Add metadata module with container classes for TUF role metadata, including
methods to read/serialize/write from and to JSON, perform TUF-compliant
metadata updates, and create and verify signatures.
The 'Metadata' class provides a container for inner TUF metadata objects (Root,
Timestamp, Snapshot, Targets) (i.e. OOP composition)
The 'Signed' class provides a base class to aggregate common attributes (i.e.
version, expires, spec_version) of the inner metadata classes. (i.e. OOP
inheritance). The name of the class also aligns with the 'signed' field of
the outer metadata container.
Based on prior observations in TUF's sister project in-toto, this architecture
seems to well represent the metadata model as it is defined in the
specification (see in-toto/in-toto#98 and in-toto/in-toto#142 for related
discussions).
This commits also adds tests.
**TODO: See doc header TODO list**
**Additional design considerations**
(also in regards to prior sketches of this module)
- Aims at simplicity, brevity and recognizability of the wireline metadata
format.
- All attributes that correspond to fields in TUF JSON metadata are public.
There doesn't seem to be a good reason to protect them with leading
underscores and use setters/getters instead, it just adds more code, and
impedes recognizability of the wireline metadata format.
- Although, it might be convenient to have short-cuts on the Metadata class
that point to methods and attributes that are common to all subclasses of
the contained Signed class (e.g. Metadata.version instead of
Metadata.signed.version, etc.), this also conflicts with goal of
recognizability of the wireline metadata. Thus we won't add such short-cuts
for now. See:
https://github.com/theupdateframework/tuf/pull/1060#discussion_r452906629
- Signing keys and a 'consistent_snapshot' boolean are not on the targets
metadata class. They are a better fit for management code. See:
https://github.com/theupdateframework/tuf/pull/1060#issuecomment-660056376,
and #660.
- Does not use sslib schema checks (see TODO notes about validation in
doc header)
- Does not use existing tuf utils, such as make_metadata_fileinfo,
build_dict_conforming_to_schema, if it is easy and more explicit to
just re-implement the desired behavior on the metadata classes.
- All datetime's are treated as UTC. Since timezone info is not captured in
the wireline metadata format it should not be captured in the internal
representation either.
- Does not use 3rd-party dateutil package, in order to minimize dependency
footprint, which is especially important for update clients which often have
to vendor their dependencies.
However, compatibility between the more advanced dateutil.relativedelta (e.g
handles leap years automatically) and timedelta is tested.
- Uses PEP8 indentation (4 space) and Google-style doc string instead of
sslab-style. See
https://github.com/secure-systems-lab/code-style-guidelines/issues/20
- Does not support Python =< 3.5
Co-authored-by: Trishank Karthik Kuppusamy <trishank.kuppusamy@datadoghq.com>
Co-authored-by: Joshua Lock <jlock@vmware.com>
Co-authored-by: Teodora Sechkova <tsechkova@vmware.com>
Signed-off-by: Lukas Puehringer <lukas.puehringer@nyu.edu>
This method is duplicating verification steps which have already been
completed before the file was written to disk.
Signed-off-by: Joshua Lock <jlock@vmware.com>
We no longer handle compressed metadata files, so rename this method to be
shorter and less confusing:
_verify_uncompressed_metadata_file -> _verify_metadata_file
Signed-off-by: Joshua Lock <jlock@vmware.com>
proxy_server.py is python2 only, don't try to setup the class as it
leads to a confusing TimeoutError.
This may prevent me from debugging this apparent test failure a third
time.
Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
Our tests already expect localhost lookup to work to find test servers:
use it consistently instead of sometimes using 127.0.0.1
Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
Travis managed to still timeout with 5 seconds: increasing the timeout
(now that it's not a sleep) doesn't really hurt normal non-VM use cases
so let's bump it to 10 seconds.
Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
* Add utility function to wait on a socket until it responds
* Use the function instead of sleeping in tests that need to wait for
the server to start
* Increase the max timeout to 5 seconds by default (as appveyor builds
still seem to hit the 3 second mark sometimes)
wait_for_server() functions quite differently depending on OS: Windows
can take 2 seconds to respond with ECONNREFUSED whereas Linux is almost
instant. There might be tricks to be faster on Windows (like setting
a shorter socket timeout) but this was not done here.
This makes a full Linux test run almost 40% faster and should be more
reproducible on every platform.
Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
This avoids the need to sleep() before removing the temporary
directories used, and makes sure we don't get
ResourceWarning: subprocess N is still running
messages. Use subprocess.communicate() instead of wait() if the process
has a pipe (currently the return values are just dropped though).
Practical results should be more reliability and a slightly reduced
test runtime.
Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
If a test happens to use the same port as a previous test run
(either by bad luck or hardcoding like TestMultiRepoUpdater) that
happened within a minute, the second run will fail because TCP by
default keeps sockets open for a while.
Avoid this by explicitly saying re-use is fine in this case.
Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
This commit ensures that each key will only count toward the signature
threshold once, even if the keys have different keyids.
Signed-off-by: marinamoore <mmoore32@calpoly.edu>
First in the generate_timestamp_metadata both "snapshot_filename"
and the constant SNAPSHOT_FILENAME are used which is redundant
and possibly confusing. There should be only one input
for the snapshot file name.
Second, when calling the generate_timestamp_metadata there are
cases when "snapshot_filename" is in reality "snapshot_file_path".
That's what led to the need for the addition of SNAPSHOT_FILENAME
when populating the "meta" field from the TIMESTAMP_SCHEMA.
For the same reason, it seems logical to me to rename snapshot_filename
to snapshot_file_path and explicitly take the snapshot file name
from it.
Third, in the _generate_and_write_metadata function the argument
"filenames" is by default None, but at the same time without check
it's considered that filenames is a dictionary which has a key
"snapshot". This is could be okay if the default "filenames" value
was not None, but in the current situation it's easy to call
"_generate_and_write_metadata" with rolename = timestamp
and forget to populate the filenames dictionary.
Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
This separation and refactoring is part of the change to
make length and hashes optional for timestamp and snapshot roles.
It separates FILEINFO_SCHEMA into two separate schemas:
TARGETS_FILEINFO_SCHEMA and METADATA_FILEINFO_SCHEMA.
The distinction is needed because as of version 1.0.1 of the tuf
spec targets role has mandatory length and hashes, and
snapshot and timestamp roles have a mandatory version, and optional
length and hashes.
That's why targets can't share the same schemas
as timestamp and snapshot.
Because of that schema distinction, make_fileinfo had to be too
separated into make_targets_fileinfo and make_metadata_fileinfo.
Signed-off-by: Martin Vrachev <mvrachev@vmware.com>
The argument targets_filename in the generate_snapshot_metadata
is redundant because the places where we are calling
generate_snapshot_metadata is by using the constant
TARGETS_FILENAME or by creating a variable with the same value
of "targets.json".
Signed-off-by: Martin Vrachev <mvrachev@vmware.com>