Skip to content

Commit ca048a2

Browse files
author
Jussi Kukkonen
committed
tests: Remove sleeps from indefinite freeze tests
Instead of sleeping, mock time.time() so Updater thinks it lives in the future. Signed-off-by: Jussi Kukkonen <jkukkonen@vmware.com>
1 parent e7ce873 commit ca048a2

File tree

1 file changed

+55
-79
lines changed

1 file changed

+55
-79
lines changed

tests/test_indefinite_freeze_attack.py

Lines changed: 55 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
from __future__ import division
4545
from __future__ import unicode_literals
4646

47+
import datetime
48+
import unittest.mock as mock
4749
import os
4850
import time
4951
import 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

Comments
 (0)