Exemple #1
0
    def test_assert_methods(self):
        requestor_keys = self._fake_keys()
        provider_keys = self._fake_keys()
        concent_keys = self._fake_keys()

        rct = msg_factories.tasks.ReportComputedTaskFactory()

        dump(rct, provider_keys.raw_privkey, requestor_keys.raw_pubkey)

        stored_rct = pickle.loads(pickle.dumps(rct))

        frct_concent = message.concents.ForceReportComputedTask(
            report_computed_task=rct)

        frct_concent_data = dump(frct_concent, provider_keys.raw_privkey,
                                 concent_keys.raw_pubkey)

        stored_frct = pickle.loads(pickle.dumps(frct_concent))

        frct_concent_rcv = load(frct_concent_data, concent_keys.raw_privkey,
                                provider_keys.raw_pubkey)

        concent_rct = frct_concent_rcv.report_computed_task

        frct_requestor = message.concents.ForceReportComputedTask(
            report_computed_task=concent_rct)
        frct_requestor_data = dump(frct_requestor, concent_keys.raw_privkey,
                                   requestor_keys.raw_pubkey)
        frct_requestor_rcv = load(frct_requestor_data,
                                  requestor_keys.raw_privkey,
                                  concent_keys.raw_pubkey)

        self.assertEqual(frct_requestor_rcv.report_computed_task, stored_rct)
        self.assertNotEqual(frct_requestor_rcv, stored_frct)
        self.assertSamePayload(frct_requestor_rcv, stored_frct)
Exemple #2
0
    def test_message_sig(self):
        """Signed message inside a signed message"""

        concent_keys = cryptography.ECCx(None)
        provider_keys = cryptography.ECCx(None)
        requestor_keys = cryptography.ECCx(None)

        report_computed_task = factories.tasks.ReportComputedTaskFactory()

        # Dump TaskToCompute to make it signed
        s_rct = shortcuts.dump(
            report_computed_task,
            requestor_keys.raw_privkey,
            provider_keys.raw_pubkey,
        )

        # Load TaskToCompute back to its original format
        # Task TaskToCompute is verified correctly
        report_computed_task = shortcuts.load(
            s_rct,
            provider_keys.raw_privkey,
            requestor_keys.raw_pubkey,
        )

        first_sig = report_computed_task.sig
        first_hash = report_computed_task.get_short_hash()

        force_report = message.ForceReportComputedTask()
        force_report.report_computed_task = report_computed_task

        s_force_report = shortcuts.dump(
            force_report,
            provider_keys.raw_privkey,
            concent_keys.raw_pubkey,
        )

        force_report = shortcuts.load(
            s_force_report,
            concent_keys.raw_privkey,
            provider_keys.raw_pubkey,
        )

        second_sig = force_report.report_computed_task.sig
        second_hash = force_report.report_computed_task.get_short_hash()

        self.assertEqual(first_sig, second_sig)
        self.assertEqual(first_hash, second_hash)

        # Now, attached TaskToCompute should still be verified using
        # original key. ecdsa_verify will raise InvalidSignature on
        # failure.
        cryptography.ecdsa_verify(
            requestor_keys.raw_pubkey,
            force_report.report_computed_task.sig,
            force_report.report_computed_task.get_short_hash(),
        )
    def test_validation(self):
        for key in ('nonce', 'gasprice', 'startgas', 'value', 'r', 's'):
            invalid_message_instance = self.FACTORY(**{key: '1' * 79})
            serialized_message = dump(invalid_message_instance, None, None)
            with self.assertRaises(FieldError):
                load(serialized_message, None, None)

        invalid_message_instance = self.FACTORY(v='1' * 4)
        serialized_message = dump(invalid_message_instance, None, None)
        with self.assertRaises(FieldError):
            load(serialized_message, None, None)
Exemple #4
0
    def test_send_should_return_http_200_if_message_timeout(self):
        assert StoredMessage.objects.count() == 0

        task_to_compute = self.task_to_compute
        task_to_compute.compute_task_def[
            'deadline'] = self.message_timestamp - 1  # pylint: disable=no-member
        task_to_compute.sig = None
        task_to_compute = self._sign_message(task_to_compute)
        report_computed_task = self._get_deserialized_report_computed_task(
            task_to_compute=task_to_compute)
        correct_golem_data = self._get_deserialized_force_report_computed_task(
            report_computed_task=report_computed_task)

        response = self.client.post(
            reverse('core:send'),
            data=dump(correct_golem_data, self.PROVIDER_PRIVATE_KEY,
                      CONCENT_PUBLIC_KEY),
            content_type='application/octet-stream',
        )

        self.assertEqual(response.status_code, 200)
        response_message = load(
            response.content,
            self.PROVIDER_PRIVATE_KEY,
            CONCENT_PUBLIC_KEY,
        )
        self.assertIsInstance(response_message,
                              message.concents.ForceReportComputedTaskResponse)
    def test_load_without_public_key_should_load_message(self):
        """
        Test that message loaded with load_without_public_key function will be the same as load
        with golem_messages load function.
        """

        # Create and fill some data into ComputeTaskDef
        compute_task_def = tasks.ComputeTaskDefFactory(
            task_id=generate_uuid_for_tests(),
            subtask_id=generate_uuid_for_tests(),
            deadline=1510912800,
        )

        # Create TaskToCompute
        task_to_compute = tasks.TaskToComputeFactory(
            compute_task_def = compute_task_def,
            price=0,
        )

        # Dump TaskToCompute to make it signed
        dumped_task_to_compute = dump(task_to_compute, REQUESTOR_PRIVATE_KEY, CONCENT_PUBLIC_KEY)

        loaded_task_to_compute_with_utility_function    = load_without_public_key(
            dumped_task_to_compute,
            REQUESTOR_PUBLIC_KEY,
        )

        loaded_task_to_compute_with_golem_messages_load = load(
            dumped_task_to_compute,
            CONCENT_PRIVATE_KEY,
            REQUESTOR_PUBLIC_KEY,
        )

        self.assertEqual(loaded_task_to_compute_with_utility_function, loaded_task_to_compute_with_golem_messages_load)
