def __init__(self, config): super().__init__() self._config = config worker_id = config.get("WorkerConfig")["worker_id"] self._worker_id = hex_utils.get_worker_id_from_name(worker_id) self._kv_helper = self._connect_to_kv_store() self._worker_kv_delegate = WorkerKVDelegate(self._kv_helper) self._wo_kv_delegate = WorkOrderKVDelegate(self._kv_helper, self._worker_id) signup_data, measurements = self._setup_enclave() self.enclave_data = signup_data self.sealed_data = signup_data.sealed_data self.verifying_key = signup_data.verifying_key self.encryption_key = signup_data.encryption_key # TODO: encryption_key_nonce is hardcoded to an empty str # Need to come up with a scheme to generate it for every unique # encryption key. self.encryption_key_nonce = "" self.encryption_key_signature = signup_data.encryption_key_signature self.enclave_id = signup_data.enclave_id self.extended_measurements = measurements self.proof_data = signup_data.proof_data
def __init__(self, config): super().__init__() self._config = config worker_id = config.get("WorkerConfig")["worker_id"] self._worker_id = hex_utils.get_worker_id_from_name(worker_id)
def Main(args=None): options = _parse_command_line(args) config = _parse_config_file(options.config) if config is None: logger.error("\n Error in parsing config file: {}\n".format( options.config)) sys.exit(-1) # mode should be one of listing or registry (default) mode = options.mode # Http JSON RPC listener uri uri = options.uri if uri: config["tcf"]["json_rpc_uri"] = uri # Setting blockchain type # if blockchain parameter is not passed, set to None # and None implies direct mode. blockchain = options.blockchain if blockchain: config['blockchain']['type'] = blockchain # Address of smart contract address = options.address if address: if mode == "listing": config["ethereum"]["direct_registry_contract_address"] = \ address elif mode == "registry": logger.error( "\n Only Worker registry listing address is supported." + "Worker registry address is unsupported \n") sys.exit(-1) # worker id worker_id = options.worker_id worker_id_hex = options.worker_id_hex worker_id = worker_id_hex if not worker_id \ else hex_utils.get_worker_id_from_name(worker_id) # work load id of worker workload_id = options.workload_id if not workload_id: logger.error("\nWorkload id is mandatory\n") sys.exit(-1) # work order input data in_data = options.in_data # show receipt in output show_receipt = options.receipt # show decrypted result in output show_decrypted_output = options.decrypted_output # requester signature for work order requests requester_signature = options.requester_signature # setup logging config["Logging"] = {"LogFile": "__screen__", "LogLevel": "INFO"} plogger.setup_loggers(config.get("Logging", {})) sys.stdout = plogger.stream_to_logger(logging.getLogger("STDOUT"), logging.DEBUG) sys.stderr = plogger.stream_to_logger(logging.getLogger("STDERR"), logging.WARN) logger.info("******* Hyperledger Avalon Generic client *******") if mode == "registry" and address: logger.error("\n Worker registry contract address is unsupported \n") sys.exit(-1) # Retrieve JSON RPC uri from registry list for direct mode. if not uri and mode == "listing": if not blockchain: uri = _retrieve_uri_from_registry_list(config) if uri is None: logger.error("\n Unable to get http JSON RPC uri \n") sys.exit(-1) # Prepare worker worker_registry = _create_worker_registry_instance(blockchain, config) worker_obj, worker_id = _get_first_active_worker(worker_registry, worker_id, config) if worker_obj is None: logger.error("Cannot proceed without a valid worker") sys.exit(-1) # Create session key and iv to sign work order request session_key = crypto_utility.generate_key() session_iv = crypto_utility.generate_iv() s_key = session_key s_iv = session_iv logger.info( "**********Worker details Updated with Worker ID" + "*********\n%s\n", worker_id) # Create work order verification_key = worker_obj.verification_key code, wo_params = _create_work_order_params(worker_id, workload_id, in_data, worker_obj.encryption_key, session_key, session_iv) if not code: logger.error("Work order submission failed") exit(1) client_private_key = crypto_utility.generate_signing_keys() if requester_signature: # Add requester signature and requester verifying_key if wo_params.add_requester_signature(client_private_key) is False: logger.info("Work order request signing failed") exit(1) # Submit work order jrpc_req_id = random.randint(0, 100000) logger.info("Work order submit request : %s, \n \n ", wo_params.to_jrpc_string(jrpc_req_id)) work_order = _create_work_order_instance(blockchain, config) jrpc_req_id += 1 wo_id = wo_params.get_worker_id() response = work_order.work_order_submit(wo_params.get_work_order_id(), wo_params.get_worker_id(), wo_params.get_requester_id(), wo_params.to_string(), id=jrpc_req_id) logger.info("Work order submit response : {}\n ".format(response)) if blockchain is None: if "error" in response and response["error"]["code"] != \ WorkOrderStatus.PENDING: sys.exit(1) else: if response != ContractResponse.SUCCESS: sys.exit(1) # Create receipt wo_receipt = _create_work_order_receipt_instance(blockchain, config) if show_receipt and wo_receipt: jrpc_req_id += 1 _create_work_order_receipt(wo_receipt, wo_params, client_private_key, jrpc_req_id) # Retrieve work order result res = _get_work_order_result(work_order, wo_params.get_work_order_id(), jrpc_req_id + 1) if res: logger.info("Work order get result : {}\n ".format( json.dumps(res, indent=4))) # Check if result field is present in work order response if "result" in res: # Verify work order response signature if _verify_wo_res_signature(res['result'], worker_obj.verification_key, wo_params.get_requester_nonce()) \ is False: logger.error( "Work order response signature verification Failed") sys.exit(1) # Decrypt work order response if show_decrypted_output: decrypted_res = crypto_utility.decrypted_response( res['result'], session_key, session_iv) logger.info("\nDecrypted response:\n {}".format(decrypted_res)) else: logger.error("\n Work order get result failed {}\n".format(res)) sys.exit(1) else: logger.error("\n Work order get result failed {}\n".format(res)) sys.exit(1) if show_receipt and wo_receipt: # Retrieve receipt jrpc_req_id += 1 retrieve_wo_receipt \ = _retrieve_work_order_receipt(wo_receipt, wo_params, jrpc_req_id) # Verify receipt signature if _verify_receipt_signature(retrieve_wo_receipt) is False: logger.error("Receipt signature verification Failed") sys.exit(1)
def Main(args=None): options = _parse_command_line(args) config = _parse_config_file(options.config) if config is None: logger.error("\n Error in parsing config file: {}\n".format( options.config)) sys.exit(-1) # mode should be one of listing or registry (default) mode = options.mode # Http JSON RPC listener uri uri = options.uri if uri: config["tcf"]["json_rpc_uri"] = uri # Address of smart contract address = options.address if address: if mode == "listing": config["ethereum"]["direct_registry_contract_address"] = \ address elif mode == "registry": logger.error( "\n Only Worker registry listing address is supported." + "Worker registry address is unsupported \n") sys.exit(-1) # worker id worker_id = options.worker_id worker_id_hex = options.worker_id_hex worker_id = worker_id_hex if not worker_id \ else hex_utils.get_worker_id_from_name(worker_id) # work load id of worker workload_id = options.workload_id if not workload_id: logger.error("\nWorkload id is mandatory\n") sys.exit(-1) # work order input data in_data = options.in_data # Option to send input data in plain text in_data_plain_text = options.in_data_plain # show receipt in output show_receipt = options.receipt # show decrypted result in output show_decrypted_output = options.decrypted_output # requester signature for work order requests requester_signature = options.requester_signature # setup logging config["Logging"] = {"LogFile": "__screen__", "LogLevel": "INFO"} plogger.setup_loggers(config.get("Logging", {})) sys.stdout = plogger.stream_to_logger(logging.getLogger("STDOUT"), logging.DEBUG) sys.stderr = plogger.stream_to_logger(logging.getLogger("STDERR"), logging.WARN) logger.info("******* Hyperledger Avalon Generic client *******") if mode == "registry" and address: logger.error("\n Worker registry contract address is unsupported \n") sys.exit(-1) # Retrieve JSON RPC uri from registry list if not uri and mode == "listing": uri = _retrieve_uri_from_registry_list(config) if uri is None: logger.error("\n Unable to get http JSON RPC uri \n") sys.exit(-1) # Prepare worker # JRPC request id. Choose any integer value jrpc_req_id = 31 worker_registry = JRPCWorkerRegistryImpl(config) if not worker_id: # Get first worker from worker registry worker_id = _lookup_first_worker(worker_registry, jrpc_req_id) if worker_id is None: logger.error("\n Unable to get worker \n") sys.exit(-1) # Retrieve worker details jrpc_req_id += 1 worker_retrieve_result = worker_registry.worker_retrieve( worker_id, jrpc_req_id) logger.info("\n Worker retrieve response: {}\n".format( json.dumps(worker_retrieve_result, indent=4))) if "error" in worker_retrieve_result: logger.error("Unable to retrieve worker details\n") sys.exit(1) # Create session key and iv to sign work order request session_key = crypto_utility.generate_key() session_iv = crypto_utility.generate_iv() # Initializing Worker Object worker_obj = worker_details.SGXWorkerDetails() worker_obj.load_worker(worker_retrieve_result['result']['details']) # Do worker verification _do_worker_verification(worker_obj) logger.info( "**********Worker details Updated with Worker ID" + "*********\n%s\n", worker_id) # Create work order if in_data_plain_text: # As per TC spec, if encryptedDataEncryptionKey is "-" then # input data is not encrypted encrypted_data_encryption_key = "-" else: # As per TC spec, if encryptedDataEncryptionKey is not # provided then set it to None which means # use default session key to encrypt input data encrypted_data_encryption_key = None wo_params = _create_work_order_params(worker_id, workload_id, in_data, worker_obj.encryption_key, session_key, session_iv, encrypted_data_encryption_key) client_private_key = crypto_utility.generate_signing_keys() if requester_signature: # Add requester signature and requester verifying_key if wo_params.add_requester_signature(client_private_key) is False: logger.info("Work order request signing failed") exit(1) # Submit work order logger.info("Work order submit request : %s, \n \n ", wo_params.to_jrpc_string(jrpc_req_id)) work_order = JRPCWorkOrderImpl(config) jrpc_req_id += 1 response = work_order.work_order_submit(wo_params.get_work_order_id(), wo_params.get_worker_id(), wo_params.get_requester_id(), wo_params.to_string(), id=jrpc_req_id) logger.info("Work order submit response : {}\n ".format( json.dumps(response, indent=4))) if "error" in response and response["error"]["code"] != \ WorkOrderStatus.PENDING: sys.exit(1) # Create receipt wo_receipt = JRPCWorkOrderReceiptImpl(config) if show_receipt: jrpc_req_id += 1 _create_work_order_receipt(wo_receipt, wo_params, client_private_key, jrpc_req_id) # Retrieve work order result jrpc_req_id += 1 res = work_order.work_order_get_result(wo_params.get_work_order_id(), jrpc_req_id) logger.info("Work order get result : {}\n ".format( json.dumps(res, indent=4))) # Check if result field is present in work order response if "result" in res: # Verify work order response signature if _verify_wo_res_signature(res['result'], worker_obj.verification_key, wo_params.get_requester_nonce()) is False: logger.error("Work order response signature verification Failed") sys.exit(1) # Decrypt work order response if show_decrypted_output: decrypted_res = crypto_utility.decrypted_response( res['result'], session_key, session_iv) logger.info("\nDecrypted response:\n {}".format(decrypted_res)) else: logger.error("\n Work order get result failed {}\n".format(res)) sys.exit(1) if show_receipt: # Retrieve receipt jrpc_req_id += 1 retrieve_wo_receipt \ = _retrieve_work_order_receipt(wo_receipt, wo_params, jrpc_req_id) # Verify receipt signature if "result" in retrieve_wo_receipt: if _verify_receipt_signature(retrieve_wo_receipt) is False: logger.error("Receipt signature verification Failed") sys.exit(1) else: logger.info("Work Order receipt retrieve failed") sys.exit(1)
def parse_command_line(args): """Setup and parse command line arguments and help information.""" global worker_obj global worker_id global verbose global config global off_chain global requester_signature parser = argparse.ArgumentParser() use_service = parser.add_mutually_exclusive_group() parser.add_argument("-c", "--config", help="the config file containing the" + " Ethereum contract information", type=str) use_service.add_argument("-r", "--registry-list", help="the Ethereum address of the registry list", type=str) use_service.add_argument("-s", "--service-uri", help="skip URI lookup and send to specified URI", type=str) use_service.add_argument( "-o", "--off-chain", help="skip URI lookup and use the registry in the config file", action="store_true") optional_worker_id = parser.add_mutually_exclusive_group() optional_worker_id.add_argument( "-w", "--worker_id", help="skip worker lookup and retrieve specified worker (plain text)", type=str) optional_worker_id.add_argument( "-wx", "--worker_id_hex", help="skip worker lookup and retrieve specified worker (hex string)", type=str) parser.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true") parser.add_argument( "-rs", "--requester_signature", help="Enable requester signature for work order requests", action="store_true") options = parser.parse_args(args) if options.config: conf_files = [options.config] else: conf_files = [TCFHOME + "/sdk/avalon_sdk/tcf_connector.toml"] conf_paths = ["."] try: config = pconfig.parse_configuration_files(conf_files, conf_paths) json.dumps(config, indent=4) except pconfig.ConfigurationException as e: logger.error(str(e)) sys.exit(-1) global direct_jrpc direct_jrpc = AvalonDirectClient(conf_files[0]) # Whether or not to connect to the registry list on the blockchain off_chain = False if options.registry_list: config["ethereum"]["direct_registry_contract_address"] = \ options.registry_list if options.service_uri: off_chain = True if options.off_chain: off_chain = True requester_signature = options.requester_signature verbose = options.verbose worker_id = options.worker_id worker_id_hex = options.worker_id_hex worker_id = worker_id_hex if not worker_id \ else hex_utils.get_worker_id_from_name(worker_id) # Initializing Worker Object worker_obj = SGXWorkerDetails()
def __init__(self, args): # Parse command line arguments options = self._parse_command_line(args) # Read config params if options.config: self._config = self._parse_config_file(options.config) else: self._config = self._parse_config_file( TCF_HOME + "/sdk/avalon_sdk/tcf_connector.toml") if self._config is None: logging.error("\n Error in parsing config file: {}\n") sys.exit(-1) if options.blockchain: self._config['blockchain']['type'] = options.blockchain self._blockchain = options.blockchain else: self._blockchain = self._config['blockchain']['type'] self._is_direct_mode = False # Mode self._mode = options.mode # Http JSON RPC listener uri self._uri = options.uri if self._uri: self._config["tcf"]["json_rpc_uri"] = self._uri # Address of smart contract self._address = options.address if self._address: if self._mode == "listing": self._config["ethereum"]["direct_registry_contract_address"] =\ self._address elif self._mode == "registry": logging.error( "\n Only Worker registry listing address is supported." + "Worker registry address is unsupported \n") sys.exit(-1) bc_type = self._blockchain if self._uri or self._address: self._is_direct_mode = True elif bc_type == 'fabric' or bc_type == 'ethereum': self._is_direct_mode = False # worker id self._worker_id = options.worker_id self._worker_id_hex = options.worker_id_hex self._worker_id = self._worker_id_hex if not self._worker_id \ else hex_utils.get_worker_id_from_name(self._worker_id) # work load id of worker self._workload_id = options.workload_id if not self._workload_id: logging.error("\nWorkload id is mandatory\n") sys.exit(-1) # work order input data self._in_data = options.in_data # Option to send input data in plain text self._in_data_plain_text = options.in_data_plain # show receipt in output self._show_receipt = options.receipt # show decrypted result in output self._show_decrypted_output = options.decrypted_output # requester signature for work order requests self._requester_signature = options.requester_signature logging.info("******* Hyperledger Avalon Generic client *******") # mode should be one of listing or registry (default) if self._mode == "registry" and self._address: logging.error("\n Worker registry contract" " address is unsupported \n") sys.exit(-1)
def ParseCommandLine(args): global worker_obj global worker_id global message global config global off_chain global requester_signature global input_data_hash parser = argparse.ArgumentParser() use_service = parser.add_mutually_exclusive_group() parser.add_argument( "-c", "--config", help="the config file containing the Ethereum contract information", type=str) use_service.add_argument("-r", "--registry-list", help="the Ethereum address of the registry list", type=str) use_service.add_argument("-s", "--service-uri", help="skip URI lookup and send to specified URI", type=str) use_service.add_argument( "-o", "--off-chain", help="skip URI lookup and use the registry in the config file", action="store_true") mutually_excl_group_worker = parser.add_mutually_exclusive_group( required=True) mutually_excl_group_worker.add_argument( "-w", "--worker_id", help="worker id in plain text to use to submit a work order", type=str) mutually_excl_group_worker.add_argument( "-wx", "--worker_id_hex", help="worker id as hex string to use to submit a work order", type=str) parser.add_argument( "-m", "--message", help='text message to be included in the JSON request payload', type=str) parser.add_argument( "-rs", "--requester-signature", help="Enable requester signature for work order requests", action="store_true") parser.add_argument("-dh", "--data-hash", help="Enable input data hash for work order requests", action="store_true") options = parser.parse_args(args) if options.config: conf_files = [options.config] else: conf_files = [TCFHOME + "/sdk/avalon_sdk/tcf_connector.toml"] confpaths = ["."] try: config = pconfig.parse_configuration_files(conf_files, confpaths) config_json_str = json.dumps(config) except pconfig.ConfigurationException as e: logger.error(str(e)) sys.exit(-1) # Whether or not to connect to the registry list on the blockchain off_chain = False if options.registry_list: config["ethereum"]["direct_registry_contract_address"] = \ options.registry_list if options.service_uri: config["tcf"]["json_rpc_uri"] = options.service_uri off_chain = True if options.off_chain: off_chain = True global direct_jrpc direct_jrpc = AvalonDirectClient(config=config) requester_signature = options.requester_signature input_data_hash = options.data_hash # worker id worker_id = options.worker_id worker_id_hex = options.worker_id_hex worker_id = worker_id_hex if not worker_id \ else hex_utils.get_worker_id_from_name(worker_id) message = options.message if options.message is None or options.message == "": message = "Test Message" # Initializing Worker Object worker_obj = worker.SGXWorkerDetails()