Example #1
0
    def _start_kme_listener(self):
        """
        This function reads the host_name and port for the listener to
        bind. It instantiates the KMEListener and starts it. This
        listener runs indefinitely processing requests received from
        WPEs. It terminates only when an exception occurs within start
        method os the listener instance.
        """
        host_name, port = parse_bind_url(
            self._config["KMEListener"].get("bind"))

        rpc_methods = [
            self.GetUniqueVerificationKey, self.RegisterWorkOrderProcessor,
            self.PreProcessWorkOrder
        ]
        self._kme_listener = KMEListener(rpc_methods)
        self._kme_listener.start(host_name, port)
Example #2
0
class KeyManagementEnclaveManager(EnclaveManager):
    """
    Class to manage key management enclave in a worker pool
    setup for processing work orders
    """
    def __init__(self, config):

        super().__init__(config)
        self.proof_data_type = config.get("WorkerConfig")["ProofDataType"]

# -------------------------------------------------------------------------

    def _create_signup_data(self):
        """
        Create KME signup data.

        Returns :
            signup_data - Relevant signup data to be used for requests to the
                          enclave
        """
        return enclave_info.\
            KeyManagementEnclaveInfo(self._config,
                                     self._worker_id,
                                     EnclaveType.KME)

# -------------------------------------------------------------------------

    def _manager_on_boot(self):
        """
        Executes Boot flow of enclave manager
        """
        logger.info("Executing boot time procedure")

        # Cleanup all stale work orders for this worker which
        # used old worker keys
        self._wo_kv_delegate.cleanup_work_orders()

        # Clear all WPEs mapped to this worker_id (pool). WPEs will have
        # to register afresh to get into the pool now.
        self._worker_kv_delegate.cleanup_pool(self._worker_id)

        # Add a new worker
        worker_info = EnclaveManager.create_json_worker(self, self._config)
        # Hex string read from config which is 64 characters long
        self._worker_kv_delegate.add_new_worker(self._worker_id, worker_info)

# -------------------------------------------------------------------------

    def _execute_work_order(self, input_json_str, ext_data=""):
        """
        Submits request to KME and retrieves the response

        Parameters :
            @param input_json_str - A JSON formatted str of the request
            @param ext_data - Extended data to pass to trusted code
        Returns :
            @returns json_response - A JSON formatted str of the response
                                     received from the enclave
        """
        try:
            logger.info("Request sent to enclave %s", input_json_str)
            wo_request = work_order_request.SgxWorkOrderRequest(
                EnclaveType.KME, input_json_str, ext_data)
            wo_response = wo_request.execute()
            logger.info("_execute_work_order Done")
            try:
                json_response = json.dumps(wo_response, indent=4)
                logger.info("Response from enclave %s", json_response)
            except Exception as err:
                logger.error("ERROR: Failed to serialize JSON; %s", str(err))

        except Exception as e:
            logger.error("failed to execute work order; %s", str(e))
            wo_response = dict()
            wo_response["error"] = dict()
            wo_response["error"]["code"] = WorkOrderStatus.FAILED
            wo_response["error"]["message"] = str(e)
            json_response = json.dumps(wo_response, indent=4)

        return json_response

# -------------------------------------------------------------------------

    def start_enclave_manager(self):
        """
        Execute boot flow and run time flow
        """
        try:
            logger.info(
                "--------------- Starting Boot time flow ----------------")
            self._manager_on_boot()
            logger.info(
                "--------------- Boot time flow Complete ----------------")
        except Exception as err:
            logger.error("Failed to execute boot time flow; " +
                         "exiting Intel SGX Enclave manager: {}".format(err))
            exit(1)

        self._start_kme_listener()

# -------------------------------------------------------------------------

    def _start_kme_listener(self):
        """
        This function reads the host_name and port for the listener to
        bind. It instantiates the KMEListener and starts it. This
        listener runs indefinitely processing requests received from
        WPEs. It terminates only when an exception occurs within start
        method os the listener instance.
        """
        host_name, port = parse_bind_url(
            self._config["KMEListener"].get("bind"))

        rpc_methods = [
            self.GetUniqueVerificationKey, self.RegisterWorkOrderProcessor,
            self.PreProcessWorkOrder
        ]
        self._kme_listener = KMEListener(rpc_methods)
        self._kme_listener.start(host_name, port)

# -----------------------------------------------------------------

    def GetUniqueVerificationKey(self, **params):
        """
        RPC method registered with the KME listener to generate an
        unique verification key before a WPE registration.

        Parameters :
            @param params - variable-length argument list
        Returns :
            @returns response - A jrpc response
        """
        logger.info("in kme_enclave_manager.py GetUniqueVerificationKey")
        try:
            wo_request = get_request_json("GetUniqueVerificationKey",
                                          random.randint(0, 100000))
            wo_request["params"] = params
            wo_response = self._execute_work_order(json.dumps(wo_request), "")
            wo_response_json = json.loads(wo_response)

            data = {"workOrderId": wo_request["params"]["workOrderId"]}

            if "result" in wo_response_json:
                return wo_response_json["result"]
            else:
                logger.error("Could not get UniqueVerificationKey - %s",
                             wo_response_json)
                # For all negative cases, response should have an error field.
                # Hence constructing JSONRPC error response with
                # error code and message mapped to KME enclave response
                err_code = wo_response_json["error"]["code"]
                err_msg = wo_response_json["error"]["message"]
                raise JSONRPCDispatchException(err_code, err_msg, data)
        except Exception as e:
            raise JSONRPCDispatchException(WorkOrderStatus.FAILED, str(e),
                                           data)

# -----------------------------------------------------------------

    def RegisterWorkOrderProcessor(self, **params):
        """
        RPC method registered with the KME listener to register a WPE
        with a KME.

        Parameters :
            @param params - variable-length argument list
        Returns :
            @returns response - A jrpc response
        """
        logger.info("in kme_enclave_manager.py RegisterWorkOrderProcessor")

        wo_request = get_request_json("RegisterWorkOrderProcessor",
                                      random.randint(0, 100000))
        wo_request["params"] = params
        wo_response = self._execute_work_order(json.dumps(wo_request), "")
        wo_response_json = json.loads(wo_response)

        logger.info("kme_enclave_manager.py RegisterWorkOrderProcessor Done")
        if "result" in wo_response_json:
            return wo_response_json["result"]
        else:
            logger.error("Could not register WPE")
            return wo_response_json

# -----------------------------------------------------------------

    def PreProcessWorkOrder(self, **params):
        """
        RPC method registered with the KME listener to pre-process a
        work order request.

        Parameters :
            @param params - variable-length argument list
        Returns :
            @returns response - A jrpc response
        """
        wo_request = get_request_json("PreProcessWorkOrder",
                                      random.randint(0, 100000))
        wo_request["params"] = params
        wo_response = self._execute_work_order(json.dumps(wo_request), "")
        wo_response_json = json.loads(wo_response)

        if "result" in wo_response_json:
            return wo_response_json["result"]
        else:
            logger.error("Could not preprocess work order at KME")
            # For all negative cases, response should have an error field.
            # Hence constructing JSONRPC error response with
            # error code and message mapped to KME enclave response
            err_code = wo_response_json["error"]["code"]
            err_msg = wo_response_json["error"]["message"]
            data = {
                "workOrderId": wo_response_json["error"]["data"]["workOrderId"]
            }
            raise JSONRPCDispatchException(err_code, err_msg, data)