예제 #1
0
    def add_in_data(self,
                    data,
                    data_hash=None,
                    encrypted_data_encryption_key=None,
                    data_iv=None):
        """Add inData work order parameter."""
        if data is None:
            return util.create_error_response(
                WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE, 0,
                "Invalid data format for in data")

        in_data_copy = self.params_obj["inData"]
        new_data_list = self.__add_data_params(in_data_copy, data, data_hash,
                                               encrypted_data_encryption_key,
                                               data_iv)

        self.params_obj["inData"] = new_data_list

        code, err_msg = WOcheck.schema_validation("sdk_inData",
                                                  self.params_obj["inData"])
        if not code:
            return util.create_error_response(
                WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE, 0, err_msg)

        return None
예제 #2
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 = 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 = jrpc_utility.create_error_response(
                        WorkOrderStatus.UNKNOWN_ERROR, jrpc_id,
                        "UNKNOWN_ERROR: Error while loading input JSON file")
                    return response

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

        except Exception as err:
            logger.exception('exception while decoding http request %s: %s',
                             request.path, str(err))
            # JRPC response with 0 as id is returned because id can't be
            # fetched from improper request
            response = jrpc_utility.create_error_response(
                WorkOrderStatus.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 Exception as err:
            logger.exception(
                'unknown exception while processing request %s: %s',
                request.path, str(err))
            response = jrpc_utility.create_error_response(
                WorkOrderStatus.UNKNOWN_ERROR, jrpc_id,
                "UNKNOWN_ERROR: unknown exception processing http " +
                "request {0}: {1}".format(request.path, str(err)))
            return response
예제 #3
0
    def render_POST(self, request):
        """
        Handle a POST request to the listener. Decode and delegate to
        _process_request for handling.

        Parameters :
            request - Request coming in from a client
        Returns :
            response - A dict type response
        """
        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':
                input_json_str = data.decode('utf-8')
                response = self._process_request(input_json_str)

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

        except Exception as err:
            logger.exception('exception while decoding http request %s: %s',
                             request.path, str(err))
            # JRPC response with 0 as id is returned because id can't be
            # fetched from improper request
            response = jrpc_utility.create_error_response(
                JRPCErrorCodes.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 Exception as err:
            logger.exception(
                'unknown exception while processing request %s: %s',
                request.path, str(err))
            response = jrpc_utility.create_error_response(
                JRPCErrorCodes.UNKNOWN_ERROR, jrpc_id,
                "UNKNOWN_ERROR: unknown exception processing http " +
                "request {0}: {1}".format(request.path, str(err)))
            return response
예제 #4
0
    def workerType_validation(self, worker_type, json_rpc_request):
        """
        Validate the worker type recived in worker related request

        Parameters:
        worker_type Worker type value derived from the worker's DID
        json_rpc_request    JSON RPC request

        Returns:
        True if worker type is valid
        False with error response if workertype is invalid
        """

        if worker_type is not None:
            if isinstance(worker_type, WorkerType):
                json_rpc_request["params"]["workerType"] = worker_type.value
            elif isinstance(worker_type, int) and \
                    (worker_type in [w.value for w in WorkerType]):
                json_rpc_request["params"]["workerType"] = worker_type
            else:
                return False, create_error_response(
                    JRPCErrorCodes.INVALID_PARAMETER_FORMAT_OR_VALUE,
                    json_rpc_request["id"],
                    "WorkType should be an Integer of range 1-3")

        return True, ""
예제 #5
0
    def _execute_wo_in_trusted_enclave(self, input_json_str):
        """
        Submits workorder request to Worker enclave and retrieves the response

        Parameters :
            input_json_str - A JSON formatted str of the request to execute
        Returns :
            json_response - A JSON response received from the enclave. Errors
                            are also wrapped in a JSON str if exceptions have
                            occurred.
        """
        try:
            pre_proc_output = self._wpe_requester\
                .preprocess_work_order(input_json_str, self.encryption_key)
            if "error" in pre_proc_output:
                # If error in preprocessing response, skip workorder processing
                logger.error("Failed to preprocess at WPE enclave manager.")
                return pre_proc_output

            wo_response = self._send_wo_to_process(input_json_str,
                                                   pre_proc_output)
        except Exception as e:
            logger.error("failed to execute work order; %s", str(e))
            wo_response = create_error_response(WorkOrderStatus.FAILED,
                                                random.randint(0, 100000),
                                                str(e))
            logger.info("unknown enclave type response = %s", wo_response)
        return wo_response
    def _persist_wo_response_to_db(self, wo_id, status,
                                   wo_response=None, msg=None):
        """
        persist the response of a work order processing into the database
        for success as well as failure. Construct response JSON in case
        one is not passed in. Make use of msg field in json.

        Parameters:
            @param wo_id - Id of the work-order being handled
            @param status - WorkOrderStatus of work order ro be persisted
            @param wo_response - Response JSON to be persisted
            @param msg - Message in response in case wo_response is None
        """
        if wo_response is None:
            # Passing jrpc_id as 0 as this will be overridden anyways
            err_response = jrpc_utility.create_error_response(
                WorkOrderStatus.FAILED, "0", msg)
            wo_response = json.dumps(err_response)

        logger.info("Update response in wo-responses for workorder %s.", wo_id)
        self._kv_helper.set("wo-responses", wo_id, wo_response)

        logger.info(
            "Persist work order id %s in wo-worker-processed map.", wo_id)
        # Append wo_id to the list of work orders processed by this worker
        self._kv_helper.csv_append("wo-worker-processed",
                                   self._worker_id, wo_id)
예제 #7
0
    def worker_retrieve(self, worker_id, id=None):
        """
        Retrieve the worker identified by worker ID.

        Parameters:
        worker_id Worker ID value derived from the worker's DID
        id        Optional Optional JSON RPC request ID

        Returns:
        JRPC response containing:
        organization ID, application ID, worker status,
        and worker details.
        """

        if worker_id is None:
            return create_error_response(
                JRPCErrorCodes.INVALID_PARAMETER_FORMAT_OR_VALUE, id,
                "Empty params in the request")

        json_rpc_request = {
            "jsonrpc": "2.0",
            "method": "WorkerRetrieve",
            "id": id,
            "params": {
                "workerId": worker_id
            }
        }
        response = self.__uri_client._postmsg(json.dumps(json_rpc_request))
        return response
예제 #8
0
    def render_GET(self, request):
        # JRPC response with id 0 is returned because id parameter
        # will not be found in GET request
        response = jrpc_utility.create_error_response(
            WorkOrderStatus.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
예제 #9
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"))
예제 #10
0
 def add_encrypted_request_hash(self):
     """
     Calculates request hash based on EEA trusted-computing spec 6.1.8.1
     and set encryptedRequestHash parameter in the request.
     """
     try:
         sig_obj = signature.ClientSignature()
         self.request_hash = sig_obj.calculate_request_hash(self.params_obj)
         encrypted_request_hash = crypto_utility.encrypt_data(
             self.request_hash, self.session_key, self.session_iv)
         enc_request_hash_hex = crypto_utility.byte_array_to_hex(
             encrypted_request_hash)
         self.params_obj["encryptedRequestHash"] = enc_request_hash_hex
         return None
     except Exception as err:
         return util.create_error_response(
             WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE, 0, err)
    def render_GET(self, request):
        """
        Handle a GET request to the listener. Not supported. So only
        error is expected to be returned as response.

        Parameters :
            request - Request coming in from a client
        Returns :
            response - A dict type response which always contains error
        """
        # JRPC response with id 0 is returned because id parameter
        # will not be found in GET request
        response = jrpc_utility.create_error_response(
            JRPCErrorCodes.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
예제 #12
0
    def create_request(self,
                       work_order_id,
                       worker_id,
                       workload_id,
                       requester_id,
                       session_key,
                       session_iv,
                       requester_nonce,
                       verifying_key=None,
                       payload_format="JSON-RPC",
                       response_timeout_msecs=6000,
                       result_uri=None,
                       notify_uri=None,
                       worker_encryption_key=None,
                       data_encryption_algorithm=None,
                       encrypted_session_key=None):
        """validate and creates workorder request with received values"""
        if work_order_id:
            self.set_work_order_id(work_order_id)
        self.set_response_timeout_msecs(response_timeout_msecs)
        self.set_payload_format(payload_format)
        self.set_requester_nonce(requester_nonce)
        self.session_key = session_key
        self.set_workload_id(workload_id)
        self.set_worker_id(worker_id)
        if requester_id is not None:
            self.set_requester_id(requester_id)
        if session_iv:
            self.set_session_key_iv(
                crypto_utility.byte_array_to_hex(session_iv))
        if result_uri:
            self.set_result_uri(result_uri)
        if notify_uri:
            self.set_notify_uri(notify_uri)
        if worker_encryption_key:
            self.set_worker_encryption_key(worker_encryption_key)
        if data_encryption_algorithm:
            self.set_data_encryption_algorithm(data_encryption_algorithm)

        self.set_encrypted_session_key(encrypted_session_key)

        code, err_msg = WOcheck.schema_validation("sdk_WorkOrderSubmit",
                                                  self.params_obj)

        # When the WorkorderSubmit request fails basic Json Validation
        # the init object created is deleted to avoid futhur processing
        # on that object by the user.
        if not code:
            return util.create_error_response(
                WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE, 0, err_msg)

        self.set_worker_encryption_key(
            worker_encryption_key.encode("UTF-8").hex())

        self.session_iv = session_iv
        self.params_obj["encryptedRequestHash"] = ""
        self.params_obj["requesterSignature"] = ""
        self.params_obj["inData"] = list()
        if encrypted_session_key is None:
            try:
                encrypted_session_key = crypto_utility.generate_encrypted_key(
                    session_key, worker_encryption_key)
                self.set_encrypted_session_key(
                    crypto_utility.byte_array_to_hex(encrypted_session_key))
            except Exception as err:
                return util.create_error_response(
                    WorkOrderStatus.INVALID_PARAMETER_FORMAT_OR_VALUE, 0, err)
        return None