Exemple #6
0
    def test_send_should_return_http_200_if_message_timeout(self):
        assert StoredMessage.objects.count() == 0

        task_to_compute = self._get_deserialized_task_to_compute(
            deadline=self.message_timestamp - 1
        )
        report_computed_task = self._get_deserialized_report_computed_task(
            task_to_compute=task_to_compute
        )
        correct_golem_data = self._get_deserialized_force_report_computed_task(
            report_computed_task=report_computed_task
        )

        response = self.send_request(
            url='core:send',
            data=dump(
                correct_golem_data,
                self.PROVIDER_PRIVATE_KEY,
                CONCENT_PUBLIC_KEY),
        )

        self.assertEqual(response.status_code, 200)
        response_message = load(
            response.content,
            self.PROVIDER_PRIVATE_KEY,
            CONCENT_PUBLIC_KEY,
        )
        self.assertIsInstance(response_message, message.concents.ForceReportComputedTaskResponse)
        self.assertEqual(response_message.reason,
                         message.concents.ForceReportComputedTaskResponse.REASON.SubtaskTimeout)
Exemple #7
0
    def test_send_should_return_http_400_if_task_to_compute_deadline_exceeded(self):
        compute_task_def = message.ComputeTaskDef()
        compute_task_def['task_id'] = '8'
        compute_task_def['deadline'] = self.message_timestamp - 9000

        with freeze_time(datetime.datetime.fromtimestamp(self.message_timestamp - 10000)):
            task_to_compute = tasks.TaskToComputeFactory(
                compute_task_def     = self.compute_task_def,
                provider_public_key  = PROVIDER_PUBLIC_KEY,
                requestor_public_key = REQUESTOR_PUBLIC_KEY,
                price=0,
            )

        serialized_task_to_compute      = dump(task_to_compute,             REQUESTOR_PRIVATE_KEY,   PROVIDER_PUBLIC_KEY)
        deserialized_task_to_compute    = load(serialized_task_to_compute,  PROVIDER_PRIVATE_KEY,  REQUESTOR_PUBLIC_KEY, check_time = False)

        ack_report_computed_task = message.AckReportComputedTask()
        ack_report_computed_task.report_computed_task = message.ReportComputedTask(
            task_to_compute = deserialized_task_to_compute
        )

        response_400 = self.client.post(
            reverse('core:send'),
            data = dump(
                ack_report_computed_task,
                PROVIDER_PRIVATE_KEY,
                CONCENT_PUBLIC_KEY
            ),
            content_type                    = 'application/octet-stream',
        )

        self._test_400_response(
            response_400,
            error_code=ErrorCode.QUEUE_COMMUNICATION_NOT_STARTED
        )
Exemple #8
0
def receive_all_left_pending_responses(
    host: str,
    endpoint: str,
    client_private_key: bytes,
    client_public_key: bytes,
    concent_public_key: bytes,
    client_name: str,
) -> None:
    url = f"{host}/api/v1/{endpoint}/"
    status_code = 200
    received_messages = []
    while status_code == 200:
        response = requests.post(f"{url}",
                                 headers=REQUEST_HEADERS,
                                 data=create_client_auth_message(
                                     client_private_key, client_public_key,
                                     concent_public_key),
                                 verify=False)
        status_code = response.status_code
        if status_code == 200:
            if isinstance(response.content, bytes) and response.headers[
                    'Content-Type'] == 'application/octet-stream':
                received_messages.append(
                    load(response.content, client_private_key,
                         concent_public_key).__class__.__name__)

    if len(received_messages) > 0:
        print(
            f'Concent had {len(received_messages)} messages which waited for {client_name} to receive. Name of these messages: {received_messages}'
        )
    else:
        print(f'Concent had not any pending messages for {client_name}')
 def test_ethereum_address(self):
     msg = factories.tasks.TaskToComputeFactory()
     serialized = shortcuts.dump(msg, None, None)
     msg_l = shortcuts.load(serialized, None, None)
     for addr_slot in (
             'requestor_ethereum_address',
             'provider_ethereum_address'):
         address = getattr(msg_l, addr_slot)
         self.assertEqual(len(address), 2 + (20*2))
Exemple #10
0
def try_to_decode_golem_message(private_key, public_key, content):
    try:
        decoded_response = load(content,
                                private_key,
                                public_key,
                                check_time=False)
    except MessageError:
        print("Failed to decode a Golem Message.")
        raise
    return decoded_response
