From b0d9f103a2d2b3c5e5cb302aef1e6cc858d260e1 Mon Sep 17 00:00:00 2001 From: Lukas Puehringer Date: Fri, 4 Oct 2019 16:27:41 +0200 Subject: [PATCH] Add full root rotation updater test Test that a client whose root is outdated by multiple versions and who has none of the latest nor next-to-latest root keys can still update and does so by incrementally verifying all roots until the most recent one. Signed-off-by: Lukas Puehringer --- .../test_updater_root_rotation_integration.py | 42 ++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/tests/test_updater_root_rotation_integration.py b/tests/test_updater_root_rotation_integration.py index 7937af40..d5a4876c 100755 --- a/tests/test_updater_root_rotation_integration.py +++ b/tests/test_updater_root_rotation_integration.py @@ -51,6 +51,7 @@ import subprocess import sys import unittest +import filecmp import tuf import tuf.log @@ -213,10 +214,48 @@ def test_root_rotation(self): shutil.rmtree(os.path.join(self.repository_directory, 'metadata')) shutil.copytree(os.path.join(self.repository_directory, 'metadata.staged'), os.path.join(self.repository_directory, 'metadata')) - self.repository_updater.refresh() + + def test_root_rotation_full(self): + """Test that a client whose root is outdated by multiple versions and who + has none of the latest nor next-to-latest root keys can still update and + does so by incrementally verifying all roots until the most recent one. """ + # Load initial repository with 1.root.json == root.json, signed by "root" + # key. This is the root.json that is already on the client. + repository = repo_tool.load_repository(self.repository_directory) + + # 1st rotation: 1.root.json --> 2.root.json + # 2.root.json will be signed by previous "root" key and by new "root2" key + repository.root.load_signing_key(self.role_keys['root']['private']) + repository.root.add_verification_key(self.role_keys['root2']['public']) + repository.root.load_signing_key(self.role_keys['root2']['private']) + repository.writeall() + + # 2nd rotation: 2.root.json --> 3.root.json + # 3.root.json will be signed by previous "root2" key and by new "root3" key + repository.root.unload_signing_key(self.role_keys['root']['private']) + repository.root.remove_verification_key(self.role_keys['root']['public']) + repository.root.add_verification_key(self.role_keys['root3']['public']) + repository.root.load_signing_key(self.role_keys['root3']['private']) + repository.writeall() + + # Move staged metadata to "live" metadata + shutil.rmtree(os.path.join(self.repository_directory, 'metadata')) + shutil.copytree(os.path.join(self.repository_directory, 'metadata.staged'), + os.path.join(self.repository_directory, 'metadata')) + + # Update on client 1.root.json --> 2.root.json --> 3.root.json + self.repository_updater.refresh() + + # Assert that client updated to the latest root from the repository + self.assertTrue(filecmp.cmp( + os.path.join(self.repository_directory, 'metadata', '3.root.json'), + os.path.join(self.client_metadata_current, 'root.json'))) + + + def test_root_rotation_missing_keys(self): repository = repo_tool.load_repository(self.repository_directory) @@ -327,6 +366,7 @@ def test_root_rotation_unmet_threshold(self): + def _load_role_keys(keystore_directory): # Populating 'self.role_keys' by importing the required public and private