4444from __future__ import division
4545from __future__ import unicode_literals
4646
47+ import datetime
48+ import unittest .mock as mock
4749import os
4850import time
4951import tempfile
@@ -265,8 +267,7 @@ def test_with_tuf(self):
265267 # Load the repository
266268 repository = repo_tool .load_repository (self .repository_directory )
267269
268- # Load the timestamp and snapshot keys, since we will be signing a new
269- # timestamp and a new snapshot file.
270+ # Load the snapshot and timestamp keys
270271 key_file = os .path .join (self .keystore_directory , 'timestamp_key' )
271272 timestamp_private = repo_tool .import_ed25519_privatekey_from_file (key_file ,
272273 'password' )
@@ -276,17 +277,11 @@ def test_with_tuf(self):
276277 'password' )
277278 repository .snapshot .load_signing_key (snapshot_private )
278279
279- # Expire snapshot in 10s. This should be far enough into the future that we
280- # haven't reached it before the first refresh validates timestamp expiry.
281- # We want a successful refresh before expiry, then a second refresh after
282- # expiry (which we then expect to raise an exception due to expired
283- # metadata).
284- expiry_time = time .time () + 10
285- datetime_object = tuf .formats .unix_timestamp_to_datetime (int (expiry_time ))
286-
287- repository .snapshot .expiration = datetime_object
288-
289- # Now write to the repository.
280+ # sign snapshot with expiry in near future (earlier than e.g. timestamp)
281+ expiry = int (time .time () + 60 * 60 )
282+ repository .snapshot .expiration = tuf .formats .unix_timestamp_to_datetime (
283+ expiry )
284+ repository .mark_dirty (['snapshot' , 'timestamp' ])
290285 repository .writeall ()
291286
292287 # And move the staged metadata to the "live" metadata.
@@ -297,30 +292,24 @@ def test_with_tuf(self):
297292 # Refresh metadata on the client. For this refresh, all data is not expired.
298293 logger .info ('Test: Refreshing #1 - Initial metadata refresh occurring.' )
299294 self .repository_updater .refresh ()
300- logger .info ('Test: Refreshed #1 - Initial metadata refresh completed '
301- 'successfully. Now sleeping until snapshot metadata expires.' )
302-
303- # Sleep until expiry_time ('repository.snapshot.expiration')
304- time .sleep (max (0 , expiry_time - time .time () + 1 ))
305-
306- logger .info ('Test: Refreshing #2 - Now trying to refresh again after local'
307- ' snapshot expiry.' )
308295
309- try :
310- self .repository_updater .refresh () # We expect this to fail!
296+ logger .info ('Test: Refreshing #2 - refresh after local snapshot expiry.' )
311297
312- except tuf .exceptions .ExpiredMetadataError :
313- logger .info ('Test: Refresh #2 - failed as expected. Expired local'
314- ' snapshot case generated a tuf.exceptions.ExpiredMetadataError'
315- ' exception as expected. Test pass.' )
298+ # mock current time to one second after snapshot expiry
299+ mock_time = mock .Mock ()
300+ mock_time .return_value = expiry + 1
301+ with mock .patch ('time.time' , mock_time ):
302+ try :
303+ self .repository_updater .refresh () # We expect this to fail!
316304
317- # I think that I only expect tuf.ExpiredMetadata error here. A
318- # NoWorkingMirrorError indicates something else in this case - unavailable
319- # repo, for example.
320- else :
305+ except tuf .exceptions . ExpiredMetadataError :
306+ logger . info ( 'Test: Refresh #2 - failed as expected. Expired local'
307+ ' snapshot case generated a tuf.exceptions.ExpiredMetadataError'
308+ ' exception as expected. Test pass.' )
321309
322- self .fail ('TUF failed to detect expired stale snapshot metadata. Freeze'
323- ' attack successful.' )
310+ else :
311+ self .fail ('TUF failed to detect expired stale snapshot metadata. Freeze'
312+ ' attack successful.' )
324313
325314
326315
@@ -355,7 +344,7 @@ def test_with_tuf(self):
355344 # We cannot set the timestamp expiration with
356345 # 'repository.timestamp.expiration = ...' with already-expired timestamp
357346 # metadata because of consistency checks that occur during that assignment.
358- expiry_time = time .time () + 1
347+ expiry_time = time .time () + 60 * 60
359348 datetime_object = tuf .formats .unix_timestamp_to_datetime (int (expiry_time ))
360349 repository .timestamp .expiration = datetime_object
361350 repository .writeall ()
@@ -365,29 +354,21 @@ def test_with_tuf(self):
365354 shutil .copytree (os .path .join (self .repository_directory , 'metadata.staged' ),
366355 os .path .join (self .repository_directory , 'metadata' ))
367356
368- # Wait just long enough for the timestamp metadata (which is now both on
369- # the repository and on the client) to expire.
370- time .sleep (max (0 , expiry_time - time .time () + 1 ))
357+ # mock current time to one second after timestamp expiry
358+ mock_time = mock .Mock ()
359+ mock_time .return_value = expiry_time + 1
360+ with mock .patch ('time.time' , mock_time ):
361+ try :
362+ self .repository_updater .refresh () # We expect NoWorkingMirrorError.
371363
372- # Try to refresh top-level metadata on the client. Since we're already past
373- # 'repository.timestamp.expiration', the TUF client is expected to detect
374- # that timestamp metadata is outdated and refuse to continue the update
375- # process.
376- try :
377- self .repository_updater .refresh () # We expect NoWorkingMirrorError.
364+ except tuf .exceptions .NoWorkingMirrorError as e :
365+ # Make sure the contained error is ExpiredMetadataError
366+ for mirror_url , mirror_error in six .iteritems (e .mirror_errors ):
367+ self .assertTrue (isinstance (mirror_error , tuf .exceptions .ExpiredMetadataError ))
378368
379- except tuf .exceptions .NoWorkingMirrorError as e :
380- # NoWorkingMirrorError indicates that we did not find valid, unexpired
381- # metadata at any mirror. That exception class preserves the errors from
382- # each mirror. We now assert that for each mirror, the particular error
383- # detected was that metadata was expired (the timestamp we manually
384- # expired).
385- for mirror_url , mirror_error in six .iteritems (e .mirror_errors ):
386- self .assertTrue (isinstance (mirror_error , tuf .exceptions .ExpiredMetadataError ))
387-
388- else :
389- self .fail ('TUF failed to detect expired, stale timestamp metadata.'
390- ' Freeze attack successful.' )
369+ else :
370+ self .fail ('TUF failed to detect expired, stale timestamp metadata.'
371+ ' Freeze attack successful.' )
391372
392373
393374
@@ -416,8 +397,8 @@ def test_with_tuf(self):
416397 # Set ts to expire in 1 month.
417398 ts_expiry_time = time .time () + 2630000
418399
419- # Set snapshot to expire in 1 second .
420- snapshot_expiry_time = time .time () + 1
400+ # Set snapshot to expire in 1 hour .
401+ snapshot_expiry_time = time .time () + 60 * 60
421402
422403 ts_datetime_object = tuf .formats .unix_timestamp_to_datetime (
423404 int (ts_expiry_time ))
@@ -432,28 +413,23 @@ def test_with_tuf(self):
432413 shutil .copytree (os .path .join (self .repository_directory , 'metadata.staged' ),
433414 os .path .join (self .repository_directory , 'metadata' ))
434415
435- # Wait just long enough for the Snapshot metadata (which is now on the
436- # repository) to expire.
437- time .sleep (max (0 , snapshot_expiry_time - time .time () + 1 ))
438-
439-
440- try :
441- # We expect the following refresh() to raise a NoWorkingMirrorError.
442- self .repository_updater .refresh ()
443-
444- except tuf .exceptions .NoWorkingMirrorError as e :
445- # NoWorkingMirrorError indicates that we did not find valid, unexpired
446- # metadata at any mirror. That exception class preserves the errors from
447- # each mirror. We now assert that for each mirror, the particular error
448- # detected was that metadata was expired (the Snapshot we manually
449- # expired).
450- for mirror_url , mirror_error in six .iteritems (e .mirror_errors ):
451- self .assertTrue (isinstance (mirror_error , tuf .exceptions .ExpiredMetadataError ))
452- self .assertTrue (mirror_url .endswith ('snapshot.json' ))
453-
454- else :
455- self .fail ('TUF failed to detect expired, stale Snapshot metadata.'
456- ' Freeze attack successful.' )
416+ # mock current time to one second after snapshot expiry
417+ mock_time = mock .Mock ()
418+ mock_time .return_value = snapshot_expiry_time + 1
419+ with mock .patch ('time.time' , mock_time ):
420+ try :
421+ # We expect the following refresh() to raise a NoWorkingMirrorError.
422+ self .repository_updater .refresh ()
423+
424+ except tuf .exceptions .NoWorkingMirrorError as e :
425+ # Make sure the contained error is ExpiredMetadataError
426+ for mirror_url , mirror_error in six .iteritems (e .mirror_errors ):
427+ self .assertTrue (isinstance (mirror_error , tuf .exceptions .ExpiredMetadataError ))
428+ self .assertTrue (mirror_url .endswith ('snapshot.json' ))
429+
430+ else :
431+ self .fail ('TUF failed to detect expired, stale Snapshot metadata.'
432+ ' Freeze attack successful.' )
457433
458434 # The client should have rejected the malicious Snapshot metadata, and
459435 # distrusted the local snapshot file that is no longer valid.
0 commit comments