def test_authorisation():
    key = PrivateKey()

    resource = uuid.uuid4()

    auth = Authorisation(resource=resource, testing_key=key)

    auth.verify(resource=resource, testing_key=key.public_key())

    wrong_key = PrivateKey()

    with pytest.raises(PermissionError):
        auth.verify(resource=resource, testing_key=wrong_key.public_key())

    wrong_resource = uuid.uuid4()

    with pytest.raises(PermissionError):
        auth.verify(resource=wrong_resource, testing_key=key.public_key())

    data = auth.to_data()

    new_auth = Authorisation.from_data(data)

    new_auth.verify(resource=resource, testing_key=key.public_key())

    with pytest.raises(PermissionError):
        new_auth.verify(resource=resource, testing_key=wrong_key.public_key())

    with pytest.raises(PermissionError):
        new_auth.verify(resource=wrong_resource, testing_key=key.public_key())
Exemplo n.º 2
0
def run(args):
    """This function is used to handle requests to access resources

        Args:
            args (dict): contains data for authorisation service

        Returns:
            dict: a dictionary containing the status of the authorisation
                    and a status message

    """

    status = 0
    message = None

    request = None
    authorisation = None

    if "request" in args:
        request = Request.from_data(args["request"])

    if "authorisation" in args:
        authorisation = Authorisation.from_data(args["authorisation"])

    if request is None:
        status = 0
        message = "No request"

    if authorisation is None:
        raise AuthorisationError(
            "You must provide a valid authorisation to make the request %s" %
            str(request))

    authorisation.verify(request.signature())
Exemplo n.º 3
0
def run(args):
    """Call this function to open and return a handle to the
       user's requested CloudDrive. This will create the
       drive (and the all intermediate drives) unless the
       user sets autocreate to false
    """

    authorisation = Authorisation.from_data(args["authorisation"])
    name = args["name"]

    try:
        autocreate = args["autocreate"]

        if autocreate is False:
            autocreate = False
        else:
            autocreate = True
    except:
        autocreate = True

    if autocreate and "aclrules" in args:
        aclrules = ACLRules.from_data(args["aclrules"])
    else:
        aclrules = None

    drives = UserDrives(authorisation=authorisation)

    drive = drives.get_drive(name=name, aclrules=aclrules,
                             autocreate=autocreate)

    return_value = {}

    return_value["drive"] = drive.to_data()

    return return_value
Exemplo n.º 4
0
    def from_data(data):
        """Return a DebitNote that has been extracted from the passed
           json-decoded dictionary

           Args:
                data (dict): Dictionary from which to create object
           Returns:
                DebitNote: Created from dictionary
        """
        d = DebitNote()

        if (data and len(data) > 0):
            from Acquire.Accounting import Transaction as _Transaction
            from Acquire.Identity import Authorisation as _Authorisation
            from Acquire.ObjectStore import string_to_datetime \
                as _string_to_datetime

            d._transaction = _Transaction.from_data(data["transaction"])
            d._account_uid = data["account_uid"]
            d._authorisation = _Authorisation.from_data(data["authorisation"])
            d._is_provisional = data["is_provisional"]
            d._datetime = _string_to_datetime(data["datetime"])
            d._uid = data["uid"]

            if d._is_provisional:
                d._receipt_by = _string_to_datetime(data["receipt_by"])

        return d
Exemplo n.º 5
0
def run(args):
    """This function will allow the current user to authorise
       a logout from the current session - this will be authorised
       by signing the request to logout
       
       Args:
        args (dict): contains identifying information about the session
    
        Returns:
            dict: contains data on the success of the logout request
       
       """

    session_uid = args["session_uid"]

    try:
        authorisation = Authorisation.from_data(args["authorisation"])
    except:
        authorisation = None

    try:
        signature = string_to_bytes(args["signature"])
    except:
        signature = None

    login_session = LoginSession.load(uid=session_uid)

    login_session.set_logged_out(authorisation=authorisation,
                                 signature=signature)