Exemple #11
0
    def test_send_should_return_http_400_if_task_to_compute_deadline_is_not_an_integer(self):
        compute_task_def = ComputeTaskDefFactory()

        invalid_values = [
            -11,
            'a11b',
            {},
            [],
            (1, 2, 3),
            None,
        ]

        for deadline in invalid_values:
            StoredMessage.objects.all().delete()
            compute_task_def['deadline'] = deadline
            task_to_compute = tasks.TaskToComputeFactory(
                compute_task_def=compute_task_def,
                provider_public_key=self._get_provider_hex_public_key(),
                requestor_public_key=self._get_requestor_hex_public_key(),
            )

            serialized_task_to_compute = dump(
                task_to_compute,
                self.REQUESTOR_PRIVATE_KEY,
                self.PROVIDER_PUBLIC_KEY,
            )
            deserialized_task_to_compute = load(
                serialized_task_to_compute,
                self.PROVIDER_PRIVATE_KEY,
                self.REQUESTOR_PUBLIC_KEY,
                check_time=False,
            )

            with freeze_time("2017-11-17 10:00:00"):
                force_report_computed_task = message.concents.ForceReportComputedTask(
                    report_computed_task=message.tasks.ReportComputedTask(
                        task_to_compute=deserialized_task_to_compute
                    )
                )

                response_400 = self.send_request(
                    url='core:send',
                    data=dump(
                        force_report_computed_task,
                        self.PROVIDER_PRIVATE_KEY,
                        CONCENT_PUBLIC_KEY
                    ),
                )

            self._test_400_response(response_400)
    def test_validate_that_golem_messages_are_signed_with_key_should_raise_error_if_incorrect_message_and_key_is_used(self):
        task_to_compute = tasks.TaskToComputeFactory()

        dumped_task_to_compute = dump(task_to_compute, CONCENT_PRIVATE_KEY, CONCENT_PUBLIC_KEY)
        task_to_compute = load(dumped_task_to_compute, CONCENT_PRIVATE_KEY, CONCENT_PUBLIC_KEY)

        assert task_to_compute.sig is not None
        assert task_to_compute.SIGN is not False

        with self.assertRaises(Http400):
            validate_that_golem_messages_are_signed_with_key(
                REQUESTOR_PUBLIC_KEY,
                task_to_compute,
            )
    def test_validate_that_golem_messages_are_signed_with_key_should_not_raise_error_if_correct_message_and_key_is_used(self):
        task_to_compute = tasks.TaskToComputeFactory()

        dumped_task_to_compute = dump(task_to_compute, CONCENT_PRIVATE_KEY, CONCENT_PUBLIC_KEY)
        task_to_compute = load(dumped_task_to_compute, CONCENT_PRIVATE_KEY, CONCENT_PUBLIC_KEY)

        assert task_to_compute.sig is not None
        assert task_to_compute.SIGN is not False

        try:
            validate_that_golem_messages_are_signed_with_key(
                CONCENT_PUBLIC_KEY,
                task_to_compute,
            )
        except Http400:
            self.fail()
Exemple #14
0
    def test_send_should_return_http_400_if_task_to_compute_deadline_is_not_an_integer(
            self):
        compute_task_def = message.ComputeTaskDef()
        compute_task_def['task_id'] = '8'
        compute_task_def['subtask_id'] = '8'

        invalid_values = [
            -11,
            'a11b',
            {},
            [],
            (1, 2, 3),
            None,
        ]

        for deadline in invalid_values:
            StoredMessage.objects.all().delete()
            compute_task_def['deadline'] = deadline
            task_to_compute = tasks.TaskToComputeFactory(
                compute_task_def=compute_task_def,
                provider_public_key=PROVIDER_PUBLIC_KEY,
                requestor_public_key=REQUESTOR_PUBLIC_KEY,
                price=0,
            )

            serialized_task_to_compute = dump(task_to_compute,
                                              REQUESTOR_PRIVATE_KEY,
                                              PROVIDER_PUBLIC_KEY)
            deserialized_task_to_compute = load(serialized_task_to_compute,
                                                PROVIDER_PRIVATE_KEY,
                                                REQUESTOR_PUBLIC_KEY,
                                                check_time=False)

            with freeze_time("2017-11-17 10:00:00"):
                force_report_computed_task = message.ForceReportComputedTask(
                    report_computed_task=message.tasks.ReportComputedTask(
                        task_to_compute=deserialized_task_to_compute))

                response_400 = self.client.post(
                    reverse('core:send'),
                    data=dump(force_report_computed_task, PROVIDER_PRIVATE_KEY,
                              CONCENT_PUBLIC_KEY),
                    content_type='application/octet-stream',
                )

            self._test_400_response(response_400)
Exemple #15
0
 def _exchange_message(self, priv_key, cluster_url, data):
     headers = {
         'Content-Type': 'application/octet-stream',
     }
     response = requests.post(cluster_url, headers=headers, data=data)
     if response.status_code == 202:
         print('')
         print('STATUS: 202 Message Accepted')
     elif response.status_code == 204:
         print('')
         print('STATUS: 204 No Content')
     elif response.status_code in [400, 404, 500, 503]:
         print('')
         print('STATUS: {}'.format(response.status_code))
         print('Response Content:', response.content)
     else:
         deserialized_response = load(response.content, priv_key, self.concent_pub_key, check_time=False)
         print_message(deserialized_response, cluster_url, '')
    def test_message_remove_task_container(self):
        test_cases = 10
        task_ids = ['test-{}'.format(uuid.uuid4()) for _ in range(test_cases)]
        remove_tasks = [message.RemoveTask(task_id=task_ids[i])
                        for i in range(test_cases)]
        msg = message.RemoveTaskContainer(remove_tasks=remove_tasks)
        serialized = shortcuts.dump(msg, None, None)
        msg_l = shortcuts.load(serialized, None, None)

        expected = [
            ['remove_tasks', remove_tasks]
        ]
        self.assertEqual(expected, msg_l.slots())
        self.assertEqual(len(msg_l.remove_tasks), test_cases)
        for msg_remove_task in msg_l.remove_tasks:
            self.assertIsInstance(
                msg_remove_task,
                message.p2p.RemoveTask
            )
        for i in range(test_cases):
            self.assertEqual(msg_l.remove_tasks[i].task_id, task_ids[i])
    def test_timestamp_and_timezones(self, *_):
        epoch_t = 1475238345

        def set_tz(tz):
            os.environ['TZ'] = tz
            try:
                time.tzset()
            except AttributeError:
                raise unittest.SkipTest("tzset required")

        set_tz('Europe/Warsaw')
        warsaw_time = time.localtime(epoch_t)
        msg_pre = message.Hello(header=datastructures.MessageHeader(
            message.Hello.TYPE,
            epoch_t,
            False,
        ))
        data = shortcuts.dump(msg_pre, None, None)
        set_tz('US/Eastern')
        msg_post = shortcuts.load(data, None, None)
        newyork_time = time.localtime(msg_post.timestamp)
        self.assertNotEqual(warsaw_time, newyork_time)
        self.assertEqual(time.gmtime(epoch_t), time.gmtime(msg_post.timestamp))
