Пример #1
0
    def __process_worker_update(self, worker_id, input_json_str, response):
        """
        Function to update the worker details.
        Parameters:
            - worker_id is the worker id specified in the input json str.
            - input_json_str is a worker request json as per TCF API 5.3.2 Worker Update JSON Payload
            - response is the response object to be returned to client.
        """

        jrpc_id = json.loads(input_json_str)["id"]

        # value retrieved is 'result' field as per Spec 5.3.8 Worker Retrieve Response Payload
        value = self.kv_helper.get("workers", worker_id)

        if value is not None:
            json_dict = json.loads(value)
            input_value = json.loads(input_json_str)
            worker_details = input_value["params"]["details"]
            for item in worker_details:
                json_dict["details"][item] = worker_details[item]

            value = json.dumps(json_dict)
            self.kv_helper.set("workers", worker_id, value)
            response = utility.create_error_response(WorkerError.SUCCESS,
                                                     jrpc_id,
                                                     "Successfully Updated")
        else:
            response = utility.create_error_response(
                WorkerError.INVALID_PARAMETER_FORMAT_OR_VALUE, jrpc_id,
                "Worker Id not found in the database. \
                 Hence invalid parameter")
        return response
Пример #2
0
    def __process_work_order_get_result(self, wo_id, jrpc_id, response):
        """
        Function to process work order get result
        This API corresponds to TCF API 6.1.4 Work Order Pull Request Payload
        Parameters:
            - wo_id is work order id
            - jrpc_id is JRPC id of response
            - response is the response object to be returned
        """

        # Work order is processed if it is in wo-response table
        value = self.kv_helper.get("wo-responses", wo_id)
        if value:
            input_value = json.loads(value)
            if 'result' in value:
                response['result'] = input_value['result']
            else:
                response['result'] = input_value['error']
        else:
            if (self.kv_helper.get("wo-timestamps", wo_id) is not None):
                # work order is yet to be processed
                response = utility.create_error_response(
                    WorkOrderStatus.PENDING, jrpc_id,
                    "Work order result is yet to be updated")
            else:
                # work order not in 'wo-timestamps' table
                response = utility.create_error_response(
                    WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE, jrpc_id,
                    "Work order Id not found in the database. \
                     Hence invalid parameter")

        return response
Пример #3
0
    def __process_worker_register(self, worker_id, input_json_str, response):
        """
        Function to register a new worker to the enclave
        Parameters:
            - worker_id is the worker id specified in the input json str.
            - input_json_str is a worker request json as per TCF API 5.3.1 Worker Register JSON Payload.
            - response is the response object to be returned to client.
        """

        input_value_json = json.loads(input_json_str)
        jrpc_id = input_value_json["id"]

        if (self.kv_helper.get("workers", worker_id) is None):
            input_value = {}
            input_value = input_value_json['params']

            # Worker Initial Status is set to Active
            input_value["status"] = WorkerStatus.ACTIVE

            input_json_str = json.dumps(input_value)
            self.kv_helper.set("workers", worker_id, input_json_str)
            response = utility.create_error_response(
                WorkerError.SUCCESS, jrpc_id, "Successfully Registered")
        else:
            response = utility.create_error_response(
                WorkerError.INVALID_PARAMETER_FORMAT_OR_VALUE, jrpc_id,
                "Worker Id already exists in the database. \
                 Hence invalid parameter")
        return response
Пример #4
0
    def __process_worker_set_status(self, worker_id, input_json_str, response):
        """
        Function to set the status of worker
        Parameters:
            - worker_id is the worker id specified in the input json str.
            - input_json_str is a worker request json as per TCF API 5.3.3 Worker Set Status JSON Payload
            - response is the response object to be returned to client.
        """

        # status can be one of active, offline, decommissioned, or compromised

        input_value = json.loads(input_json_str)
        jrpc_id = input_value["id"]

        value = self.kv_helper.get("workers", worker_id)
        if value:
            json_dict = json.loads(value)
            json_dict['status'] = input_value['params']['status']

            value = json.dumps(json_dict)
            self.kv_helper.set("workers", worker_id, value)
            response = utility.create_error_response(
                WorkerError.SUCCESS, jrpc_id, "Successfully Set Status")
        else:
            response = utility.create_error_response(
                WorkerError.INVALID_PARAMETER_FORMAT_OR_VALUE, jrpc_id,
                "Worker Id not found in the database. \
                 Hence invalid parameter")

        return response