Exemplo n.º 6
0
    def from_data(data):
        """ Create a request from a JSON object

            Args:
                data (str) : an object serialised as a JSON object
            Returns:
                FileWriteRequest: a FileWriteRequest object created from
                the JSON data

        """
        if (data and len(data) > 0):
            from Acquire.Identity import Authorisation as _Authorisation
            f = FileWriteRequest()

            f._uid = data["uid"]
            f._destination_keys = data["destination_keys"]
            f._file_sizes = data["file_sizes"]
            f._checksums = data["checksums"]
            f._authorisation = _Authorisation.from_data(data["authorisation"])
            f._account_uid = data["account_uid"]
            f._accounting_service_url = data["accounting_service_url"]

            f._from_data(data)

            return f
        else:
            return None
Exemplo n.º 7
0
    def from_data(data):
        """Return a Refund from the passed json-decoded dictionary"""
        r = Refund()

        if (data and len(data) > 0):
            r._credit_note = _CreditNote.from_data(data["credit_note"])
            r._authorisation = _Authorisation.from_data(data["authorisation"])

        return r
Exemplo n.º 8
0
    def from_data(data):
        """Return a Receipt from the passed json-decoded dictionary"""
        r = Receipt()

        if (data and len(data) > 0):
            r._credit_note = _CreditNote.from_data(data["credit_note"])
            r._authorisation = _Authorisation.from_data(data["authorisation"])
            r._receipted_value = _create_decimal(data["receipted_value"])

        return r
Exemplo n.º 9
0
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()})
Exemplo n.º 10
0
def run(args):
    """This function is called to handle requests for information about
       particular accounts

       Args:
            args (dict): data for account query

        Returns:
            dict: contains status, status message and details regarding
                the account including balance (if available), overdraft
                limit and a description of the account
    """

    status = 0
    message = None

    account = None
    balance_status = None

    try:
        account_name = str(args["account_name"])
    except:
        account_name = None

    try:
        authorisation = Authorisation.from_data(args["authorisation"])
    except:
        authorisation = None

    if account_name is None:
        raise AccountError("You must supply the account_name")

    if authorisation is None:
        raise AccountError("You must supply a valid authorisation")

    # load the account
    bucket = get_service_account_bucket()
    accounts = Accounts(user_guid=authorisation.user_guid())
    account = accounts.get_account(account_name, bucket=bucket)

    # validate the authorisation for this account
    authorisation.verify(resource="get_info %s" % account.uid())

    balance = account.balance()

    return_value = {}

    return_value["description"] = account.description()
    return_value["overdraft_limit"] = str(account.get_overdraft_limit())
    return_value["balance"] = balance.to_data()

    return return_value
Exemplo n.º 11
0
    def from_data(data):
        f = FileWriteRequest()

        if (data and len(data) > 0):
            f._uid = data["uid"]
            f._destination_keys = data["destination_keys"]
            f._file_sizes = data["file_sizes"]
            f._checksums = data["checksums"]
            f._authorisation = _Authorisation.from_data(data["authorisation"])
            f._account_uid = data["account_uid"]
            f._accounting_service_url = data["accounting_service_url"]

        return f
Exemplo n.º 12
0
    def perform_transaction(key, result):
        delta1 = zero
        delta2 = zero

        # need to work with thread-local copies of the accounts
        my_account1 = Account(uid=account1.uid())
        my_account2 = Account(uid=account2.uid())

        for i in range(0, 10):
            transaction = Transaction(value=create_decimal(random.random()),
                                      description="Transaction %d" % i)

            if random.randint(0, 1):
                auth = Authorisation(
                    resource=transaction.fingerprint(),
                    testing_key=testing_key,
                    testing_user_guid=my_account1.group_name())

                Ledger.perform(transaction=transaction,
                               debit_account=my_account1,
                               credit_account=my_account2,
                               authorisation=auth)
                delta1 -= transaction.value()
                delta2 += transaction.value()
            else:
                auth = Authorisation(
                    resource=transaction.fingerprint(),
                    testing_key=testing_key,
                    testing_user_guid=my_account2.group_name())

                Ledger.perform(transaction=transaction,
                               debit_account=my_account2,
                               credit_account=my_account1,
                               authorisation=auth)
                delta1 += transaction.value()
                delta2 -= transaction.value()

        with rlock:
            result[key] = (delta1, delta2)
