def start_enclave_manager(config):
    """
    Instantiate KvStorage, Execute boot flow and run time flow
    """
    global enclave_data
    if config.get("KvStorage") is None:
        logger.error("Kv Storage path is missing")
        sys.exit(-1)
    try:
        logger.debug("initialize the enclave")
        # Extended measurements is a list of enclave basename and enclave measurement
        extended_measurements = enclave_helper.initialize_enclave(config.get("EnclaveModule"))
    except Exception as e:
        logger.exception("failed to initialize enclave; %s", str(e))
        sys.exit(-1)

    logger.info("creating a new enclave")
    enclave_signup_data = create_enclave_signup_data()

    logger.info("initialize enclave_manager")
    enclave_manager = EnclaveManager(config, enclave_signup_data, extended_measurements)
    logger.info("Enclave manager started")

    try:
        kv_helper = KvStorage()
        kv_helper.open(TCFHOME + "/" + config["KvStorage"]["StoragePath"])
    except:
        logger.error("Failed to open KV storage interface, Exiting SGX Enclave manager...")
        exit(1)

    try:
        logger.info("----------------------- Starting Boot time flow -----------------------")
        enclave_manager.manager_on_boot(kv_helper)
        logger.info("----------------------- Boot time flow Complete -----------------------")
    except:
        logger.error("Failed to execute boot time flow, Exiting SGX Enclave manager...")
        exit(1)

    try:
        sleep_interval = int(config["EnclaveManager"]["sleep_interval"])
    except:
        logger.error("Failed to get sleep interval from config file. setting sleep interval to 10 secs")
        sleep_interval = 10

    try:
        while True:
            # Poll KV storage for new work-order requests and process
            enclave_manager.process_work_orders(kv_helper)
            logger.info("Enclave manager sleeping for %d secs", sleep_interval)
            time.sleep(sleep_interval)
    except:
        logger.error("Error while processing work-order. Shutting down enclave manager")
        exit(1)
Beispiel #2
0
def main():
    logger.info("Testing Direct registry bridge functionality.")

    eth_direct_registry = dir_registry.EthereumDirectRegistry("0x8c99670a15047248403a3E5A38eb8FBE7a12533e",
                                                 '../contracts/WorkerRegistryList.sol')
    kv_storage = KvStorage()
    kv_storage.open("kv_storage")

    logger.info("------------------- test_sync_to_lmdb  ---------------------- \n")
    test_sync_to_lmdb(eth_direct_registry, kv_storage)
    logger.info("\n------------------- test_sync_to_smart_contract  ---------------------- \n")
    test_sync_to_smart_contract(eth_direct_registry, kv_storage)
def main(args=None):
    logger.info(
        "Starting synchronization between Smart contract and KvStorage.")

    # Smart contract address is the address where smart contract is deployed.
    # TODO: Add mechanism to read the address from config file.

    eth_direct_registry = registry.EthereumDirectRegistry("0x8c99670a15047248403a3E5A38eb8FBE7a12533e", \
                                        '../connectors/contracts/WorkerRegistryList.sol')
    kv_storage = KvStorage()
    kv_storage.open("kv_storage")

    while True:
        sync_contract_and_lmdb(eth_direct_registry, kv_storage)
        logger.info("Direct registry bridge is Sleeping off..")
        time.sleep(10)
def open(config):
    """
    @dev open implements a generic API for opening connections to a LMDB
        database where it's local or remote
    @return (conn, type), where
        - conn is the connection helper to interact with db
        - type is 1 for the local LMDB, 2 for the remote LMDB
    """

    kv_config = config.get('KvStorage')
    if kv_config is None:
        raise ValueError("config for KvStorage is missing")

    # employ the remote version if remote_url is set
    if kv_config.get("remote_url") is not None:
        database_url = kv_config["remote_url"]
        logger.info(f"connect to remote LMDB @{database_url}")
        return (LMDBHelperProxy(database_url), 2)

    # otherwise, use the local one
    storage_path = TCFHOME + '/' + kv_config['StoragePath']
    storage_size = kv_config['StorageSize']
    conn = KvStorage()
    if not conn.open(storage_path, storage_size):
        raise ValueError("Failed to open KV Storage DB")

    logger.info(f"employ the local LMDB @{storage_path}")
    return (conn, 1)
