def UnitTestRequest(contractid, enclaveid, opk, signature, url): # Sends a secret request to the Provisioning Service and recieves a response: Either the Provisioning Services # Public Key (PSPK) and an accompanying Secret or None if the request has failed # Code to create valid Signature for request # goodsig = self.SigningKey.SignMessage(crypto.string_to_byte_array(enclave_id + contract_id)) # goodsig = crypto.byte_array_to_hex(goodsig) # logger.warn('Good sig: %s', goodsig) provclient = ProvisioningServiceClient(url) secret_info = provclient.get_secret(enclaveid, contractid, opk, signature) if secret_info: print(secret_info) else: print('Secret Request Failed')
def get_pservice_list(state, pservice_group="default"): """create a list of pservice clients from the specified pservice group; assumes exception handling by the calling procedure """ pservice_url_list = state.get( ['Service', 'ProvisioningServiceGroups', pservice_group, 'urls'], []) pservice_client_list = [] for pservice_url in pservice_url_list: pservice_client_list.append(ProvisioningServiceClient(pservice_url)) return pservice_client_list
def create(cls, config, service_url, name=None) : """create a new pservice from a URL and save it """ try : logger.info('create pservice for %s', service_url) pservice_client = ProvisioningServiceClient(service_url) except : logger.warn('failed to retrieve pservice information') return None logger.warn('verifying key: %s', pservice_client.verifying_key) psinfo = pservice_client.get_public_info() logger.warn('pspk: %s', psinfo['pspk']) pservice_object = cls() pservice_object.service_url = service_url pservice_object.service_key = pservice_client.verifying_key pservice_object.file_name = hashlib.sha256(pservice_client.verifying_key.encode('utf8')).hexdigest()[:16] pservice_object.name = name pservice_object.save(config) return pservice_object
def LocalMain(commands, config): # ---------- load the contract ---------- try: ledger_config = config['Sawtooth'] contract_config = config['Contract'] service_config = config['Service'] key_config = config['Key'] except KeyError as ke: logger.error('missing configuration section %s', str(ke)) sys.exit(-1) # ---------- load the invoker's keys ---------- try: keyfile = key_config['FileName'] keypath = key_config['SearchPath'] client_keys = ServiceKeys.read_from_file(keyfile, keypath) except KeyError as ke: logger.error('missing configuration parameter %s', str(ke)) sys.exit(-1) except Exception as e: logger.error('unable to load client keys; %s', str(e)) sys.exit(-1) # ---------- read the contract source code ---------- try: contract_name = contract_config['Name'] data_directory = contract_config['DataDirectory'] save_file = contract_config['SaveFile'] source_file = contract_config['SourceFile'] source_path = contract_config['SourceSearchPath'] contract_code = ContractCode.create_from_scheme_file( contract_name, source_file, source_path) except KeyError as ke: logger.error('missing configuration parameter %s', str(ke)) sys.exit(-1) except Exception as e: logger.error('unable to load contract source; %s', str(e)) sys.exit(-1) logger.info('Loaded contract data for %s', contract_name) # ---------- set up the enclave clients ---------- try: enclaveclients = [] for url in service_config['EnclaveServiceURLs']: enclaveclients.append(EnclaveServiceClient(url)) except Exception as e: logger.error('unable to setup enclave services; %s', str(e)) sys.exit(-1) # ---------- set up the provisioning service clients ---------- # This is a dictionary of provisioning service public key : client pairs try: provclients = [] for url in service_config['ProvisioningServiceURLs']: provclients.append(ProvisioningServiceClient(url)) except Exception as e: logger.error('unable to setup provisioning services; %s', str(e)) sys.exit(-1) logger.debug("All enclaveclients: %s", enclaveclients) logger.debug("All provclients: %s", provclients) # process the commands to create & register the contract if 'register' in commands: try: provisioning_service_keys = [pc.identity for pc in provclients] contract_id = register_contract(ledger_config, client_keys, contract_code, provisioning_service_keys) logger.info('Registered contract %s with id %s', contract_name, contract_id) contract_state = ContractState.create_new_state(contract_id) contract = Contract(contract_code, contract_state, contract_id, client_keys.identity) contract.save_to_file(save_file, data_dir=data_directory) except Exception as e: logger.error('failed to register the contract; %s', str(e)) sys.exit(-1) else: # need to read the contract from the contract file contract = Contract.read_from_file(ledger_config, contract_name, data_directory) if 'addenclave' in commands: encrypted_state_encryption_keys = AddEnclaveSecrets( ledger_config, contract.contract_id, client_keys, enclaveclients, provclients) for enclave_id in encrypted_state_encryption_keys: encrypted_key = encrypted_state_encryption_keys[enclave_id] contract.set_state_encryption_key(enclave_id, encrypted_key) contract.save_to_file(save_file, data_dir=data_directory) logger.info( 'Successfully added enclave secrets to ledger for contract %s', contract_code.name) if 'create' in commands: CreateContract(ledger_config, client_keys, enclaveclients, contract) contract.contract_state.save_to_cache(data_dir=data_directory) contract.save_to_file(save_file, data_dir=data_directory) print('export CONTRACTID={0}'.format(contract.contract_id))
def CreateAndRegisterContract(config, contract_info, creator_keys): ledger_config = config.get('Sawtooth') contract_config = config.get('Contract') contract_creator_id = creator_keys.identity contract_name = contract_info['Name'] source_file = contract_info['Source'] search_path = contract_config['SourceSearchPath'] contract_code = ContractCode.create_from_scheme_file( contract_name, source_file, search_path=search_path) # -------------------------------------------------- logger.info('register the contract') # -------------------------------------------------- pservice_urls = contract_info.get("ProvisioningServices") provisioning_services = list( map(lambda url: ProvisioningServiceClient(url), pservice_urls)) provisioning_service_keys = list( map(lambda svc: svc.identity, provisioning_services)) contract_id = register_contract(ledger_config, creator_keys, contract_code, provisioning_service_keys) logger.info('registered the contract as %s', contract_id) contract_state = ContractState.create_new_state(contract_id) contract = Contract(contract_code, contract_state, contract_id, contract_creator_id) # -------------------------------------------------- logger.info('provision enclaves') # -------------------------------------------------- eservice_urls = contract_info.get("EnclaveServices") enclave_services = list( map(lambda url: GetEnclaveServiceByURL(url), eservice_urls)) for eservice in enclave_services: secret_list = [] for pservice in provisioning_services: message = pcrypto.string_to_byte_array(eservice.enclave_id + contract_id) signature = creator_keys.sign(message) secret = pservice.get_secret(eservice.enclave_id, contract_id, creator_keys.verifying_key, signature) secret_list.append(secret) secretinfo = eservice.verify_secrets(contract_id, contract_creator_id, secret_list) encrypted_state_encryption_key = secretinfo[ 'encrypted_state_encryption_key'] signature = secretinfo['signature'] txnid = add_enclave_to_contract(ledger_config, creator_keys, contract_id, eservice.enclave_id, secret_list, encrypted_state_encryption_key, signature) contract.set_state_encryption_key(eservice.enclave_id, encrypted_state_encryption_key) # -------------------------------------------------- logger.info('create the initial contract state') # -------------------------------------------------- eservice = random.choice(enclave_services) initialize_request = contract.create_initialize_request( creator_keys, eservice) initialize_response = initialize_request.evaluate() if initialize_response.status is False: emessage = initialize_response.result logger.warn('initialization for contract %s failed; %s', contract_name, emessage) raise Exception('initialization failed; {}'.format(emessage)) contract.set_state(initialize_response.encrypted_state) logger.info('initial state created') # -------------------------------------------------- logger.info('save the initial state in the ledger') # -------------------------------------------------- txnid = initialize_response.submit_initialize_transaction(ledger_config, wait=30) return contract
def command_create(state, bindings, pargs) : """controller command to create a contract """ parser = argparse.ArgumentParser(prog='create') parser.add_argument('-c', '--contract-class', help='Name of the contract class', required = True, type=str) parser.add_argument('-s', '--contract-source', help='File that contains contract source code', required=True, type=str) parser.add_argument('-f', '--save-file', help='File where contract data is stored', type=str) options = parser.parse_args(pargs) contract_class = options.contract_class contract_source = options.contract_source contract_file = "{0}.pdo".format(contract_class) if options.save_file : contract_file = options.save_file # ---------- load the invoker's keys ---------- try : keyfile = state.get(['Key', 'FileName']) keypath = state.get(['Key', 'SearchPath']) client_keys = ServiceKeys.read_from_file(keyfile, keypath) except Exception as e : raise Exception('unable to load client keys; {0}'.format(str(e))) # ---------- read the contract source code ---------- try : source_path = state.get(['Contract', 'SourceSearchPath']) contract_code = ContractCode.create_from_scheme_file(contract_class, contract_source, source_path) except Exception as e : raise Exception('unable to load contract source; {0}'.format(str(e))) logger.info('Loaded contract code for %s', contract_class) # ---------- set up the enclave clients ---------- try : eservice_urls = state.get(['Service', 'EnclaveServiceURLs'], []) if len(eservice_urls) == 0 : raise Exception('no enclave services specified') enclaveclients = [] for url in eservice_urls : enclaveclients.append(EnclaveServiceClient(url)) except Exception as e : raise Exception('unable to contact enclave services; {0}'.format(str(e))) # ---------- set up the provisioning service clients ---------- # This is a dictionary of provisioning service public key : client pairs try : pservice_urls = state.get(['Service', 'ProvisioningServiceURLs']) if len(pservice_urls) == 0 : raise Exception('no provisioning services specified') provclients = [] for url in pservice_urls : provclients.append(ProvisioningServiceClient(url)) except Exception as e : raise Exception('unable to contact provisioning services; {0}'.format(str(e))) # ---------- register contract ---------- data_directory = state.get(['Contract', 'DataDirectory']) ledger_config = state.get(['Sawtooth']) try : provisioning_service_keys = [pc.identity for pc in provclients] contract_id = register_contract( ledger_config, client_keys, contract_code, provisioning_service_keys) logger.info('Registered contract with class %s and id %s', contract_class, contract_id) contract_state = ContractState.create_new_state(contract_id) contract = Contract(contract_code, contract_state, contract_id, client_keys.identity) contract.save_to_file(contract_file, data_dir=data_directory) except Exception as e : raise Exception('failed to register the contract; {0}'.format(str(e))) # provision the encryption keys to all of the enclaves try : encrypted_state_encryption_keys = __add_enclave_secrets( ledger_config, contract.contract_id, client_keys, enclaveclients, provclients) for enclave_id in encrypted_state_encryption_keys : encrypted_key = encrypted_state_encryption_keys[enclave_id] contract.set_state_encryption_key(enclave_id, encrypted_key) contract.save_to_file(contract_file, data_dir=data_directory) except Exception as e : raise Exception('failed to provisioning the enclaves; {0}'.format(str(e))) # create the initial contract state try : __create_contract(ledger_config, client_keys, enclaveclients, contract) contract.contract_state.save_to_cache(data_dir = data_directory) contract.save_to_file(contract_file, data_dir=data_directory) except Exception as e : raise Exception('failed to create the initial contract state; {0}'.format(str(e)))
def command_pservice(state, bindings, pargs): """controller command to manage the list of provisioning services """ subcommands = ['add', 'remove', 'set', 'info', 'list'] parser = argparse.ArgumentParser(prog='pservice') subparsers = parser.add_subparsers(dest='command') add_parser = subparsers.add_parser('add') add_parser.add_argument('--url', help='URLs for the provisioning service', type=str, nargs='+', required=True) remove_parser = subparsers.add_parser('remove') remove_parser.add_argument('--url', help='URLs for the provisioning service', type=str, nargs='+', required=True) set_parser = subparsers.add_parser('set') set_parser.add_argument('--url', help='URLs for the provisioning service', type=str, nargs='+', required=True) info_parser = subparsers.add_parser('info') info_parser.add_argument('--url', help='URLs for the provisioning service', type=str, nargs='+') list_parser = subparsers.add_parser('list') options = parser.parse_args(pargs) if options.command == 'add': services = set(state.get(['Service', 'ProvisioningServiceURLs'], [])) services = services.union(options.url) state.set(['Service', 'ProvisioningServiceURLs'], list(services)) return if options.command == 'remove': services = set(state.get(['Service', 'ProvisioningServiceURLs'], [])) services = services.difference(options.url) state.set(['Service', 'ProvisioningServiceURLs'], list(services)) return if options.command == 'set': state.set(['Service', 'ProvisioningServiceURLs'], options.url) return if options.command == 'info': services = state.get(['Service', 'ProvisioningServiceURLs'], []) if options.url: services = options.url for url in services: try: client = ProvisioningServiceClient(url) print("{0} --> {1}".format(url, client.verifying_key)) except: print('unable to retreive information from {0}'.format(url)) return if options.command == 'list': services = set(state.get(['Service', 'ProvisioningServiceURLs'], [])) for service in services: print(service) return raise Exception('unknown subcommand')
def pservice_client(self) : if self.__pservice_client__ is None : self.__pservice_client__ = ProvisioningServiceClient(self.service_url) return self.__pservice_client__