def __init__(self, other=None): if isinstance(other, _Service): self.__dict__ = _copy(other.__dict__) if not self.is_identity_service(): raise IdentityServiceError( "Cannot construct an IdentityService from " "a service which is not an identity service!") else: _Service.__init__(self)
def __init__(self, other=None): if isinstance(other, _Service): self.__dict__ = _copy(other.__dict__) if not self.is_accounting_service(): raise AccountingServiceError( "Cannot construct an AccountingService from " "a service which is not an accounting service!") else: _Service.__init__(self)
def __init__(self, other=None): if isinstance(other, _Service): self.__dict__ = _copy(other.__dict__) if not self.is_access_service(): from Acquire.Access import AccessServiceError raise AccessServiceError( "Cannot construct an AccessService from " "a service which is not an access service!") else: _Service.__init__(self)
def __init__(self, other=None): if isinstance(other, _Service): self.__dict__ = _copy(other.__dict__) if not self.is_compute_service(): from Acquire.Compute import ComputeServiceError raise ComputeServiceError( "Cannot construct a ComputeService from " "a service which is not an compute service!") else: _Service.__init__(self)
def __init__(self, other=None): if isinstance(other, _Service): self.__dict__ = _copy(other.__dict__) if self.service_type() != "hugs": from hugs.Service import HugsServiceError raise HugsServiceError( "Cannot construct a HugsService from a service which is not a hugs service!" ) else: _Service.__init__(self)
def __init__(self, other=None): if isinstance(other, _Service): self.__dict__ = _copy(other.__dict__) if not self.is_storage_service(): from Acquire.Storage import StorageServiceError raise StorageServiceError( "Cannot construct an StorageService from " "a service which is not an storage service!") else: _Service.__init__(self) self._storage_compartment_id = None
def __init__(self, other=None): if isinstance(other, _Service): from copy import copy as _copy self.__dict__ = _copy(other.__dict__) if not self.is_registry_service(): from Acquire.Registry import RegistryServiceError raise RegistryServiceError( "Cannot construct a RegistryService from " "a service which is not a registry service!") else: _Service.__init__(self)
def register(username, password, identity_url=None, service=None): """Request to register a new user with the specified username one the identity service running at 'identity_url', using the supplied 'password'. This will return a QR code that you must use immediately to add this user on the identity service to a QR code generator """ if service is not None: from Acquire.Service import Service as _Service service = _Service.resolve(service, fetch=True)["service"] elif identity_url is not None: from Acquire.Service import Service as _Service service = _Service.resolve(identity_url, fetch=True)["service"] else: service = _get_default_service() from Acquire.Client import Credentials as _Credentials encoded_password = _Credentials.encode_password( identity_uid=service.uid(), password=password) args = {"username": username, "password": encoded_password} result = service.call_function(function="register", args=args) try: provisioning_uri = result["provisioning_uri"] except: from Acquire.Client import UserError raise UserError("Cannot register the user '%s' on " "the identity service at '%s'!" % (username, identity_url)) # return a QR code for the provisioning URI result = {} result["provisioning_uri"] = provisioning_uri try: import re otpsecret = re.search(r"secret=([\w\d+]+)&issuer", provisioning_uri).groups()[0] result["otpsecret"] = otpsecret except: pass try: from Acquire.Client import create_qrcode as _create_qrcode result["qrcode"] = _create_qrcode(provisioning_uri) except: pass return result
def _refresh_this_service_keys_and_certs(service_info, service_password): from Acquire.Service import Service as _Service service = _Service.from_data(service_info, service_password) if service._uid == "STAGE1": return service_info if not service.should_refresh_keys(): return service_info oldkeys = service.dump_keys(include_old_keys=False) # now write the old keys to storage from Acquire.ObjectStore import ObjectStore as _ObjectStore from Acquire.ObjectStore import Mutex as _Mutex from Acquire.Service import get_service_account_bucket as \ _get_service_account_bucket bucket = _get_service_account_bucket() key = "%s/oldkeys/%s" % (_service_key, oldkeys["datetime"]) _ObjectStore.set_object_from_json(bucket, key, oldkeys) # now write the pointers from fingerprint to file... for fingerprint in oldkeys.keys(): if fingerprint not in ["datetime", "encrypted_passphrase"]: _ObjectStore.set_string_object( bucket, "%s/oldkeys/fingerprints/%s" % (_service_key, fingerprint), key) # generate new keys last_update = service.last_key_update() service.refresh_keys() # now lock the object store so that we are the only function # that can write the new keys to global state m = _Mutex(key=service.uid(), bucket=bucket) service_data = _ObjectStore.get_object_from_json(bucket, _service_key) service_info = _Service.from_data(service_data) if service_info.last_key_update() == last_update: # no-one else has beaten us - write the updated keys to global state _ObjectStore.set_object_from_json(bucket, _service_key, service.to_data(service_password)) m.unlock() return service_data
def get_this_service(need_private_access=False): """Return the service info object for this service. If private access is needed then this will decrypt and access the private keys and signing certificates, which is slow if you just need the public certificates. """ assert_running_service() from Acquire.Service import MissingServiceAccountError try: service_info = _get_this_service_data() except MissingServiceAccountError: raise except Exception as e: raise MissingServiceAccountError( "Unable to read the service info from the object store! : %s" % str(e)) service_password = None if need_private_access: service_password = _get_service_password() try: from Acquire.Service import Service as _Service if service_password: service = _Service.from_data(service_info, service_password) else: service = _Service.from_data(service_info) except Exception as e: raise MissingServiceAccountError( "Unable to create the ServiceAccount object: %s %s" % (e.__class__, str(e))) if service.should_refresh_keys(): if service_password is None: service_password = _get_service_password() service_info = _refresh_this_service_keys_and_certs( service_info, service_password) if need_private_access: return _Service.from_data(service_info, service_password) else: return _Service.from_data(service_info) else: return service
def _get_identity_service(identity_url=None): """Function to return the identity service for the system""" if identity_url is None: identity_url = _get_identity_url() privkey = _PrivateKey() response = _call_function(identity_url, response_key=privkey) try: service = _Service.from_data(response["service_info"]) except: raise LoginError("Have not received the identity service info from " "the identity service at '%s' - got '%s'" % (identity_url, response)) if not service.is_identity_service(): raise LoginError( "You can only use a valid identity service to log in! " "The service at '%s' is a '%s'" % (identity_url, service.service_type())) if identity_url != service.service_url(): service.update_service_url(identity_url) return service
def _get_access_service(access_url=None): """Function to return the access service for the system""" if access_url is None: access_url = _get_access_url() privkey = _PrivateKey() response = _call_function(access_url, response_key=privkey) try: service = _Service.from_data(response["service_info"]) except: raise LoginError("Have not received the access service info from " "the access service at '%s' - got '%s'" % (access_url, response)) if not service.is_access_service(): raise LoginError( "You can only use a valid access service to access resources! " "The service at '%s' is a '%s'" % (access_url, service.service_type())) if service.service_url() != access_url: service.update_service_url(access_url) return service
def from_data(data, password=None): """Deserialise this object from the passed data. This will only deserialise the private key and private certificate if the password is supplied """ from Acquire.Service import Service as _Service return _Service.from_data(data, password)
def __init__(self, other=None): if isinstance(other, _Service): self.__dict__ = _copy(other.__dict__) if not self.is_storage_service(): from Acquire.Storage import StorageServiceError raise StorageServiceError( "Cannot construct an StorageService from " "a service which is not an storage service!") # the storage service must define the ID for the compartment # in which user data will be stored self._storage_compartment_id = _os.getenv("STORAGE_COMPARTMENT") else: _Service.__init__(self) self._storage_compartment_id = None
def __init__(self, service=None, service_url=None, service_uid=None, service_type=None): """Construct the service that is accessed at the remote URL 'service_url'. This will fetch and return the details of the remote service. This wrapper is a chameleon class, and will transform into the class type of the fetched service, e.g. service = Acquire.Client.Service("https://identity_service_url") service.__class__ == Acquire.Identity.IdentityService """ if service is not None: from Acquire.Service import Service as _Service service = _Service.resolve(service, fetch=True)["service"] else: try: from Acquire.Client import Wallet as _Wallet service = _Wallet().get_service(service_url=service_url, service_uid=service_uid, service_type=service_type) except Exception as e: self._failed = True raise e from copy import copy as _copy self.__dict__ = _copy(service.__dict__) self.__class__ = service.__class__
def run(args): """Call this function to register a new service with this registry""" service = Service.from_data(args["service"]) challenge = string_to_bytes(args["challenge"]) fingerprint = args["fingerprint"] try: force_new_uid = args["force_new_uid"] except: force_new_uid = False if force_new_uid: force_new_uid = True # respond to the challenge from the service to be registered this_service = get_this_service(need_private_access=True) key = this_service.get_key(fingerprint) response = key.decrypt(challenge) # ok - we can respond to its challenge, so now challenge # it, and if it passes, register the service registry = Registry() service_uid = registry.register_service(service=service, force_new_uid=force_new_uid) return {"service_uid": service_uid, "response": response}
def _get_service(self, service_url): """Return the service data for the passed service""" try: return self._service_info[service_url] except: pass # can we read this from a file? service_file = "%s/certs_%s" % ( ServiceWallet._wallet_dir(), _base64.b64encode(service_url.encode("utf-8")).decode("utf-8")) try: with open(service_file, "rb") as FILE: service_info = _Service.from_data( _unpack_arguments(FILE.read())) self._service_info[service_url] = service_info return service_info except: pass try: key = _PrivateKey() response = _call_function(service_url, response_key=key) service = _Service.from_data(response["service_info"]) except Exception as e: service = None if str(e).find( "You haven't yet created the service account for " "this service. Please create an account first") != -1: return None raise LoginError("Error connecting to the service %s: Error = %s" % (service, str(e))) if service is None: raise LoginError("Error connecting to the service %s. " "Has it been setup?" % service_url) self._service_info[service_url] = service # save this for future reference with open(service_file, "wb") as FILE: FILE.write(_pack_arguments(service.to_data())) return service
def _get_default_service(): """Return the default identity service""" global _default_service if _default_service is None: from Acquire.Service import Service as _Service _default_service = _Service.resolve("fn.acquire-aaai.com/t/identity", fetch=True)["service"] return _default_service
def run(args): """This function is used to request access to a bucket for data in the object store. The user can request read-only or read-write access. Access is granted based on a permission list """ status = 0 message = None access_token = None user_uuid = args["user_uuid"] identity_service_url = args["identity_service"] # log into the central access account bucket = login_to_service_account() # is the identity service supplied by the user one that we trust? identity_service = Service.from_data( ObjectStore.get_object_from_json(bucket, "services/%s" % identity_service_url)) if not identity_service: raise RequestBucketError( "You cannot request a bucket because " "this access service does not know or trust your supplied " "identity service (%s)" % identity_service_url) if not identity_service.is_identity_service(): raise RequestBucketError( "You cannot request a bucket because " "the passed service (%s) is not an identity service. It is " "a %s" % (identity_service_url, identity_service.service_type())) # Since we trust this identity service, we can ask it to give us the # public certificate and signing certificate for this user. key = PrivateKey() response = call_function(identity_service_url, "get_user_keys", args_key=identity_service.public_key(), response_key=key, user_uuid=user_uuid) status = 0 message = "Success: Status = %s" % str(response) return_value = create_return_value(status, message) if access_token: return_value["access_token"] = access_token return return_value
def _related_service(self, service_type): # TODO: Allow the user to specify their preferred services url = self.identity_service_url() if not url.endswith("identity"): raise ValueError("No default accounting service set for this user") from Acquire.Service import Service as _Service url = _rreplace(url, "identity", service_type) return _Service.resolve(url)["service"]
def test_service_object(tmpdir_factory): bucket = tmpdir_factory.mktemp("test_service") push_testing_objstore(bucket) push_is_running_service() try: service = Service.create(service_type="identity", service_url="identity") assert(service.uid() is not None) assert(service.uid().startswith("STAGE1")) service.create_stage2(service_uid="Z9-Z8", response=service.uid()) assert(service.is_identity_service()) assert(not service.should_refresh_keys()) assert(service.is_unlocked()) assert(not service.is_locked()) passphrase = PrivateKey.random_passphrase() data = service.to_data(passphrase) service2 = IdentityService.from_data(data, passphrase) assert(service2.uid() == service.uid()) assert(service2.is_unlocked()) assert(not service2.is_locked()) assert(service2.is_identity_service()) assert(service.canonical_url() == service2.canonical_url()) assert(not service2.should_refresh_keys()) keys = service.dump_keys() keys = service.load_keys(keys) assert(keys[service.private_key().fingerprint()] == service.private_key()) assert(keys[service.private_certificate().fingerprint()] == service.private_certificate()) service.refresh_keys() assert(service.last_key_update() > service2.last_key_update()) assert(service.last_certificate().public_key() == service2.public_certificate()) assert(service.last_key() == service2.private_key()) except: pop_is_running_service() pop_testing_objstore() raise pop_is_running_service() pop_testing_objstore()
def _get_service_info(self, identity_service): """Return the service info for the passed identity service""" try: return self._service_info[identity_service] except: pass # can we read this from a file? service_file = "%s/service_%s" % (Wallet._wallet_dir( ), _base64.b64encode(identity_service.encode("utf-8")).decode("utf-8")) try: with open(service_file, "rb") as FILE: service_info = _Service.from_data( _unpack_arguments(FILE.read())) self._service_info[identity_service] = service_info return service_info except: pass try: key = _PrivateKey() response = _call_function(identity_service, response_key=key) service = _Service.from_data(response["service_info"]) except Exception as e: raise LoginError( "Error connecting to the login service %s: Error = %s" % (identity_service, str(e))) if not service.is_identity_service(): raise LoginError("You cannot log into something that is not " "a valid identity service!") self._service_info[identity_service] = service # save this for future reference with open(service_file, "wb") as FILE: FILE.write(_pack_arguments(service.to_data())) return service
def __init__(self, username=None, service=None, identity_url=None, identity_uid=None, scope=None, permissions=None, auto_logout=True): """Construct the user with specified 'username', who will login to the identity service at specified URL 'identity_url', or with UID 'identity_uid'. You can optionally request a user with a limited scope or limited permissions. Service lookup will be using you wallet. By default, the user will logout when this object is destroyed. Prevent this behaviour by setting auto_logout to False """ self._username = username self._status = _LoginStatus.EMPTY self._identity_service = None self._scope = scope self._permissions = permissions if service is not None: from Acquire.Service import Service as _Service s = _Service.resolve(service, fetch=False) self._identity_url = s["service_url"] self._identity_uid = s["service_uid"] self._identity_service = s["service"] elif (identity_uid is None) and (identity_url is None): service = _get_default_service() self._identity_url = service.canonical_url() self._identity_uid = service.uid() self._identity_service = service else: if identity_url: self._identity_url = identity_url if identity_uid: self._identity_uid = identity_uid else: self._identity_uid = None self._user_uid = None if auto_logout: self._auto_logout = True else: self._auto_logout = False
def get_trusted_services(): """Return a dictionary of all trusted services indexed by their 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 # we already trust ourselves service = _get_this_service() trusted_services = {} trusted_services[service.service_type()] = [service] bucket = _get_service_account_bucket() uidkey = "_trusted/uid/" datas = _ObjectStore.get_all_objects(bucket, uidkey) for data in datas: 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() key = "%s/%s" % (uidkey, remote_service.uid()) _ObjectStore.set_object_from_json(bucket, key, remote_service.to_data()) if remote_service.service_type() in datas: datas[remote_service.service_type()].append(remote_service) else: datas[remote_service.service_type()] = [remote_service] return datas else: # this is running on the client from Acquire.Client import Wallet as _Wallet wallet = _Wallet() return wallet.get_services()
def refresh_service_keys_and_certs(service, force_refresh=False): """This function will check if any key rotation is needed, and if so, it will automatically refresh the keys and certificates. The old keys and certificates will be stored in a database of old keys and certificates """ assert_running_service() if service._uid == "STAGE1": return service if (not force_refresh) and (not service.should_refresh_keys()): return service # ensure that the current keys are saved to the object store save_service_keys_to_objstore() # generate new keys last_update = service.last_key_update() service.refresh_keys() # now lock the object store so that we are the only function # that can write the new keys to global state from Acquire.Service import get_service_account_bucket as \ _get_service_account_bucket from Acquire.Service import Service as _Service from Acquire.ObjectStore import Mutex as _Mutex from Acquire.ObjectStore import ObjectStore as _ObjectStore bucket = _get_service_account_bucket() m = _Mutex(key=service.uid(), bucket=bucket) service_data = _ObjectStore.get_object_from_json(bucket, _service_key) service_info = _Service.from_data(service_data) if service_info.last_key_update() == last_update: # no-one else has beaten us - write the updated keys to global state _ObjectStore.set_object_from_json( bucket, _service_key, service.to_data(_get_service_password())) m.unlock() # clear the cache as we will need to load a new object clear_serviceinfo_cache() return get_this_service(need_private_access=True)
def identity_service(self): """Return the identity service info object for the identity service used to validate the identity of this user """ if self._identity_service is not None: return self._identity_service from Acquire.Service import Service as _Service service = _Service.resolve(service_url=self._identity_url, service_uid=self._identity_uid, fetch=True)["service"] self._identity_service = service self._identity_url = service.canonical_url() self._identity_uid = service.uid() return self._identity_service
def get_service(self, service_url=None, service_uid=None): """Ask the registry to return the service with specified service_url or service_uid """ if service_url is None and service_uid is None: raise PermissionError( "You must specify one of service_url or service_uid") args = {"service_uid": service_uid, "service_url": service_url} response = self.call_function(function="get_service", args=args) from Acquire.Service import Service as _Service service = _Service.from_data(response["service_info"]) return service
def __init__(self, name=None, drive_uid=None, user=None, service=None, creds=None, aclrules=None, cheque=None, max_size=None, autocreate=True): """Construct a handle to the drive that the passed user calls 'name' on the passed storage service. If 'autocreate' is True and the user is logged in then this will automatically create the drive if it doesn't exist already """ self._metadata = None self._creds = None if user is not None: from Acquire.Client import StorageCreds as _StorageCreds from Acquire.Service import Service as _Service if service is None: service = user.storage_service() else: service = _Service.resolve(service, fetch=True)["service"] creds = _StorageCreds(user=user, service=service) if creds is not None: from Acquire.Client import StorageCreds as _StorageCreds if not isinstance(creds, _StorageCreds): raise TypeError("creds must be type StorageCreds") drive = _get_drive(creds=creds, name=name, drive_uid=drive_uid, aclrules=aclrules, autocreate=autocreate) from copy import copy as _copy self.__dict__ = _copy(drive.__dict__)
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 test_service(service_url, aaai_services): # get the public service from the default API frontend privkey = get_private_key("testing") response = call_function(service_url, response_key=privkey) service = Service.from_data(response["service_info"]) # also read the service from the object store directly push_testing_objstore(aaai_services["_services"][service_url]) push_is_running_service() private_service = get_this_service(need_private_access=True) pop_is_running_service() pop_testing_objstore() # create some test data that contain unicode characters for # testing encryption, signing and both encryption and signing data = {"hello": "'å∫ç∂ƒ©˙˚'", "key": privkey.public_key().to_data()} encrypted = service.encrypt_data(data) decrypted = private_service.decrypt_data(encrypted) assert(data == decrypted) signed = private_service.sign_data(data) verified = service.verify_data(signed) assert(data == verified) enc_sign = service.encrypt_data(private_service.sign_data(data)) dec_ver = service.verify_data(private_service.decrypt_data(enc_sign)) assert(data == dec_ver) service.call_function("admin/test") admin_user = aaai_services[service_url]["user"] auth = Authorisation(user=admin_user, resource="dump_keys %s" % service.uid()) service.call_function( function="dump_keys", args={"authorisation": auth.to_data()})