Пример #1
0
    def isAuthorized(self, username, account, cloudspace=None, machine=None):
        """
        Check if a user has the authorization to access a resource

        :param username: username of the user to be checked
        :param machine: machine object if authorization should be done on machine level
        :param cloudspace: cloudspace object if authorization should be done on cloudspace level
        :param account: account object if authorization should be done on account level
        :return: True if username is authorized to access the resource, False otherwise
        """
        userobj = j.core.portal.active.auth.getUserInfo(username)
        if not userobj or not userobj.active:
            raise exceptions.Forbidden(
                'User is not allowed to execute action while status is '
                'inactive.')
        groups = userobj.groups
        # add brokeradmin access
        if 'admin' in groups:
            return True

        if self.groups:
            groups = set()
            if userobj:
                groups = set(userobj.groups)
            if not groups.intersection(self.groups):
                raise exceptions.Forbidden(
                    'User %s has no access. If you would like to gain access please contact your adminstrator'
                    % username)

        if 'account' in self.acl and account:
            grantedaccountacl = self.expandAclFromAccount(
                username, groups, account)
            if self.acl['account'].issubset(grantedaccountacl):
                self.checkAccountStatus(self.acl['account'], account)
                return True

        if 'cloudspace' in self.acl and cloudspace:
            grantedcloudspaceacl = self.expandAclFromCloudspace(
                username, groups, cloudspace)
            if self.acl['cloudspace'].issubset(grantedcloudspaceacl):
                self.checkAccountStatus(self.acl['cloudspace'], account)
                self.checkCloudspaceStatus(self.acl['cloudspace'], cloudspace)
                return True

        if 'machine' in self.acl and machine:
            grantedmachineacl = self.expandAclFromVMachine(
                username, groups, machine)
            if self.acl['machine'].issubset(grantedmachineacl):
                self.checkAccountStatus(self.acl['machine'], account)
                self.checkCloudspaceStatus(self.acl['machine'], cloudspace)
                return True

        return False
Пример #2
0
        def wrapper(*args, **kwargs):
            self.tags_str = ' '.join(
                ["%s:%s" % (k, kwargs[v]) for k, v in self.tags.iteritems()])

            if 'ctx' not in kwargs:
                # call is not performed over rest let it pass
                return func(*args, **kwargs)

            ctx = kwargs['ctx']
            if self.tags:
                ctx.env['tags'] = self.tags_str
            user = ctx.env['beaker.session']['user']
            if self.groups:
                userobj = j.core.portal.active.auth.getUserInfo(user)
                groups = set()
                if userobj:
                    groups = set(userobj.groups)
                if not groups.intersection(self.groups):
                    raise exceptions.Forbidden(
                        'User %s has no access. If you would like to gain access please contact your adminstrator'
                        % user)

            if self.audit:
                ctx.env['write_audit']()
            return func(*args, **kwargs)
Пример #3
0
    def checkCloudspaceStatus(self, requiredaccessrights, cloudspace):
        """
        Check if the required action can be executed on a cloudspace. If cloudspace is
        'DESTROYED' then a 404 NotFound will be returned, else if an action requires a permission
        other than READ, the call will fail with 403 Forbidden if cloudspace is not in any of the
        statuses 'VIRTUAL', 'DEPLOYING' or'DEPLOYED'

        :param requiredaccessrights: the required access rights to access an cloudspace or one of
            its machines
        :param cloudspace: the cloudspace object its status should be checked
        :raise Exception with 404 if destroyed or 403 Forbidden if non-read action cannot be
            performed on cloudspace or one of its machines
        """
        if cloudspace.status == resourcestatus.Cloudspace.DESTROYED:
            raise exceptions.NotFound('Could not find an accessible resource.')
        elif cloudspace.status == resourcestatus.Cloudspace.DELETED and requiredaccessrights != set(
                'D'):
            raise exceptions.NotFound('Could not find an accessible resource.')
        elif requiredaccessrights != set('R') and cloudspace.status not in [
                resourcestatus.Cloudspace.VIRTUAL,
                resourcestatus.Cloudspace.DEPLOYING,
                resourcestatus.Cloudspace.DEPLOYED
        ]:
            raise exceptions.Forbidden(
                'Only READ actions can be executed on cloudspace '
                '(or one of its machines) with status %s.' % cloudspace.status)
Пример #4
0
    def checkAccountStatus(self, requiredaccessrights, account):
        """
        Check if the required action can be executed on an account. If account is 'DISABLED',
        'DESTROYED', 'ERROR' and action requires a permission other than READ, the call should
        fail with 403 Forbidden

        Check if the required action can be executed on an account. If account is
        'DESTROYED' then a 404 NotFound will be returned, else if an action requires a permission
        other than READ, the call will fail with 403 Forbidden if account is not 'CONFIRMED'

        :param requiredaccessrights: the required access rights to access an account or one of
            its cloudspaces or machines
        :param account: the account object its status should be checked
        :raise Exception with 403 Forbidden if action cannot be performed on account or one of
            its cloduspaces or machines

        :raise Exception with 404 if destroyed or 403 Forbidden if non-read action cannot be
            performed on account or one of its cloudspace  or machines
        """
        if account.status == 'DESTROYED':
            raise exceptions.NotFound('Could not find an accessible resource.')
        elif requiredaccessrights != set(
                'R') and account.status != 'CONFIRMED':
            raise exceptions.Forbidden(
                'Only READ actions can be executed on account '
                '(or one of its cloudspace or machines) with status %s.' %
                account.status)
