Example #1
0
def test_MetadataSyncJob_success_with_missing_key(mocker, homedir, session,
                                                  session_maker):
    """
    Check that we can gracefully handle missing source keys.
    """
    gpg = GpgHelper(homedir, session_maker, is_qubes=False)
    job = MetadataSyncJob(homedir, gpg)

    mock_source = factory.RemoteSource(key={
        'type': 'PGP',
        'public': '',
        'fingerprint': '',
    })

    mock_key_import = mocker.patch.object(job.gpg, 'import_key')
    mock_get_remote_data = mocker.patch(
        'securedrop_client.api_jobs.sync.get_remote_data',
        return_value=([mock_source], [], []))

    api_client = mocker.MagicMock()
    api_client.default_request_timeout = mocker.MagicMock()

    job.call_api(api_client, session)

    assert mock_key_import.call_count == 0
    assert mock_get_remote_data.call_count == 1
Example #2
0
    def __init__(
        self,
        api_client: API,
        session_maker: scoped_session,
        gpg: GpgHelper,
        data_dir: str,
        sync_started: pyqtSignal,
        on_sync_success,
        on_sync_failure,
    ):
        super().__init__()

        self.api_client = api_client
        self.session_maker = session_maker
        self.gpg = gpg
        self.data_dir = data_dir
        self.sync_started = sync_started
        self.on_sync_success = on_sync_success
        self.on_sync_failure = on_sync_failure

        self.job = MetadataSyncJob(self.data_dir)
        self.job.success_signal.connect(self.on_sync_success,
                                        type=Qt.QueuedConnection)
        self.job.failure_signal.connect(self.on_sync_failure,
                                        type=Qt.QueuedConnection)
Example #3
0
def test_MetadataSyncJob_success_with_key_import_fail(mocker, homedir, session,
                                                      session_maker):
    """
    Check that we can gracefully handle a key import failure.
    """
    gpg = GpgHelper(homedir, session_maker, is_qubes=False)
    job = MetadataSyncJob(homedir, gpg)

    mock_source = factory.RemoteSource(key={
        'type': 'PGP',
        'public': PUB_KEY,
        'fingerprint': '123456ABC',
    })

    mock_key_import = mocker.patch.object(job.gpg,
                                          'import_key',
                                          side_effect=CryptoError)
    mock_get_remote_data = mocker.patch(
        'securedrop_client.api_jobs.sync.get_remote_data',
        return_value=([mock_source], [], []))

    api_client = mocker.MagicMock()
    api_client.default_request_timeout = mocker.MagicMock()

    job.call_api(api_client, session)

    assert mock_key_import.call_args[0][0] == mock_source.uuid
    assert mock_key_import.call_args[0][1] == mock_source.key['public']
    assert mock_key_import.call_args[0][2] == mock_source.key['fingerprint']
    assert mock_get_remote_data.call_count == 1
Example #4
0
class ApiSyncBackgroundTask(QObject):
    """
    ApiSyncBackgroundTask provides a sync method that executes a MetadataSyncJob.
    """
    def __init__(
        self,
        api_client: API,
        session_maker: scoped_session,
        gpg: GpgHelper,
        data_dir: str,
        sync_started: pyqtSignal,
        on_sync_success,
        on_sync_failure,
    ):
        super().__init__()

        self.api_client = api_client
        self.session_maker = session_maker
        self.gpg = gpg
        self.data_dir = data_dir
        self.sync_started = sync_started
        self.on_sync_success = on_sync_success
        self.on_sync_failure = on_sync_failure

        self.job = MetadataSyncJob(self.data_dir)
        self.job.success_signal.connect(self.on_sync_success,
                                        type=Qt.QueuedConnection)
        self.job.failure_signal.connect(self.on_sync_failure,
                                        type=Qt.QueuedConnection)

    def sync(self) -> None:
        """
        Create and run a new MetadataSyncJob.
        """
        try:
            self.sync_started.emit()
            session = self.session_maker()
            self.job.remaining_attempts = 2
            self.job._do_call_api(self.api_client, session)
        except ApiInaccessibleError as e:
            self.job.failure_signal.emit(
                e)  # the job's failure signal is not emitted in base
        except Exception:
            pass  # the job's failure signal is emitted for everything else in base
        finally:
            session.close()
Example #5
0
def test_MetadataSyncJob_success(mocker, homedir, session, session_maker):
    job = MetadataSyncJob(homedir)

    mock_source = factory.RemoteSource(key={
        "type": "PGP",
        "public": PUB_KEY,
        "fingerprint": "123456ABC"
    })

    mock_get_remote_data = mocker.patch(
        "securedrop_client.api_jobs.sync.get_remote_data",
        return_value=([mock_source], [], []))

    api_client = mocker.MagicMock()
    api_client.default_request_timeout = mocker.MagicMock()
    api_client.default_request_timeout = mocker.MagicMock()

    job.call_api(api_client, session)

    assert mock_get_remote_data.call_count == 1
Example #6
0
def test_MetadataSyncJob_success_with_missing_key(mocker, homedir, session,
                                                  session_maker):
    """
    Check that we can gracefully handle missing source keys.
    """
    job = MetadataSyncJob(homedir)

    mock_source = factory.RemoteSource(key={
        "type": "PGP",
        "public": "",
        "fingerprint": ""
    })

    mock_get_remote_data = mocker.patch(
        "securedrop_client.api_jobs.sync.get_remote_data",
        return_value=([mock_source], [], []))

    api_client = mocker.MagicMock()
    api_client.default_request_timeout = mocker.MagicMock()

    job.call_api(api_client, session)

    assert mock_get_remote_data.call_count == 1
Example #7
0
def test_MetadataSyncJob_only_import_new_source_keys(mocker, homedir, session,
                                                     session_maker):
    """
    Verify that we only import source keys we don't already have.
    """
    gpg = GpgHelper(homedir, session_maker, is_qubes=False)
    job = MetadataSyncJob(homedir, gpg)

    mock_source = factory.RemoteSource(key={
        'type': 'PGP',
        'public': PUB_KEY,
        'fingerprint': '123456ABC',
    })

    mock_get_remote_data = mocker.patch(
        'securedrop_client.api_jobs.sync.get_remote_data',
        return_value=([mock_source], [], []))

    api_client = mocker.MagicMock()
    api_client.default_request_timeout = mocker.MagicMock()

    crypto_logger = mocker.patch('securedrop_client.crypto.logger')
    storage_logger = mocker.patch('securedrop_client.storage.logger')

    job.call_api(api_client, session)

    assert mock_get_remote_data.call_count == 1

    log_msg = crypto_logger.debug.call_args_list[0][0]
    assert log_msg == ('Importing key with fingerprint %s',
                       mock_source.key['fingerprint'])

    job.call_api(api_client, session)

    assert mock_get_remote_data.call_count == 2

    log_msg = storage_logger.debug.call_args_list[1][0][0]
    assert log_msg == 'Source key data is unchanged'