@@ -310,43 +310,78 @@ def test_new_timestamp_unsigned(self) -> None:
310
310
311
311
@patch .object (datetime , "datetime" , wraps = datetime .datetime )
312
312
def test_expired_timestamp_version_rollback (self , mock_time : Mock ) -> None :
313
+ """Verifies that local timestamp is used in rollback checks even if it is expired.
314
+
315
+ The timestamp updates and rollback checks are performed
316
+ with the following timing:
317
+ - Timestamp v1 expiry set to day 7
318
+ - First updater refresh performed on day 0
319
+ - Repository publishes timestamp v2 on day 0
320
+ - Timestamp v2 expiry set to day 21
321
+ - Second updater refresh performed on day 18:
322
+ assert that rollback check uses expired timestamp v1"""
323
+
324
+ now = datetime .datetime .utcnow ()
325
+ self .sim .timestamp .expires = now + datetime .timedelta (days = 7 )
326
+
327
+ self .sim .timestamp .version = 2
328
+
329
+ # Make a successful update of valid metadata which stores it in cache
313
330
self ._run_refresh ()
314
331
332
+ self .sim .timestamp .expires = now + datetime .timedelta (days = 21 )
333
+
334
+ self .sim .timestamp .version = 1
335
+
315
336
mock_time .utcnow .return_value = (
316
- datetime .datetime .utcnow () + datetime .timedelta (seconds = 1 )
337
+ datetime .datetime .utcnow () + datetime .timedelta (days = 18 )
317
338
)
318
339
with patch ("datetime.datetime" , mock_time ):
319
- # Check for a rollback attack
320
- self .sim .timestamp .version = 2
321
- self ._run_refresh ()
322
-
323
- self .sim .timestamp .version = 1
340
+ # Check that a rollback protection is performed even if
341
+ # local timestamp has expired
324
342
with self .assertRaises (BadVersionNumberError ):
325
343
self ._run_refresh ()
326
344
327
- self ._assert_version_equals (Timestamp .type , 2 )
345
+ self ._assert_version_equals (Timestamp .type , 2 )
328
346
329
347
@patch .object (datetime , "datetime" , wraps = datetime .datetime )
330
348
def test_expired_timestamp_snapshot_rollback (self , mock_time : Mock ) -> None :
349
+ """Verifies that rollback protection is done even if local timestamp has expired.
350
+
351
+ The snapshot updates and rollback protection checks are performed
352
+ with the following timing:
353
+ - Timestamp v1 expiry set to day 7
354
+ - Repository bumps snapshot to v3 on day 0
355
+ - First updater refresh performed on day 0
356
+ - Timestamp v2 expiry set to day 21
357
+ - Second updater refresh performed on day 18:
358
+ assert that rollback protection is done with expired timestamp v1"""
359
+
360
+ now = datetime .datetime .utcnow ()
361
+ self .sim .timestamp .expires = now + datetime .timedelta (days = 7 )
362
+
363
+ # Bump the snapshot version number to 3
364
+ self .sim .update_snapshot ()
365
+ self .sim .update_snapshot ()
366
+
367
+ # Make a successful update of valid metadata which stores it in cache
331
368
self ._run_refresh ()
332
369
370
+ self .sim .snapshot .version = 1
371
+ # Snapshot version number is set to 2, which is still less than 3
372
+ self .sim .update_snapshot ()
373
+ self .sim .timestamp .expires = now + datetime .timedelta (days = 21 )
374
+
333
375
mock_time .utcnow .return_value = (
334
- datetime .datetime .utcnow () + datetime .timedelta (seconds = 1 )
376
+ datetime .datetime .utcnow () + datetime .timedelta (days = 18 )
335
377
)
336
378
with patch ("datetime.datetime" , mock_time ):
337
- # Check for a rollback attack.
338
- self .sim .snapshot .version = 2
339
- self .sim .update_timestamp () # timestamp v2
340
- self ._run_refresh ()
341
-
342
- # Snapshot meta version is smaller than previous
343
- self .sim .timestamp .snapshot_meta .version = 1
344
- self .sim .timestamp .version += 1 # timestamp v3
345
-
379
+ # Assert that rollback protection is done even if
380
+ # local timestamp has expired
346
381
with self .assertRaises (BadVersionNumberError ):
347
382
self ._run_refresh ()
348
383
349
- self ._assert_version_equals (Timestamp .type , 2 )
384
+ self ._assert_version_equals (Timestamp .type , 3 )
350
385
351
386
def test_new_timestamp_version_rollback (self ) -> None :
352
387
# Check for a rollback attack
@@ -706,22 +741,34 @@ def test_load_metadata_from_cache(self, wrapped_open: MagicMock) -> None:
706
741
707
742
@patch .object (datetime , "datetime" , wraps = datetime .datetime )
708
743
def test_expired_metadata (self , mock_time : Mock ) -> None :
709
- # Test that expired local timestamp/snapshot can be used for updating
710
- # from remote
744
+ """Verifies that expired local timestamp/snapshot can be used for
745
+ updating from remote.
746
+
747
+ The updates and verifications are performed with the following timing:
748
+ - Timestamp v1 expiry set to day 7
749
+ - First updater refresh performed on day 0
750
+ - Repository bumps snapshot and targets to v2 on day 0
751
+ - Timestamp v2 expiry set to day 21
752
+ - Second updater refresh performed on day 18,
753
+ it is successful and timestamp/snaphot final versions are v2"""
754
+
755
+ now = datetime .datetime .utcnow ()
756
+ self .sim .timestamp .expires = now + datetime .timedelta (days = 7 )
711
757
712
758
# Make a successful update of valid metadata which stores it in cache
713
759
self ._run_refresh ()
714
760
715
- # Simulate expired local metadata by mocking system time one second ahead
761
+ self .sim .targets .version += 1
762
+ self .sim .update_snapshot ()
763
+ self .sim .timestamp .expires = now + datetime .timedelta (days = 21 )
764
+
765
+ # Mocking time so that local timestam has expired
766
+ # but the new timestamp has not
716
767
mock_time .utcnow .return_value = (
717
- datetime .datetime .utcnow () + datetime .timedelta (seconds = 1 )
768
+ datetime .datetime .utcnow () + datetime .timedelta (days = 18 )
718
769
)
719
770
with patch ("datetime.datetime" , mock_time ):
720
- self .sim .targets .version += 1
721
- self .sim .update_snapshot ()
722
- # Create a new updater and perform a second update while
723
- # the metadata is already stored in cache (metadata dir)
724
- self ._run_refresh ()
771
+ self ._run_refresh ()
725
772
726
773
# Assert that the final version of timestamp/snapshot is version 2
727
774
# which means a successful refresh is performed
0 commit comments