Exemplo n.º 13
0
def run(args):
    """This function is called to handle requests for information about
       particular accounts
    """

    status = 0
    message = None

    account = None
    balance_status = None

    try:
        account_name = str(args["account_name"])
    except:
        account_name = None

    try:
        authorisation = Authorisation.from_data(args["authorisation"])
    except:
        authorisation = None

    if account_name is None:
        raise AccountError("You must supply the account_name")

    if authorisation is None:
        raise AccountError("You must supply a valid authorisation")

    # load the account
    bucket = login_to_service_account()
    account = Accounts(authorisation.user_uid()).get_account(account_name,
                                                             bucket=bucket)

    # validate the authorisation for this account
    authorisation.verify(resource=account.uid())

    balance_status = account.balance_status(bucket=bucket)

    status = 0
    message = "Success"

    return_value = create_return_value(status, message)

    if account:
        return_value["description"] = account.description()
        return_value["overdraft_limit"] = str(account.get_overdraft_limit())

    if balance_status:
        for key in balance_status.keys():
            return_value[key] = str(balance_status[key])

    return return_value
Exemplo n.º 14
0
    def from_data(data):
        """Return a LineItem constructed from the json-decoded dictionary"""
        l = LineItem()

        if (data and len(data) > 0):
            l._uid = data["uid"]

            if "authorisation" in data:
                l._authorisation = _Authorisation.from_data(
                    data["authorisation"])
            else:
                l._authorisation = None

        return l
Exemplo n.º 15
0
def run(args):
    """This function is called to handle creating accounts for users"""

    status = 0
    message = None

    account_uid = None

    try:
        account_name = args["account_name"]
    except:
        account_name = None

    try:
        description = args["description"]
    except:
        description = None

    try:
        authorisation = Authorisation.from_data(args["authorisation"])
    except:
        authorisation = None

    if account_name is None or description is None \
            or authorisation is None:
        raise CreateAccountError("You must supply both an account name "
                                 "and a description to create an account")

    if not isinstance(authorisation, Authorisation):
        raise TypeError("The passed authorisation must be of type "
                        "Authorisation")

    authorisation.verify()

    # try to create a 'main' account for this user
    accounts = Accounts(authorisation.user_uid())
    account = accounts.create_account(name=account_name,
                                      description=description)

    account_uid = account.uid()

    status = 0
    message = "Success"

    return_value = create_return_value(status, message)

    if account_uid:
        return_value["account_uid"] = account_uid

    return return_value
Exemplo n.º 16
0
    def from_data(data):
        """Return a DebitNote that has been extracted from the passed
           json-decoded dictionary
        """
        d = DebitNote()

        if (data and len(data) > 0):
            d._transaction = _Transaction.from_data(data["transaction"])
            d._account_uid = data["account_uid"]
            d._authorisation = _Authorisation.from_data(data["authorisation"])
            d._is_provisional = data["is_provisional"]
            d._timestamp = data["timestamp"]
            d._uid = data["uid"]

        return d
Exemplo n.º 17
0
def run(args):
    """This function is used to handle requests to run compute jobs using
       the system. This will be passed in the RunRequest with a valid
       authorisation and also a Cheque to pay for the calculation.

       This will return the UID of the running job plus the location
       to which the output will be written
    """

    request = None
    authorisation = None
    cheque = None

    if "request" in args:
        request = RunRequest.from_data(args["request"])

    if "authorisation" in args:
        authorisation = Authorisation.from_data(args["authorisation"])

    if "cheque" in args:
        cheque = Cheque.from_data(args["cheque"])

    if request is None:
        return

    if authorisation is None:
        raise AuthorisationError(
            "You must provide a valid authorisation to make the request %s"
            % str(request))

    if cheque is None:
        raise AuthorisationError(
            "You must provide a valid cheque to pay for the request %s"
            % str(request))

    # create a job sheet to record all stages of the job
    worksheet = WorkSheet(request=request, authorisation=authorisation)

    # submit the job, recording everything necessary to the JobSheet
    worksheet.execute(cheque=cheque)

    # Return to the user the UID of the job and also the location
    # to which all output from the job is being written
    return {"uid": worksheet.uid(),
            "output": worksheet.output_location().to_string()}