Exemple #18
0
    def test_receive_should_accept_valid_message(self):
        message_timestamp = datetime.datetime.now(timezone.utc)
        new_message = StoredMessage(
            type=self.force_golem_data.report_computed_task.TYPE,
            timestamp=message_timestamp,
            data=self.force_golem_data.report_computed_task.serialize(),
            task_id=self.compute_task_def['task_id'],  # pylint: disable=no-member
            subtask_id=self.compute_task_def['subtask_id'],  # pylint: disable=no-member
        )
        new_message.full_clean()
        new_message.save()

        client_provider = Client(public_key_bytes=PROVIDER_PUBLIC_KEY)
        client_provider.full_clean()
        client_provider.save()

        client_requestor = Client(public_key_bytes=REQUESTOR_PUBLIC_KEY)
        client_requestor.full_clean()
        client_requestor.save()

        task_to_compute_message = StoredMessage(
            type=self.task_to_compute.TYPE,
            timestamp=message_timestamp,
            data=self.task_to_compute.serialize(),
            task_id=self.compute_task_def['task_id'],  # pylint: disable=no-member
            subtask_id=self.compute_task_def['subtask_id'],  # pylint: disable=no-member
        )
        task_to_compute_message.full_clean()
        task_to_compute_message.save()

        subtask = Subtask(
            task_id=self.compute_task_def['task_id'],
            subtask_id=self.compute_task_def['subtask_id'],
            task_to_compute=task_to_compute_message,
            report_computed_task=new_message,
            state=Subtask.SubtaskState.REPORTED.name,  # pylint: disable=no-member
            provider=client_provider,
            requestor=client_requestor,
            result_package_size=self.size,
            computation_deadline=parse_timestamp_to_utc_datetime(
                self.compute_task_def['deadline']))
        subtask.full_clean()
        subtask.save()

        new_message_inbox = PendingResponse(
            response_type=PendingResponse.ResponseType.ForceReportComputedTask.
            name,  # pylint: disable=no-member
            client=client_requestor,
            queue=PendingResponse.Queue.Receive.name,  # pylint: disable=no-member
            subtask=subtask,
        )
        new_message_inbox.full_clean()
        new_message_inbox.save()

        response = self.client.post(
            reverse('core:receive'),
            content_type='application/octet-stream',
            data=self._create_client_auth_message(REQUESTOR_PRIVATE_KEY,
                                                  REQUESTOR_PUBLIC_KEY),
        )
        decoded_response = load(
            response.content,
            REQUESTOR_PRIVATE_KEY,
            CONCENT_PUBLIC_KEY,
        )
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            new_message.task_id, decoded_response.report_computed_task.
            task_to_compute.compute_task_def['task_id'])
        self.assertEqual(
            new_message.subtask_id, decoded_response.report_computed_task.
            task_to_compute.compute_task_def['subtask_id'])
 def test_serialization(self):
     message_instance = self.get_instance()
     serialized_message = dump(message_instance, None, None)
     deserialized_message = load(serialized_message, None, None)
     self.assertEqual(message_instance, deserialized_message)