Пример #5
0
    def render_POST(self, request):
        response = {}

        logger.info('Received a new request from the client')
        try :
            # process the message encoding
            encoding = request.getHeader('Content-Type')
            data = request.content.read()
            if encoding == 'application/json' :

                try:
                    input_json_str = json.loads(data.decode('utf-8'))
                    input_json = json.loads(input_json_str)
                    jrpc_id = input_json["id"]
                    response = self._process_request(input_json_str)

                except AttributeError:
                    logger.error("Error while loading input json")
                    response = utility.create_error_response(
                        WorkorderError.UNKNOWN_ERROR,
                        jrpc_id,
                        "UNKNOWN_ERROR: Error while loading the input JSON file")
                    return response

            else :
                # JRPC response with 0 as id is returned because id can't be fecthed
                # from a request with unknown encoding
                response = utility.create_error_response(
                        WorkorderError.UNKNOWN_ERROR,
                        0,
                        "UNKNOWN_ERROR: unknown message encoding")
                return response

        except :
            logger.exception('exception while decoding http request %s', request.path)
            # JRPC response with 0 as id is returned because id can't be
            # fetched from improper request
            response = utility.create_error_response(
                    WorkorderError.UNKNOWN_ERROR,
                    0,
                    "UNKNOWN_ERROR: unable to decode incoming request")
            return response

        # send back the results
        try :
            if encoding == 'application/json' :
                response = json.dumps(response)
            logger.info('response[%s]: %s', encoding, response)
            request.setHeader('content-type', encoding)
            request.setResponseCode(http.OK)
            return response.encode('utf8')

        except :
            logger.exception('unknown exception while processing request %s', request.path)
            response = utility.create_error_response(
                    WorkorderError.UNKNOWN_ERROR,
                    jrpc_id,
                    "UNKNOWN_ERROR: unknown exception processing http \
                    request {0}".format(request.path))
            return response
Пример #6
0
    def test_create_error_response(self):
        """Tests to verify create_error_response(code, jrpc_id, message) function
        """
        expected_response = {
            "jsonrpc": "2.0", "id": "id1",
            "error": {"code": 404, "message": "Page not found"}, }
        self.assertEquals(expected_response, create_error_response(
            404, "id1", "Page not found"))

        expected_response = {"jsonrpc": "2.0", "id": "id2",
                             "error":
                             {"code": "2", "message": "General error"}, }
        self.assertEquals(expected_response, create_error_response("2", "id2",
                          "General error"))
Пример #7
0
    def __process_workorder_receipt_update(self, wo_id, input_json_str,
                                           response):
        """
        Function to process update work order request
        Parameters:
            - wo_id is work order id
            - input_json_str is work order receipt update json as per
              TCF API 7.2.6 Receipt Update Retrieve Request Payload
            - response is the response object to be returned to client
        """

        input_value = json.loads(input_json_str)
        jrpc_id = input_value["id"]

        # value retrieved is 'result' field as per Spec 7.2.5 Receipt Retrieve Response Payload
        value = self.kv_helper.get("wo-receipts", wo_id)
        response['error'] = {}

        if value:
            updater_value = input_value['params']
            # WorkorderId already a part of receipt. And will be not change for a given receipt. Hence it's not stored in updater param.
            del updater_value['workOrderId']

            json_dict = json.loads(value)
            updater_objects = json_dict['result']['updater']

            if len(updater_objects) > 0:
                # Updater Object is sorted based on index and then last index is chosen
                index = int(sorted(updater_objects.keys())[-1]) + 1
            else:
                index = 0

            updater_objects[index] = updater_value
            json_dict['result']['receiptCurrentStatus'] = updater_value[
                'updateType']
            json_dict['result']['updater'] = updater_objects

            value = json.dumps(json_dict)
            self.kv_helper.set("wo-receipts", wo_id, value)
            response = utility.create_error_response(
                WorkorderError.SUCCESS, jrpc_id,
                "Receipt Successfully Updated")
        else:
            response = utility.create_error_response(
                WorkorderError.INVALID_PARAMETER_FORMAT_OR_VALUE, jrpc_id,
                "Work order id not found in the database. \
                 Hence invalid parameter")
        return response