Exemplo n.º 18
0
    def from_data(data):
        """Return a Refund from the passed JSON-decoded dictionary

           Args:
                dict: JSON-decoded dictionary
           Returns:
                Refund: Refund object created from JSON


        """
        r = Refund()

        if (data and len(data) > 0):
            from Acquire.Accounting import CreditNote as _CreditNote
            from Acquire.Identity import Authorisation as _Authorisation
            r._credit_note = _CreditNote.from_data(data["credit_note"])
            r._authorisation = _Authorisation.from_data(data["authorisation"])

        return r
Exemplo n.º 19
0
    def from_data(data):
        """Return a Receipt from the passed JSON-decoded dictionary

           Args:
                data (dict): JSON dictionary to create object
           Returns:
                Receipt: Receipt created from JSON

        """
        r = Receipt()

        if (data and len(data) > 0):
            from Acquire.Accounting import CreditNote as _CreditNote
            from Acquire.Accounting import create_decimal as _create_decimal
            from Acquire.Identity import Authorisation as _Authorisation
            r._credit_note = _CreditNote.from_data(data["credit_note"])
            r._authorisation = _Authorisation.from_data(data["authorisation"])
            r._receipted_value = _create_decimal(data["receipted_value"])

        return r
Exemplo n.º 20
0
    def from_data(data):
        """Return a WorkSheet constructed from the passed JSON-deserialised
           dictionary
        """
        if data is None or len(data) == 0:
            return

        j = WorkSheet()

        from Acquire.Access import RunRequest as _RunRequest
        from Acquire.Client import Authorisation as _Authorisation
        from Acquire.Client import Location as _Location
        from Acquire.Client import Cheque as _Cheque
        from Acquire.Accounting import CreditNote as _CreditNote
        from Acquire.ObjectStore import string_to_list \
            as _string_to_list

        j._uid = str(data["uid"])

        if "request" in data:
            j._request = _RunRequest.from_data(data["request"])

        if "authorisation" in data:
            j._authorisation = _Authorisation.from_data(data["authorisation"])

        if "credit_notes" in data:
            j._credit_notes = _string_to_list(data["credit_notes"],
                                              _CreditNote)

        j._status = data["status"]

        if "output_location" in data:
            j._output_loc = _Location.from_string(data["output_location"])

        if "compute_cheque" in data:
            j._compute_cheque = _Cheque.from_data(data["compute_cheque"])

        if "storage_cheque" in data:
            j._storage_cheque = _Cheque.from_data(data["storage_cheque"])

        return j
Exemplo n.º 21
0
def run(args):
    """Call this function to return a list of DriveMetas for the
       top-level drives accessible to the authorising user, or the
       list of DriveMetas contained in the drive with passed UID
    """

    authorisation = Authorisation.from_data(args["authorisation"])

    drives = UserDrives(authorisation=authorisation)

    try:
        drive_uid = args["drive_uid"]
    except:
        drive_uid = None

    return_value = {}

    return_value["drives"] = list_to_string(
        drives.list_drives(drive_uid=drive_uid))

    return return_value
Exemplo n.º 22
0
def test_accounts(bucket):
    for user_guid in [None, "chris@something", "ƒ˚®ø©∆∂µ@¨^ø¨^ø"]:
        if user_guid is None:
            accounts = Accounts(group=user_guid,
                                aclrules=ACLRules.owner(user_guid=None))
        else:
            accounts = Accounts(user_guid=user_guid)

        account_names = [
            "new account", "chris's checking account", "å∫ç∂´® account"
        ]

        created_accounts = {}

        testing_key = get_private_key("testing")

        for name in account_names:
            authorisation = Authorisation(resource="create_account %s" % name,
                                          testing_key=testing_key,
                                          testing_user_guid=user_guid)

            account = accounts.create_account(name,
                                              description="Account: %s" % name,
                                              bucket=bucket,
                                              authorisation=authorisation)

            assert (name == account.name())

            created_accounts[name] = account

        names = accounts.list_accounts()

        for name in account_names:
            assert (name in names)

        for name in account_names:
            account = accounts.get_account(name, bucket=bucket)
            assert (name == account.name())

            assert (account == created_accounts[name])
