export/securedrop_export/disk/service.py (54 lines of code) (raw):

import logging from securedrop_export.archive import Archive from securedrop_export.exceptions import ExportException from .cli import CLI from .status import Status from .volume import MountedVolume, Volume logger = logging.getLogger(__name__) class Service: """ Actions that can be performed against USB device(s). This is the "API" portion of the export workflow. """ def __init__(self, submission: Archive, cli: CLI = CLI()): self.cli = cli self.submission = submission def scan_all_devices(self) -> Status: """ Check all connected devices and return current device status. """ try: volume = self.cli.get_volume() if isinstance(volume, MountedVolume): return Status.DEVICE_WRITABLE elif isinstance(volume, Volume): return Status.DEVICE_LOCKED else: # Above will return MountedVolume, Volume, or raise error; # this shouldn't be reachable raise ExportException(sdstatus=Status.DEVICE_ERROR) except ExportException as ex: logger.debug(ex) status = ex.sdstatus if ex.sdstatus is not None else Status.DEVICE_ERROR logger.error(f"Encountered {status.value} while checking volumes") return status def export(self) -> Status: """ Export material to USB drive. """ try: volume = self.cli.get_volume() if isinstance(volume, MountedVolume): logger.debug("Mounted volume detected, exporting files") self.cli.write_data_to_device( volume, self.submission.tmpdir, self.submission.target_dirname ) return Status.SUCCESS_EXPORT elif isinstance(volume, Volume): if self.submission.encryption_key is not None: logger.debug("Volume is locked, try unlocking") mv = self.cli.unlock_volume(volume, self.submission.encryption_key) if isinstance(mv, MountedVolume): logger.debug("Export to device") # Exports then locks the drive. # If the export succeeds but the drive is in use, will raise # exception. self.cli.write_data_to_device( mv, self.submission.tmpdir, self.submission.target_dirname ) return Status.SUCCESS_EXPORT else: raise ExportException(sdstatus=Status.ERROR_UNLOCK_GENERIC) else: logger.info("Volume is locked and no key has been provided") return Status.DEVICE_LOCKED except ExportException as ex: logger.debug(ex) status = ex.sdstatus if ex.sdstatus is not None else Status.ERROR_EXPORT logger.error(f"Enountered {status.value} while trying to export") return status