Пример #8
0
    def __process_worker_retrieve(self, worker_id, response):
        """
        Function to retrieve the details of worker
        Parameters:
            - worker_id is the worker id specified in worker request json as per TCF API 5.3.7 Worker Retrieve JSON Payload
            - response is the response object to be returned to client.
        """

        # value retrieved is 'result' field as per Spec 5.3.8 Worker Retrieve Response Payload
        value = self.kv_helper.get("workers", worker_id)

        if value is not None:
            json_dict = json.loads(value)
            response["result"] = {}
            response["result"]["workerType"] = json_dict["workerType"]
            response["result"]["organizationId"] = json_dict["organizationId"]
            response["result"]["applicationTypeId"] = json_dict[
                "applicationTypeId"]
            response["result"]["details"] = json_dict["details"]
            response["result"]["status"] = json_dict["status"]
        else:
            jrpc_id = json.loads(response)["id"]
            response = utility.create_error_response(
                WorkerError.INVALID_PARAMETER_FORMAT_OR_VALUE, jrpc_id,
                "Worker Id not found in the database. Hence invalid parameter")
        return response
Пример #9
0
    def __process_workorder_receipt_retrieve(self, wo_id, jrpc_id, response):
        """
        Function to retrieve the details of worker
        Parameters:
            - worker_id is the worker id specified in worker request json
              as per TCF API 7.2.4 Receipt Retrieve Request Payload
            - response is the response object to be returned to client
            - jrpc_id is the jrpc id of response object to be returned to client
        """

        # value retrieved is 'result' field as per Spec 7.2.5 Receipt Retrieve Response Payload
        value = self.kv_helper.get("wo-receipts", wo_id)

        if value:
            input_value = json.loads(value)
            response['result'] = {}
            if 'result' in value:
                response['result'] = input_value['result']
            else:
                # Need to revisit code when actual receipts are created
                response['result'] = input_value['error']
        else:
            response = utility.create_error_response(
                WorkorderError.INVALID_PARAMETER_FORMAT_OR_VALUE, jrpc_id,
                "Work order id not found in the database. \
                 Hence invalid parameter")
            return response

        return response
Пример #10
0
    def render_GET(self, request):
        # JRPC response with id 0 is returned because id parameter
        # will not be found in GET request
        response = utility.create_error_response(
                WorkorderError.INVALID_PARAMETER_FORMAT_OR_VALUE, "0",
                "Only POST request is supported")
        logger.error("GET request is not supported. Only POST request is supported")

        return response