Exemplo n.º 23
0
def run(args):
    """Call this function to force the service to regenerate its keys

       Args:
            args (dict): contains authorisaton details for key refresh
    """
    try:
        authorisation = Authorisation.from_data(args["authorisation"])
    except:
        raise PermissionError("Only an authorised admin can dump the keys")

    service = get_this_service(need_private_access=True)
    service.assert_admin_authorised(authorisation,
                                    "refresh_keys %s" % service.uid())

    service = refresh_service_keys_and_certs(service=service,
                                             force_refresh=True)

    return_value = {}
    return_value["service_info"] = service.to_data()

    return return_value
Exemplo n.º 24
0
def run(args):
    """This function return the status and service info

       Args:
            args (dict): containing data on the service we want
            to trust

       Returns:
            dict: containing status, status message and passed in args  
    
    """
    try:
        service_url = args["service_url"]
    except:
        service_url = None

    try:
        public_cert = PublicKey.from_data(args["public_certificate"])
    except:
        public_cert = None

    try:
        authorisation = Authorisation.from_data(args["authorisation"])
    except:
        authorisation = None

    if service_url is not None:
        service = get_checked_remote_service(service_url, public_cert)
    else:
        service = None

    if service is not None:
        trust_service(service, authorisation)

    return_value = {}

    return_value["args"] = args

    return return_value
Exemplo n.º 25
0
def run(args):
    """Call this function to trust the passed accounting service,
       specifically to trust that we can move money using that service.

       Args:
            args(dict): containing data on the service we want
            to trust

       Returns:
            dict: containing status, status message and passed in args
    """
    service_url = args["service_url"]

    authorisation = Authorisation.from_data(args["authorisation"])

    accounting_service = get_trusted_service(service_url=service_url)

    if not accounting_service.is_accounting_service():
        raise ServiceAccountError(
            "%s is not an accounting service, so should not be "
            "trusted as one" % str(accounting_service))

    service = get_this_service(need_private_access=True)
    service.assert_admin_authorised(
        authorisation,
        "trust_accounting_service %s" % accounting_service.uid())

    url = accounting_service.canonical_url()

    create_service_user_account(service=service, accounting_service_url=url)

    return_value = {}

    return_value["args"] = args

    return return_value
Exemplo n.º 26
0
    def perform_transaction(key, result):
        delta1 = zero
        delta2 = zero
        auth = Authorisation()

        # need to work with thread-local copies of the accounts
        my_account1 = Account(uid=account1.uid())
        my_account2 = Account(uid=account2.uid())

        for i in range(0, 5):
            transaction = Transaction(value=create_decimal(random.random()),
                                      description="Transaction %d" % i)

            if random.randint(0, 1):
                Ledger.perform(transaction, my_account1, my_account2, auth)
                delta1 -= transaction.value()
                delta2 += transaction.value()
            else:
                Ledger.perform(transaction, my_account2, my_account1, auth)
                delta1 += transaction.value()
                delta2 -= transaction.value()

        with rlock:
            result[key] = (delta1, delta2)
Exemplo n.º 27
0
def test_login(username, password, aaai_services, tmpdir):
    # register the new user
    result = User.register(username=username,
                           password=password,
                           identity_url="identity")

    assert(type(result) is dict)

    otpsecret = result["otpsecret"]

    otp = OTP(otpsecret)

    user = User(username=username, identity_url="identity",
                auto_logout=False)

    result = user.request_login()

    assert(type(result) is dict)

    login_url = result["login_url"]
    print(login_url)

    wallet = Wallet()

    wallet.send_password(url=login_url, username=username,
                         password=password, otpcode=otp.generate(),
                         remember_password=True)

    user.wait_for_login()
    assert(user.is_logged_in())

    auth = Authorisation(user=user, resource="test")

    auth.verify("test")

    user.logout()

    # now try to log in, using the remembered password
    user = User(username=username, identity_url="identity",
                auto_logout=False)

    result = user.request_login()

    login_url = result["login_url"]

    # the test has to specify the username as we can't choose...
    wallet.send_password(url=login_url, username=username,
                         otpcode=otp.generate(),
                         remember_device=True)

    user.wait_for_login()
    assert(user.is_logged_in())

    auth = Authorisation(user=user, resource="test")

    auth.verify("test")

    user.logout()

    # now see if the wallet can send all login info
    # now try to log in, using the remembered password
    user = User(username=username, identity_url="identity",
                auto_logout=False)

    result = user.request_login()

    login_url = result["login_url"]

    # the test has to specify the username as we can't choose...
    wallet.send_password(url=login_url, username=username)

    user.wait_for_login()
    assert(user.is_logged_in())

    auth = Authorisation(user=user, resource="test")

    auth.verify("test")

    user.logout()
