コード例 #1
0
    async def workspace_continue_reencryption(self, workspace_id: EntryID) -> ReencryptionJob:
        """
        Raises:
            FSError
            FSBackendOfflineError
            FSWorkspaceNoAccess
            FSWorkspaceNotFoundError
        """
        user_manifest = self.get_user_manifest()
        workspace_entry = user_manifest.get_workspace_entry(workspace_id)
        if not workspace_entry:
            raise FSWorkspaceNotFoundError(f"Unknown workspace `{workspace_id}`")

        # First make sure the workspace is under maintenance
        try:
            rep = await self.backend_cmds.realm_status(workspace_entry.id)

        except BackendNotAvailable as exc:
            raise FSBackendOfflineError(str(exc)) from exc

        except BackendConnectionError as exc:
            raise FSError(
                f"Cannot continue maintenance on workspace {workspace_id}: {exc}"
            ) from exc

        if rep["status"] == "not_allowed":
            raise FSWorkspaceNoAccess(f"Not allowed to access workspace {workspace_id}: {rep}")
        elif rep["status"] != "ok":
            raise FSError(f"Error while getting status for workspace {workspace_id}: {rep}")

        if not rep["in_maintenance"] or rep["maintenance_type"] != MaintenanceType.REENCRYPTION:
            raise FSWorkspaceNotInMaintenance("Not in reencryption maintenance")
        current_encryption_revision = rep["encryption_revision"]
        if rep["encryption_revision"] != workspace_entry.encryption_revision:
            raise FSError("Bad encryption revision")

        # Must retrieve the previous encryption revision's key
        version_to_fetch = None
        while True:
            previous_user_manifest = await self._fetch_remote_user_manifest(
                version=version_to_fetch
            )
            previous_workspace_entry = previous_user_manifest.get_workspace_entry(
                workspace_entry.id
            )
            if not previous_workspace_entry:
                raise FSError(
                    f"Never had access to encryption revision {current_encryption_revision - 1}"
                )

            if previous_workspace_entry.encryption_revision == current_encryption_revision - 1:
                break
            else:
                version_to_fetch = previous_user_manifest.version - 1

        return ReencryptionJob(self.backend_cmds, workspace_entry, previous_workspace_entry)
コード例 #2
0
ファイル: userfs.py プロジェクト: Scille/parsec-cloud
    async def _send_start_reencryption_cmd(
        self,
        workspace_id: EntryID,
        encryption_revision: int,
        timestamp: DateTime,
        per_user_ciphered_msgs: Dict[UserID, bytes],
    ) -> bool:
        """
        Raises:
            FSError
            FSBackendOfflineError
            FSWorkspaceNoAccess
            BackendCmdsParticipantsMismatchError
        """
        # Finally send command to the backend
        try:
            rep = await self.backend_cmds.realm_start_reencryption_maintenance(
                RealmID(workspace_id.uuid), encryption_revision, timestamp,
                per_user_ciphered_msgs)

        except BackendNotAvailable as exc:
            raise FSBackendOfflineError(str(exc)) from exc

        except BackendConnectionError as exc:
            raise FSError(
                f"Cannot start maintenance on workspace {workspace_id}: {exc}"
            ) from exc

        if rep["status"] == "participants_mismatch":
            # Catched by caller
            return False
        elif rep["status"] == "in_maintenance":
            raise FSWorkspaceInMaintenance(
                f"Workspace {workspace_id} already in maintenance: {rep}")
        elif rep["status"] == "not_allowed":
            raise FSWorkspaceNoAccess(
                f"Not allowed to start maintenance on workspace {workspace_id}: {rep}"
            )
        elif rep["status"] != "ok":
            raise FSError(
                f"Cannot start maintenance on workspace {workspace_id}: {rep}")
        return True
コード例 #3
0
ファイル: userfs.py プロジェクト: anthrax3/parsec-cloud
    async def do_one_batch(self, size=100) -> Tuple[int, int]:
        """
        Raises:
            FSError
            FSBackendOfflineError
            FSWorkspaceInMaintenance
            FSWorkspaceNoAccess
        """
        workspace_id = self.new_workspace_entry.id
        new_encryption_revision = self.new_workspace_entry.encryption_revision

        # Get the batch
        try:
            rep = await self.backend_cmds.vlob_maintenance_get_reencryption_batch(
                workspace_id, new_encryption_revision, size
            )
            if rep["status"] in ("not_in_maintenance", "bad_encryption_revision"):
                raise FSWorkspaceNotInMaintenance(f"Reencryption job already finished: {rep}")
            elif rep["status"] == "not_allowed":
                raise FSWorkspaceNoAccess(
                    f"Not allowed to do reencryption maintenance on workspace {workspace_id}: {rep}"
                )
            elif rep["status"] != "ok":
                raise FSError(
                    f"Cannot do reencryption maintenance on workspace {workspace_id}: {rep}"
                )

            donebatch = []
            for item in rep["batch"]:
                cleartext = self.old_workspace_entry.key.decrypt(item["blob"])
                newciphered = self.new_workspace_entry.key.encrypt(cleartext)
                donebatch.append((item["vlob_id"], item["version"], newciphered))

            rep = await self.backend_cmds.vlob_maintenance_save_reencryption_batch(
                workspace_id, new_encryption_revision, donebatch
            )
            if rep["status"] in ("not_in_maintenance", "bad_encryption_revision"):
                raise FSWorkspaceNotInMaintenance(f"Reencryption job already finished: {rep}")
            elif rep["status"] == "not_allowed":
                raise FSWorkspaceNoAccess(
                    f"Not allowed to do reencryption maintenance on workspace {workspace_id}: {rep}"
                )
            elif rep["status"] != "ok":
                raise FSError(
                    f"Cannot do reencryption maintenance on workspace {workspace_id}: {rep}"
                )
            total = rep["total"]
            done = rep["done"]

            if total == done:
                # Finish the maintenance
                rep = await self.backend_cmds.realm_finish_reencryption_maintenance(
                    workspace_id, new_encryption_revision
                )
                if rep["status"] in ("not_in_maintenance", "bad_encryption_revision"):
                    raise FSWorkspaceNotInMaintenance(f"Reencryption job already finished: {rep}")
                elif rep["status"] == "not_allowed":
                    raise FSWorkspaceNoAccess(
                        f"Not allowed to do reencryption maintenance on workspace {workspace_id}: {rep}"
                    )
                elif rep["status"] != "ok":
                    raise FSError(
                        f"Cannot do reencryption maintenance on workspace {workspace_id}: {rep}"
                    )

        except BackendNotAvailable as exc:
            raise FSBackendOfflineError(str(exc)) from exc

        except BackendConnectionError as exc:
            raise FSError(
                f"Cannot do reencryption maintenance on workspace {workspace_id}: {exc}"
            ) from exc

        return total, done