Пример #11
0
    def __process_store_workorder_receipt(self, wo_id, input_json_str,
                                          response):
        """
        Function to process work order request
        Parameters:
            - wo_id is work order id
            - input_json_str is create work order receipt json
              as per TCF API 7.2.2 Receipt Create Request Payload
            - response is the response object to be returned to client
        """

        input_value_json = json.loads(input_json_str)
        jrpc_id = input_value_json["id"]
        input_value = {}
        input_value['result'] = input_value_json['params']
        input_value['result'][
            'receiptCurrentStatus'] = ReceiptCreateStatus.PENDING
        # Updater is introduced to maintain multiple update details on a receipt
        input_value['result']['updater'] = {}
        input_json_str = json.dumps(input_value)

        if (self.kv_helper.get("wo-receipts", wo_id) is None):
            value = self.kv_helper.get("wo-requests", wo_id)
            if value:
                self.kv_helper.set("wo-receipts", wo_id, input_json_str)
                response = utility.create_error_response(
                    WorkorderError.SUCCESS, jrpc_id,
                    "Receipt created successfully")
            else:
                response = utility.create_error_response(
                    WorkorderError.INVALID_PARAMETER_FORMAT_OR_VALUE, jrpc_id,
                    "Work order does not exists. Hence invalid parameter")
        else:
            response = utility.create_error_response(
                WorkorderError.INVALID_PARAMETER_FORMAT_OR_VALUE, jrpc_id,
                "Work order receipt already exist in the database. Hence invalid parameter"
            )

        return response
    def __process_work_order_get_result(self, wo_id, jrpc_id, response):
        """
        Function to process work order get result
        This API corresponds to TCF API 6.1.4 Work Order Pull Request Payload
        Parameters:
            - wo_id is work order id
            - jrpc_id is JRPC id of response
            - response is the response object to be returned
        """

        # Work order is processed if it is in wo-response table
        value = self.kv_helper.get("wo-responses", wo_id)
        if value:
            response = json.loads(value)
            if "error" in response:
                # Mapping standard enclave error codes to JSON RPC error codes
                if response["error"]["code"] == EnclaveError.ENCLAVE_ERR_VALUE:
                    response["error"][
                        "code"] = WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE
                elif response["error"][
                        "code="] == EnclaveError.ENCLAVE_ERR_UNKNOWN:
                    response["error"]["code"] = WorkOrderStatus.UNKNOWN_ERROR
                else:
                    response["error"]["code"] = WorkOrderStatus.FAILED
        else:
            if (self.kv_helper.get("wo-timestamps", wo_id) is not None):
                # work order is yet to be processed
                response = utility.create_error_response(
                    WorkOrderStatus.PENDING, jrpc_id,
                    "Work order result is yet to be updated")
            else:
                # work order not in 'wo-timestamps' table
                response = utility.create_error_response(
                    WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE, jrpc_id,
                    "Work order Id not found in the database. \
                     Hence invalid parameter")

        return response
    def __process_encryption_key_set(self, input_json_str, response):
        """
        Function to process set encryption key request.
        Parameters:
            - input_json_str is a work order request json as per TCF API 6.1.11 Set Encryption Key Request Payload
            - response is the response object to be returned
        """

        input_json = json.loads(input_json_str)
        jrpc_id = input_json["id"]
        response = utility.create_error_response(
            WorkerError.INVALID_PARAMETER_FORMAT_OR_VALUE, jrpc_id,
            "Operation is not supported. Hence invalid parameter")
        return response