Exemple #20
0
    def test_receive_should_return_first_messages_in_order_they_were_added_to_queue_if_the_receive_queue_contains_only_force_report_and_its_past_deadline(self):
        message_timestamp = parse_timestamp_to_utc_datetime(get_current_utc_timestamp())
        new_message = StoredMessage(
            type=self.force_golem_data.report_computed_task.header.type_,
            timestamp=message_timestamp,
            data=self.force_golem_data.report_computed_task.serialize(),
            task_id=self.compute_task_def['task_id'],  # pylint: disable=no-member
            subtask_id=self.compute_task_def['subtask_id'],  # pylint: disable=no-member
            protocol_version=settings.GOLEM_MESSAGES_VERSION,
        )
        new_message.full_clean()
        new_message.save()

        want_to_compute_message = StoredMessage(
            type=self.want_to_compute_task.header.type_,
            timestamp=message_timestamp,
            data=self.want_to_compute_task.serialize(),
            task_id=self.compute_task_def['task_id'],  # pylint: disable=no-member
            subtask_id=self.compute_task_def['subtask_id'],  # pylint: disable=no-member
            protocol_version=settings.GOLEM_MESSAGES_VERSION,
        )
        want_to_compute_message.full_clean()
        want_to_compute_message.save()

        task_to_compute_message = StoredMessage(
            type=self.task_to_compute.header.type_,
            timestamp=message_timestamp,
            data=self.task_to_compute.serialize(),
            task_id=self.compute_task_def['task_id'],  # pylint: disable=no-member
            subtask_id=self.compute_task_def['subtask_id'],  # pylint: disable=no-member
            protocol_version=settings.GOLEM_MESSAGES_VERSION,
        )
        task_to_compute_message.full_clean()
        task_to_compute_message.save()

        ack_report_computed_task = message.tasks.AckReportComputedTask(
            report_computed_task=self.report_computed_task
        )

        stored_ack_report_computed_task = StoredMessage(
            type=ack_report_computed_task.header.type_,
            timestamp=message_timestamp,
            data=ack_report_computed_task.serialize(),
            task_id=self.compute_task_def['task_id'],  # pylint: disable=no-member
            subtask_id=self.compute_task_def['subtask_id'],  # pylint: disable=no-member
            protocol_version=settings.GOLEM_MESSAGES_VERSION,
        )
        stored_ack_report_computed_task.full_clean()
        stored_ack_report_computed_task.save()

        client_provider = Client(
            public_key_bytes=self.PROVIDER_PUBLIC_KEY
        )
        client_provider.full_clean()
        client_provider.save()

        client_requestor = Client(
            public_key_bytes=self.REQUESTOR_PUBLIC_KEY
        )
        client_requestor.full_clean()
        client_requestor.save()

        subtask = Subtask(
            task_id                  = self.compute_task_def['task_id'],
            subtask_id               = self.compute_task_def['subtask_id'],
            report_computed_task     = new_message,
            task_to_compute          = task_to_compute_message,
            want_to_compute_task=want_to_compute_message,
            ack_report_computed_task = stored_ack_report_computed_task,
            state                    = Subtask.SubtaskState.REPORTED.name,  # pylint: disable=no-member
            provider                 = client_provider,
            requestor                = client_requestor,
            result_package_size=self.size,
            computation_deadline=parse_timestamp_to_utc_datetime(self.compute_task_def['deadline'])
        )
        subtask.full_clean()
        subtask.save()

        new_message_inbox = PendingResponse(
            response_type=PendingResponse.ResponseType.ForceReportComputedTask.name,  # pylint: disable=no-member
            client=client_requestor,
            queue=PendingResponse.Queue.Receive.name,  # pylint: disable=no-member
            subtask=subtask,
        )
        new_message_inbox.full_clean()
        new_message_inbox.save()

        new_message_inbox_out_of_band = PendingResponse(
            response_type=PendingResponse.ResponseType.VerdictReportComputedTask.name,  # pylint: disable=no-member
            client=client_requestor,
            queue=PendingResponse.Queue.ReceiveOutOfBand.name,  # pylint: disable=no-member
            subtask=subtask,
        )
        new_message_inbox_out_of_band.full_clean()
        new_message_inbox_out_of_band.save()

        with freeze_time("2017-11-17 12:00:00"):
            response = self.send_request(
                url='core:receive',
                data=self._create_client_auth_message(self.REQUESTOR_PRIVATE_KEY, self.REQUESTOR_PUBLIC_KEY),
            )

        decoded_message = load(
            response.content,
            self.REQUESTOR_PRIVATE_KEY,
            CONCENT_PUBLIC_KEY,
            check_time=False,
        )

        self.assertIsInstance(decoded_message, message.concents.ForceReportComputedTask)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(decoded_message.timestamp, self._create_timestamp_from_string("2017-11-17 12:00:00"))
        self.assertEqual(decoded_message.report_computed_task.task_to_compute.compute_task_def,
                         self.task_to_compute.compute_task_def)  # pylint: disable=no-member
        self.assertEqual(decoded_message.report_computed_task.task_to_compute.sig, self.task_to_compute.sig)

        with freeze_time("2017-11-17 12:00:00"):
            response = self.send_request(
                url='core:receive',
                data=self._create_client_auth_message(self.REQUESTOR_PRIVATE_KEY, self.REQUESTOR_PUBLIC_KEY),
            )

        decoded_message = load(
            response.content,
            self.REQUESTOR_PRIVATE_KEY,
            CONCENT_PUBLIC_KEY,
            check_time=False,
        )

        self.assertIsInstance(decoded_message, message.concents.VerdictReportComputedTask)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(decoded_message.timestamp, self._create_timestamp_from_string("2017-11-17 12:00:00"))
        self.assertEqual(decoded_message.ack_report_computed_task.report_computed_task.task_to_compute.compute_task_def,
                         self.task_to_compute.compute_task_def)  # pylint: disable=no-member
        self.assertEqual(decoded_message.ack_report_computed_task.report_computed_task.task_to_compute.sig,
                         self.task_to_compute.sig)
