Exemple #1
0
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
Exemple #2
0
    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
Exemple #3
0
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
Exemple #5
0
    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