Пример #14
0
    def __process_workorder_receipt_update_retrieve(self, wo_id,
                                                    input_json_str, response):
        """
        Function to process work order receipt update retrieve
        Parameters:
            - wo_id is work order id
            - input_json_str is work order receipt update json
              as per TCF API 7.2.6 Receipt Update Retrieve Request Payload
            - response is the response object to be returned to client
        """

        input_value = json.loads(input_json_str)
        jrpc_id = input_value["id"]

        # value retrieved is 'result' field as per Spec 7.2.5 Receipt Retrieve Response Payload
        value = self.kv_helper.get("wo-receipts", wo_id)

        if value:
            updater_id = input_value["params"]['updaterId']
            update_index = input_value["params"]['updateIndex']

            json_dict = json.loads(value)
            updater_objects = json_dict['result']['updater']

            update_count = 0
            result_item = {}
            for item in updater_objects:
                id = updater_objects[item]['updaterId']
                if id == updater_id:
                    # Considering Index 0 as  first update
                    if update_count == update_index:
                        result_item = updater_objects[item]
                # the total number of updates made by the updaterId.
                update_count = update_count + 1

            response['result'] = {}
            response['result'] = result_item
            response['result']['updateCount'] = update_count

        else:
            response = utility.create_error_response(
                WorkorderError.INVALID_PARAMETER_FORMAT_OR_VALUE, jrpc_id,
                "Work order id not found in the database. \
                 Hence invalid parameter")

        return response
    def __process_encryption_key_get(self, input_json_str, response):
        """
        Function to process get encryption key request.
        Parameters:
            - input_json_str is a work order request json as per TCF API 6.1.10 Get Encryption Key Request Payload
            - response is the response object to be returned
        """

        input_json = json.loads(input_json_str)
        jrpc_id = input_json["id"]
        worker_id = str(input_json['params']['workerId'])
        value = self.kv_helper.get("workers", worker_id)

        if value is not None:
            json_dict = json.loads(value)
            response["result"] = {}
            response["result"]["workerId"] = worker_id
            encryptionKey = json_dict["details"]["workerTypeData"][
                "encryptionKey"]
            try:
                encryptionKeyNonce = json_dict["details"]["workerTypeData"][
                    "encryptionKeyNonce"]
            except:
                encryptionKeyNonce = crypto.random_bit_string(NO_OF_BYTES)
            tag = ""
            response["result"]["encryptionKey"] = encryptionKey
            response["result"]["encryptionKeyNonce"] = encryptionKeyNonce
            response["result"]["tag"] = tag
            #calculate signature
            concat_string = worker_id.encode('UTF-8') + encryptionKey.encode(
                'UTF-8') + encryptionKeyNonce.encode('UTF-8') + tag.encode(
                    'UTF-8')
            concat_hash = bytes()
            concat_hash = bytes(concat_string)
            hash_1 = crypto.compute_message_hash(concat_hash)
            s1 = crypto.byte_array_to_base64(hash_1)
            # Requires worker private key to sign.
            # signature =  self.PrivateKey.SignMessage(hash)
            response["result"]["signature"] = s1
        else:
            # Workorder id already exists
            response = utility.create_error_response(
                WorkerError.INVALID_PARAMETER_FORMAT_OR_VALUE, jrpc_id,
                "Worker id not found in the database. Hence invalid parameter")

        return response
Пример #16
0
    def workorder_receipt_handler(self, input_json_str):
        """
        Function to process work order receipt request
        Parameters:
            - input_json_str is a work order receipt request json
              as per TCF API 7.2 Direct Model Receipt Handling
        """
        input_json = json.loads(input_json_str)
        response = {}
        response['jsonrpc'] = input_json['jsonrpc']
        response['id'] = input_json['id']

        logger.info("Received Work order Receipt request : %s",
                    input_json['method'])
        if (input_json['method'] == "WorkOrderReceiptLookUp"):
            return self.__process_workorder_receipt_lookup(
                input_json_str, response)
        elif (input_json['method'] == "WorkOrderReceiptLookUpNext"):
            return self.__process_workorder_receipt_lookup_next(
                input_json_str, response)

        if 'workOrderId' in input_json_str:
            wo_id = str(input_json['params']['workOrderId'])
        else:
            response = utility.create_error_response(
                WorkorderError.INVALID_PARAMETER_FORMAT_OR_VALUE,
                input_json['id'], "Work order id not found in the database. \
                 Hence invalid parameter")
            return response

        jrpc_id = input_json['id']
        if (input_json['method'] == "WorkOrderReceiptCreate"):
            return self.__process_store_workorder_receipt(
                wo_id, input_json_str, response)
        elif (input_json['method'] == "WorkOrderReceiptUpdate"):
            return self.__process_workorder_receipt_update(
                wo_id, input_json_str, response)
        elif (input_json['method'] == "WorkOrderReceiptRetrieve"):
            return self.__process_workorder_receipt_retrieve(
                wo_id, jrpc_id, response)
        elif (input_json['method'] == "WorkOrderReceiptUpdateRetrieve"):
            return self.__process_workorder_receipt_update_retrieve(
                wo_id, input_json_str, response)