Exemple #21
0
    def test_receive_should_accept_valid_message(self):
        message_timestamp = parse_timestamp_to_utc_datetime(get_current_utc_timestamp())
        new_message = StoredMessage(
            type=self.force_golem_data.report_computed_task.header.type_,
            timestamp=message_timestamp,
            data=self.force_golem_data.report_computed_task.serialize(),
            task_id=self.compute_task_def['task_id'],  # pylint: disable=no-member
            subtask_id=self.compute_task_def['subtask_id'],  # pylint: disable=no-member
            protocol_version=settings.GOLEM_MESSAGES_VERSION,
        )
        new_message.full_clean()
        new_message.save()

        client_provider = Client(
            public_key_bytes=self.PROVIDER_PUBLIC_KEY
        )
        client_provider.full_clean()
        client_provider.save()

        client_requestor = Client(
            public_key_bytes=self.REQUESTOR_PUBLIC_KEY
        )
        client_requestor.full_clean()
        client_requestor.save()

        want_to_compute_message = StoredMessage(
            type=self.want_to_compute_task.header.type_,
            timestamp=message_timestamp,
            data=self.want_to_compute_task.serialize(),
            task_id=self.compute_task_def['task_id'],  # pylint: disable=no-member
            subtask_id=self.compute_task_def['subtask_id'],  # pylint: disable=no-member
            protocol_version=settings.GOLEM_MESSAGES_VERSION,
        )
        want_to_compute_message.full_clean()
        want_to_compute_message.save()

        task_to_compute_message = StoredMessage(
            type=self.task_to_compute.header.type_,
            timestamp=message_timestamp,
            data=self.task_to_compute.serialize(),
            task_id=self.compute_task_def['task_id'],  # pylint: disable=no-member
            subtask_id=self.compute_task_def['subtask_id'],  # pylint: disable=no-member
            protocol_version=settings.GOLEM_MESSAGES_VERSION,
        )
        task_to_compute_message.full_clean()
        task_to_compute_message.save()

        subtask = Subtask(
            task_id                 = self.compute_task_def['task_id'],
            subtask_id              = self.compute_task_def['subtask_id'],
            task_to_compute         = task_to_compute_message,
            want_to_compute_task=want_to_compute_message,
            report_computed_task    = new_message,
            state                   = Subtask.SubtaskState.REPORTED.name,  # pylint: disable=no-member
            provider                = client_provider,
            requestor               = client_requestor,
            result_package_size=self.size,
            computation_deadline=parse_timestamp_to_utc_datetime(self.compute_task_def['deadline'])
        )
        subtask.full_clean()
        subtask.save()

        new_message_inbox = PendingResponse(
            response_type=PendingResponse.ResponseType.ForceReportComputedTask.name,  # pylint: disable=no-member
            client=client_requestor,
            queue=PendingResponse.Queue.Receive.name,  # pylint: disable=no-member
            subtask=subtask,
        )
        new_message_inbox.full_clean()
        new_message_inbox.save()

        response = self.send_request(
            url='core:receive',
            data=self._create_client_auth_message(self.REQUESTOR_PRIVATE_KEY, self.REQUESTOR_PUBLIC_KEY),
        )
        decoded_response = load(
            response.content,
            self.REQUESTOR_PRIVATE_KEY,
            CONCENT_PUBLIC_KEY,
        )
        self.assertEqual(response.status_code, 200)
        self.assertEqual(new_message.task_id,
                         decoded_response.report_computed_task.task_to_compute.compute_task_def['task_id'])
        self.assertEqual(new_message.subtask_id,
                         decoded_response.report_computed_task.task_to_compute.compute_task_def['subtask_id'])