Пример #5
0
        def wrapper(*args, **kwargs):
            if 'ctx' not in kwargs:
                # call is not performed over rest let it pass
                return func(*args, **kwargs)
            ctx = kwargs['ctx']
            user = ctx.env['beaker.session']['user']
            if self.groups:
                userobj = j.core.portal.active.auth.getUserInfo(user)
                if userobj:
                    groups = set(userobj.groups)
                if not groups.intersection(self.groups):
                    raise exceptions.Forbidden(
                        'User %s has no access. If you would like to gain access please contact your adminstrator'
                        % user)

            ctx.env['JS_AUDIT'] = self.audit
            return func(*args, **kwargs)
Пример #6
0
    def deleteImage(self, imageId, permanently):
        image = self.models.image.get(imageId)
        if image.status == resourcestatus.Image.DESTROYED:
            return True
        references = self.models.vmachine.count({'imageId': imageId,
                                                 'status': {'$ne': resourcestatus.Machine.DESTROYED}})
        if references and permanently:
            raise exceptions.Conflict("Can not delete an image which is still used")
        if image.status != resourcestatus.Image.DELETED:
            if image.status != resourcestatus.Image.CREATED:
                raise exceptions.Forbidden("Can not delete an image which is not created yet.")

        deleted_state = resourcestatus.Image.DELETED
        if permanently:
            deleted_state = resourcestatus.Image.DESTROYED
            provider = self.cb.getProviderByGID(image.gid)
            provider.ex_delete_template(image.referenceId)

        self.models.image.updateSearch({'id': imageId}, {'$set': {'status': deleted_state, 'deletionTime': int(time.time())}})
        self.models.stack.updateSearch({'images': imageId}, {'$pull': {'images': imageId}})
        return True
Пример #7
0
    def authorize(self, **kwargs):
        ctx = kwargs['ctx']
        code = kwargs.get('code')
        if not code:
            raise exceptions.Forbidden('Not Authorized -- Code is missing')

        state = kwargs.get('state')
        if not state:
            return exceptions.Forbidden('Not Authorized -- State is missing')

        cache = j.clients.redis.getByInstance('system')
        cache_result = cache.get(state)

        if not cache_result:
            unauthorized_redirect_url = '%s?%s' % (
                '/restmachine/system/oauth/authenticate',
                urllib.urlencode({
                    'type':
                    j.core.portal.active.force_oauth_instance or 'github'
                }))
            msg = 'Not Authorized -- Invalid or expired state'
            j.logger.log(msg)
            raise exceptions.Redirect(unauthorized_redirect_url)

        cache_result = json.loads(cache_result)
        client = j.clients.oauth.get(instance=cache_result['type'])
        payload = {
            'code': code,
            'client_id': client.id,
            'client_secret': client.secret,
            'redirect_uri': client.redirect_url,
            'grant_type': 'authorization_code'
        }
        result = requests.post(client.accesstokenaddress,
                               data=payload,
                               headers={'Accept': 'application/json'})

        if not result.ok or 'error' in result.json():
            msg = 'Not Authorized -- %s' % result.json()['error']
            j.logger.log(msg)
            raise exceptions.Forbidden(msg)

        result = result.json()
        access_token = result['access_token']
        params = {'access_token': access_token}
        userinfo = requests.get(
            '%s?%s' % (client.user_info_url, urllib.urlencode(params))).json()
        username = userinfo['login']
        email = userinfo['email']

        osis = j.clients.osis.getByInstance('main')
        user = j.clients.osis.getCategory(osis, "system", "user")
        users = user.search({'id': username})[1:]

        if not users:
            # register user
            u = user.new()
            u.id = username
            u.emails = [email]
            user.set(u)
        else:
            u = users[0]
            if email not in u['emails']:
                raise exceptions.BadRequest(
                    'User with same name already exists')

        session = ctx.env['beaker.session']
        session['user'] = username
        session['email'] = email
        session['oauth'] = {
            'authorized': True,
            'type': str(cache_result['type']),
            'logout_url': client.logout_url
        }
        session.save()

        raise exceptions.Redirect(str(cache_result['redirect']))