Exemplo n.º 28
0
def run(args):
    """Call this function to initiate the two-step file-upload process.

       Step 1: upload - tells the service that a file of specific
               size and checksum will be uploaded. This gives the service
               the chance to decide whether this will be allowed. If the
               file is small, and was thus included in the FileHandle,
               then it is uploaded immediately and the operation completes.
               If the file is large, then we now returns a OSPar
               that can be used for this upload (Step 2)

       Step 2: after the user has used the OSPar to upload
               the file, they should call OSPar.close() to notify
               the service that the file has been successfully uploaded.
               This will verify that the file has been uploaded correctly,
               will receipt the storage cost and will delete the OSPar
    """

    filehandle = FileHandle.from_data(args["filehandle"])

    try:
        authorisation = Authorisation.from_data(args["authorisation"])
    except:
        authorisation = None

    try:
        par_uid = args["par_uid"]
    except:
        par_uid = None

    try:
        secret = args["secret"]
    except:
        secret = None

    try:
        public_key = PublicKey.from_data(args["encryption_key"])
    except:
        public_key = None

    if par_uid is not None:
        registry = PARRegistry()
        (par, identifiers) = registry.load(par_uid=par_uid, secret=secret)
    else:
        par = None
        identifiers = None

    drive_uid = filehandle.drive_uid()

    drive = DriveInfo(drive_uid=drive_uid)

    return_value = {}

    (filemeta, par) = drive.upload(filehandle=filehandle,
                                   authorisation=authorisation,
                                   encrypt_key=public_key,
                                   par=par,
                                   identifiers=identifiers)

    if filemeta is not None:
        return_value["filemeta"] = filemeta.to_data()

    if par is not None:
        return_value["upload_par"] = par.to_data()

    return return_value