Beispiel #5
0
class LMDBRequestHandler(resource.Resource):
    """
    LMDBRequestHandler is comprised of HTTP interface which 
    listens for calls to LMDB
    """
    # The isLeaf instance variable describes whether or not
    # a resource will have children and only leaf resources get rendered.
    # LMDBRequestHandler is the most derived class hence isLeaf is required.

    isLeaf = True

    ## -----------------------------------------------------------------
    def __init__(self, config):

        if config.get('KvStorage') is None:
            logger.error("Kv Storage path is missing")
            sys.exit(-1)

        self.kv_helper = KvStorage()

        storage_path = TCFHOME + '/' + config['KvStorage']['StoragePath']
        if not self.kv_helper.open(storage_path):
            logger.error("Failed to open KV Storage DB")
            sys.exit(-1)

    def __del__(self):
        self.kv_helper.close()

    def _process_request(self, request):
        response = ""
        logger.info(request.encode('utf-8'))
        args = request.split('\n')
        for i in range(len(args)):
            args[i] = unescape(args[i])
        logger.info(args)
        cmd = args[0]

        # Lookup
        if (cmd == "L"):
            if len(args) == 2:
                result_list = self.kv_helper.lookup(args[1])
                result = ""
                for key in result_list:
                    if result == "":
                        result = key
                    else:
                        result = result + "," + key
                # Lookup result found
                if result != "":
                    response = "l\n" + escape(result)
                # No result found
                else:
                    response = "n"
            # Error
            else:
                logger.error("Invalid args for cmd Lookup")
                response = "e\nInvalid args for cmd Lookup"

        # Get
        elif (cmd == "G"):
            if len(args) == 3:
                result = self.kv_helper.get(args[1], args[2])
                # Value found
                if result is not None:
                    response = "v\n" + escape(result)
                # Value not found
                else:
                    response = "n"
            # Error
            else:
                logger.error("Invalid args for cmd Get")
                response = "e\nInvalid args for cmd Get"

        # Set
        elif (cmd == "S"):
            if len(args) == 4:
                result = self.kv_helper.set(args[1], args[2], args[3])
                # Set successful (returned True)
                if result:
                    response = "t"
                # Set unsuccessful (returned False)
                else:
                    response = "f"
            # Error
            else:
                logger.error("Invalid args for cmd Set")
                response = "e\nInvalid args for cmd Set"

        # Remove
        elif (cmd == "R"):
            if len(args) == 3 or len(args) == 4:
                if len(args) == 3:
                    result = self.kv_helper.remove(args[1], args[2])
                else:
                    result = self.kv_helper.remove(args[1],
                                                   args[2],
                                                   value=args[3])
                # Remove successful (returned True)
                if result:
                    response = "t"
                # Remove unsuccessful (returned False)
                else:
                    response = "f"
            # Error
            else:
                logger.error("Invalid args for cmd Remove")
                response = "e\nInvalid args for cmd Remove"
        # Error
        else:
            logger.error("Unknown cmd")
            response = "e\nUnknown cmd"
        return response

    def render_GET(self, request):
        response = 'Only POST request is supported'
        logger.error("GET request is not supported." + \
            " Only POST request is supported")

        return response

    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().decode('utf-8')

            if encoding == 'text/plain; charset=utf-8':
                response = self._process_request(data)
            else:
                response = 'UNKNOWN_ERROR: unknown message encoding'
                return response

        except:
            logger.exception('exception while decoding http request %s',
                             request.path)
            response = 'UNKNOWN_ERROR: unable to decode incoming request '
            return response

        # Send back the results
        try:
            logger.info('response[%s]: %s', encoding, response.encode('utf-8'))
            request.setHeader('content-type', encoding)
            request.setResponseCode(http.OK)
            return response.encode('utf-8')

        except:
            logger.exception('unknown exception while processing request %s',
                             request.path)
            response = 'UNKNOWN_ERROR: unknown exception processing ' + \
                'http request {0}'.format(request.path)
            return response
