def refetch_trusted_service(service): """Refetch the trusted service 'service'. This will refetch the keys for this service from the registry. This is sometimes needed if we lose the chain of keys to the service (e.g. if the service admin resets the service) """ from Acquire.Service import Service as _Service from Acquire.Registry import get_trusted_registry_service \ as _get_trusted_registry_service s = _Service.resolve(service, fetch=False) registry = _get_trusted_registry_service(service_uid=service.uid()) clear_services_cache() service = registry.get_service(service_uid=s["service_uid"], service_url=s["service_url"]) from Acquire.Service import trust_service as _trust_service _trust_service(service) return service
def _get_service_from_registry(self, service_url=None, service_uid=None): """Return the service fetched from the registry""" from Acquire.Registry import get_trusted_registry_service \ as _get_trusted_registry_service from Acquire.ObjectStore import string_to_safestring \ as _string_to_safestring _output("Connecting to registry...") _flush_output() registry = _get_trusted_registry_service(service_uid=service_uid, service_url=service_url) _output("...connected to registry %s" % registry) _flush_output() # ensure we cache this registry... service_dir = Wallet._get_service_dir(registry.uid()) registry_file = "%s/service_%s.json" % ( service_dir, _string_to_safestring(registry.canonical_url())) _write_service(service=registry, filename=registry_file) if service_url is not None: _output("Securely fetching keys for %s..." % service_url) _flush_output() else: _output("Securely fetching keys for UID %s..." % service_uid) _flush_output() service = registry.get_service(service_url=service_url, service_uid=service_uid) _output("...success.\nFetched %s" % service) _flush_output() return service
def get_trusted_service(service_url=None, service_uid=None, service_type=None, autofetch=True): """Return the trusted service info for the service with specified service_url or service_uid""" if service_url is not None: from Acquire.Service import Service as _Service service_url = _Service.get_canonical_url(service_url, service_type=service_type) from Acquire.Service import is_running_service as _is_running_service if _is_running_service(): from Acquire.Service import get_this_service as _get_this_service from Acquire.Service import Service as _Service from Acquire.Service import get_service_account_bucket as \ _get_service_account_bucket from Acquire.ObjectStore import ObjectStore as _ObjectStore from Acquire.ObjectStore import url_to_encoded as \ _url_to_encoded service = _get_this_service() if service_url is not None and service.canonical_url() == service_url: # we trust ourselves :-) return service if service_uid is not None and service.uid() == service_uid: # we trust ourselves :-) return service bucket = _get_service_account_bucket() uidkey = None data = None if service_uid is not None: uidkey = "_trusted/uid/%s" % service_uid try: data = _ObjectStore.get_object_from_json(bucket, uidkey) except: pass elif service_url is not None: urlkey = "_trusted/url/%s" % _url_to_encoded(service_url) try: uidkey = _ObjectStore.get_string_object(bucket, urlkey) if uidkey is not None: data = _ObjectStore.get_object_from_json(bucket, uidkey) except: pass if data is not None: remote_service = _Service.from_data(data) if remote_service.should_refresh_keys(): # need to update the keys in our copy of the service remote_service.refresh_keys() if uidkey is not None: _ObjectStore.set_object_from_json(bucket, uidkey, remote_service.to_data()) return remote_service if not autofetch: from Acquire.Service import ServiceAccountError if service_uid is not None: raise ServiceAccountError( "We do not trust the service with UID '%s'" % service_uid) else: raise ServiceAccountError( "We do not trust the service at URL '%s'" % service_url) # we can try to fetch this data - we will ask our own # registry from Acquire.Registry import get_trusted_registry_service \ as _get_trusted_registry_service registry = _get_trusted_registry_service(service_uid=service.uid()) service = registry.get_service(service_uid=service_uid, service_url=service_url) from Acquire.Service import trust_service as _trust_service _trust_service(service) return service else: # this is running on the client from Acquire.Client import Wallet as _Wallet wallet = _Wallet() service = wallet.get_service(service_uid=service_uid, service_url=service_url, service_type=service_type, autofetch=autofetch) return service
def register_service(service, registry_uid): """Call this function to register the passed new service with the specified registry_uid. This function will complete registration and construction of the service """ from Acquire.Service import Service as _Service if not isinstance(service, _Service): raise TypeError("You can only register Service objects") if not service.uid().startswith("STAGE1"): raise PermissionError( "You can only register services that are at STAGE1 of " "construction") if service.service_type() == "registry": from Acquire.Registry import get_registry_details \ as _get_registry_details details = _get_registry_details(registry_uid=registry_uid) from Acquire.Service import Service as _Service canonical_url = _Service.get_canonical_url(details["canonical_url"]) # make sure that everything matches what was specified if canonical_url != service.canonical_url(): raise PermissionError( "Cannot change the canonical URL. I expect %s, but " "you are trying to set to %s" % (service.canonical_url(), details["canonical_url"])) from Acquire.Registry import update_registry_keys_and_certs \ as _update_registry_keys_and_certs _update_registry_keys_and_certs( registry_uid=registry_uid, public_key=service.public_key(), public_certificate=service.public_certificate()) service.create_stage2(service_uid=registry_uid, response=service._uid) return service # get the trusted registry from Acquire.Registry import get_trusted_registry_service \ as _get_trusted_registry_service registry_service = _get_trusted_registry_service(service_uid=registry_uid) if not registry_service.is_registry_service(): raise PermissionError( "You can only register new services on an existing and valid " "registry service. Not %s" % registry_service) from Acquire.ObjectStore import bytes_to_string as _bytes_to_string pubkey = registry_service.public_key() challenge = pubkey.encrypt(service.uid()) args = { "service": service.to_data(), "challenge": _bytes_to_string(challenge), "fingerprint": pubkey.fingerprint() } result = registry_service.call_function(function="register_service", args=args) service_uid = result["service_uid"] response = result["response"] service.create_stage2(service_uid=service_uid, response=response) return service
def get_service(self, service_url=None, service_uid=None, service_type=None, autofetch=True): """Return the service at either 'service_url', or that has UID 'service_uid'. This will return the cached service if it exists, or will add a new service if we are able to validate it from a trusted registry """ from Acquire.ObjectStore import string_to_safestring \ as _string_to_safestring service = None if service_url is None: if service_uid is None: raise PermissionError( "You need to specify one of service_uid or service_url") # we need to look up the name... import glob as _glob service_files = _glob.glob("%s/service_*" % self._wallet_dir) for service_file in service_files: s = _read_service(service_file) if s.uid() == service_uid: service = s break else: from Acquire.Service import Service as _Service service_url = _Service.get_canonical_url(service_url, service_type=service_type) service_file = "%s/service_%s" % ( self._wallet_dir, _string_to_safestring(service_url)) try: service = _read_service(service_file) except: pass must_write = False if service is None: if not autofetch: from Acquire.Service import ServiceError raise ServiceError("No service at %s:%s" % (service_url, service_uid)) # we need to look this service up from the registry from Acquire.Registry import get_trusted_registry_service \ as _get_trusted_registry_service _output("Connecting to registry...") _flush_output() registry = _get_trusted_registry_service(service_uid=service_uid, service_url=service_url) _output("...connected to registry %s" % registry) _flush_output() # ensure we cache this registry... registry_file = "%s/service_%s" % ( self._wallet_dir, _string_to_safestring(registry.canonical_url())) _write_service(service=registry, filename=registry_file) if service_url is not None: _output("Securely fetching keys for %s..." % service_url) _flush_output() else: _output("Securely fetching keys for UID %s..." % service_uid) _flush_output() service = registry.get_service(service_url=service_url, service_uid=service_uid) _output("...success.\nFetched %s" % service) _flush_output() must_write = True # check if the keys need rotating - if they do, load up # the new keys and save them to the service file... if service.should_refresh_keys(): service.refresh_keys() must_write = True if service_uid is not None: if service.uid() != service_uid: raise PermissionError( "Disagreement over the service UID for '%s' (%s)" % (service, service_uid)) if must_write: service_file = "%s/service_%s" % ( self._wallet_dir, _string_to_safestring(service.canonical_url())) _write_service(service=service, filename=service_file) return service