Exemplo n.º 29
0
def aaai_services(tmpdir_factory):
    """This function creates mocked versions of all of the main services
       of the system, returning the json describing each service as
       a dictionary (which is passed to the test functions as the
       fixture)
    """
    from Acquire.Identity import Authorisation
    from Acquire.Crypto import PrivateKey, OTP
    from Acquire.Service import call_function, Service

    _services = {}
    _services["registry"] = tmpdir_factory.mktemp("registry")
    _services["identity"] = tmpdir_factory.mktemp("identity")
    _services["accounting"] = tmpdir_factory.mktemp("accounting")
    _services["access"] = tmpdir_factory.mktemp("access")
    _services["storage"] = tmpdir_factory.mktemp("storage")
    _services["userdata"] = tmpdir_factory.mktemp("userdata")
    _services["compute"] = tmpdir_factory.mktemp("compute")
    _services["hugs"] = tmpdir_factory.mktemp("hugs")

    wallet_dir = tmpdir_factory.mktemp("wallet")
    wallet_password = PrivateKey.random_passphrase()

    _set_services(_services, wallet_dir, wallet_password)

    password = PrivateKey.random_passphrase()
    args = {"password": password}

    responses = {}

    os.environ["SERVICE_PASSWORD"] = "******"
    os.environ["STORAGE_COMPARTMENT"] = str(_services["userdata"])

    args["canonical_url"] = "registry"
    args["service_type"] = "registry"
    args["registry_uid"] = "Z9-Z9"  # UID of testing registry
    response = call_function("registry", function="admin/setup", args=args)

    registry_service = Service.from_data(response["service"])
    registry_otp = OTP(OTP.extract_secret(response["provisioning_uri"]))
    registry_user = _login_admin("registry", "admin", password, registry_otp)
    responses["registry"] = {
        "service": registry_service,
        "user": registry_user,
        "response": response,
    }

    assert registry_service.registry_uid() == registry_service.uid()
    service_uids = [registry_service.uid()]

    args["canonical_url"] = "identity"
    args["service_type"] = "identity"
    response = call_function("identity", function="admin/setup", args=args)

    identity_service = Service.from_data(response["service"])
    identity_otp = OTP(OTP.extract_secret(response["provisioning_uri"]))
    identity_user = _login_admin("identity", "admin", password, identity_otp)
    responses["identity"] = {
        "service": identity_service,
        "user": identity_user,
        "response": response,
    }

    assert identity_service.registry_uid() == registry_service.uid()
    assert identity_service.uid() not in service_uids
    service_uids.append(identity_service.uid())

    args["canonical_url"] = "accounting"
    args["service_type"] = "accounting"
    response = call_function("accounting", function="admin/setup", args=args)
    accounting_service = Service.from_data(response["service"])
    accounting_otp = OTP(OTP.extract_secret(response["provisioning_uri"]))
    accounting_user = _login_admin("accounting", "admin", password,
                                   accounting_otp)
    responses["accounting"] = {
        "service": accounting_service,
        "user": accounting_user,
        "response": response,
    }

    assert accounting_service.registry_uid() == registry_service.uid()
    assert accounting_service.uid() not in service_uids
    service_uids.append(accounting_service.uid())

    args["canonical_url"] = "access"
    args["service_type"] = "access"
    response = call_function("access", function="admin/setup", args=args)
    responses["access"] = response
    access_service = Service.from_data(response["service"])
    access_otp = OTP(OTP.extract_secret(response["provisioning_uri"]))
    access_user = _login_admin("access", "admin", password, access_otp)
    responses["access"] = {
        "service": access_service,
        "user": access_user,
        "response": response,
    }

    assert access_service.registry_uid() == registry_service.uid()
    assert access_service.uid() not in service_uids
    service_uids.append(access_service.uid())

    args["canonical_url"] = "compute"
    args["service_type"] = "compute"
    response = call_function("compute", function="admin/setup", args=args)
    responses["compute"] = response
    compute_service = Service.from_data(response["service"])
    compute_otp = OTP(OTP.extract_secret(response["provisioning_uri"]))
    compute_user = _login_admin("compute", "admin", password, compute_otp)
    responses["compute"] = {
        "service": compute_service,
        "user": compute_user,
        "response": response,
    }

    assert compute_service.registry_uid() == registry_service.uid()
    assert compute_service.uid() not in service_uids
    service_uids.append(compute_service.uid())

    args["canonical_url"] = "storage"
    args["service_type"] = "storage"
    response = call_function("storage", function="admin/setup", args=args)
    storage_service = Service.from_data(response["service"])
    storage_otp = OTP(OTP.extract_secret(response["provisioning_uri"]))
    storage_user = _login_admin("storage", "admin", password, storage_otp)
    responses["storage"] = {
        "service": storage_service,
        "user": storage_user,
        "response": response,
    }

    assert storage_service.registry_uid() == registry_service.uid()
    assert storage_service.uid() not in service_uids
    service_uids.append(storage_service.uid())

    args["canonical_url"] = "hugs"
    args["service_type"] = "hugs"
    response = call_function("hugs", function="admin/setup", args=args)
    responses["hugs"] = response
    hugs_service = Service.from_data(response["service"])
    hugs_otp = OTP(OTP.extract_secret(response["provisioning_uri"]))
    hugs_user = _login_admin("hugs", "admin", password, hugs_otp)
    responses["hugs"] = {
        "service": hugs_service,
        "user": hugs_user,
        "response": response,
    }

    resource = "trust_accounting_service %s" % accounting_service.uid()
    args = {
        "service_url":
        accounting_service.canonical_url(),
        "authorisation":
        Authorisation(user=access_user, resource=resource).to_data(),
    }
    access_service.call_function(function="admin/trust_accounting_service",
                                 args=args)

    responses["_services"] = _services

    return responses