Beispiel #6
0
class TCSListener(resource.Resource):
    """
    TCSListener Class  is comprised of HTTP interface which listens for the end user requests, 
    Worker Registry Handler, Work Order Handler and Work Order Receipts Handler .
    """
    # The isLeaf instance variable describes whether or not a resource will have children and only leaf resources get rendered.
    # TCSListener is the most derived class hence isLeaf is required.

    isLeaf = True

    ## -----------------------------------------------------------------
    def __init__(self, config):

        if config.get('KvStorage') is None:
            logger.error("Kv Storage path is missing")
            sys.exit(-1)

        storage_path = TCFHOME + '/' + config['KvStorage']['StoragePath']
        self.kv_helper = KvStorage()
        if not self.kv_helper.open(storage_path):
            logger.error("Failed to open KV Storage DB")
            sys.exit(-1)

        # Worker registry handler needs to be instantiated before Work order handler. Otherwise, LMDB operations don't operate on updated values.
        # TODO: Needs further investigation on what is causing the above behavior.

        self.worker_registry_handler = TCSWorkerRegistryHandler(self.kv_helper)
        self.workorder_handler = TCSWorkOrderHandler(
            self.kv_helper, config["Listener"]["max_work_order_count"])
        self.workorder_receipt_handler = TCSWorkOrderReceiptHandler(
            self.kv_helper)
        self.worker_encryption_key_handler = WorkerEncryptionKeyHandler(
            self.kv_helper)

    def _process_request(self, input_json_str):
        response = {}
        response['error'] = {}
        response['error'][
            'code'] = WorkorderError.INVALID_PARAMETER_FORMAT_OR_VALUE

        try:
            input_json = json.loads(input_json_str)
        except:
            response['error'][
                'message'] = 'Error: Improper Json. Unable to load'
            return response

        if ('jsonrpc' not in input_json or 'id' not in input_json
                or 'method' not in input_json or 'params' not in input_json):
            response['error'][
                'message'] = 'Error: Json does not have the required field'
            return response

        if not isinstance(input_json['id'], int):
            response['error'][
                'message'] = 'Error: Id should be of type integer'
            return response

        response['jsonrpc'] = input_json['jsonrpc']
        response['id'] = input_json['id']

        if not isinstance(input_json['method'], str):
            response['error'][
                'message'] = 'Error: Method has to be of type string'
            return response

        if ((input_json['method'] == "WorkOrderSubmit")
                or (input_json['method'] == "WorkOrderGetResult")):
            return self.workorder_handler.process_work_order(input_json_str)
        elif ("WorkOrderReceipt" in input_json['method']):
            return self.workorder_receipt_handler.workorder_receipt_handler(
                input_json_str)
        elif ("Worker" in input_json['method']):
            return self.worker_registry_handler.worker_registry_handler(
                input_json_str)
        elif ("EncryptionKey" in input_json['method']):
            return self.worker_encryption_key_handler.process_encryption_key(
                input_json_str)
        else:
            response['error']['message'] = 'Error: Invalid method field'
            return response

    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

    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
def LocalMain(config) :

    if config.get('KvStorage') is None:
        logger.error("Kv Storage path is missing")
        sys.exit(-1)

    KvHelper = KvStorage()
    KvHelper.open((TCFHOME + '/' + config['KvStorage']['StoragePath']))
    
    if not input_json_str and not input_json_dir:
       logger.error("JSON input file is not provided")
       exit(1)
    
    if not output_json_file_name:
        logger.error("JSON output file is not provided")
        exit(1)
    
    if not server_uri:
        logger.error("Server URI is not provided")
        exit(1)
        
    logger.info('execute work order')
    uri_client = GenericServiceClient(server_uri) 
    
    if input_json_dir:
        directory = os.fsencode(input_json_dir)
        files = os.listdir(directory)
            
        for file in sorted(files) :
            logger.info("------------------Input file name: %s ---------------\n",file.decode("utf-8"))
            input_json_str1 = enclave_helper.read_json_file((directory.decode("utf-8") + file.decode("utf-8")))
            logger.info("*********Request Json********* \n%s\n", input_json_str1)
            response = uri_client._postmsg(input_json_str1)
            logger.info("**********Received Response*********\n%s\n", response)
            
    else :
        j=json.loads(input_json_str)
        
        if(j['method'] == "WorkOrderGetResult"):
            response = {}
            response['id'] =  j['params']['workOrderId']
            response["outData"] = "Processed response"
            KvHelper.set("wo-responses", str(j['params']['workOrderId']), json.dumps(response))
            input_str = json.dumps(j)
            logger.info('input str %s', input_str)
            response = uri_client._postmsg(input_str)
            logger.info("Received Response : %s , \n \n ", response)
            
            j['params']['workOrderId'] = "101"
            input_str = json.dumps(j)
            logger.info('input str %s', input_str)
            response = uri_client._postmsg(input_str)
            logger.info("Received Response : %s , \n \n ", response)
            
            j['params']['workOrderId'] = "121"
            input_str = json.dumps(j)
            logger.info('input str %s', input_str)
            response = uri_client._postmsg(input_str)
            logger.info("Received Response : %s , \n \n ", response)
            
        else:
            id = 100
            logger.info("time stamp lookup  : %s", KvHelper.lookup("wo-timestamps"))
            logger.info("Test adding new time stamps entries")
            for x in range(5):
                j['params']['workOrderId'] = id + x
                input_str = json.dumps(j)
                logger.info('input str %s', input_str)
                response = uri_client._postmsg(input_str)
                logger.info("Received Response : %s , \n \n ", response)
            
                logger.info("time stamp lookup  : %s", KvHelper.lookup("wo-timestamps"))
                
            logger.info("Work order id exists")
            id = 100    
            for x in range(5):
                j['params']['workOrderId'] = id + x
                input_str = json.dumps(j)
                logger.info('input str %s', input_str)
                response = uri_client._postmsg(input_str)
                logger.info("Received Response : %s , \n \n ", response);
            
            logger.info("time stamp lookup  : %s", KvHelper.lookup("wo-timestamps"))
                
            logger.info("Test max count reached and buys status")
            id = 105
            for x in range(10):
                j['params']['workOrderId'] = id + x
                input_str = json.dumps(j)
                logger.info('input str %s', input_str)
                response = uri_client._postmsg(input_str)
                logger.info("Received Response : %s , \n \n ", response);
                
            logger.info("time stamp lookup  : %s", KvHelper.lookup("wo-timestamps"))
            
            logger.info("Adding a work order id 109 into processed table")
            KvHelper.set("wo-processed", "109", "109")
            
            logger.info("Sending a new request with work order id %s", id + x)
            j['params']['workOrderId'] = id + x
            input_str = json.dumps(j)
            logger.info('input str %s', input_str)
            response = uri_client._postmsg(input_str)
            logger.info("Received Response : %s , \n \n ", response);
            
            logger.info("time stamp lookup  : %s", KvHelper.lookup("wo-timestamps"))
            
            work_orders = KvHelper.lookup("wo-scheduled")
            for wo_id in work_orders:
                KvHelper.remove("wo-scheduled", wo_id)
            
            logger.info("adding 3 entries into processing scheduled and processed table to test boot flow")
            KvHelper.set("wo-scheduled", "100", input_str)
            KvHelper.set("wo-processing", "101", input_str)
            KvHelper.set("wo-processed", "102", input_str)
            
            logger.info("restart tcf listener and verify it adds to its internal list during boot up")

    exit(0)
