1
1
import logging
2
- from typing import Optional , Union
2
+ from typing import Optional , Union , Callable
3
3
import os
4
4
import sys
5
5
import unittest
6
6
from datetime import datetime
7
7
8
8
from tuf import exceptions
9
- from tuf .api .metadata import Metadata , MetaFile
9
+ from tuf .api .metadata import Metadata , Signed , Timestamp , Snapshot , MetaFile
10
10
from tuf .ngclient ._internal .trusted_metadata_set import TrustedMetadataSet
11
11
12
12
from securesystemslib .signer import SSlibSigner
@@ -84,41 +84,15 @@ def _update_all_besides_targets(
84
84
snapshot_bytes = snapshot_bytes or self .metadata ["snapshot" ]
85
85
self .trusted_set .update_snapshot (snapshot_bytes )
86
86
87
- def _modify_timestamp_meta (self , version : Optional [int ] = 1 ):
88
- """Remove hashes and length from timestamp.meta["snapshot.json"].
89
- Create a timestamp.meta["snapshot.json"] containing only version.
90
-
91
- Args:
92
- version:
93
- Version used when instantiating MetaFile for timestamp.meta.
94
-
95
- """
96
- timestamp = Metadata .from_bytes (self .metadata ["timestamp" ])
97
- timestamp .signed .meta ["snapshot.json" ] = MetaFile (version )
98
- timestamp .sign (self .keystore ["timestamp" ])
99
- return timestamp .to_bytes ()
100
-
101
- def _modify_snapshot_meta (
102
- self , version : Union [int , None ] = 1 , length : Optional [int ]= None
103
- ):
104
- """Modify hashes and length from snapshot_meta.meta["snapshot.json"].
105
- If version and length is None, then snapshot meta will be an empty dictionary.
106
-
107
- Args:
108
- version:
109
- Version used when instantiating MetaFile for snapshot.meta.
110
- length:
111
- Length used when instantiating MetaFile for snapshot.meta.
112
-
113
- """
114
- snapshot = Metadata .from_bytes (self .metadata ["snapshot" ])
115
- if version is None and length is None :
116
- snapshot .signed .meta = {}
117
- else :
118
- for metafile_path in snapshot .signed .meta :
119
- snapshot .signed .meta [metafile_path ] = MetaFile (version , length )
120
- snapshot .sign (self .keystore ["snapshot" ])
121
- return snapshot .to_bytes ()
87
+ def modify_metadata (
88
+ self , rolename : str , modification_func : Callable [["Signed" ], None ]
89
+ ):
90
+ """Instantiate metadata from rolename type, call modification_func and
91
+ sign it again with self.keystore[rolename] signer."""
92
+ metadata = Metadata .from_bytes (self .metadata [rolename ])
93
+ modification_func (metadata .signed )
94
+ metadata .sign (self .keystore [rolename ])
95
+ return metadata .to_bytes ()
122
96
123
97
def test_update (self ):
124
98
self .trusted_set .root_update_finished ()
@@ -255,7 +229,10 @@ def test_update_timestamp_new_timestamp_ver_below_trusted_ver(self):
255
229
self .trusted_set .update_timestamp (self .metadata ["timestamp" ])
256
230
257
231
def test_update_timestamp_snapshot_ver_below_trusted_snapshot_ver (self ):
258
- modified_timestamp = self ._modify_timestamp_meta (version = 3 )
232
+ def version_modifier (timestamp : Timestamp ):
233
+ timestamp .version = 3
234
+
235
+ modified_timestamp = self .modify_metadata ("timestamp" , version_modifier )
259
236
self ._root_updated_and_update_timestamp (modified_timestamp )
260
237
# new_timestamp.snapshot.version < trusted_timestamp.snapshot.version
261
238
with self .assertRaises (exceptions .ReplayedMetadataError ):
@@ -272,16 +249,27 @@ def test_update_timestamp_expired(self):
272
249
273
250
274
251
def test_update_snapshot_cannot_verify_snapshot_with_threshold (self ):
275
- modified_timestamp = self ._modify_timestamp_meta ()
276
- self ._root_updated_and_update_timestamp (modified_timestamp )
252
+ def hashes_length_modifier (timestamp : Timestamp ):
253
+ timestamp .meta ["snapshot.json" ].hashes = None
254
+ timestamp .meta ["snapshot.json" ].length = None
255
+
256
+ timestamp = self .modify_metadata ("timestamp" , hashes_length_modifier )
257
+ self ._root_updated_and_update_timestamp (timestamp )
277
258
snapshot = Metadata .from_bytes (self .metadata ["snapshot" ])
278
259
snapshot .signatures .clear ()
279
260
with self .assertRaises (exceptions .UnsignedMetadataError ):
280
261
self .trusted_set .update_snapshot (snapshot .to_bytes ())
281
262
282
263
def test_update_snapshot_version_different_timestamp_snapshot_version (self ):
283
- modified_timestamp = self ._modify_timestamp_meta (version = 2 )
284
- self ._root_updated_and_update_timestamp (modified_timestamp )
264
+ def hashes_length_version_modifier (timestamp : Timestamp ):
265
+ timestamp .meta ["snapshot.json" ].hashes = None
266
+ timestamp .meta ["snapshot.json" ].length = None
267
+ timestamp .meta ["snapshot.json" ].version = 2
268
+
269
+ timestamp = self .modify_metadata (
270
+ "timestamp" , hashes_length_version_modifier
271
+ )
272
+ self ._root_updated_and_update_timestamp (timestamp )
285
273
# new_snapshot.version != trusted timestamp.meta["snapshot"].version
286
274
snapshot = Metadata .from_bytes (self .metadata ["snapshot" ])
287
275
snapshot .signed .version = 3
@@ -290,8 +278,12 @@ def test_update_snapshot_version_different_timestamp_snapshot_version(self):
290
278
self .trusted_set .update_snapshot (snapshot .to_bytes ())
291
279
292
280
def test_update_snapshot_after_successful_update_new_snapshot_no_meta (self ):
293
- modified_timestamp = self ._modify_timestamp_meta ()
294
- self ._update_all_besides_targets (modified_timestamp )
281
+ def hashes_length_modifier (timestamp : Timestamp ):
282
+ timestamp .meta ["snapshot.json" ].hashes = None
283
+ timestamp .meta ["snapshot.json" ].length = None
284
+
285
+ timestamp = self .modify_metadata ("timestamp" , hashes_length_modifier )
286
+ self ._update_all_besides_targets (timestamp )
295
287
# Test removing a meta_file in new_snapshot compared to the old snapshot
296
288
snapshot = Metadata .from_bytes (self .metadata ["snapshot" ])
297
289
snapshot .signed .meta = {}
@@ -300,8 +292,12 @@ def test_update_snapshot_after_successful_update_new_snapshot_no_meta(self):
300
292
self .trusted_set .update_snapshot (snapshot .to_bytes ())
301
293
302
294
def test_update_snapshot_after_succesfull_update_new_snapshot_meta_version_different (self ):
303
- modified_timestamp = self ._modify_timestamp_meta ()
304
- self ._root_updated_and_update_timestamp (modified_timestamp )
295
+ def hashes_length_modifier (timestamp : Timestamp ):
296
+ timestamp .meta ["snapshot.json" ].hashes = None
297
+ timestamp .meta ["snapshot.json" ].length = None
298
+
299
+ timestamp = self .modify_metadata ("timestamp" , hashes_length_modifier )
300
+ self ._root_updated_and_update_timestamp (timestamp )
305
301
# snapshot.meta["project1"].version != new_snapshot.meta["project1"].version
306
302
snapshot = Metadata .from_bytes (self .metadata ["snapshot" ])
307
303
for metafile_path in snapshot .signed .meta .keys ():
@@ -312,8 +308,12 @@ def test_update_snapshot_after_succesfull_update_new_snapshot_meta_version_diffe
312
308
self .trusted_set .update_snapshot (self .metadata ["snapshot" ])
313
309
314
310
def test_update_snapshot_expired_new_snapshot (self ):
315
- modified_timestamp = self ._modify_timestamp_meta ()
316
- self ._root_updated_and_update_timestamp (modified_timestamp )
311
+ def hashes_length_modifier (timestamp : Timestamp ):
312
+ timestamp .meta ["snapshot.json" ].hashes = None
313
+ timestamp .meta ["snapshot.json" ].length = None
314
+
315
+ timestamp = self .modify_metadata ("timestamp" , hashes_length_modifier )
316
+ self ._root_updated_and_update_timestamp (timestamp )
317
317
# new_snapshot has expired
318
318
snapshot = Metadata .from_bytes (self .metadata ["snapshot" ])
319
319
snapshot .signed .expires = datetime (1970 , 1 , 1 )
@@ -323,34 +323,48 @@ def test_update_snapshot_expired_new_snapshot(self):
323
323
324
324
325
325
def test_update_targets_no_meta_in_snapshot (self ):
326
- modified_timestamp = self ._modify_timestamp_meta ()
327
- modified_snapshot = self ._modify_snapshot_meta (version = None )
328
- self ._update_all_besides_targets (
329
- timestamp_bytes = modified_timestamp ,
330
- snapshot_bytes = modified_snapshot
331
- )
326
+ def hashes_length_modifier (timestamp : Timestamp ):
327
+ timestamp .meta ["snapshot.json" ].hashes = None
328
+ timestamp .meta ["snapshot.json" ].length = None
329
+
330
+ timestamp = self .modify_metadata ("timestamp" , hashes_length_modifier )
331
+ def no_meta_modifier (snapshot : Snapshot ):
332
+ snapshot .meta = {}
333
+
334
+ snapshot = self .modify_metadata ("snapshot" , no_meta_modifier )
335
+ self ._update_all_besides_targets (timestamp , snapshot )
332
336
# remove meta information with information about targets from snapshot
333
337
with self .assertRaises (exceptions .RepositoryError ):
334
338
self .trusted_set .update_targets (self .metadata ["targets" ])
335
339
336
340
def test_update_targets_hash_different_than_snapshot_meta_hash (self ):
337
- modified_timestamp = self ._modify_timestamp_meta ()
338
- modified_snapshot = self ._modify_snapshot_meta (version = 1 , length = 1 )
339
- self ._update_all_besides_targets (
340
- timestamp_bytes = modified_timestamp ,
341
- snapshot_bytes = modified_snapshot
342
- )
341
+ def hashes_length_modifier (timestamp : Timestamp ):
342
+ timestamp .meta ["snapshot.json" ].hashes = None
343
+ timestamp .meta ["snapshot.json" ].length = None
344
+
345
+ timestamp = self .modify_metadata ("timestamp" , hashes_length_modifier )
346
+ def meta_length_modifier (snapshot : Snapshot ):
347
+ for metafile_path in snapshot .meta :
348
+ snapshot .meta [metafile_path ] = MetaFile (version = 1 , length = 1 )
349
+
350
+ snapshot = self .modify_metadata ("snapshot" , meta_length_modifier )
351
+ self ._update_all_besides_targets (timestamp , snapshot )
343
352
# observed_hash != stored hash in snapshot meta for targets
344
353
with self .assertRaises (exceptions .RepositoryError ):
345
354
self .trusted_set .update_targets (self .metadata ["targets" ])
346
355
347
356
def test_update_targets_version_different_snapshot_meta_version (self ):
348
- modified_timestamp = self ._modify_timestamp_meta ()
349
- modified_snapshot = self ._modify_snapshot_meta (version = 2 )
350
- self ._update_all_besides_targets (
351
- timestamp_bytes = modified_timestamp ,
352
- snapshot_bytes = modified_snapshot
353
- )
357
+ def hashes_length_modifier (timestamp : Timestamp ):
358
+ timestamp .meta ["snapshot.json" ].hashes = None
359
+ timestamp .meta ["snapshot.json" ].length = None
360
+
361
+ timestamp = self .modify_metadata ("timestamp" , hashes_length_modifier )
362
+ def meta_modifier (snapshot : Snapshot ):
363
+ for metafile_path in snapshot .meta :
364
+ snapshot .meta [metafile_path ] = MetaFile (version = 2 )
365
+
366
+ snapshot = self .modify_metadata ("snapshot" , meta_modifier )
367
+ self ._update_all_besides_targets (timestamp , snapshot )
354
368
# new_delegate.signed.version != meta.version stored in snapshot
355
369
with self .assertRaises (exceptions .BadVersionNumberError ):
356
370
self .trusted_set .update_targets (self .metadata ["targets" ])
0 commit comments