Exemple #22
0
def parse_headers(
    request: WSGIRequest,
    path_to_file: str,
    operation: FileTransferToken.Operation,
) -> Union[FileTransferToken.FileInfo, JsonResponse]:
    # Decode and check if request header contains a golem message:
    if 'HTTP_AUTHORIZATION' not in request.META:
        return gatekeeper_access_denied_response(
            "Missing 'Authorization' header.",
            operation,
            ErrorCode.HEADER_AUTHORIZATION_MISSING,
            path_to_file,
        )

    authorization_scheme_and_token = request.META['HTTP_AUTHORIZATION'].split(" ", 1)
    assert len(authorization_scheme_and_token) in [1, 2]

    if len(authorization_scheme_and_token) == 1:
        return gatekeeper_access_denied_response(
            "Missing token in the 'Authorization' header.",
            operation,
            ErrorCode.HEADER_AUTHORIZATION_MISSING_TOKEN,
            path_to_file,
        )

    (scheme, token) = authorization_scheme_and_token

    if scheme != 'Golem':
        return gatekeeper_access_denied_response(
            "Unrecognized scheme in the 'Authorization' header.",
            operation,
            ErrorCode.HEADER_AUTHORIZATION_UNRECOGNIZED_SCHEME,
            path_to_file,
        )

    try:
        decoded_auth_header_content = b64decode(token, validate = True)
    except binascii.Error:
        return gatekeeper_access_denied_response(
            "Unable to decode token in the 'Authorization' header.",
            operation,
            ErrorCode.HEADER_AUTHORIZATION_NOT_BASE64_ENCODED_VALUE,
            path_to_file,
        )

    try:
        loaded_golem_message = load(
            decoded_auth_header_content,
            settings.CONCENT_PRIVATE_KEY,
            settings.CONCENT_PUBLIC_KEY,
            check_time = False
        )
    except MessageError:
        return gatekeeper_access_denied_response(
            "Token in the 'Authorization' header is not a valid Golem message.",
            operation,
            ErrorCode.HEADER_AUTHORIZATION_TOKEN_INVALID_MESSAGE,
            path_to_file,
        )

    assert isinstance(loaded_golem_message, Message)

    # Check if request header contains Concent-Auth:
    if 'HTTP_CONCENT_AUTH' not in request.META:
        return gatekeeper_access_denied_response(
            'Missing Concent-Auth header.',
            operation,
            ErrorCode.AUTH_CLIENT_AUTH_MESSAGE_MISSING,
            path_to_file,
            loaded_golem_message.subtask_id
        )

    # Try to load in ClientAuthorization message from Concent-Auth header
    try:
        client_authorization = load(
            b64decode(request.META['HTTP_CONCENT_AUTH'], validate=True),
            settings.CONCENT_PRIVATE_KEY,
            loaded_golem_message.authorized_client_public_key,
        )
        concent_client_public_key = b64encode(client_authorization.client_public_key).decode('ascii')
    except (MessageError, binascii.Error):
        return gatekeeper_access_denied_response(
            'Cannot load ClientAuthorization message from Concent-Auth header.',
            operation,
            ErrorCode.AUTH_CLIENT_AUTH_MESSAGE_INVALID,
            path_to_file,
            loaded_golem_message.subtask_id
        )
    logging.log(
        logger,
        f"{loaded_golem_message.operation.capitalize()} request will be validated. "
        f"Message type: '{loaded_golem_message.__class__.__name__}'. File: '{path_to_file}'",
        subtask_id=loaded_golem_message.subtask_id,
        client_public_key=concent_client_public_key,
    )
    current_time = get_current_utc_timestamp()

    if current_time > loaded_golem_message.token_expiration_deadline:
        return gatekeeper_access_denied_response(
            'token_expiration_deadline has passed.',
            operation,
            ErrorCode.MESSAGE_TOKEN_EXPIRATION_DEADLINE_PASSED,
            path_to_file,
            loaded_golem_message.subtask_id,
            concent_client_public_key
        )

    try:
        validate_file_transfer_token(loaded_golem_message)
    except FileTransferTokenError as exception:
        return gatekeeper_access_denied_response(
            exception.error_message,
            operation,
            exception.error_code,
            path_to_file,
            loaded_golem_message.subtask_id,
            concent_client_public_key
        )

    authorized_client_public_key_base64 = (b64encode(loaded_golem_message.authorized_client_public_key)).decode('ascii')
    if concent_client_public_key != authorized_client_public_key_base64:
        return gatekeeper_access_denied_response(
            'You are not authorized to use this token.',
            operation,
            ErrorCode.MESSAGE_AUTHORIZED_CLIENT_PUBLIC_KEY_UNAUTHORIZED_CLIENT,
            path_to_file,
            loaded_golem_message.subtask_id,
            concent_client_public_key
        )

    # -OPERATION
    if request.method == 'POST' and loaded_golem_message.operation != FileTransferToken.Operation.upload:
        return gatekeeper_access_denied_response(
            'Upload requests must use POST method.',
            operation,
            ErrorCode.MESSAGE_OPERATION_INVALID,
            path_to_file,
            loaded_golem_message.subtask_id,
            concent_client_public_key
        )
    if request.method in ['GET', 'HEAD'] and loaded_golem_message.operation != FileTransferToken.Operation.download:
        return gatekeeper_access_denied_response(
            'Download requests must use GET or HEAD method.',
            operation,
            ErrorCode.MESSAGE_OPERATION_INVALID,
            path_to_file,
            loaded_golem_message.subtask_id,
            concent_client_public_key
        )

    matching_files = [file for file in loaded_golem_message.files if path_to_file == file['path']]

    if len(matching_files) == 1:
        logging.log(
            logger,
            f"{loaded_golem_message.operation.capitalize()} request passed all validations. "
            f"Message type: '{loaded_golem_message.__class__.__name__}'. File: '{path_to_file}'",
            subtask_id=loaded_golem_message.subtask_id,
            client_public_key=concent_client_public_key
        )
        return matching_files[0]
    else:
        assert len(matching_files) == 0
        return gatekeeper_access_denied_response(
            'Your token does not authorize you to transfer the requested file.',
            operation,
            ErrorCode.MESSAGE_FILES_PATH_NOT_LISTED_IN_FILES,
            path_to_file,
            loaded_golem_message.subtask_id,
            concent_client_public_key
        )
 def test_task_to_compute_basic(self):
     ttc = factories.tasks.TaskToComputeFactory()
     serialized = shortcuts.dump(ttc, None, None)
     msg = shortcuts.load(serialized, None, None)
     self.assertIsInstance(msg, message.tasks.TaskToCompute)
 def _dump_and_load(msg):
     msg_d = shortcuts.dump(msg, None, None)
     return shortcuts.load(msg_d, None, None)