Beispiel #8
0
def LocalMain(config):

    if config.get('KvStorage') is None:
        logger.error("Kv Storage path is missing")
        sys.exit(-1)

    KvHelper = KvStorage()
    KvHelper.open((TCFHOME + '/' + config['KvStorage']['StoragePath']))

    if not input_json_str and not input_json_dir:
        logger.error("JSON input file is not provided")
        exit(1)

    if not output_json_file_name:
        logger.error("JSON output file is not provided")
        exit(1)

    if not server_uri:
        logger.error("Server URI is not provided")
        exit(1)

    logger.info('Execute work order')
    uri_client = GenericServiceClient(server_uri)
    response = None
    if input_json_dir:
        directory = os.fsencode(input_json_dir)
        files = os.listdir(directory)

        for file in sorted(files):
            input_json_str1 = enclave_helper.read_json_file(
                (directory.decode("utf-8") + file.decode("utf-8")))

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

            #If Client request is WorkOrderSubmit,a requester payload’s signature with the requester private signing key is generated.
            if "WorkOrderSubmit" in input_json_str1:
                input_json_str1 = signature_generate(input_json_str1)
                if input_json_str1 is None:
                    continue
            #----------------------------------------------------------------------------------

            # Update the worker ID
            if response:
                if "workerId" in input_json_str1:
                    #Retrieving the worker id from the "WorkerRetrieve" response and update the worker id information for further json requests
                    if 'result' in response and 'ids' in response[
                            "result"].keys():
                        input_json_final = json.loads(input_json_str1)
                        input_json_final['params']['workerId'] = response[
                            'result']['ids'][0]
                        input_json_str1 = json.dumps(input_json_final)
                        logger.info(
                            "**********Worker details Updated with Worker ID*********\n%s\n",
                            response['result']['ids'][0])
            #-----------------------------------------------------------------------------------

            logger.info("*********Request Json********* \n%s\n",
                        input_json_str1)
            response = uri_client._postmsg(input_json_str1)
            logger.info("**********Received Response*********\n%s\n", response)

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

            #Worker details are loaded into Worker_Obj
            if "WorkerRetrieve" in input_json_str1:
                worker_obj.load_worker(response)
            #----------------------------------------------------------------------------------

            # Key already exist test scenario "test_wo_submit_key_already_exist"
            response = uri_client._postmsg(input_json_str1)
            if 'WorkOrderSubmit' in input_json_str1 and 'result' not in response:
                logger.info("*****key already exist *****")
                assert response['error']['message'], 'key already exist'
                assert response['error']['code'], 8
            #----------------------------------------------------------------------------------

            # Polling for the "WorkOrderGetResult" and break when you get the result
            while ('WorkOrderGetResult' in input_json_str1
                   and 'result' not in response):
                response = uri_client._postmsg(input_json_str1)
                logger.info(" Received Response : %s, \n \n ", response)
                time.sleep(3)
            #----------------------------------------------------------------------------------

            #Verify the signature
            if ('WorkOrderGetResult' in input_json_str1):
                sig_bool = verify_signature(json.dumps(response))
            #----------------------------------------------------------------------------------
    else:
        logger.info('Input Request %s', input_json_str)
        input_json_str_1 = signature_generate(input_json_str)
        response = uri_client._postmsg(input_json_str_1)
        logger.info("Received Response : %s , \n \n ", response)
        sig_bool = verify_signature(json.dumps(response))

    exit(0)