def setUp(self): TestCase.setUp(self) self.tarfile_path = "/tmp/_verify_extract" self.tarfile_name = os.path.join(self.tarfile_path, "test_tarfile.tar") self.custom_processor = CustomUpload() self.custom_processor.tmpdir = self.makeTemporaryDirectory() self.custom_processor.tarfile_path = self.tarfile_name
def extract(self): CustomUpload.extract(self) # We now have a valid unpacked installer directory, but it's one level # deeper than it should be. Move it up and remove the debris. unpack_dir = 'installer-%s' % self.arch os.rename(os.path.join(self.tmpdir, unpack_dir, self.version), os.path.join(self.tmpdir, self.version)) shutil.rmtree(os.path.join(self.tmpdir, unpack_dir))
def test_sign_with_signing_key(self): filename = os.path.join(getPubConfig(self.archive).archiveroot, "file") write_file(filename, "contents") self.assertIsNone(self.archive.signing_key) self.useFixture(InProcessKeyServerFixture()).start() key_path = os.path.join(gpgkeysdir, '*****@*****.**') yield IArchiveSigningKey(self.archive).setSigningKey( key_path, async_keyserver=True) self.assertIsNotNone(self.archive.signing_key) custom_processor = CustomUpload() custom_processor.sign(self.archive, "suite", filename) with open(filename) as cleartext_file: cleartext = cleartext_file.read() with open("%s.gpg" % filename) as signature_file: signature = getUtility(IGPGHandler).getVerifiedSignature( cleartext, signature_file.read()) self.assertEqual(self.archive.signing_key.fingerprint, signature.fingerprint)
def test_sign_with_external_run_parts(self): self.enableRunParts(distribution_name=self.distro.name) archiveroot = getPubConfig(self.archive).archiveroot filename = os.path.join(archiveroot, "file") write_file(filename, "contents") self.assertIsNone(self.archive.signing_key) run_parts_fixture = self.useFixture( MonkeyPatch("lp.archivepublisher.archivesigningkey.run_parts", FakeMethod())) custom_processor = CustomUpload() custom_processor.sign(self.archive, "suite", filename) args, kwargs = run_parts_fixture.new_value.calls[0] self.assertEqual((self.distro.name, "sign.d"), args) self.assertThat( kwargs["env"], MatchesDict({ "ARCHIVEROOT": Equals(archiveroot), "INPUT_PATH": Equals(filename), "OUTPUT_PATH": Equals("%s.gpg" % filename), "MODE": Equals("detached"), "DISTRIBUTION": Equals(self.distro.name), "SUITE": Equals("suite"), }))
def testFixCurrentSymlink(self): """Test `CustomUpload.fixCurrentSymlink` behaviour. Ensure only 3 entries named as valid versions are kept around and the 'current' symbolic link is created (or updated) to point to the latests entry. Also check if it copes with entries not named as valid versions and leave them alone. """ # Setup a bogus `CustomUpload` object with the 'targetdir' pointing # to the directory created for the test. custom_processor = CustomUpload() custom_processor.targetdir = self.test_dir # Let's create 4 entries named as valid versions. os.mkdir(os.path.join(self.test_dir, '1.0')) os.mkdir(os.path.join(self.test_dir, '1.1')) os.mkdir(os.path.join(self.test_dir, '1.2')) os.mkdir(os.path.join(self.test_dir, '1.3')) self.assertEntries(['1.0', '1.1', '1.2', '1.3']) # `fixCurrentSymlink` will keep only the latest 3 and create a # 'current' symbolic link the highest one. custom_processor.fixCurrentSymlink() self.assertEntries(['1.1', '1.2', '1.3', 'current']) self.assertEqual('1.3', os.readlink(os.path.join(self.test_dir, 'current'))) # When there is a invalid version present in the directory it is # ignored, since it was probably put there manually. The symbolic # link still pointing to the latest version. os.mkdir(os.path.join(self.test_dir, '1.4')) os.mkdir(os.path.join(self.test_dir, 'alpha-5')) custom_processor.fixCurrentSymlink() self.assertEntries(['1.2', '1.3', '1.4', 'alpha-5', 'current']) self.assertEqual('1.4', os.readlink(os.path.join(self.test_dir, 'current')))
def testFixCurrentSymlink(self): """Test `CustomUpload.fixCurrentSymlink` behaviour. Ensure only 3 entries named as valid versions are kept around and the 'current' symbolic link is created (or updated) to point to the latests entry. Also check if it copes with entries not named as valid versions and leave them alone. """ # Setup a bogus `CustomUpload` object with the 'targetdir' pointing # to the directory created for the test. custom_processor = CustomUpload() custom_processor.targetdir = self.test_dir # Let's create 4 entries named as valid versions. os.mkdir(os.path.join(self.test_dir, '1.0')) os.mkdir(os.path.join(self.test_dir, '1.1')) os.mkdir(os.path.join(self.test_dir, '1.2')) os.mkdir(os.path.join(self.test_dir, '1.3')) self.assertEntries(['1.0', '1.1', '1.2', '1.3']) # `fixCurrentSymlink` will keep only the latest 3 and create a # 'current' symbolic link the highest one. custom_processor.fixCurrentSymlink() self.assertEntries(['1.1', '1.2', '1.3', 'current']) self.assertEqual( '1.3', os.readlink(os.path.join(self.test_dir, 'current'))) # When there is a invalid version present in the directory it is # ignored, since it was probably put there manually. The symbolic # link still pointing to the latest version. os.mkdir(os.path.join(self.test_dir, '1.4')) os.mkdir(os.path.join(self.test_dir, 'alpha-5')) custom_processor.fixCurrentSymlink() self.assertEntries(['1.2', '1.3', '1.4', 'alpha-5', 'current']) self.assertEqual( '1.4', os.readlink(os.path.join(self.test_dir, 'current')))
def test_sign_without_signing_key(self): filename = os.path.join(getPubConfig(self.archive).archiveroot, "file") self.assertIsNone(self.archive.signing_key) custom_processor = CustomUpload() custom_processor.sign(self.archive, "suite", filename) self.assertThat("%s.gpg" % filename, Not(PathExists()))
class TestTarfileVerification(TestCase): def setUp(self): TestCase.setUp(self) self.tarfile_path = "/tmp/_verify_extract" self.tarfile_name = os.path.join(self.tarfile_path, "test_tarfile.tar") self.custom_processor = CustomUpload() self.custom_processor.tmpdir = self.makeTemporaryDirectory() self.custom_processor.tarfile_path = self.tarfile_name def createTarfile(self): self.tar_fileobj = cStringIO.StringIO() tar_file = tarfile.open(name=None, mode="w", fileobj=self.tar_fileobj) root_info = tarfile.TarInfo(name='./') root_info.type = tarfile.DIRTYPE tar_file.addfile(root_info) # Ordering matters here, addCleanup pushes onto a stack which is # popped in reverse order. self.addCleanup(self.tar_fileobj.close) self.addCleanup(tar_file.close) return tar_file def createSymlinkInfo(self, target, name="i_am_a_symlink"): info = tarfile.TarInfo(name=name) info.type = tarfile.SYMTYPE info.linkname = target return info def createTarfileWithSymlink(self, target): info = self.createSymlinkInfo(target) tar_file = self.createTarfile() tar_file.addfile(info) return tar_file def createTarfileWithFile(self, file_type, name="testfile"): info = tarfile.TarInfo(name=name) info.type = file_type tar_file = self.createTarfile() tar_file.addfile(info) return tar_file def assertFails(self, exception, tar_file): self.assertRaises(exception, self.custom_processor.verifyBeforeExtracting, tar_file) def assertPasses(self, tar_file): result = self.custom_processor.verifyBeforeExtracting(tar_file) self.assertTrue(result) def testFailsToExtractBadSymlink(self): """Fail if a symlink's target is outside the tmp tree.""" tar_file = self.createTarfileWithSymlink(target="/etc/passwd") self.assertFails(CustomUploadTarballBadSymLink, tar_file) def testFailsToExtractBadRelativeSymlink(self): """Fail if a symlink's relative target is outside the tmp tree.""" tar_file = self.createTarfileWithSymlink(target="../outside") self.assertFails(CustomUploadTarballBadSymLink, tar_file) def testFailsToExtractBadFileType(self): """Fail if a file in a tarfile is not a regular file or a symlink.""" tar_file = self.createTarfileWithFile(tarfile.FIFOTYPE) self.assertFails(CustomUploadTarballInvalidFileType, tar_file) def testFailsToExtractBadFileLocation(self): """Fail if the file resolves to a path outside the tmp tree.""" tar_file = self.createTarfileWithFile(tarfile.REGTYPE, "../outside") self.assertFails(CustomUploadTarballBadFile, tar_file) def testFailsToExtractBadAbsoluteFileLocation(self): """Fail if the file resolves to a path outside the tmp tree.""" tar_file = self.createTarfileWithFile(tarfile.REGTYPE, "/etc/passwd") self.assertFails(CustomUploadTarballBadFile, tar_file) def testRegularFileDoesntRaise(self): """Adding a normal file should pass inspection.""" tar_file = self.createTarfileWithFile(tarfile.REGTYPE) self.assertPasses(tar_file) def testDirectoryDoesntRaise(self): """Adding a directory should pass inspection.""" tar_file = self.createTarfileWithFile(tarfile.DIRTYPE) self.assertPasses(tar_file) def testSymlinkDoesntRaise(self): """Adding a symlink should pass inspection.""" tar_file = self.createTarfileWithSymlink(target="something/blah") self.assertPasses(tar_file) def testRelativeSymlinkToRootDoesntRaise(self): tar_file = self.createTarfileWithSymlink(target=".") self.assertPasses(tar_file) def testRelativeSymlinkTargetInsideDirectoryDoesntRaise(self): tar_file = self.createTarfileWithFile(tarfile.DIRTYPE, name="testdir") info = self.createSymlinkInfo(name="testdir/symlink", target="../dummy") tar_file.addfile(info) self.assertPasses(tar_file) def test_extract(self): """Test that the extract method calls the verify function. This test is different from the previous tests in that it actually pokes a fake tar file on disk. This is slower, so it's only done once, here. """ # Make a bad tarfile and poke it into the custom processor. self.custom_processor.tmpdir = None try: os.makedirs(self.tarfile_path) tar_file = tarfile.open(self.tarfile_name, mode="w") info = tarfile.TarInfo("test_file") info.type = tarfile.FIFOTYPE tar_file.addfile(info) tar_file.close() self.assertRaises(CustomUploadTarballInvalidFileType, self.custom_processor.extract) finally: shutil.rmtree(self.tarfile_path)
class TestTarfileVerification(TestCase): def setUp(self): TestCase.setUp(self) self.tarfile_path = "/tmp/_verify_extract" self.tarfile_name = os.path.join(self.tarfile_path, "test_tarfile.tar") self.custom_processor = CustomUpload() self.custom_processor.tmpdir = self.makeTemporaryDirectory() self.custom_processor.tarfile_path = self.tarfile_name def createTarfile(self): self.tar_fileobj = cStringIO.StringIO() tar_file = tarfile.open(name=None, mode="w", fileobj=self.tar_fileobj) root_info = tarfile.TarInfo(name='./') root_info.type = tarfile.DIRTYPE tar_file.addfile(root_info) # Ordering matters here, addCleanup pushes onto a stack which is # popped in reverse order. self.addCleanup(self.tar_fileobj.close) self.addCleanup(tar_file.close) return tar_file def createSymlinkInfo(self, target, name="i_am_a_symlink"): info = tarfile.TarInfo(name=name) info.type = tarfile.SYMTYPE info.linkname = target return info def createTarfileWithSymlink(self, target): info = self.createSymlinkInfo(target) tar_file = self.createTarfile() tar_file.addfile(info) return tar_file def createTarfileWithFile(self, file_type, name="testfile"): info = tarfile.TarInfo(name=name) info.type = file_type tar_file = self.createTarfile() tar_file.addfile(info) return tar_file def assertFails(self, exception, tar_file): self.assertRaises( exception, self.custom_processor.verifyBeforeExtracting, tar_file) def assertPasses(self, tar_file): result = self.custom_processor.verifyBeforeExtracting(tar_file) self.assertTrue(result) def testFailsToExtractBadSymlink(self): """Fail if a symlink's target is outside the tmp tree.""" tar_file = self.createTarfileWithSymlink(target="/etc/passwd") self.assertFails(CustomUploadTarballBadSymLink, tar_file) def testFailsToExtractBadRelativeSymlink(self): """Fail if a symlink's relative target is outside the tmp tree.""" tar_file = self.createTarfileWithSymlink(target="../outside") self.assertFails(CustomUploadTarballBadSymLink, tar_file) def testFailsToExtractBadFileType(self): """Fail if a file in a tarfile is not a regular file or a symlink.""" tar_file = self.createTarfileWithFile(tarfile.FIFOTYPE) self.assertFails(CustomUploadTarballInvalidFileType, tar_file) def testFailsToExtractBadFileLocation(self): """Fail if the file resolves to a path outside the tmp tree.""" tar_file = self.createTarfileWithFile(tarfile.REGTYPE, "../outside") self.assertFails(CustomUploadTarballBadFile, tar_file) def testFailsToExtractBadAbsoluteFileLocation(self): """Fail if the file resolves to a path outside the tmp tree.""" tar_file = self.createTarfileWithFile(tarfile.REGTYPE, "/etc/passwd") self.assertFails(CustomUploadTarballBadFile, tar_file) def testRegularFileDoesntRaise(self): """Adding a normal file should pass inspection.""" tar_file = self.createTarfileWithFile(tarfile.REGTYPE) self.assertPasses(tar_file) def testDirectoryDoesntRaise(self): """Adding a directory should pass inspection.""" tar_file = self.createTarfileWithFile(tarfile.DIRTYPE) self.assertPasses(tar_file) def testSymlinkDoesntRaise(self): """Adding a symlink should pass inspection.""" tar_file = self.createTarfileWithSymlink(target="something/blah") self.assertPasses(tar_file) def testRelativeSymlinkToRootDoesntRaise(self): tar_file = self.createTarfileWithSymlink(target=".") self.assertPasses(tar_file) def testRelativeSymlinkTargetInsideDirectoryDoesntRaise(self): tar_file = self.createTarfileWithFile( tarfile.DIRTYPE, name="testdir") info = self.createSymlinkInfo( name="testdir/symlink", target="../dummy") tar_file.addfile(info) self.assertPasses(tar_file) def test_extract(self): """Test that the extract method calls the verify function. This test is different from the previous tests in that it actually pokes a fake tar file on disk. This is slower, so it's only done once, here. """ # Make a bad tarfile and poke it into the custom processor. self.custom_processor.tmpdir = None try: os.makedirs(self.tarfile_path) tar_file = tarfile.open(self.tarfile_name, mode="w") info = tarfile.TarInfo("test_file") info.type = tarfile.FIFOTYPE tar_file.addfile(info) tar_file.close() self.assertRaises( CustomUploadTarballInvalidFileType, self.custom_processor.extract) finally: shutil.rmtree(self.tarfile_path)