Exemple #25
0
    def test_receive_should_return_first_messages_in_order_they_were_added_to_queue_if_the_receive_queue_contains_only_force_report_and_its_past_deadline(
            self):
        message_timestamp = datetime.datetime.now(timezone.utc)
        new_message = StoredMessage(
            type=self.force_golem_data.report_computed_task.TYPE,
            timestamp=message_timestamp,
            data=self.force_golem_data.report_computed_task.serialize(),
            task_id=self.compute_task_def['task_id'],  # pylint: disable=no-member
            subtask_id=self.compute_task_def['subtask_id'],  # pylint: disable=no-member
        )
        new_message.full_clean()
        new_message.save()

        task_to_compute_message = StoredMessage(
            type=self.task_to_compute.TYPE,
            timestamp=message_timestamp,
            data=self.task_to_compute.serialize(),
            task_id=self.compute_task_def['task_id'],  # pylint: disable=no-member
            subtask_id=self.compute_task_def['subtask_id'],  # pylint: disable=no-member
        )
        task_to_compute_message.full_clean()
        task_to_compute_message.save()

        ack_report_computed_task = message.AckReportComputedTask(
            report_computed_task=message.ReportComputedTask(
                task_to_compute=self.task_to_compute, ))

        stored_ack_report_computed_task = StoredMessage(
            type=ack_report_computed_task.TYPE,
            timestamp=message_timestamp,
            data=ack_report_computed_task.serialize(),
            task_id=self.compute_task_def['task_id'],  # pylint: disable=no-member
            subtask_id=self.compute_task_def['subtask_id'],  # pylint: disable=no-member
        )
        stored_ack_report_computed_task.full_clean()
        stored_ack_report_computed_task.save()

        client_provider = Client(public_key_bytes=PROVIDER_PUBLIC_KEY)
        client_provider.full_clean()
        client_provider.save()

        client_requestor = Client(public_key_bytes=REQUESTOR_PUBLIC_KEY)
        client_requestor.full_clean()
        client_requestor.save()

        subtask = Subtask(
            task_id=self.compute_task_def['task_id'],
            subtask_id=self.compute_task_def['subtask_id'],
            report_computed_task=new_message,
            task_to_compute=task_to_compute_message,
            ack_report_computed_task=stored_ack_report_computed_task,
            state=Subtask.SubtaskState.REPORTED.name,  # pylint: disable=no-member
            provider=client_provider,
            requestor=client_requestor,
            result_package_size=self.size,
            computation_deadline=parse_timestamp_to_utc_datetime(
                self.compute_task_def['deadline']))
        subtask.full_clean()
        subtask.save()

        new_message_inbox = PendingResponse(
            response_type=PendingResponse.ResponseType.ForceReportComputedTask.
            name,  # pylint: disable=no-member
            client=client_requestor,
            queue=PendingResponse.Queue.Receive.name,  # pylint: disable=no-member
            subtask=subtask,
        )
        new_message_inbox.full_clean()
        new_message_inbox.save()

        new_message_inbox_out_of_band = PendingResponse(
            response_type=PendingResponse.ResponseType.
            VerdictReportComputedTask.name,  # pylint: disable=no-member
            client=client_requestor,
            queue=PendingResponse.Queue.ReceiveOutOfBand.name,  # pylint: disable=no-member
            subtask=subtask,
        )
        new_message_inbox_out_of_band.full_clean()
        new_message_inbox_out_of_band.save()

        with freeze_time("2017-11-17 12:00:00"):
            response = self.client.post(
                reverse('core:receive'),
                content_type='application/octet-stream',
                data=self._create_client_auth_message(REQUESTOR_PRIVATE_KEY,
                                                      REQUESTOR_PUBLIC_KEY),
            )

        decoded_message = load(
            response.content,
            REQUESTOR_PRIVATE_KEY,
            CONCENT_PUBLIC_KEY,
            check_time=False,
        )

        self.assertIsInstance(decoded_message,
                              message.concents.ForceReportComputedTask)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            decoded_message.timestamp,
            int(dateutil.parser.parse("2017-11-17 12:00:00").timestamp()))
        self.assertEqual(decoded_message.report_computed_task.task_to_compute.
                         compute_task_def,
                         self.task_to_compute.compute_task_def)  # pylint: disable=no-member
        self.assertEqual(
            decoded_message.report_computed_task.task_to_compute.sig,
            self.task_to_compute.sig)

        with freeze_time("2017-11-17 12:00:00"):
            response = self.client.post(
                reverse('core:receive_out_of_band'),
                content_type='application/octet-stream',
                data=self._create_client_auth_message(REQUESTOR_PRIVATE_KEY,
                                                      REQUESTOR_PUBLIC_KEY),
            )

        decoded_message = load(
            response.content,
            REQUESTOR_PRIVATE_KEY,
            CONCENT_PUBLIC_KEY,
            check_time=False,
        )

        self.assertIsInstance(decoded_message,
                              message.concents.VerdictReportComputedTask)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            decoded_message.timestamp,
            int(dateutil.parser.parse("2017-11-17 12:00:00").timestamp()))
        self.assertEqual(decoded_message.ack_report_computed_task.
                         report_computed_task.task_to_compute.compute_task_def,
                         self.task_to_compute.compute_task_def)  # pylint: disable=no-member
        self.assertEqual(
            decoded_message.ack_report_computed_task.report_computed_task.
            task_to_compute.sig, self.task_to_compute.sig)
    def test_message_sig(self):
        """Signed message inside a signed message"""

        concent_keys = cryptography.ECCx(None)
        provider_keys = cryptography.ECCx(None)
        requestor_keys = cryptography.ECCx(None)

        task_to_compute = message.TaskToCompute()
        ctd = message.ComputeTaskDef({
            'task_id': 20,
        })
        task_to_compute.compute_task_def = ctd

        # Dump TaskToCompute to make it signed
        s_task_to_compute = shortcuts.dump(
            task_to_compute,
            requestor_keys.raw_privkey,
            provider_keys.raw_pubkey,
        )

        # Load TaskToCompute back to its original format
        task_to_compute = shortcuts.load(
            s_task_to_compute,
            provider_keys.raw_privkey,
            requestor_keys.raw_pubkey,
        )

        first_sig = task_to_compute.sig
        first_hash = task_to_compute.get_short_hash()

        # Task TaskToCompute is verified correctly
        cryptography.ecdsa_verify(
            requestor_keys.raw_pubkey,
            task_to_compute.sig,
            task_to_compute.get_short_hash(),
        )

        force_report = message.ForceReportComputedTask()
        force_report.task_to_compute = task_to_compute

        s_force_report = shortcuts.dump(
            force_report,
            provider_keys.raw_privkey,
            concent_keys.raw_pubkey,
        )

        force_report = shortcuts.load(
            s_force_report,
            concent_keys.raw_privkey,
            provider_keys.raw_pubkey,
        )

        second_sig = force_report.task_to_compute.sig
        second_hash = force_report.task_to_compute.get_short_hash()

        self.assertEqual(first_sig, second_sig)
        self.assertEqual(first_hash, second_hash)

        # Now, attached TaskToCompute should still be verified using
        # original key. ecdsa_verify will raise InvalidSignature on
        # failure.
        cryptography.ecdsa_verify(
            requestor_keys.raw_pubkey,
            force_report.task_to_compute.sig,
            force_report.task_to_compute.get_short_hash(),
        )