Пример #8
0
        def wrapper(*args, **kwargs):
            if 'ctx' not in kwargs:
                # call is not performed over rest let it pass
                return func(*args, **kwargs)
            ctx = kwargs['ctx']
            if not self.skipversioncheck and sysmodels.version.count(
                {'status': 'INSTALLING'}) != 0:
                raise exceptions.ServiceUnavailable(
                    'Can not call API during upgrade')

            tags = j.core.tags.getObject(ctx.env['tags'])
            user = ctx.env['beaker.session']['user']
            account = None
            cloudspace = None
            machine = None
            if 'machineId' in kwargs and kwargs['machineId']:
                machine = self.models.vmachine.get(int(kwargs['machineId']))
                cloudspace = self.models.cloudspace.get(machine.cloudspaceId)
                account = self.models.account.get(cloudspace.accountId)
            elif 'diskId' in kwargs and kwargs['diskId']:
                disk = self.models.disk.get(int(kwargs['diskId']))
                machinedict = self.models.vmachine.searchOne({
                    'disks': disk.id,
                    'status': {
                        '$ne': resourcestatus.Machine.DESTROYED
                    }
                })
                if machinedict:
                    machine = self.models.vmachine.new()
                    machine.load(machinedict)
                    cloudspace = self.models.cloudspace.get(
                        machine.cloudspaceId)
                accountId = disk.accountId
                if accountId:
                    account = self.models.account.get(accountId)
            elif 'cloudspaceId' in kwargs and kwargs['cloudspaceId']:
                cloudspace = self.models.cloudspace.get(
                    int(kwargs['cloudspaceId']))
                account = self.models.account.get(cloudspace.accountId)
            elif 'accountId' in kwargs and kwargs['accountId']:
                account = self.models.account.get(int(kwargs['accountId']))

            for key, value in (('accountId', account),
                               ('cloudspaceId', cloudspace), ('machineId',
                                                              machine)):
                if value is not None:
                    tags.tagSet(key, str(value.id))
            if 'nid' in kwargs and kwargs['nid']:
                tags.tagSet('nodeId', str(kwargs['nid']))

            tagstr = str(tags)
            if 'nids' in kwargs and kwargs['nids']:
                for nid in kwargs['nids']:
                    tagstr += " nodeId:{}".format(nid)

            ctx.env['tags'] = tagstr
            ctx.env['write_audit']()
            if self.isAuthorized(user, account, cloudspace, machine):
                return func(*args, **kwargs)
            else:
                raise exceptions.Forbidden(
                    '''User: "******" isn't allowed to execute this action.
                        Not enough permissions''' % user)
Пример #9
0
        def wrapper(*args, **kwargs):
            if "ctx" not in kwargs:
                # call is not performed over rest let it pass
                return func(*args, **kwargs)
            ctx = kwargs["ctx"]
            if (
                not self.skipversioncheck
                and sysmodels.version.count({"status": "INSTALLING"}) != 0
            ):
                raise exceptions.ServiceUnavailable("Can not call API during upgrade")

            tags = j.core.tags.getObject(ctx.env["tags"])
            user = ctx.env["beaker.session"]["user"]
            account = None
            cloudspace = None
            machine = None
            if "machineId" in kwargs and kwargs["machineId"]:
                machine = self.models.vmachine.get(int(kwargs["machineId"]))
                cloudspace = self.models.cloudspace.get(machine.cloudspaceId)
                account = self.models.account.get(cloudspace.accountId)
            elif "diskId" in kwargs and kwargs["diskId"]:
                disk = self.models.disk.get(int(kwargs["diskId"]))
                machinedict = self.models.vmachine.searchOne(
                    {
                        "disks": disk.id,
                        "status": {"$ne": resourcestatus.Machine.DESTROYED},
                    }
                )
                if machinedict:
                    machine = self.models.vmachine.new()
                    machine.load(machinedict)
                    cloudspace = self.models.cloudspace.get(machine.cloudspaceId)
                accountId = disk.accountId
                if accountId:
                    account = self.models.account.get(accountId)
            elif "cloudspaceId" in kwargs and kwargs["cloudspaceId"]:
                cloudspace = self.models.cloudspace.get(int(kwargs["cloudspaceId"]))
                account = self.models.account.get(cloudspace.accountId)
            elif "accountId" in kwargs and kwargs["accountId"]:
                account = self.models.account.get(int(kwargs["accountId"]))

            for key, value in (
                ("accountId", account),
                ("cloudspaceId", cloudspace),
                ("machineId", machine),
            ):
                if value is not None:
                    tags.tagSet(key, str(value.id))
            if "nid" in kwargs and kwargs["nid"]:
                tags.tagSet("nodeId", str(kwargs["nid"]))

            tagstr = str(tags)
            if "nids" in kwargs and kwargs["nids"]:
                for nid in kwargs["nids"]:
                    tagstr += " nodeId:{}".format(nid)

            ctx.env["tags"] = tagstr
            ctx.env["write_audit"]()
            if self.isAuthorized(user, account, cloudspace, machine):
                return func(*args, **kwargs)
            else:
                raise exceptions.Forbidden(
                    """User: "******" isn't allowed to execute this action.
                        Not enough permissions"""
                    % user
                )