Exemple #1
0
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')
Exemple #2
0
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
Exemple #3
0
    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
Exemple #4
0
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))
Exemple #5
0
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
Exemple #6
0
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')
Exemple #8
0
    def pservice_client(self) :
        if self.__pservice_client__ is None :
            self.__pservice_client__ = ProvisioningServiceClient(self.service_url)

        return self.__pservice_client__