def do_verify_cmd(config, args): """subcommand to verify an entry in the database """ parser = argparse.ArgumentParser( prog='verify', description='verify current binding in the database') parser.add_argument('-n', '--name', help='name given to the enclave service', required=True) options = parser.parse_args(args) _load_database_(config) try: ledger_config = config['Ledger'] enclave_info = eservice_db.get_by_name(options.name) if enclave_info is None: print('no enclave with name {0}'.format(options.name)) sys.exit(-1) if not enclave_info.verify(ledger_config): print('verification failed') sys.exit(-1) except Exception as e: logger.error('unable to verify eservice data for %s; %s', options.name, str(e)) sys.exit(-1) print('verification succeeded')
def __expand_eservice_names__(names): result = set() if names: for name in names: eservice_info = eservice_db.get_by_name(name) if eservice_info is None: raise Exception('unknown eservice name {0}'.format(name)) result.add(eservice_info.url) return result
def do_list_cmd(config, args) : """subcommand to list entries in the database """ _load_database_(config) enclave_names = list(eservice_db.get_enclave_names()) enclave_names.sort() for enclave_name in enclave_names : enclave_info = eservice_db.get_by_name(enclave_name) enclave_short_id = _hashed_identity_(enclave_info.enclave_id) print("{0:<18} {1:<18} {2}".format(enclave_name, enclave_short_id, enclave_info.url))
def compute_database_hash(): """compute a hash that we can use to compare two versions of the enclave database """ enclave_names = list(eservice_db.get_enclave_names()) enclave_names.sort() serialized_einfo_list = [] for enclave_name in enclave_names: einfo = eservice_db.get_by_name(enclave_name) serialized_einfo_list.append(einfo.serialize()) serialized_db = json.dumps(serialized_einfo_list) return hash(serialized_db)
def command_eservice_db(state, bindings, pargs): """controller command to manage the enclave service database """ parser = argparse.ArgumentParser(prog='eservice') subparsers = parser.add_subparsers(dest='command') add_parser = subparsers.add_parser( 'add', description='add an eservice to the database') add_parser.add_argument('--url', help='URL for the enclave service to add', type=str, required=True) add_parser.add_argument('--name', help='Short name for the enclave service', type=str, required=True) clear_parser = subparsers.add_parser( 'clear', description='remove all eservices in the database') list_parser = subparsers.add_parser( 'list', description='list eservices in the database') load_parser = subparsers.add_parser( 'load', description='load an eservice database') load_parser.add_argument('--database', help='Name of the eservice database to use', type=str, required=True) merge_group = load_parser.add_mutually_exclusive_group(required=False) merge_group.add_argument('--merge', help='Merge new database with current db', dest='merge', action='store_true') merge_group.add_argument('--no-merge', help='Overwrite current db with new database', dest='merge', action='store_false') load_parser.set_defaults(merge=False) remove_parser = subparsers.add_parser( 'remove', description='remove eservice from the database') remove_group = remove_parser.add_mutually_exclusive_group(required=True) remove_group.add_argument('--name', help='Short name for enclave service to remove', type=str) save_parser = subparsers.add_parser( 'save', description='save the current eservice database') save_parser.add_argument('--database', help='Name of the eservice database to use', type=str, required=True) options = parser.parse_args(pargs) default_database = state.get(['Service', 'EnclaveServiceDatabaseFile']) ledger_config = state.get(['Sawtooth']) if options.command == 'add': if not eservice_db.add_by_url( ledger_config, options.url, name=options.name, update=True): raise Exception( 'failed to add eservice {0} to the database'.format( options.name)) return if options.command == 'clear': eservice_db.clear_all_data() return if options.command == 'list': enclave_names = list(eservice_db.get_enclave_names()) enclave_names.sort() for enclave_name in enclave_names: enclave_info = eservice_db.get_by_name(enclave_name) enclave_short_id = _hashed_identity_(enclave_info.enclave_id) print("{0:<18} {1:<18} {2}".format(enclave_name, enclave_short_id, enclave_info.url)) if options.command == 'load': eservice_db.load_database(options.database, options.merge) return if options.command == 'remove': eservice_db.remove_by_name(name=options.name) return if options.command == 'save': eservice_db.save_database(options.database, True) return raise Exception('unknown subcommand')
def command_eservice(state, bindings, pargs): """controller command to manage the list of enclave services """ subcommands = ['add', 'remove', 'set', 'list', 'create-group', 'use'] parser = argparse.ArgumentParser(prog='eservice') parser.add_argument('--group', help='Name of the eservice group', type=str, default="default") subparsers = parser.add_subparsers(dest='command') subparser = subparsers.add_parser('add') subparser.add_argument('--url', help='URLs for enclave services', type=str, nargs='+') subparser.add_argument('--name', help='EService DB name for enclave services', type=str, nargs='+') subparser = subparsers.add_parser('remove') subparser.add_argument('--url', help='URLs for enclave services', type=str, nargs='+') subparser.add_argument('--name', help='EService DB name for enclave services', type=str, nargs='+') subparser = subparsers.add_parser('set') subparser.add_argument('--url', help='URLs for enclave services', type=str, nargs='+') subparser.add_argument('--name', help='EService DB name for enclave services', type=str, nargs='+') subparser = subparsers.add_parser('list') subparser = subparsers.add_parser('use') eservice_group = subparser.add_mutually_exclusive_group(required=True) eservice_group.add_argument('--url', help='URLs for enclave services', type=str) eservice_group.add_argument('--name', help='EService DB name for enclave services', type=str) eservice_group.add_argument('--random', help='No preferred enclave service', action='store_true') options = parser.parse_args(pargs) if options.command == 'add': services = set( state.get( ['Service', 'EnclaveServiceGroups', options.group, 'urls'], [])) if options.url: services = services.union(options.url) if options.name: services = services.union(__expand_eservice_names__(options.name)) state.set(['Service', 'EnclaveServiceGroups', options.group, 'urls'], list(services)) return if options.command == 'remove': services = set( state.get( ['Service', 'EnclaveServiceGroups', options.group, 'urls'], [])) if options.url: services = services.difference(options.url) if options.name: services = services.difference( __expand_eservice_names__(options.name)) state.set(['Service', 'EnclaveServiceGroups', options.group, 'urls'], list(services)) return if options.command == 'set': services = set() if options.url: services = services.union(options.url) if options.name: services = services.union(__expand_eservice_names__(options.name)) state.set(['Service', 'EnclaveServiceGroups', options.group, 'urls'], list(services)) return if options.command == 'use': if options.random: state.set([ 'Service', 'EnclaveServiceGroups', options.group, 'preferred' ], 'random') return service_url = None if options.url: service_url = options.url if options.name: service_info = eservice_db.get_by_name(options.name) if service_info is None: raise Exception('unknown eservice name; %s', options.name) service_url = service_info.url services = state.get( ['Service', 'EnclaveServiceGroups', options.group, 'urls'], []) if service_url in services: state.set([ 'Service', 'EnclaveServiceGroups', options.group, 'preferred' ], service_url) else: raise Exception('preferred URL not in the service group') return if options.command == 'list': preferred = state.get( ['Service', 'EnclaveServiceGroups', options.group, 'preferred'], 'random') services = state.get( ['Service', 'EnclaveServiceGroups', options.group, 'urls'], []) print("preferred: {0}".format(preferred)) for service in services: print(service) return raise Exception('unknown subcommand')
def command_eservice_db(state, bindings, pargs): """controller command to manage the enclave service database """ parser = argparse.ArgumentParser(prog='eservice_db') parser.add_argument('-q', '--quiet', help='Do not print the result', action='store_true') subparsers = parser.add_subparsers(dest='command') add_parser = subparsers.add_parser( 'add', description='add an eservice to the database') add_parser.add_argument('--url', help='URL for the enclave service to add', type=str, required=True) add_parser.add_argument('--name', help='Short name for the enclave service', type=str, required=True) clear_parser = subparsers.add_parser( 'clear', description='remove all eservices in the database') list_parser = subparsers.add_parser( 'list', description='list eservices in the database') info_parser = subparsers.add_parser( 'info', description='get information about a specific eservice') info_parser.add_argument('--name', help='Short name for enclave service', type=str, required=True) info_parser.add_argument('-s', '--symbol', help='binding symbol for the result', type=str) info_parser.add_argument('-f', '--field', help='field to display', type=str) load_parser = subparsers.add_parser( 'load', description='load an eservice database') load_parser.add_argument('--database', help='Name of the eservice database to use', type=str, required=True) merge_group = load_parser.add_mutually_exclusive_group(required=False) merge_group.add_argument('--merge', help='Merge new database with current db', dest='merge', action='store_true') merge_group.add_argument('--no-merge', help='Overwrite current db with new database', dest='merge', action='store_false') load_parser.set_defaults(merge=False) remove_parser = subparsers.add_parser( 'remove', description='remove eservice from the database') remove_group = remove_parser.add_mutually_exclusive_group(required=True) remove_group.add_argument('--name', help='Short name for enclave service to remove', type=str) save_parser = subparsers.add_parser( 'save', description='save the current eservice database') save_parser.add_argument('--database', help='Name of the eservice database to use', type=str, required=True) options = parser.parse_args(pargs) default_database = state.get(['Service', 'EnclaveServiceDatabaseFile']) ledger_config = state.get(['Ledger']) if options.command == 'add': if not eservice_db.add_by_url( ledger_config, options.url, name=options.name, update=True): raise Exception( 'failed to add eservice {0} to the database'.format( options.name)) return if options.command == 'clear': eservice_db.clear_all_data() return if options.command == 'list': enclave_names = list(eservice_db.get_enclave_names()) enclave_names.sort() for enclave_name in enclave_names: enclave_info = eservice_db.get_by_name(enclave_name) enclave_short_id = _hashed_identity_(enclave_info.enclave_id) print("{0:<18} {1:<18} {2}".format(enclave_name, enclave_short_id, enclave_info.url)) return if options.command == 'info': enclave_info = eservice_db.get_by_name(options.name) enclave_info.verify(state.get(['Ledger'])) enclave = {} enclave['short_name'] = options.name enclave['short_id'] = _hashed_identity_(enclave_info.enclave_id) enclave['enclave_id'] = enclave_info.enclave_id enclave['url'] = enclave_info.url enclave['last_verified_time'] = enclave_info.last_verified_time enclave['interpreter'] = enclave_info.client.interpreter enclave[ 'storage_service_url'] = enclave_info.client.storage_service_url enclave['verifying_key'] = enclave_info.client.verifying_key enclave['encryption_key'] = enclave_info.client.encryption_key result = enclave if options.field: result = enclave[options.field] if not options.quiet: print(json.dumps(result, indent=4, sort_keys=True)) if options.symbol: bindings.bind(options.symbol, result) return if options.command == 'load': eservice_db.load_database(options.database, options.merge) return if options.command == 'remove': eservice_db.remove_by_name(name=options.name) return if options.command == 'save': eservice_db.save_database(options.database, True) return raise Exception('unknown subcommand')
# ----------------------------------------------------------------- # logger.info('create and load the database from the provided URLs') # ----------------------------------------------------------------- names = [] enclave_count = 0 for url in options.url: names.append('enclave_{0}'.format(enclave_count)) eservice_db.add_by_url(ledger_config, url, name=names[enclave_count]) enclave_count += 1 # ----------------------------------------------------------------- # logger.info('verify that the information in the database is consistent') # ----------------------------------------------------------------- for e in names: einfo_by_name = eservice_db.get_by_name(e) einfo_by_enclave_id = eservice_db.get_by_enclave_id( einfo_by_name.client.enclave_id) # this can probably be simplified to just a comparison of # the two objects assert einfo_by_name.name == e assert einfo_by_enclave_id.name == e assert einfo_by_name.name == einfo_by_enclave_id.name assert einfo_by_name.enclave_id == einfo_by_enclave_id.enclave_id # ----------------------------------------------------------------- # logger.info('verify that database can be saved and loaded') # ----------------------------------------------------------------- initial_hash = compute_database_hash() eservice_db.save_database(options.eservice_db, overwrite=True)