コード例 #1
0
def deposit(user, value, description=None,
            accounting_service=None, accounting_url=None):
    """Tell the system to allow the user to deposit 'value' from
       their (real) financial account to the system accounts
    """
    authorisation = _Authorisation(user=user)

    if accounting_service is None:
        accounting_service = _get_accounting_service(accounting_url)
    else:
        if not accounting_service.is_accounting_service():
            raise TypeError("You can only deposit funds using an "
                            "accounting service!")

    args = {"authorisation": authorisation.to_data()}

    if description is None:
        args["value"] = str(_create_decimal(value))
    else:
        args["transaction"] = _Transaction(value, description).to_data()

    privkey = _PrivateKey()

    result = _call_function(
                    accounting_service.service_url(), "deposit",
                    args=args,
                    args_key=accounting_service.public_key(),
                    response_key=privkey,
                    public_cert=accounting_service.public_certificate())

    return result
コード例 #2
0
ファイル: _user.py プロジェクト: michellab/BioSimSpaceCloud
    def logout(self):
        """Log out from the current session"""
        if self.is_logged_in() or self.is_logging_in():
            identity_url = self.identity_service_url()

            if identity_url is None:
                return

            # create a permission message that can be signed
            # and then validated by the user
            permission = "Log out request for %s" % self._session_uid
            signature = self.signing_key().sign(permission)

            print("Logging out %s from session %s" %
                  (self._username, self._session_uid))

            result = _call_function(
                identity_url,
                "logout",
                args_key=self.identity_service().public_key(),
                username=self._username,
                session_uid=self._session_uid,
                permission=permission,
                signature=_bytes_to_string(signature))
            print(result)

            self._status = _LoginStatus.LOGGED_OUT

            return result
コード例 #3
0
    def refund(self, credit_note):
        """Refunds the passed credit note that contained a transfer of
           from another account to the passed account
        """
        if not self.is_logged_in():
            raise PermissionError("You cannot refund a credit note as the "
                                  "user has not yet logged in!")

        if credit_note.account_uid() != self.uid():
            raise ValueError(
                "You cannot refund a transaction from a different "
                "account! %s versus %s" % (credit_note.account_uid(),
                                           self.uid()))

        auth = _Authorisation(resource=self._account_uid, user=self._user)

        args = {"credit_note": credit_note.to_data(),
                "authorisation": auth.to_data()}

        privkey = _PrivateKey()

        result = _call_function(
                    self._accounting_service.service_url(), "refund",
                    args=args,
                    args_key=self._accounting_service.public_key(),
                    response_key=privkey,
                    public_cert=self._accounting_service.public_certificate())

        return result["transaction_record"]
コード例 #4
0
ファイル: _user.py プロジェクト: michellab/BioSimSpaceCloud
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
コード例 #5
0
ファイル: _user.py プロジェクト: michellab/BioSimSpaceCloud
def get_session_keys(username=None,
                     user_uid=None,
                     session_uid=None,
                     identity_url=None):
    """Function to return the session keys for the specified user"""
    if username is None and user_uid is None:
        raise ValueError("You must supply either the username or user_uid!")

    if session_uid is None:
        raise ValueError("You must supply a valid UID for a login session")

    if identity_url is None:
        identity_url = _get_identity_url()

    response = _call_function(identity_url,
                              "whois",
                              username=username,
                              user_uid=user_uid,
                              session_uid=session_uid)

    try:
        response["public_key"] = _PublicKey.from_data(response["public_key"])
    except:
        pass

    try:
        response["public_cert"] = _PublicKey.from_data(response["public_cert"])
    except:
        pass

    return response
コード例 #6
0
def _get_account_uids(user, accounting_service=None, accounting_url=None):
    """Return the names and UIDs of all of the accounts that belong
        to the passed user on the passed accounting_service
    """
    if accounting_service is None:
        accounting_service = _get_accounting_service(accounting_url)

    elif not accounting_service.is_accounting_service():
        raise ValueError("You can only query account using "
                         "a valid accounting service")

    if not user.is_logged_in():
        raise PermissionError(
            "You can only get information about about a user's accounts "
            "if they have authenticated their login")

    auth = _Authorisation(user=user)
    args = {"authorisation": auth.to_data()}

    privkey = _PrivateKey()

    result = _call_function(
            accounting_service.service_url(), "get_account_uids",
            args=args,
            args_key=accounting_service.public_key(),
            response_key=privkey,
            public_cert=accounting_service.public_certificate())

    return result["account_uids"]