Exemplo n.º 30
0
    def read(self, spend, resource, receipt_by):
        """Read the cheque - this will read the cheque to return the
           decrypted contents. This will only work if this function
           is called on the accounting service that will cash the
           cheque, if the signature on the cheque matches the
           service that is authorised to cash the cheque, and
           if the passed resource matches the resource
           encoded in the cheque. If this is all correct, then the
           returned dictionary will contain;

           {"recipient_url": The URL of the service which was sent the cheque,
            "recipient_key_fingerprint": Verified fingerprint of the service
                                         key that signed this cheque
            "spend": The amount authorised by this cheque,
            "uid": The unique ID for this cheque,
            "resource": String that identifies the resource this cheque will
                        be used to pay for,
            "account_uid": UID of the account from which funds will be drawn
            "authorisation" : Verified authorisation from the user who
                              says they own the account for the spend
            "receipt_by" : Time when we must receipt the cheque, or
                           we will lose the money
           }

           You must pass in the spend you want to draw from the cheque,
           a string representing the resource this cheque will
           be used to pay for, and the time by which you promise to receipt
           the cheque after cashing

           Args:
                spend (Decimal): Amount authorised by cheque
                resource (str): Resource to pay for
                receipt_by (datetime): Time cheque must be receipted
                by
           Returns:
                dict: Dictionary described above

        """

        if self._cheque is None:
            raise PaymentError("You cannot read a null cheque")

        from Acquire.ObjectStore import string_to_decimal \
            as _string_to_decimal
        from Acquire.ObjectStore import string_to_datetime \
            as _string_to_datetime
        from Acquire.ObjectStore import datetime_to_string \
            as _datetime_to_string
        from Acquire.Service import get_this_service as _get_this_service

        spend = _string_to_decimal(spend)
        resource = str(resource)
        receipt_by = _string_to_datetime(receipt_by)

        service = _get_this_service(need_private_access=True)

        # get the cheque data - this may have been signed
        try:
            cheque_data = _json.loads(self._cheque["signed_data"])
        except:
            cheque_data = self._cheque

        # decrypt the cheque's data - only possible on the accounting service
        cheque_data = service.decrypt_data(cheque_data)

        # the date comprises the user-authorisation that acts as a
        # signature that the user wrote this cheque, and the info
        # for the cheque to say how it is valid
        from Acquire.Identity import Authorisation as _Authorisation
        auth = _Authorisation.from_data(cheque_data["authorisation"])
        info = cheque_data["info"]

        # the json.dumps version is the resource used to verify
        # the above authorisation
        auth_resource = info

        # validate that the user authorised this cheque
        try:
            auth.verify(resource=info)
        except Exception as e:
            raise PaymentError(
                "The user's signature/authorisation for this cheque "
                "is not valid! ERROR: %s" % str(e))

        info = _json.loads(info)

        # the user signed this cheque :-)
        info["authorisation"] = auth

        # check the signature if one was needed
        try:
            recipient_url = info["recipient_url"]
        except:
            recipient_url = None

        if recipient_url:
            # the recipient was specified - verify that we trust
            # the recipient, and that they have signed the cheque
            recipient_service = service.get_trusted_service(
                                            service_url=recipient_url)
            recipient_service.verify_data(self._cheque)
            info["recipient_key_fingerprint"] = self._cheque["fingerprint"]

        # validate that the item signature is correct
        try:
            cheque_resource = info["resource"]
        except:
            cheque_resource = None

        if cheque_resource is not None:
            if resource != resource:
                raise PaymentError(
                    "Disagreement over the resource for which "
                    "this cheque has been signed")

        info["resource"] = resource
        info["auth_resource"] = auth_resource

        try:
            max_spend = info["max_spend"]
            del info["max_spend"]
        except:
            max_spend = None

        if max_spend is not None:
            max_spend = _string_to_decimal(max_spend)

            if max_spend < spend:
                raise PaymentError(
                    "The requested spend (%s) exceeds the authorised "
                    "maximum value of the cheque" % (spend))

        info["spend"] = spend

        try:
            expiry_date = info["expiry_date"]
            del expiry_date["expiry_date"]
        except:
            expiry_date = None

        if expiry_date is not None:
            expiry_date = _string_to_datetime(expiry_date)

            # validate that the cheque will not have expired
            # when we receipt it
            from Acquire.ObjectStore import get_datetime_now \
                as _get_datetime_now
            now = _get_datetime_now()

            if now > receipt_by:
                raise PaymentError(
                    "The time when you promised to receipt the cheque "
                    "has already passed!")

            if receipt_by > expiry_date:
                raise PaymentError(
                    "The cheque will have expired after you plan to "
                    "receipt it!: %s versus %s" %
                    (_datetime_to_string(receipt_by),
                     _datetime_to_string(expiry_date)))

        info["receipt_by"] = receipt_by

        return info