Пример #17
0
    def worker_registry_handler(self, input_json_str):
        """
        Function to process worker request
        Parameters:
            - input_json_str is a worker request json as per TCF API 5.3 Off-Chain Worker Registry JSON RPC API
        """

        input_json = json.loads(input_json_str)
        response = {}
        response['jsonrpc'] = '2.0'
        response['id'] = input_json['id']

        logger.info("Received Worker request : %s", input_json['method'])

        if (input_json['method'] == "WorkerLookUp"):
            return self.__process_worker_lookup(input_json_str, response)
        elif (input_json['method'] == "WorkerLookUpNext"):
            return self.__process_worker_lookup_next(input_json_str, response)

        if 'workerId' in input_json_str:
            worker_id = str(input_json['params']['workerId'])
        else:
            return utility.create_error_response(
                WorkerError.INVALID_PARAMETER_FORMAT_OR_VALUE,
                input_json["id"], "Worker Id not found in the database. \
                     Hence invalid parameter")

        if (input_json['method'] == "WorkerRegister"):
            return self.__process_worker_register(worker_id, input_json_str,
                                                  response)
        elif (input_json['method'] == "WorkerSetStatus"):
            return self.__process_worker_set_status(worker_id, input_json_str,
                                                    response)
        elif (input_json['method'] == "WorkerRetrieve"):
            return self.__process_worker_retrieve(worker_id, response)
        elif (input_json['method'] == "WorkerUpdate"):
            return self.__process_worker_update(worker_id, input_json_str,
                                                response)
Пример #18
0
    def __process_work_order_submission(self, wo_id, input_json_str, response):
        """
        Function to process work order request
        Parameters:
            - wo_id is work order id
            - input_json_str is a work order request json as per TCF API 6.1.1 Work Order Request Payload
            - response is the response object to be returned to client
        """

        input_value_json = json.loads(input_json_str)
        jrpc_id = input_value_json["id"]

        if ((self.workorder_count + 1) > self.max_workorder_count):

            # if max count reached clear a processed entry
            work_orders = self.kv_helper.lookup("wo-timestamps")
            for id in work_orders:

                # If work order is processed then remove from table
                if (self.kv_helper.get("wo-processed", id) is not None):
                    self.kv_helper.remove("wo-processed", id)
                    self.kv_helper.remove("wo-requests", id)
                    self.kv_helper.remove("wo-responses", id)
                    self.kv_helper.remove("wo-receipts", id)
                    self.kv_helper.remove("wo-timestamps", id)

                    self.workorder_list.remove(id)
                    self.workorder_count -= 1
                    break

            # If no work order is processed then return busy
            if ((self.workorder_count + 1) > self.max_workorder_count):
                response = utility.create_error_response(
                    WorkOrderStatus.BUSY, jrpc_id,
                    "Work order handler is busy updating the result")
                return response

        if (self.kv_helper.get("wo-timestamps", wo_id) is None):

            # Create a new work order entry. Don't change the order of table updation.
            # The order is important for clean up if the TCS is restarted in middle
            epoch_time = str(time.time())

            # Update the tables
            self.kv_helper.set("wo-timestamps", wo_id, epoch_time)
            self.kv_helper.set("wo-requests", wo_id, input_json_str)
            self.kv_helper.set("wo-scheduled", wo_id, input_json_str)
            # Add to the internal FIFO
            self.workorder_list.append(wo_id)
            self.workorder_count += 1

            response = utility.create_error_response(
                WorkOrderStatus.PENDING, jrpc_id,
                "Work order is computing. Please query for WorkOrderGetResult"
                + " to view the result")

        else:
            # Workorder id already exists
            response = utility.create_error_response(
                WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE, jrpc_id,
                "Work order id already exists in the database." +
                " Hence invalid parameter")

        return response