diff --git a/src/tufup/repo/__init__.py b/src/tufup/repo/__init__.py index 5d2d676..dfa50d8 100644 --- a/src/tufup/repo/__init__.py +++ b/src/tufup/repo/__init__.py @@ -383,6 +383,7 @@ def add_or_update_target( target_file_path=url_path, local_path=str(local_path) ) if custom: + # todo: handle creation of patch metadata here? # todo: should we verify that custom is a dict? target_file_info.unrecognized_fields['custom'] = custom # note we assume self.targets has been initialized diff --git a/tests/data/repository/metadata/1.root.json b/tests/data/repository/metadata/1.root.json index 03a6d63..32f7456 100755 --- a/tests/data/repository/metadata/1.root.json +++ b/tests/data/repository/metadata/1.root.json @@ -2,17 +2,17 @@ "signatures": [ { "keyid": "b7ad916e4138911155b771d0ede66666e9647e7fb6c85a1904be97dee5653568", - "sig": "8582f12a66a923c8069a4385ef594c345ca2bd69741c0ba2691c4cb20e005e7a771f6ca651852d1264d13107d108c5843d3f9b69bcd20500f7108cca6e6c8901" + "sig": "0f634a6e5f82af4447accce63c2987350c9c16fe6f8ce391ed504da106be8a127e1d606424c97a27822038cfd35e4daa96da2ec07a4a75bc2610df3bfc95cd0c" }, { "keyid": "d4ec748f9476f9f7e1f0a247b917dde4abe8a024de9ba34c7458b41bec8be6b2", - "sig": "3f2a6d6cd8232d0ca1f2b75445a7dc9bc4342f72fe88204fac7e7acad48eb6102ff1ba4b1efaf8f8ec32ee11cf68a5f92e34300f66b37e5970e878f77b2e9c0b" + "sig": "678256d67bcf6022f75920ff380dc2111e2d68120af834f1769d694665236a2c7fb57ea5731f4050e1562a8b2be870b6594a2203f52182b1b77fa98ae89ed90c" } ], "signed": { "_type": "root", "consistent_snapshot": false, - "expires": "2051-06-25T13:08:41Z", + "expires": "2051-06-27T21:21:03Z", "keys": { "5ef48ab6f5398d2bf17f1f4c4fc0e0440c4aa3734a05ae523561e02e8a99957a": { "keytype": "ed25519", diff --git a/tests/data/repository/metadata/2.root.json b/tests/data/repository/metadata/2.root.json index 52d548e..c51f327 100755 --- a/tests/data/repository/metadata/2.root.json +++ b/tests/data/repository/metadata/2.root.json @@ -1,22 +1,22 @@ { "signatures": [ { - "keyid": "b7ad916e4138911155b771d0ede66666e9647e7fb6c85a1904be97dee5653568", - "sig": "740d4c6945050abd3abba7023cb5128a4e344e83ae0f52f9c978b7b3582dd21213e72a66dec6cd4206093c634cb973cf3ec0940103e54e6a81c4424322cf2d01" + "keyid": "1bd53d9d6f08f6efba19477880b348906f5f29a67d78cbca8a44aedfad12d003", + "sig": "47a42813ae34829c60539dcceba0d4b9a8a9286beaa8d5f07d3de3050d404426c22bc95b271e7c5e7ee529bc3180f009eb31313fb825f76c3ed9ca2c501bd503" }, { - "keyid": "1bd53d9d6f08f6efba19477880b348906f5f29a67d78cbca8a44aedfad12d003", - "sig": "58ed242676830567413936feec20c80cd79d03fc31bdad38ffd0ef69e40298dfd8fe15edb7a4fd504a01ee5a7cddd3bfbd169ccd9bd2c6067e452aeee3a18102" + "keyid": "b7ad916e4138911155b771d0ede66666e9647e7fb6c85a1904be97dee5653568", + "sig": "421d85636350a89805abc4561acd3019ecf17246a37e91374a53276b5d56638c83754960c27d038c7d1193bdb33db12faf69b7a19099627c745c569093ee0005" }, { "keyid": "d4ec748f9476f9f7e1f0a247b917dde4abe8a024de9ba34c7458b41bec8be6b2", - "sig": "7ea041490934e6637998eb22ab367f1d260b3d0cdde144cc5a776dda7a65c27a6061d1b62986851ecbc49ad04c7a428987b323c1c961f65f8e0143c792deb706" + "sig": "a65dbf32349f1a57dd1dd6fc058c69a98be467f5ad408179da6e3b67abc6f2361415eb70214588d21079a9d0351500808f8c244b69f40b35a41999294461ca00" } ], "signed": { "_type": "root", "consistent_snapshot": false, - "expires": "2051-06-25T13:08:48Z", + "expires": "2051-06-27T21:21:13Z", "keys": { "1bd53d9d6f08f6efba19477880b348906f5f29a67d78cbca8a44aedfad12d003": { "keytype": "ed25519", diff --git a/tests/data/repository/metadata/root.json b/tests/data/repository/metadata/root.json index 52d548e..c51f327 100755 --- a/tests/data/repository/metadata/root.json +++ b/tests/data/repository/metadata/root.json @@ -1,22 +1,22 @@ { "signatures": [ { - "keyid": "b7ad916e4138911155b771d0ede66666e9647e7fb6c85a1904be97dee5653568", - "sig": "740d4c6945050abd3abba7023cb5128a4e344e83ae0f52f9c978b7b3582dd21213e72a66dec6cd4206093c634cb973cf3ec0940103e54e6a81c4424322cf2d01" + "keyid": "1bd53d9d6f08f6efba19477880b348906f5f29a67d78cbca8a44aedfad12d003", + "sig": "47a42813ae34829c60539dcceba0d4b9a8a9286beaa8d5f07d3de3050d404426c22bc95b271e7c5e7ee529bc3180f009eb31313fb825f76c3ed9ca2c501bd503" }, { - "keyid": "1bd53d9d6f08f6efba19477880b348906f5f29a67d78cbca8a44aedfad12d003", - "sig": "58ed242676830567413936feec20c80cd79d03fc31bdad38ffd0ef69e40298dfd8fe15edb7a4fd504a01ee5a7cddd3bfbd169ccd9bd2c6067e452aeee3a18102" + "keyid": "b7ad916e4138911155b771d0ede66666e9647e7fb6c85a1904be97dee5653568", + "sig": "421d85636350a89805abc4561acd3019ecf17246a37e91374a53276b5d56638c83754960c27d038c7d1193bdb33db12faf69b7a19099627c745c569093ee0005" }, { "keyid": "d4ec748f9476f9f7e1f0a247b917dde4abe8a024de9ba34c7458b41bec8be6b2", - "sig": "7ea041490934e6637998eb22ab367f1d260b3d0cdde144cc5a776dda7a65c27a6061d1b62986851ecbc49ad04c7a428987b323c1c961f65f8e0143c792deb706" + "sig": "a65dbf32349f1a57dd1dd6fc058c69a98be467f5ad408179da6e3b67abc6f2361415eb70214588d21079a9d0351500808f8c244b69f40b35a41999294461ca00" } ], "signed": { "_type": "root", "consistent_snapshot": false, - "expires": "2051-06-25T13:08:48Z", + "expires": "2051-06-27T21:21:13Z", "keys": { "1bd53d9d6f08f6efba19477880b348906f5f29a67d78cbca8a44aedfad12d003": { "keytype": "ed25519", diff --git a/tests/data/repository/metadata/snapshot.json b/tests/data/repository/metadata/snapshot.json index db4b04a..c05b5ad 100755 --- a/tests/data/repository/metadata/snapshot.json +++ b/tests/data/repository/metadata/snapshot.json @@ -2,12 +2,12 @@ "signatures": [ { "keyid": "5ef48ab6f5398d2bf17f1f4c4fc0e0440c4aa3734a05ae523561e02e8a99957a", - "sig": "29c6c8a45e7c0940e51cac1b9052304bb0baec1e1df35885522846ae5abd039c1846c453cd599ccc36e11c4f0a52de6b772d71627886e22dc77822b4404af602" + "sig": "73a146f5e1f12c0a36e88c8d7bf613baa1d528ea0c9480fe0d2ccd74d6da239da04470f68d283738194185cc82289c5f9f1312efea373b51dc8722965ca1fc0b" } ], "signed": { "_type": "snapshot", - "expires": "2051-06-25T13:08:48Z", + "expires": "2051-06-27T21:21:13Z", "meta": { "targets.json": { "version": 6 diff --git a/tests/data/repository/metadata/targets.json b/tests/data/repository/metadata/targets.json index 9b5797f..122d603 100755 --- a/tests/data/repository/metadata/targets.json +++ b/tests/data/repository/metadata/targets.json @@ -2,12 +2,12 @@ "signatures": [ { "keyid": "cd9930c92ac25c02a2f92ae3128b50459b53d7532ef9c0f364e78f388d5808a5", - "sig": "dbcc91a73275a2478489e491b3054328659ce5e7cdeeb7623fe41e745cbe585a0dc874e05d80a291c5658138549051a24d81f3fb61093b6133b5d3e8927e9e01" + "sig": "344b1c779103db5c8462508d7a5e72ef9ae8dea0c5fd303d55cace03a87fd67312ff5ca01fc2e377d7d0dcbbbf3f4dff378f5c9759801590340c0b9e3d23bc07" } ], "signed": { "_type": "targets", - "expires": "2051-06-25T13:08:48Z", + "expires": "2051-06-27T21:21:13Z", "spec_version": "1.0.31", "targets": { "example_app-1.0.tar.gz": { @@ -17,10 +17,15 @@ "length": 101613 }, "example_app-2.0.patch": { + "custom": { + "tar_hash": "855c631eb1a8d756bbad8441b76b5452505d292a162b3d497a60877fee2140b5", + "tar_hash_algorithm": "sha256", + "tar_size": 112640 + }, "hashes": { - "sha256": "f7ee90e00fa69d5832eeee193f9b6bb2d32ff028c413f47fbaf853b3d2add27f" + "sha256": "f2be4504e464bd23c022772c7f3c011e0082295775a24e3fc986bb2504df0f53" }, - "length": 18709 + "length": 318 }, "example_app-2.0.tar.gz": { "custom": { @@ -36,10 +41,15 @@ "length": 101744 }, "example_app-3.0rc0.patch": { + "custom": { + "tar_hash": "3cd260c121d05f4c6ed55b6e87569d3710e539e0a86e6fce98189ddca20c99f5", + "tar_hash_algorithm": "sha256", + "tar_size": 112640 + }, "hashes": { - "sha256": "dcf2ce8ca9fc0ccc0e541fb0fca97a7772374177197a41fa4cf17653ef850956" + "sha256": "01fa6f30ac54fd405dfb5bd6e39f71af572c8e341675f5b2822b35ec341ce6f9" }, - "length": 6458 + "length": 323 }, "example_app-3.0rc0.tar.gz": { "custom": { @@ -55,10 +65,15 @@ "length": 101841 }, "example_app-4.0a0.patch": { + "custom": { + "tar_hash": "3d3efe43388f3bbae910af39232526ef624d1540cfbb69cf0d4c66b7d5dc4b45", + "tar_hash_algorithm": "sha256", + "tar_size": 112640 + }, "hashes": { - "sha256": "0fc6918d6d0757e234fe550e26bca659503166da3d3f493ec6bdbb5281b356ce" + "sha256": "e19ccd94e60d1d817dcc44c481f4fb48f54fa335cc0bd7a7e60377a4f6ccf2ea" }, - "length": 102567 + "length": 100988 }, "example_app-4.0a0.tar.gz": { "custom": { diff --git a/tests/data/repository/metadata/timestamp.json b/tests/data/repository/metadata/timestamp.json index 7c7b0f4..e2ce07a 100755 --- a/tests/data/repository/metadata/timestamp.json +++ b/tests/data/repository/metadata/timestamp.json @@ -2,12 +2,12 @@ "signatures": [ { "keyid": "eddb87d254d513c1404d71e17620ecf5260e1836babdaa55197916c582f37a00", - "sig": "bc22b24fadb6fabbc915cd7c5dd704cd338bad94d268f53e5c5e743fbbb707dfa8e339b5d5a6fefa4360431d610e383c6744d2e7306121d4cd4bd2388ecfef02" + "sig": "4f05f9947e1fd704ffb877fa994e8841eb1a34a2ccf021c2eac5a618eca3c11baad8531d154fa5c8aa187e0bfaa57b521901ef502bd7a3dc601bfa1c408a4106" } ], "signed": { "_type": "timestamp", - "expires": "2051-06-25T13:08:48Z", + "expires": "2051-06-27T21:21:13Z", "meta": { "snapshot.json": { "version": 7 diff --git a/tests/data/repository/targets/example_app-2.0.patch b/tests/data/repository/targets/example_app-2.0.patch index 1a9628a..a029fcd 100644 Binary files a/tests/data/repository/targets/example_app-2.0.patch and b/tests/data/repository/targets/example_app-2.0.patch differ diff --git a/tests/data/repository/targets/example_app-3.0rc0.patch b/tests/data/repository/targets/example_app-3.0rc0.patch index 3d0d978..a4b50f1 100644 Binary files a/tests/data/repository/targets/example_app-3.0rc0.patch and b/tests/data/repository/targets/example_app-3.0rc0.patch differ diff --git a/tests/data/repository/targets/example_app-4.0a0.patch b/tests/data/repository/targets/example_app-4.0a0.patch index 8874b82..1f968db 100644 Binary files a/tests/data/repository/targets/example_app-4.0a0.patch and b/tests/data/repository/targets/example_app-4.0a0.patch differ diff --git a/tests/test_client.py b/tests/test_client.py index d1737a3..ea8f3d3 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -13,6 +13,7 @@ from tuf.ngclient import TargetFile from tests import TempDirTestCase, TEST_REPO_DIR +import tufup.client from tufup.client import AuthRequestsFetcher, Client, SUFFIX_FAILED from tufup.common import TargetMeta @@ -98,15 +99,19 @@ def test_init(self): def test_trusted_target_metas(self): client = self.get_refreshed_client() self.assertTrue(client.trusted_target_metas) - # in the test data, only the archives have custom metadata, as defined in - # the repo_workflow_example.py script + # The archives have custom metadata from the user, as defined in the + # repo_workflow_example.py script. The patches have custom metadata for .tar + # integrity check (internal). for meta in client.trusted_target_metas: with self.subTest(msg=meta): - if meta.is_archive and str(meta.version) != '1.0': - self.assertTrue(meta.custom) - self.assertIsInstance(meta.custom, dict) - else: - self.assertIsNone(meta.custom) + if str(meta.version) != '1.0': + if meta.is_archive: + self.assertTrue(meta.custom) + example_key = 'changes' # see repo workflow example + self.assertIn(example_key, meta.custom) + else: + # patches must have tar hash information + self.assertIn('tar_hash', meta.custom) def test_get_targetinfo(self): client = self.get_refreshed_client() @@ -254,9 +259,9 @@ def test__apply_updates(self): with self.subTest(msg='patch failure due to mismatch'): mock_install = Mock() with patch.object( - client.new_archive_info, - 'verify_length_and_hashes', - Mock(side_effect=LengthOrHashMismatchError()), + tufup.client.Patcher, + '_verify_tar_size_and_hash', + Mock(side_effect=Exception()), ): client._apply_updates(install=mock_install, skip_confirmation=True) mock_install.assert_not_called()