コード例 #7
0
ファイル: _user.py プロジェクト: michellab/BioSimSpaceCloud
    def _poll_session_status(self):
        """Function used to query the identity service for this session
           to poll for the session status"""

        identity_url = self.identity_service_url()

        if identity_url is None:
            return

        result = _call_function(identity_url,
                                "get_status",
                                username=self._username,
                                session_uid=self._session_uid)

        # look for status = 0
        try:
            status = int(result["status"])
        except:
            status = -1

        try:
            message = result["message"]
        except:
            message = str(result)

        if status != 0:
            error = "Failed to query identity service. Error = %d. " \
                    "Message = %s" % (status, message)
            self._set_error_state(error)
            raise LoginError(error)

        # now update the status...
        status = result["session_status"]
        self._set_status(status)
コード例 #8
0
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
コード例 #9
0
ファイル: _user.py プロジェクト: michellab/BioSimSpaceCloud
    def register(self, password, identity_url=None):
        """Request to register this user with 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 self._username is None:
            return None

        if identity_url is None:
            identity_url = _get_identity_url()

        privkey = _PrivateKey()

        result = _call_function(
            identity_url,
            "register",
            args_key=self.identity_service().public_key(),
            response_key=privkey,
            public_cert=self.identity_service().public_certificate(),
            username=self._username,
            password=password)

        try:
            provisioning_uri = result["provisioning_uri"]
        except:
            raise UserError("Cannot register the user '%s' on "
                            "the identity service at '%s'!" %
                            (self._username, identity_url))

        # return a QR code for the provisioning URI
        return (provisioning_uri, _create_qrcode(provisioning_uri))
コード例 #10
0
ファイル: _user.py プロジェクト: michellab/BioSimSpaceCloud
def username_to_uid(username, identity_url=None):
    """Function to return the uid for the passed username"""
    if identity_url is None:
        identity_url = _get_identity_url()

    response = _call_function(identity_url, "whois", username=str(username))

    return response["user_uid"]
コード例 #11
0
ファイル: _user.py プロジェクト: michellab/BioSimSpaceCloud
def uid_to_username(user_uid, identity_url=None):
    """Function to return the username for the passed uid"""
    if identity_url is None:
        identity_url = _get_identity_url()

    response = _call_function(identity_url, "whois", user_uid=str(user_uid))

    return response["username"]
コード例 #12
0
    def _refresh(self, force_update=False):
        """Refresh the current status of this account. This fetches
           the latest data, e.g. balance, limits etc. Note that this
           limits you to refreshing at most once every five seconds...
        """
        if self.is_null():
            self._overdraft_limit = _create_decimal(0)
            self._balance = _create_decimal(0)
            self._liability = _create_decimal(0)
            self._receivable = _create_decimal(0)
            self._spent_today = _create_decimal(0)
            return

        if force_update:
            should_refresh = True
        else:
            should_refresh = False

            if self._last_update is None:
                should_refresh = True
            else:
                should_refresh = (_datetime.datetime.now() -
                                  self._last_update).seconds > 5

        if not should_refresh:
            return

        if not self.is_logged_in():
            raise PermissionError(
                "You cannot get information about this account "
                "until after the owner has successfully authenticated.")

        auth = _Authorisation(resource=self._account_uid, user=self._user)

        args = {"authorisation": auth.to_data(),
                "account_name": self.name()}

        privkey = _PrivateKey()

        result = _call_function(
                    self._accounting_service.service_url(), "get_info",
                    args=args,
                    args_key=self._accounting_service.public_key(),
                    response_key=privkey,
                    public_cert=self._accounting_service.public_certificate())

        self._overdraft_limit = _create_decimal(result["overdraft_limit"])
        self._balance = _create_decimal(result["balance"])
        self._liability = _create_decimal(result["liability"])
        self._receivable = _create_decimal(result["receivable"])
        self._spent_today = _create_decimal(result["spent_today"])
        self._description = result["description"]

        self._last_update = _datetime.datetime.now()
コード例 #13
0
def create_account(user, account_name, description=None,
                   accounting_service=None, accounting_url=None):
    """Create an account on the accounting service for the passed
        user, calling the account 'account_name' and optionally
        passing in an account description. Note that the user must
        have authorised the login
    """
    if accounting_service is None:
        accounting_service = _get_accounting_service(accounting_url)

    elif not accounting_service.is_accounting_service():
        raise ValueError("You can only create an account by connecting "
                         "to a valid accounting service")

    if not user.is_logged_in():
        raise PermissionError(
            "You cannot create an account called '%s' for user "
            "'%s' as the user login has not been authenticated." %
            (account_name, user.name()))

    authorisation = _Authorisation(user=user)

    args = {"account_name": str(account_name),
            "authorisation": authorisation.to_data()}

    if description is None:
        args["description"] = "Account '%s' for '%s'" % \
                                (str(account_name), user.name())
    else:
        args["description"] = str(description)

    privkey = _PrivateKey()

    result = _call_function(
                accounting_service.service_url(), "create_account",
                args=args,
                args_key=accounting_service.public_key(),
                response_key=privkey,
                public_cert=accounting_service.public_certificate())

    account_uid = result["account_uid"]

    account = Account()
    account._account_name = account_name
    account._account_uid = account_uid
    account._user = user
    account._accounting_service = accounting_service

    return account
コード例 #14
0
    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
コード例 #15
0
    def perform(self, transaction, credit_account, is_provisional=False):
        """Tell this accounting service to apply the transfer described
           in 'transaction' from this account to the passed account. Note
           that the user must have logged into this account so that they
           have authorised this transaction. This returns the record
           of this transaction
        """
        if not self.is_logged_in():
            raise PermissionError("You cannot transfer value from '%s' to "
                                  "'%s' because you have not authenticated "
                                  "the user who owns this account" %
                                  (str(self), str(credit_account)))

        if not isinstance(transaction, _Transaction):
            raise TypeError("The passed transaction must be of type "
                            "Transaction")

        if not isinstance(credit_account, Account):
            raise TypeError("The passed credit account must be of type "
                            "Account")

        if transaction.is_null():
            return None

        auth = _Authorisation(resource=self._account_uid, user=self._user)

        if is_provisional:
            is_provisional = True
        else:
            is_provisional = False

        args = {"transaction": transaction.to_data(),
                "debit_account_uid": str(self.uid()),
                "credit_account_uid": str(credit_account.uid()),
                "is_provisional": is_provisional,
                "authorisation": auth.to_data()}

        privkey = _PrivateKey()

        result = _call_function(
                    self._accounting_service.service_url(), "perform",
                    args=args,
                    args_key=self._accounting_service.public_key(),
                    response_key=privkey,
                    public_cert=self._accounting_service.public_certificate())

        return result["transaction_records"]
コード例 #16
0
    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
コード例 #17
0
def _get_account_uid(user, account_name, accounting_service=None,
                     accounting_url=None):
    """Return the UID of the account called 'account_name' that
        belongs to passed user on the passed accounting_service
    """
    if account_name is None:
        # return the UID of the default account for this user
        account_name = "main"

    if accounting_service is None:
        accounting_service = _get_accounting_service(accounting_url)

    elif not accounting_service.is_accounting_service():
        raise ValueError("You can only query account using "
                         "a valid accounting service")

    args = {"user_uid": user.uid(),
            "account_name": str(account_name)}

    if user.is_logged_in():
        auth = _Authorisation(user=user)
        args["authorisation"] = auth.to_data()

    privkey = _PrivateKey()

    result = _call_function(
            accounting_service.service_url(), "get_account_uids",
            args=args,
            args_key=accounting_service.public_key(),
            response_key=privkey,
            public_cert=accounting_service.public_certificate())

    account_uids = result["account_uids"]

    for account_uid in account_uids:
        if account_uids[account_uid] == account_name:
            return account_uid

    raise AccountError("There is no account called '%s' for '%s'" %
                       (account_name, str(user)))
コード例 #18
0
    def challenge_service(self, service):
        """Send a challenge to the passed service, returning the actual
           service returned. This will only pass if our copy of the
           service matches us with the copy returned from the actual
           service. This verifies that there is a real service sitting
           at that URL, and that we have the right keys and certs
        """
        from Acquire.Crypto import PrivateKey as _PrivateKey
        from Acquire.ObjectStore import bytes_to_string as _bytes_to_string
        from Acquire.Service import Service as _Service

        challenge = _PrivateKey.random_passphrase()
        pubkey = service.public_key()
        encrypted_challenge = pubkey.encrypt(challenge)

        args = {"challenge": _bytes_to_string(encrypted_challenge),
                "fingerprint": pubkey.fingerprint()}

        if service.uid().startswith("STAGE"):
            # we cannot call using the service directly, as it is
            # not yet fully constructed
            from Acquire.Service import get_this_service as _get_this_service
            from Acquire.Service import call_function as _call_function
            this_service = _get_this_service(need_private_access=True)
            result = _call_function(service_url=service.service_url(),
                                    function=None,
                                    args=args,
                                    args_key=service.public_key(),
                                    response_key=this_service.private_key(),
                                    public_cert=service.public_certificate())
        else:
            result = service.call_function(function=None, args=args)

        if result["response"] != challenge:
            raise PermissionError(
                "Failure of the service %s to correctly respond "
                "to the challenge!" % service)

        return _Service.from_data(result["service_info"])
コード例 #19
0
    def whois(self, username=None, user_uid=None, session_uid=None):
        """Do a whois lookup to map from username to user_uid or
           vice versa. If 'session_uid' is provided, then also validate
           that this is a correct login session, and return also
           the public key and signing certificate for this login session.

           This should return a dictionary with the following keys
           optionally contained;

           username = name of the user
           user_uid = uid of the user
           public_key = public key for the session with uid 'session_uid'
           public_cert = public certificate for that login session
        """

        if (username is None) and (user_uid is None):
            raise IdentityServiceError("You must supply either a username "
                                       "or a user's UID for a lookup")

        key = _PrivateKey()

        response = None

        if session_uid is None:
            args = {}
        else:
            args = {"session_uid": str(session_uid)}

        try:
            if username:
                args["username"] = str(username)
                response = _call_function(
                    self.service_url(),
                    "whois",
                    public_cert=self.public_certificate(),
                    response_key=key,
                    args=args)
                lookup_uid = response["user_uid"]
            else:
                lookup_uid = None

            if user_uid:
                args["user_uid"] = str(user_uid)
                response = _call_function(
                    self.service_url(),
                    "whois",
                    public_cert=self.public_certificate(),
                    response_key=key,
                    args=args)
                lookup_username = response["username"]
            else:
                lookup_username = None

        except Exception as e:
            raise IdentityServiceError("Failed whois lookup: %s" % str(e))

        if username is None:
            username = lookup_username

        elif (lookup_username is not None) and (username != lookup_username):
            raise IdentityServiceError(
                "Disagreement of the user who matches "
                "UID=%s. We think '%s', but the identity service says '%s'" %
                (user_uid, username, lookup_username))

        if user_uid is None:
            user_uid = lookup_uid

        elif (lookup_uid is not None) and (user_uid != lookup_uid):
            raise IdentityServiceError(
                "Disagreement of the user's UID for user "
                "'%s'. We think %s, but the identity service says %s" %
                (username, user_uid, lookup_uid))

        result = response

        try:
            result["public_key"] = _PublicKey.from_data(response["public_key"])
        except:
            pass

        try:
            result["public_cert"] = _PublicKey.from_data(
                response["public_cert"])
        except:
            pass

        return result
コード例 #20
0
    def call_admin_function(self,
                            function,
                            args={},
                            service_url=None,
                            remember_password=True,
                            remember_device=None):
        """Call the admin function 'function' using supplied arguments 'args',
           on the service at 'service_url'
        """

        self._manual_password = False
        self._manual_otpcode = False

        if not remember_password:
            remember_device = False

        if not service_url:
            # choose a service_url from any existing files...
            service_url = self._get_service_url()

        # get the public key of this identity service
        service_key = self._get_service_key(service_url)
        service_cert = self._get_service_cert(service_url)

        password = self._get_admin_password(service_url)
        otpcode = self._get_otpcode(service_url)

        strargs = str(args)

        args["password"] = password
        args["otpcode"] = otpcode
        args["remember_device"] = remember_device

        print("\nCalling '%s' with %s... " % (function, strargs), end="")
        _sys.stdout.flush()

        try:
            key = _PrivateKey()
            response = _call_function(service_url,
                                      function,
                                      args_key=service_key,
                                      response_key=key,
                                      public_cert=service_cert,
                                      args=args)
            print("SUCCEEDED!")
            _sys.stdout.flush()
        except Exception as e:
            print("FAILED!")
            _sys.stdout.flush()
            raise LoginError("Failed to log in: %s" % str(e))

        if remember_password:
            try:
                provisioning_uri = response["provisioning_uri"]
            except:
                provisioning_uri = None

            otpsecret = None

            if provisioning_uri:
                try:
                    otpsecret = _re.search(r"secret=([\w\d+]+)&issuer",
                                           provisioning_uri).groups()[0]
                except:
                    pass

            try:
                service_info = self._read_service_info(service_url)
            except:
                service_info = {}

            if service_info is None:
                service_info = {}

            pubkey = self._wallet_key.public_key()

            must_write = self._manual_password

            if otpsecret:
                if self._manual_otpcode:
                    must_write = True

            if must_write:
                service_info["service_url"] = service_url.encode(
                    "utf-8").decode("utf-8")
                service_info["password"] = _bytes_to_string(
                    pubkey.encrypt(password.encode("utf-8")))

                if otpsecret:
                    service_info["otpsecret"] = _bytes_to_string(
                        pubkey.encrypt(otpsecret.encode("utf-8")))

                packed_data = _pack_arguments(service_info)

                with open(ServiceWallet._get_service_file(service_url),
                          "wb") as FILE:
                    FILE.write(packed_data)

        self._manual_password = False
        self._manual_otpcode = False

        return response
コード例 #21
0
    def send_password(self,
                      url,
                      username=None,
                      remember_password=True,
                      remember_device=None,
                      dryrun=None):
        """Send a password and one-time code to the supplied login url"""

        self._manual_password = False
        self._manual_otpcode = False

        if not remember_password:
            remember_device = False

        # the login URL is of the form "server/code"
        words = url.split("/")
        identity_service = "/".join(words[0:-1])
        short_uid = words[-1]

        # get the public key of this identity service
        service_key = self._get_service_key(identity_service)
        service_cert = self._get_service_cert(identity_service)

        if not username:
            # choose a username from any existing files...
            username = self._get_username()

        print("Logging in using username '%s'" % username)
        password = self._get_user_password(username)
        otpcode = self._get_otpcode(username)

        print("\nLogging in to '%s', session '%s'..." %
              (identity_service, short_uid),
              end="")
        _sys.stdout.flush()

        if dryrun:
            print("Calling %s with username=%s, password=%s, otpcode=%s, "
                  "remember_device=%s, device_uid=%s, short_uid=%s" %
                  (identity_service, username, password, otpcode,
                   remember_device, self._device_uid, short_uid))
            return

        try:
            key = _PrivateKey()
            response = _call_function(identity_service,
                                      "login",
                                      args_key=service_key,
                                      response_key=key,
                                      public_cert=service_cert,
                                      username=username,
                                      password=password,
                                      otpcode=otpcode,
                                      remember_device=remember_device,
                                      device_uid=self._device_uid,
                                      short_uid=short_uid)
            print("SUCCEEDED!")
            _sys.stdout.flush()
        except Exception as e:
            print("FAILED!")
            _sys.stdout.flush()
            raise LoginError("Failed to log in: %s" % str(e))

        if remember_password:
            try:
                provisioning_uri = response["provisioning_uri"]
            except:
                provisioning_uri = None

            try:
                device_uid = response["device_uid"]
            except:
                device_uid = None

            otpsecret = None

            if provisioning_uri:
                try:
                    otpsecret = _re.search(r"secret=([\w\d+]+)&issuer",
                                           provisioning_uri).groups()[0]
                except:
                    pass

            try:
                user_info = self._read_userinfo(username)
            except:
                user_info = {}

            if user_info is None:
                user_info = {}

            pubkey = self._wallet_key.public_key()

            must_write = self._manual_password

            if otpsecret:
                if self._manual_otpcode:
                    must_write = True

            if must_write:
                user_info["username"] = username.encode("utf-8").decode(
                    "utf-8")
                user_info["password"] = _bytes_to_string(
                    pubkey.encrypt(password.encode("utf-8")))

                if otpsecret:
                    user_info["otpsecret"] = _bytes_to_string(
                        pubkey.encrypt(otpsecret.encode("utf-8")))
                    user_info["device_uid"] = device_uid

                packed_data = _pack_arguments(user_info)

                with open(Wallet._get_userfile(username), "wb") as FILE:
                    FILE.write(packed_data)

        self._manual_password = False
        self._manual_otpcode = False

        return response
コード例 #22
0
def get_trusted_registry_service(registry_uid=None,
                                 service_uid=None,
                                 service_url=None):
    """Return the trusted service info for the registry with specified
       registry_uid, or get any trusted registry service using either
       'service_uid' or 'service_url' as a starting hint to
       locate a suitable registry
    """
    if service_uid is not None:
        # for the moment, just try to get one registry. Eventually we should
        # try to get several in case this one is down
        registry_uid = get_primary_registry_uid(service_uid)
        return get_trusted_registry_service(registry_uid=registry_uid)

    if service_url is not None:
        if service_url.find(".") != -1:
            # try the main acquire registry first
            return get_trusted_registry_service(registry_uid="a0-a0")
        else:
            # this must be testing...
            return get_trusted_registry_service(registry_uid="Z9-Z9")

    if registry_uid is None:
        raise PermissionError(
            "You must specify one of registry_uid, service_uid "
            "or service_url")

    from Acquire.Service import get_trusted_service as _get_trusted_service

    try:
        registry_service = _get_trusted_service(service_uid=registry_uid,
                                                autofetch=False)
    except:
        registry_service = None

    if registry_service is not None:
        if not registry_service.is_registry_service():
            from Acquire.Service import ServiceError
            raise ServiceError("The requested service (%s) for %s is NOT a "
                               "registry service!" %
                               (registry_service, registry_uid))

        if registry_service.uid() != registry_uid:
            from Acquire.Service import ServiceError
            raise ServiceError(
                "Disagreement of UID (%s) is NOT the right registry service!" %
                registry_service)

        # everything is ok - we have seen this registry before
        return registry_service

    # boostrapping
    from Acquire.Registry import get_registry_details \
        as _get_registry_details

    details = _get_registry_details(registry_uid)

    from Acquire.Service import call_function as _call_function
    from Acquire.Service import Service as _Service
    from Acquire.Crypto import get_private_key as _get_private_key
    from Acquire.Crypto import PrivateKey as _PrivateKey
    from Acquire.Crypto import PublicKey as _PublicKey
    from Acquire.ObjectStore import bytes_to_string as _bytes_to_string
    from Acquire.ObjectStore import string_to_bytes as _string_to_bytes

    privkey = _get_private_key(key="registry")

    pubkey = _PublicKey.from_data(details["public_key"])
    pubcert = _PublicKey.from_data(details["public_certificate"])

    # ask the registry to return to us their latest details - use
    # a challenge-response to make sure that the response is
    # properly returned
    challenge = _PrivateKey.random_passphrase()
    encrypted_challenge = _bytes_to_string(pubkey.encrypt(challenge))
    args = {
        "challenge": encrypted_challenge,
        "fingerprint": pubkey.fingerprint()
    }

    result = _call_function(service_url=details["canonical_url"],
                            function=None,
                            args=args,
                            args_key=pubkey,
                            response_key=privkey,
                            public_cert=pubcert)

    if result["response"] != challenge:
        from Acquire.Service import ServiceError
        raise ServiceError(
            "The requested service (%s) failed to respond to the challenge!" %
            registry_service)

    registry_service = _Service.from_data(result["service_info"])

    if not registry_service.is_registry_service():
        from Acquire.Service import ServiceError
        raise ServiceError(
            "The requested service (%s) is NOT a registry service!" %
            registry_service)

    if registry_service.uid() != details["uid"]:
        from Acquire.Service import ServiceError
        raise ServiceError(
            "Disagreement of UID (%s) is NOT the right registry service!" %
            registry_service)

    # ok - we've got the registry - add this to the set of
    # trusted services so that we don't need to bootstrap from
    # the registry details again
    from Acquire.Service import trust_service as _trust_service
    _trust_service(registry_service)

    return registry_service
コード例 #23
0
    def upload(self, source, destination=None, ignore_hidden=True,
               account=None):
        """Upload a file (or files) from 'source' to 'destination'. If
           'destination is not supplied, then the file(s) will be uploaded
           with 'destination' equals 'source' (i.e. they will have the same
           name on the cloud drive as they do on the drive). If 'destination'
           is supplied then if it ends in a "/" then the destination will
           be treated like a directory. If the number of source files is
           greater than 1 and only a single destination directory is provided
           then all files will be uploaded into that directory.

           If 'ignore_hidden' is true, then hidden files will be ignored
           when uploading directories (but not when specifying files
           manually)

           If you pass in 'account', then
           this account will be used to pay for the storage. The account
           can be authorised from a different user to the owner of the drive,
           although both the user and account must be in the logged-in state.

           If you don't specify the account then the default account for
           the user will be used.

           Note that you cannot overwrite a file that already exists. It has
           to be explicitly removed first.

           Note that this is an atomic function - either all of none
           of the files will be written.

           This will return the list of read-only handles to allow you
           (or anyone else) to read these files.
        """

        if source is None:
            return

        if account is None:
            if not self._user.is_logged_in():
                raise PermissionError(
                    "You cannot upload files unless you have logged into "
                    "your account. Please log in and try again.")

            account = _Account(user=self._user)

        from Acquire.Access import FileWriteRequest as _FileWriteRequest

        request = _FileWriteRequest(source=source, destination=destination,
                                    ignore_hidden=ignore_hidden,
                                    account=account)

        args = {"request": request.to_data()}

        privkey = _PrivateKey()

        result = _call_function(
                    self._access_service.service_url(), "request",
                    args=args,
                    args_key=self._access_service.public_key(),
                    response_key=privkey,
                    public_cert=self._access_service.public_certificate())

        return result
コード例 #24
0
ファイル: _user.py プロジェクト: michellab/BioSimSpaceCloud
    def request_login(self, login_message=None):
        """Request to authenticate as this user. This returns a login URL that
           you must connect to to supply your login credentials

           If 'login_message' is supplied, then this is passed to
           the identity service so that it can be displayed
           when the user accesses the login page. This helps
           the user validate that they have accessed the correct
           login page. Note that if the message is None,
           then a random message will be generated.
        """
        self._check_for_error()

        if not self.is_empty():
            raise LoginError("You cannot try to log in twice using the same "
                             "User object. Create another object if you want "
                             "to try to log in again.")

        # first, create a private key that will be used
        # to sign all requests and identify this login
        session_key = _PrivateKey()
        signing_key = _PrivateKey()

        args = {
            "username": self._username,
            "public_key": session_key.public_key().to_data(),
            "public_certificate": signing_key.public_key().to_data(),
            "ipaddr": None
        }

        # get information from the local machine to help
        # the user validate that the login details are correct
        if _has_socket:
            hostname = _socket.gethostname()
            ipaddr = _socket.gethostbyname(hostname)
            args["ipaddr"] = ipaddr
            args["hostname"] = hostname

        if login_message is None:
            login_message = "User '%s' in process '%s' wants to log in..." % \
                              (_os.getlogin(), _os.getpid())

        args["message"] = login_message

        result = _call_function(
            self.identity_service_url(),
            "request_login",
            args_key=self.identity_service().public_key(),
            response_key=session_key,
            public_cert=self.identity_service().public_certificate(),
            username=self._username,
            public_key=session_key.public_key().to_data(),
            public_certificate=signing_key.public_key().to_data(),
            ipaddr=None,
            message=login_message)

        # look for status = 0
        try:
            status = int(result["status"])
        except:
            status = -1

        try:
            message = result["message"]
        except:
            message = str(result)

        try:
            prune_message = result["prune_message"]
            print("Pruning old sessions...\n%s" % "\n".join(prune_message))
        except:
            pass

        if status != 0:
            error = "Failed to login. Error = %d. Message = %s" % \
                                (status, message)
            self._set_error_state(error)
            raise LoginError(error)

        try:
            login_url = result["login_url"]
        except:
            login_url = None

        if login_url is None:
            error = "Failed to login. Could not extract the login URL! " \
                    "Result is %s" % (str(result))
            self._set_error_state(error)
            raise LoginError(error)

        try:
            session_uid = result["session_uid"]
        except:
            session_uid = None

        if session_uid is None:
            error = "Failed to login. Could not extract the login " \
                    "session UID! Result is %s" % (str(result))

            self._set_error_state(error)
            raise LoginError(error)

        # now save all of the needed data
        self._login_url = result["login_url"]
        self._session_key = session_key
        self._signing_key = signing_key
        self._session_uid = session_uid
        self._status = _LoginStatus.LOGGING_IN
        self._user_uid = result["user_uid"]

        qrcode = None

        if _has_qrcode():
            try:
                self._login_qrcode = _create_qrcode(self._login_url)
                qrcode = self._login_qrcode
            except:
                pass

        return (self._login_url, qrcode)